必应搜索引擎网站最快新闻资讯在哪看
学习目标:立创·庐山派K230CanMV开发板的进阶学习——特征检测
学习内容:特征检测
1. 本节介绍
📝 学习内容:本节将学习图像特征检测的核心技术,包括线段检测、矩形检测和圆形检测,这些技术是目标识别与场景分析的基础。
🏆 学习目标:
- 掌握从摄像头采集的图像中检测线段、矩形和圆形的方法;
- 理解各检测算法的参数调优思路,提升检测准确性。
⚠️ 注意事项:
1️⃣大部分图像处理API仅支持RGB565或GRAYSCALE,使用时需要注意。2️⃣如无特殊说明,以后所有例程的显示设备均为通过外接立创·3.1寸屏幕扩展板,在3.1寸小屏幕上显示。若用户无3.1寸屏幕扩展板也可以正常在IDE的缓冲区,只是受限于USB带宽,可能会帧率较低或卡顿。
特征检测通常基于霍夫变换、LSD(线段检测)、AprilTag四边形检测等算法实现。实际应用中,需结合预处理(如二值化、边缘检测)提升效果,本节为简化演示,直接在原图上进行检测。
2. 线段检测
线段检测是视觉识别中的一个重要的基础功能,常用于识别图像中的线段部分,为更高层次的视觉处理任务提供支持。常使用霍夫变换算法来实现。庐山派-K230-CanMV 开发板所使用的 find_line_segments
接口即采用了 LSD 算法,与部分OpenCV版本一致,检测效果准确并且线段不易抖动或跳跃。
2.1 算法原理
-
空间变换:霍夫变换中,会将图像边缘像素映射到一个极坐标或其它累加空间,并在累加空间中找极大值点对应的直线或线段。
-
后续合并:如果检出很多近似平行并且重叠度较高的线段,会做一个“合并距离”与“角度差”判断,把它们合并成一条线段。在庐山派中就是体现为两个参数,
merge_distance
和max_theta_difference
。
2.2 API说明
image.find_line_segments([roi[, merge_distance=0[, max_theta_difference=15]]])
- 参数:
roi
: 为感兴趣区域的矩形元组 (x, y, w, h)。若未指定,ROI 默认为整个图像的矩形。操作仅限于该区域内的像素。merge_distance
:指定两条线段之间的最大像素距离,若小于该值则合并为一条线段。max_theta_difference
:为需合并的两条线段之间的最大角度差。
该方法使用 LSD 库(OpenCV 亦采用)来查找图像中的线段。虽然速度较慢,但准确性高,且线段不会出现跳跃现象。
注意:不支持压缩图像和Bayer格式。
2.3 代码示例
import time, os, sysfrom media.sensor import *
from media.display import *
from media.media import *picture_width = 400
picture_height = 240sensor_id = 2
sensor = None# 显示模式选择:可以是 "VIRT"、"LCD" 或 "HDMI"
DISPLAY_MODE = "LCD"# 根据模式设置显示宽高
if DISPLAY_MODE == "VIRT":# 虚拟显示器模式DISPLAY_WIDTH = ALIGN_UP(1920, 16)DISPLAY_HEIGHT = 1080
elif DISPLAY_MODE == "LCD":# 3.1寸屏幕模式DISPLAY_WIDTH = 800DISPLAY_HEIGHT = 480
elif DISPLAY_MODE == "HDMI":# HDMI扩展板模式DISPLAY_WIDTH = 1920DISPLAY_HEIGHT = 1080
else:raise ValueError("未知的 DISPLAY_MODE,请选择 'VIRT', 'LCD' 或 'HDMI'")try:# 构造一个具有默认配置的摄像头对象sensor = Sensor(id=sensor_id)# 重置摄像头sensorsensor.reset()# 无需进行镜像翻转# 设置水平镜像# sensor.set_hmirror(False)# 设置垂直翻转# sensor.set_vflip(False)# 设置通道0的输出尺寸为1920x1080sensor.set_framesize(width=picture_width, height=picture_height, chn=CAM_CHN_ID_0)# 设置通道0的输出像素格式为RGB565sensor.set_pixformat(Sensor.RGB565, chn=CAM_CHN_ID_0)# 根据模式初始化显示器if DISPLAY_MODE == "VIRT":Display.init(Display.VIRT, width=DISPLAY_WIDTH, height=DISPLAY_HEIGHT, fps=60)elif DISPLAY_MODE == "LCD":Display.init(Display.ST7701, width=DISPLAY_WIDTH, height=DISPLAY_HEIGHT, to_ide=True)elif DISPLAY_MODE == "HDMI":Display.init(Display.LT9611, width=DISPLAY_WIDTH, height=DISPLAY_HEIGHT, to_ide=True)# 初始化媒体管理器MediaManager.init()# 启动传感器sensor.run()while True:os.exitpoint()# 捕获通道0的图像img = sensor.snapshot(chn=CAM_CHN_ID_0)# 可以在此处根据需求先做一些预处理,如灰度化、边缘检测、二值化等# 查找线段(LSD算法)# merge_distance=20 # 两线段中心点相距小于20像素则合并# max_theta_diff=10 # 两线段角度差小于10°则合并lines = img.find_line_segments(merge_distance=20, max_theta_diff=10)count = 0 # 初始化线段计数器print("------线段统计开始------")for line in lines:img.draw_line(line.line(), color=(1, 147, 230), thickness=3) # 绘制线段print(f"Line {count}: {line}") # 打印线段信息count += 1 # 更新计数器print("---------END---------")# 显示捕获的图像,中心对齐,居中显示Display.show_image(img, x=int((DISPLAY_WIDTH - picture_width) / 2), y=int((DISPLAY_HEIGHT - picture_height) / 2))except KeyboardInterrupt as e:print("用户停止: ", e)
except BaseException as e:print(f"异常: {e}")
finally:# 停止传感器运行if isinstance(sensor, Sensor):sensor.stop()# 反初始化显示模块Display.deinit()os.exitpoint(os.EXITPOINT_ENABLE_SLEEP)time.sleep_ms(100)# 释放媒体缓冲区MediaManager.deinit()
2.4 效果说明
将摄像头对准含明显线段的场景(如文档边缘),屏幕会显示检测到的线段并标注,终端打印线段坐标信息。通过调整merge_distance
和max_theta_diff
可优化合并效果,避免线段碎片化或过度合并。
3. 矩形检测
矩形检测一般用于条码检测,可以先定位条码或者二维码,然后再去解码,提高运行速度。也常用来OCR的前置检测,先定位文档中的文字块或段落。CanMV固件中的find_rects
函数使用了与 AprilTag 中的四边形检测类似的算法,能适应一定程度的平移、旋转和仿射变化(扭曲)。
3.1 API说明
image.find_rects([roi=Auto, threshold=10000])
此函数使用与 AprilTag 相同的四边形检测算法查找图像中的矩形。该算法最适用于与背景形成鲜明对比的矩形。AprilTag 的四边形检测能够处理任意缩放、旋转和剪切的矩形,并返回一个包含 image.rect 对象的列表。
- 参数:
roi
:是用于指定感兴趣区域的矩形元组 (x, y, w, h)。若未指定,ROI 默认为整个图像。操作范围仅限于该区域内的像素。threshold
:矩形边界强度阈值(通过索贝尔算子累加值计算,小于阈值的矩形会被过滤)。
注意:不支持压缩图像和Bayer格式,需矩形与背景有明显对比度。
3.2 代码示例
核心检测部分替换为:
# 矩形检测(阈值5000)
rects = img.find_rects(threshold=5000)
count = 0print("------矩形统计开始------")
for rect in rects:# 绘制矩形边界img.draw_rectangle(rect.rect(), color=(1, 147, 230), thickness=3)# 可选:获取四个顶点(顺时针排序)# corners = rect.corners()print(f"Rect {count}: {rect}")count += 1
print("---------END---------")
3.3 效果说明
对准含矩形的目标,检测到的矩形会被标注,终端打印其位置和尺寸。threshold
需根据对比度调整:值太低易误检噪声,太高可能漏检弱对比度矩形。
4. 圆形检测
圆形检测用于定位圆心和半径,适用于检测圆环标记、交通标志、棋子等,基于霍夫变换实现。
4.1 API说明
image.find_circles([roi[, x_stride=2[, y_stride=1[, threshold=2000[, x_margin=10[, y_margin=10[, r_margin=10]]]]]]])
- 参数:
x_stride/y_stride
:霍夫变换中跳过的像素数(圆较大时可增大,提高速度);threshold
:圆强度阈值(索贝尔滤波像素值总和,需根据圆大小调整);x_margin/y_margin/r_margin
:合并相似圆的允许偏差(位置和半径)。
该方法通过在图像上应用索贝尔滤波器,并利用其幅值和梯度响应执行霍夫变换。无需对图像进行任何预处理,尽管图像的清理和过滤将会产生更为稳定的结果。
注意: 此功能不支持压缩图像和 Bayer 图像。
4.2 代码示例
核心检测部分替换为:
# 圆形检测(阈值6000)
circles = img.find_circles(threshold=6000)
count = 0print("------圆形统计开始------")
for circle in circles:# 绘制圆形img.draw_circle(circle.circle(), color=(1, 147, 230), thickness=3)print(f"Circle {count}: {circle}") # 打印圆心(x,y)和半径rcount += 1
print("---------END---------")
4.3 效果说明
对准圆形目标(如硬币、按钮),检测到的圆会被标注,终端打印圆心坐标和半径。调整x_margin
、y_margin
、r_margin
可避免抖动导致的重复检测。
5. 重点提示
5.1 提升检测效果的技巧
-
多角度与多距离测试:
特征检测受光照、分辨率、角度影响较大,需在不同条件下测试,必要时结合预处理(如边缘检测、二值化)增强对比度。庐山派摄像头为定焦,过近会模糊,可通过工具调整镜头对焦。 -
参数调优:
- 线段检测:
merge_distance
和max_theta_difference
需平衡线段合并效果; - 矩形检测:
threshold
需根据边缘对比度调整,过滤噪声和弱边缘; - 圆形检测:
threshold
控制检测灵敏度,x/y/r_margin
避免重复标注。
- 线段检测:
-
设置ROI(感兴趣区域):
大部分 API 中都可以通过 roi=(x, y, w, h) 设置仅对部分图像区域进行检测,一是可以减少干扰:若在画面其它区域存在大量不需要的特征,设置 ROI 能避免算法被无关特征干扰或误检。二是可提升效率:只对局部区域进行检测可以节省计算量,提高处理速度。
学习时间:8月9日
1. 本节介绍解读
核心内容梳理
本节聚焦于图像特征检测的三大核心技术:线段检测、矩形检测和圆形检测,这些技术是目标识别与场景分析的基础。学习目标明确为掌握检测方法和理解参数调优思路。
理解与感悟
- 特征检测是计算机视觉的"基础建材",线段、矩形、圆形作为最基本的几何特征,是识别复杂物体的前提。例如识别二维码先找矩形边框,识别交通标志先定位圆形或矩形轮廓。
- 注意事项中提到的"图像处理处理API仅支持RGB565或GRAYSCALE"很关键,这提示在实际开发中需先确保图像格式转换,否则会导致功能失效。
- 显示设备的说明体现了开发板的灵活性,即使没有实体屏幕也能通过IDE调试,降低了入门门槛,但USB带宽限制提醒我们在实时性要求高的场景需考虑性能优化。
2. 线段检测
算法原理分析
- 霍夫变换的核心是"空间变换",将图像空间中的线段转换为参数空间的点,通过累加器找峰值来检测线段,这种"换个角度看问题"的思路很巧妙。
- 合并策略(merge_distance和max_theta_difference)解决了线段碎片化问题,实际应用中需根据场景调整:例如检测建筑物边缘时,应减小角度差阈值保证直线完整性;而检测复杂电路时,可能需要增大距离阈值避免过度合并。
API与代码
find_line_segments
采用LSD算法,相比传统霍夫变换在抗抖动和准确性上更优,适合实时检测场景。- 代码中通过
merge_distance=20
和max_theta_diff=10
平衡检测精度和效率,绘制线段并打印信息的方式直观展示了检测结果。 - 预处理步骤的留白提示我们:在复杂场景下,先进行灰度化、边缘检测等操作能大幅提升线段检测效果(例如消除色彩干扰)。
实践启示
- 线段检测在结构化场景(如工业流水线、建筑检测)中表现优异,但在自然场景(如树叶、云朵)中易受干扰。
- 参数调优需结合实际:线条密集时减小merge_distance避免误合并,线条稀疏时增大该值保证连续性。
3. 矩形检测
技术定位分析
矩形检测在实际应用中具有明确的场景指向性:条码/二维码定位、文档区域提取、工业零件检测等。其基于AprilTag四边形检测算法,对几何形变的适应性(平移、旋转、仿射变化)是核心优势。
API与代码
find_rects
的threshold参数控制检测灵敏度,本质是通过索贝尔算子累加值判断边缘强度。阈值设置是关键:- 高对比度场景(如黑框白纸)可提高阈值(如10000)过滤噪声
- 低对比度场景(如灰色物体)需降低阈值(如5000)避免漏检
- 代码中获取四角顶点的注释提示矩形检测可用于更复杂的几何变换(如透视矫正),为后续OCR等任务奠定基础。
实践感悟
- 矩形检测对"对比度"的依赖度高,实际应用中可能需要通过光照控制(如补光灯)或图像增强(如直方图均衡化)提升效果。
- 与线段检测结合使用可提高鲁棒性:先检测线段,再通过线段组合判断矩形,减少误检。
4. 圆形检测
算法特性分析
基于霍夫变换的圆形检测通过圆心坐标和半径三个参数描述圆形,适用于交通标志、机械零件、棋子等场景。相比矩形和线段,圆形检测需要处理更多参数,计算量更大。
API与参数
x_stride/y_stride
影响检测速度和精度:大步长(如5)适合快速预览,小步长(如1)适合精确检测。x_margin/y_margin/r_margin
用于合并相似圆,解决因图像抖动导致的"同一圆被多次检测"问题,在实时视频流处理中尤为重要。- threshold参数需根据圆的大小调整:大圆需要更高阈值(边缘像素更多),小圆则需降低阈值。
实践总结
- 圆形检测对光照均匀性要求高,阴影或反光易导致边缘断裂,实际应用中可配合偏振片或多光源改善。
- 当场景中存在大量圆弧(非完整圆)时,需结合其他特征(如面积、周长比)过滤误检。
5. 重点提示
提升检测效果的技巧分析
-
预处理的重要性:原文多次暗示预处理的价值,实际开发中可按以下流程优化:
原图 → 灰度化 → 去噪(高斯模糊) → 边缘检测(Canny) → 特征检测
这种流程能显著减少干扰信息,提升算法效率。
-
参数调优策略:
- 线段检测:优先调整merge_distance控制合并粒度
- 矩形检测:threshold是核心,从高到低逐步测试
- 圆形检测:先固定margin参数,再调整threshold
-
ROI的价值:
- 功能层面:排除无关区域(如检测仪表盘时只关注中心区域)
- 性能层面:减少50%的检测区域可使速度提升近一倍,对嵌入式设备尤为重要
学习总结:
-
技术关联性:线段、矩形、圆形检测虽为独立功能,但实际应用中常组合使用(如矩形由四条线段组成,圆形可通过弧线特征辅助),理解它们的算法共性(如霍夫变换)能触类旁通。
-
嵌入式特性:开发板的资源限制(算力、内存)决定了需在精度和速度间平衡,例如通过ROI缩减检测区域、增大stride参数等,这与PC端OpenCV开发思路有显著差异。
-
实践优先级:
- 先保证基本功能实现(如能稳定检测高对比度目标)
- 再通过参数调优提升鲁棒性
- 最后结合预处理和多特征融合解决复杂场景问题
通过本节学习,不仅掌握了K230CanMV开发板的特征检测API使用,更理解了计算机视觉中"从简单特征到复杂识别"的递进逻辑,为后续更高级的目标跟踪、场景理解打下基础。