【花雕动手做】CanMV K230 AI 视觉识别模块之物体计数
项目测试实验代码
- #【花雕动手做】CanMV K230 AI 视觉识别模块之物体计数
-
- import time
- import os
- import sys
- from media.sensor import Sensor
- from media.display import Display
- from media.media import MediaManager
-
- # 常量定义 / Constants definition
- SCREEN_WIDTH = 640 # 屏幕宽度 / Screen width
- SCREEN_HEIGHT = 480 # 屏幕高度 / Screen height
-
- # 待检测物体的LAB色彩空间阈值 / LAB color space thresholds
- # 这里写的阈值是配套工具中【金币生成器】生成的金币的颜色
- # Format: (L_min, L_max, A_min, A_max, B_min, B_max)
- TRACK_THRESHOLD = [(0, 100, -7, 127, 10, 83)]
- # 这个阈值范围专门针对金币生成器产生的金币颜色进行优化
- # 参数说明:
- # L: 亮度 (0-100),这里范围很宽,适应不同光照条件
- # A: 红绿色度 (-128到127),-7到127表示偏红色
- # B: 黄蓝色度 (-128到127),10到83表示偏黄色
-
- # 文字显示参数 / Text display parameters
- FONT_SIZE = 25 # 字体大小 / Font size
- TEXT_COLOR = (233, 233, 233) # 白色 / White (接近纯白的浅灰色)
-
- def init_camera():
- """
- 初始化并配置摄像头
- Initialize and configure the camera
-
- 返回:
- sensor: 初始化后的传感器对象 / Initialized sensor object
- """
- # sensor = Sensor(width=1280,height=960) # 备用高分辨率配置
- sensor = Sensor() # 创建传感器实例
- sensor.reset() # 重置传感器到默认状态
- # 设置图像分辨率为640x480 / Set image resolution to 640x480
- sensor.set_framesize(width=SCREEN_WIDTH, height=SCREEN_HEIGHT)
- # 设置像素格式为RGB565 / Set pixel format to RGB565 (16位彩色)
- sensor.set_pixformat(Sensor.RGB565)
- return sensor
-
- def init_display():
- """
- 初始化显示设备
- Initialize display device
- """
- # 初始化3.5寸MIPI屏幕和IDE显示
- # Initialize 3.5-inch MIPI screen and IDE display
- # ST7701: 显示屏驱动芯片型号
- # to_ide=True: 同时输出到IDE,便于调试
- Display.init(Display.ST7701, width=SCREEN_WIDTH, height=SCREEN_HEIGHT, to_ide=True)
- # 初始化媒体管理器,分配图像处理资源
- MediaManager.init()
-
- def process_frame(img, threshold):
- """
- 处理单帧图像,检测并标记目标物体
- Process single frame, detect and mark target objects
-
- Args:
- img: 输入图像 / Input image
- threshold: 颜色阈值 / Color threshold
-
- Returns:
- blobs: 检测到的物体列表 / List of detected objects
- """
- # 在图像中查找符合颜色阈值的色块
- # find_blobs函数返回满足条件的连通区域列表
- blobs = img.find_blobs([threshold])
- # 默认参数:自动合并相邻色块,无最小面积限制
-
- # 如果检测到色块,进行可视化标记
- if blobs:
- for blob in blobs:
- # 绘制矩形框标记物体边界 / Draw rectangle around object boundary
- # blob[0:4] 包含 (x, y, width, height)
- img.draw_rectangle(blob[0:4])
-
- # 在物体中心绘制十字准星 / Draw cross at object center
- # blob[5], blob[6] 是中心点坐标 (cx, cy)
- img.draw_cross(blob[5], blob[6])
-
- return blobs # 返回检测到的物体列表
-
- def draw_info(img, fps, num_objects):
- """
- 在图像上绘制信息
- Draw information on image
-
- Args:
- img: 输入图像 / Input image
- fps: 帧率 / Frames per second
- num_objects: 检测到的物体数量 / Number of detected objects
- """
- # 构建信息文本字符串
- info_text = f'FPS: {fps:.3f} Num: {num_objects}'
-
- # 在图像左上角绘制信息文本
- # 参数说明:
- # 0, 0: 文本起始坐标 (x, y)
- # FONT_SIZE: 字体大小
- # info_text: 要显示的文本内容
- # color=TEXT_COLOR: 文本颜色 (白色)
- img.draw_string_advanced(0, 0, FONT_SIZE, info_text, color=TEXT_COLOR)
-
- def main():
- """
- 主程序入口
- Main program entry
- """
- # 初始化设备 / Initialize devices
- sensor = init_camera() # 初始化摄像头
- init_display() # 初始化显示设备
- sensor.run() # 启动摄像头开始采集图像
-
- # 创建时钟对象用于FPS计算 / Create clock object for FPS calculation
- clock = time.clock()
-
- try:
- # 主循环 - 实时物体计数
- while True:
- # 更新时钟,记录当前时间点
- clock.tick()
-
- # 捕获图像 / Capture image
- img = sensor.snapshot() # 从摄像头获取一帧图像
-
- # 处理图像,检测目标物体
- # 使用预设的颜色阈值检测金币或其他目标物体
- blobs = process_frame(img, TRACK_THRESHOLD[0])
-
- # 在图像上显示帧率和物体数量信息
- draw_info(img, clock.fps(), len(blobs))
-
- # 显示处理后的图像 / Show image
- Display.show_image(img)
-
- # 在控制台打印FPS信息,用于性能监控
- print(f"FPS: {clock.fps():.3f}")
-
- except KeyboardInterrupt:
- # 处理用户中断 (Ctrl+C)
- print("Program terminated by user")
- except Exception as e:
- # 处理其他异常
- print(f"Error occurred: {str(e)}")
- finally:
- # 清理资源 / Cleanup resources (无论是否异常都会执行)
- sensor.deinit() # 反初始化传感器,释放硬件资源
- Display.deinit() # 关闭显示设备
-
- # 程序入口点
- if __name__ == "__main__":
- main()
复制代码
代码解读:
程序总体功能
这是一个基于颜色特征的实时物体计数系统,专门用于检测和统计画面中特定颜色(如金币)的物体数量。
系统架构设计
核心处理流程
text
图像采集 → 颜色空间转换 → 阈值分割 → 连通域分析 → 物体标记 → 数量统计 → 结果显示
1. 模块化架构
python
- # 硬件抽象层
-
- from media.sensor import Sensor # 摄像头硬件控制
-
- from media.display import Display # 显示输出控制
-
- from media.media import MediaManager # 媒体资源管理
-
-
-
- # 应用逻辑层
-
- init_camera() # 摄像头初始化
-
- init_display() # 显示初始化
-
- process_frame() # 图像处理核心
-
- draw_info() # 信息可视化
复制代码
核心技术组件详解
1. LAB颜色空间检测系统
颜色阈值设计
python
- TRACK_THRESHOLD = [(0, 100, -7, 127, 10, 83)]
复制代码
LAB颜色空间参数分析:
L通道 (亮度): 0-100
覆盖全部亮度范围,适应各种光照条件
从完全黑暗到最亮都能检测
A通道 (红-绿): -7 到 127
负值偏绿,正值偏红
-7 起点略偏红,127 强红色调
B通道 (黄-蓝): 10 到 83
负值偏蓝,正值偏黄
10-83 明确的金黄色调范围
阈值设计策略:
宽范围的L值确保光照鲁棒性
A、B通道精确锁定金黄色特征
专门针对"金币生成器"工具优化
2. 色块检测引擎
核心检测算法
python
- blobs = img.find_blobs([threshold])
复制代码
算法内部工作机制:
颜色空间转换: RGB → LAB(自动处理)
阈值分割: 根据LAB范围创建二值掩膜
连通域标记: 识别相连的像素区域
特征提取: 计算每个区域的位置、大小、中心点
色块数据结构
python
- blob = [x, y, width, height, cx, cy]
-
- # x, y: 边界框左上角坐标
-
- # width, height: 边界框尺寸
-
- # cx, cy: 区域中心点坐标
复制代码
3. 可视化系统
物体标记策略
python
- img.draw_rectangle(blob[0:4]) # 边界框
-
- img.draw_cross(blob[5], blob[6]) # 中心十字
复制代码
视觉设计原理:
矩形框: 快速识别物体空间范围
十字准星: 精确定位物体中心
默认颜色: 自动选择高对比度颜色,确保可见性
信息显示设计
python
- info_text = f'FPS: {fps:.3f} Num: {num_objects}'
复制代码
信息层级:
性能指标: 帧率(3位小数精度)
业务数据: 物体数量(实时更新)
布局优化: 左上角固定位置,避免遮挡主要内容
性能优化分析
1. 分辨率策略
python
- SCREEN_WIDTH = 640
-
- SCREEN_HEIGHT = 480 # 307,200像素
复制代码
性能权衡分析:
计算复杂度: 相比1280×960(1,228,800像素)减少75%
检测精度: 480p分辨率对物体计数足够精确
实时性: 确保在高帧率下稳定运行
2. 算法效率优化
python
- # 默认参数优化
-
- blobs = img.find_blobs([threshold])
-
- # 等效于:
-
- # blobs = img.find_blobs([threshold], merge=True, area_threshold=0, pixels_threshold=0)
复制代码
参数默认值优势:
merge=True: 自动合并相邻区域,减少碎片化
无面积限制: 检测所有大小的目标
简化配置: 用户只需关注颜色阈值
3. 实时性能监控
python
- clock = time.clock()
-
- clock.tick() # 记录时间点
-
- fps = clock.fps() # 计算帧率
复制代码
监控机制:
高精度计时: 微秒级时间测量
持续跟踪: 每帧更新性能数据
双重输出: 屏幕显示 + 控制台日志
系统工作流程
完整处理流水线
text
1. 硬件初始化
↓
2. 图像采集 (sensor.snapshot())
↓
3. 颜色空间转换 (RGB→LAB)
↓
4. 阈值分割 (LAB范围过滤)
↓
5. 连通域分析 (区域标记)
↓
6. 特征计算 (位置、大小、中心)
↓
7. 可视化渲染 (边框 + 十字)
↓
8. 信息叠加 (帧率 + 计数)
↓
9. 结果显示 (Display.show_image)
物体计数逻辑
python
- # 检测阶段
-
- blobs = img.find_blobs([threshold])
-
-
-
- # 统计阶段
-
- object_count = len(blobs) # 直接使用列表长度作为计数
-
-
-
- # 显示阶段
-
- draw_info(img, fps, object_count)
复制代码
健壮性设计
异常处理机制
python
- try:
-
- # 主业务逻辑
-
- while True:
-
- # 实时处理循环
-
- except KeyboardInterrupt:
-
- # 用户主动中断
-
- print("Program terminated by user")
-
- except Exception as e:
-
- # 其他异常捕获
-
- print(f"Error occurred: {str(e)}")
-
- finally:
-
- # 资源清理保障
-
- sensor.deinit()
-
- Display.deinit()
复制代码
|