函数使用measure_pos检测边缘点,里面加了计算距离的筛选规则,用规则去挑出更符合需要的点位。
函数原理:
1、使用灰度投影求出可能是边缘的几根线,再使用参数自己选择需要哪条边。这条边作为边缘的参考边。
2、使用measure_pos求出边缘的所有点位,计算点位于参考边的距离,判断这个距离是否满足参数要求,不满足的直接剔除。将剩下的点位生成我们需要的直线。
函数封装:
Rows := []
Columns := []
LineParam := []
gen_empty_obj (OutContour)
try
*RecRow, RecColumn, RecPhi, RecLength1, RecLength2:直线ROI区域rectagnle2参数
*Transition 卡尺朝向;SmoothSigma 平滑系数;Threshold 边缘梯度;
*LineIndex 边缘索引,0-第一条边,-1-最后一条边;RecHeight-测量矩形高度;RecWidth-测量矩形宽度
******第一步,用两个一维测量算子,求出直线两点,并得到直线方位角
smallest_rectangle2 (FindRectangle, RecRow, RecColumn, RecPhi, RecLength1, RecLength2)
smallest_rectangle1(FindRectangle, Row11, Column11, Row22, Column22)
reduce_domain (ImageEnhanced, FindRectangle, ImageReduced)
crop_domain (ImageReduced, ImagePart)
********
if(RecPhi>-rad(45))
Angle:=RecPhi-rad(90)
else
Angle:=RecPhi+rad(90)
endif
***************第二步,根据直线角度,生成测量矩形,灰度投影,得到边缘位置集合
get_image_size(ImagePart, Width, Height)
gen_rectangle2(Rectangle3,Height/2, Width/2,Angle, RecLength2-5, RecLength1-5)
gen_contour_polygon_xld(Contour, [Height/2-RecLength1*sin(RecPhi),Height/2+RecLength1*sin(RecPhi)], [Width/2+RecLength1*cos(RecPhi),Width/2-RecLength1*cos(RecPhi)])
*
gen_measure_rectangle2( Height/2, Width/2,Angle, RecLength2-5, RecLength1-5, Width, Height, 'nearest_neighbor', MeasureHandle2)
measure_projection(ImagePart, MeasureHandle2, GrayValues)
create_funct_1d_array(GrayValues, Function)
smooth_funct_1d_gauss (Function, SmoothSigma, SmoothedFunction)
derivate_funct_1d(SmoothedFunction, 'first', Derivative)
local_min_max_funct_1d(Derivative, 'strict_min_max', 'false', Min, Max)
funct_1d_to_pairs(Derivative, XValues, YValues)
*
minIndex:=[]
for Index := 0 to |Min|-1 by 1
if (YValues[Min[Index]]<-Threshold)
minIndex:=[minIndex,Min[Index]]
endif
endfor
*
maxIndex:=[]
for Index := 0 to |Max|-1 by 1
if (YValues[Max[Index]]>Threshold)
maxIndex:=[maxIndex,Max[Index]]
endif
endfor
****
*
if (|maxIndex|=0 and Transition == 'positive')
return()
endif
*
if (|minIndex|=0 and Transition == 'negative')
return()
endif
***************第三步,根据参数配置筛选出参考边缘轮廓
lineIndex:=-9999
if (Transition == 'positive')
if (LineIndex>=0 and |maxIndex|> LineIndex)
lineIndex := maxIndex[LineIndex]
elseif(|maxIndex|>= abs(LineIndex))
lineIndex := maxIndex[|maxIndex|+LineIndex]
endif
else
if (LineIndex>=0 and |minIndex|> LineIndex)
lineIndex := minIndex[LineIndex]
elseif(|minIndex|>= abs(LineIndex))
lineIndex := minIndex[|minIndex|+LineIndex]
endif
endif
if(lineIndex=-9999)
return()
endif
*得到参考边缘,将矩形中线平移至参考边缘位置
if(RecPhi>=-rad(45))
gen_parallel_contour_xld(Contour, LineContour1, 'regression_normal', -lineIndex+(RecLength2-5))
else
gen_parallel_contour_xld(Contour, LineContour1, 'regression_normal', lineIndex-(RecLength2-5))
endif
get_contour_xld(LineContour1, Row1, Col1)
Row1:=Row1+Row11
Col1:=Col1+Column11
****************第四步,根据参考边缘,筛选实际边缘点
gen_contour_polygon_xld(LineContour, Row1, Col1)
*
tuple_mean(Row1,RCenter)
tuple_mean(Col1,CCenter)
*
gen_empty_obj(Crosses)
rows:=[]
cols:=[]
*一维卡尺测量点位
get_image_size(Image, Width, Height)
RecHeight := RecLength2
RecWidth := NumDistance
for i := -RecLength1+RecWidth to RecLength1-RecWidth by RecWidth
row:=RCenter-i*sin(RecPhi)
col:=CCenter+i*cos(RecPhi)
gen_rectangle2 (Rectangle1, row, col, Angle, RecHeight, RecWidth)
gen_measure_rectangle2 (row, col, Angle, RecHeight, RecWidth, Width, Height, 'nearest_neighbor', MeasureHandle)
if (Transition == 'positive')
measure_pos(Image, MeasureHandle, 1, 5, 'positive', 'all', RowEdge, ColumnEdge, Amplitude, Distance)
else
measure_pos(Image, MeasureHandle, 1, 5, 'negative', 'all', RowEdge, ColumnEdge, Amplitude, Distance)
endif
gen_cross_contour_xld (Cross, RowEdge, ColumnEdge, 30, 0.785398)
***
if (|RowEdge|=0)
continue
else
d := 9999
for k := 0 to |RowEdge|-1 by 1
distance_pc (LineContour, RowEdge[k], ColumnEdge[k], DistanceMin, DistanceMax)
if (DistanceMin<d) //循环将每次的最小距离作为判断,逐渐提高判断要求
d := DistanceMin
if (d<MinDistance)
row := RowEdge[k]
col := ColumnEdge[k]
endif
endif
endfor
if (row!=0)
gen_cross_contour_xld (Cross, row, col, 10, 0.785398)
Rows := [Rows,row]
Columns := [Columns,col]
concat_obj (Crosses, Cross, Crosses)
endif
endif
endfor
if(|Rows|<2)
throw ([201005,''])
endif
*得到点位,拟合直线
gen_contour_polygon_xld (Contour, Rows, Columns)
fit_line_contour_xld (Contour, 'tukey', -1, 0, 5, 2, RowBegin, ColBegin, RowEnd, ColEnd, Nr, Nc, Dist)
LineParam:=[RowBegin, ColBegin, RowEnd, ColEnd]
gen_contour_polygon_xld(Line, [RowBegin,RowEnd], [ColBegin,ColEnd])
*测量轮廓
concat_obj (OutContour, Rectangle1, OutContour)
concat_obj (OutContour, Crosses, OutContour)
catch (Exception)
endtry
return ()
这个函数稍微有一点绕,还是需要看代码跑一下,这个能加深理解。