对应示例程序:
measure_ic_leads.hdev
目标:测量IC脚的长度,以及IC管脚的宽度和彼此之间的距离
思路为:
这个例程主要是学习一维测量的几个核心算子:
gen_measure_rectangle2 – 一维矩形测量句柄
measure_pos --检测区域内垂直于长轴 的边缘 。返回的是边缘的中心坐标
measure_pairs–加强版的measure_pos ,找出的都是边缘对(两个边形成一对边缘),边缘给出的是边缘对间距值;返回的也是边缘的中心点坐标,因此在显示时需要进行计算。因为得到的只是一个点,但是在显示时肯定是线,所以要自己进行适当的由点到线的扩展,可以参考这样的表示方式:
//长度 根据图像的特点,进行自己选择 ,长就选大点 小就选小点
//角度 选择画矩形时的角度
*RowStart := Row + Length * cos(Phi)
*RowEnd := Row - Length * cos(Phi)
*ColStart := Col + Length * sin(Phi)
*ColEnd := Col - Length * sin(Phi)
比如:将算子measure_pairs处理后得到的RowStart,RowEnd,ColStart,ColEnd 进行显示,其实就是几个点,不是边缘的全部点,要显示,还是要自己扩展一下。
如果直接将各个点连接处理的话,边缘可能并不是想显示的那样,有出入。
由点扩展到线的处理显示结果::
1.读取图像
2.根据先验知识,在含有IC脚的顶部和顶部各画一个矩形ROI 用于进行后续的边缘检测。
在实际的工业检测中,也可以这样做,手动增加检测区域。可以在做模板时,手动画框。后面再根据模板匹配,等定位方式进行自动的调整。
3.利用算子measure_pos提取垂直于矩形长轴的边缘,并把返回的边缘间的距离Distance作为IC脚的长度。
4.再根据先验知识,画一个细长矩形,用于测量单个IC脚的宽度,以及IC脚之间的两两距离。
5.利用算子measure_pairs对矩形ROI区域进行处理, 提取得到边缘,并将边缘对距离的平均数作为最后的结果
6.为了更好的显示结果,例程中选了一小块区域,进行放大处理和显示。
图像:
代码:
* IC Pin脚的测量:
* 首先测量IC的长度,然后测量IC管脚的宽度和彼此之间的距离。
* First, read in the image and initialize the program
//读入图像 参数初始化
read_image (Image, 'ic_pin')
get_image_pointer1 (Image, Pointer, Type, Width, Height)
dev_close_window ()
dev_open_window_fit_image (Image, 0, 0, 509, 509, WindowHandle)
set_display_font (WindowHandle, 14, 'mono', 'true', 'false')
dev_display (Image)
dev_set_draw ('margin')
dev_set_line_width (3)
* 根据先验知识,画两个矩形ROI 用于进行后续的边缘检测
* 在实际的工业检测中,也可以这样做,手动增加检测区域。
* 可以在做模板时,手动画框。后面再根据模板匹配,等定位方式进行自动的调整
* Define and display the rectangular ROIs within which the edges will be detected
Row := 55
RowBottom := 955
Column := 200
Phi := rad(-90)
Length1 := 50
Length2 := 35
dev_set_color ('gray')
gen_rectangle2 (Rectangle, Row, Column, Phi, Length1, Length2) //画的两个矩形
gen_rectangle2 (Rectangle, RowBottom, Column, Phi, Length1, Length2)
disp_continue_message (WindowHandle, 'black', 'true')
stop ()
*
* Create a measure object for the ROI at the top of the image.
//申请一个测量句柄 用于对顶部的ROI区域进行检测
Interpolation := 'nearest_neighbor' //插值方式 最近邻
gen_measure_rectangle2 (Row, Column, Phi, Length1, Length2, Width, Height, Interpolation, MeasureHandle)
*
* Determine all edges and calculate the lead height at the top of the image
*检测出所有边缘
Sigma := 1.0
Threshold := 30
Transition := 'all'
Select := 'all'
//检测是直线并且垂直于长轴 的边缘 因此要合理设置矩形的长抽
measure_pos (Image, MeasureHandle, Sigma, Threshold, Transition, Select, RowEdge, ColumnEdge, Amplitude, Distance)
//返回的是边缘点对的中点坐标,在显示时要进行换算 长度可以自己选择
//带角度时 可以参考:
*RowStart := Row + Length * cos(Phi)
*RowEnd := Row - Length * cos(Phi)
*ColStart := Col + Length * sin(Phi)
*ColEnd := Col - Length * sin(Phi)
LeadLength1 := Distance
*
* Display the results
//显示检测出的边缘 和 顶部IC Pin脚的长度
dev_set_color ('white')
disp_line (WindowHandle, RowEdge, ColumnEdge - Length2, RowEdge, ColumnEdge + Length2) //这里进行了简单的换算
disp_message (WindowHandle, 'Top Lead Length: ' + LeadLength1$'.2f', 'window', RowEdge[1] + 40, ColumnEdge[1] + 100, 'yellow', 'false')
*
* Shift the measure object and determine the lead height at the bottom of the image
//调整测量句柄 测量底部的ROI区域
translate_measure (MeasureHandle, RowBottom, Column)
measure_pos (Image, MeasureHandle, Sigma, Threshold, Transition, Select, RowEdge, ColumnEdge, Amplitude, Distance)
LeadLength2 := Distance
*
//展示底部的测量结果
* Display the results
dev_set_color ('white')
disp_line (WindowHandle, RowEdge, ColumnEdge - Length2, RowEdge, ColumnEdge + Length2)
disp_message (WindowHandle, 'BOttoman Lead Length: ' + LeadLength2$'.2f', 'window', 50, 70, 'yellow', 'false')
*
* Close the measure
//使用完后 关闭测量句柄
close_measure (MeasureHandle)
disp_continue_message (WindowHandle, 'black', 'true')
stop ()
*
* Now, define and display a rectangular ROI perpendicular to the leads and create the measure
//定义一个长条矩形 用于测量IC Pin脚的距离
dev_display (Image)
Row := 47
Column := 485
Phi := 0
Length1 := 420
Length2 := 8
Interpolation := 'nearest_neighbor' //采用最近邻的差值方式
dev_set_color ('black')
gen_rectangle2 (Rectangle, Row, Column, Phi, Length1, Length2)
//申请测量句柄
gen_measure_rectangle2 (Row, Column, Phi, Length1, Length2, Width, Height, Interpolation, MeasureHandle)
*
* Determine all edge pairs that have a negative transition, i.e., edge pairs
* that enclose dark regions.
//检测边缘 即 垂直于IC Pin脚 的横线
Sigma := 1.0
Threshold := 30
Transition := 'negative' //检测参数
Select := 'all'
measure_pairs (Image, MeasureHandle, Sigma, Threshold, Transition, Select, RowEdgeFirst, ColumnEdgeFirst, AmplitudeFirst, RowEdgeSecond, ColumnEdgeSecond, AmplitudeSecond, IntraDistance, InterDistance)
disp_continue_message (WindowHandle, 'black', 'true')
stop ()
dev_set_color ('white')
//显示
disp_line (WindowHandle, RowEdgeFirst, ColumnEdgeFirst, RowEdgeSecond, ColumnEdgeSecond) //这里没换算 显示的线其实严格来说,不合适
//显示检测到的Pin脚数量 Pin脚的宽度 Pin脚间的距离
avgLeadWidth := sum(IntraDistance) / |IntraDistance| // 边缘对内边缘之间的距离
avgLeadDistance := sum(InterDistance) / |InterDistance| //连续边缘对之间的距离
numLeads := |IntraDistance|
disp_message (WindowHandle, 'Number of Leads: ' + numLeads, 'window', 200, 100, 'yellow', 'false')
disp_message (WindowHandle, 'Average Lead Width: ' + avgLeadWidth$'.2f', 'window', 260, 100, 'yellow', 'false')
disp_message (WindowHandle, 'Average Lead Distance: ' + avgLeadDistance$'.2f', 'window', 320, 100, 'yellow', 'false')
disp_continue_message (WindowHandle, 'black', 'true')
disp_continue_message (WindowHandle, 'black', 'true')
stop ()
*
* Zoom in to visualize the measurement results in more detail.
* First, define and display the zoom window.
//这里 主要是对图像进行缩放 进行更好的可视化处理
Row1 := 0
Column1 := 600
Row2 := 100
Column2 := 700
dev_set_color ('blue')
disp_rectangle1 (WindowHandle, Row1, Column1, Row2, Column2)
disp_continue_message (WindowHandle, 'black', 'true')
stop ()
*
* Then, zoom the image and display the results.
dev_set_part (Row1, Column1, Row2, Column2)
dev_display (Image)
dev_set_color ('black')
dev_display (Rectangle)
//调用的自定义函数
p_disp_edge_marker (RowEdgeFirst, ColumnEdgeFirst, Phi, 5, 'white', 3, WindowHandle) //自定义函数里面,进行了点到线的换算,因此看到的是正确的显示结果
p_disp_edge_marker (RowEdgeSecond, ColumnEdgeSecond, Phi, 5, 'white', 3, WindowHandle)
*
* Close the measure
close_measure (MeasureHandle)
*
* Reset the display parameters.
dev_set_part (0, 0, Height - 1, Width - 1)
dev_set_draw ('fill')
dev_set_line_width (1)
用到的几个算子:
gen_measure_rectangle2 – 一维矩形测量句柄
measure_pos --检测区域内垂直于长轴 的边缘 。返回的是边缘的中点坐标
measure_pairs–加强版的measure_pos ,找出的都是边缘对(两个边形成一对边缘),边缘给出的是边缘对间距值。
参考资料:
[1]. https://blog.csdn.net/mufeng008/article/details/84104099
[2]. https://cloud.tencent.com/developer/article/1442112