mirror of
https://github.com/openmv/openmv.git
synced 2025-09-26 23:09:13 +08:00
Compare commits
39 Commits
47d35b9ed2
...
3667b54319
Author | SHA1 | Date | |
---|---|---|---|
![]() |
3667b54319 | ||
![]() |
f6f39f924b | ||
![]() |
65829023f0 | ||
![]() |
7124b5134d | ||
![]() |
eccb90699d | ||
![]() |
14d277c95b | ||
![]() |
3a79080713 | ||
![]() |
f16f566141 | ||
![]() |
aaabe05565 | ||
![]() |
2205f177f3 | ||
![]() |
0de60ff3d5 | ||
![]() |
75c7a4fb82 | ||
![]() |
04145abea8 | ||
![]() |
1dab51addf | ||
![]() |
a559f03553 | ||
![]() |
3946a19cd2 | ||
![]() |
f994fe1d06 | ||
![]() |
01113ebee9 | ||
![]() |
28f0ad2d7d | ||
![]() |
e60750b5cc | ||
![]() |
1b59e95162 | ||
![]() |
085f282e4b | ||
![]() |
ce4922c1bc | ||
![]() |
bcb20f45ac | ||
![]() |
bb52288561 | ||
![]() |
4f40ae487e | ||
![]() |
050d750afd | ||
![]() |
9937b9cc1e | ||
![]() |
8b19717c21 | ||
![]() |
a4ce426308 | ||
![]() |
616ce71b96 | ||
![]() |
1dd9b33acc | ||
![]() |
facd715c12 | ||
![]() |
384c3e734d | ||
![]() |
1308129fdb | ||
![]() |
be25f116ab | ||
![]() |
22981bdb61 | ||
![]() |
51e87a4e40 | ||
![]() |
960ae86545 |
63
.github/workflows/codeformat.yml
vendored
63
.github/workflows/codeformat.yml
vendored
@ -5,7 +5,9 @@ on:
|
||||
branches:
|
||||
- 'master'
|
||||
paths:
|
||||
- '**/*.{c,cc,h}'
|
||||
- '**/*.c'
|
||||
- '**/*.cc'
|
||||
- '**/*.h'
|
||||
|
||||
pull_request:
|
||||
types:
|
||||
@ -16,7 +18,9 @@ on:
|
||||
branches:
|
||||
- 'master'
|
||||
paths:
|
||||
- '**/*.{c,cc,h}'
|
||||
- '**/*.c'
|
||||
- '**/*.cc'
|
||||
- '**/*.h'
|
||||
|
||||
jobs:
|
||||
formatting-check:
|
||||
@ -27,42 +31,23 @@ jobs:
|
||||
with:
|
||||
submodules: false
|
||||
persist-credentials: false
|
||||
|
||||
- name: '♻ Caching dependencies'
|
||||
uses: actions/cache@v4.2.0
|
||||
id: cache
|
||||
with:
|
||||
path: ~/cache/deps/bin
|
||||
key: 'uncrustify'
|
||||
|
||||
- name: '🛠 Install dependencies'
|
||||
if: steps.cache.outputs.cache-hit != 'true'
|
||||
run: source tools/ci.sh && ci_install_code_format_deps
|
||||
|
||||
- name: '📜 Get list of changed files'
|
||||
id: changed-files
|
||||
uses: tj-actions/changed-files@v46
|
||||
with:
|
||||
files: |
|
||||
**/*.{c,cc,h}
|
||||
!cubeai/**
|
||||
!docker/**
|
||||
!docs/**
|
||||
!drivers/**
|
||||
drivers/sensors/*.{c,cc,h}
|
||||
!lib/**
|
||||
lib/imlib/*.{c,cc,h}
|
||||
lib/tflm/*.{c,cc,h}
|
||||
!scripts/**
|
||||
!tools/**
|
||||
|
||||
- name: '📜 Show list of changed files'
|
||||
run: |
|
||||
echo "${{ toJSON(steps.changed-files.outputs) }}"
|
||||
shell:
|
||||
bash
|
||||
fetch-depth: 0
|
||||
|
||||
- name: '🔎 Check code formatting'
|
||||
if: steps.changed-files.outputs.any_changed == 'true'
|
||||
run: |
|
||||
source tools/ci.sh && ci_run_code_format_check ${{ steps.changed-files.outputs.all_changed_files }}
|
||||
uses: openmv/uncrustify-action@v1
|
||||
with:
|
||||
config-path: 'tools/uncrustify.cfg'
|
||||
extensions: 'c,cc,h'
|
||||
exclude-patterns: |
|
||||
cubeai/**
|
||||
docker/**
|
||||
docs/**
|
||||
drivers/**
|
||||
!drivers/sensors/**
|
||||
lib/**
|
||||
!lib/imlib/**
|
||||
!lib/tflm/**
|
||||
scripts/**
|
||||
tools/**
|
||||
uncrustify-version: '0.75.0'
|
||||
fail-on-error: true
|
||||
|
8
.github/workflows/firmware.yml
vendored
8
.github/workflows/firmware.yml
vendored
@ -75,7 +75,7 @@ jobs:
|
||||
key: 'gcc-14.3.rel1_llvm-18.1.3_make-4.4.1_stedgeai-2.1'
|
||||
|
||||
- name: '🐍 Install Python'
|
||||
uses: actions/setup-python@v5
|
||||
uses: actions/setup-python@v6
|
||||
with:
|
||||
cache: 'pip'
|
||||
python-version: "3.12.4"
|
||||
@ -136,7 +136,7 @@ jobs:
|
||||
key: 'gcc-14.3.rel1_llvm-18.1.3_make-4.4.1_stedgeai-2.1'
|
||||
|
||||
- name: '🐍 Install Python'
|
||||
uses: actions/setup-python@v5
|
||||
uses: actions/setup-python@v6
|
||||
with:
|
||||
cache: 'pip'
|
||||
python-version: "3.12.4"
|
||||
@ -202,7 +202,7 @@ jobs:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: '🔥 Create stable release'
|
||||
uses: softprops/action-gh-release@da05d552573ad5aba039eaac05058a918a7bf631
|
||||
uses: softprops/action-gh-release@6cbd405e2c4e67a21c47fa9e383d020e4e28b836
|
||||
with:
|
||||
draft: true
|
||||
files: firmware_*.zip
|
||||
@ -254,7 +254,7 @@ jobs:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: '🔥 Create development release'
|
||||
uses: softprops/action-gh-release@da05d552573ad5aba039eaac05058a918a7bf631
|
||||
uses: softprops/action-gh-release@6cbd405e2c4e67a21c47fa9e383d020e4e28b836
|
||||
with:
|
||||
draft: false
|
||||
name: Development Release
|
||||
|
2
.github/workflows/python-linter.yml
vendored
2
.github/workflows/python-linter.yml
vendored
@ -28,7 +28,7 @@ jobs:
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: '🐍 Set up Python ${{ matrix.python-version }}'
|
||||
uses: actions/setup-python@v5
|
||||
uses: actions/setup-python@v6
|
||||
with:
|
||||
cache: 'pip'
|
||||
python-version: ${{ matrix.python-version }}
|
||||
|
7
Makefile
7
Makefile
@ -253,9 +253,12 @@ endif
|
||||
$(SIZE) --format=SysV $(FW_DIR)/$(FIRMWARE).elf
|
||||
|
||||
jlink:
|
||||
${JLINK_GDB_SERVER} -speed ${JLINK_SPEED} -nogui \
|
||||
setsid ${JLINK_GDB_SERVER} -speed ${JLINK_SPEED} -nogui \
|
||||
-if ${JLINK_INTERFACE} -halt -cpu cortex-m \
|
||||
-device ${JLINK_DEVICE} -novd ${JLINK_SCRIPT}
|
||||
-device ${JLINK_DEVICE} -novd ${JLINK_SCRIPT} >/dev/null 2>&1 & \
|
||||
JLINK_PID=$$!; \
|
||||
trap "kill $$JLINK_PID 2>/dev/null" EXIT; \
|
||||
sleep 1 && jlink-gdb $(FW_DIR)/$(FIRMWARE).elf
|
||||
|
||||
submodules:
|
||||
$(MAKE) -C $(MICROPY_DIR)/ports/$(PORT) BOARD=$(TARGET) submodules
|
||||
|
@ -38,6 +38,12 @@
|
||||
"alignment": 16,
|
||||
"optimize": "Performance"
|
||||
},
|
||||
{
|
||||
"type": "tflite",
|
||||
"path": "{TOP}/lib/models/blazeface_front_128.tflite",
|
||||
"alignment": 16,
|
||||
"optimize": "Performance"
|
||||
},
|
||||
{
|
||||
"type": "haar",
|
||||
"path": "{TOP}/lib/haar/haarcascade_eye.xml",
|
||||
|
@ -32,6 +32,12 @@
|
||||
"alignment": 16,
|
||||
"optimize": "Performance"
|
||||
},
|
||||
{
|
||||
"type": "tflite",
|
||||
"path": "{TOP}/lib/models/blazeface_front_128.tflite",
|
||||
"alignment": 16,
|
||||
"optimize": "Performance"
|
||||
},
|
||||
{
|
||||
"type": "haar",
|
||||
"path": "{TOP}/lib/haar/haarcascade_eye.xml",
|
||||
|
@ -38,6 +38,12 @@
|
||||
"alignment": 16,
|
||||
"optimize": "Performance"
|
||||
},
|
||||
{
|
||||
"type": "tflite",
|
||||
"path": "{TOP}/lib/models/blazeface_front_128.tflite",
|
||||
"alignment": 16,
|
||||
"optimize": "Performance"
|
||||
},
|
||||
{
|
||||
"type": "haar",
|
||||
"path": "{TOP}/lib/haar/haarcascade_eye.xml",
|
||||
|
@ -38,6 +38,12 @@
|
||||
"alignment": 16,
|
||||
"optimize": "Performance"
|
||||
},
|
||||
{
|
||||
"type": "tflite",
|
||||
"path": "{TOP}/lib/models/blazeface_front_128.tflite",
|
||||
"alignment": 16,
|
||||
"optimize": "Performance"
|
||||
},
|
||||
{
|
||||
"type": "haar",
|
||||
"path": "{TOP}/lib/haar/haarcascade_eye.xml",
|
||||
|
@ -38,6 +38,12 @@
|
||||
"alignment": 16,
|
||||
"optimize": "Performance"
|
||||
},
|
||||
{
|
||||
"type": "tflite",
|
||||
"path": "{TOP}/lib/models/blazeface_front_128.tflite",
|
||||
"alignment": 16,
|
||||
"optimize": "Performance"
|
||||
},
|
||||
{
|
||||
"type": "haar",
|
||||
"path": "{TOP}/lib/haar/haarcascade_eye.xml",
|
||||
|
@ -32,6 +32,12 @@
|
||||
"alignment": 16,
|
||||
"optimize": "Performance"
|
||||
},
|
||||
{
|
||||
"type": "tflite",
|
||||
"path": "{TOP}/lib/models/blazeface_front_128.tflite",
|
||||
"alignment": 16,
|
||||
"optimize": "Performance"
|
||||
},
|
||||
{
|
||||
"type": "haar",
|
||||
"path": "{TOP}/lib/haar/haarcascade_eye.xml",
|
||||
|
@ -19,6 +19,12 @@
|
||||
"path": "{TOP}/lib/models/yolo_v5_224_nano.tflite",
|
||||
"alignment": 32,
|
||||
"profile": "default"
|
||||
},
|
||||
{
|
||||
"type": "tflite",
|
||||
"path": "{TOP}/lib/models/blazeface_front_128.tflite",
|
||||
"alignment": 32,
|
||||
"profile": "default"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -38,6 +38,12 @@
|
||||
"alignment": 16,
|
||||
"optimize": "Performance"
|
||||
},
|
||||
{
|
||||
"type": "tflite",
|
||||
"path": "{TOP}/lib/models/blazeface_front_128.tflite",
|
||||
"alignment": 16,
|
||||
"optimize": "Performance"
|
||||
},
|
||||
{
|
||||
"type": "haar",
|
||||
"path": "{TOP}/lib/haar/haarcascade_eye.xml",
|
||||
|
@ -31,6 +31,7 @@ COMMON_SRC_C += \
|
||||
mutex.c \
|
||||
nosys_stubs.c \
|
||||
omv_csi.c \
|
||||
omv_crc.c \
|
||||
pendsv.c \
|
||||
tinyusb_debug.c \
|
||||
trace.c \
|
||||
|
86
common/omv_crc.c
Normal file
86
common/omv_crc.c
Normal file
@ -0,0 +1,86 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Copyright (C) 2025 OpenMV, LLC.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
#include "omv_crc.h"
|
||||
|
||||
static const uint16_t crc16_table[256] = {
|
||||
0x0000, 0xBAAD, 0xCFF7, 0x755A, 0x2543, 0x9FEE, 0xEAB4, 0x5019,
|
||||
0x4A86, 0xF02B, 0x8571, 0x3FDC, 0x6FC5, 0xD568, 0xA032, 0x1A9F,
|
||||
0x950C, 0x2FA1, 0x5AFB, 0xE056, 0xB04F, 0x0AE2, 0x7FB8, 0xC515,
|
||||
0xDF8A, 0x6527, 0x107D, 0xAAD0, 0xFAC9, 0x4064, 0x353E, 0x8F93,
|
||||
0x90B5, 0x2A18, 0x5F42, 0xE5EF, 0xB5F6, 0x0F5B, 0x7A01, 0xC0AC,
|
||||
0xDA33, 0x609E, 0x15C4, 0xAF69, 0xFF70, 0x45DD, 0x3087, 0x8A2A,
|
||||
0x05B9, 0xBF14, 0xCA4E, 0x70E3, 0x20FA, 0x9A57, 0xEF0D, 0x55A0,
|
||||
0x4F3F, 0xF592, 0x80C8, 0x3A65, 0x6A7C, 0xD0D1, 0xA58B, 0x1F26,
|
||||
0x9BC7, 0x216A, 0x5430, 0xEE9D, 0xBE84, 0x0429, 0x7173, 0xCBDE,
|
||||
0xD141, 0x6BEC, 0x1EB6, 0xA41B, 0xF402, 0x4EAF, 0x3BF5, 0x8158,
|
||||
0x0ECB, 0xB466, 0xC13C, 0x7B91, 0x2B88, 0x9125, 0xE47F, 0x5ED2,
|
||||
0x444D, 0xFEE0, 0x8BBA, 0x3117, 0x610E, 0xDBA3, 0xAEF9, 0x1454,
|
||||
0x0B72, 0xB1DF, 0xC485, 0x7E28, 0x2E31, 0x949C, 0xE1C6, 0x5B6B,
|
||||
0x41F4, 0xFB59, 0x8E03, 0x34AE, 0x64B7, 0xDE1A, 0xAB40, 0x11ED,
|
||||
0x9E7E, 0x24D3, 0x5189, 0xEB24, 0xBB3D, 0x0190, 0x74CA, 0xCE67,
|
||||
0xD4F8, 0x6E55, 0x1B0F, 0xA1A2, 0xF1BB, 0x4B16, 0x3E4C, 0x84E1,
|
||||
0x8D23, 0x378E, 0x42D4, 0xF879, 0xA860, 0x12CD, 0x6797, 0xDD3A,
|
||||
0xC7A5, 0x7D08, 0x0852, 0xB2FF, 0xE2E6, 0x584B, 0x2D11, 0x97BC,
|
||||
0x182F, 0xA282, 0xD7D8, 0x6D75, 0x3D6C, 0x87C1, 0xF29B, 0x4836,
|
||||
0x52A9, 0xE804, 0x9D5E, 0x27F3, 0x77EA, 0xCD47, 0xB81D, 0x02B0,
|
||||
0x1D96, 0xA73B, 0xD261, 0x68CC, 0x38D5, 0x8278, 0xF722, 0x4D8F,
|
||||
0x5710, 0xEDBD, 0x98E7, 0x224A, 0x7253, 0xC8FE, 0xBDA4, 0x0709,
|
||||
0x889A, 0x3237, 0x476D, 0xFDC0, 0xADD9, 0x1774, 0x622E, 0xD883,
|
||||
0xC21C, 0x78B1, 0x0DEB, 0xB746, 0xE75F, 0x5DF2, 0x28A8, 0x9205,
|
||||
0x16E4, 0xAC49, 0xD913, 0x63BE, 0x33A7, 0x890A, 0xFC50, 0x46FD,
|
||||
0x5C62, 0xE6CF, 0x9395, 0x2938, 0x7921, 0xC38C, 0xB6D6, 0x0C7B,
|
||||
0x83E8, 0x3945, 0x4C1F, 0xF6B2, 0xA6AB, 0x1C06, 0x695C, 0xD3F1,
|
||||
0xC96E, 0x73C3, 0x0699, 0xBC34, 0xEC2D, 0x5680, 0x23DA, 0x9977,
|
||||
0x8651, 0x3CFC, 0x49A6, 0xF30B, 0xA312, 0x19BF, 0x6CE5, 0xD648,
|
||||
0xCCD7, 0x767A, 0x0320, 0xB98D, 0xE994, 0x5339, 0x2663, 0x9CCE,
|
||||
0x135D, 0xA9F0, 0xDCAA, 0x6607, 0x361E, 0x8CB3, 0xF9E9, 0x4344,
|
||||
0x59DB, 0xE376, 0x962C, 0x2C81, 0x7C98, 0xC635, 0xB36F, 0x09C2
|
||||
};
|
||||
|
||||
__attribute__((weak)) void omv_crc_init(void) {
|
||||
|
||||
}
|
||||
|
||||
__attribute__((weak)) omv_crc_t omv_crc_start(const void *buf, size_t size) {
|
||||
const uint8_t *data = (const uint8_t *)buf;
|
||||
omv_crc_t crc = OMV_CRC_INIT;
|
||||
|
||||
for (size_t i = 0; i < size; i++) {
|
||||
uint8_t index = (crc >> 8) ^ data[i];
|
||||
crc = (crc << 8) ^ crc16_table[index];
|
||||
}
|
||||
|
||||
return crc;
|
||||
}
|
||||
|
||||
__attribute__((weak)) omv_crc_t omv_crc_update(omv_crc_t crc, const void *buf, size_t size) {
|
||||
const uint8_t *data = (const uint8_t *)buf;
|
||||
|
||||
for (size_t i = 0; i < size; i++) {
|
||||
uint8_t index = (crc >> 8) ^ data[i];
|
||||
crc = (crc << 8) ^ crc16_table[index];
|
||||
}
|
||||
|
||||
return crc;
|
||||
}
|
63
common/omv_crc.h
Normal file
63
common/omv_crc.h
Normal file
@ -0,0 +1,63 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Copyright (C) 2025 OpenMV, LLC.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
#ifndef __OMV_CRC_H__
|
||||
#define __OMV_CRC_H__
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
// 0xBAAD is ironically good - HD=5 up to 108 bits, HD=4 up to 7985 bits
|
||||
#define OMV_CRC_POLY (0xBAAD)
|
||||
#define OMV_CRC_INIT (0xFFFF)
|
||||
#define OMV_CRC_SIZE (16)
|
||||
typedef uint16_t omv_crc_t;
|
||||
|
||||
// Initialize CRC hardware (if available)
|
||||
void omv_crc_init(void);
|
||||
|
||||
// Start CRC calculation for buffer data
|
||||
omv_crc_t omv_crc_start(const void *buf, size_t size);
|
||||
|
||||
// Update CRC with additional buffer data
|
||||
omv_crc_t omv_crc_update(omv_crc_t crc, const void *buf, size_t size);
|
||||
|
||||
// Read CRC value from the last 2 bytes of buffer
|
||||
static inline omv_crc_t omv_crc_read(const void *buf, size_t size) {
|
||||
const uint8_t *crc_buf = (const uint8_t *)buf + size - 2;
|
||||
return *((omv_crc_t*) crc_buf);
|
||||
}
|
||||
|
||||
// Calculate CRC and write it to the last 2 bytes of buffer
|
||||
static inline void omv_crc_write(void *buf, size_t size) {
|
||||
omv_crc_t crc = omv_crc_start(buf, size - 2);
|
||||
uint8_t *crc_buf = (uint8_t *)buf + size - 2;
|
||||
crc_buf[0] = crc & 0xFF;
|
||||
crc_buf[1] = (crc >> 8) & 0xFF;
|
||||
}
|
||||
|
||||
// Calculate and check if CRC matches the one stored in buffer
|
||||
static inline bool omv_crc_check(const void *buf, size_t size) {
|
||||
return omv_crc_read(buf, size) == omv_crc_start(buf, size - 2);
|
||||
}
|
||||
#endif // __OMV_CRC_H__
|
@ -189,7 +189,7 @@ void usbdbg_data_in(uint32_t size, usbdbg_write_callback_t write_callback) {
|
||||
case USBDBG_FRAME_DUMP:
|
||||
if (xfer_offs < xfer_size) {
|
||||
framebuffer_t *fb = framebuffer_get(FB_STREAM_ID);
|
||||
write_callback(fb->raw_base + xfer_offs, size);
|
||||
write_callback(fb->raw_base + sizeof(framebuffer_header_t) + xfer_offs, size);
|
||||
xfer_offs += size;
|
||||
if (xfer_offs == xfer_size) {
|
||||
cmd = USBDBG_NONE;
|
||||
|
@ -736,6 +736,7 @@ int genx320_init(omv_csi_t *csi) {
|
||||
csi->set_hmirror = set_hmirror;
|
||||
csi->set_vflip = set_vflip;
|
||||
csi->ioctl = ioctl;
|
||||
csi->auxiliary = 1;
|
||||
|
||||
// Set csi flags
|
||||
csi->mono_bpp = sizeof(uint8_t);
|
||||
|
@ -9,6 +9,7 @@
|
||||
|
||||
HAL_SRC_C += \
|
||||
drivers/source/adc.c \
|
||||
drivers/source/crc.c \
|
||||
drivers/source/dma_ctrl.c \
|
||||
drivers/source/dma_op.c \
|
||||
drivers/source/i2c.c \
|
||||
|
@ -52,6 +52,10 @@ void framebuffer_init0() {
|
||||
// Initialize the streaming buffer.
|
||||
framebuffer_init(framebuffer_get(FB_STREAM_ID), &_sb_memory_start,
|
||||
&_sb_memory_end - &_sb_memory_start, false, enabled);
|
||||
|
||||
// Reset embedded header
|
||||
framebuffer_t *fb = framebuffer_get(FB_STREAM_ID);
|
||||
memset(fb->raw_base, 0, sizeof(framebuffer_header_t));
|
||||
}
|
||||
|
||||
void framebuffer_init(framebuffer_t *fb, void *buff, size_t size, bool dynamic, bool enabled) {
|
||||
@ -65,6 +69,11 @@ void framebuffer_init(framebuffer_t *fb, void *buff, size_t size, bool dynamic,
|
||||
#if OMV_RAW_PREVIEW_ENABLE
|
||||
fb->raw_w = OMV_RAW_PREVIEW_WIDTH;
|
||||
fb->raw_h = OMV_RAW_PREVIEW_HEIGHT;
|
||||
fb->raw_enabled = true;
|
||||
#else
|
||||
fb->raw_w = 0;
|
||||
fb->raw_h = 0;
|
||||
fb->raw_enabled = false;
|
||||
#endif
|
||||
fb->quality = ((OMV_JPEG_QUALITY_HIGH - OMV_JPEG_QUALITY_LOW) / 2) + OMV_JPEG_QUALITY_LOW;
|
||||
mutex_init0(&fb->lock);
|
||||
@ -265,13 +274,18 @@ void framebuffer_update_preview(image_t *src) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Reserve space for header at the beginning
|
||||
framebuffer_header_t *header = (framebuffer_header_t *)fb->raw_base;
|
||||
uint8_t *frame_data = (uint8_t *)fb->raw_base + sizeof(framebuffer_header_t);
|
||||
size_t available_size = fb->raw_size - sizeof(framebuffer_header_t);
|
||||
|
||||
if (src->is_compressed) {
|
||||
if (src->size > fb->raw_size) {
|
||||
if (src->size > available_size) {
|
||||
framebuffer_from_image(fb, NULL);
|
||||
mp_printf(MP_PYTHON_PRINTER, "\x1b[40O\n");
|
||||
} else {
|
||||
framebuffer_from_image(fb, src);
|
||||
memcpy(fb->raw_base, src->pixels, src->size);
|
||||
memcpy(frame_data, src->pixels, src->size);
|
||||
}
|
||||
goto exit_cleanup;
|
||||
}
|
||||
@ -280,40 +294,36 @@ void framebuffer_update_preview(image_t *src) {
|
||||
.w = src->w,
|
||||
.h = src->h,
|
||||
.pixfmt = PIXFORMAT_JPEG,
|
||||
.size = fb->raw_size,
|
||||
.pixels = (uint8_t *) fb->raw_base
|
||||
.size = available_size,
|
||||
.pixels = frame_data
|
||||
};
|
||||
|
||||
bool compress = true;
|
||||
bool overflow = false;
|
||||
bool raw_stream = src->is_mutable && fb->raw_enabled && fb->raw_w && fb->raw_h;
|
||||
|
||||
#if OMV_RAW_PREVIEW_ENABLE
|
||||
if (src->is_mutable) {
|
||||
if (raw_stream) {
|
||||
// Down-scale the frame (if necessary) and send the raw frame.
|
||||
dst.size = src->bpp;
|
||||
dst.pixfmt = src->pixfmt;
|
||||
if (src->w <= fb->raw_w && src->h <= fb->raw_h) {
|
||||
if (image_size(&dst) <= fb->raw_size) {
|
||||
memcpy(dst.pixels, src->pixels, image_size(src));
|
||||
compress = false;
|
||||
}
|
||||
if (image_size(&dst) <= available_size) {
|
||||
memcpy(dst.pixels, src->pixels, image_size(src));
|
||||
} else {
|
||||
float scale = IM_MIN((fb->raw_w / (float) src->w),
|
||||
(fb->raw_h / (float) src->h));
|
||||
dst.w = fast_floorf(src->w * scale);
|
||||
dst.h = fast_floorf(src->h * scale);
|
||||
if (image_size(&dst) <= fb->raw_size) {
|
||||
if (image_size(&dst) <= available_size) {
|
||||
imlib_draw_image(&dst, src, 0, 0, scale, scale, NULL, -1, 255, NULL, NULL,
|
||||
IMAGE_HINT_BILINEAR | IMAGE_HINT_BLACK_BACKGROUND,
|
||||
NULL, NULL, NULL, NULL);
|
||||
compress = false;
|
||||
} else {
|
||||
raw_stream = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// Compress the frame if the raw image didn't fit or the format is non-mutable.
|
||||
if (compress) {
|
||||
if (!raw_stream) {
|
||||
overflow = jpeg_compress(src, &dst, fb->quality, false, JPEG_SUBSAMPLING_AUTO);
|
||||
}
|
||||
|
||||
@ -345,6 +355,11 @@ void framebuffer_update_preview(image_t *src) {
|
||||
}
|
||||
|
||||
exit_cleanup:
|
||||
header->width = fb->w;
|
||||
header->height = fb->h;
|
||||
header->pixfmt = fb->pixfmt;
|
||||
header->size = fb->is_compressed ? fb->size : fb->bpp;
|
||||
|
||||
// Unlock the streaming buffer.
|
||||
mutex_unlock(&fb->lock, MUTEX_TID_OMV);
|
||||
}
|
||||
|
@ -123,6 +123,13 @@ typedef struct vbuffer {
|
||||
OMV_ATTR_ALIGNED(uint8_t data[], FRAMEBUFFER_ALIGNMENT); // Data.
|
||||
} vbuffer_t;
|
||||
|
||||
// Frame header embedded in frame data for streaming protocol.
|
||||
typedef struct __attribute__((packed)) framebuffer_header {
|
||||
uint32_t width; // Frame width
|
||||
uint32_t height; // Frame height
|
||||
PIXFORMAT_STRUCT; // Pixel format
|
||||
} framebuffer_header_t;
|
||||
|
||||
void framebuffer_init0();
|
||||
|
||||
// Initializes a frame buffer instance.
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit 034e21a74587e6dee72a89e04ca93e810804c181
|
||||
Subproject commit b7efb956cfb21afda9b71162eeefec8c31d3dff9
|
BIN
lib/models/blazeface_front_128.tflite
Normal file
BIN
lib/models/blazeface_front_128.tflite
Normal file
Binary file not shown.
@ -178,7 +178,7 @@ int ml_backend_init_model(py_ml_model_obj_t *model) {
|
||||
const LL_Buffer_InfoTypeDef *model_outputs = ll_aton_reloc_get_output_buffers_info(&state->nn_inst, -1);
|
||||
|
||||
// Initialize the model's inputs.
|
||||
model->inputs_size = 1;
|
||||
for (model->inputs_size = 0; model_inputs[model->inputs_size].name != NULL; model->inputs_size++);
|
||||
model->input_shape = (mp_obj_tuple_t *) MP_OBJ_TO_PTR(mp_obj_new_tuple(model->inputs_size, NULL));
|
||||
model->input_scale = (mp_obj_tuple_t *) MP_OBJ_TO_PTR(mp_obj_new_tuple(model->inputs_size, NULL));
|
||||
model->input_zero_point = (mp_obj_tuple_t *) MP_OBJ_TO_PTR(mp_obj_new_tuple(model->inputs_size, NULL));
|
||||
@ -205,7 +205,7 @@ int ml_backend_init_model(py_ml_model_obj_t *model) {
|
||||
}
|
||||
|
||||
// Initialize the model's outputs.
|
||||
model->outputs_size = 1;
|
||||
for (model->outputs_size = 0; model_outputs[model->outputs_size].name != NULL; model->outputs_size++);
|
||||
model->output_shape = (mp_obj_tuple_t *) MP_OBJ_TO_PTR(mp_obj_new_tuple(model->outputs_size, NULL));
|
||||
model->output_scale = (mp_obj_tuple_t *) MP_OBJ_TO_PTR(mp_obj_new_tuple(model->outputs_size, NULL));
|
||||
model->output_zero_point = (mp_obj_tuple_t *) MP_OBJ_TO_PTR(mp_obj_new_tuple(model->outputs_size, NULL));
|
||||
|
70
ports/alif/omv_crc.c
Normal file
70
ports/alif/omv_crc.c
Normal file
@ -0,0 +1,70 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Copyright (C) 2023-2024 OpenMV, LLC.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
#include "crc.h"
|
||||
#include "global_map.h"
|
||||
#include "omv_crc.h"
|
||||
|
||||
#define CRC0 ((CRC_Type *)CRC0_BASE)
|
||||
|
||||
static bool crc_initialized = false;
|
||||
|
||||
void omv_crc_init(void) {
|
||||
crc_clear_config(CRC0);
|
||||
crc_enable_16bit(CRC0);
|
||||
crc_enable_custom_poly(CRC0);
|
||||
crc_set_custom_poly(CRC0, OMV_CRC_POLY);
|
||||
crc_set_seed(CRC0, OMV_CRC_INIT);
|
||||
crc_enable(CRC0);
|
||||
crc_initialized = true;
|
||||
}
|
||||
|
||||
omv_crc_t omv_crc_start(const void *buf, size_t size) {
|
||||
if (!crc_initialized) {
|
||||
omv_crc_init();
|
||||
}
|
||||
|
||||
if (size == 0) {
|
||||
return OMV_CRC_INIT;
|
||||
}
|
||||
|
||||
uint32_t result = 0;
|
||||
crc_calculate_16bit(CRC0, buf, size, &result);
|
||||
return (omv_crc_t)result;
|
||||
}
|
||||
|
||||
omv_crc_t omv_crc_update(omv_crc_t crc, const void *buf, size_t size) {
|
||||
if (!crc_initialized) {
|
||||
omv_crc_init();
|
||||
}
|
||||
|
||||
if (size == 0) {
|
||||
return crc;
|
||||
}
|
||||
|
||||
// Set current CRC value and calculate incrementally
|
||||
crc_set_seed(CRC0, crc);
|
||||
uint32_t result = 0;
|
||||
crc_calculate_16bit(CRC0, buf, size, &result);
|
||||
return (omv_crc_t)result;
|
||||
}
|
73
ports/stm32/omv_crc.c
Normal file
73
ports/stm32/omv_crc.c
Normal file
@ -0,0 +1,73 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Copyright (C) 2025 OpenMV, LLC.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
// Only compile for STM32 families with configurable CRC hardware
|
||||
#include STM32_HAL_H
|
||||
#include "omv_crc.h"
|
||||
#include <stdbool.h>
|
||||
|
||||
#if defined(STM32F7) || defined(STM32H7) || defined(STM32N6)
|
||||
static CRC_HandleTypeDef hcrc = {0};
|
||||
static bool crc_initialized = false;
|
||||
|
||||
void omv_crc_init(void) {
|
||||
hcrc.Instance = CRC;
|
||||
hcrc.Init.DefaultPolynomialUse = DEFAULT_POLYNOMIAL_DISABLE;
|
||||
hcrc.Init.GeneratingPolynomial = OMV_CRC_POLY;
|
||||
hcrc.Init.DefaultInitValueUse = DEFAULT_INIT_VALUE_DISABLE;
|
||||
hcrc.Init.InitValue = OMV_CRC_INIT;
|
||||
hcrc.Init.CRCLength = CRC_POLYLENGTH_16B;
|
||||
hcrc.Init.InputDataInversionMode = CRC_INPUTDATA_INVERSION_NONE;
|
||||
hcrc.Init.OutputDataInversionMode = CRC_OUTPUTDATA_INVERSION_DISABLE;
|
||||
hcrc.InputDataFormat = CRC_INPUTDATA_FORMAT_BYTES;
|
||||
|
||||
HAL_CRC_Init(&hcrc);
|
||||
crc_initialized = true;
|
||||
}
|
||||
|
||||
omv_crc_t omv_crc_start(const void *buf, size_t size) {
|
||||
if (!crc_initialized) {
|
||||
omv_crc_init();
|
||||
}
|
||||
|
||||
if (size == 0) {
|
||||
return OMV_CRC_INIT;
|
||||
}
|
||||
|
||||
return (omv_crc_t) HAL_CRC_Calculate(&hcrc, (uint32_t *)buf, size);
|
||||
}
|
||||
|
||||
omv_crc_t omv_crc_update(omv_crc_t crc, const void *buf, size_t size) {
|
||||
if (!crc_initialized) {
|
||||
omv_crc_init();
|
||||
}
|
||||
|
||||
if (size == 0) {
|
||||
return crc;
|
||||
}
|
||||
|
||||
return (omv_crc_t) HAL_CRC_Accumulate(&hcrc, (uint32_t *)buf, size);
|
||||
}
|
||||
|
||||
#endif // STM32F7 || STM32H7 || STM32N6
|
@ -146,54 +146,39 @@ void HAL_MspInit(void) {
|
||||
|
||||
// Enable GPIO clocks.
|
||||
__HAL_RCC_GPIOA_CLK_ENABLE();
|
||||
__HAL_RCC_GPIOA_CLK_SLEEP_ENABLE();
|
||||
__HAL_RCC_GPIOB_CLK_ENABLE();
|
||||
__HAL_RCC_GPIOB_CLK_SLEEP_ENABLE();
|
||||
__HAL_RCC_GPIOC_CLK_ENABLE();
|
||||
__HAL_RCC_GPIOC_CLK_SLEEP_ENABLE();
|
||||
__HAL_RCC_GPIOD_CLK_ENABLE();
|
||||
__HAL_RCC_GPIOD_CLK_SLEEP_ENABLE();
|
||||
__HAL_RCC_GPIOE_CLK_ENABLE();
|
||||
__HAL_RCC_GPIOE_CLK_SLEEP_ENABLE();
|
||||
#if OMV_GPIO_PORT_F_ENABLE
|
||||
__HAL_RCC_GPIOF_CLK_ENABLE();
|
||||
__HAL_RCC_GPIOF_CLK_SLEEP_ENABLE();
|
||||
#endif
|
||||
#if OMV_GPIO_PORT_G_ENABLE
|
||||
__HAL_RCC_GPIOG_CLK_ENABLE();
|
||||
__HAL_RCC_GPIOG_CLK_SLEEP_ENABLE();
|
||||
#endif
|
||||
#if OMV_GPIO_PORT_H_ENABLE
|
||||
__HAL_RCC_GPIOH_CLK_ENABLE();
|
||||
__HAL_RCC_GPIOH_CLK_SLEEP_ENABLE();
|
||||
#endif
|
||||
#if OMV_GPIO_PORT_I_ENABLE
|
||||
__HAL_RCC_GPIOI_CLK_ENABLE();
|
||||
__HAL_RCC_GPIOI_CLK_SLEEP_ENABLE();
|
||||
#endif
|
||||
#if OMV_GPIO_PORT_J_ENABLE
|
||||
__HAL_RCC_GPIOJ_CLK_ENABLE();
|
||||
__HAL_RCC_GPIOJ_CLK_SLEEP_ENABLE();
|
||||
#endif
|
||||
#if OMV_GPIO_PORT_K_ENABLE
|
||||
__HAL_RCC_GPIOK_CLK_ENABLE();
|
||||
__HAL_RCC_GPIOK_CLK_SLEEP_ENABLE();
|
||||
#endif
|
||||
#if OMV_GPIO_PORT_N_ENABLE
|
||||
__HAL_RCC_GPION_CLK_ENABLE();
|
||||
__HAL_RCC_GPION_CLK_SLEEP_ENABLE();
|
||||
#endif
|
||||
#if OMV_GPIO_PORT_O_ENABLE
|
||||
__HAL_RCC_GPIOO_CLK_ENABLE();
|
||||
__HAL_RCC_GPIOO_CLK_SLEEP_ENABLE();
|
||||
#endif
|
||||
#if OMV_GPIO_PORT_P_ENABLE
|
||||
__HAL_RCC_GPIOP_CLK_ENABLE();
|
||||
__HAL_RCC_GPIOP_CLK_SLEEP_ENABLE();
|
||||
#endif
|
||||
#if OMV_GPIO_PORT_Q_ENABLE
|
||||
__HAL_RCC_GPIOQ_CLK_ENABLE();
|
||||
__HAL_RCC_GPIOQ_CLK_SLEEP_ENABLE();
|
||||
#endif
|
||||
|
||||
// Enable DMA clocks.
|
||||
@ -205,11 +190,9 @@ void HAL_MspInit(void) {
|
||||
#endif
|
||||
#if defined(__HAL_RCC_GPDMA1_CLK_ENABLE)
|
||||
__HAL_RCC_GPDMA1_CLK_ENABLE();
|
||||
__HAL_RCC_GPDMA1_CLK_SLEEP_ENABLE();
|
||||
#endif
|
||||
#if defined(__HAL_RCC_HPDMA1_CLK_ENABLE)
|
||||
__HAL_RCC_HPDMA1_CLK_ENABLE();
|
||||
__HAL_RCC_HPDMA1_CLK_SLEEP_ENABLE();
|
||||
#endif
|
||||
#if defined(__HAL_RCC_MDMA_CLK_ENABLE)
|
||||
__HAL_RCC_MDMA_CLK_ENABLE();
|
||||
@ -220,10 +203,7 @@ void HAL_MspInit(void) {
|
||||
// Enable SDMMCx clocks.
|
||||
#if defined(STM32N6)
|
||||
__HAL_RCC_SDMMC1_CLK_ENABLE();
|
||||
__HAL_RCC_SDMMC1_CLK_SLEEP_ENABLE();
|
||||
|
||||
__HAL_RCC_SDMMC2_CLK_ENABLE();
|
||||
__HAL_RCC_SDMMC2_CLK_SLEEP_ENABLE();
|
||||
#endif
|
||||
|
||||
// Setup AXI QoS
|
||||
@ -277,6 +257,23 @@ void HAL_MspInit(void) {
|
||||
HAL_SYSCFG_AnalogSwitchConfig(SYSCFG_SWITCH_PC3, SYSCFG_SWITCH_PC3_CLOSE);
|
||||
#endif
|
||||
|
||||
#if defined(STM32N6)
|
||||
// Enable AHB peripherals during sleep.
|
||||
LL_AHB1_GRP1_EnableClockLowPower(LL_AHB1_GRP1_PERIPH_ALL);
|
||||
LL_AHB2_GRP1_EnableClockLowPower(LL_AHB2_GRP1_PERIPH_ALL);
|
||||
LL_AHB3_GRP1_EnableClockLowPower(LL_AHB3_GRP1_PERIPH_ALL);
|
||||
LL_AHB4_GRP1_EnableClockLowPower(LL_AHB4_GRP1_PERIPH_ALL);
|
||||
LL_AHB5_GRP1_EnableClockLowPower(LL_AHB5_GRP1_PERIPH_ALL);
|
||||
|
||||
// Enable APB peripherals during sleep.
|
||||
LL_APB1_GRP1_EnableClockLowPower(LL_APB1_GRP1_PERIPH_ALL);
|
||||
LL_APB1_GRP2_EnableClockLowPower(LL_APB1_GRP2_PERIPH_ALL);
|
||||
LL_APB2_GRP1_EnableClockLowPower(LL_APB2_GRP1_PERIPH_ALL);
|
||||
LL_APB4_GRP1_EnableClockLowPower(LL_APB4_GRP1_PERIPH_ALL);
|
||||
LL_APB4_GRP2_EnableClockLowPower(LL_APB4_GRP2_PERIPH_ALL);
|
||||
LL_APB5_GRP1_EnableClockLowPower(LL_APB5_GRP1_PERIPH_ALL);
|
||||
#endif
|
||||
|
||||
#if defined(STM32N6)
|
||||
__HAL_RCC_RIFSC_CLK_ENABLE();
|
||||
|
||||
@ -315,28 +312,24 @@ void HAL_I2C_MspInit(I2C_HandleTypeDef *hi2c) {
|
||||
scl_pin = OMV_I2C1_SCL_PIN;
|
||||
sda_pin = OMV_I2C1_SDA_PIN;
|
||||
__HAL_RCC_I2C1_CLK_ENABLE();
|
||||
__HAL_RCC_I2C1_CLK_SLEEP_ENABLE();
|
||||
#endif
|
||||
#if defined(OMV_I2C2_ID)
|
||||
} else if (hi2c->Instance == I2C2) {
|
||||
scl_pin = OMV_I2C2_SCL_PIN;
|
||||
sda_pin = OMV_I2C2_SDA_PIN;
|
||||
__HAL_RCC_I2C2_CLK_ENABLE();
|
||||
__HAL_RCC_I2C2_CLK_SLEEP_ENABLE();
|
||||
#endif
|
||||
#if defined(OMV_I2C3_ID)
|
||||
} else if (hi2c->Instance == I2C3) {
|
||||
scl_pin = OMV_I2C3_SCL_PIN;
|
||||
sda_pin = OMV_I2C3_SDA_PIN;
|
||||
__HAL_RCC_I2C3_CLK_ENABLE();
|
||||
__HAL_RCC_I2C3_CLK_SLEEP_ENABLE();
|
||||
#endif
|
||||
#if defined(OMV_I2C4_ID)
|
||||
} else if (hi2c->Instance == I2C4) {
|
||||
scl_pin = OMV_I2C4_SCL_PIN;
|
||||
sda_pin = OMV_I2C4_SDA_PIN;
|
||||
__HAL_RCC_I2C4_CLK_ENABLE();
|
||||
__HAL_RCC_I2C4_CLK_SLEEP_ENABLE();
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -353,28 +346,24 @@ void HAL_I2C_MspDeInit(I2C_HandleTypeDef *hi2c) {
|
||||
__HAL_RCC_I2C1_FORCE_RESET();
|
||||
__HAL_RCC_I2C1_RELEASE_RESET();
|
||||
__HAL_RCC_I2C1_CLK_DISABLE();
|
||||
__HAL_RCC_I2C1_CLK_SLEEP_DISABLE();
|
||||
#endif
|
||||
#if defined(OMV_I2C2_ID)
|
||||
} else if (hi2c->Instance == I2C2) {
|
||||
__HAL_RCC_I2C2_FORCE_RESET();
|
||||
__HAL_RCC_I2C2_RELEASE_RESET();
|
||||
__HAL_RCC_I2C2_CLK_DISABLE();
|
||||
__HAL_RCC_I2C2_CLK_SLEEP_DISABLE();
|
||||
#endif
|
||||
#if defined(OMV_I2C3_ID)
|
||||
} else if (hi2c->Instance == I2C3) {
|
||||
__HAL_RCC_I2C3_FORCE_RESET();
|
||||
__HAL_RCC_I2C3_RELEASE_RESET();
|
||||
__HAL_RCC_I2C3_CLK_DISABLE();
|
||||
__HAL_RCC_I2C3_CLK_SLEEP_DISABLE();
|
||||
#endif
|
||||
#if defined(OMV_I2C4_ID)
|
||||
} else if (hi2c->Instance == I2C4) {
|
||||
__HAL_RCC_I2C4_FORCE_RESET();
|
||||
__HAL_RCC_I2C4_RELEASE_RESET();
|
||||
__HAL_RCC_I2C4_CLK_DISABLE();
|
||||
__HAL_RCC_I2C4_CLK_SLEEP_DISABLE();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@ -384,7 +373,6 @@ void HAL_TIM_PWM_MspInit(TIM_HandleTypeDef *htim) {
|
||||
if (htim->Instance == OMV_CSI_TIM) {
|
||||
// Enable DCMI timer clock.
|
||||
OMV_CSI_TIM_CLK_ENABLE();
|
||||
OMV_CSI_TIM_CLK_SLEEP_ENABLE();
|
||||
// Timer GPIO configuration.
|
||||
omv_gpio_config(OMV_CSI_TIM_PIN, OMV_GPIO_MODE_ALT, OMV_GPIO_PULL_UP, OMV_GPIO_SPEED_HIGH, -1);
|
||||
#if defined(OMV_CSI_TIM_EXT_PIN)
|
||||
@ -399,7 +387,6 @@ void HAL_TIM_PWM_MspDeInit(TIM_HandleTypeDef *htim) {
|
||||
if (htim->Instance == OMV_CSI_TIM) {
|
||||
// Disable DCMI timer clock.
|
||||
OMV_CSI_TIM_CLK_DISABLE();
|
||||
OMV_CSI_TIM_CLK_SLEEP_DISABLE();
|
||||
// Deinit timer GPIO.
|
||||
omv_gpio_deinit(OMV_CSI_TIM_PIN);
|
||||
#if defined(OMV_CSI_TIM_EXT_PIN)
|
||||
@ -429,10 +416,8 @@ void HAL_DCMI_MspInit(DCMI_HandleTypeDef *hdcmi) {
|
||||
// Enable DCMI clock.
|
||||
#if defined(PSSI)
|
||||
__HAL_RCC_DCMI_PSSI_CLK_ENABLE();
|
||||
__HAL_RCC_DCMI_PSSI_CLK_SLEEP_ENABLE();
|
||||
#else
|
||||
__HAL_RCC_DCMI_CLK_ENABLE();
|
||||
__HAL_RCC_DCMI_CLK_SLEEP_ENABLE();
|
||||
#endif
|
||||
|
||||
#ifdef OMV_CSI_VSYNC_PIN
|
||||
@ -469,10 +454,8 @@ void HAL_DCMI_MspDeInit(DCMI_HandleTypeDef *hdcmi) {
|
||||
// Disable DCMI clock.
|
||||
#if defined(PSSI)
|
||||
__HAL_RCC_DCMI_PSSI_CLK_DISABLE();
|
||||
__HAL_RCC_DCMI_PSSI_CLK_SLEEP_DISABLE();
|
||||
#else
|
||||
__HAL_RCC_DCMI_CLK_DISABLE();
|
||||
__HAL_RCC_DCMI_CLK_SLEEP_DISABLE();
|
||||
#endif
|
||||
|
||||
// Deinit pins.
|
||||
@ -485,13 +468,11 @@ void HAL_DCMI_MspDeInit(DCMI_HandleTypeDef *hdcmi) {
|
||||
void HAL_DCMIPP_MspInit(DCMIPP_HandleTypeDef *hdcmipp) {
|
||||
// Enable DCMIPP clock.
|
||||
__HAL_RCC_DCMIPP_CLK_ENABLE();
|
||||
__HAL_RCC_DCMIPP_CLK_SLEEP_ENABLE();
|
||||
__HAL_RCC_DCMIPP_FORCE_RESET();
|
||||
__HAL_RCC_DCMIPP_RELEASE_RESET();
|
||||
|
||||
// Enable CSI clock
|
||||
__HAL_RCC_CSI_CLK_ENABLE();
|
||||
__HAL_RCC_CSI_CLK_SLEEP_ENABLE();
|
||||
__HAL_RCC_CSI_FORCE_RESET();
|
||||
__HAL_RCC_CSI_RELEASE_RESET();
|
||||
}
|
||||
@ -501,12 +482,10 @@ void HAL_DCMIPP_MspDeInit(DCMIPP_HandleTypeDef *hdcmipp) {
|
||||
__HAL_RCC_DCMIPP_FORCE_RESET();
|
||||
__HAL_RCC_DCMIPP_RELEASE_RESET();
|
||||
__HAL_RCC_DCMIPP_CLK_DISABLE();
|
||||
__HAL_RCC_DCMIPP_CLK_SLEEP_DISABLE();
|
||||
|
||||
__HAL_RCC_CSI_FORCE_RESET();
|
||||
__HAL_RCC_CSI_RELEASE_RESET();
|
||||
__HAL_RCC_CSI_CLK_DISABLE();
|
||||
__HAL_RCC_CSI_CLK_SLEEP_DISABLE();
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -524,7 +503,6 @@ void HAL_SPI_MspInit(SPI_HandleTypeDef *hspi) {
|
||||
#if defined(OMV_SPI1_ID)
|
||||
} else if (hspi->Instance == SPI1) {
|
||||
__HAL_RCC_SPI1_CLK_ENABLE();
|
||||
__HAL_RCC_SPI1_CLK_SLEEP_ENABLE();
|
||||
spi_pins = (spi_pins_t) {
|
||||
OMV_SPI1_SCLK_PIN, OMV_SPI1_MISO_PIN, OMV_SPI1_MOSI_PIN, OMV_SPI1_SSEL_PIN
|
||||
};
|
||||
@ -532,7 +510,6 @@ void HAL_SPI_MspInit(SPI_HandleTypeDef *hspi) {
|
||||
#if defined(OMV_SPI2_ID)
|
||||
} else if (hspi->Instance == SPI2) {
|
||||
__HAL_RCC_SPI2_CLK_ENABLE();
|
||||
__HAL_RCC_SPI2_CLK_SLEEP_ENABLE();
|
||||
spi_pins = (spi_pins_t) {
|
||||
OMV_SPI2_SCLK_PIN, OMV_SPI2_MISO_PIN, OMV_SPI2_MOSI_PIN, OMV_SPI2_SSEL_PIN
|
||||
};
|
||||
@ -540,7 +517,6 @@ void HAL_SPI_MspInit(SPI_HandleTypeDef *hspi) {
|
||||
#if defined(OMV_SPI3_ID)
|
||||
} else if (hspi->Instance == SPI3) {
|
||||
__HAL_RCC_SPI3_CLK_ENABLE();
|
||||
__HAL_RCC_SPI3_CLK_SLEEP_ENABLE();
|
||||
spi_pins = (spi_pins_t) {
|
||||
OMV_SPI3_SCLK_PIN, OMV_SPI3_MISO_PIN, OMV_SPI3_MOSI_PIN, OMV_SPI3_SSEL_PIN
|
||||
};
|
||||
@ -548,7 +524,6 @@ void HAL_SPI_MspInit(SPI_HandleTypeDef *hspi) {
|
||||
#if defined(OMV_SPI4_ID)
|
||||
} else if (hspi->Instance == SPI4) {
|
||||
__HAL_RCC_SPI4_CLK_ENABLE();
|
||||
__HAL_RCC_SPI4_CLK_SLEEP_ENABLE();
|
||||
spi_pins = (spi_pins_t) {
|
||||
OMV_SPI4_SCLK_PIN, OMV_SPI4_MISO_PIN, OMV_SPI4_MOSI_PIN, OMV_SPI4_SSEL_PIN
|
||||
};
|
||||
@ -556,7 +531,6 @@ void HAL_SPI_MspInit(SPI_HandleTypeDef *hspi) {
|
||||
#if defined(OMV_SPI5_ID)
|
||||
} else if (hspi->Instance == SPI5) {
|
||||
__HAL_RCC_SPI5_CLK_ENABLE();
|
||||
__HAL_RCC_SPI5_CLK_SLEEP_ENABLE();
|
||||
spi_pins = (spi_pins_t) {
|
||||
OMV_SPI5_SCLK_PIN, OMV_SPI5_MISO_PIN, OMV_SPI5_MOSI_PIN, OMV_SPI5_SSEL_PIN
|
||||
};
|
||||
@ -564,7 +538,6 @@ void HAL_SPI_MspInit(SPI_HandleTypeDef *hspi) {
|
||||
#if defined(SPI6_ID)
|
||||
} else if (hspi->Instance == SPI6) {
|
||||
__HAL_RCC_SPI6_CLK_ENABLE();
|
||||
__HAL_RCC_SPI6_CLK_SLEEP_ENABLE();
|
||||
spi_pins = (spi_pins_t) {
|
||||
SPI6_SCLK_PIN, SPI6_MISO_PIN, SPI6_MOSI_PIN, SPI6_SSEL_PIN
|
||||
};
|
||||
@ -630,7 +603,6 @@ void HAL_SPI_MspDeInit(SPI_HandleTypeDef *hspi) {
|
||||
__HAL_RCC_SPI1_FORCE_RESET();
|
||||
__HAL_RCC_SPI1_RELEASE_RESET();
|
||||
__HAL_RCC_SPI1_CLK_DISABLE();
|
||||
__HAL_RCC_SPI1_CLK_SLEEP_DISABLE();
|
||||
spi_pins = (spi_pins_t) {
|
||||
OMV_SPI1_SCLK_PIN, OMV_SPI1_MISO_PIN, OMV_SPI1_MOSI_PIN, OMV_SPI1_SSEL_PIN
|
||||
};
|
||||
@ -640,7 +612,6 @@ void HAL_SPI_MspDeInit(SPI_HandleTypeDef *hspi) {
|
||||
__HAL_RCC_SPI2_FORCE_RESET();
|
||||
__HAL_RCC_SPI2_RELEASE_RESET();
|
||||
__HAL_RCC_SPI2_CLK_DISABLE();
|
||||
__HAL_RCC_SPI2_CLK_SLEEP_DISABLE();
|
||||
spi_pins = (spi_pins_t) {
|
||||
OMV_SPI2_SCLK_PIN, OMV_SPI2_MISO_PIN, OMV_SPI2_MOSI_PIN, OMV_SPI2_SSEL_PIN
|
||||
};
|
||||
@ -650,7 +621,6 @@ void HAL_SPI_MspDeInit(SPI_HandleTypeDef *hspi) {
|
||||
__HAL_RCC_SPI3_FORCE_RESET();
|
||||
__HAL_RCC_SPI3_RELEASE_RESET();
|
||||
__HAL_RCC_SPI3_CLK_DISABLE();
|
||||
__HAL_RCC_SPI3_CLK_SLEEP_DISABLE();
|
||||
spi_pins = (spi_pins_t) {
|
||||
OMV_SPI3_SCLK_PIN, OMV_SPI3_MISO_PIN, OMV_SPI3_MOSI_PIN, OMV_SPI3_SSEL_PIN
|
||||
};
|
||||
@ -660,7 +630,6 @@ void HAL_SPI_MspDeInit(SPI_HandleTypeDef *hspi) {
|
||||
__HAL_RCC_SPI4_FORCE_RESET();
|
||||
__HAL_RCC_SPI4_RELEASE_RESET();
|
||||
__HAL_RCC_SPI4_CLK_DISABLE();
|
||||
__HAL_RCC_SPI4_CLK_SLEEP_DISABLE();
|
||||
spi_pins = (spi_pins_t) {
|
||||
OMV_SPI4_SCLK_PIN, OMV_SPI4_MISO_PIN, OMV_SPI4_MOSI_PIN, OMV_SPI4_SSEL_PIN
|
||||
};
|
||||
@ -670,7 +639,6 @@ void HAL_SPI_MspDeInit(SPI_HandleTypeDef *hspi) {
|
||||
__HAL_RCC_SPI5_FORCE_RESET();
|
||||
__HAL_RCC_SPI5_RELEASE_RESET();
|
||||
__HAL_RCC_SPI5_CLK_DISABLE();
|
||||
__HAL_RCC_SPI5_CLK_SLEEP_DISABLE();
|
||||
spi_pins = (spi_pins_t) {
|
||||
OMV_SPI5_SCLK_PIN, OMV_SPI5_MISO_PIN, OMV_SPI5_MOSI_PIN, OMV_SPI5_SSEL_PIN
|
||||
};
|
||||
@ -680,7 +648,6 @@ void HAL_SPI_MspDeInit(SPI_HandleTypeDef *hspi) {
|
||||
__HAL_RCC_SPI6_FORCE_RESET();
|
||||
__HAL_RCC_SPI6_RELEASE_RESET();
|
||||
__HAL_RCC_SPI6_CLK_DISABLE();
|
||||
__HAL_RCC_SPI6_CLK_SLEEP_DISABLE();
|
||||
spi_pins = (spi_pins_t) {
|
||||
SPI6_SCLK_PIN, SPI6_MISO_PIN, SPI6_MOSI_PIN, SPI6_SSEL_PIN
|
||||
};
|
||||
@ -742,10 +709,8 @@ void HAL_MDF_MspInit(MDF_HandleTypeDef *hmdf) {
|
||||
if (hmdf->Instance == OMV_MDF) {
|
||||
if (IS_ADF_INSTANCE(hmdf->Instance)) {
|
||||
__HAL_RCC_ADF1_CLK_ENABLE();
|
||||
__HAL_RCC_ADF1_CLK_SLEEP_ENABLE();
|
||||
} else {
|
||||
__HAL_RCC_MDF1_CLK_ENABLE();
|
||||
__HAL_RCC_MDF1_CLK_SLEEP_ENABLE();
|
||||
}
|
||||
|
||||
omv_gpio_config(OMV_MDF_CK_PIN, OMV_GPIO_MODE_ALT, OMV_GPIO_PULL_NONE, OMV_GPIO_SPEED_LOW, -1);
|
||||
@ -757,10 +722,8 @@ void HAL_MDF_MspDeInit(MDF_HandleTypeDef *hmdf) {
|
||||
if (hmdf->Instance == OMV_MDF) {
|
||||
if (IS_ADF_INSTANCE(hmdf->Instance)) {
|
||||
__HAL_RCC_ADF1_CLK_DISABLE();
|
||||
__HAL_RCC_ADF1_CLK_SLEEP_DISABLE();
|
||||
} else {
|
||||
__HAL_RCC_MDF1_CLK_DISABLE();
|
||||
__HAL_RCC_MDF1_CLK_SLEEP_DISABLE();
|
||||
}
|
||||
|
||||
omv_gpio_deinit(OMV_MDF_CK_PIN);
|
||||
@ -771,65 +734,53 @@ void HAL_MDF_MspDeInit(MDF_HandleTypeDef *hmdf) {
|
||||
|
||||
void HAL_CRC_MspInit(CRC_HandleTypeDef *hcrc) {
|
||||
__HAL_RCC_CRC_CLK_ENABLE();
|
||||
__HAL_RCC_CRC_CLK_SLEEP_ENABLE();
|
||||
}
|
||||
|
||||
void HAL_CRC_MspDeInit(CRC_HandleTypeDef *hcrc) {
|
||||
__HAL_RCC_CRC_CLK_DISABLE();
|
||||
__HAL_RCC_CRC_CLK_SLEEP_DISABLE();
|
||||
}
|
||||
|
||||
void HAL_DMA2D_MspInit(DMA2D_HandleTypeDef *hdma2d) {
|
||||
__HAL_RCC_DMA2D_CLK_ENABLE();
|
||||
__HAL_RCC_DMA2D_CLK_SLEEP_ENABLE();
|
||||
}
|
||||
|
||||
void HAL_DMA2D_MspDeInit(DMA2D_HandleTypeDef *hdma2d) {
|
||||
__HAL_RCC_DMA2D_FORCE_RESET();
|
||||
__HAL_RCC_DMA2D_RELEASE_RESET();
|
||||
|
||||
__HAL_RCC_DMA2D_CLK_DISABLE();
|
||||
__HAL_RCC_DMA2D_CLK_SLEEP_DISABLE();
|
||||
}
|
||||
|
||||
#if defined(GPU2D)
|
||||
void HAL_GPU2D_MspInit(GPU2D_HandleTypeDef *hgpu2d) {
|
||||
__HAL_RCC_GPU2D_FORCE_RESET();
|
||||
__HAL_RCC_GPU2D_RELEASE_RESET();
|
||||
|
||||
__HAL_RCC_GPU2D_CLK_ENABLE();
|
||||
__HAL_RCC_GPU2D_CLK_SLEEP_ENABLE();
|
||||
}
|
||||
|
||||
void HAL_GPU2D_MspDeInit(GPU2D_HandleTypeDef *hgpu2d) {
|
||||
__HAL_RCC_GPU2D_CLK_DISABLE();
|
||||
__HAL_RCC_GPU2D_CLK_SLEEP_DISABLE();
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(GFXMMU)
|
||||
void HAL_GFXMMU_MspInit(GFXMMU_HandleTypeDef *hgfxmmu) {
|
||||
__HAL_RCC_GFXMMU_CLK_ENABLE();
|
||||
__HAL_RCC_GFXMMU_CLK_SLEEP_ENABLE();
|
||||
}
|
||||
|
||||
void HAL_GFXMMU_MspDeInit(GFXMMU_HandleTypeDef *hgfxmmu) {
|
||||
__HAL_RCC_GFXMMU_CLK_DISABLE();
|
||||
__HAL_RCC_GFXMMU_CLK_SLEEP_DISABLE();
|
||||
}
|
||||
#endif
|
||||
|
||||
#if (OMV_JPEG_CODEC_ENABLE == 1)
|
||||
void HAL_JPEG_MspInit(JPEG_HandleTypeDef *hjpeg) {
|
||||
__HAL_RCC_JPEG_CLK_ENABLE();
|
||||
__HAL_RCC_JPEG_CLK_SLEEP_ENABLE();
|
||||
}
|
||||
|
||||
void HAL_JPEG_MspDeInit(JPEG_HandleTypeDef *hjpeg) {
|
||||
__HAL_RCC_JPEG_FORCE_RESET();
|
||||
__HAL_RCC_JPEG_RELEASE_RESET();
|
||||
__HAL_RCC_JPEG_CLK_DISABLE();
|
||||
__HAL_RCC_JPEG_CLK_SLEEP_DISABLE();
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -974,17 +925,14 @@ void HAL_XSPI_MspInit(XSPI_HandleTypeDef *hxspi) {
|
||||
__HAL_RCC_XSPI1_FORCE_RESET();
|
||||
__HAL_RCC_XSPI1_RELEASE_RESET();
|
||||
__HAL_RCC_XSPI1_CLK_ENABLE();
|
||||
__HAL_RCC_XSPI1_CLK_SLEEP_ENABLE();
|
||||
} else if (hxspi->Instance == XSPI2) {
|
||||
__HAL_RCC_XSPI2_FORCE_RESET();
|
||||
__HAL_RCC_XSPI2_RELEASE_RESET();
|
||||
__HAL_RCC_XSPI2_CLK_ENABLE();
|
||||
__HAL_RCC_XSPI2_CLK_SLEEP_ENABLE();
|
||||
} else if (hxspi->Instance == XSPI3) {
|
||||
__HAL_RCC_XSPI3_FORCE_RESET();
|
||||
__HAL_RCC_XSPI3_RELEASE_RESET();
|
||||
__HAL_RCC_XSPI3_CLK_ENABLE();
|
||||
__HAL_RCC_XSPI3_CLK_SLEEP_ENABLE();
|
||||
}
|
||||
|
||||
for (int i = 0; i < OMV_ARRAY_SIZE(xspi_pins); i++) {
|
||||
@ -1021,17 +969,14 @@ void HAL_XSPI_MspDeInit(XSPI_HandleTypeDef *hxspi) {
|
||||
__HAL_RCC_XSPI1_FORCE_RESET();
|
||||
__HAL_RCC_XSPI1_RELEASE_RESET();
|
||||
__HAL_RCC_XSPI1_CLK_DISABLE();
|
||||
__HAL_RCC_XSPI1_CLK_SLEEP_DISABLE();
|
||||
} else if (hxspi->Instance == XSPI2) {
|
||||
__HAL_RCC_XSPI2_FORCE_RESET();
|
||||
__HAL_RCC_XSPI2_RELEASE_RESET();
|
||||
__HAL_RCC_XSPI2_CLK_DISABLE();
|
||||
__HAL_RCC_XSPI2_CLK_SLEEP_DISABLE();
|
||||
} else if (hxspi->Instance == XSPI3) {
|
||||
__HAL_RCC_XSPI3_FORCE_RESET();
|
||||
__HAL_RCC_XSPI3_RELEASE_RESET();
|
||||
__HAL_RCC_XSPI3_CLK_DISABLE();
|
||||
__HAL_RCC_XSPI3_CLK_SLEEP_DISABLE();
|
||||
}
|
||||
|
||||
for (int i = 0; i < OMV_ARRAY_SIZE(xspi_pins); i++) {
|
||||
|
@ -0,0 +1,49 @@
|
||||
# This work is licensed under the MIT license.
|
||||
# Copyright (c) 2013-2025 OpenMV LLC. All rights reserved.
|
||||
# https://github.com/openmv/openmv/blob/master/LICENSE
|
||||
#
|
||||
# This example shows off Google's MediaPipe BlazeFace face detection model.
|
||||
|
||||
import csi
|
||||
import time
|
||||
import ml
|
||||
from ml.postprocessing import mediapipe_face_detection_postprocess
|
||||
|
||||
# Initialize the sensor.
|
||||
csi0 = csi.CSI()
|
||||
csi0.reset()
|
||||
csi0.pixformat(csi.RGB565)
|
||||
csi0.framesize(csi.VGA)
|
||||
csi0.window((400, 400))
|
||||
|
||||
# Load built-in face detection model
|
||||
model = ml.Model("/rom/blazeface_front_128.tflite")
|
||||
print(model)
|
||||
|
||||
# Create the face detection post-processor. This post-processor dynamically
|
||||
# generates anchors for the model input size which should only be done once.
|
||||
face_detection_postprocess = mediapipe_face_detection_postprocess(threshold=0.6)
|
||||
|
||||
clock = time.clock()
|
||||
while True:
|
||||
clock.tick()
|
||||
img = csi0.snapshot()
|
||||
|
||||
# faces is a list of ((x, y, w, h), score, keypoints) tuples
|
||||
faces = model.predict([img], callback=face_detection_postprocess)
|
||||
|
||||
# Draw bounding boxes around the detected faces and keypoints.
|
||||
if faces:
|
||||
for r, score, keypoints in faces[0]:
|
||||
ml.utils.draw_predictions(img, [r], ["face"], [(0, 0, 255)], format=None)
|
||||
# keypoints is a ndarray of shape (6, 2)
|
||||
# 0 - right eye (x, y)
|
||||
# 1 - left eye (x, y)
|
||||
# 2 - nose (x, y)
|
||||
# 3 - mouth (x, y)
|
||||
# 4 - right ear (x, y)
|
||||
# 5 - left ear (x, y)
|
||||
for kp in keypoints.tolist():
|
||||
img.draw_circle(int(kp[0]), int(kp[1]), 4, color=(255, 0, 0))
|
||||
|
||||
print(clock.fps(), "fps")
|
@ -34,6 +34,14 @@ from ulab import numpy as np
|
||||
_NO_DETECTION = const(())
|
||||
|
||||
|
||||
def logit(x):
|
||||
return np.log(x / (1.0 - x))
|
||||
|
||||
|
||||
def sigmoid(x):
|
||||
return 1.0 / (1.0 + np.exp(-x))
|
||||
|
||||
|
||||
def mod(a, b):
|
||||
return a - (b * (a // b))
|
||||
|
||||
@ -49,16 +57,16 @@ def threshold(scores, threshold, scale, find_max=False, find_max_axis=1):
|
||||
return np.nonzero(scores < threshold)[0]
|
||||
|
||||
|
||||
def quantize(model, value):
|
||||
if model.output_dtype[0] == 'f':
|
||||
def quantize(model, value, index=0):
|
||||
if model.output_dtype[index] == 'f':
|
||||
return value
|
||||
return (value / model.output_scale[0]) + model.output_zero_point[0]
|
||||
return (value / model.output_scale[index]) + model.output_zero_point[index]
|
||||
|
||||
|
||||
def dequantize(model, value):
|
||||
if model.output_dtype[0] == 'f':
|
||||
def dequantize(model, value, index=0):
|
||||
if model.output_dtype[index] == 'f':
|
||||
return value
|
||||
return (value - model.output_zero_point[0]) * model.output_scale[0]
|
||||
return (value - float(model.output_zero_point[index])) * model.output_scale[index]
|
||||
|
||||
|
||||
class fomo_postprocess:
|
||||
@ -141,12 +149,6 @@ class yolo_v2_postprocess:
|
||||
|
||||
def __call__(self, model, inputs, outputs):
|
||||
|
||||
def logit(x):
|
||||
return np.log(x / (1.0 - x))
|
||||
|
||||
def sigmoid(x):
|
||||
return 1.0 / (1.0 + np.exp(-x))
|
||||
|
||||
def softmax(x):
|
||||
e_x = np.exp(x - np.max(x, axis=1, keepdims=True))
|
||||
return e_x / np.sum(e_x, axis=1, keepdims=True)
|
||||
@ -330,3 +332,94 @@ class yolo_v8_postprocess:
|
||||
nms.add_bounding_box(xmin[i], ymin[i], xmax[i], ymax[i],
|
||||
bb_scores[i], bb_classes[i])
|
||||
return nms.get_bounding_boxes(threshold=self.nms_threshold, sigma=self.nms_sigma)
|
||||
|
||||
|
||||
class mediapipe_face_detection_postprocess:
|
||||
_BLAZEFACE_CX = const(0)
|
||||
_BLAZEFACE_CY = const(1)
|
||||
_BLAZEFACE_CW = const(2)
|
||||
_BLAZEFACE_CH = const(3)
|
||||
_BLAZEFACE_KP = const(4)
|
||||
|
||||
def __init__(self, threshold=0.6, anchors=None, nms_threshold=0.1, nms_sigma=0.1):
|
||||
self.threshold = threshold
|
||||
self.anchors = anchors
|
||||
|
||||
if self.anchors is None:
|
||||
self.anchors = np.empty((896, 2))
|
||||
idx = 0
|
||||
|
||||
# Generate anchors for 16x16 grid with 2 duplicates and
|
||||
# 8x8 grid with 6 duplicates to match the model output size.
|
||||
for grid_size, scales in [(16, 2), (8, 6)]:
|
||||
for gy in range(grid_size):
|
||||
cy = (gy + 0.5) / grid_size
|
||||
for gx in range(grid_size):
|
||||
cx = (gx + 0.5) / grid_size
|
||||
for _ in range(scales):
|
||||
self.anchors[idx, 0] = cx
|
||||
self.anchors[idx, 1] = cy
|
||||
idx += 1
|
||||
|
||||
self.nms_threshold = nms_threshold
|
||||
self.nms_sigma = nms_sigma
|
||||
|
||||
def __call__(self, model, inputs, outputs):
|
||||
ib, ih, iw, ic = model.input_shape[0]
|
||||
nms = NMS(iw, ih, inputs[0].roi)
|
||||
output_len = outputs[0].shape[1]
|
||||
|
||||
self.blazeface_post_process(ih, iw, nms, model, inputs, outputs, 1, 0,
|
||||
self.threshold, self.anchors[:output_len])
|
||||
|
||||
if output_len < len(self.anchors):
|
||||
self.blazeface_post_process(ih, iw, nms, model, inputs, outputs, 2, 3,
|
||||
self.threshold, self.anchors[output_len:])
|
||||
|
||||
return nms.get_bounding_boxes(threshold=self.nms_threshold, sigma=self.nms_sigma)
|
||||
|
||||
def blazeface_post_process(self, ih, iw, nms, model, inputs, outputs, score_idx, cords_idx, t, anchors):
|
||||
s_oh, s_ow, s_oc = model.output_shape[score_idx]
|
||||
scale = model.output_scale[score_idx]
|
||||
t = quantize(model, logit(t), index=score_idx)
|
||||
|
||||
# Threshold all the scores
|
||||
score_row_outputs = outputs[score_idx].reshape((s_oh * s_ow * s_oc))
|
||||
score_indices = threshold(score_row_outputs, t, scale)
|
||||
if not len(score_indices):
|
||||
return _NO_DETECTION
|
||||
|
||||
# Get the score information
|
||||
bb_scores = np.take(score_row_outputs, score_indices, axis=0)
|
||||
bb_scores = sigmoid(dequantize(model, bb_scores, index=score_idx))
|
||||
|
||||
# Get the bounding boxes that have a valid score
|
||||
c_oh, c_ow, c_oc = model.output_shape[cords_idx]
|
||||
cords_row_outputs = outputs[cords_idx].reshape((c_oh * c_ow, c_oc))
|
||||
bb = dequantize(model, np.take(cords_row_outputs, score_indices, axis=0), index=cords_idx)
|
||||
|
||||
# Get the anchor box information
|
||||
bb_a_array = np.take(anchors, score_indices, axis=0)
|
||||
|
||||
# Compute the bounding box information
|
||||
ax = bb_a_array[:, _BLAZEFACE_CX]
|
||||
ay = bb_a_array[:, _BLAZEFACE_CY]
|
||||
x_center = bb[:, _BLAZEFACE_CX] / iw + ax
|
||||
y_center = bb[:, _BLAZEFACE_CY] / ih + ay
|
||||
w_rel = bb[:, _BLAZEFACE_CW] / iw * 0.5
|
||||
h_rel = bb[:, _BLAZEFACE_CH] / ih * 0.5
|
||||
|
||||
# Get the keypoint information
|
||||
row_count = bb.shape[0]
|
||||
keypoints = np.empty((row_count, (c_oc - _BLAZEFACE_KP) // 2, 2))
|
||||
keypoints[:, :, 0] = (bb[:, _BLAZEFACE_KP::2] / iw + ax.reshape((row_count, 1))) * iw
|
||||
keypoints[:, :, 1] = (bb[:, _BLAZEFACE_KP + 1::2] / ih + ay.reshape((row_count, 1))) * ih
|
||||
|
||||
# Scale the bounding boxes to have enough integer precision for NMS
|
||||
xmin = (x_center - w_rel) * iw
|
||||
ymin = (y_center - h_rel) * ih
|
||||
xmax = (x_center + w_rel) * iw
|
||||
ymax = (y_center + h_rel) * ih
|
||||
|
||||
for i in range(bb.shape[0]):
|
||||
nms.add_bounding_box(xmin[i], ymin[i], xmax[i], ymax[i], bb_scores[i], 0, keypoints=keypoints[i])
|
||||
|
@ -93,4 +93,6 @@ class Normalization:
|
||||
fadd = (fadd - np.array(self.mean)) / np.array(self.stdev)
|
||||
fscale = fscale / np.array(self.stdev)
|
||||
|
||||
array = (array * fscale) + fadd
|
||||
# Apply normalization in-place (must be done in two steps for ulab).
|
||||
array *= fscale
|
||||
array += fadd
|
||||
|
@ -43,7 +43,7 @@ class NMS:
|
||||
raise ValueError("Invalid ROI dimensions!")
|
||||
self.boxes = []
|
||||
|
||||
def add_bounding_box(self, xmin, ymin, xmax, ymax, score, label_index):
|
||||
def add_bounding_box(self, xmin, ymin, xmax, ymax, score, label_index, keypoints=None):
|
||||
if score >= 0.0 and score <= 1.0:
|
||||
xmin = max(0.0, min(xmin, self.window_w))
|
||||
ymin = max(0.0, min(ymin, self.window_h))
|
||||
@ -52,7 +52,7 @@ class NMS:
|
||||
w = int(xmax - xmin)
|
||||
h = int(ymax - ymin)
|
||||
if w > 0 and h > 0:
|
||||
self.boxes.append([int(xmin), int(ymin), w, h, score, label_index])
|
||||
self.boxes.append([int(xmin), int(ymin), w, h, score, label_index, keypoints])
|
||||
|
||||
def get_bounding_boxes(self, threshold=0.1, sigma=0.1):
|
||||
sorted_boxes = sorted(self.boxes, key=lambda x: x[4], reverse=True)
|
||||
@ -107,15 +107,22 @@ class NMS:
|
||||
output_boxes[i][1] = int((output_boxes[i][1] * scale) + y_offset)
|
||||
output_boxes[i][2] = int(output_boxes[i][2] * scale)
|
||||
output_boxes[i][3] = int(output_boxes[i][3] * scale)
|
||||
keypoints = output_boxes[i][6]
|
||||
if keypoints is not None:
|
||||
keypoints *= scale
|
||||
keypoints[:, 0] += x_offset
|
||||
keypoints[:, 1] += y_offset
|
||||
|
||||
# Create a list per class with (rect, score) tuples.
|
||||
|
||||
output_list = [[] for i in range(max_label_index + 1)]
|
||||
|
||||
for i in range(len(output_boxes)):
|
||||
output_list[output_boxes[i][5]].append(
|
||||
(output_boxes[i][0:4], output_boxes[i][4])
|
||||
)
|
||||
rect_score = [output_boxes[i][:4], output_boxes[i][4]]
|
||||
keypoints = output_boxes[i][6]
|
||||
if keypoints is not None:
|
||||
rect_score.append(keypoints)
|
||||
output_list[output_boxes[i][5]].append(tuple(rect_score))
|
||||
|
||||
return output_list
|
||||
|
||||
|
39
tools/ci.sh
39
tools/ci.sh
@ -75,45 +75,6 @@ ci_package_firmware_development() {
|
||||
(cd firmware && for i in *; do zip -r -j "firmware_${i%/}.zip" "$i"; done)
|
||||
}
|
||||
|
||||
########################################################################################
|
||||
# Install code formatter deps
|
||||
CODEFORMAT_PATH=${HOME}/cache/deps/
|
||||
UNCRUSTIFY_PATH=${CODEFORMAT_PATH}/uncrustify
|
||||
UNCRUSTIFY_URL="https://github.com/uncrustify/uncrustify/archive/uncrustify-0.75.0.tar.gz"
|
||||
|
||||
ci_install_code_format_deps() {
|
||||
sudo apt-get install wget cmake build-essential colordiff
|
||||
|
||||
mkdir -p ${UNCRUSTIFY_PATH}
|
||||
wget --no-check-certificate -O - ${UNCRUSTIFY_URL} | tar xvz --strip-components=1 -C ${UNCRUSTIFY_PATH}
|
||||
(cd ${UNCRUSTIFY_PATH} && mkdir build && cd build && cmake .. && cmake --build .)
|
||||
|
||||
# Copy binaries to cache
|
||||
mkdir -p ${CODEFORMAT_PATH}/bin
|
||||
cp ${UNCRUSTIFY_PATH}/build/uncrustify ${CODEFORMAT_PATH}/bin/
|
||||
cp `which colordiff` ${CODEFORMAT_PATH}/bin/
|
||||
chmod +x ${CODEFORMAT_PATH}/bin/uncrustify
|
||||
}
|
||||
|
||||
########################################################################################
|
||||
# Run code formatter
|
||||
ci_run_code_format_check() {
|
||||
export PATH=${CODEFORMAT_PATH}/bin:${PATH}
|
||||
UNCRUSTIFY_CONFIG=tools/uncrustify.cfg
|
||||
|
||||
exit_code=0
|
||||
for file in "$@"; do
|
||||
file_fmt="${file}.tmp"
|
||||
uncrustify -q -c ${UNCRUSTIFY_CONFIG} -f ${file} -o ${file_fmt} || true
|
||||
|
||||
diff -q -u ${file} ${file_fmt} >> /dev/null 2>&1 || {
|
||||
colordiff -u ${file} ${file_fmt} || true
|
||||
exit_code=1
|
||||
}
|
||||
done
|
||||
exit $exit_code
|
||||
}
|
||||
|
||||
########################################################################################
|
||||
# Install STEdgeAI tools
|
||||
STEDGEAI_URL="https://upload.openmv.io/stedgeai/STEdgeAI-2.1.0.tar.gz"
|
||||
|
Loading…
Reference in New Issue
Block a user