57浏览
查看: 57|回复: 4

[项目] 【花雕动手做】CanMV K230 AI 视觉识别模块之物体计数

[复制链接]
【花雕动手做】CanMV K230 AI 视觉识别模块之物体计数图1

什么是 CanMV K230?
CanMV K230是一款高性价比的RISC-V边缘AI平台,凭借低功耗、强视觉处理能力和开放的开发生态,成为嵌入式AI开发的理想选择,尤其适合需要快速部署视觉与AI功能的创客、中小企业及教育场景。CanMV 是一套 AI 视觉开发平台,K230 是其核心芯片。该模块结合了图像采集、AI推理、边缘计算等能力,适合嵌入式视觉应用开发。

CanMV:类似 OpenMV 的图像处理框架,支持 Python 编程,简化视觉识别开发流程。
K230 芯片:嘉楠科技推出的 AIoT SoC,采用 RISC-V 架构,内置第三代 KPU(AI加速单元),算力高达 6 TOPS,性能是 K210 的 13.7 倍。


【花雕动手做】CanMV K230 AI 视觉识别模块之物体计数图2

驴友花雕  高级技神
 楼主|

发表于 3 天前

【花雕动手做】CanMV K230 AI 视觉识别模块之物体计数

知识点
物体计数(Object Counting)指利用传感器或计算机视觉技术,对图像、视频或真实场景中“有多少个目标”进行自动统计的过程。是计算机视觉领域的一项重要任务,旨在确定图像或视频中特定物体的数量。以下是一些常见的物体计数方法:

1、基于检测的计数方法:该方法依赖于能够定位图像中物体实例的视觉检测器。先使用目标检测算法,如 YOLO、Faster R-CNN 等,对图像中的物体进行检测,每个检测框对应一个物体,然后统计检测框的数量,从而得到物体的计数结果。这种方法的优点是直观且对于单个物体检测精度较高,但需要为不同的物体训练单独的检测器,并且在标注数据稀少的情况下,检测效果可能会受到影响。

2、基于回归的计数方法:这类方法旨在学习从全局图像特征到一个标量(即物体数量)的映射,或者从密集图像特征到密度图的映射。例如,通过训练一个神经网络,输入整幅图像,输出图像中物体的数量。它避免了解决复杂的检测问题,在计数高度重叠的实例上可能取得更好的效果,但缺点是缺乏对物体具体位置的定位信息。

3、基于聚类的计数方法:对于一些没有明显物体边界的情况,如细胞计数等,可以采用聚类的方法。首先提取图像中物体的特征,然后根据这些特征将相似的物体聚合成不同的类,每个类代表一个物体,最后统计类的数量得到物体计数。
通用匹配网络(GMN)计数方法:这是一种能够以类别无关的方式计数任何物体的模型架构。它将计数问题重新定义为匹配问题,利用计数任务中天然存在的图像自相似性特性,通过在同一张图像内匹配与示例块相似的 patches 来进行计数。GMN 可以充分利用大量为视频目标追踪标注的数据进行训练,并且引入了适配器模块,只需使用少量标注示例,就能对模型进行专业化微调,实现少样本学习。

【花雕动手做】CanMV K230 AI 视觉识别模块之物体计数图1

【花雕动手做】CanMV K230 AI 视觉识别模块之物体计数图2

【花雕动手做】CanMV K230 AI 视觉识别模块之物体计数图3

【花雕动手做】CanMV K230 AI 视觉识别模块之物体计数图4

回复

使用道具 举报

驴友花雕  高级技神
 楼主|

发表于 3 天前

【花雕动手做】CanMV K230 AI 视觉识别模块之物体计数

【花雕动手做】CanMV K230 AI 视觉识别模块之物体计数图2

【花雕动手做】CanMV K230 AI 视觉识别模块之物体计数图1

【花雕动手做】CanMV K230 AI 视觉识别模块之物体计数图3

【花雕动手做】CanMV K230 AI 视觉识别模块之物体计数图4

【花雕动手做】CanMV K230 AI 视觉识别模块之物体计数图5
回复

使用道具 举报

驴友花雕  高级技神
 楼主|

发表于 3 天前

【花雕动手做】CanMV K230 AI 视觉识别模块之物体计数

【花雕动手做】CanMV K230 AI 视觉识别模块之物体计数
项目测试实验代码

  1. #【花雕动手做】CanMV K230 AI 视觉识别模块之物体计数
  2. import time
  3. import os
  4. import sys
  5. from media.sensor import Sensor
  6. from media.display import Display
  7. from media.media import MediaManager
  8. # 常量定义 / Constants definition
  9. SCREEN_WIDTH = 640    # 屏幕宽度 / Screen width
  10. SCREEN_HEIGHT = 480   # 屏幕高度 / Screen height
  11. # 待检测物体的LAB色彩空间阈值 / LAB color space thresholds
  12. # 这里写的阈值是配套工具中【金币生成器】生成的金币的颜色
  13. # Format: (L_min, L_max, A_min, A_max, B_min, B_max)
  14. TRACK_THRESHOLD = [(0, 100, -7, 127, 10, 83)]
  15. # 这个阈值范围专门针对金币生成器产生的金币颜色进行优化
  16. # 参数说明:
  17. # L: 亮度 (0-100),这里范围很宽,适应不同光照条件
  18. # A: 红绿色度 (-128到127),-7到127表示偏红色
  19. # B: 黄蓝色度 (-128到127),10到83表示偏黄色
  20. # 文字显示参数 / Text display parameters
  21. FONT_SIZE = 25                    # 字体大小 / Font size
  22. TEXT_COLOR = (233, 233, 233)     # 白色 / White (接近纯白的浅灰色)
  23. def init_camera():
  24.     """
  25.     初始化并配置摄像头
  26.     Initialize and configure the camera
  27.    
  28.     返回:
  29.         sensor: 初始化后的传感器对象 / Initialized sensor object
  30.     """
  31.     # sensor = Sensor(width=1280,height=960)  # 备用高分辨率配置
  32.     sensor = Sensor()              # 创建传感器实例
  33.     sensor.reset()                 # 重置传感器到默认状态
  34.     # 设置图像分辨率为640x480 / Set image resolution to 640x480
  35.     sensor.set_framesize(width=SCREEN_WIDTH, height=SCREEN_HEIGHT)
  36.     # 设置像素格式为RGB565 / Set pixel format to RGB565 (16位彩色)
  37.     sensor.set_pixformat(Sensor.RGB565)
  38.     return sensor
  39. def init_display():
  40.     """
  41.     初始化显示设备
  42.     Initialize display device
  43.     """
  44.     # 初始化3.5寸MIPI屏幕和IDE显示
  45.     # Initialize 3.5-inch MIPI screen and IDE display
  46.     # ST7701: 显示屏驱动芯片型号
  47.     # to_ide=True: 同时输出到IDE,便于调试
  48.     Display.init(Display.ST7701, width=SCREEN_WIDTH, height=SCREEN_HEIGHT, to_ide=True)
  49.     # 初始化媒体管理器,分配图像处理资源
  50.     MediaManager.init()
  51. def process_frame(img, threshold):
  52.     """
  53.     处理单帧图像,检测并标记目标物体
  54.     Process single frame, detect and mark target objects
  55.     Args:
  56.         img: 输入图像 / Input image
  57.         threshold: 颜色阈值 / Color threshold
  58.     Returns:
  59.         blobs: 检测到的物体列表 / List of detected objects
  60.     """
  61.     # 在图像中查找符合颜色阈值的色块
  62.     # find_blobs函数返回满足条件的连通区域列表
  63.     blobs = img.find_blobs([threshold])
  64.     # 默认参数:自动合并相邻色块,无最小面积限制
  65.     # 如果检测到色块,进行可视化标记
  66.     if blobs:
  67.         for blob in blobs:
  68.             # 绘制矩形框标记物体边界 / Draw rectangle around object boundary
  69.             # blob[0:4] 包含 (x, y, width, height)
  70.             img.draw_rectangle(blob[0:4])
  71.             
  72.             # 在物体中心绘制十字准星 / Draw cross at object center
  73.             # blob[5], blob[6] 是中心点坐标 (cx, cy)
  74.             img.draw_cross(blob[5], blob[6])
  75.     return blobs  # 返回检测到的物体列表
  76. def draw_info(img, fps, num_objects):
  77.     """
  78.     在图像上绘制信息
  79.     Draw information on image
  80.     Args:
  81.         img: 输入图像 / Input image
  82.         fps: 帧率 / Frames per second
  83.         num_objects: 检测到的物体数量 / Number of detected objects
  84.     """
  85.     # 构建信息文本字符串
  86.     info_text = f'FPS: {fps:.3f}       Num: {num_objects}'
  87.    
  88.     # 在图像左上角绘制信息文本
  89.     # 参数说明:
  90.     # 0, 0: 文本起始坐标 (x, y)
  91.     # FONT_SIZE: 字体大小
  92.     # info_text: 要显示的文本内容
  93.     # color=TEXT_COLOR: 文本颜色 (白色)
  94.     img.draw_string_advanced(0, 0, FONT_SIZE, info_text, color=TEXT_COLOR)
  95. def main():
  96.     """
  97.     主程序入口
  98.     Main program entry
  99.     """
  100.     # 初始化设备 / Initialize devices
  101.     sensor = init_camera()  # 初始化摄像头
  102.     init_display()          # 初始化显示设备
  103.     sensor.run()            # 启动摄像头开始采集图像
  104.     # 创建时钟对象用于FPS计算 / Create clock object for FPS calculation
  105.     clock = time.clock()
  106.     try:
  107.         # 主循环 - 实时物体计数
  108.         while True:
  109.             # 更新时钟,记录当前时间点
  110.             clock.tick()
  111.             # 捕获图像 / Capture image
  112.             img = sensor.snapshot()  # 从摄像头获取一帧图像
  113.             # 处理图像,检测目标物体
  114.             # 使用预设的颜色阈值检测金币或其他目标物体
  115.             blobs = process_frame(img, TRACK_THRESHOLD[0])
  116.             # 在图像上显示帧率和物体数量信息
  117.             draw_info(img, clock.fps(), len(blobs))
  118.             # 显示处理后的图像 / Show image
  119.             Display.show_image(img)
  120.             # 在控制台打印FPS信息,用于性能监控
  121.             print(f"FPS: {clock.fps():.3f}")
  122.     except KeyboardInterrupt:
  123.         # 处理用户中断 (Ctrl+C)
  124.         print("Program terminated by user")
  125.     except Exception as e:
  126.         # 处理其他异常
  127.         print(f"Error occurred: {str(e)}")
  128.     finally:
  129.         # 清理资源 / Cleanup resources (无论是否异常都会执行)
  130.         sensor.deinit()     # 反初始化传感器,释放硬件资源
  131.         Display.deinit()    # 关闭显示设备
  132. # 程序入口点
  133. if __name__ == "__main__":
  134.     main()
复制代码

代码解读:

程序总体功能
这是一个基于颜色特征的实时物体计数系统,专门用于检测和统计画面中特定颜色(如金币)的物体数量。

系统架构设计
核心处理流程
text
图像采集 → 颜色空间转换 → 阈值分割 → 连通域分析 → 物体标记 → 数量统计 → 结果显示
1. 模块化架构
python
  1. # 硬件抽象层
  2. from media.sensor import Sensor      # 摄像头硬件控制
  3. from media.display import Display    # 显示输出控制  
  4. from media.media import MediaManager # 媒体资源管理
  5. # 应用逻辑层
  6. init_camera()    # 摄像头初始化
  7. init_display()   # 显示初始化
  8. process_frame()  # 图像处理核心
  9. draw_info()      # 信息可视化
复制代码

核心技术组件详解
1. LAB颜色空间检测系统
颜色阈值设计
python
  1. 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
  1. blobs = img.find_blobs([threshold])
复制代码

算法内部工作机制:
颜色空间转换: RGB → LAB(自动处理)
阈值分割: 根据LAB范围创建二值掩膜
连通域标记: 识别相连的像素区域
特征提取: 计算每个区域的位置、大小、中心点
色块数据结构
python
  1. blob = [x, y, width, height, cx, cy]
  2. # x, y: 边界框左上角坐标
  3. # width, height: 边界框尺寸  
  4. # cx, cy: 区域中心点坐标
复制代码

3. 可视化系统
物体标记策略
python
  1. img.draw_rectangle(blob[0:4])      # 边界框
  2. img.draw_cross(blob[5], blob[6])   # 中心十字
复制代码

视觉设计原理:
矩形框: 快速识别物体空间范围
十字准星: 精确定位物体中心
默认颜色: 自动选择高对比度颜色,确保可见性
信息显示设计
python
  1. info_text = f'FPS: {fps:.3f}       Num: {num_objects}'
复制代码

信息层级:
性能指标: 帧率(3位小数精度)
业务数据: 物体数量(实时更新)
布局优化: 左上角固定位置,避免遮挡主要内容

性能优化分析
1. 分辨率策略
python
  1. SCREEN_WIDTH = 640
  2. SCREEN_HEIGHT = 480  # 307,200像素
复制代码

性能权衡分析:
计算复杂度: 相比1280×960(1,228,800像素)减少75%
检测精度: 480p分辨率对物体计数足够精确
实时性: 确保在高帧率下稳定运行

2. 算法效率优化
python
  1. # 默认参数优化
  2. blobs = img.find_blobs([threshold])
  3. # 等效于:
  4. # blobs = img.find_blobs([threshold], merge=True, area_threshold=0, pixels_threshold=0)
复制代码

参数默认值优势:
merge=True: 自动合并相邻区域,减少碎片化
无面积限制: 检测所有大小的目标
简化配置: 用户只需关注颜色阈值

3. 实时性能监控
python
  1. clock = time.clock()
  2. clock.tick()    # 记录时间点
  3. fps = clock.fps() # 计算帧率
复制代码

监控机制:
高精度计时: 微秒级时间测量
持续跟踪: 每帧更新性能数据
双重输出: 屏幕显示 + 控制台日志

系统工作流程
完整处理流水线
text
1. 硬件初始化
   ↓
2. 图像采集 (sensor.snapshot())
   ↓  
3. 颜色空间转换 (RGB→LAB)
   ↓
4. 阈值分割 (LAB范围过滤)
   ↓
5. 连通域分析 (区域标记)
   ↓
6. 特征计算 (位置、大小、中心)
   ↓
7. 可视化渲染 (边框 + 十字)
   ↓
8. 信息叠加 (帧率 + 计数)
   ↓
9. 结果显示 (Display.show_image)
物体计数逻辑
python
  1. # 检测阶段
  2. blobs = img.find_blobs([threshold])
  3. # 统计阶段  
  4. object_count = len(blobs)  # 直接使用列表长度作为计数
  5. # 显示阶段
  6. draw_info(img, fps, object_count)
复制代码

健壮性设计
异常处理机制
python
  1. try:
  2.     # 主业务逻辑
  3.     while True:
  4.         # 实时处理循环
  5. except KeyboardInterrupt:
  6.     # 用户主动中断
  7.     print("Program terminated by user")
  8. except Exception as e:
  9.     # 其他异常捕获
  10.     print(f"Error occurred: {str(e)}")
  11. finally:
  12.     # 资源清理保障
  13.     sensor.deinit()
  14.     Display.deinit()
复制代码


回复

使用道具 举报

驴友花雕  高级技神
 楼主|

发表于 3 天前

【花雕动手做】CanMV K230 AI 视觉识别模块之物体计数

实际测试的范本

【花雕动手做】CanMV K230 AI 视觉识别模块之物体计数图1

实验串口返回情况

【花雕动手做】CanMV K230 AI 视觉识别模块之物体计数图2

实验场景图


【花雕动手做】CanMV K230 AI 视觉识别模块之物体计数图3

【花雕动手做】CanMV K230 AI 视觉识别模块之物体计数图4

【花雕动手做】CanMV K230 AI 视觉识别模块之物体计数图5

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

为本项目制作心愿单
购买心愿单
心愿单 编辑
[[wsData.name]]

硬件清单

  • [[d.name]]
btnicon
我也要做!
点击进入购买页面
上海智位机器人股份有限公司 沪ICP备09038501号-4 备案 沪公网安备31011502402448

© 2013-2025 Comsenz Inc. Powered by Discuz! X3.4 Licensed

mail