缺陷检测解决策略之一: blob分析+特征分析

本文详细介绍了几种基于blob分析和特征分析的缺陷检测策略,包括利用孔洞面积和矩形度等特征判断产品质量,通过动态阈值分割和图像增强技术检测复杂背景下的细微缺陷。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

缺陷检测解决策略之一:blob分析+特征分析 缺陷检测解决策略之一: blob分析+特征分析缺陷检测解决策略之一:blob分析+特征分析

示例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




评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值