1. 看一个案例
- 下图是电池UV点胶和热熔胶。
- 想测量胶水的宽度,然后将宽度以曲线的形式显示在窗口中。
2. 具体要求
- 只需关注W1、W2的技术要求
3. 解决方案和效果
- 首先使用blob分析将UV胶区域分割出来,然后抠图;
- 然后使用抓边工具/或Blob差分方法,测量胶水的宽度;
- 最后在窗口中画出坐标系,显示宽度变化曲线
4. 抓边工具方法
dev_update_off ()
dev_get_window (WindowHandle)
dev_set_line_width (2)
* Image Acquisition 01: Code generated by Image Acquisition 01
list_files ('', ['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
read_image (Image, ImageFiles[Index])
*通过Blob分析确定UV胶的大概位置
threshold (Image, Regions1, 240, 255)
erosion_rectangle1 (Regions1, RegionErosion, 11, 3)
connection (RegionErosion, ConnectedRegions)
select_shape (ConnectedRegions, SelectedRegions, ['area','row'], 'and', [31306,1676.7], [95838.7,2000])
smallest_rectangle2 (SelectedRegions, Row, Column, Phi, Length1, Length2)
LineRow1:=Row
LineCol1:=Column-Length1
LineRow2:=Row
LineCol2:=Column+Length1
*===================Gap=======================
* 1. 创建ROI draw_rake函数
Elements:=200
DetectHeight:=50
DetectWidth:=5
* draw_rake (Regions, WindowHandle, Elements, DetectHeight, DetectWidth, Row1, Column1, Row2, Column2)
* 2. 边缘测量 rake函数
Sigma:=3
Threshold:=5
Transition:='negative'
Select:='all'
dev_set_color ('white')
rake (Image, Regions, Elements, DetectHeight, DetectWidth, Sigma, Threshold,\
Transition, Select, LineRow1, LineCol1, LineRow2, LineCol2, ResultRows1, ResultColumns1)
* 3. 拟合直线 pts_to_best_line函数
* ActiveNum:=5
* pts_to_best_line (Line1, ResultRow, ResultColumn, ActiveNum, R1, C1, R2, C2)
Transition:='positive'
rake (Image, Regions, Elements, DetectHeight, DetectWidth, Sigma, Threshold, \
Transition, Select, LineRow1, LineCol1, LineRow2, LineCol2, ResultRows2, ResultColumns2)
* pts_to_best_line (Line2, ResultRow, ResultColumn, ActiveNum, R3, C3, R4, C4)
* 计算点对之间的距离
distance_pp (ResultRows1, ResultColumns1, ResultRows2, ResultColumns2, Distances)
gen_contour_polygon_xld (Contour1, ResultRows1, ResultColumns1)
gen_contour_polygon_xld (Contour2, ResultRows2, ResultColumns2)
* 显示
dev_set_color ('blue')
dev_display (Image)
dev_display (Contour1)
dev_display (Contour2)
*标准线所在行数列数
*像素与mm的换算关系 1mm = PMM pixel
PMM:=100
ScaleR:=15
offsetRow:=200
*不设置基准线,只保留上下限
mmStdA:=0.6
mmUpA:=0.3
mmLowA:=-0.2
mmStdB:=0.512
mmUpB:=0.25
mmLowB:=-0.122
mmAvoid:=3
mmAllLength:=285
mmStartA:=100
mmEndA:=mmStartA+mmAvoid
mmStartB:=mmStartA+mmAvoid
mmEndB:=mmStartA+mmAllLength
pixStartACol:=LineCol1
pixStartBCol:=LineCol1 + mmAvoid*PMM
pixEndACol:=pixStartBCol
pixEndBCol:=LineCol2
pixStdARow:=offsetRow + mmStdA*PMM*ScaleR
pixStdBRow:=offsetRow + (2*mmStdA-mmStdB)*PMM*ScaleR
pixUpARow:=pixStdARow-mmUpA*PMM*ScaleR
pixLowARow:=pixStdARow-mmLowA*PMM*ScaleR
pixUpBRow:=pixStdBRow-mmUpB*PMM*ScaleR
pixLowBRow:=pixStdBRow-mmLowB*PMM*ScaleR
*gen_contour_polygon_xld (StdLA, [pixStdARow,pixStdARow], [pixStartACol,pixEndACol])
*gen_contour_polygon_xld (StdLB, [pixStdBRow,pixStdBRow], [pixStartBCol,pixEndBCol])
*A区上下限
gen_contour_polygon_xld (UpLA, [pixUpARow,pixUpARow], [pixStartACol,pixEndACol])
gen_contour_polygon_xld (LowLA, [pixLowARow,pixLowARow], [pixStartACol,pixEndACol])
*B区上下限
gen_contour_polygon_xld (UpLB, [pixUpBRow,pixUpBRow], [pixStartBCol,pixEndBCol])
gen_contour_polygon_xld (LowLB, [pixLowBRow,pixLowBRow], [pixStartBCol,pixEndBCol])
*Y轴
gen_arrow_contour_xld (ArrowY, pixLowBRow+200, pixStartACol, pixUpARow-200, pixStartACol, 50, 50)
*实测线
RealRow:=1400 - Distances*ScaleR
gen_contour_polygon_xld (ContourReal, RealRow, ResultColumns1)
dev_set_color ('white')
dev_display (ArrowY)
dev_set_color ('red')
dev_display (UpLA)
dev_display (LowLA)
dev_display (UpLB)
dev_display (LowLB)
dev_set_color ('green')
dev_display (ContourReal)
stop()
endfor
dev_update_on ()
5. Blob差分方法
dev_update_off ()
dev_get_window (WindowHandle)
dev_set_line_width (2)
* Image Acquisition 01: Code generated by Image Acquisition 01
list_files ('', ['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
read_image (Image, ImageFiles[Index])
*通过Blob分析确定UV胶的大概位置
threshold (Image, Regions1, 240, 255)
erosion_rectangle1 (Regions1, RegionErosion, 11, 3)
connection (RegionErosion, ConnectedRegions)
select_shape (ConnectedRegions, SelectedRegions, ['area','row'], 'and', [31306,1676.7], [95838.7,2000])
smallest_rectangle2 (SelectedRegions, Row, Column, Phi, Length1, Length2)
LineRow1:=Row
LineCol1:=Column-Length1
LineRow2:=Row
LineCol2:=Column+Length1
*===================宽度=======================
smallest_rectangle1 (SelectedRegions, Row1, Column11, Row2, Column21)
gen_rectangle1 (Rectangle, Row1, Column11, Row2, Column21)
get_region_contour (SelectedRegions, Rows, Columns)
gen_region_points (SelectedRegions, Rows, Columns)
smallest_rectangle1 (SelectedRegions, UpperRow, Column1, LowerRow, Column2)
Distances := []
dev_set_color ('red')
dev_update_var ('off')
dev_update_time ('off')
dev_update_pc ('off')
for i := Column11+2 to Column21-2 by 1
gen_region_line (ScanLine, UpperRow, i, LowerRow, i)
dev_display (ScanLine)
intersection (SelectedRegions, ScanLine, BoundaryPoints)
get_region_points (BoundaryPoints, Rows, Columns)
Distances := [Distances,abs(Rows[|Rows| - 1] - Rows[0])]
endfor
dev_display (Image)
* 坐标系向下偏移像素
dev_set_color ('blue')
OffsetY:=1200
OffsetX:=LineCol1
* X轴
AxisXRow1:=OffsetY
AxisXCol1:=OffsetX
AxisXRow2:=OffsetY
AxisXCol2:=AxisXCol1+2*Length1
gen_arrow_contour_xld (AxisX, AxisXRow1, AxisXCol1, AxisXRow2, AxisXCol2, 50, 50)
* Y轴
AxisYRow1:=AxisXRow1
AxisYCol1:=OffsetX
AxisYRow2:=AxisXRow1-OffsetY
AxisYCol2:=OffsetX
gen_arrow_contour_xld (AxisY, AxisYRow1, AxisYCol1, AxisYRow2, AxisYCol2, 50, 50)
*实测线
PMM:=40
Mul:=20
RealRow:=AxisXRow1-Distances*Mul
tuple_gen_sequence (Column1+2, Column2-2, 1, Sequence)
gen_contour_polygon_xld (ContourReal, RealRow, Sequence)
*上下限
mmStdA:=0.6
mmUpA:=0.6+0.3
mmLowA:=0.6-0.2
mmStdB:=0.512
mmUpB:=0.512+0.25
mmLowB:=0.512-0.122
mmAvoid:=3
mmAllLength:=285
mmStartA:=100
mmEndA:=mmStartA+mmAvoid
mmStartB:=mmStartA+mmAvoid
mmEndB:=mmStartA+mmAllLength
pixStartACol:=AxisXCol1
pixEndACol:=AxisXCol1 + mmAvoid*PMM
pixStartBCol:=AxisXCol1 + mmAvoid*PMM
pixEndBCol:=AxisXCol2
pixStdARow:=AxisXRow1-mmStdA*PMM*Mul
pixStdBRow:=AxisXRow1-mmStdB*PMM*Mul
pixUpARow:=AxisXRow1-mmUpA*PMM*Mul
pixLowARow:=AxisXRow1-mmLowA*PMM*Mul
pixUpBRow:=AxisXRow1-mmUpB*PMM*Mul
pixLowBRow:=AxisXRow1-mmLowB*PMM*Mul
gen_contour_polygon_xld (StdLA, [pixStdARow,pixStdARow], [pixStartACol,pixEndACol])
gen_contour_polygon_xld (StdLB, [pixStdBRow,pixStdBRow], [pixStartBCol,pixEndBCol])
*A区上下限
gen_contour_polygon_xld (UpLA, [pixUpARow,pixUpARow], [pixStartACol,pixEndACol])
gen_contour_polygon_xld (LowLA, [pixLowARow,pixLowARow], [pixStartACol,pixEndACol])
*B区上下限
gen_contour_polygon_xld (UpLB, [pixUpBRow,pixUpBRow], [pixStartBCol,pixEndBCol])
gen_contour_polygon_xld (LowLB, [pixLowBRow,pixLowBRow], [pixStartBCol,pixEndBCol])
dev_set_color ('white')
dev_display (AxisX)
dev_display (AxisY)
dev_set_color ('green')
dev_display (ContourReal)
dev_set_color ('blue')
dev_display (StdLA)
dev_display (StdLB)
dev_set_color ('red')
dev_display (UpLA)
dev_display (LowLA)
dev_display (UpLB)
dev_display (LowLB)
stop()
endfor
dev_update_on ()
6. 两种方法的不同
- 抓边的方法精度精度更高,是亚像素级别的,但是存在有时抓不到变得风险;
- Blob差分方法精度不高,是像素级别的,但是稳定性更好;
- 实际项目中到底要用哪种方法,还需要具体情况具体分析。
7. 资源下载
https://download.csdn.net/download/weixin_38566632/37361354