Halcon 寻找方形Mark

图像:

效果:

思路:

先使用edges_sub_pix找出所有轮廓

平滑轮廓,连接轮廓,去除Mark边上的干扰点,比如下面这里:

要连到一起形成封闭的轮廓方便后续处理。

然后找出封闭的、面积最大的一个轮廓

以这个轮廓位置为基准,进行二维两侧找矩形精确找边

然后计算顶点确定中心。

代码:

Matlab 复制代码
* Image Acquisition 01: Code generated by Image Acquisition 01
list_files ('G:/图像/打光测试用方框', ['files','follow_links'], ImageFiles)
tuple_regexp_select (ImageFiles, ['\\.(tif|tiff|gif|bmp|jpg|jpeg|jp2|png|pcx|pgm|ppm|pbm|xwd|ima|hobj)$','ignore_case'], ImageFiles)
for Index := 0 to |ImageFiles| - 1 by 1
   
 dev_close_window ()
 read_image (Image, ImageFiles[Index])
get_image_size (Image, Width, Height)

dev_set_colored (12)
dev_set_draw ('margin')
dev_open_window_fit_image (Image, 0, 0, -1, -1, WindowHandle)
dev_display (Image)

edges_sub_pix (Image, Edges, 'canny', 5, 3, 5)
smooth_contours_xld (Edges, SmoothedEdges, 3)
* segment_contours_xld (Edges, ContoursSplit, 'lines', 5, 4, 2)
* 2. 连接相切的轮廓(坑和路平滑过渡)
* MaxDist: 端点间的最大距离(像素)
* MaxAngle: 最大角度差(弧度)- 允许一定角度偏差
* MaxTang: 最大切线方向差(弧度)- 保证平滑连接
union_cotangential_contours_xld (Edges, UnionEdges, 20, rad(30), rad(30), 10, 10, 3, 'attr_keep')
* 步骤1:从原始轮廓中筛选出封闭的轮廓
select_contours_xld (UnionEdges, ClosedContours, 'closed', 0, 1.0, 0, 0)

* 步骤2:计算所有封闭轮廓的面积
area_center_xld (ClosedContours, Area, Row, Column, PointOrder)

* 步骤3:获取面积排序索引(升序:面积小的在前,大的在后)
tuple_sort_index (Area, Indices)

* 步骤4:获取轮廓数量
count_obj (ClosedContours, NumClosed)

* 步骤5:选出面积最大的两个轮廓
if (NumClosed >= 2)
    * 最大面积的索引(最后一个)
    Index1 := Indices[NumClosed - 1] + 1
    * 第二大面积的索引(倒数第二个)
    Index2 := Indices[NumClosed - 2] + 1
    
    * 选择两个轮廓
    select_obj (ClosedContours, LargestContour, Index1)
    select_obj (ClosedContours, SecondLargestContour, Index2)
    
    * 合并成一个对象数组(可选)
    concat_obj (LargestContour, SecondLargestContour, TopTwoContours)
elseif (NumClosed == 1)
    * 只有一个封闭轮廓的情况
    select_obj (ClosedContours, TopTwoContours, 1)
    
else
    * 没有封闭轮廓
    gen_empty_obj (TopTwoContours)
   
endif

* 显示结果
dev_display (TopTwoContours)

* ========== 为第一个轮廓生成最小外接矩形 ==========
smallest_rectangle2_xld (LargestContour, Row1, Column1, Phi1, Length1_1, Length2_1)
gen_rectangle2 (Rectangle1, Row1, Column1, Phi1, Length1_1, Length2_1)

* ========== 为第二个轮廓生成最小外接矩形 ==========
smallest_rectangle2_xld (SecondLargestContour, Row2, Column2, Phi2, Length1_2, Length2_2)
gen_rectangle2 (Rectangle2, Row2, Column2, Phi2, Length1_2, Length2_2)

   
    dev_display (Image)
   

* ========== 使用 Metrology Model 精确测量 ==========
* 获取图像尺寸
get_image_size (Image, Width, Height)

* 创建测量模型
create_metrology_model (MetrologyHandle)

* 设置图像尺寸
set_metrology_model_image_size (MetrologyHandle, Width, Height)

* 添加矩形测量对象
* 参数:[中心行, 中心列, 角度, 半长, 半宽]
* 测量区域长度: 30, 测量区域宽度: 10
* 平滑参数: 0.4, 边缘阈值: 20
add_metrology_object_generic (MetrologyHandle, 'rectangle2', [Row1, Column1, Phi1, Length1_1, Length2_1],20, 5, 1, 10, [], [], Index3)
                              

* 设置测量参数
set_metrology_object_param (MetrologyHandle, 'all', 'measure_transition', 'all')
set_metrology_object_param (MetrologyHandle, 'all', 'measure_select', 'first')
set_metrology_object_param (MetrologyHandle, 'all', 'num_measures', 40)

* 执行测量
apply_metrology_model (Image, MetrologyHandle)

* 获取测量到的边缘点轮廓
get_metrology_object_measures (MeasuresContour, MetrologyHandle, 'all', 'all', RowPoints, ColPoints)

* 将测量点转换为轮廓
gen_contour_polygon_xld (MeasuresContour, RowPoints, ColPoints)

* 使用拟合矩形(可选,如果直接获取结果不够精确)
fit_rectangle2_contour_xld (MeasuresContour, 'regression', -1, 0, 0, 3, 2, PreciseRow, PreciseCol, PrecisePhi, PreciseLen1, PreciseLen2, PointOrder)

* 生成精确矩形轮廓
gen_rectangle2_contour_xld (PreciseRectangle, PreciseRow, PreciseCol, PrecisePhi, PreciseLen1, PreciseLen2)

* 或者直接获取测量结果(更简洁的方式)
* get_metrology_object_result (MetrologyHandle, Index, 'all', 'result_type', 'all_param', RectParams)
* PreciseRow := RectParams[0]
* PreciseCol := RectParams[1]
* PrecisePhi := RectParams[2]
* PreciseLen1 := RectParams[3]
* PreciseLen2 := RectParams[4]

* 清理测量模型
clear_metrology_model (MetrologyHandle)

* ========== 计算四个顶点 ==========
* 从矩形参数计算四个角点
CosPhi := cos(PrecisePhi)
SinPhi := sin(PrecisePhi)

* 顶点1(右上)
V1Row := PreciseRow + PreciseLen1 * CosPhi - PreciseLen2 * SinPhi
V1Col := PreciseCol + PreciseLen1 * SinPhi + PreciseLen2 * CosPhi

* 顶点2(右下)
V2Row := PreciseRow + PreciseLen1 * CosPhi + PreciseLen2 * SinPhi
V2Col := PreciseCol + PreciseLen1 * SinPhi - PreciseLen2 * CosPhi

* 顶点3(左下)
V3Row := PreciseRow - PreciseLen1 * CosPhi + PreciseLen2 * SinPhi
V3Col := PreciseCol - PreciseLen1 * SinPhi - PreciseLen2 * CosPhi

* 顶点4(左上)
V4Row := PreciseRow - PreciseLen1 * CosPhi - PreciseLen2 * SinPhi
V4Col := PreciseCol - PreciseLen1 * SinPhi + PreciseLen2 * CosPhi

* 计算中心点(四个顶点的平均值)
CenterRow := (V1Row + V2Row + V3Row + V4Row) / 4
CenterCol := (V1Col + V2Col + V3Col + V4Col) / 4

* ========== 显示结果 ==========
dev_clear_window ()
dev_display (Image)

* 显示初始外接矩形(灰色)
dev_set_color ('gray')
dev_display (Rectangle1)

* 显示测量边缘点(蓝色)
dev_set_color ('blue')
dev_display (MeasuresContour)

* 显示精确矩形(绿色)
dev_set_color ('green')
dev_set_line_width (3)
dev_display (PreciseRectangle)

* 显示四个顶点(红色十字)
dev_set_color ('red')
gen_cross_contour_xld (Cross1, V1Row, V1Col, 25, 0)
gen_cross_contour_xld (Cross2, V2Row, V2Col, 25, 0)
gen_cross_contour_xld (Cross3, V3Row, V3Col, 25, 0)
gen_cross_contour_xld (Cross4, V4Row, V4Col, 25, 0)
dev_display (Cross1)
dev_display (Cross2)
dev_display (Cross3)
dev_display (Cross4)

* 显示精确中心(黄色十字)
dev_set_color ('yellow')
gen_cross_contour_xld (CenterCross, CenterRow, CenterCol, 35, 0)
dev_display (CenterCross)

* 显示坐标信息
disp_message (WindowHandle, '精确中心: (' + CenterRow$'.2f' + ', ' + CenterCol$'.2f' + ')', 'window', 12, 12, 'yellow', 'false')
disp_message (WindowHandle, '矩形尺寸: ' + (2*PreciseLen1)$'.1f' + ' x ' + (2*PreciseLen2)$'.1f', 'window', 40, 12, 'green', 'false')  
stop ()
endfor
相关推荐
程序员黑豆30 分钟前
使用AI编程开发鸿蒙应用:从环境搭建到实战示例
前端·harmonyos
程序员黑豆4 小时前
鸿蒙应用开发:一次开发多端部署之响应式布局完全指南
前端·harmonyos
小月土星4 小时前
2.0 React Router 前端路由深度解析:从传统后端路由到现代 SPA 的完整演进
前端
To_OC5 小时前
LC 35 搜索插入位置:二分查找谁都会,边界条件谁写谁懵
javascript·算法·leetcode
码哥DFS6 小时前
二叉树的直径
开发语言·javascript·算法
long3167 小时前
MySQL 学习练习(配套 01 入门资料)
数据库·学习·mysql
badhope3387 小时前
当所有AI都在抄同一份作业:前端模板的趋同、困局与破局
前端·ai·ai编程·前端开发·tailwind·ui设计
数据库小学妹8 小时前
数据库等保三级和四级有什么区别?从访问控制到备份恢复的完整对比
数据库·安全·数据库安全·三级等保·等保合规·四级等保
光影少年8 小时前
RN的Fabric 渲染流程
运维·前端·javascript·react native·react.js·fabric
__zRainy__9 小时前
React开始:直接在网站中使用React.js
前端·react.js·前端框架