最小外接矩形2显示四条边缘
在机器视觉中,计算和显示物体的最小外接矩形是一项极其常见且关键的任务。与使用规则矩形(由x,y,width,height定义)不同,最小外接矩形通常是旋转的,能更紧凑地包围目标物体。
一个旋转的最小外接矩形通常由以下要素描述:
- 中心点 (Center Point):
(cx, cy)
- 宽度 (Width) 和 高度 (Height)
- 旋转角度 (Angle): 通常指矩形相对于水平轴的旋转角度。
计算并显示其四条边缘,在以下机器视觉场景中具有核心意义:
1. 物体姿态估计与方位分析
这是最经典的应用。最小外接矩形的方向直接反映了被检测物体的主导朝向。
应用场景:
- 工业检测:在生产线上,检查零件在传送带上的摆放角度是否正确。例如,一个芯片是否被正确旋转了90度?一个螺栓的朝向是否在允许的误差范围内?
- 机器人抓取:机器人需要知道一个物体的长边和短边,才能规划最优的抓取姿态。最小外接矩形提供了物体的长度、宽度和朝向。
- 农业自动化:分析水果(如黄瓜、茄子)的朝向,以便机械臂能顺其长轴进行抓取,避免损伤。
为何要显示边缘:在视觉系统中,将最小外接矩形的四条边缘叠加显示在原始图像上,可以直观地验证算法的准确性。操作员可以立即判断矩形是否很好地拟合了物体,以及计算出的角度是否符合预期。
2. 尺寸测量
虽然最小外接矩形的尺寸不完全等于物体的真实尺寸(因为它是一个二维投影),但在许多约束条件下,它是测量物体长、宽等特征的高效方法。
应用场景:
- PCB板检测:测量电路板的实际长宽,或者板上某个大元件的位置和角度。
- 物流分拣:快速估算包裹在传送带上的投影面积和最长边,用于初步的体积测量和分拣。
- 生物医学:测量显微镜下细胞或细菌的近似长度和宽度。
为何要显示边缘:显示边缘可以确保测量是在正确的基准上进行的。例如,可以清楚地看到测量的“长度”对应的是矩形的长边,“宽度”对应的是短边,避免因角度旋转而导致的测量混淆。
3. 目标识别与分类
物体的长宽比和基本形状是重要的分类特征。最小外接矩形提供了这些信息。
应用场景:
- 交通监控:区分车辆类型。小轿车的最小外接矩形通常长宽比较大,而卡车可能更长,公共汽车则更接近一个大的长方形。通过与水平线的夹角还可以判断车辆是否在正常行驶道内。
- 零件分类:在散乱的零件中,螺丝和螺母的最小外接矩形长宽比会有明显差异,可用于快速分类。
为何要显示边缘:在开发和调试分类算法时,可视化矩形有助于工程师理解算法是如何“看待”物体的。如果分类错误,通过观察矩形拟合情况,可以判断是特征提取有问题,还是分类器需要调整。
4. 视觉伺服与跟踪
在对运动物体进行跟踪时,不仅需要知道物体的位置(中心点),还需要知道其朝向。
应用场景:
- 自动驾驶:跟踪前方车辆时,用一个带角度的矩形框(通常是最小外接矩形的变体)来包围车辆,比用一个正矩形更精确,能更好地反映车辆的实时姿态。
- 无人机巡检:跟踪地面上的车辆或船只,其最小外接矩形的方向变化直接反映了目标的运动方向。
为何要显示边缘:在监控屏幕上,显示带有方向的矩形框,能给操作员提供远比正矩形框更丰富、更准确的运动信息,便于监控和决策。
5. 图像裁剪与ROI提取
当需要从图像中提取出目标物体并进行后续分析时,最小外接矩形可以用来获取一个方向校正后的、无冗余背景的图像区域。
应用场景:
- 文档扫描:拍摄了一张倾斜的名片,首先找到名片的最小外接矩形,然后根据矩形的角度对图像进行旋转校正,最后根据矩形的四边裁剪出名片的正面图。
- 车牌识别:检测到倾斜的车牌区域后,通过其最小外接矩形计算倾斜角度并进行校正,能大幅提高后续字符识别的准确率。
为何要显示边缘:在自动裁剪前,需要人工确认或调整裁剪区域。显示出的四条边缘就是最终的裁剪边界,可视化是质量控制的关键一步。
6.基于Halcon通常通过以下步骤计算和绘制最小外接矩形:
- 图像预处理和二值化:将目标物体与背景分离。
- 区域查找:找到物体所在区域。
- 计算最小外接矩形:smallest_rectangle2函数,它会返回一个包含中心点、宽高和角度的旋转矩形结构。
- 获取四个顶点/绘制边缘:(四顶点获取可参考往期文章)本文主要分享绘制边缘
示例结果
示例Demo
read_image (Image, 'YourPath')
gen_rectangle1 (ROI_0, 35.2612, 29.0341, 1017.2, 1079.98)
reduce_domain (Image, ROI_0, ImageReduced)
mean_image (ImageReduced, ImageMean, 19, 19)
dyn_threshold (ImageReduced, ImageMean, Region, 5, 'dark')
connection (Region, Regions)
Xs := [1, 1, -1, -1]
Ys := [1, -1, -1, 1]
Sx:=1.25
Sy:=1.25
count_obj (Regions, Number)
gen_empty_obj (Obj)
for Index := 1 to Number by 1select_obj (Regions, Front, Index)smallest_rectangle2 (Front, Row, Column, Phi, Length1_F, Length2_F)orientation_region (Front, Phi)Xs_extX := Xs * SxYs_extY := Ys * Syhom_mat2d_identity (HomMat2DIdentity)hom_mat2d_scale (HomMat2DIdentity, Length1_F, Length2_F, 0, 0, HomMat2DScale)hom_mat2d_rotate (HomMat2DScale, rad(180) - Phi, 0, 0, HomMat2DRotate)hom_mat2d_translate (HomMat2DRotate, Column, Row, HomMat2DTranslate)affine_trans_point_2d (HomMat2DTranslate, Xs, Ys_extY, Qx_1, Qy_1)affine_trans_point_2d (HomMat2DTranslate, Xs_extX, Ys, Qx_2, Qy_2)for IndexLines := 0 to |Qx_1| - 1 by 1if (IndexLines % 2)gen_contour_polygon_xld (ContourLine, [Qy_2[IndexLines],Qy_2[(IndexLines + 1) % 4]], [Qx_2[IndexLines],Qx_2[(IndexLines + 1) % 4]])elsegen_contour_polygon_xld (ContourLine, [Qy_1[IndexLines],Qy_1[(IndexLines + 1) % 4]], [Qx_1[IndexLines],Qx_1[(IndexLines + 1) % 4]])endifdev_display (ContourLine)concat_obj (Obj, ContourLine, Obj)endforendfor
dev_display (Image)
dev_display (Obj)