Home
对于检测表面是具有一定纹理的比如:布匹、皮革、塑料等,针对这一类表面的检测就不能单纯依靠帧差或者背景差来完成,这种情况下,通过将图像变换到频域进行处理,提取缺陷分量后反变换到时域,然后通过Blob分析获得缺陷的具体位置。
代码示例如下:
* 首先,创建合适的带通滤波
* 然后,输入图像在频域中进行傅里叶变换和滤波,以便增强高频信息
* 最后,再被转换回空间域,增强的缺陷通过形态学进行之后的处理
dev_update_off ()
dev_close_window ()
* 读图像
read_image (Image, 'surface_scratch')
* 翻转图像,亮变暗 暗变量
invert_image (Image, ImageInverted)
* 获取图像宽高
get_image_size (Image, Width, Height)
dev_open_window (0, 0, Width, Height, 'black', WindowHandle)
set_display_font (WindowHandle, 16, 'mono', 'true', 'false')
dev_display (Image)
*
* Optimize the speed of the fast fourier transform
* 优化快速傅里叶变换的速度
* Message := 'Optimize the speed of the fast fourier transform.'
* Message[1] := 'Please wait...'
* disp_message (WindowHandle, Message, 'window', 12, 12, 'black', 'true')
* optimize_rft_speed (Width, Height, 'standard')
* disp_continue_message (WindowHandle, 'black', 'true')
* stop ()
*
* Enhance the scratches by filtering in the frequency domain
* 通过在频域中滤波来增强划痕
* 生成具有正弦形状的带通滤波器
gen_sin_bandpass (ImageBandpass, 0.4, 'none', 'rft', Width, Height)
* 对一幅图片的实部进行快速傅里叶变换的计算,将图像转为傅里叶图像
* 参数为'to_freq',输出图像为复数形式
* ImageInverted:输入的图片(输入图像需要为背景为暗,前景为亮的图像,一般需要先要将原始图像反转)
* ImageFFT:傅里叶变换后输出的图片
* 'to_freq':变换方向,傅里叶变换
* 'none':变换因子的规范
* 'complex':输出图片的数据类型,输出图像为复数形式
* Width: 图像的宽
rft_generic (ImageInverted, ImageFFT, 'to_freq', 'none', 'complex', Width)
* 对图片用滤波器在频域进行卷积运算
* ImageFFT: 输入的图片
* ImageBandpass:频域滤波器
* ImageConvol:计算后的输出图像
convol_fft (ImageFFT, ImageBandpass, ImageConvol)
* 对滤波后的图片进行傅里叶反变换
* 参数为'from_freq',输入图像为复数形式
rft_generic (ImageConvol, Lines, 'from_freq', 'n', 'byte', Width)
*
* Segment the scratches by using morphology
* 使用形态分割划痕
* 二值化
threshold (Lines, Region, 5, 255)
* 获得连通域
connection (Region, ConnectedRegions)
* 特征直方图,按照面积特征选择区域
select_shape (ConnectedRegions, SelectedRegions, 'area', 'and', 5, 5000)
* 膨胀
dilation_circle (SelectedRegions, RegionDilation, 5.5)
* 区域联合成一个区域
union1 (RegionDilation, RegionUnion)
* 抠图
reduce_domain (Image, RegionUnion, ImageReduced)
* 检测线条及其宽度
* 输出亚像素直线轮廓
lines_gauss (ImageReduced, LinesXLD, 0.8, 3, 5, 'dark', 'false', 'bar-shaped', 'false')
* 联合直线亚像素轮廓
union_collinear_contours_xld (LinesXLD, UnionContours, 40, 3, 3, 0.2, 'attr_keep')
* 按照轮廓的总长度来选择亚像素轮廓
select_shape_xld (UnionContours, SelectedXLD, 'contlength', 'and', 15, 1000)
* 由亚像素轮廓生成区域
gen_region_contour_xld (SelectedXLD, RegionXLD, 'filled')
* 区域联合
union1 (RegionXLD, RegionUnion)
* 膨胀
dilation_circle (RegionUnion, RegionScratches, 10.5)
*
* Display the results
* 显示标记出来的的直线划痕
dev_set_draw ('margin')
dev_set_line_width (3)
dev_set_colored (12)
dev_display (Image)
dev_display (RegionScratches)
重点说明:
频域处理部分的过程为:
1)先生成一个滤波器,此处生成的是正弦形状的带通滤波,使用的算子为gen_sin_bandpass。
2)然后再进行图像的傅里叶变换,使用的算子为rft_generic,此处需要注意参数的使用。
3)使用之前的滤波器,对图像在频域进行卷积计算,从而增强高频信息。
4)最后对图像进行傅里叶反变换,使用的算子依然是rft_generic,注意和第二步中的参数进行区分。在这一步,即得到了我们平时进行Blob分析的图像。
之后的处理分为三部分:
1)第一部分,先进行Blob分析后,筛选掉一些杂点。然后提取出保留区域所对应的图像。
2)第二部分进行亚像素处理,先提取出亚像素轮廓,使用的是lines_gauss算子;然后按照轮廓总长度进行轮廓筛选,从而得到划痕的亚像素轮廓。至此,已经得到划痕了。
3)第三部分进行划痕区域的处理,先将亚像素轮廓转为区域,使用的算子是gen_region_contour_xld;得到划痕轮廓之后就可以将划痕标记出来了。
执行流程:
待处理图像:

带通滤波器作为频域中的图像:

待进行Blob分析的图像:

提取完亚像素轮廓:

划痕区域:

在原图中标记出划痕:
