一、项目介绍
活动推出时,犹豫了好久。一方面很想玩玩这种带人工智能的开发板,另一方面由于本人从未接触过非 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为概念验证和早期软件开发提供经过功率优化管理的便捷、灵活开发平台,加快产品上市。
1.2 开发板硬件介绍
- 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协处理器
- 音频处理:多关键词识别、声音分类、消噪声
- 面部识别
- 目标检测和分类
- 时间序列数据处理:心率/健康信号分析、多传感器分析、预测性维护
二、项目设计思路(含设计框图)
如上图所示,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 安装训练依赖库
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 目录下,如下图所示:
根据 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;
}
}
}
六、实现结果展示
由于项目快结束时才改的选题,跟声音相关的都没法实现了,只能改视觉识别类的选题。并且来不及购买屏幕,因此,选择在串口输出识别结果。以下是部分标志拍摄的识别串口输出截图。
- 五菱标志正确识别
- 宝马标志正确识别正确
- 长安标志正确识别正确
- 比亚迪标志正确识别正确
- 尉来标志不能识别
七、遇到的主要难题及解决方法,或未来的计划或建议等
-
原本是打算实现智能音响的,做到一半发现不知是麦克风出问题了,还是语音芯片出问题了,始终无法识别语音指令。曾一度怀疑是我训练过程有问题,后面烧录官方的 kws20_demo 示例程序,也是无法识别。烧录 I2S_DMA_Target 示例程序发现发出的全是杂音,无法正常获取音频。由于本人能力有限无法解决,因此只能半道调整目标为识别汽车标志。
-
识别正确率的问题,拍摄的画面只能在固定角度能正确识别,对拍摄的要求挺高。近一点、远一点、倾斜一点、亮一点、暗一点都可能导致识别错误。这一点在使用官方示例的 cats-dogs_demo 也是一样。猜测可能需要更大量级的样本数据以及对拍摄的画面作预处理,这就留待以后再去探索了。
-
网络模型是整个预训练与识别的基础,本项目中尚不明确每层模型的含义,以及每层模型参数的意义。这也只能留待以后再去探索了。
八、参考文献
- https://www.eetree.cn/project/detail/1152
- https://github.com/MaximIntegratedAI/ai8x-training
- https://github.com/MaximIntegratedAI/MaximAI_Documentation/blob/master/Guides/Making Your Own Audio and Image Classification Application Using Keyword Spotting and Cats-vs-Dogs.md
- https://analog-devices-msdk.github.io/msdk/USERGUIDE/