在 CanMV K210 入门和 AI 视觉项目中,YOLO 手掌检测实验是一个很适合拆解的案例。它不是只验证摄像头、LCD 或模型文件是否能单独工作,而是把摄像头采集、图像预处理、KPU 模型推理、检测结果解析、LCD 框选显示和串口调试信息串成一个完整流程。通过这个实验,可以直观看到"摄像头画面如何经过 AI 模型,最终变成屏幕上的检测框"。
本实验使用 CanMV K210 运行 4.8_Palmar_detection.py。程序加载 /sd/hand_detect.kmodel 手掌检测模型,通过摄像头获取实时图像,将图像转换为 KPU 推理需要的格式,再调用 YOLO2 后处理函数获得手掌位置。如果检测到手掌,程序会在 LCD 画面中绘制绿色矩形框,并在串口打印检测结果,同时在左上角显示当前 FPS。
| 学习目标 | 说明 |
|---|---|
| 理解 AI 视觉流程 | 掌握摄像头采集、图像预处理、KPU 推理、后处理和显示输出之间的关系 |
| 掌握 KPU 模型加载 | 使用 KPU() 创建对象,并通过 load_kmodel() 加载手掌检测模型 |
| 理解 YOLO2 检测参数 | 认识 anchor、输入尺寸、阈值、NMS 和类别数量在检测中的作用 |
| 学会结果框选显示 | 使用 draw_rectangle() 在 LCD 图像上标出手掌区域 |
| 建立调试思路 | 从摄像头画面、模型路径、阈值、光照、目标距离和 FPS 排查问题 |
这个实验的重点不是单纯"识别到手掌",而是理解 K210 端侧 AI 检测的基本结构。摄像头负责输入,KPU 负责推理,YOLO2 后处理负责生成检测框,LCD 负责显示结果,串口负责输出调试信息。后续做人机交互、手势控制、智能拍照、机器人控制等项目时,都可以在这个流程上继续扩展。
文章目录
理论基础
YOLO 手掌检测属于目标检测任务。普通图像显示程序只负责把摄像头画面显示到 LCD 上,而目标检测程序还需要判断画面中有没有目标、目标位于哪里、目标框多大。对于本实验来说,目标类别只有一种,也就是手掌。程序不需要区分多类物体,只需要判断画面中是否出现手掌,并返回手掌所在区域的矩形框。
CanMV K210 内置 KPU 神经网络加速器,适合运行经过转换和部署的 kmodel 模型。程序中的 /sd/hand_detect.kmodel 就是本实验使用的手掌检测模型文件。摄像头采集到的图像不能直接交给模型使用,需要先调整为模型要求的输入格式。代码中创建了 od_img = image.Image(size=(320,256)),再把摄像头图像绘制到这张图上,并调用 pix_to_ai() 转换成 KPU 推理需要的数据格式。
YOLO2 检测需要初始化 anchor、输入尺寸、网络尺寸、特征层尺寸、置信度阈值、NMS 参数和类别数量。threshold=0.7 表示检测置信度阈值,阈值越高,误检可能减少,但漏检也可能增加;nms_value=0.3 用于抑制重叠检测框;classes=1 表示当前模型只检测一种类别。检测完成后,regionlayer_yolo2() 会返回检测结果列表,每个结果中包含检测框位置和尺寸等信息。
下面这张流程图从 AI 视觉链路角度展示本实验。摄像头采集图像后,程序把图像送入 KPU,KPU 输出检测结果,最后由 LCD 显示框选画面。
摄像头模块
sensor.snapshot()
图像缓存
QVGA 320x240
模型输入图像
od_img 320x256
AI 格式转换
pix_to_ai()
KPU 推理
run_with_output()
YOLO2 后处理
regionlayer_yolo2()
检测结果
手掌位置框
LCD 显示
draw_rectangle / display
串口调试
print(dect) / FPS
模型文件
/sd/hand_detect.kmodel
检测参数
anchor / threshold / nms
从这条链路可以看出,YOLO 手掌检测不是摄像头直接"看懂"手掌,而是摄像头先提供图像,程序再把图像转换为模型输入,KPU 完成神经网络推理,YOLO2 后处理再把模型输出转换成可用的检测框。LCD 上看到的绿色矩形框,就是程序根据检测结果绘制出来的可视化反馈。
本实验中的检测效果会受到光照、背景、手掌距离、模型文件、阈值和输入尺寸影响。目标太小、画面太暗、手掌被遮挡、模型路径错误或阈值设置过高,都可能导致检测不到手掌。因此 AI 视觉实验的调试重点不只是代码有没有运行,还要同时观察画面质量、模型加载状态和检测结果输出。
硬件设施
本实验围绕 CanMV K210、摄像头模块、LCD 显示屏、KPU 神经网络加速器和 SD 卡模型文件展开。代码没有使用按键、蜂鸣器、电机、传感器或外接 GPIO 控制模块,因此硬件重点集中在摄像头图像采集、LCD 显示、模型文件路径和运行内存状态上。
实验接线或模块安装可以先通过下面的位置补充实物图。重点检查摄像头排线是否插紧、LCD 是否正常显示、SD 卡中是否存在 hand_detect.kmodel 模型文件。
| 硬件 / 软件 | 作用 | 说明 |
|---|---|---|
| CanMV K210 开发板 | 实验运行平台 | 执行 MicroPython 程序,完成摄像头采集、KPU 推理和 LCD 显示 |
| 摄像头模块 | 图像输入设备 | 通过 sensor.snapshot() 获取实时画面 |
| LCD 显示屏 | 结果显示设备 | 显示摄像头画面、FPS 和手掌检测框 |
| KPU 神经网络加速器 | AI 推理核心 | 加载 kmodel 模型并执行端侧神经网络运算 |
| SD 卡或模型存储路径 | 模型文件来源 | 程序从 /sd/hand_detect.kmodel 加载手掌检测模型 |
sensor 模块 |
摄像头控制 | 完成摄像头复位、格式设置、分辨率设置和图像采集 |
lcd 模块 |
屏幕显示 | 初始化 LCD,并显示绘制后的图像 |
image 模块 |
图像处理 | 创建模型输入图像、绘制矩形框和文字 |
maix.KPU |
KPU 控制接口 | 加载模型、初始化 YOLO2、执行推理和获取检测结果 |
gc |
内存管理 | 主循环中回收内存,减少长时间运行时的内存压力 |
time |
帧率统计 | 使用 clock.fps() 计算当前运行帧率 |
摄像头、LCD 和模型文件是本实验最关键的三个检查点。摄像头异常会导致没有图像输入,LCD 异常会导致无法观察检测框,模型文件缺失会导致 KPU 无法加载模型。AI 视觉实验中,模型路径和硬件连接同样重要。
| 接口 / 资源 | 代码对象 | 对应硬件与说明 |
|---|---|---|
| 摄像头接口 | sensor.reset()、sensor.snapshot() |
初始化摄像头并持续获取图像帧 |
| LCD 接口 | lcd.init()、lcd.display(img) |
显示摄像头画面、FPS 和检测框 |
| 图像格式 | sensor.RGB565 |
摄像头输出 RGB565 图像 |
| 图像尺寸 | sensor.QVGA |
摄像头输出 320x240 画面 |
| 模型输入图像 | image.Image(size=(320,256)) |
创建 KPU 推理前的输入图像缓存 |
| KPU 模型文件 | /sd/hand_detect.kmodel |
手掌检测模型文件,需要放在指定路径 |
| YOLO 参数 | anchor、threshold、nms_value |
控制检测框生成和过滤效果 |
运行效果截图可以放在下面位置。程序正常运行后,LCD 会显示摄像头实时画面;当手掌进入画面时,手掌区域会被绿色矩形框选出来,左上角显示当前 FPS。
| 实验现象 | 正常表现 | 异常提示 |
|---|---|---|
| 程序启动 | LCD 初始化,摄像头开始输出画面 | 黑屏或花屏时检查 LCD、摄像头和固件环境 |
| 模型加载 | 串口输出 ready load model 后继续运行 |
停在模型加载处时检查 /sd/hand_detect.kmodel 是否存在 |
| 画面显示 | LCD 持续显示摄像头画面 | 没有画面时检查摄像头排线和 sensor 初始化 |
| 手掌靠近 | 画面中手掌区域出现绿色矩形框 | 无框选时检查光照、距离、阈值和模型文件 |
| 串口输出 | 检测到目标时输出 dect: 结果 |
没有输出不一定异常,可能当前画面未检测到手掌 |
| FPS 显示 | 左上角显示当前帧率 | 帧率过低时检查无关打印、模型复杂度和图像处理耗时 |
软件代码
本实验的软件部分以 4.8_Palmar_detection.py 为核心。程序导入 sensor、image、time、lcd、KPU 和 gc 模块,随后完成 LCD 初始化、摄像头初始化、模型输入图像创建、KPU 模型加载和 YOLO2 参数初始化。主循环中不断采集图像、执行 KPU 推理、获取检测框、绘制结果并刷新 LCD。
| 软件环境 | 作用 | 检查重点 |
|---|---|---|
| CanMV IDE | 编辑、运行和调试 K210 程序 | 能识别开发板串口,并能正常运行基础测试程序 |
| CanMV 固件 | 提供 sensor、lcd、image、maix.KPU 等模块 |
固件环境需要支持 KPU 模型推理 |
| 摄像头驱动 | 获取实时图像 | 能通过 sensor.snapshot() 得到画面 |
| LCD 显示驱动 | 显示识别结果 | 能通过 lcd.display(img) 显示图像 |
| 模型文件 | 手掌检测模型 | /sd/hand_detect.kmodel 文件名和路径必须与代码一致 |
| 串口终端 | 查看调试输出 | 能看到模型加载提示、检测结果和运行状态 |
python
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# ----湖南创乐博智能科技有限公司----
# 文件名:4.8_Palmar_detection.py
# 版本:V2.0
# author: zhulin
# 说明:CanMv K210 Yolo 手掌检测实验
#####################################################
import sensor, image, time, lcd
from maix import KPU
import gc
lcd.init() # 初始化LCD显示屏
sensor.reset() # 复位并初始化摄像头
sensor.set_pixformat(sensor.RGB565) # 设置摄像头输出格式为 RGB565
sensor.set_framesize(sensor.QVGA) # 设置摄像头输出大小为 QVGA (320x240)
sensor.skip_frames(time = 1000) # 等待摄像头稳定
clock = time.clock() # 创建一个clock对象,用来计算帧率
#检测模型需要320*256图输入,这里初始化一个image
od_img = image.Image(size=(320,256))
anchor = (0.8125, 0.4556, 1.1328, 1.2667, 1.8594, 1.4889, 1.4844, 2.2000, 2.6484, 2.9333)
# 创建一个kpu对象,用于人脸检测
kpu = KPU()
print("ready load model")
# 加载模型
kpu.load_kmodel("/sd/hand_detect.kmodel")
# yolo2初始化
kpu.init_yolo2(anchor, anchor_num=5, img_w=320, img_h=240, net_w=320 , net_h=256 ,layer_w=10 ,layer_h=8, threshold=0.7, nms_value=0.3, classes=1)
while True:
gc.collect()
clock.tick() # 更新计算帧率的clock
img = sensor.snapshot() # 拍照,获取一张图像
a = od_img.draw_image(img, 0,0) # 将img图像写到od_img图像的坐标(0,0)位置处
od_img.pix_to_ai() # 对rgb565的image生成ai运算需要的r8g8b8格式存储
kpu.run_with_output(od_img) # 对输入图像进行kpu运算
dect = kpu.regionlayer_yolo2() # yolo2后处理
fps = clock.fps() # 获取帧率
# 画出结果
if len(dect) > 0:
print("dect:",dect)
for l in dect :
a = img.draw_rectangle(l[0],l[1],l[2],l[3], color=(0, 255, 0))
a = img.draw_string(0, 0, "%2.1ffps" %(fps), color=(0, 60, 128), scale=2.0)
lcd.display(img)
# 创建的kpu对象去初始化,释放模型内存
kpu.deinit()
这段程序可以分成初始化、模型配置、循环推理和结果显示几个层级。初始化部分负责准备 LCD、摄像头和帧率统计对象;模型配置部分负责创建 KPU 对象、加载模型并初始化 YOLO2 参数;循环推理部分负责采集图像、转换 AI 输入格式、运行模型和获取检测结果;结果显示部分负责绘制检测框、显示 FPS 并刷新 LCD。
| 函数 / 代码部分 | 功能 | 对应现象 |
|---|---|---|
lcd.init() |
初始化 LCD 显示屏 | 屏幕准备显示摄像头画面 |
sensor.reset() |
初始化摄像头 | 摄像头进入可采集状态 |
sensor.set_pixformat(sensor.RGB565) |
设置图像格式 | 摄像头输出 RGB565 彩色图像 |
sensor.set_framesize(sensor.QVGA) |
设置图像尺寸 | 摄像头输出 320x240 图像 |
sensor.skip_frames(time=1000) |
等待摄像头稳定 | 减少启动初期曝光不稳定 |
image.Image(size=(320,256)) |
创建模型输入图像 | 为 KPU 推理准备 320x256 输入缓存 |
KPU() |
创建 KPU 对象 | 准备加载和运行神经网络模型 |
load_kmodel() |
加载手掌检测模型 | 从 /sd/hand_detect.kmodel 读取模型 |
init_yolo2() |
初始化 YOLO2 后处理参数 | 设置 anchor、阈值、NMS 和类别数量 |
sensor.snapshot() |
获取摄像头图像 | LCD 显示实时画面来源 |
draw_image() |
将摄像头图像写入模型输入图像 | 把 320x240 图像放入 320x256 输入区域 |
pix_to_ai() |
转换为 AI 运算格式 | 为 KPU 推理准备数据 |
run_with_output() |
执行 KPU 推理 | 模型开始检测手掌 |
regionlayer_yolo2() |
获取 YOLO2 检测结果 | 返回手掌检测框列表 |
draw_rectangle() |
绘制检测框 | 手掌区域出现绿色矩形框 |
draw_string() |
绘制 FPS 文本 | 左上角显示帧率 |
lcd.display(img) |
刷新 LCD | 屏幕显示最终图像 |
需要注意的是,代码末尾的 kpu.deinit() 位于 while True 无限循环之后,正常情况下不会执行。实际调试时,如果需要退出后释放 KPU 资源,可以在后续优化版本中加入 try...finally 结构。不过本实验作为基础示例,重点仍然是模型加载、实时检测和显示框选结果。
主循环中使用 gc.collect() 做内存回收,可以降低图像循环处理时的内存压力。clock.tick() 和 clock.fps() 用于计算当前帧率,方便观察模型推理速度。检测结果只有在 len(dect) > 0 时才会打印和绘制,因此串口没有持续输出不一定是异常,可能只是当前画面没有达到检测阈值。
扩展应用
YOLO 手掌检测实验常见问题集中在摄像头画面、模型路径、输入尺寸、检测阈值、光照环境和目标距离几个方面。排查时应先确认摄像头和 LCD 是否正常,再检查模型文件是否能加载,最后再调整检测阈值和拍摄环境。
| 问题现象 | 可能原因 | 处理思路 |
|---|---|---|
| 程序无法运行 | 固件不支持相关模块、模型文件缺失、代码文件未正确运行 | 确认 CanMV 固件支持 sensor、lcd 和 KPU,检查报错行号 |
| LCD 没有画面 | 摄像头初始化失败、LCD 初始化异常、摄像头排线松动 | 先运行摄像头显示基础例程,确认摄像头和 LCD 均正常 |
| 模型加载失败 | /sd/hand_detect.kmodel 文件不存在或路径不一致 |
将模型文件放到 SD 卡根目录,并核对文件名大小写 |
| 检测不到手掌 | 置信度阈值过高、手掌太小、光照不足、角度不合适 | 增强光照,让手掌靠近摄像头,必要时适当降低 threshold |
| 检测结果不稳定 | 背景复杂、手掌移动过快、模型对当前场景适应不足 | 固定摄像头位置,使用纯色背景,保持手掌完整进入画面 |
| 检测框位置异常 | 图像输入尺寸、模型尺寸或绘制坐标不匹配 | 核对 img_w、img_h、net_w、net_h 和 od_img 尺寸 |
| FPS 较低 | 模型推理耗时、串口打印过多、图像处理复杂 | 减少无关打印,保持 QVGA 输入,避免增加额外复杂绘制 |
串口没有 dect 输出 |
当前没有检测到目标 | 观察 LCD 画面,确认手掌是否清晰、完整、靠近摄像头 |
| 画面偏暗或颜色异常 | 环境光不足、摄像头曝光未稳定 | 增加光照,重新上电或延长 skip_frames() 稳定时间 |
YOLO 手掌检测实验的扩展价值在于把"画面中的手掌"变成程序可以使用的输入事件。普通摄像头显示只能看到画面,目标检测则可以获得目标位置框。这个位置框可以继续用于手势交互、目标跟踪、云台控制、智能拍照和人机交互原型。
| 应用场景 | 实现思路 | 可扩展能力 |
|---|---|---|
| 手势交互入口 | 检测到手掌后触发菜单、确认或切换动作 | 可继续加入按键、LCD 菜单或蜂鸣器反馈 |
| 智能拍照 | 检测到手掌并保持一段时间后自动拍照 | 可扩展为倒计时拍摄、识别触发拍摄 |
| 摄像头云台控制 | 根据手掌框中心位置判断偏左或偏右 | 后续可接入舵机或步进电机实现目标跟随 |
| 机器人控制 | 将手掌检测结果作为启动、停止或方向提示 | 可结合电机驱动实现视觉交互控制 |
| 课堂视觉演示 | 在 LCD 上展示检测框和 FPS | 适合讲解 AI 模型推理、阈值和边缘计算 |
| 安全区域检测 | 判断手掌是否进入画面指定区域 | 可扩展为区域触发、接近提示或报警 |
| 多模块联动 | 检测到手掌后触发 LED、蜂鸣器或激光提示 | 可把 AI 结果转换成外设动作 |
从工程角度看,这段代码已经具备 AI 视觉项目的基本骨架。摄像头采集负责输入,KPU 推理负责识别,YOLO2 后处理负责提取位置框,LCD 和串口负责输出反馈。后续扩展时,可以把 dect 结果继续传给状态判断函数,例如判断手掌是否在画面中央、检测框是否足够大、是否连续多帧出现,再根据判断结果触发其他硬件动作。
总结
本实验通过 CanMV K210 完成了 YOLO 手掌检测的基础验证,核心内容包括摄像头初始化、LCD 显示、KPU 模型加载、YOLO2 参数初始化、图像格式转换、模型推理、检测框绘制和 FPS 显示。程序把摄像头采集到的真实画面转换成 AI 检测结果,并用绿色矩形框把手掌区域显示出来,展示了 K210 端侧视觉识别的基本流程。
AI 视觉实验的调试重点和普通 GPIO 实验不同。除了检查代码是否运行,还要检查模型文件路径、摄像头画面质量、目标大小、光照条件、检测阈值和模型输入尺寸。掌握这套流程后,后续可以继续扩展手势交互、智能拍照、摄像头云台、机器人控制、声光提示和多模块联动等项目,让视觉识别结果真正参与智能硬件控制。