一、引言
直线拟合应用场景:
- 产品边缘检测:检测产品的直线边缘(如金属板、塑料件的边缘),判断是否符合设计规格。
- 缺陷检测:通过拟合直线检测边缘的直线度,识别是否存在弯曲、断裂或毛刺等缺陷。
- 长度、宽度测量:通过拟合直线计算物体的长度、宽度等几何尺寸。
二、具体实施:
dev_get_window (WindowHandle)
read_image (Image2, 'C:/Users/10314/Desktop/rpic1.jpg')
rgb1_to_gray (Image2, Image)
*1、绘制卡尺形态
Elements:=10
Rowc:=0
Colc:=0
DetecHeight:=100
DetecWidth:=20
disp_message (WindowHandle, '画一条直线,右键是确认', 'window', 12, 12, 'red', 'false')
*生成空显示对象,用于显示
gen_empty_obj (EmptyObject)
*画线
draw_line (WindowHandle, Row1, Column1, Row2, Column2)
*产生直线xld 多边形的两点表示直线轮廓
gen_contour_polygon_xld (RegionLines, [Row1,Row2], [Column1,Column2])
*存储到显示对象
concat_obj (EmptyObject, RegionLines, EmptyObject)
*计算直线与X轴的夹角,逆时针为正
angle_lx (Row1, Column1, Row2, Column2, Angle)
*边缘检测方向垂直于检测直线:加90°
Angle:=Angle+rad(90)
*根据检测直线按顺序产生测量区域矩形,并存储到显示对象
for Index:=1 to Elements by 1
*只有一个测量矩形,作为卡尺工具,宽度为检测直线的长度
if(Elements==1)
Rowc:=(Row1+Row2)/2
Colc:=(Column1+Column2)/2
distance_pp (Row1, Column1, Row2, Column2, Distance)
gen_rectangle2_contour_xld (Rectangle, Rowc, Colc, Angle, DetecHeight/2, Distance/2)
else
*多个测量矩形,产生该测量矩形xld
Rowc:=Row1 + ((Row2-Row1)/(Elements-1))*(Index-1)
Colc:=Column1 +((Column2-Column1)/(Elements-1))*(Index-1)
gen_rectangle2_contour_xld (Rectangle, Rowc, Colc, Angle, DetecHeight/2, DetecWidth/2)
endif
if(Index==1)
ArrBStartRow:= Rowc-cos(-Angle+rad(90))*DetecHeight/2
ArrStartCol:= Colc +sin(-Angle+rad(90))*DetecHeight/2
ArrEndRow:=Rowc+cos(-Angle+rad(90))*DetecHeight/2
ArrEndCol:=Colc -sin(-Angle+rad(90))*DetecHeight/2
HeadLength:=10
HeadWidth:=10
*在第一个测量矩形绘制一个箭头xld。显示边缘检测方向
gen_arrow_contour_xld (Arrow, ArrBStartRow, ArrStartCol, ArrEndRow, ArrEndCol, HeadLength, HeadWidth)
endif
endfor
*2、卡尺测量
get_image_size (Image, Width, Height)
RowEdgeList:=[]
for i := 0 to Elements-1 by 1
RowEdgeList := [RowEdgeList, i]
endfor
ColumnEdgeList:=[]
for i := 0 to Elements-1 by 1
ColumnEdgeList := [ColumnEdgeList, i]
endfor
sigma:=1
Threshold:=20
*由明到暗为负极性
trans:='negative'
sel:='first'
dev_set_color ('green')
for Index:=1 to Elements by 1
*只有一个测量矩形2,作为卡尺工具,宽度为检测直线的长度
if(Elements==1)
*省略
else
*生成多个矩形2卡尺并测量
Rowc:=Row1 + ((Row2-Row1)/(Elements-1))*(Index-1)
Colc:=Column1 +((Column2-Column1)/(Elements-1))*(Index-1)
**由于检测为negative: 亮--暗,所以测量矩阵需要角度往下,也就是加上180°
gen_measure_rectangle2 (Rowc, Colc, Angle+rad(180), DetecHeight/2, DetecWidth/2, Width, Height, 'nearest_neighbor', MeasureHandle)
measure_pos (Image, MeasureHandle,sigma, Threshold, trans, sel, RowEdge, ColumnEdge, Amplitude, Distance1)
RowEdgeList[Index-1]:= RowEdge
ColumnEdgeList[Index-1]:=ColumnEdge
gen_cross_contour_xld (Cross, RowEdge, ColumnEdge, 12, 0.785398)
clear_handle (MeasureHandle)
endif
endfor
*3.拟合直线
*生成xld轮廓
gen_contour_polygon_xld (Contour, RowEdgeList, ColumnEdgeList)
*Contour :输入轮廓
*‘tukey’ 使用Tukey权重函数进行鲁棒拟合
*-1: 最大点数(此处使用-1表示使用所有点)
* 0: 裁剪端点(0表示不裁剪)
*5: 迭代次数(对于鲁棒拟合)
*2: 拟合直线的阶数(1表示直线)拟合直线的阶数为2表示你正在使用二次多项式(即抛物线)来拟合数据点,而不是简单的直线(一阶多项式)。
*一阶(Degree=1):直线方程 y=a⋅x+b。 二阶(Degree=2):抛物线方程 y=a⋅x 2+b⋅x+c。
* 输出 RowBegin, ColBegin: 拟合直线起点的行和列坐标
* 输出 RowEnd, ColEnd: 拟合直线终点的行和列坐标
* Nr, Nc: 输出直线的方向向量(可选)
* 输出 点到直线的平均距离(可选)
fit_line_contour_xld(Contour, 'tukey', -1, 0, 5, 2, RowBegin, ColBegin, RowEnd, ColEnd, Nr, Nc, Dist)
gen_contour_polygon_xld(FittedLine, [RowBegin, RowEnd], [ColBegin, ColEnd])
dev_display(Image)
dev_set_color('red')
dev_set_line_width(2)
dev_display(FittedLine)
最终效果为: