一、程序简介

这个案例主要展示使用卡尺工具去测量圆、线、矩形,得到拟合线(xld)的相关信息,包括:拟合出来的圆的圆心坐标、半径;矩形的中心坐标、角度、半长和半宽;线的起始结束坐标。
在这里插入图片描述

二、卡尺测量相关算子

  • create_metrology_model()
  • set_metrology_model_image_size()
  • add_metrology_object_circle_measure()
  • add_metrology_object_rectangle2_measure()
  • add_metrology_object_line_measure()
  • set_metrology_object_param(): 这里可以对测量对象进行很多参数设定,提高拟合边缘线的准确度
  • apply_metrology_model()
  • get_metrology_object_result(): 获取拟合出来的圆、矩形、直线以及椭圆的相关数据

三、应用

①卡尺工具应用十分广泛,在2D的测量项目中,一般用于定位产品和测量产品的尺寸上。
②在缺陷检测的项目中(产品表面缺陷如DDS),一般用于来料定位,纠正来料的位置偏差(这里就涉及到九点标定和旋转标定),计算偏差值,由机构进行补偿,提高下个工位的检测精度。

四、步骤流程

  • 第一步:根据图像创建坐标、角度、长宽、卡尺大小等数据
  • 第二步:创建、添加、设置计量模型参数
  • 第三步:将计量模型应用到原图中
  • 第四步:获取并显示计量模型中卡尺卡到的边缘点
  • 第五步:提取数据 例如:圆心坐标;矩形中心坐标;面积;线的坐标等,提高数据的可读性

五、Positive和Negative方向判断

首先看定义:
Positive: 由暗到亮,即由黑到白去找边缘,简称:正边缘
Negative: 由亮到暗,即由白到黑去找边缘,简称:负边缘
那么问题来了:一条边缘线,由暗到亮或者由亮到暗,到底是从边缘线的左边到右边?还是上边到下边?亦或是从里边往外边?还是从外边往里边?
①圆——由里往外
在这里插入图片描述
②矩形——由里往外

在这里插入图片描述

③直线——右手定则
(这个从描述上会比较抽象)
在对某条线(某个边缘)进行卡尺测量之前,我们是已经知道这条线的起始点位和结束点位,那么,右手定则是这样子的:举起右手,摊开巴掌,四根手指并拢,拇指分开垂直于食指,如下图可判定方向:
在这里插入图片描述在这里插入图片描述

六、官方程序及注释和理解

* This example shows the usage of the metrology model
* to measure circles and rectangles with subpixel
* accuracy under challenging conditions easily.
* 本例子展示了在具有挑战性的条件下使用计量模型以亚像素精度轻松地测量圆和矩形
* Display initializations
dev_update_off ()
read_image (Image, 'pads')
get_image_size (Image, Width, Height)
dev_close_window ()
dev_open_window_fit_image (Image, 0, 0, -1, -1, WindowHandle)
set_display_font (WindowHandle, 14, 'mono', 'true', 'false')
*  
* 以下的坐标点可以通过-> PS <- 软件去查看,当然也可以通过draw_circle()后去得到每个圆的中心坐标和半径
*
* Define the approximate position and the measure
* tolerance for the circles
* 确定圆的大致位置和测量公差
* 这里[52:89:500]: 在52 - 500 之间,每隔89个像素选出一个数。注意,包括52和500这两个数字
RowCircle := [52:89:500]
CircleInitRow := [RowCircle,RowCircle]
* 这里是生成6个348,6个438
CircleInitColumn := [gen_tuple_const(6,348),gen_tuple_const(6,438)]
gen_cross_contour_xld (Cross1, CircleInitRow, CircleInitColumn, 6, 0.785398)
CircleInitRadius := [gen_tuple_const(6,23),gen_tuple_const(6,23)]
* 外圈半径与内圈半径的差
CircleRadiusTolerance := 12
* Define the approximate position and the measure
* tolerance for the rectangles
* 确定两个矩形的大致位置和测量公差,同样用PS软件去打开查看
* 这里行列是两个矩形的中心坐标,
RectangleInitRow := [410,410]
RectangleInitColumn := [215,562]
RectangleInitPhi := [0,0]
RectangleInitLength1 := [85,85]
RectangleInitLength2 := [88,88]
RectangleTolerance := 10
* 
* Prepare the metrology model data structure
* 创建计量模型结构(几何形状)
create_metrology_model (MetrologyHandle)
* Setting the image width in advance is not
* necessary, but improves the runtime of the
* first measurement.
* 设置计量模型的尺寸大小(为了提高第一次测量的时间)
set_metrology_model_image_size (MetrologyHandle, Width, Height)
* Add the metrology rectangle objects to the model
* as defined above
* 将上述定位的计量矩形对象添加到模型当中
add_metrology_object_rectangle2_measure (MetrologyHandle, RectangleInitRow, RectangleInitColumn, RectangleInitPhi, RectangleInitLength1, RectangleInitLength2, RectangleTolerance, 5, .5, 1, [], [], MetrologyRectangleIndices)
* Add the metrology circle objects to the model
* as defined above
* 将上述定位的计量圆对象添加到模型当中
add_metrology_object_circle_measure (MetrologyHandle, CircleInitRow, CircleInitColumn, CircleInitRadius, CircleRadiusTolerance, 5, 1.5, 2, [], [], MetrologyCircleIndices)
* It is possible to measure more than one circle/rectangle/line/ellipse
* instance per metrology object in one call.
* Since we like to measure two circles per object,
* we set 'num_instances' to 2.
*可以在一次调用中测量每个计量对象的多个圆/矩形/直线/椭圆实例。因为我们喜欢测量每个对象的两个圆,所以我们将'num_instances'设置为2
set_metrology_object_param (MetrologyHandle, MetrologyCircleIndices, 'num_instances', 2)
* Setting 'measure_transition' to 'uniform' assures
* that only consistent circles are returned, that have
* either only edges from bright to dark or vice versa.
* Since the consistency check increases runtime, it is
* switched of by default.
*设置'measure_transition'为'uniform'确保只返回一致的圆圈,只有边缘从亮到暗或反之亦然。由于一致性检查增加了运行时间,因此默认情况下是关闭的。
* In this example however, it is safer to switch it on,
* because both negative and positive edges are present.
*在这个例子中,它是更安全的开关,因为负边和正边都存在。
set_metrology_object_param (MetrologyHandle, MetrologyCircleIndices, 'measure_transition', 'uniform')
* Setting the minimum score can make the results more robust
* 设定最低分数可以使得结果更加稳定
set_metrology_object_param (MetrologyHandle, MetrologyCircleIndices, 'min_score', .9)
* 
* Perform the measurement 
* 执行测量
apply_metrology_model (Image, MetrologyHandle)
* 
get_metrology_object_result (MetrologyHandle, MetrologyRectangleIndices, 'all', 'result_type', 'all_param', RectangleParameter)
* Extract the parameters for better readability
* 提取参数以获得更好的可读性
Sequence := [0:5:|RectangleParameter| - 1]
RectangleRow := RectangleParameter[Sequence]
RectangleColumn := RectangleParameter[Sequence + 1]
RectanglePhi := RectangleParameter[Sequence + 2]
RectangleLength1 := RectangleParameter[Sequence + 3]
RectangleLength2 := RectangleParameter[Sequence + 4]
* 
* Access the results of the circle measurement
* 访问圆的测量结果
get_metrology_object_result (MetrologyHandle, MetrologyCircleIndices, 'all', 'result_type', 'all_param', CircleParameter)
* Extract the parameters for better readability
Sequence := [0:3:|CircleParameter| - 1]
CircleRow := CircleParameter[Sequence]
CircleColumn := CircleParameter[Sequence + 1]
CircleRadius := CircleParameter[Sequence + 2]
* 
* Display the results
* 
* Get measured contours
get_metrology_object_result_contour (Contours, MetrologyHandle, 'all', 'all', 1.5)
* Get the contours of the measure regions
* and the coordinates of the edge points
* that were the basis for fitting the circles and rectangles
* 获取测量区域的轮廓和边缘点的坐标,这是拟合圆和矩形的基础
get_metrology_object_measures (Contour, MetrologyHandle, 'all', 'all', Row1, Column1)
gen_cross_contour_xld (Cross, Row1, Column1, 6, 0.785398)
* Display everything
Color := ['gray','cyan','green']
dev_display (Image)
dev_set_line_width (1)
dev_set_color (Color[0])
dev_display (Contour)
dev_set_color (Color[1])
dev_display (Cross)
dev_set_line_width (2)
dev_set_color (Color[2])
dev_display (Contours)
Message := Color[2] + ': Measurement result'
Message[1] := Color[1] + ': Edge candidate points'
Message[2] := Color[0] + ': Measure regions'
disp_message (WindowHandle, Message, 'window', 12, 12, 'black', 'true')

在这里插入图片描述

七、理解后编写的

dev_update_off ()
* 第一步:根据图像创建区域
read_image (Image, 'pads')
get_image_size (Image, Width, Height)
dev_open_window_fit_image (Image, 0, 0, -1, -1, WindowHandle)
set_display_font (WindowHandle, 16, 'mono', 'true', 'false')

* 定位圆的区域圆心坐标和半径
RowCircle := [52:89:500]
CircleInitRow := [RowCircle, RowCircle]
CircleInitColumn := [gen_tuple_const(6, 348), gen_tuple_const(6, 438)]
dev_display (Image)
gen_cross_contour_xld (Cross, CircleInitRow, CircleInitColumn, 16, 0.785398)
CircleInitRadius := [gen_tuple_const(6, 23), gen_tuple_const(6, 23)]
CircleRadiusTolerance := 12

* 定位矩形的中心坐标和长宽
RectangleInitRow := [410, 410]
RectangleInitColumn := [215, 562]
RectangleInitPhi := [0, 0]
RectangleInitLength1 := [85, 85]
RectangleInitLength2 := [88, 88]
RectangleTolerance := 10
gen_cross_contour_xld (Cross1, RectangleInitRow, RectangleInitColumn, 16, 0.785398)

* 定位线的坐标
* 以下每个元组中,最后一个坐标组合的线,对应negative(从亮到暗);其他坐标组合的线,对应positive(从暗到亮)
RowBegin := [144, 144,  144]
ColumnBegin := [477, 648,  477]
RowEnd := [144, 8,  4]
ColumnEnd := [649, 648,  477]
LineTolerance := 10

* 第二步:创建、添加、设置计量模型参数
create_metrology_model (MetrologyHandle)
set_metrology_model_image_size (MetrologyHandle, Width, Height)
add_metrology_object_circle_measure (MetrologyHandle, CircleInitRow, CircleInitColumn, CircleInitRadius, CircleRadiusTolerance, 5, 1.5, 2, [], [], MetroCircleIndices)
add_metrology_object_rectangle2_measure (MetrologyHandle, RectangleInitRow, RectangleInitColumn, RectangleInitPhi, RectangleInitLength1, RectangleInitLength2, RectangleTolerance, 5, 1, 2, [], [], MetroRectangleIndices)
add_metrology_object_line_measure (MetrologyHandle, RowBegin, ColumnBegin, RowEnd, ColumnEnd, LineTolerance, 5, 1, 2, [], [], MetroLineIndices)
* 计量模型中对象的参数设定:
* measure_length1: 半宽
* measure_length2: 半高
* measure_sigma: 高斯平滑系数
* measure_threshold: 最小边缘阈值(就是最小的灰度差)
* measure_select: 选择结束点(all, first, last)
* measure_transition: 边缘:Positive:正边缘(暗到亮); Negative:负边缘(亮到暗); 
*                           uniform: 一致正边缘或一致负边缘,拟合时仅用一个方向的点拟合直线或圆
* min_score: 最小分数
* num_instances: 拟合实例最大数量(这个和uniform参数对应着来:uniform是对每一实例去进行一致的,所以设置uniform可以提取所有边缘)
* measure_interpolation: 插值类型:"bicubic"双三次,"bilinear"双线性,"nearest_neighbor"近邻
*========================================圆===========================================================
set_metrology_object_param (MetrologyHandle, MetroCircleIndices, 'num_instances', 2)
set_metrology_object_param (MetrologyHandle, MetroCircleIndices, 'min_score', 0.9)
set_metrology_object_param (MetrologyHandle, MetroCircleIndices, 'measure_transition', 'uniform')
*set_metrology_object_param (MetrologyHandle, MetroCircleIndices, 'measure_select', 'last')
*========================================矩形=========================================================
set_metrology_object_param (MetrologyHandle, MetroRectangleIndices, 'min_score', 0.9)
set_metrology_object_param (MetrologyHandle, MetroRectangleIndices, 'measure_transition', 'positive')
*set_metrology_object_param (MetrologyHandle, MetroRectangleIndices, 'measure_select', 'first')
*=========================================线==========================================================
set_metrology_object_param (MetrologyHandle, MetroLineIndices, 'measure_transition', 'negative')

* 第三步:将计量模型应用到原图中
* get_metrology_object_result()返回的Parameter说明:
* Circle: ['row', 'column', 'radius']
* Rectangle: ['row', 'column', 'phi', 'length1', 'length2']
* Line:  ['row_begin', 'column_begin', 'row_end', 'column_end'] 
apply_metrology_model (Image, MetrologyHandle)
get_metrology_object_result (MetrologyHandle, MetroCircleIndices, 'all', 'result_type', 'all_param', CircleParameter)
get_metrology_object_result (MetrologyHandle, MetroRectangleIndices, 'all', 'result_type', 'all_param', RectangleParameter)
get_metrology_object_result (MetrologyHandle, MetroLineIndices, 'all', 'result_type', 'all_param', LineParameter)
get_metrology_object_result_contour (Contour, MetrologyHandle, 'all', 'all', 1.5)

stop()

* 第四步:获取并显示计量模型中卡尺卡到的边缘点
* 获取计量模型中所有测量对象的测量区域和边缘点位置的坐标
* Contours: 矩形测量区域xld
* MetrologyHandle: 测量模型句柄
* Index: 计量对象,本例中可选圆或矩形,选all则是所有记录对象
* Transition: 选择 亮->暗(Negative) 或者 暗->亮(Positive) 的边缘
* Row: 测出来的所有边缘点的行坐标
* Column: 测出来的所有边缘点的列坐标
get_metrology_object_measures (Circle_Contours, MetrologyHandle, MetroCircleIndices, 'all', Row, Column)
get_metrology_object_measures (Rectangle_Contours, MetrologyHandle, MetroRectangleIndices, 'all', Row1, Column1)
get_metrology_object_measures (Line_Contours, MetrologyHandle, MetroLineIndices, 'all', Row2, Column2)
gen_cross_contour_xld (Cross2, Row, Column, 6, 0.785398)
gen_cross_contour_xld (Cross3, Row1, Column1, 6, 0.785398)
gen_cross_contour_xld (Cross4, Row2, Column2, 6, 0.785398)
stop ()
dev_display (Image)
dev_set_line_width (1)
dev_set_color ('white')
*dev_display (Circle_Contours)
*dev_display (Rectangle_Contours)
dev_display (Line_Contours)
dev_set_color ('green')
*dev_display (Cross2)
*dev_display (Cross3)
dev_display (Cross4)
dev_set_color ('red')
dev_set_line_width (1)
dev_display (Contour)


* 第五步:提取数据 例如:圆心坐标;矩形中心坐标;面积;线的坐标等,提高数据的可读性
* 对圆数据进行切片,提取数据
SequenceCircle := [0:3:|CircleParameter|-1]
CircleRow := CircleParameter[SequenceCircle]
CircleColumn := CircleParameter[SequenceCircle+1]
CircleRadius := CircleParameter[SequenceCircle+2]
* 对矩形数据进行切片,提取数据
SequenceRectangle := [0:5:|RectangleParameter|-1]
RectangleRow := RectangleParameter[SequenceRectangle]
RectangleColumn := RectangleParameter[SequenceRectangle+1]
RectanglePhi := RectangleParameter[SequenceRectangle+2]
RectangleLength1 := RectangleParameter[SequenceRectangle+3]
RectangleLength2 := RectangleParameter[SequenceRectangle+4]
* 对线数据进行切片,提取数据
SequenceLine := [0:2:|LineParameter|-1]
LineRow := LineParameter[SequenceLine]
LineColumn := LineParameter[SequenceLine+1]

* 可以生成区域去裁剪roi,对roi进行下一步操作(比如:形态学分析等); 可以求卡尺卡出来的两条线的交点和线之间角度
gen_circle (Circle, CircleRow, CircleColumn, CircleRadius)
gen_rectangle2 (Rectangle, RectangleRow, RectangleColumn, RectanglePhi, RectangleLength1, RectangleLength2)
dev_display (Circle)
* 线交点
intersection_lines (LineRow[0], LineColumn[0], LineRow[1], LineColumn[1], LineRow[2], LineColumn[2], LineRow[3], LineColumn[3], InterSRow, InterSColumn, IsOverlapping)
gen_cross_contour_xld (Cross5, InterSRow, InterSColumn, 26, 0.785398)
* 两条线的角度
angle_ll (LineRow[0], LineColumn[0], LineRow[1], LineColumn[1], LineRow[2], LineColumn[2], LineRow[3], LineColumn[3], Angle)
Angle := deg(Angle)

* 显示交点数据
set_display_font (WindowHandle, 12, 'mono', 'true', 'false')
dev_display (Cross5)
message := 'IPoint: ' +  InterSRow + ', ' + InterSColumn
dev_disp_text (message, 'image', InterSRow+20, InterSColumn-100, 'cyan', 'box_color', 'yellow')

* 显示矩形圆心数据
for Index := 0 to |RectangleRow|-1 by 1
    message[Index] := 'Point' + Index + ': ' + RectangleRow[Index] + ', ' + RectangleColumn[Index]
    gen_cross_contour_xld (Cross, RectangleRow[Index], RectangleColumn[Index], 26, 0.785398)
    dev_display (Cross)
    dev_disp_text (message[Index], 'image', RectangleRow[Index]+20, RectangleColumn[Index]-100, 'cyan', 'box_color', 'yellow')  
endfor

在这里插入图片描述分析有不到位的,请各位点评指正~

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐