MAX78000FTHR-边缘AI
简介
MAX78000FTHR扩展板,方便MAX78000FTHR采集图像。
简介:MAX78000FTHR扩展板,方便MAX78000FTHR采集图像。开源协议
:GPL 3.0
(未经作者授权,禁止转载)描述
11月17日更新内容- MAX78000FTHR的边缘AI应用
在之前的内容中,我使用MAX78000FTHR开发板+本项目中的扩展板实现了一个简易照相机的功能,能够拍摄图片并保存至SD卡中。
在本次更新中,我将使用MAX78000FTHR开发板+本项目中的扩展板(下称MAX78000FTHR扩展)实现三种汽车Logo的分类识别,并对实现过程进行说明。
三种汽车Logo分类识别的效果展示
三种汽车品牌分别是五菱、大众和马自达,下面三张图片分别是这三种品牌Logo的识别现象
五菱车标识别
大众车标识别
马自达车标识别
训练实现过程
模型的训练流程分为以下步骤:
模型训练->模型量化->模型评估->模型转换
下面分这四步进行说明
1、三分类训练
打开训练工程中的train.py文件,该训练文件需要输入参数,下面以猫狗识别为例进行说明
找到scripts/train_catsdogs.sh文件,将文件内的参数内容复制下来
--epochs 250 --optimizer Adam --lr 0.001 --wd 0 --deterministic --compress policies/schedule-catsdogs.yaml --model ai85cdnet --dataset vehicle_logo --confusion --param-hist --embedding --device MAX78000
将其复制到train.py的运行参数中去,如下图所示
然后点击运行train.py文件,它会自动加载我们刚输入的参数,并开始训练
训练完成后,会在logs文件夹内生成下一步需要的量化需要的文件,如下图所示
2、量化
将上一步生成的best.pth.tar文件复制到量化工程下的trained文件夹下
打开quantize.py文件,并为该文件配置运行参数,如下图所示
运行参数为:trained/best.pth.tar trained/best-q.pth.tar --device MAX78000 -v
配置完成后运行quantize.py文件,运行完成后在trained文件中生成的best-q.pth.tar即为量化后的模型文件
3、模型评估
在得到量化后的模型文件之后,我们切换回训练工程进行模型的评估
模型评估使用的文件和模型训练使用的是同一个文件,只不过是运行参数不同,这里我们对train.py的运行参数进行修改即可进行模型的评估
评估输入参数如下:
--model ai85cdnet --dataset vehicle_logo --confusion --evaluate --exp-load-weights-from ../ai8x-synthesis/trained/best-q.pth.tar -8 --device MAX78000
运行train.py文件,运行结果如下:
效果还可以
4、模型转换
模型转换是将训练好的的模型转换为C文件,以便于我们方便的部署模型
再次切换到量化工程中,这次我们需要使用到ai8xize.py文件,同样,我们需要给该文件配置运行参数来完成模型的转换,该文件的运行参数如下:
--verbose --test-dir demos --prefix ai85-vehicle_logo_3 --checkpoint-file trained/best-q.pth.tar --config-file networks/vehicle_logo-hwc.yaml --fifo --device MAX78000 --softmax
运行后会在量化工程下的demos文件夹中生成我们需要的开发板工程文件,如下图所示:
该工程文件可以使用VScode打开并编辑
模型部署
在上一步中,我实现了模型的训练并最终得到了芯片的工程文件,但是这里面生成的仅仅是一个样例,向模型输入的数据是由训练工程生成的一个样例,无法将摄像头采集到的图像发送给模型,所以这一步我们将模型部署到可用的工程中
1、模型迁移
首先打开由模型转化得到的工程文件夹,复制其中的cnn.c/h、softmax.c和weights.h文件
然后将其粘贴到cats-dogs_demo例程(该例程能够将摄像头采集到的图像发送给模型)中去,当粘贴时会弹出下图中窗口,选择“替换目标中的文件”这一选项
这样我们就将训练好的模型迁移到原猫狗分类的工程中了
2、程序修改
首先修改屏幕初始化函数,以适应扩展板的屏幕,将下面代码放到main函数的屏幕初始化位置,如下图所示
reset_ctrl.port = MXC_GPIO2;
reset_ctrl.mask = MXC_GPIO_PIN_3;
reset_ctrl.pad = MXC_GPIO_PAD_PULL_UP;
reset_ctrl.func = MXC_GPIO_FUNC_IN;
MXC_GPIO_Config(&reset_ctrl);
/* Setup output pin. */
bl_ctrl.port = MXC_GPIO2;
bl_ctrl.mask = MXC_GPIO_PIN_4;
bl_ctrl.pad = MXC_GPIO_PAD_NONE;
bl_ctrl.func = MXC_GPIO_FUNC_OUT;
MXC_GPIO_Config(&bl_ctrl);
/* Initialize TFT display */
MXC_TFT_Init(MXC_SPI0, 1, &reset_ctrl, &bl_ctrl);
MXC_TFT_SetRotation(ROTATE_90);
然后修改程序内的分类定义,即下图中框选内容
该定义用以区分分类的内容,将该数组改为下图所示内容,修改后如下图所示
添加扩展板按键代码,如下所示
mxc_gpio_cfg_t gpio_set;
gpio_set.port = MXC_GPIO0;
gpio_set.mask = MXC_GPIO_PIN_19;
gpio_set.pad = MXC_GPIO_PAD_PULL_UP;
gpio_set.func = MXC_GPIO_FUNC_IN;
MXC_GPIO_Config(&gpio_set);
有了这个初始化之后,我们可以通过MXC_GPIO_InGet()函数获取引脚的高低电平,从而得知按键有没有按下,由于按键按下时,会将引脚电平拉低,所以使用MXC_GPIO_InGet(gpio_set.port, gpio_set.mask) != 0替换掉工程中的所有!PB_Get(0)
代码
然后将摄像头图像刷新函数部分(注意该函数是在main函数中)修改为如下函数
while (MXC_GPIO_InGet(gpio_set.port, gpio_set.mask) != 0)
{
capture_process_camera();
}
位置如下图所示
之所以这样修改是因为源程序中无法时刻浏览到视像头拍摄的内容,只能在拍摄的时候观察到拍摄的那张图片,这样不利于拍摄,而这样修改可以时刻观察到摄像头的画面,从而能够捕捉到自己满意的画面
但这样需要在下一次按键判断后面加上一个延时函数,以防止误触的发生,如下图所示
但由于我的扩展板上屏幕与开发板的摆放位置问题,会导致摄像头画面的角度与人观看屏幕的角度呈现90度垂直,所以我们需要再修改一下摄像头图像显示的函数
我们将capture_process_camera函数内的 MXC_TFT_ShowImageCameraRGB565(TFT_X_START, TFT_Y_START + row, data565, w, 1);
换为MXC_TFT_ShowImageCameraRGB565(TFT_X_START + h - row, TFT_Y_START, data565, 1, h);
即可将摄像头画面旋转过来
这么做的原理的话,基本上就是我们获取到的摄像头数据是一行一行的进行显示,原函数的显示效果是向左旋转了90度,那么这样拍摄到的图像的第一行的数据就应该是正常图像最右侧一列的数据,所以我们获取到图像数据后不按照原先一行一行的进行显示,而是一列一列的进行显示,同时从最右侧开始,这处理过后的图像在我们看来就是正常的效果了
该行代码的位置如下图所示
三分类识别代码见附件 WuLing-VW-Mazda.7z
以上就是程序修改的全部内容,效果展示见三种汽车Logo分类识别的效果展示部分
量化工程太大,放到网盘中了,后面会在评论区中发出网盘链接
以上就是本次更新MAX78000FTHR的边缘AI应用的全部内容
—————————————手动分割线————————————
11月17日前内容
项目分析
本项目为MAX78000FTHR扩展板,能够实现拍摄并存储图像到SD卡
本项目能够方便地使用MAX78000FTHR采集图像,获取板载摄像头拍摄到的实际画面,从而大大提高数据集的获取效率。使用这种图像进行MAX78000的模型训练,能够提高摄像头识别的精准度。
下图为硬件结构图
下图为软件结构图
原理图设计说明
本项目使用TP5400进行电源管理
在外部电源供电时,能够给3.7V锂电池充电并输出5V电压
外部电源未供电时,能够将3.7V电压升压至5V
从而实现充电升压二合一
屏幕显示部分使用的一块2.4寸屏幕,驱动为ILI9341,可以直接使用MAX78000官方提供的屏幕驱动,硬件连接如下
按键操作部分,因为MAX78000FTHR上的按键太过迷你,不方便操作,所以在本扩展板上重新连接了按键以实现按键操作,原理图如下所示
MAX78000FTHR与其他部分连接如下图所示
PCB设计说明
在PCD设计部分,本项目使用了彩色丝印,非常好看,3D预览图如下所示
实物图如下所示
注:如不想使用彩色丝印打印PCB板,直接将PCB中的彩色丝印图删去即可,不会对电路运行产生影响,或直接使用附件中的普通丝印Gerber文件进行打板
实物展示说明
正面图
反面图
11月10日bug更新
在摄像头拍摄程序中有一个bug,就是在按下拍摄按键之后,屏幕上会显示按下按键时的摄像头拍摄画面,但按下保存按键时,保存的却是按下保存按键时的摄像头拍摄画面,这是有问题的
解决方案:
将按下拍摄按键时的画面在按下按键时就保存下来,当按下保存按键时就存到SD卡中,按下丢弃按键时就删除,关键代码部分如下所示
#ifdef SD
// Capture images on the basis of SD card opening
cnn_img_data_t img_data = stream_img(g_app_settings.imgres_w, g_app_settings.imgres_h,
g_app_settings.pixel_format,
g_app_settings.dma_channel);
memset(buff, 32, TFT_BUFF_SIZE);
TFT_Print(buff, 37, TFT_Y_START + IMAGE_SIZE_Y + 5, font_2,
snprintf(buff, sizeof(buff), "PRESS UP to Save Image"));
TFT_Print(buff, 0, TFT_Y_START + IMAGE_SIZE_Y + 35, font_2,
snprintf(buff, sizeof(buff), " PRESS DOWN to Discard Image"));
// MXC_Delay(1000000);
while (1)
{
// SD card is enabled. save image
if (Key_get() == key_up)
{
save_stream_sd(img_data, NULL);
area_t area;
area.x = 0;
area.y = 180;
area.w = 320;
area.h = 60;
MXC_TFT_ClearArea(&area, BLACK);
memset(buff, 32, TFT_BUFF_SIZE);
TFT_Print(buff, 0, TFT_Y_START + IMAGE_SIZE_Y + 20, font_2,
snprintf(buff, sizeof(buff), "Saved Image to %s Successed", path));
break;
}
// discard image
if (Key_get() == key_down)
{
area_t area;
area.x = 0;
area.y = 180;
area.w = 320;
area.h = 60;
MXC_TFT_ClearArea(&area, BLACK);
memset(buff, 32, TFT_BUFF_SIZE);
TFT_Print(buff, 30, TFT_Y_START + IMAGE_SIZE_Y + 20, font_2,
snprintf(buff, sizeof(buff), "Discard Image Successfully"));
break;
}
}
MXC_Delay(200000);
#endif
附件中的工程已更新
评论