理论基础
具有一定纹理特征的图像,纹理可以理解为条纹,如布匹、木板、纸张等材质容易出现。
需要提取对比度低或者信噪比低的特征。
图像尺寸较大或者需要与大尺寸滤波器进行计算,此时转换至频域计算,具有速度优势。因为空间域滤波为卷积过程(加权求和),频域计算直接相乘。
一个是生成合适的滤波器;
一个是空间域和频域之间的转换。
gen_std_bandpass, gen_sin_bandpass, gen_gauss_filter, gen_mean_filter, gen_derivative_filter, gen_bandpass, gen_bandfilter, gen_highpass, gen_lowpass
空间域和频域之间的转换,主要有如下两个关键算子:
rft_generic fft_generic
举例说明
*《Halcon机器视觉算法原理与编程实战》16-1 *清空当前窗口 dev_close_window () *读取测试图像 read_image (Image, 'data/cloth1') *获取图像的宽 get_image_size (Image, Width, Height) *创建显示窗口,并设置窗口及绘制参数 dev_open_window_fit_size (0, 0, Width, Height, -1, -1, WindowHandle) dev_display (Image) dev_set_draw ('margin') dev_set_line_width (3) dev_set_color ('red') *创建一个高斯滤波器,用于将傅里叶转换后的图像进行滤波 gen_gauss_filter (GaussFilter, 3.0, 3.0, 0.0, 'none', 'rft', Width, Height) *开始检测 *将测试图像转化为单通道的灰度图像 rgb1_to_gray (Image, ImageGray) *对灰度图像进行颜色反转 invert_image (ImageGray, ImageInvert) *对反转后的图像进行傅里叶变换 rft_generic (ImageInvert, ImageFFT, 'to_freq', 'none', 'complex', Width) *对傅里叶图像做卷积,使用之前创建的高斯滤波器作为卷积核 convol_fft (ImageFFT, GaussFilter, ImageConvol) *将卷积后的傅里叶图像还原为空间域图像。可见图像的突变部分得到了增强 rft_generic (ImageConvol, ImageFiltered, 'from_freq', 'n', 'real', Width) *设置提取线条的参数 calculate_lines_gauss_parameters (17, [25,3], Sigma, Low, High) *将图像中的有灰度差异的线条提取出来 lines_gauss (ImageFiltered, Lines, Sigma, Low, High, 'dark', 'true', 'gaussian', 'true') *将提取出的结果显示出来 dev_display (Image) dev_display (Lines)
2、傅里叶变换之划痕检测
*微信公众号--机器视觉那些事儿 *检测-FFT傅里叶变换之划痕检测 *对于检测表面是具有一定纹理的比如:布匹、皮革、塑料等,针对这一类表面的检测就不能单纯依靠帧差或者背景差来完成, *这种情况下,通过将图像变换到频域进行处理,提取缺陷分量后反变换到时域,然后通过Blob分析获得缺陷的具体位置。 *重点说明: *频域处理部分的过程为: *1)先生成一个滤波器,此处生成的是正弦形状的带通滤波,使用的算子为gen_sin_bandpass。 *2)然后再进行图像的傅里叶变换,使用的算子为rft_generic,此处需要注意参数的使用。 *3)使用之前的滤波器,对图像在频域进行卷积计算,从而增强高频信息。 *4)最后对图像进行傅里叶反变换,使用的算子依然是rft_generic,注意和第二步中的参数进行区分。在这一步,即得到了我们平时进行Blob分析的图像。 *之后的处理分为三部分: *1)第一部分,先进行Blob分析后,筛选掉一些杂点。然后提取出保留区域所对应的图像。 *2)第二部分进行亚像素处理,先提取出亚像素轮廓,使用的是lines_gauss算子;然后按照轮廓总长度进行轮廓筛选,从而得到划痕的亚像素轮廓。至此,已经得到划痕了。 *3)第三部分进行划痕区域的处理,先将亚像素轮廓转为区域,使用的算子是gen_region_contour_xld;得到划痕轮廓之后就可以将划痕标记出来了。 * 首先,创建合适的带通滤波 * 然后,输入图像在频域中进行傅里叶变换和滤波,以便增强高频信息 * 最后,再被转换回空间域,增强的缺陷通过形态学进行之后的处理 dev_update_off () dev_close_window () * 读图像 read_image (Image, '检测-FFT傅里叶变换之划痕检测.png') *彩色转灰度图 count_channels (Image, Channels) if (Channels == 3 or Channels == 4) rgb1_to_gray (Image, Image) endif * 翻转图像,亮变暗 暗变量 invert_image (Image, ImageInverted) * 获取图像宽高 get_image_size (Image, Width, Height) * dev_open_window (0, 0, Width, Height, 'black', WindowHandle) dev_open_window_fit_image (Image, 0, 0, -1, -1, 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)
3、木板划痕检测
*http://www.ihalcon.com/read-13031-1.html *缺陷检测,将木板的划痕提取出来 dev_update_off () dev_close_window () read_image (Image, '缺陷检测木板划痕提取.jpg') *彩色转灰度图 count_channels (Image, Channels) if (Channels == 3 or Channels == 4) rgb1_to_gray (Image, Image) endif get_image_size (Image, Width, Height) dev_open_window_fit_size (0, 0, Width, Height, -1, -1, WindowHandle) dev_display (Image) *傅里叶变换去背景 fft_generic (Image, ImageFFT, 'to_freq', -1, 'sqrt', 'dc_center', 'complex') gen_rectangle2 (Rectangle1, 308.5, 176.56, rad(-0), 179.4, 7.725) gen_rectangle2 (Rectangle2, 306.955, 175, rad(-90), 180.765, 4.68) union2 (Rectangle1, Rectangle2, UnionRectangle) paint_region (UnionRectangle, ImageFFT, ImageResult, 0, 'fill') fft_generic (ImageResult, ImageFFT1, 'from_freq', 1, 'sqrt', 'dc_center', 'byte') *提取划痕 threshold (ImageFFT1, Regions, 5, 240) connection (Regions, ConnectedRegions) select_shape (ConnectedRegions, SelectedRegions, 'area', 'and', 20, 99999) union1 (SelectedRegions, RegionUnion) dilation_rectangle1 (RegionUnion, RegionDilation, 5, 5) connection (RegionDilation, ConnectedRegions1) select_shape (ConnectedRegions1, SelectedRegions1, ['width','height'], 'and', [30,15], [150,100]) dilation_rectangle1 (SelectedRegions1, RegionDilation1, 11, 11) union1 (RegionDilation1, RegionUnion1) skeleton (RegionUnion1, Skeleton) *显示 dev_set_color ('red') dev_display (Image) dev_display (Skeleton)
halcon官方自带的例子
detect_indent_fft.hdev * Optimize the fft speed for the specific image size optimize_rft_speed (Width, Height, 'standard') * * Construct a suitable filter by combining two gaussian * filters Sigma1 := 10.0 Sigma2 := 3.0 gen_gauss_filter (GaussFilter1, Sigma1, Sigma1, 0.0, 'none', 'rft', Width, Height) gen_gauss_filter (GaussFilter2, Sigma2, Sigma2, 0.0, 'none', 'rft', Width, Height) sub_image (GaussFilter1, GaussFilter2, Filter, 1, 0) * * Process the images iteratively NumImages := 11 for Index := 1 to NumImages by 1 * * Read an image and convert it to gray values read_image (Image, 'plastics/plastics_' + Index$'02') rgb1_to_gray (Image, Image) * Perform the convolution in the frequency domain rft_generic (Image, ImageFFT, 'to_freq', 'none', 'complex', Width) convol_fft (ImageFFT, Filter, ImageConvol) rft_generic (ImageConvol, ImageFiltered, 'from_freq', 'n', 'real', Width)
参考文献
微信公众号:机器视觉那些事儿
《Halcon机器视觉算法原理与编程实战》杨青
本文出自勇哥的网站《少有人走的路》wwww.skcircle.com,转载请注明出处!讨论可扫码加群:


