在缺陷检测时,频域(FFT)和空间域经常转换,以利用两者的特点。
例如下面的代码,就是先把空间域转频域,做完频域空间的算法后(convol_fft 卷积计算),再把频域转回空间域。
rft_generic (img, ImageFFT, 'to_freq', 'none', 'complex', Width) convol_fft(ImageFFT, ImageGauss, ImageConvol1) rft_generic(ImageConvol1, ImageFFT1, 'from_freq', 'n', 'real', Width)
因此存在专门用于频域空间的算子。
勇哥摘抄了一份相关算子的列表如下:
5.6 FFT 1. convol_fft 功能:用在频域内的滤波器使一个图像卷积。 2. convol_gabor 功能:用在频域内的一个Gabor滤波器使一个图像卷积。 3. correlation_fft 功能:计算在频域内的两个图像的相互关系。 4. energy_gabor 功能:计算一个两通道图像的能量。 5. fft_generic 功能:计算一个图像的快速傅里叶变换。 6. fft_image 功能:计算一个图像的快速傅里叶变换。 7. fft_image_inv 功能:计算一个图像的快速傅里叶逆变换。 8. gen_bandfilter 功能:生成一个理想带通滤波器。 9. gen_bandpass 功能:生成一个理想带通滤波器。 10. gen_derivative_filter 功能:在频域内生成一个倒数滤波器。 11. gen_filter_mask 功能:在空域内存储一个滤波器掩码作为实时图像。 12. gen_gabor 功能:生成一个Gabor滤波器。 13. gen_gauss_filter 功能:在频域内生成一个高斯滤波器。 14. gen_highpass 功能:生成一个理想高通滤波器。 15. gen_lowpass 功能:生成一个理想低通滤波器。 16. gen_sin_bandpass 功能:用正弦形状生成一个带通滤波器。 17. gen_std_bandpass 功能:用高斯或者正弦形状生成一个带通滤波器。 18. optimize_fft_speed 功能:使FFT的运行时间最优化。 19. optimize_rft_speed 功能:使实值的FFT的运行时间最优化。 20. phase_deg 功能:返回用角度表示的一个复杂图像的相位。 21. phase_rad 功能:返回用弧度表示的一个复杂图像的相位。 22. power_byte 功能:返回一个复杂图像的功率谱。 23. power_ln 功能:返回一个复杂图像的功率谱。 24. power_real 功能:返回一个复杂图像的功率谱。 25. read_fft_optimization_data 功能:从一个文件中下载FFT速度最优数据。 26. rft_generic 功能:计算一个图像的实值快速傅里叶变换。 27. write_fft_optimization_data 功能:把FFT速度最优数据存储在一个文件中。
FFT是纹理检测的一种办法,而缺陷检测属于纹理检测的一部分。
要想检测缺陷,基本思路是:
(1)fft变换
(2)卷积滤波(一般为了得到图像的高频部分)
(3)fft逆变换
(4)到这一步缺陷被变得更明显,提取缺陷部分就容易很多。
先说说一些名词概念:
有关频域,时域,空间域见贴子:
http://www.skcircle.com/?id=1543
本站一些关于频域的贴子,做为大家参考:
频率域滤波基础之一 http://www.skcircle.com/?id=330
频率域滤波基础之二 http://www.skcircle.com/?id=331
频率域滤波基础之三 http://www.skcircle.com/?id=332
频率域滤波基础之五 http://www.skcircle.com/?id=333
下面来研究一下频域空间下的常见的滤波器:
(一) 高斯滤波器
简单的高斯滤波器构造代码如下:
sigma :=2 gen_gauss_filter (ImageFilter, sigma, sigma, 0.0, 'none', 'rft', Width, Height)
传一张没水印的图片做为原片
下面是photoshop的高斯模糊2个像素的效果
下面是用halcon验证sigma=2的高斯模糊的效果。
相对于ps的高斯模糊,gen_gauss_filter产生的效果对比度要高一些,但是模糊程序是差不多的。
gen_gauss_filter算子原型说明如下:
gen_gauss_filter( : ImageGauss : Sigma1, Sigma2, Phi, Norm, Mode, Width, Height : ) gen_gauss_filter是一种高斯低通滤波器。(与之对应的还有一种高通滤波器) 在频域中生成一个(可能是各向异性的)高斯滤波器。高斯在空间域中的标准偏差(即平滑量)由Sigma1和Sigma2确定。 Sigma1 是在滤波器主方向上在空间域中由角度Phi确定的标准偏差。 为了获得最大的滤波操作总体效率,可以使用参数Norm来指定滤波器的归一化因子。如果使用fft_generic且Norm = 'n',则可以避免FFT中的标准化。 模式可以用来确定滤波器的直流项在哪里,或者是否应在实值FFT中使用该滤波器。如果fft_generic使用,“dc_edge”可以用来提高效率。 如果使用fft_image和fft_image_inv 进行过滤,则必须使用Norm = 'none'和 Mode = 'dc_center'。如果 rft_generic被使用,模式= “RFT”必须被使用。 Sigma1 高斯在空间域中滤波器主要方向的标准偏差 Sigma2 高斯垂直于空间域中滤波器主要方向的标准偏差 Phi 空间域中筛选器的主要方向,弧度值 Norm 滤波器的规范化因子,貌似只有'none', 'n'可选。 这东西的作用在于提升滤操作的最大整体效率。 Mode DC项在频域中的位置,可取值:"dc_center",'dc_edge',"rft" Width, Height 图像(滤镜)的宽度和调试
(二)FFT用来做缺陷检测
我们来看一个缺陷检测的例子,这个例子引自ihalcon论坛。
这个作者的源代码要5个积分下载,勇哥舍不得,自己写了一段,效果差不多的。
傅立叶变换后的缺陷特征就明显多了,如下图:
给个文字版的吧,方便大家
read_image (img, 'C:/Users/Administrator.PC8-20191007LRY/Desktop/32.jpeg') get_image_size(img, Width, Height) rgb1_to_gray(img, GrayImage) dev_set_draw('margin') dev_set_color('yellow') sigma1:=1 sigma2:=225 gen_gauss_filter(GaussFilter1, sigma1, sigma1, 0, 'none', 'rft', Width, Height) gen_gauss_filter(GaussFilter2, sigma2, sigma2, 0, 'none', 'rft', Width, Height) sub_image(GaussFilter1, GaussFilter2, ImageFilter, 1, 0) rft_generic (GrayImage, ImageFFT, 'to_freq', 'none', 'complex', Width) convol_fft (ImageFFT, ImageFilter, ImageConvol) rft_generic (ImageConvol, ImageFiltered, 'from_freq', 'n', 'real', Width) threshold (ImageFiltered, Regions, -50, -17.181) dilation_circle(Regions, RegionDilation,8.5)
哦,你注意到那个threshold没有,居然参数是负数,这是什么鬼呢?
勇哥也是才发现这个现象,有违天理啊,暂时不知道为啥子~~
勇哥2020/11/20 注:
关于阈值可以取负数的问题,是因为这个是real图像,请参考下面的有关halcon的数据类型的说明。
http://www.skcircle.com/?id=1547
勇哥参考了一下例程detect_indent_fft.hdev
发现例程在傅立叶变换后,并没有直接阈值,而是使用gray_range_rect算子增强缺陷的灰度值,再求得画面上的最小与最大灰度值,以此来决定阈值是多少。
参照改了一下代码,效果好多了。
read_image (img, 'C:/Users/Administrator.PC8-20191007LRY/Desktop/32.jpeg') get_image_size(img, Width, Height) rgb1_to_gray(img, GrayImage) dev_set_draw('margin') dev_set_color('yellow') sigma1:=1 sigma2:=225 gen_gauss_filter(GaussFilter1, sigma1, sigma1, 0, 'none', 'rft', Width, Height) gen_gauss_filter(GaussFilter2, sigma2, sigma2, 0, 'none', 'rft', Width, Height) sub_image(GaussFilter1, GaussFilter2, ImageFilter, 1, 0) rft_generic (GrayImage, ImageFFT, 'to_freq', 'none', 'complex', Width) convol_fft (ImageFFT, ImageFilter, ImageConvol) rft_generic (ImageConvol, ImageFiltered, 'from_freq', 'n', 'real', Width) gray_range_rect(ImageFiltered, ImageResult, 10, 10) min_max_gray(ImageResult, ImageResult, 0, Min, Max, Range) threshold (ImageResult, Regions, max([5.55,Max * 0.8]),255) dilation_circle(Regions, RegionDilation,8.5)
这段代码中,精华的其实是下面这段:
sigma1:=1 sigma2:=225 gen_gauss_filter(GaussFilter1, sigma1, sigma1, 0, 'none', 'rft', Width, Height) gen_gauss_filter(GaussFilter2, sigma2, sigma2, 0, 'none', 'rft', Width, Height) sub_image(GaussFilter1, GaussFilter2, ImageFilter, 1, 0)
这个可是内有乾坤的,请听勇哥下回分解。
http://www.skcircle.com/?id=1551 转到下篇
---------------------
作者:hackpig
来源:www.skcircle.com
版权声明:本文为博主原创文章,转载请附上博文链接!

