☰
STM32神经网络开发实战:从模型训练到边缘AI部署
2026/10/26 9:37:38 网站建设 项目流程

这两年,总有朋友问我:STM32这种嵌入式MCU,真的能跑神经网络、落地AI功能?我的回答一直很明确:能,而且“STM32神经网络开发工具箱”这套路线,已经把我手头的边缘项目从云端AI变成了本地实时推理。不是噱头,是实打实跑在产品里的东西。STM32H7这种Cortex-M7内核的芯片跑小型卷积网络做手势识别、关键词唤醒、异常检测,完全没问题;哪怕是F103这种入门级MCU,跑一个多层前馈神经网络做分类预测,也绰绰有余。

这套工具箱的完整链路就是:传感器采集数据 → PC端训练模型 → 模型量化压缩 → STM32Cube.AI或TensorFlow Lite Micro转换部署 → 嵌入式端实时推理。它解决的核心痛点是“AI上不了MCU”的陈旧认知,以及“边缘设备只能做数据搬运工”的尴尬处境。这篇文章,我把这几年在边缘AI项目里的实战经验、踩坑记录、能直接照抄的流程整理出来,给正在准备把AI引入嵌入式项目的你做个参考。全文不限平台、不绑框架,只要手里有一块STM32开发板就能跟着走一遍。

1. 为什么要在STM32上跑神经网络:边缘AI的价值与工具箱整体架构

先说个最基础的问题:为什么非要在STM32这种资源受限的芯片上跑神经网络,把数据发到服务器让大模型算不香吗?

1.1 边缘推理的刚性需求:延迟、隐私、带宽

物联网设备一旦依赖云端的AI推理,会面临三个绕不开的问题。

第一是实时性。很多控制场景对延迟极其敏感,比如工业设备振动异常检测,传感器采样到故障特征后,需要毫秒级响应切断电源或触发报警。数据如果走网络到云端往返,即使网络状况良好也要几百毫秒,这在工业现场是不可接受的。神经网络跑在STM32本地,推理耗时只是几十到几百个时钟周期的事,决策和处理完全在设备内闭环完成。

第二是隐私。越来越多设备采集的是医疗健康、家庭行为、个人语音这类敏感信息。把原始数据传到云端意味着数据的所有权和控制权都交出去了,很多企业用户和消费者并不买账。在STM32上本地推理,特征向量只留在设备里,云端只需要接收“该不该报警”“运动状态是什么”这类结论,既保护隐私也大幅降低数据泄露风险。

第三是带宽成本。一个多通道传感器节点,每秒可能产生几十KB的原始数据,如果长期不间断上传,流量费和维护成本极其惊人。而在边缘节点上先做完特征提取和分类,再按需上传结果,带宽占用能降低几个数量级。

用生活类比来解释的话,就像你在家里做饭,不需要每个菜都打电话问远处餐厅的大厨怎么做。家里备一套顺手的小工具,常见菜式自己就能搞定,只有遇到真正复杂的菜才去请教专家。STM32端跑神经网络,相当于给设备配了一套“家常菜工具”,大部分判断和决策自己完成,云端AI负责处理真正棘手的问题。

1.2 工具箱整体链路:训练、转换、部署三步走

STM32神经网络开发工具箱的完整流程,我习惯拆成三条链路来看:

  • 数据链路:传感器(ADC、超声波、IMU等)通过DMA、定时器或中断把采集值送入预处理模块,完成滤波、归一化、特征对齐后,变成神经网络的输入张量。
  • 模型链路:PC端用TensorFlow、Keras或PyTorch训练模型,导出为TFLite或ONNX格式,再通过STM32Cube.AI或TensorFlow Lite Micro转换成嵌入式C代码。
  • 运行链路:嵌入式工程里初始化网络句柄,把预处理后的数据填入输入缓冲区,调用推理函数,取输出结果驱动执行器(电机、显示屏、报警器)或上传通信模块(蓝牙、RS485、LoRa)。

这三条链路相互嵌套,任何一个环节出错都会导致最终推理结果不可靠。很多人在模型训练阶段很顺利,一到单片机就跑飞,通常就是忽略了数据链路的实时性处理和模型链路的量化对齐问题。后面我会分别展开讲。

1.3 三个主流方案怎么选:Cube.AI、TensorFlow Lite Micro、CMSIS-NN

不少首次接触STM32 AI开发的工程师,一上来就被工具选择搞懵了。我直接给结论:主流路线就三条,适用场景完全不同。

方案适合场景模型格式硬件加速生态绑定
STM32Cube.AI / X-CUBE-AIST芯片为主、追求极致优化Keras / TFLite / ONNX自动调用CMSIS-NN深度绑定ST生态
TensorFlow Lite Micro(TFLM)跨平台、多厂商MCUTFLite可选CMSIS-NN社区活跃、平台中立
CMSIS-NN底层算子库,通常搭配前两者使用无独立支持ARM Cortex-M优化内核ARM系芯片通用

如果你确定项目就用STM32,那就老老实实用STM32Cube.AI。这套工具对ST自家芯片的优化是最到位的,模型转换后能自动估算RAM、Flash占用和推理周期数,甚至可以生成STM32CubeMX工程,直接省掉手工移植网络代码的时间。

TFLM的优势在于跨平台。如果你的团队同时做STM32、ESP32、瑞萨等多个平台的AI产品,用TFLM可以统一一套部署代码,只用改变量头文件就能适配不同芯片。代价是它对STM32系列的特殊优化不如Cube.AI细致,个别算子的内存复用策略要手调。

CMSIS-NN本质上是ARM提供的神经网络算子加速库,包含卷积、池化、全连接等核心函数的优化实现。Cube.AI和TFLM在Cortex-M内核上都会调用CMSIS-NN来加速,所以它更像是“底层引擎”,而不是独立的部署方案。

2. 动手前的关键设计:模型、内存与数据通道

很多人习惯一上来就训练模型,训完才发现单片机塞不下。这颗雷我在早期项目里踩过不止一次。正确的顺序是先评估资源边界,再设计模型和数据结构。

2.1 先给模型“瘦身”:INT8量化与内存预算

STM32端的神经网络和GPU服务器上的大模型完全是两种物种。服务器模型动辄几百MB参数,而STM32内部Flash一般只有128KB到2MB,RAM更是只有几十KB到1MB。想让神经网络在嵌入式端落地,模型必须做大幅压缩,核心手段就是量化。

浮点模型里每个权重用32位float存储,一个小型卷积网络参数动辄几百KB。把它量化为8位整数后,模型体积直接缩小到原来的四分之一。同时,整数运算在Cortex-M内核上比浮点运算快得多,尤其是M4和M7这类带DSP指令的内核,INT8推理耗时通常能降低一半以上。

我的经验是:第一版不要追求复杂模型。比如做一个基于超声波测距和光敏传感器数据的“接近状态识别”项目,用一个三层的全连接前馈神经网络就够了:输入层2个神经元(距离值、光照值),隐藏层16个神经元,输出层3个神经元(靠近、离开、静止)。整个模型的参数量只有几百个,训练完的TFLite文件不到2KB,在STM32F103上推理耗时不到1毫秒。

内存预算方面要心里有数。Cube.AI生成工程时会明确告诉你网络权重占用多少Flash、中间激活值占用多少RAM。激活层内存可以在网络运行前后复用,所以RAM占用主要看“最大单层激活量”而不是所有层的总和。小模型的激活值往往只有几百字节,留给传感器缓冲区和通信协议栈的空间非常宽裕。

2.2 传感器数据怎么“喂”进网络:ADC、编码与对齐

网络模型是在特定数据分布上训练的,它在MCU上推理时,输入数据的格式和范围必须与训练时保持一致。这里最常见翻车点有三个:ADC采集不稳定、数据编码不一致、时序对齐错乱。

ADC多通道采集时,建议用DMA循环模式配合规则组扫描,一次性把多个通道的数据搬进内存缓冲区,而不是在主循环里频繁切换通道、排队等待转换。规则组的好处是硬件自动按顺序完成多通道采样,DMA再把结果连续写入内存,CPU几乎零开销。每轮采样结束后做一次中值滤波或滑动平均,把传感器噪声压下去,再进入归一化环节。

归一化是另一个必须严格对齐的点。训练脚本里如果用了“减均值、除标准差”的预处理,MCU端推理前必须用完全相同的方式处理数据,否则你喂给网络的数值分布跟训练时完全不同,输出的概率自然是一堆垃圾。我建议把归一化系数(均值、缩放因子)直接以常量的方式烧录在固件里,避免运行时去Flash读配置。

编码对齐这个问题,很多老手都会阴沟翻船。嵌入式工程师经常要处理GBK转UTF8这类字符编码转换,而在AI推理场景里,“编码”的含义更宽泛:传感器原始数据、通信协议里的JSON字符串、SD卡里的模型配置文件,最终都必须转换成网络输入张量规定的数据类型和字节序。比如模型输入是float32,你直接从串口缓存里按uint8数组喂进去,轻则数值全错,重则触发HardFault。项目里我养成了一个习惯:每个传感器数据源接入网络前,都写一个明确的“编码转换函数”,把原始字节流转成Tensor,并做范围校验。

时序对齐在多传感器融合场景尤其重要。超声波模块从发出脉冲到收到回波,本身就有几十毫秒的测量延迟;ADC采样是突发完成的;IMU数据可能是定时器中断驱动的。如果直接把不同时刻采样到的数据拼成一个特征向量喂给网络,相当于把不同时间点的状态强行捏在一起,推理结果根本不可信。我在这类项目里用DWT(数据观察点与跟踪单元)的周期计数器打时间戳,每次采样都记录当前时刻,只有时间差在允许范围内的数据才组合成一次输入向量。

2.3 别小看外设联动:按键、PWM、DWT与执行器

AI推理只是整个嵌入式系统中的一个环节,它要和周围外设协同工作才有实际价值。这里我用自己的项目举例:一个带AI能力的门禁检测节点,涉及的外设包括非阻塞按键扫描、PWM模拟输出、DWT性能测量、RS485伺服电机控制和蓝牙通信。

非阻塞按键扫描是一个很容易被忽视的“基本功”。边缘AI设备经常需要人机交互,比如通过按键切换工作模式、触发一次推理。如果按键扫描写成阻塞式延时消抖,整个系统的实时性就完蛋了。我习惯用状态机加定时器扫描的方式:每5毫秒扫描一次GPIO电平,配合10到20毫秒的去抖窗口,既不影响主循环,也不会漏掉按键事件。

PWM在AI设备里通常扮演执行器的角色,比如根据推理结果输出不同占空比的PWM,控制LED亮度或者蜂鸣器音量。做“PWM模拟测试”时要注意频率选择,别和传感器采样频率产生拍频干扰。我一般把PWM频率设在20kHz以上,超出人耳听力和多数传感器采样带宽,减少干扰风险。

DWT是Cortex-M内核提供的一个调试外设,它里面有个免费的周期计数器,可以高精度测量代码执行时间。想确认某个推理函数到底花了多少毫秒,不用外接逻辑分析仪,直接在代码里记录DWT->CYCCNT的前后差值即可。这块我放到后面实操部分给出具体代码。

最后说RS485伺服电机控制。AI判断出动作意图后,最终要落到执行机构上。RS485是工业现场最常见的总线,差分信号抗干扰能力强,传输距离远。用STM32的UART加一个RS485收发器芯片,控制方向引脚即可实现半双工通信。关键是方向切换的时序:发送数据前先把方向引脚拉高,等待至少一个字节的传输时间后再发数据,发送完成后延时几十微秒再拉低方向引脚,否则最后一个字节会被截断。

3. 实操:从一个接近状态识别Demo看完整落地流程

理论讲再多,不如完整跑一遍流程。下面这个项目案例是我用来给团队新人做培训的“标准作业”——基于STM32F407、超声波传感器、光敏传感器和全连接神经网络的接近状态识别。

3.1 数据采集与模型训练:Keras

这个项目要解决的需求很简单:设备放在桌面上,当有物体靠近时,设备判断“有人靠近”并点亮一盏灯;物体离开后熄灭;如果物体静止不动超过一定时间,则进入休眠。逻辑上三个状态:靠近、离开、静止。

我选两个物理特征作为输入:超声波测得的距离值(厘米),光敏电阻经ADC采集到的电压值(伏特)。这两个特征组合起来,在大多数场景下足以区分“手掌靠近遮挡光线”和“人离开环境变暗”之间的差异。

训练代码在PC上用Keras完成,模型结构如下:

import numpy as np import tensorflow as tf from tensorflow import keras # 假设 X_train 形状为 (样本数, 2),y_train 为 (样本数, 3) 的 one-hot 标签 model = keras.Sequential([ keras.layers.Dense(16, activation='relu', input_shape=(2,)), keras.layers.Dense(8, activation='relu'), keras.layers.Dense(3, activation='softmax') ]) model.compile( optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy'] ) model.fit(X_train, y_train, epochs=50, batch_size=8, validation_split=0.2) # 保存为 TFLite 格式 converter = tf.lite.TFLiteConverter.from_keras_model(model) converter.optimizations = [tf.lite.Optimize.DEFAULT] tflite_model = converter.convert() with open('approach_model.tflite', 'wb') as f: f.write(tflite_model)

训练数据就来自STM32板子本身,通过串口把距离和电压数据以CSV格式发到电脑,人手工操作并标注状态。这样训练出来的模型在部署回MCU后,数据分布天然一致,省去大量适配工作。

嵌入式的模型没必要搞复杂结构,先用一个几百参数的小模型把链路跑通,效果不够再加层数。全连接神经网络在MCU上友好度极高,部署时几乎不会遇到算子支持问题。

3.2 模型转换:STM32Cube.AI生成C代码

训练好的TFLite文件要通过STM32Cube.AI转成C代码。直接在STM32CubeMX工具链里操作,流程很简单:

打开CubeMX,选中你的芯片型号(我选的是STM32F407VET6),在中间栏的“Additional Software”选项里找到“X-CUBE-AI”,点击添加。然后进入配置页面,选择“Network model”,加载approach_model.tflite。

工具会自动做几件事:校验模型结构和算子兼容性、分析RAM和Flash占用、生成模型部署的C文件。关键的输出文件有三个:network.h(网络API声明)、network.c(推理主逻辑)、network_data.c(权重和偏置数组)。

Cube.AI新版生成的API大致如下:

#include "network.h" // 创建网络实例 ai_handle network; ai_network_create(&network); // 内部会自动分配和管理内存 // 准备输入输出缓冲区 AI_ALIGNED(4) ai_float input_data[2]; AI_ALIGNED(4) ai_float output_data[3]; // 推理 ai_network_input_init(&network, input_data, NULL); ai_network_output_init(&network, output_data, NULL); ai_network_run(&network, input_data, output_data);

在Cube.AI的分析界面里,还会显示每个算子的周期估算和激活内存消耗。我的这个模型转换后权重占1.5KB Flash,激活RAM约200字节,推理周期数在F407上大约是1.2万周期,按168MHz主频算只有70多微秒,几乎可以忽略不计。

生成C代码后,直接在CubeMX里勾选“Generate Code”,把网络集成进初始化的HAL工程,后面就是我们的主场了。

3.3 嵌入式工程整合:FreeRTOS、HAL库与外设初始化

模型只是工具箱中的一环,真正让设备跑起来的是嵌入式工程的整合。我在这个Demo里引入了FreeRTOS,把任务划分成以下四个:

  • SensorTask:优先级3,每20ms唤醒一次,触发超声波测距并读取ADC光敏值,预处理后发送到队列。
  • InferenceTask:优先级2,阻塞等待队列中的数据,填充网络输入,执行推理,把分类结果发给控制任务。
  • ControlTask:优先级1,接收推理结果,控制PWM占空比点亮LED,或通过RS485发送指令驱动伺服电机。
  • CommTask:优先级1,处理UART蓝牙接收的命令,比如切换模型阈值、进入调试模式、打印推理日志。

工程里各外设的初始化按照CubeMX勾选生成即可。几个关键配对的细节我展开说一下:超声波模块的触发引脚用GPIO输出高电平脉冲,测量回波用定时器输入捕获;ADC1开启两个通道(PA0和PA1)用规则组配合DMA循环传输;PWM用TIM4的通道1,频率设20kHz。

连接推理任务的队列定义非常简单:

typedef struct { float distance; float voltage; uint32_t timestamp; } sensor_packet_t; QueueHandle_t sensor_queue; // 在启动任务前创建 sensor_queue = xQueueCreate(4, sizeof(sensor_packet_t));

SensorTask里把采集值归一化后发送:

sensor_packet_t packet; packet.distance = (raw_distance - 20.0f) / 180.0f; // 假设量程20-200cm packet.voltage = (adc_value * 3.3f / 4095.0f) / 3.3f; packet.timestamp = DWT->CYCCNT; xQueueSend(sensor_queue, &packet, 0);

InferenceTask拿队列数据推理:

sensor_packet_t packet; if (xQueueReceive(sensor_queue, &packet, portMAX_DELAY) == pdTRUE) { input_data[0] = packet.distance; input_data[1] = packet.voltage; ai_network_run(&network, input_data, output_data); // 找到最大概率类别,发送控制指令 }

这个架构的好处是任务之间完全解耦。传感器采集变慢不会阻塞推理,推理变慢不会阻塞控制输出,每个任务都能独立调整优先级。

3.4 推理性能与功耗调优:CMSIS-NN和低功耗

虽然小模型推理本身很快,但在真实产品里我们还要考虑性能优化和功耗管理两个维度。

编译设置上,工程必须开-O2优化,否则推理时间会慢上两三倍。STM32F407没有缓存,如果是F7或H7系列,记得开启ICache和DCache,并把网络权重和输入输出缓冲区放在紧密耦合内存或D1 AXI SRAM里,能显著减少访问延迟。

CMSIS-NN加速不只在Cube.AI内部生效,如果自己集成TFLM,也可以在编译时启用ARM_MATH_DSP和ARM_MATH_CM4等宏定义,让卷基层自动调用优化过的汇编内核。全连接层的时间主要消耗在矩阵乘上,CMSIS-NN提供了arm_fully_connected_s8这类函数,这类底层函数对INT8数据做了寄存器级别的优化,速度相当可观。

功耗优化是边缘AI设备的必修课。我的做法是:推理完成后立即把设备切到STOP模式,用低功耗定时器或RTC闹钟在下一个采样周期唤醒;ADC采样改成定时器触发,而不是主循环轮询;蓝牙模块如果不是在通信状态,就让它进入休眠,只在必要时唤醒。FreeRTOS里开启configUSE_TICKLESS_IDLE,在空闲任务里自动进入低功耗模式。这样一套下来,同样的传感器节点电池续航能提升好几倍。

4. 常见问题与排查技巧实录

做嵌入式AI快两年,遇到的坑比头发还多。我把高频问题整理成一个速查表,按现象、原因、解决思路三个维度给出来,照着排查能省下大量瞎试的时间。

4.1 模型怎么都编译不过去

现象:Cube.AI转换时报错“unsupported operator”或生成工程后编译报错。

绝大部分原因是模型里用了工具不支持的算子。比如自定义Lambda层、很新的激活函数、非标准的上采样实现,在TFLite转换和Cube.AI的解析阶段都会出问题。解决思路是回到Keras里,把自定义层替换成标准层组合,或者干脆简化模型结构。实验证明,Dense、Conv2D、ReLU、Softmax、AveragePooling这几个算子,是Cube.AI兼容性最好的基础构件。真碰上新算子,可以切到TFLM,它的算子覆盖范围明显更广。

编译期间报undefined symbol或链接错误,先查启动文件里是否包含浮点相关的初始化代码。M7内核用FPU必须开启__FPU_PRESENT宏并调用SystemInit里的FPU使能代码,否则一旦网络里有浮点运算就会死机。

4.2 推理结果总是“漂”或NaN

现象:部署到MCU后,推理输出的概率值全是0或NaN,偶尔是明显错误分类——明明手靠近了却输出“离开”。

排查顺序第一步看输入预处理。检查MCU端的归一化系数和训练脚本是否完全一致,这是九成意外的来源。第二步看数据类型,ai_float输入是4字节浮点,如果给的是uint8数据,必须显式类型转换并缩放。第三步看栈空间,FreeRTOS任务栈如果设得过小,网络推理时的局部变量一旦超出栈顶,就会破坏相邻内存,导致网络权重被改写。我用Cube.AI跑一个稍大的网络时,任务栈通常要给4KB以上才稳妥。

超声波测距结果本身受环境温度、声波反射面影响很大。实测发现,同一个距离多次测量可能偏差好几厘米。解决办法是对连续三次测量取中值,再进入归一化。ADC光敏值相对稳定,但也建议做一次滑动平均。

4.3 内存不够、Flash爆炸

现象:编译通过,但下载时报Flash容量不足;或者运行到一半卡死,看门狗复位。

这是嵌入式AI绕不开的话题。先说Flash,STM32F103C8T6是64KB Flash,跑一个几十KB的模型加全套HAL库确实勉强。选型阶段就要预留空间,我的项目大多用F407(512KB Flash)或H743(2MB Flash),基本不用太担心容量。如果已经定了小容量芯片,就从模型下手:减小隐藏层神经元数量、用INT8量化、去掉多余特征输入。权重聚类(Weight Clustering)也能进一步压缩,多少个聚类中心就能把权重索引压缩到对应位数。

RAM方面比较复杂,除了网络自身的激活缓冲区,还有传感器队列、DMA缓冲、通信协议栈、RTOS任务栈都在抢内存。可视化看板里把Cube.AI显示的网络RAM占用和链接器报告里的RAM用量加起来,就差不多是真实需求了。内存不够时,优先把大的静态缓冲区搬到外部SRAM或SDRAM,这就要手改LD文件。STM32的链接脚本按RAM、FLASH、CCM等段划分,新增大缓冲区时在.ld文件里增加一个SDRAM段,并把数组显式指定到该段。这一步如果觉得麻烦,更省事的方案是换H7系列,它内部有1MB大RAM,很多小模型直接全放内部就够了。

4.4 外设干扰与通信乱码

现象:ADC通道切换后第一笔数据明显偏大;485方向的伺服电机偶尔丢指令;蓝牙打印日志中文全乱。

ADC多通道切换后,采样电容还没来得及稳定,转换结果会带毛刺。解决办法是把DMA缓冲区第一个样本丢弃,或者将采样周期调大到15个时钟周期以上。按键扫描用状态机加10ms去抖后,误触概率会降很多,但还是建议在最终触发前增加一个“确认按下超过50ms”的逻辑,避免人体静电或电磁干扰造成的假信号。

RS485通信乱码的根源大多数在方向引脚切换时序,我之前专门聊过,这里再提一次:发送前拉高方向引脚后,要等待至少一个字节的发送时间,用HAL_UART_Transmit的阻塞模式或延时函数都能实现。实际测试中,串口波特率越高,对方向切换时序越敏感。9600波特率时,延时1ms绰绰有余;115200波特率时,延时也要在几微秒到几十微秒之间调整,最好用逻辑分析仪看波形。

蓝牙乱码,尤其是调试日志中文乱码,这就要用到字符编码的知识了。STM32串口工具和编辑器之间的编码不一致,最常见就是UTF-8数据在GBK环境下显示成一团乱码。字符串处理上,直接把所有日志文件统一用UTF-8编码,串口工具同样选择UTF-8解码,别再折腾GBK转UTF8的代码。如果确实要做转换,也要注意中英混排时字节长度变化的问题,转换后的缓冲区分明要按最大上限设置,否则极容易写越界。

4.5 速度不够快:DWT定位瓶颈

现象:推理结果正确,但系统整体响应变慢,从传感器采完数据到执行器动作延迟明显。

不要急着优化代码,先用DWT周期计数器测量每一段的耗时。初始化时使能DWT:

CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk; DWT->CYCCNT = 0; DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk;

测试函数耗时:

uint32_t t0 = DWT->CYCCNT; ai_network_run(&network, input_data, output_data); uint32_t t1 = DWT->CYCCNT; uint32_t cycles = t1 - t0; float time_ms = (float)cycles / (float)HAL_RCC_GetHCLKFreq() * 1000.0f;

实测我的三段切换模型,F407主频168MHz时,一次推理大约为0.1毫秒,瓶颈不在推理本身,而在超声波测距的等待周期。超声波模块的应答时间本身就要几十毫秒,无法规避,但可以让它在后台用定时器中断测距,而不是在主循环里阻塞等待回波。整体延迟从原来的150毫秒降到50毫秒,用户体验明显改善。

收尾:先把链路跑通,再追求复杂模型

最后分享一点个人体会。我最初接触STM32神经网络开发时,也想着一步到位跑一个图像分类的卷积网络,结果在算子兼容、内存分配、数据预处理这些环节被反复摩擦,折腾了一个月毫无进展。后来换了个思路,先拿最简单的全连接模型把采集、训练、转换、部署、调试这条链路完整跑通,就像先焊好电路板再做功能调试一样。链路打通之后,换CNN、引FreeRTOS、加多传感器融合、甚至搞人脸识别图像经过神经网络输出高维特征向量这类视觉任务,都只是往这套框架里填新模型而已。所以给想做嵌入式AI的朋友一个建议:第一版永远不要贪大,用最小可用的模型跑通全链路,后面的扩展才是水到渠成的事。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询