基于MAX78000FTHR实现汽车标志识别
使用MAX78000FTHR开发板实现汽车标志识别,通过按钮触发拍摄画面,识别结果通过串口输出。
标签
嵌入式系统
AI
人工智能
MAX78000
MAX78000FTHR
汽车标志
品牌识别
鲜de芒果
更新2024-01-10
150

一、项目介绍

活动推出时,犹豫了好久。一方面很想玩玩这种带人工智能的开发板,另一方面由于本人从未接触过非 Arduino 以外的单片机开发,身边也没有这方面的朋友可以咨询。经过长时间的尝试后,成功安装好了开发环境,才决定参加这次的活动。这次决定实现的为汽车标志识别。

1.1 开发板介绍

MAX78000FTHR为快速开发平台,帮助工程师利用MAX78000 Arm® Cortex® M4F处理器快速实施超低功耗、人工智能(AI)方案,器件集成卷积神经网络加速器。评估板包括MAX20303 PMIC,用于电池和电源管理。评估板规格为0.9in x 2.6in、双排连接器,兼容Adafruit Feather Wing外设扩展板。评估板包括各种外设,例如CMOS VGA图像传感器、数字麦克风、低功耗立体声音频CODEC、1MB QSPI SRAM、micro SD存储卡连接器、RGB指示LED和按键。MAX78000FTHR为概念验证和早期软件开发提供经过功率优化管理的便捷、灵活开发平台,加快产品上市。

Frs_VpbUvy0G-QkLX7A5ohivNxcL

 

1.2 开发板硬件介绍

FjkwDgRNfhJFwu9m-UuIbaXrbDeg

FpUzvPjB4fZh2SJiC83M4qHiZ738FjHbfbL-nTdX-YBZ3UizrrrKpa66
  • MAX78000微控制器
    • 双核:Arm Cortex-M4 FPU处理器,100MHz;RISC-V协处理器,60MHz
    • 512KB闪存
    • 128KB SRAM
    • 16KB缓存
    • 卷积神经网络加速器
    • 12位并行摄像头接口
    • MAX20303可穿戴PMIC,带电量计
    • 通过USB充电
    • 板载DAPLink调试和编程(MAX32625)
    • Arm Cortex-M4 FPU处理器接口
    • 兼容面包板的连接头
    • Micro USB连接器
    • Micro SD卡连接器
  • 集成外设
    • RGB指示LED
    • 用户按钮
    • CMOS VGA图像传感器(OVM769)
    • 低功耗、立体声音频编解码器(MAX9867)
    • SPH0645LM4H-B数字麦克风
    • SWD调试器
    • 虚拟UART控制台
    • 10引脚Cortex调试接头,用于RISC-V协处理器
  • 音频处理:多关键词识别、声音分类、消噪声
  • 面部识别
  • 目标检测和分类
  • 时间序列数据处理:心率/健康信号分析、多传感器分析、预测性维护

 

二、项目设计思路(含设计框图)

FpwjsvB1royIJyBnvslBTWGjrNs1

如上图所示,MAX78000FTHR通过板载摄像头拍摄一帧画面数据,经过处理后通过CNN加速引擎匹配出正确的车辆标志,通过串口输出识别结果。(如果有 TFT 显示屏,则在显示屏幕上显示结果)

 

三、搜集素材的思路

原本打算搜索网络上开源的语料库,尝试了很多之后,没有找到合适的现成素材。最终通过图片搜索,抓取到了十几种类型的车辆标志,通过剪裁筛选,最终得到了十种品牌的车辆标志图(原本有20种左右,经过筛选,只选取了图片数量最多的十种。数量过少的由于训练识别率太低而去除),平均每种标志图片在40 ~ 50张。按照猫狗示例项目的分类存放在 data 目录下。

 

四、预训练环境搭建

训练环境安装还算比较顺利,按官方提供的Github库中的说明一步一步执行即可完成训练环境的安装,如果安装过程中出现错误很大一部分原因是网络环境导致的。以下为记录安装过程中使用的命令。 如果有人看到并按照我的方法进行安装,请记得将以下命令一行一行进行执行,批量执行不保证正确性。 我使用的环境是基于 Windows11 22H2 的 WSL2 环境,系统为 Ubuntu 20.04.6LTS

 

4.1. 系统环境

环境 说明
系统: Windows 11 专业版
版本: 22H2
环境: WSL2
子系统: Ubuntu 20.04.6LTS

 

4.2. 系统依赖库安装

# 依赖库安装
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

 

4.3. pyenv安装

# Python环境,依赖版本 3.8。使用 pyenv 安装
curl -L https://github.com/pyenv/pyenv-installer/raw/master/bin/pyenv-installer | bash

 

4.4. Python环境安装

# 添加环境变量将以下添加至环境变量配置文件中,~/.bashrc
export PYENV_ROOT="$HOME/.pyenv"
export PATH="$PYENV_ROOT/bin:$PATH"
eval "$(pyenv init --path)"
eval "$(pyenv virtualenv-init -)"

# 使用 pyenv 安装 python 3.8.11
pyenv install 3.8.11

 

4.5. 训练代码仓库拉取

# 训练仓库拉取
git clone --recursive https://github.com/MaximIntegratedAI/ai8x-training.git
# 量化仓库拉取
git clone --recursive https://github.com/MaximIntegratedAI/ai8x-synthesis.git

这一步尽量拉取到同一目录下,最终目录结构如下所示:

├─folder

│ ├─ai8x-training/

│ ├─ai8x-synthesis/

注:这一步非常容易失败,确保拉取时添加了 --recursive 指令,一并将依赖的子仓库一起下载完整。 更新子模块时,也需要添加 --recursive 指令,完整命令为:git submodule update --init --recursive

 

4.6. 创建虚拟训练环境

4.6.1 进入训练仓库目录

cd ai8x-training
# 检查 python 版本(可选)
python --version

 

4.6.2 创建虚拟环境

python -m venv venv --prompt ai8x-training

 

4.6.3 激活训练虚拟环境

source venv/bin/activate

 

4.6.4 安装依赖安装库

(ai8x-training) $ pip3 install -U pip wheel setuptools

注意:这一步在激活的虚拟环境下执行,命令行会带有 (ai8x-training) 前缀字样。

 

4.6.5 安装训练依赖库

(ai8x-training) $ pip3 install -r requirements-cu11.txt

 

4.7. 创建虚拟量化环境

4.7.1 进入量化仓库目录

cd ai8x-synthesis
# 检查 python 版本(可选)
python --version

 

4.7.2 创建虚拟环境

python -m venv venv --prompt ai8x-synthesis

 

4.7.3 激活量化虚拟环境

source venv/bin/activate

 

4.7.4 安装依赖安装库

(ai8x-synthesis) $ pip3 install -U pip wheel setuptools

注意:这一步在激活的虚拟环境下执行,命令行会带有 (ai8x-synthesis) 前缀字样。

 

4.7.5 安装量化依赖库

(ai8x-synthesis) $ pip3 install -r requirements.txt

到此完成了训练与量化环境的搭建,可以进行示例程序的训练与量化了。

 

五、预训练实现过程及关键代码说明

预训练参考官示例项目 catsdogs 搭建训练模型与训练素材的组织,主要分为以下步骤:

5.1. 素材准备

汽车标志识别的素材,通过搜索引擎图片分类查找相关分类图片,再使用绘图工具框选出汽车标志部分。按照 catsdogs 的训练素材的目录结构组织,存放在 ai8x-training/data 目录下,如下图所示:

FqN8nNHenfgwS75pJQywJufS6YQz

 

根据 catsdogs 的数据集建立汽车标志数据集,关键代码如下:

...

datasets = [
    {
        'name': 'vehicle_brand',
        'input': (3, 128, 128),
        'output': ('Audi', 'BMW', 'BYD', 'ChangAn', 'Geely', 'GWM', 'immotors', 'Pagani', 'WuLing', 'XiaoPeng'),
        'loader': vehicle_brand_get_datasets,
    },
]

参考 ai85net-cd.py 建立模型文件 ai85net-vehicle-brand.py

class AI85VehicleBrand(nn.Module):
    """
    Define CNN model for image classification.
    """
    def __init__(self, num_classes=10, num_channels=3, dimensions=(128, 128),
                 fc_inputs=16, bias=False, **kwargs):

...

models = [
    {
        'name': 'ai85vehicle_brand',
        'min_input': 1,
        'dim': 2,
    },
]

注意: 模型文件中的 num_classes 数量需要和数据集中的数据分类数对应,如果大于数据集分类数训练时会报索引超出异常。

 

5.2. 训练

训练脚本需要使用 vehicle_brand 数据集,创建训练脚本文件 train_vehicle_brand.sh 输入如下内容:

#!/bin/sh
python train.py --epochs 250 --optimizer Adam --lr 0.001 --wd 0 --deterministic --compress policies/schedule-vehicle-brand.yaml --model ai85vehicle_brand --dataset vehicle_brand --confusion --param-hist --embedding --device MAX78000 "$@"

数据集训练日志输出如下:

2023-12-14 17:02:27,295 - Log file for this run: /home/xxx/MaximIntegratedAI/ai8x-training/logs/2023.12.14-170227/2023.12.14-170227.log
2023-12-14 17:02:27,300 - Optimizer Type: <class 'torch.optim.adam.Adam'>
2023-12-14 17:02:27,300 - Optimizer Args: {'lr': 0.001, 'betas': (0.9, 0.999), 'eps': 1e-08, 'weight_decay': 0.0, 'amsgrad': False}
2023-12-14 17:02:27,308 - Dataset sizes:
	training=717
	validation=79
	test=56
2023-12-14 17:02:27,309 - Reading compression schedule from: policies/schedule-vehicle-brand.yaml
2023-12-14 17:02:27,310 - 

2023-12-14 17:02:27,310 - Training epoch: 717 samples (256 per mini-batch)
2023-12-14 17:02:28,944 - Epoch: [0][    3/    3]    Overall Loss 2.261726    Objective Loss 2.261726    Top1 16.268980    Top5 64.859002    LR 0.001000    Time 0.544561    
2023-12-14 17:02:28,954 - --- validate (epoch=0)-----------
2023-12-14 17:02:28,954 - 79 samples (256 per mini-batch)
2023-12-14 17:02:29,145 - Epoch: [0][    1/    1]    Loss 2.200456    Top1 13.924051    Top5 58.227848    
2023-12-14 17:02:29,153 - ==> Top1: 13.924    Top5: 58.228    Loss: 2.200

2023-12-14 17:02:29,153 - ==> Confusion:
[[11  0  0  0  0  0  0  0  0  0]
 [ 9  0  0  0  0  0  0  0  1  0]
 [10  0  0  0  0  0  0  0  0  0]
 [ 3  0  0  0  0  0  0  0  0  0]
 [ 8  0  0  0  0  0  0  0  0  0]
 [10  0  0  0  0  0  0  0  0  0]
 [ 6  0  0  0  0  0  0  0  0  0]
 [ 8  0  0  0  0  0  0  0  0  0]
 [11  0  0  0  0  0  0  0  0  0]
 [ 2  0  0  0  0  0  0  0  0  0]]

2023-12-14 17:02:29,155 - ==> Best [Top1: 13.924   Top5: 58.228   Sparsity:0.00   Params: 65968 on epoch: 0]
2023-12-14 17:02:29,155 - Saving checkpoint to: logs/2023.12.14-170227/checkpoint.pth.tar
2023-12-14 17:02:29,157 - 

2023-12-14 17:02:29,157 - Training epoch: 717 samples (256 per mini-batch)
2023-12-14 17:02:30,882 - Epoch: [1][    3/    3]    Overall Loss 2.168664    Objective Loss 2.168664    Top1 21.258134    Top5 65.292842    LR 0.001000    Time 0.574868    
2023-12-14 17:02:30,894 - --- validate (epoch=1)-----------
2023-12-14 17:02:30,894 - 79 samples (256 per mini-batch)
2023-12-14 17:02:31,088 - Epoch: [1][    1/    1]    Loss 2.115032    Top1 31.645570    Top5 68.354430    
2023-12-14 17:02:31,096 - ==> Top1: 31.646    Top5: 68.354    Loss: 2.115

2023-12-14 17:02:31,096 - ==> Confusion:
[[8 1 0 0 0 0 0 0 2 0]
 [1 8 0 0 0 0 0 0 1 0]
 [9 0 0 0 0 0 0 0 1 0]
 [1 1 0 1 0 0 0 0 0 0]
 [4 1 0 0 0 0 0 0 3 0]
 [7 0 0 0 0 0 0 0 3 0]
 [2 1 0 0 0 0 0 0 3 0]
 [7 1 0 0 0 0 0 0 0 0]
 [3 0 0 0 0 0 0 0 8 0]
 [1 0 0 0 0 0 0 0 1 0]]

2023-12-14 17:02:31,098 - ==> Best [Top1: 31.646   Top5: 68.354   Sparsity:0.00   Params: 65968 on epoch: 1]
2023-12-14 17:02:31,098 - Saving checkpoint to: logs/2023.12.14-170227/checkpoint.pth.tar
2023-12-14 17:02:31,100 - 

...

2023-12-14 17:11:42,834 - Training epoch: 717 samples (256 per mini-batch)
2023-12-14 17:11:44,850 - Epoch: [248][    3/    3]    Overall Loss 0.006937    Objective Loss 0.006937    Top1 100.000000    Top5 100.000000    LR 0.000216    Time 0.671784    
2023-12-14 17:11:44,862 - --- validate (epoch=248)-----------
2023-12-14 17:11:44,863 - 79 samples (256 per mini-batch)
2023-12-14 17:11:45,084 - Epoch: [248][    1/    1]    Loss 0.188818    Top1 93.670886    Top5 100.000000    
2023-12-14 17:11:45,093 - ==> Top1: 93.671    Top5: 100.000    Loss: 0.189

2023-12-14 17:11:45,094 - ==> Confusion:
[[11  0  0  0  0  0  0  0  0  0]
 [ 0 10  0  0  0  0  0  0  0  0]
 [ 0  0 10  0  0  0  0  0  0  0]
 [ 0  0  0  3  0  0  0  0  0  0]
 [ 1  0  0  0  6  0  1  0  0  0]
 [ 0  0  0  0  0  9  0  0  1  0]
 [ 0  0  0  0  0  0  5  0  0  1]
 [ 0  0  0  1  0  0  0  7  0  0]
 [ 0  0  0  0  0  0  0  0 11  0]
 [ 0  0  0  0  0  0  0  0  0  2]]

2023-12-14 17:11:45,096 - ==> Best [Top1: 93.671   Top5: 100.000   Sparsity:0.00   Params: 65968 on epoch: 248]
2023-12-14 17:11:45,096 - Saving checkpoint to: logs/2023.12.14-170227/qat_checkpoint.pth.tar
2023-12-14 17:11:45,098 - 

2023-12-14 17:11:45,098 - Training epoch: 717 samples (256 per mini-batch)
2023-12-14 17:11:47,052 - Epoch: [249][    3/    3]    Overall Loss 0.006824    Objective Loss 0.006824    Top1 100.000000    Top5 100.000000    LR 0.000216    Time 0.650947    
2023-12-14 17:11:47,065 - --- validate (epoch=249)-----------
2023-12-14 17:11:47,065 - 79 samples (256 per mini-batch)
2023-12-14 17:11:47,302 - Epoch: [249][    1/    1]    Loss 0.190467    Top1 93.670886    Top5 100.000000    
2023-12-14 17:11:47,311 - ==> Top1: 93.671    Top5: 100.000    Loss: 0.190

2023-12-14 17:11:47,312 - ==> Confusion:
[[11  0  0  0  0  0  0  0  0  0]
 [ 0 10  0  0  0  0  0  0  0  0]
 [ 0  0 10  0  0  0  0  0  0  0]
 [ 0  0  0  3  0  0  0  0  0  0]
 [ 1  0  0  0  6  0  1  0  0  0]
 [ 0  0  0  0  0  9  0  0  1  0]
 [ 0  0  0  0  0  0  5  0  0  1]
 [ 0  0  0  1  0  0  0  7  0  0]
 [ 0  0  0  0  0  0  0  0 11  0]
 [ 0  0  0  0  0  0  0  0  0  2]]

2023-12-14 17:11:47,314 - ==> Best [Top1: 93.671   Top5: 100.000   Sparsity:0.00   Params: 65968 on epoch: 249]
2023-12-14 17:11:47,314 - Saving checkpoint to: logs/2023.12.14-170227/qat_checkpoint.pth.tar
2023-12-14 17:11:47,316 - --- test ---------------------
2023-12-14 17:11:47,316 - 56 samples (256 per mini-batch)
2023-12-14 17:11:47,542 - Test: [    1/    1]    Loss 0.642625    Top1 83.928571    Top5 96.428571    
2023-12-14 17:11:47,551 - ==> Top1: 83.929    Top5: 96.429    Loss: 0.643

2023-12-14 17:11:47,551 - ==> Confusion:
[[7 0 1 0 0 0 0 0 0 0]
 [0 7 0 0 0 0 0 0 0 0]
 [0 0 8 0 0 0 0 0 0 0]
 [0 0 0 4 0 0 0 0 0 0]
 [0 0 0 0 5 0 0 0 0 0]
 [1 0 1 0 1 2 0 0 0 0]
 [0 0 1 0 0 0 1 0 0 0]
 [0 0 0 0 0 0 0 5 1 0]
 [0 0 1 0 0 0 0 0 7 1]
 [0 0 0 0 0 0 0 0 1 1]]

2023-12-14 17:11:47,553 - 
2023-12-14 17:11:47,553 - Log file for this run: /home/xxx/MaximIntegratedAI/ai8x-training/logs/2023.12.14-170227/2023.12.14-170227.log

根据日志输出可以看到,训练后在测试集上的 Top1 准确率可以达到 83.929%Top5 准确率可以达到 96.429%,说明该模型网络可以识别绝大部分的汽车标志。

 

5.3. 量化

根据官方示例说明,需要对训练后的数据进行量化,将浮点数转为整数。参考 catsdogs 的量化脚本创建量化脚本 quantize_vehicle_brand.sh

#!/bin/sh
python quantize.py ../ai8x-training/logs/2023.12.14-170227/qat_best.pth.tar trained/vehicle-brand-q.pth.tar --device MAX78000 -v "$@"

 

5.4. 评估

对量化后的数据进行评估测试,并生成样本文件。创建评估脚本文件,脚本内容如下:

#!/bin/sh
python train.py --model ai85vehicle_brand --dataset vehicle_brand --confusion --evaluate --exp-load-weights-from ../ai8x-synthesis/trained/vehicle-brand-q.pth.tar -8 --save-sample 1 --device MAX78000 "$@"

注意: 评估脚本是在 ai8x-training/scripts 目录下,需要添加参数 --save-sample 1 来生成样本文件。生成的样本文件位于 ai8x-training 目录下。文件名为: ai8x-training/sample_vehicle_brand.npy

执行评估脚本输出日志如下:

2023-12-14 17:14:35,214 - Log file for this run: /home/xxx/MaximIntegratedAI/ai8x-training/logs/2023.12.14-171435/2023.12.14-171435.log
2023-12-14 17:14:35,225 - => loading checkpoint ../ai8x-synthesis/trained/vehicle-brand-q.pth.tar
2023-12-14 17:14:35,227 - => Checkpoint contents:
+----------------------+-------------+-------------------+
| Key                  | Type        | Value             |
|----------------------+-------------+-------------------|
| arch                 | str         | ai85vehicle_brand |
| compression_sched    | dict        |                   |
| epoch                | int         | 249               |
| extras               | dict        |                   |
| optimizer_state_dict | dict        |                   |
| optimizer_type       | type        | Adam              |
| state_dict           | OrderedDict |                   |
+----------------------+-------------+-------------------+

2023-12-14 17:14:35,227 - => Checkpoint['extras'] contents:
+-----------------+--------+-------------------+
| Key             | Type   | Value             |
|-----------------+--------+-------------------|
| best_epoch      | int    | 249               |
| best_mAP        | int    | 0                 |
| best_top1       | float  | 93.67088607594937 |
| clipping_method | str    | MAX_BIT_SHIFT     |
| current_mAP     | int    | 0                 |
| current_top1    | float  | 93.67088607594937 |
+-----------------+--------+-------------------+

2023-12-14 17:14:35,227 - Loaded compression schedule from checkpoint (epoch 249)
2023-12-14 17:14:35,228 - => loaded 'state_dict' from checkpoint '../ai8x-synthesis/trained/vehicle-brand-q.pth.tar'
2023-12-14 17:14:35,232 - Optimizer Type: <class 'torch.optim.sgd.SGD'>
2023-12-14 17:14:35,232 - Optimizer Args: {'lr': 0.1, 'momentum': 0.9, 'dampening': 0, 'weight_decay': 0.0001, 'nesterov': False}
2023-12-14 17:14:35,239 - Dataset sizes:
	training=717
	validation=79
	test=56
2023-12-14 17:14:35,239 - --- test ---------------------
2023-12-14 17:14:35,239 - 56 samples (256 per mini-batch)
2023-12-14 17:14:35,416 - Test: [    1/    1]    Loss 0.624380    Top1 83.928571    Top5 96.428571    
2023-12-14 17:14:35,422 - ==> Top1: 83.929    Top5: 96.429    Loss: 0.624

2023-12-14 17:14:35,423 - ==> Confusion:
[[7 0 1 0 0 0 0 0 0 0]
 [0 7 0 0 0 0 0 0 0 0]
 [0 0 8 0 0 0 0 0 0 0]
 [0 0 0 4 0 0 0 0 0 0]
 [0 0 0 0 5 0 0 0 0 0]
 [1 0 1 0 1 2 0 0 0 0]
 [0 0 1 0 0 0 1 0 0 0]
 [0 0 0 0 0 0 0 5 1 0]
 [0 0 1 0 0 0 0 0 7 1]
 [0 0 0 0 0 0 0 0 1 1]]

2023-12-14 17:14:35,424 - 
2023-12-14 17:14:35,424 - Log file for this run: /home/xxx/MaximIntegratedAI/ai8x-training/logs/2023.12.14-171435/2023.12.14-171435.log

通过以上日志可以看到,评估结果和训练结果是一致的,说明整个过程没有出错。

 

5.5. 生成

最后一步,根据量化生成的 vehicle-brand-q.pth.tar 文件、网络描述文件 ****、评估脚本生成的样本文件来生成代码。生成脚本如下:

#!/bin/sh
DEVICE="MAX78000"
TARGET="/tmp/"
COMMON_ARGS="--device $DEVICE --timer 0 --display-checkpoint --verbose"

python ai8xize.py --test-dir $TARGET --prefix cats-dogs --checkpoint-file trained/vehicle-brand-q.pth.tar --config-file networks/vehicle-brand.yaml --fifo --softmax $COMMON_ARGS "$@"

 

5.6. 工程建立

简单的来说,可以根据官方示例的 cats-dogs_demo 工程来新建一个工程,也可以直接拷贝 cats-dogs_demo 工程。 将 步骤5 生成的文件直接替换 cats-dogs_demo 工程里的相应文件,即可执行默认测试代码。如果默认测试代码在串口监视器看到输出 PASS 字样。说明测试通过,整个预训练以及工程编译烧录流程正确。可以根据自己的需要修改代码来实现汽车品牌识别的功能了。

 

5.7. 汽车标志识别

5.7.1 图像捕捉

参考 cats-dogs_demo 示例项目中的图像捕获代码,通过识别 sw1 的按下操作来触发拍摄画面。并由 cnn 加载识别。

void capture_process_camera(void)
{
    uint8_t *raw;
    uint32_t imgLen;
    uint32_t w, h;

    int cnt = 0;

    uint8_t r, g, b;
    uint16_t rgb;
    int j = 0;

    uint8_t *data = NULL;
    stream_stat_t *stat;

    camera_start_capture_image();

    // Get the details of the image from the camera driver.
    camera_get_image(&raw, &imgLen, &w, &h);
    printf("W:%d H:%d L:%d \n", w, h, imgLen);

    // Get image line by line
    for (int row = 0; row < h; row++) {
        // Wait until camera streaming buffer is full
        while ((data = get_camera_stream_buffer()) == NULL) {
            if (camera_is_image_rcv()) {
                break;
            }
        }

        j = 0;

        for (int k = 0; k < 4 * w; k += 4) {
            // data format: 0x00bbggrr
            r = data[k];
            g = data[k + 1];
            b = data[k + 2];
            //skip k+3

            // change the range from [0,255] to [-128,127] and store in buffer for CNN
            input_0[cnt++] = ((b << 16) | (g << 8) | r) ^ 0x00808080;

            // convert to RGB656 for display
            rgb = ((r & 0b11111000) << 8) | ((g & 0b11111100) << 3) | (b >> 3);
            data565[j] = (rgb >> 8) & 0xFF;
            data565[j + 1] = rgb & 0xFF;

            j += 2;
        }
        // Release stream buffer
        release_camera_stream_buffer();
    }

    //camera_sleep(1);
    stat = get_camera_stream_statistic();

    if (stat->overflow_count > 0) {
        printf("OVERFLOW DISP = %d\n", stat->overflow_count);
        LED_On(LED2); // Turn on red LED if overflow detected
        while (1) {}
    }
}

 

5.7.2 串口输出

cats-dogs_demo 示例项目中实现了串口输出图片的相应功能,只需要放开 ASCII_ART 宏定义的注释即可调用 asciiart 函数将图片使用字符的形式输出到串口。

char *brightness = "@%#*+=-:. "; // simple
#define RATIO 2 // ratio of scaling down the image to display in ascii
void asciiart(uint8_t *img)
{
    int skip_x, skip_y;
    uint8_t r, g, b, Y;
    uint8_t *srcPtr = img;
    int l = strlen(brightness) - 1;

    skip_x = RATIO;
    skip_y = RATIO;
    for (int i = 0; i < IMAGE_SIZE_Y; i++) {
        for (int j = 0; j < IMAGE_SIZE_X; j++) {
            // 0x00bbggrr, convert to [0,255] range
            r = *srcPtr++ ^ 0x80;
            g = *(srcPtr++) ^ 0x80;
            b = *(srcPtr++) ^ 0x80;

            srcPtr++; //skip msb=0x00

            // Y = 0.2126 * r + 0.7152 * g + 0.0722 * b;
            Y = (3 * r + b + 4 * g) >> 3; // simple luminance conversion
            if ((skip_x == RATIO) && (skip_y == RATIO))
                printf("%c", brightness[l - (Y * l / 255)]);

            skip_x++;
            if (skip_x > RATIO)
                skip_x = 1;
        }
        skip_y++;
        if (skip_y > RATIO) {
            printf("\n");
            skip_y = 1;
        }
    }
}

 

六、实现结果展示

由于项目快结束时才改的选题,跟声音相关的都没法实现了,只能改视觉识别类的选题。并且来不及购买屏幕,因此,选择在串口输出识别结果。以下是部分标志拍摄的识别串口输出截图。

  • 五菱标志正确识别
  • FpayDEtv4FxK8gi6HYSiy_tgX6XfFg_tzPiHnnRAe98ypNmClUWR0Jf3
 
  • 宝马标志正确识别正确
  • FjC5dDCKgeOyAj_iUfOAfhnWdisY
 
  • 长安标志正确识别正确
  • Fvn2eODejNK73cKRI3nHsqrDs2qb
 
  • 比亚迪标志正确识别正确
  • Fs-AoC6SRyngy-ZA64hwOGKvsId1
 
  • 尉来标志不能识别
  • FuMtUC0bcjB8_nRGPXQeaUDw5lXm
 

七、遇到的主要难题及解决方法,或未来的计划或建议等

  1. 原本是打算实现智能音响的,做到一半发现不知是麦克风出问题了,还是语音芯片出问题了,始终无法识别语音指令。曾一度怀疑是我训练过程有问题,后面烧录官方的 kws20_demo 示例程序,也是无法识别。烧录 I2S_DMA_Target 示例程序发现发出的全是杂音,无法正常获取音频。由于本人能力有限无法解决,因此只能半道调整目标为识别汽车标志。

  2. 识别正确率的问题,拍摄的画面只能在固定角度能正确识别,对拍摄的要求挺高。近一点、远一点、倾斜一点、亮一点、暗一点都可能导致识别错误。这一点在使用官方示例的 cats-dogs_demo 也是一样。猜测可能需要更大量级的样本数据以及对拍摄的画面作预处理,这就留待以后再去探索了。

  3. 网络模型是整个预训练与识别的基础,本项目中尚不明确每层模型的含义,以及每层模型参数的意义。这也只能留待以后再去探索了。

 

八、参考文献

附件下载
vehicle_brand.zip
工程源码
训练脚本.zip
训练脚本与量化生成文件
团队介绍
业余电子爱好者
团队成员
鲜de芒果
评论
0 / 100
查看更多
目录
硬禾服务号
关注最新动态
0512-67862536
info@eetree.cn
江苏省苏州市苏州工业园区新平街388号腾飞创新园A2幢815室
苏州硬禾信息科技有限公司
Copyright © 2023 苏州硬禾信息科技有限公司 All Rights Reserved 苏ICP备19040198号