共计 3851 个字符,预计需要花费 10 分钟才能阅读完成。
工程名称:【开发板】FryPi 炸鸡派工程作者:quenelle 前言花 50 元,用 STM32F411RET6 做了个产品级迷你开发板!名为——FryPi 炸鸡派。01 开发板的功能 / 亮点?”1 支持热成像手势识别 2 支持做产品级 LVGL 智能手表拥有功能包括:显示时间、血氧、步数、心率;支持小游戏,秒表、卡包、日历、计算器、设置、下拉菜单、蓝牙功能……3 例程丰富,除了上述,还支持:手写数字识别,与 matlab 联合开发,simulink 在环开发等等 4 支持 AI 开发,UI 开发 5 可作为数字电源控制板 6 可以拿去做毕业设计 7 可以无限拓展其他相关项目,二次开发极其友好 8 适用于初学者,也适用于进阶开发者 9 可额外焊接外置 SPI Flash,可外接扩展板02 硬件说明”核心板核心板 PCB拓展板原理图拓展板 PCBOV2640 模块原理图OV2640 模块 PCB 图3D 示意图上下滑动查看完整电路图说明:1MCU 使用 STM32F411RET6,Cortex-M4 core with DSP and FPU,512 Kbytes of Flash memory, 100 MHz CPU, ART Accelerator2 有双 TypeC 和单 TypeC 版本的 Core 板,具体看原文 03 软件说明”目前的例程 demo 如下所示,很丰富,分为:基础例程 Basic 高级例程 AdvancedBasicAdvanced0.template0.FreeRTOS 模板 1.GPIO1. 如何使用 CubeAI2.USART2. 手写数字识别 3.TIM3. 热成像手势识别 4.PWM4. 使用 VScode EIDE 插件 5.ADC5.simulink 在环开发 6.SPI6.LVGL 智能手表 7.LCD7.OV2640 摄像头 + 识别..todo…todo 本章节将说明部分例程。这里拿热成像手势识别为例进行 demo 工程说明(其他的详细的见开源原文,参考文末指引进入原文即可):01 文件夹组成
├─python_codes│ │ data_2_imgfile.py│ │ data_get.py│ │ data_show.py│ │ gesture.h5│ │ test.py│ │ train.py│ │ │ └─camera_data│ test_data.npz│ train_data.npz│ └─stm32_codes ├─ThermalCamera_data_send ├─Thermalgesture
`python_codes` 存放的是:从下位机获取数据、网络训练、测试的代码等。采集的热成像数据保存在.npz 格式的文件中,用于网络的训练和测试,模型保存为.h5 格式。`stm32_codes` 存放的是:STM32 的代码。第一个是 LCD 刷屏 + 串口发送炸鸡派获得的热成像原始数据第二个则是已经部署好的热成像手势识别的代码 02 热成像推流至 LCD 直接使用提供的 MLX90640API,然后对应更改了 IO 口即可,同时为了让刷屏更快,在mlx90640_display_process(void)
函数中将 drawPicture(void)
中刷屏显示使用缓存空间进行刷屏,因为打点刷屏太慢了。03 卷积神经网络搭建、训练、部署(1)CNN 搭建与训练搭建的卷积神经网络如下图所示。训练集大概有 4000 多张图片数组数据。num_epochs
设置为 50batch_size
设置为 64Adam 优化器 learning_rate
设置为 0.01 最后 Acc 大概可以超过 0.9。具体详细的网络搭建详见 ./python_codes/train.py
。使用 keras 搭建的 CNN 模型如下所示,其他相关代码详见 python 代码。#------------------------------【搭模型】---------------------------------model = tf.keras.models.Sequential([
tf.keras.layers.Conv2D(filters=5, kernel_size=(5, 5), padding='valid', activation=tf.nn.relu, input_shape=(24, 32, 1)),
tf.keras.layers.MaxPool2D(pool_size=(2, 2), padding='same'),
tf.keras.layers.Conv2D(filters=3, kernel_size=(3, 3), padding='valid', activation=tf.nn.relu, input_shape=(10, 14, 5)),
tf.keras.layers.MaxPool2D(pool_size=(2, 2), padding='same'),
tf.keras.layers.Flatten(),
tf.keras.layers.Dense(units=32, activation=tf.nn.relu),
tf.keras.layers.Dense(units=16, activation=tf.nn.relu),
tf.keras.layers.Dense(units=6, activation=tf.nn.softmax)
])
model.summary()
(2)CNN 部署至 STM32 首先将训练好得到的 gesture.h5 模型使用 cubemx AI 工具生成代码后,调用 API,这里主要使用的 ai_mnetwork_run()。具体如下代码块中函数 user_ai_run(const ai_float *in_data, ai_float *out_data) 所示。由于 CubeMX 生成代码选择的 systemperform,所以要注释 MX_X_CUBE_AI_Process(),这个里面主要是用来测试模型的性能,他默认使用的随机数填充输入。uint8_t user_ai_run(const ai_float *in_data, ai_float *out_data)
{int idx = 0; int batch = 0;
ai_buffer ai_input[AI_MNETWORK_IN_NUM];
ai_buffer ai_output[AI_MNETWORK_OUT_NUM];
ai_float input[1] = {0};
ai_float output[1] = {0}; if (net_exec_ctx[idx].handle == AI_HANDLE_NULL)
{printf("E: network handle is NULLrn"); return -1;
}
ai_input[0] = net_exec_ctx[idx].report.inputs[0];
ai_output[0] = net_exec_ctx[idx].report.outputs[0];
ai_input[0].data = AI_HANDLE_PTR(in_data);
ai_output[0].data = AI_HANDLE_PTR(out_data);
batch = ai_mnetwork_run(net_exec_ctx[idx].handle, ai_input, ai_output); if (batch != 1) {
aiLogErr(ai_mnetwork_get_error(net_exec_ctx[idx].handle), "ai_mnetwork_run"); return -2;
} return 0;
}
注意,这里我给到输入的数据,还是正常做了归一化的,如下代码所示。static void normalizeArray(){ float range = maxTemp - minTemp; for(uint16_t i=0; i<24*32; i++) {
normalizetempValues[i] = (tempValues[i] - minTemp) / range;
}
}
输出的数据格式为一个长度 6 的数组,分别对应无手势和手势 1~5,类别判定条件为选择最大的数,即判哪个数最大,其对应的手势判断为当前手势。以下代码为寻找最大数对应的 index。static uint8_t findMaxIndex(float arr[], uint8_t size) {if (size <= 0) {// 处理空数组或无效大小的情况
return -1;
} uint8_t maxIndex = 0; // 假设最大值的索引为第一个元素的索引
for (int i = 1; i < size; ++i) {// 检查当前元素是否大于当前最大值
if (arr[i] > arr[maxIndex]) {
maxIndex = i; // 更新最大值的索引
}
} return maxIndex;
}
最后给出整个一轮识别的流程如下所示。normalizeArray();// 先归一化 if(user_ai_run(normalizetempValues, outputs))// 将归一化数据代入,正向运算 {printf("rn run erro rn");
}uint8_t temp = findMaxIndex(outputs, sizeof(outputs) / sizeof(outputs[0]));// 寻找最大值的索引 printf("rnpredict gesture:%drn", temp);// 打印出判断的手势
当然,上面只是 demo 中的其中一个,更多的基础和高级例程 demo 详见开源原文。05 开源网址”——想复刻?想给作者点赞?可复制开源网址前往原文。开源网址:https://oshwhub.com/no_chicken/frypi正文完