基于 MAX78000 的数字检测平台设计
基于 MAX78000 平台的数字检测平台设计,能够捕获图片并使用对象检测深度学习算法对图片中的数字进行识别,通过上位机控制MCU行为并展示图片,上位机支持保存图片。
标签
嵌入式系统
MAX78000
对象检测
2x3j
更新2023-01-31
中国海洋大学
1204
1. 完成的功能及达到的性能
本项目在嵌入式端实现了捕获图片、运行推理两项功能,并支持通过串口调用相关函数。为方便运行调试,项目最终的成果通过上位机展示,接下来将详细介绍软硬件交互的具体细节:

FhWKu3CAG-JzALIEAWmXBqe602w4

1.1 连接MCU
按下按钮,将在上位机打开对应的串口,并与MCU建立同步关系,已被后续执行。串口号可通过输入框进行更新,未连接时其他功能不可使用。
 
1.2 图片循环预览
按下按钮,上位机将以固定频率向MCU发送图片捕获指令,接收来自MCU的图片并将其显示在左侧。该功能可用于调整摄像头位置,方便后续的图像识别。
 
MCU端捕获单张图片的耗时在50ms上下浮动,串口发送单张图片的耗时约为250ms。为确保显示的稳定性,目前上位机捕获指令的发送间隔被设置为500ms。
 
1.3 捕获并识别当前图像
按下按钮,上位机将发送推理指令到MCU,MCU推理运行结束后,将推理结果显示在右侧文本框,并将带有标注的图片进行展示。
 
MCU端执行tiny-ssd网络,推理时间约为15ms,能够以较高的准确率识别清晰图片中的数字。
 
1.4 保存图片到上位机
按下按钮,上位机会将当前捕获的图片复制到 saved_image 目录下,并以时间戳进行命名。
 
该功能可使用 Maxim78000 自带的摄像头捕获低分辨率下的图片数据,以制作面向嵌入式端的图片数据集。
 
1.5 功能总结
本项目通过软硬件协调工作,实现了制作捕获图像、制作数据集、执行嵌入式端神经网络推理三项主要功能。其中嵌入式端神经网络可替换为其他视觉网络,以完成在没有屏幕情况下的功能调试。
 
2. 设计思路

Fi-J44xxyhfRjMj9bucPbabbzVy7

按照系统设计框图,有以下功能需要实现:
  • MCU与上位机通信,上位机发送控制命令,MCU发送图片数据和识别结果
  • MCU调用摄像头捕获图片数据
  • MCU调用神经网络进行数字检测
  • 上位机根据识别结果绘制标签并显示
3. 搜集素材的思路
按照官方文档下载开发环境并完成板卡初始化设置,之后在SDK给出的示例中查找与本项目相关的程序进行学习。神经网络训练及代码转化方面则主要参考官方提供的神经网络仓库下的内容。
 
为简单快捷实现上位机程序,选择Python语言的Tkinter库,并查找了按钮、文本框、事件等方面的内容。
 
4. 实现过程
4.1 预训练实现过程
预训练主要参照官方 AI 文档:https://github.com/MaximIntegratedAI/MaximAI_Documentation
 
MAX78000 中使用 AI 算法主要有 training、synthesis、deployment 三个步骤,前两个步骤分别对应独立的 Github 仓库,第三个步骤则可以使用集成开发环境完成。IDE 的安装及配置主要参考了MaximAI_Documentation,写的非常详细
 
在神经网络模型方面,对常见对象检测模型进行调研,主要有 yolo、SSD、centerNet 及对应的变种方法,并未发现为边缘端定制的对象检测模型。后续查阅官方 Github 仓库,发现受支持的模型主要为分类模型,仅有一项 tinySSD 模型可用于对象检测。随后尝试部署 AI 训练及综合环境,并完成了对 tinySSD 模型的训练及量化。
 
4.1.1 环境配置
环境要求:
Full support and documentation are provided for the following platform:
CPU: 64-bit amd64/x86_64 “PC” with Ubuntu Linux 20.04 LTS GPU for hardware acceleration (optional but highly recommended): Nvidia with CUDA 11 PyTorch 1.8.1 (LTS) on Python 3.8.x
 
安装依赖:
sudo apt-get install -y make build-essential libssl-dev zlib1g-dev \
  libbz2-dev libreadline-dev libsqlite3-dev wget curl llvm \
  libncurses5-dev libncursesw5-dev xz-utils tk-dev libffi-dev liblzma-dev \
  libsndfile-dev portaudio19-dev
下载两个 git 仓库:
git clone --recursive https://github.com/MaximIntegratedAI/ai8x-training.git
git clone --recursive https://github.com/MaximIntegratedAI/ai8x-synthesis.git
创建 Anaconda 新环境并激活:
 conda create -n maxim python=3.8
 conda activate maxim
进入 ai8x-training 文件夹并安装依赖:
cd ai8x-training
pip install -r requirements-cu11.txt
ai8x-synthesis 不需要 CUDA 支持,官方教程中新建了一个环境,但实际上两个项目的软件包并没有冲突可以在一个环境中安装,避免实践中的切换。
 
4.1.2 模型训练
为训练 tinySSD 模型,需要手动访问 http://ufldl.stanford.edu/housenumbers/train 下载数据并解压到对应文件夹 /data/SVHN,后续执行训练脚本 ./scripts/train_svhn_tinierssd.sh 。训练过程的输出如下图所示:
Configuring device: MAX78000, simulate=False.
Log file for this run: /home/embed2/maxim/ai8x-training/logs/2022.11.21-214418/2022.11.21-214418.log
{'start_epoch': 25, 'weight_bits': 8, 'shift_quantile': 0.995}
{'multi_box_loss': {'alpha': 2, 'neg_pos_ratio': 3}, 'nms': {'min_score': 0.2, 'max_overlap': 0.3, 'top_k': 20}}
Optimizer Type: <class 'torch.optim.adam.Adam'>
Optimizer Args: {'lr': 0.001, 'betas': (0.9, 0.999), 'eps': 1e-08, 'weight_decay': 0.0005, 'amsgrad': False}
训练到最后的结果:
2022-11-22 01:43:22,884 - ==> Best [mAP: 0.801739   vloss: 5.124822   Sparsity:0.22   Params: 334562 on epoch: 48]
2022-11-22 01:43:22,884 - Saving checkpoint to: logs/2022.11.28-215122/qat_checkpoint.pth.tar
2022-11-22 01:43:22,901 - --- test ---------------------
2022-11-22 01:43:22,902 - 12251 samples (16 per mini-batch)
2022-11-22 01:43:44,156 - Test: [  200/  766]    Loss 5.123171    mAP 0.775422    
2022-11-22 01:43:58,389 - Test: [  400/  766]    Loss 5.132284    mAP 0.773612    
2022-11-22 01:44:12,862 - Test: [  600/  766]    Loss 5.131513    mAP 0.769577    
2022-11-22 01:44:24,824 - Test: [  766/  766]    Loss 5.132510    mAP 0.767998    
2022-11-22 01:44:24,864 - ==> mAP: 0.76800    Loss: 5.133
进行量化:
./scripts/quantize_svhn_tinierssd.sh
Configuring device: MAX78000
Converting checkpoint file trained/ai85-svhn-tinierssd-qat8.pth.tar to trained/ai85-svhn-tinierssd-qat8-q.pth.tar
......
后续使用ai8xize.py生成cnn.h和cnn.c两个文件,可用于MCU端的模型加载。
 
4.2 项目代码框架
MCU端程序流程如下:
FnNIbJ-wvGOx3AwwkYs0YcBYeVsJ
图片捕获函数名为 img_data_t capture_img(uint32_t w, uint32_t h, pixformat_t pixel_format, dmamode_t dma_mode, int dma_channel),来自官方SDK,整体分为五个步骤:
  1. 配置相机参数
  2. 调用 camera_start_capture_image() 捕获图像
  3. 等待图像捕获完成
  4. 获取相机驱动内部SRAM缓存的指针
  5. 返回捕获的图片
数字检测功能封装如下,需要注意的是每次执行推理都需要对CNN进行复位。
void digit_detection(img_data_t img_data){
    cnn_init();  // CNN 状态机复位
    cnn_load_bias();    // 重新加载bias
    cnn_configure();  // 配置CNN状态机
    load_input(img_data);     // 加载图像数据
    cnn_start();  // 开始执行CNN推理
    while (cnn_time == 0) {
        __WFI();  // 等待CNN推理完成
    }
    get_priors();   // 使用softmax计算检测结果
    localize_objects(); // 计算检测到的对象位置
    printf("CNN time: %d us\n\n", cnn_time);
}
上位机程序流程图如下:
FgjGEHQXMXY-zJ65MePSaH6xyD8a
程序的实现思路是创建串口线程与MCU通信,处理接收到的图片、识别结果等信息。而图形界面的按钮会触发相应的控制函数,使串口线程向MCU端发送控制命令。
 
其中进行图片格式转化的代码如下,会将每四个byte转化为一个像素的RGB信息,以供显示。
def rgb888_to_rgb(bytesequence):
  img = []
  for i in range(len(bytesequence) // 4):
    offset = i * 4
    byte1 = bytesequence[offset + 0]
    byte2 = bytesequence[offset + 1]
    byte3 = bytesequence[offset + 2]

    r = byte1
    g = byte2
    b = byte3

    img.append(r)
    img.append(g)
    img.append(b)

  return img

 

5. 实现效果
FhWKu3CAG-JzALIEAWmXBqe602w4
按下连接MCU按钮,上位机与MCU建立通信。点击“循环预览”后摄像头开始循环捕获图片并在上位机显示,以便调整摄像头位置。点击“捕获并识别当前图像”按钮,文本框会输出当前的检测结果,带有标注信息的图片也会在右侧显示。点击“保存图片到上位机”按钮,程序将保存当前捕获的图片,可用于小型数据集的制作。
 
6. 遇到的问题
6.1 低分辨率数据集缺失
受限于嵌入式端的性能,在边缘端运行的神经网络输入数据尺寸和模型大小都会小于GPU。而大部分可获取的对象检测数据集的尺寸都是面向GPU应用进行整理的,将这些图片直接缩小后,图片中的有效信息会被严重影响,难以用于模型训练。下面这两幅图片来自 kaggle,第二张图片是第一张直接resize为128*128的效果,放大可发现数字出现了明显的失真。
Fh6ixgLuBYD7nqnNxxZCQgG3jNTWFvlXeRh7q5MinFdGwrr204SWeiy6
由于这个问题,在进行项目实现时未采用公开的扑克牌数据集训练扑克牌识别器,而是使用了基于SVHN的网络对数字进行对象检测。
 
6.2 图像原始数据格式
在官方的camera例程中,图像使用RGB565格式保存,对应使用5、6、5位数据表示RGB通道的颜色值。相较于RGB888格式,RGB565能够降低图片的大小。但神经网络模型的输入源是RGB888格式的,为此需要在进行项目实现时把图片的捕获格式均调整为RGB888。
 
上位机从MCU端接收到的是原始数据,需要进行格式转化后才能正常存储。而例程中提供的格式转化方法是错误的,实际得到的数据一个像素对应32bit,而例程中按照24bit处理,导致图片无法显示。调整之后图片显示正常。
 
7. 总结
项目完成了上位机控制MCU捕获图像并检测数字的功能,上位机支持识别图像显示,达成了预期指标。与此同时,得益于Maxim神经网络独特的加载方式,经过简单的修改本上位机程序可应用于其他视觉相关任务。通过本项目,我熟悉了Maxim嵌入式端人工智能的开发流程,感到了边缘人工智能的广阔前景,今后将拓宽这方面的学习,期待有一天在开发板上实现更多更有趣的智能应用。
附件下载
maxim.zip
项目源码、GUI程序、MCU程序
团队介绍
个人团队
团队成员
2x3j
评论
0 / 100
查看更多
目录
硬禾服务号
关注最新动态
0512-67862536
info@eetree.cn
江苏省苏州市苏州工业园区新平街388号腾飞创新园A2幢815室
苏州硬禾信息科技有限公司
Copyright © 2023 苏州硬禾信息科技有限公司 All Rights Reserved 苏ICP备19040198号