问题描述
你是否想过,图像检测技术正以怎样的方式重塑我们的世界?从商场无人结算的 “秒级支付” 到医院 AI 辅助诊断的 “精准预判”,从工厂流水线上的 “毫米级质检” 到农田里的 “病虫害智能识别”,这项技术早已突破实验室的边界,渗透进我们生活的每一个角落。今天我们将以数字检测为例子,带领大家一步步完成图像检测在 K230 上的搭建。

一、训练环境准备
硬件:PC(考虑到训练需求,需要使用一台带 GPU 的电脑)
软件:Linux 操作系统/ Window 安装 WSL
网络:由于需要获取 github 的资源,最好是能够连接外网
1、搭建 YOLOv5 训练环境
git clone https://github.com/ultralytics/yolov5.git
cd yolov5
pip install -r requirements.txt
2、数据采集
我们已经提供 Micropython 脚本(请参考 K230 SDK 中代码 DataCollectionCamera.py),使用 K230 开发板就能完成数据采集的工作(数据采集脚本使用方法请参考文末 B站视频教程)
aaa@DESKTOP-OSN5BJK:~/canmv_k230_gitee_micropython$ cd src/canmv/resources/examples/16-AI-Cube/
aaa@DESKTOP-OSN5BJK:~/canmv_k230_gitee_micropython/src/canmv/resources/examples/16-AI-Cube$ ls
ClassificationApp.py DataCollectionCamera.py DetectionApp.py MultiLabelApp.py OCR_Det.py SegmentationApp.py SelfLearningApp.py

demo 运行起来如上图所示,我们在抓图的时候,尽量多角度,多距离抓取。
3、数据标注
图像识别的数据集,需要使用图片标注软件,在这里我们使用的是 labelme。
Labelme 下载链接:
https://github.com/wkentaro/labelme/releases/download/v5.5.0/Labelme.exe

tree -L 3 .
├── num_yolo
│ ├── calc //量化数据
│ ├── images //图片集合
│ │ ├── test //测试图片集
│ │ ├── train //训练图片集
│ │ └── val //验证图片集
│ └── labels //标注框集合
│ ├── test
│ ├── train
│ └── val
└── num_yolo.yaml //训练时使用的配置文件
由于 labelme 标注出来的数据是 json 格式,我们需要使用脚本转换成 txt 格式的 label 数据。我们提供了一个转换的脚本,方便大家快速进行文本格式转换。
脚本下载地址:
https://kendryte-download.canaan-creative.com/developer/common/jsontotxt.py
二、模型训练
一切准备就绪,让模型开始学习!在 yolov5 目录下执行如下指令:
python train.py --weight yolov5n.pt --cfg models/yolov5n.yaml --data datasets/num_yolo.yaml --epochs 300 --batch-size 8 --imgsz 320 --device '0'
注意:这个命令的参数 --device '0' 是表示使用 GPU 资源训练,如果没有 GPU 的情况下,需要切换成 --device 'cpu'
训练完成显示如下(本地使用 CPU 电脑):
300 epochs completed in 1.611 hours.
Optimizer stripped from runs/train/exp2/weights/last.pt, 3.7MB
Optimizer stripped from runs/train/exp2/weights/best.pt, 3.7MB
Validating runs/train/exp2/weights/best.pt...
Fusing layers...
YOLOv5n summary: 157 layers, 1764577 parameters, 0 gradients, 4.1 GFLOPs
Class Images Instances P R mAP50 mAP50-95: 100%|██████████| 3/3 [00:00<00:00, 4.83it/s]
all 41 41 0.993 1 0.995 0.928
0 41 11 0.992 1 0.995 0.957
1 41 10 0.995 1 0.995 0.872
2 41 10 0.993 1 0.995 0.93
3 41 10 0.993 1 0.995 0.953
Results saved to runs/train/exp2
三、模型转换
1、安装 nncase 和 onnx 转换工具
# linux平台/Linux虚拟机:nncase和nncase-kpu可以在线安装,nncase-2.x 需要安装 dotnet-7
sudo apt-get install -y dotnet-sdk-7.0
pip install --upgrade pip
pip install nncase==2.9.0
pip install nncase-kpu==2.9.0
# windows平台:请自行安装dotnet-7并添加环境变量,支持使用pip在线安装nncase,但是nncase-kpu库需要离线安装,在https://github.com/kendryte/nncase/releases下载nncase_kpu-2.*-py2.py3-none-win_amd64.whl# 进入对应的python环境,在nncase_kpu-2.*-py2.py3-none-win_amd64.whl下载目录下使用pip安装
pip install nncase_kpu-2.*-py2.py3-none-win_amd64.whl
# 除nncase和nncase-kpu外,脚本还用到的其他库包括:
pip install onnx
pip install onnxruntime
pip install onnxsim
2、下载转换脚本工具test_yolov5.zip并解压到yolov5目录下
wget https://kendryte-download.canaan-creative.com/developer/k230/yolo_files/test_yolov5.zip
unzip test_yolov5.zip
3、模型转换
按照指令先将训练好的pt模型导出为 onnx 模型,再转换为 kmodel 模型,以便在 K230 上运行,模型转换中需要使用 nncase 模型转换工具,请参考其使用指南:
https://www.kendryte.com/k230_rtos/zh/main/app_develop_guide/ai/nncase.html
量化数据集:我们在做模型转换的时候,需要使用训练数据的一个子集(推荐取训练数据的 20%)做量化,在模型转换的时候,需要指定到 --dataset 参数
# 导出onnx,pt模型路径请自行选择
python export.py --weight runs/train/exp2/weights/best.pt --imgsz 320 --batch 1 --include onnx
cd test_yolov5/detect
# 转换kmodel,onnx模型路径请自定义,生成的kmodel在onnx模型同级目录下
python to_kmodel.py --target k230 --model ../../runs/train/exp2/weights/best.onnx --dataset ../../datasets/num_yolo/images/calc --input_width 320 --input_height 320 --ptq_option 0
cd ../..
4、在文件下面,发现 kmodel 表示转换成功
aaa@DESKTOP-OSN5BJK:~/yolov5/yolov5$ find . -name *.kmodel
./runs/train/exp2/weights/best.kmodel
四、部署实战
1、准备开发环境
在 Canaan K230 开发板上部署模型,首先要烧录镜像并安装 CanMV IDE。按照开发板的下载链接获取镜像并烧录,再安装好 CanMV IDE。
镜像文件下载地址:
https://github.com/kendryte/canmv_k230/releases/tag/PreRelease
CanMV IDE下载地址:
https://www.kendryte.com/zh/resource/ide,k230
2、拷贝文件
连接 IDE ,把转换好的模型和测试图片拷贝到开发板目录下(路径可自定义,代码中记得同步修改)

3、代码实现推理
图片推理:编写代码从本地读取图片,并进行格式转换。通过 YOLOv5 类初始化实例,设置好任务类型、推理模式、模型路径、标签列表等参数。例如:
from libs.YOLO import YOLOv5
import os,sys,gc
import ulab.numpy as np
import image
# 从本地读入图片,并实现HWC转CHW
def read_img(img_path):
img_data = image.Image(img_path)
img_data_rgb888=img_data.to_rgb888()
img_hwc=img_data_rgb888.to_numpy_ref()
shape=img_hwc.shape
img_tmp = img_hwc.reshape((shape[0] * shape[1], shape[2]))
img_tmp_trans = img_tmp.transpose()
img_res=img_tmp_trans.copy()
img_return=img_res.reshape((shape[2],shape[0],shape[1]))
return img_return,img_data_rgb888
if __name__=="__main__":
img_path="/data/test.jpg"
kmodel_path="/sdcard/examples/kmodel/best.kmodel"
labels = ["0","1","2","3"]
confidence_threshold = 0.5
nms_threshold=0.45
model_input_size=[320,320]
img,img_ori=read_img(img_path)
rgb888p_size=[img.shape[2],img.shape[1]]
# 初始化YOLOv5实例
yolo=YOLOv5(task_type="detect",mode="image",kmodel_path=kmodel_path,labels=labels,rgb888p_size=rgb888p_size,model_input_size=model_input_size,conf_thresh=confidence_threshold,nms_thresh=nms_threshold,max_boxes_num=50,debug_mode=0)
yolo.config_preprocess()
try:
res=yolo.run(img)
yolo.draw_result(res,img_ori)
gc.collect()
except Exception as e:
sys.print_exception(e)
finally:
yolo.deinit()
运行代码,可以看到已经识别到这张图片上所有的数字并框出来了。

视频推理:视频推理更具挑战性。初始化 PipeLine 和 YOLOv5 实例,在循环中逐帧获取视频图像进行推理,实时展示识别结果。比如设置好显示模式、分辨率、模型路径等参数后,通过不断循环执行推理和显示操作:
from libs.PipeLine import PipeLine, ScopedTiming
from libs.YOLO import YOLOv5
import os,sys,gc
import ulab.numpy as np
import image
if __name__=="__main__":
# 显示模式,默认"hdmi",可以选择"hdmi"和"lcd"
display_mode="lcd"
rgb888p_size=[800, 480]
if display_mode=="hdmi":
display_size=[1920,1080]
else:
display_size=[800,480]
kmodel_path="/sdcard/examples/kmodel/best.kmodel"
labels = ["0","1","2","3"]
confidence_threshold = 0.8
nms_threshold=0.45
model_input_size=[320,320]
# 初始化PipeLine
pl=PipeLine(rgb888p_size=rgb888p_size,display_size=display_size,display_mode=display_mode)
pl.create()
# 初始化YOLOv5实例
yolo=YOLOv5(task_type="detect",mode="video",kmodel_path=kmodel_path,labels=labels,rgb888p_size=rgb888p_size,model_input_size=model_input_size,display_size=display_size,conf_thresh=confidence_threshold,nms_thresh=nms_threshold,max_boxes_num=50,debug_mode=0)
yolo.config_preprocess()
try:
while True:
os.exitpoint()
with ScopedTiming("total",1):
# 逐帧推理
img=pl.get_frame()
res=yolo.run(img)
yolo.draw_result(res,pl.osd_img)
pl.show_image()
gc.collect()
except Exception as e:
sys.print_exception(e)
finally:
yolo.deinit()
pl.destroy()
这样,无论是静态图片还是动态视频中的数字,都能被精准识别。
通过 YOLOv5 和 Canaan K230 开发板实现数字识别,不仅是技术的有趣应用,也展示了人工智能在日常生活中的巨大潜力。感兴趣的小伙伴不妨动手试试,探索更多人工智能与实际应用结合的可能!
参考文档
官方资料:
https://www.kendryte.com/k230_canmv/zh/main/zh/example/ai/
Micropython AI手册:
https://www.kendryte.com/k230_canmv/zh/main/zh/api/aidemo_libs.html
视频教程:
https://www.bilibili.com/video/BV1xQ5YzoEW7
问答社区(增加标签YOLO):
https://www.kendryte.com/answer