> 技术文档 > STM32F407单片机部署朴素贝叶斯算法实现运动状态识别_动物识别代码 stm32

STM32F407单片机部署朴素贝叶斯算法实现运动状态识别_动物识别代码 stm32


1.简单介绍

博主最近在做一个科研项目——利用stm32f407制作成智能项圈识别牦牛姿态。

工作学习之余写下第一篇文章记录这个项目过程中的点滴(人菜勿喷)。

常见的识别牦牛姿态的方式一般都是:stm32+运动传感器采集数据——发送给上位机进行训练——在上位机进行识别。

显然这不如直接将机器学习算法部署在单片机,直接能够识别出结果来的高效,所以博主收集了很多资料和相关博客来进行学习,以下是我个人的一些简单见解,欢迎批评指正。

2.MPU6050传感器

本文针对应用场景只做一些细节的介绍,详细的传感器介绍参考:

STM32外设系列—MPU6050角度传感器-CSDN博客

该传感器的驱动以及stm32的配置参考连接:STM32CubeMX mpu6050驱动_mpu6050驱动程序-CSDN博客

MPU6050是一种六轴的加速度传感器,支持I2C通信和SPI通信,这里我是用的是I2C通信,

常见的量程有: ±2g、±4g、±8g、±16g,采样频率可以自己设置,而且带有DLPF数字低通滤波器。

像牦牛的大型动物一般动作幅度较少,一般来说2g的量程能够满足针对动物的姿态识别,在keil中设置HAL_Delay的时间为1000,综合发送时间和牦牛的特性,采用200Hz的采样频率,在驱动中,将0X19对应的Data设置为0x04,定义一个地址0x1A,利用HAL_I2C_Mem_Write写入数据0x04即可设置DLPF的频率。

3.机器学习、深度学习算法部署

先介绍一下数据来源,由于暂时没有制作成成品,只能模拟牛只的状态,这里先分为移动和静止两种状态(后续等采集到数据再增加)。

目前基于STM32的算法部署,一般有两种方式。

第一种方式是借用STM32CUBEMX中的CUBE-AI插件,该插件可以分析模型的结构,压缩模型以达到能够较低的内存,还可以通过随机数或者csv格式的数据集进行验证(可以在上位机或目标板进行),博主使用了公开的人体姿态数据进行部署验证,在板子上准确率能达到98.2%。

参考另一篇相关部署博客:

CUBEAI详细使用教程二(STM32运行神经网络)---人体活动检测(MPU6050、CNN2D)_stm32 cnn-CSDN博客

人体姿态的数据训练模型是一个六层的CNN,但是在自己训练部署的过程中,经过数天的尝试,查阅STM32官方给出的实例代码等,最终这种方式以失败告知。

第二种办法,就是在上位机进行训练,利用机器学习算法库,先训练模型,将参数以数组的形式保存(这里还需要做一些处理,将浮点数转换为int型,减少计算量),最后利用对应算法的C语言代码,将参数导入进去即可实现部署。这里选择朴素贝叶斯算法的原因在于:代码轻量,针对姿态分类效果好(数据之间的独立性强),并且能够以C代码简单实现。

import pandas as pdfrom sklearn.model_selection import train_test_splitfrom sklearn.naive_bayes import GaussianNBimport numpy as npfrom sklearn.decomposition import PCA# 加载数据集df = pd.read_csv(“数据集路径”)correlation_matrix = df[[\'AX\', \'AY\', \'AZ\']].corr()print(correlation_matrix)# 提取特征变量和目标变量X = df[[\'AX\', \'AY\', \'AZ\']]y = df[\'Label\']pca = PCA(n_components=2)X_pca = pca.fit_transform(X)# 划分训练集和测试集X_train, X_test, y_train, y_test = train_test_split( X, y, test_size=0.2, random_state=42)# 构建高斯朴素贝叶斯模型gnb = GaussianNB()# 拟合模型gnb.fit(X_train, y_train)# 手动计算每个类别的方差classes = np.unique(y_train)manual_sigma = []for c in classes: # 选择属于当前类别的样本 X_c = X_train[y_train == c] # 计算每个特征的方差 (axis=0 表示按列计算) variance = X_c.var(axis=0) manual_sigma.append(variance)manual_sigma = np.array(manual_sigma)print(\"手动计算的方差:\", manual_sigma)theta = gnb.theta_class_prior = gnb.class_prior_theta_quantized = (theta * 1000).astype(np.int16)#sigma值可能较小,前面的因子需要比较大,不然会输出0sigma_quantized = (manual_sigma * 100000).astype(np.int16)class_prior_quantized = (class_prior * 1000).astype(np.int16)print(\"theta_quantized:\", theta_quantized)print(\"sigma_quantized:\", sigma_quantized)print(\"class_prior_quantized:\", class_prior_quantized)def save_to_c_array(data, variable_name, filename): with open(filename, \'a\') as f: f.write(f\"const int16_t {variable_name}[] = {{\\n\") for i, row in enumerate(data): if isinstance(row, (list, np.ndarray)): f.write(\" \") for j, val in enumerate(row):  f.write(f\"{val}\")  if j < len(row) - 1: f.write(\", \") f.write(\",\\n\") else: f.write(f\" {row},\\n\") f.write(\"};\\n\")# 保存参数到 C 文件save_to_c_array(theta_quantized, \"theta\", \"model_params.c\")save_to_c_array(sigma_quantized, \"sigma\", \"model_params.c\")save_to_c_array(class_prior_quantized, \"class_prior\", \"model_params.c\")

这里附上博主训练的代码,准确率约为88.6%

int16_t gaussian_nb_inference(int16_t features[], int num_classes, int num_features) { int16_t max_score = -32767; // 初始化最大得分 int16_t predicted_class = 0; for (int c = 0; c < num_classes; c++) { int16_t score = class_prior[c]; for (int f = 0; f  max_score) { max_score = score; predicted_class = c; } } return predicted_class;}

这是C代码板的函数实现。

总结一下:

官方的CUBE-AI插件更适合于较大的模型部署,而且需要自己写代码能力较强,实现数据的格式统一并实现输入,第二种方法适合简单的传统机器学习算法(根据stm32的算力和实现的目的进行模型的选择)

4.实验效果:

通过Keil将代码导入并写成函数实现的形式,声明一个数组将mpu6050获取到的传感器存入,进行姿态的识别:

        MPU6050_Read_All(&hi2c1, &MPU6050);        features[0] = MPU6050.Ax;        features[1] = MPU6050.Ay;        features[2] = MPU6050.Az;        printf(\"%2f,%2f,%2f\\n\",MPU6050.Ax,MPU6050.Ay,MPU6050.Az);        if(gaussian_nb_inference(&features[3], 2, 3)==0)        printf(\"目标静止\\n\");        else        printf(\"目标移动\\n\");

实验结果通过串口打印保存本地为txt文件,如下展示:STM32F407单片机部署朴素贝叶斯算法实现运动状态识别_动物识别代码 stm32

将开发板放在桌子上静止,放置一段时间,记录结果有1864条,其中预测正确的占(识别为静止):1614条,准确率约为86.6%

5.总结与展望

由于应用在牛只身上的数据来源都不用说是基本,那是根本没有可以使用的公开数据,只能通过简单的模拟,先进行软件实现,并且用于动物的传感器很少,基本只能通过迁移的方式进行实现,这其中不免存在了很多客观因素,后期去实地考察做实验,需要分更多的姿态类别。

在我看来以后将算法部署在单片机和嵌入式设备上是一个很好的方向,现在的大模型热度较高,AI技术发展的越来越快,理论先于应用,但终归需要应用,那么这时候就需要相关的技能了。

之后博主会结合图像进行多源数据融合来判断姿态,日后会更新相关的学习记录,本篇文章提供了一些部署算法在stm32上的思路,欢迎大家批评指导!