缺陷检测解决策略之一:blob分析+特征分析 缺陷检测解决策略之一: blob分析+特征分析 缺陷检测解决策略之一: b l o b 分析 + 特征分析
示例1
* 读取图像
read_image ( Image, 'food/hazelnut_wafer_01' )
** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** 一 窗口显示设置** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** *
* 关闭窗口
dev_close_window ( )
* 打开窗口
dev_open_window_fit_image ( Image, 0 , 0 , - 1 , - 1 , WindowHandle)
* 关闭更新
dev_update_window ( 'off' )
* 设置显示线宽
dev_set_line_width ( 3 )
* 设置显示模式为边缘模式:margin
* dev_set_draw ( 'margin' )
* 设置显示字体大小
set_display_font ( WindowHandle, 20 , 'mono' , 'true' , 'false' )
** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** 二 算法处理:策略:Blob分析加特征(孔洞的面积和矩形度)分析** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** *
* 遍历缺陷图片
for Index := 1 to 24 by 1
* 1. 采集图像
read_image ( Image, 'food/hazelnut_wafer_' + Index$'.02' )
* 2. 图像分割: 二值化分割
binary_threshold ( Image, Foreground, 'smooth_histo' , 'light' , UsedThreshold)
* 3. 形态学处理 开运算(腐蚀)
opening_circle ( Foreground, FinalRegion, 8.5 )
* 计算孔洞面积
area_holes ( FinalRegion, AreaHoles)
* 计算矩形度
rectangularity ( FinalRegion, Rectangularity)
* 显示图像
dev_display ( Image)
* 用孔洞面积和矩形度特征,来判断NG/ OK
if ( AreaHoles > 300 or Rectangularity < 0.92 )
* 设置显示颜色为红色
dev_set_color ( 'red' )
Text := 'NG'
else
dev_set_color ( 'forest green' )
Text := 'OK'
endif
* 显示缺陷区域
dev_display ( FinalRegion)
* 显示文本
disp_message ( WindowHandle, Text, 'window' , 12 , 12 , '' , 'false' )
if ( Index < 24 )
* 在屏幕右下角显示“单击“运行”以继续”
disp_continue_message ( WindowHandle, 'black' , 'true' )
stop ( )
endif
endfor
示例2
* 平滑卷积X长度
SmoothX := 501
* 阈值偏置
ThresholdOffset := 25
* 最小缺陷大小
MinDefectSize := 50
* 极坐标分辨率
PolarResolution := 640
* 环大小
RingSize := 70
* 获取空区域对象
get_system ( 'store_empty_region' , StoreEmptyRegion)
set_system ( 'store_empty_region' , 'false' )
* 读取图像
read_image ( Image, 'bottles/bottle_mouth_01' )
* 更新设备
dev_update_off ( )
* 关闭窗口
dev_close_window ( )
dev_close_window ( )
* 打开固定大小窗口
dev_open_window_fit_image ( Image, 0 , 0 , 640 , 512 , WindowHandle1)
* 设置显示字体的大小
set_display_font ( WindowHandle1, 16 , 'mono' , 'true' , 'false' )
* 显示图像
dev_display ( Image)
* 设置显示模式
dev_set_draw ( 'margin' )
* 设置显示线宽
dev_set_line_width ( 3 )
* 打开固定大小窗口
dev_open_window_fit_size ( 0 , 648 , RingSize, PolarResolution, 150 , 512 , WindowHandle)
dev_set_draw ( 'margin' )
dev_set_line_width ( 3 )
dev_set_color ( 'red' )
* 遍历
for Index := 1 to 16 by 1
* 读取图像
read_image ( Image, 'bottles/bottle_mouth_' + Index$'.02' )
* 阈值分割
* 1. 获取输入图像的灰度直方图
* 2. 使用标准差为Sigma的一维高斯滤波器对直方图进行滤波
* 3. 计算滤波后的直方图的极小值
* 4. 以计算得到的极小值所对应的灰度值为分割阈值对图像进行分割
* 直方图阈值分割
auto_threshold ( Image, Regions, 2 )
* 选择分割区域
select_obj ( Regions, DarkRegion, 1 )
* 开运算
opening_circle ( DarkRegion, RegionOpening, 3.5 )
* 闭运算
closing_circle ( RegionOpening, RegionClosing, 25.5 )
* 填充
fill_up ( RegionClosing, RegionFillUp)
* 获取边界
boundary ( RegionFillUp, RegionBorder, 'outer' )
* 膨胀
dilation_circle ( RegionBorder, RegionDilation, 3.5 )
* 获取区域图像
reduce_domain ( Image, RegionDilation, ImageReduced)
* 获取边缘
edges_sub_pix ( ImageReduced, Edges, 'canny' , 0.5 , 20 , 40 )
* 分割轮廓
segment_contours_xld ( Edges, ContoursSplit, 'lines_circles' , 5 , 4 , 2 )
* 合并轮廓
union_cocircular_contours_xld ( ContoursSplit, UnionContours, 0.9 , 0.5 , 0.5 , 200 , 50 , 50 , 'true' , 1 )
* 轮廓个数
length_xld ( UnionContours, Length)
* 选择对象
select_obj ( UnionContours, LongestContour, sort_index( Length) [ | Length| - 1 ] + 1 )
* 拟合圆轮廓
fit_circle_contour_xld ( LongestContour, 'ahuber' , - 1 , 0 , 0 , 3 , 2 , Row, Column, Radius, StartPhi, EndPhi, PointOrder)
*
* Part 2 : Transform the ring- shaped bottle neck region to a rectangle
* 生成圆
gen_circle ( Circle, Row, Column, Radius)
* 膨胀
dilation_circle ( Circle, RegionDilation, 5 )
* 腐蚀
erosion_circle ( Circle, RegionErosion, RingSize - 5 )
* 区域相减
difference ( RegionDilation, RegionErosion, RegionDifference)
* 获取区域图像
reduce_domain ( Image, RegionDifference, ImageReduced)
* 极坐标转换
polar_trans_image_ext ( ImageReduced, ImagePolar, Row, Column, 0 , rad( 360 ) , Radius - RingSize, Radius, PolarResolution, RingSize, 'nearest_neighbor' )
*
* Part 3 : Find defects with a dynamic threshold
* 灰度值拉伸到0 - 255
scale_image_max ( ImagePolar, ImageScaleMax)
* 均值滤波
mean_image ( ImageScaleMax, ImageMean, SmoothX, 3 )
* 动态阈值分割
dyn_threshold ( ImageScaleMax, ImageMean, Regions1, 55 , 'not_equal' )
* 连通
connection ( Regions1, Connection)
* 根据特征选取区域
select_shape ( Connection, SelectedRegions, 'height' , 'and' , 9 , 99999 )
* 闭运算
closing_rectangle1 ( SelectedRegions, RegionClosing1, 10 , 20 )
* 区域合并
union1 ( RegionClosing1, RegionUnion)
* re- transform defect regions for visualization
polar_trans_region_inv ( RegionUnion, XYTransRegion, Row, Column, 0 , rad( 360 ) , Radius - RingSize, Radius, PolarResolution, RingSize, 1280 , 1024 , 'nearest_neighbor' )
*
* Part 4 : Display results
* 显示结果
dev_set_window ( WindowHandle1)
dev_display ( Image)
dev_set_color ( 'blue' )
dev_display ( RegionDifference)
dev_set_color ( 'red' )
dev_display ( XYTransRegion)
* display polar transformed inspected region with results
* The image and resulting region are rotated by 90 degrees
* only for visualization purposes! ( I. e. to fit better on the screen)
* The rotation is NOT necessary for the detection algorithm.
dev_set_window ( WindowHandle)
* 旋转图像
rotate_image ( ImagePolar, ImageRotate, 90 , 'constant' )
dev_display ( ImageRotate)
* 区域计数
count_obj ( RegionUnion, Number)
if ( Number > 0 )
mirror_region ( RegionUnion, RegionMirror, 'diagonal' , PolarResolution)
mirror_region ( RegionMirror, RegionMirror, 'row' , PolarResolution)
dev_display ( RegionMirror)
disp_message ( WindowHandle1, 'Not OK' , 'window' , 12 , 12 , 'red' , 'false' )
else
disp_message ( WindowHandle1, 'OK' , 'window' , 12 , 12 , 'forest green' , 'false' )
endif
if ( Index < 16 )
disp_continue_message ( WindowHandle1, 'black' , 'true' )
stop ( )
endif
endfor
* Reset system parameters
set_system ( 'store_empty_region' , StoreEmptyRegion)
示例3: blob分析(局部二值化)+特征分析
* 窗口设置
dev_update_window ( 'off' )
* 读取图像
read_image ( Image, 'plastic_mesh/plastic_mesh_01' )
* 关闭窗口
dev_close_window ( )
* 获取图像大小
get_image_size ( Image, Width, Height)
* 设置窗口显示
dev_open_window_fit_image ( Image, 0 , 0 , Width, Height, WindowHandle)
set_display_font ( WindowHandle, 18 , 'mono' , 'true' , 'false' )
dev_set_draw ( 'margin' )
dev_set_line_width ( 3 )
* 遍历
for J := 1 to 14 by 1
* 读取图像
read_image ( Image, 'plastic_mesh/plastic_mesh_' + J$'02' )
* 中值滤波
mean_image ( Image, ImageMean, 49 , 49 )
* 动态阈值分割
dyn_threshold ( Image, ImageMean, RegionDynThresh, 5 , 'dark' )
* 连通
connection ( RegionDynThresh, ConnectedRegions)
* 通过面积选取特征区域
select_shape ( ConnectedRegions, ErrorRegions, 'area' , 'and' , 500 , 99999 )
* 计数
count_obj ( ErrorRegions, NumErrors)
* 显示结果
dev_display ( Image)
dev_set_color ( 'red' )
dev_display ( ErrorRegions)
* If the number of errors exceeds zero, the message 'Mesh not
* OK' is displayed. Otherwise the web is undamaged
* and 'Mesh OK' is displayed.
if ( NumErrors > 0 )
disp_message ( WindowHandle, 'Mesh not OK' , 'window' , 24 , 12 , 'black' , 'true' )
else
disp_message ( WindowHandle, 'Mesh OK' , 'window' , 24 , 12 , 'black' , 'true' )
endif
* If the sequence number of the image to be inspected is
* lower than 14 , the request to press 'Run' to continue appears.
* If the last image is read, pressing 'Run' will clear the SVM.
if ( J < 14 )
disp_continue_message ( WindowHandle, 'black' , 'true' )
stop ( )
endif
endfor
示例4:blob分析(定位)+特征分析
* 窗口设置
dev_close_window ( )
dev_update_off ( )
* 读取图像
read_image ( ImageOrig, 'blister/blister_reference' )
* 窗口显示设置
dev_open_window_fit_image ( ImageOrig, 0 , 0 , - 1 , - 1 , WindowHandle)
set_display_font ( WindowHandle, 14 , 'mono' , 'true' , 'false' )
dev_set_draw ( 'margin' )
dev_set_line_width ( 3 )
* 获取通道1 图像
access_channel ( ImageOrig, Image1, 1 )
* 阈值分割
threshold ( Image1, Region, 90 , 255 )
* 进行convex变换
shape_trans ( Region, Blister, 'convex' )
* 获取角度
orientation_region ( Blister, Phi)
* 获取区域的面积和中心
area_center ( Blister, Area1, Row, Column)
* 生成仿射变换矩阵
vector_angle_to_rigid ( Row, Column, Phi, Row, Column, 0 , HomMat2D)
* 进行仿射变换
affine_trans_image ( ImageOrig, Image2, HomMat2D, 'constant' , 'false' )
* 生成空对象
gen_empty_obj ( Chambers)
for I := 0 to 4 by 1
Row := 88 + I * 70
for J := 0 to 2 by 1
Column := 163 + J * 150
* 生成矩形
gen_rectangle2 ( Rectangle, Row, Column, 0 , 64 , 30 )
* 连结矩形
concat_obj ( Chambers, Rectangle, Chambers)
endfor
endfor
* 对区域进行仿射变换
affine_trans_region ( Blister, Blister, HomMat2D, 'nearest_neighbor' )
* 区域相减
difference ( Blister, Chambers, Pattern)
* 区域合并
union1 ( Chambers, ChambersUnion)
* 获取角度变换
orientation_region ( Blister, PhiRef)
* 加180
PhiRef := rad( 180 ) + PhiRef
* 获取区域的中心和面积
area_center ( Blister, Area2, RowRef, ColumnRef)
* 遍历
Count := 6
for Index := 1 to Count by 1
* 读取图像
read_image ( Image, 'blister/blister_' + Index$'02' )
* 阈值分割
threshold ( Image, Region, 90 , 255 )
* 连通
connection ( Region, ConnectedRegions)
* 根据面积选取区域
select_shape ( ConnectedRegions, SelectedRegions, 'area' , 'and' , 5000 , 9999999 )
* 进行convex变换
shape_trans ( SelectedRegions, RegionTrans, 'convex' )
* 获取角度
orientation_region ( RegionTrans, Phi)
* 获取面积和中心
area_center ( RegionTrans, Area3, Row, Column)
* 生成仿射矩阵
vector_angle_to_rigid ( Row, Column, Phi, RowRef, ColumnRef, PhiRef, HomMat2D)
* 图像进行仿射变换
affine_trans_image ( Image, ImageAffineTrans, HomMat2D, 'constant' , 'false' )
* 获取区域图像
reduce_domain ( ImageAffineTrans, ChambersUnion, ImageReduced)
* 图像分解成三个通道
decompose3 ( ImageReduced, ImageR, ImageG, ImageB)
* 对B通道进行阈值分割
var_threshold ( ImageB, Region, 7 , 7 , 0.2 , 2 , 'dark' )
* 连通
connection ( Region, ConnectedRegions0)
* 闭运算
closing_rectangle1 ( ConnectedRegions0, ConnectedRegions, 3 , 3 )
* 填充
fill_up ( ConnectedRegions, RegionFillUp)
* 根据面积选取区域
select_shape ( RegionFillUp, SelectedRegions, 'area' , 'and' , 1000 , 99999 )
* 开运算
opening_circle ( SelectedRegions, RegionOpening, 4.5 )
* 连通
connection ( RegionOpening, ConnectedRegions)
* 根据面积选取区域
select_shape ( ConnectedRegions, SelectedRegions, 'area' , 'and' , 1000 , 99999 )
* 进行convex变换
shape_trans ( SelectedRegions, Pills, 'convex' )
* 计数
count_obj ( Chambers, Number)
* 生成空对象
gen_empty_obj ( WrongPill)
* 生成空对象
gen_empty_obj ( MissingPill)
* 遍历
for I := 1 to Number by 1
* 选取对象
select_obj ( Chambers, Chamber, I)
* 交集
intersection ( Chamber, Pills, Pill)
* 获取区域中心和面积
area_center ( Pill, Area, Row1, Column1)
* 面积大于0
if ( Area > 0 )
* 湖区灰度值的最值和范围
min_max_gray ( Pill, ImageB, 0 , Min, Max, Range)
if ( Area < 3800 or Min < 60 )
* 连结对象
concat_obj ( WrongPill, Pill, WrongPill)
endif
else
* 连结对象
concat_obj ( MissingPill, Chamber, MissingPill)
endif
endfor
* 显示结果
dev_clear_window ( )
dev_display ( ImageAffineTrans)
dev_set_color ( 'forest green' )
count_obj ( Pills, NumberP)
count_obj ( WrongPill, NumberWP)
count_obj ( MissingPill, NumberMP)
dev_display ( Pills)
if ( NumberMP > 0 or NumberWP > 0 )
disp_message ( WindowHandle, 'Not OK' , 'window' , 12 , 12 + 600 , 'red' , 'true' )
else
disp_message ( WindowHandle, 'OK' , 'window' , 12 , 12 + 600 , 'forest green' , 'true' )
endif
*
Message := '# Correct pills: ' + ( NumberP - NumberWP)
Message[ 1 ] := '# Wrong pills : ' + NumberWP
Message[ 2 ] := '# Missing pills: ' + NumberMP
*
Colors := gen_tuple_const( 3 , 'black' )
if ( NumberWP > 0 )
Colors[ 1 ] := 'red'
endif
if ( NumberMP > 0 )
Colors[ 2 ] := 'red'
endif
disp_message ( WindowHandle, Message, 'window' , 12 , 12 , Colors, 'true' )
dev_set_color ( 'red' )
dev_display ( WrongPill)
dev_display ( MissingPill)
if ( Index < Count)
disp_continue_message ( WindowHandle, 'black' , 'true' )
endif
stop ( )
endfor
极坐标转换+图像增强+动态阈值分割
******************************************************************
************************* 工业视觉应用一般流程 *********************
******************************************************************
****************************** 0.窗口显示设置 ******************************
dev_get_window ( WindowHandle)
dev_set_draw ( 'margin' )
* 设置显示字体大小
set_display_font ( WindowHandle, 20, 'mono' , 'true' , 'false' )
* dev_update_window ( 'off' )
ScaleFactor : = 0.4
****************************** 1.读取图像 ******************************
read_image ( Image2, 'D:/作业/划伤/D2-3-2.bmp' )
****************************** 2.定位(Blob分析) *********************************
*** 定位内圆
* <2.1> 阈值分割
threshold ( Image2, Region, 240, 255)
* <2.2> 连通
connection ( Region, ConnectedRegions)
* <2.3> 填充
fill_up ( ConnectedRegions, RegionFillUp)
* <2.4> 通过特征筛选特征区域
select_shape_std ( RegionFillUp, SelectedRegions, 'max_area' , 70)
smallest_circle ( SelectedRegions, Row, Column, Radius1)
gen_circle ( CircleIn, Row, Column, Radius1)
*** 定位外圆
* <2.1> 阈值分割
threshold ( Image2, Region, 40, 190)
* <2.2> 连通
connection ( Region, ConnectedRegions)
* <2.3> 填充
fill_up ( ConnectedRegions, RegionFillUp)
* <2.4> 通过特征筛选特征区域
select_shape_std ( RegionFillUp, SelectedRegions, 'max_area' , 70)
smallest_circle ( SelectedRegions, Row, Column, Radius2)
gen_circle ( CircleOut, Row, Column, Radius2)
****************************** 3.获取ROI(感兴趣)区域 ******************
* 内圆往里面一点(膨胀一点)
dilation_circle ( CircleIn, RegionDilation1, 23.5)
* 外圆往里面一点(腐蚀)
erosion_circle ( CircleOut, RegionErosion2, 23.5)
* 区域相减
difference ( RegionErosion2, RegionDilation1, RegionDifference)
* 获取区域图像
reduce_domain ( Image2, RegionDifference, ImageReduced)
****************************** 4.图像预处理 *****************************
* 获取图像大小
get_image_size ( ImageReduced, Width, Height)
* 彩色图转灰度图
rgb1_to_gray ( ImageReduced, GrayImage)
* 极坐标转换
RadiusSize : =Radius2-Radius1
PolrLength : =3.14*( Radius2+Radius1)
* polar_trans_image_ext ( GrayImage, PolarTransImage1, 256, 256, 0, 6.28319, 0, 100, 512, 512, 'nearest_neighbor' )
polar_trans_image_ext ( GrayImage, PolarTransImage, Row, Column, 0, rad ( 360) , Radius1, Radius1+RadiusSize, PolrLength, RadiusSize, 'nearest_neighbor' )
* 获取图像大
get_image_size ( PolarTransImage, Width1, Height1)
* 中值滤波(去噪)
median_image ( PolarTransImage, ImageMedian1, 'circle' , 3, 'mirrored' )
* 纹理滤波(增强)
texture_laws ( PolarTransImage, ImageTexture1, 'le' , 2, 5)
* 均值滤波(去噪)
mean_image ( ImageTexture1, ImageMean, 3, 3)
* 缩放,增强图像(增强)
scale_image ( ImageMean, ImageScaled, 2, -50)
****************************** 5.图像算法处理 ***************************
* 均值滤波 1
mean_image ( ImageScaled, ImageMean1, 2, 10)
* 均值滤波2
mean_image ( ImageScaled, ImageMean2, 500, 10)
* 动态阈值分割
* dyn_threshold ( ImageMean1, ImageMean2, Region1, 30, 'not_equal' )
* 亮部缺陷
dyn_threshold ( ImageMean1, ImageMean2, Region1, 30, 'light' )
* 暗部缺陷
dyn_threshold ( ImageMean1, ImageMean2, Region2, 30, 'dark' )
* 区域合并
union2 ( Region1, Region2, Region1)
* scale_image_max ( ImageTexture1, ImageScaleMax)
* threshold ( ImageScaled, Region1, 50, 255)
* 连通
connection ( Region1, ConnectedRegions2)
* 通过面积和高度进行缺陷区域筛选
select_shape ( ConnectedRegions2, SelectedRegions, ['area' , 'height' ], 'and' , [600, 20], [99999, Height1])
* 区域合并
union1 ( SelectedRegions, RegionUnion)
* 极坐标反转
polar_trans_region_inv ( RegionUnion, XYTransRegion, Row, Column, 0, rad ( 360) , Radius1, Radius1+RadiusSize, Width1, Height1, Width, Height, 'nearest_neighbor' )
* 膨胀
dilation_circle ( XYTransRegion, RegionDilation1, 3.5)
* 连通
connection ( RegionDilation1, ConnectedRegions1)
****************************** 6.结果输出 *******************************
* 计算缺陷个数
count_obj ( ConnectedRegions1, Number)
* 显示NG
if ( Number>0)
dev_set_color ( 'red' )
Text : = 'NG'
* 显示缺陷区域
dev_display ( Image2)
dev_display ( XYTransRegion)
* 显示文本
disp_message ( WindowHandle, Text, 'window' , 12, 12, '' , 'false' )
endif