halcon视觉缺陷检测系列(2)频域和空间域转换的方法详解

理论基础

一、频率特征是图像的灰度变化特征,低频特征是灰度变化不明显,例如图像整体轮廓,高频特征是图像灰度变化剧烈,如图像边缘和噪声。一个重要的经验结论:低频代表图像整体轮廓,高频代表了图像噪声,中频代表图像边缘、纹理等细节。什么时候使用傅里叶变换进行频域分析?

  1. 具有一定纹理特征的图像,纹理可以理解为条纹,如布匹、木板、纸张等材质容易出现。 

  2. 需要提取对比度低或者信噪比低的特征。 

  3. 图像尺寸较大或者需要与大尺寸滤波器进行计算,此时转换至频域计算,具有速度优势。因为空间域滤波为卷积过程(加权求和),频域计算直接相乘。

二、在halcon中,使用频域进行检测,有两个步骤是比较关键的:

  1. 一个是生成合适的滤波器;

  2. 一个是空间域和频域之间的转换。

生成滤波器主要有如下算子:

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

这两个算子的共同点:

  1. 这两个算子都是进行快速傅里叶变换的算子

  2. 这两个算子都可以进行空间域-》频域和频域-》空间域的变换,只需要针对参数Direction分别进行选择,'to_freq'是进行的是空间域-》频域的变换,'from_freq'是频域-》空间域的变换。

  3. 针对参数ResultType,如果是'to_freq',那么ResultType一般选择'complex';如果是'from_freq',ResultType一般选择'byte'(灰度图像)。

这两个算子的不同点:

  1.  rft_generic算子的输入图像是实值函数,fft_generic的输入图像是复数函数;从输出的结果来看,rft_generic只需要计算和存储了左半边的复数图像信息就可以了,因为右半边是共轭对称的。因此从最终的输出我们可以看到,只有左上和左下有DC成分。而fft_generic如果设定的是原点在左上角,那么就会在四个角上有DC成分。

  2. fft_generic算子可以通过参数Mode设置原点的位置:如果设置的是'dc_edge',那么原点在左上角;如果设置的是'dc_center',那么就会将原点平移到中心位置。fft_generic算子一般会设置为'dc_center'。对于rft_generic算子,因为没有设置项,所以默认原点位置为左上角。

针对同一个图像,进行空间域-》频域、频域-》空间域的转换的时候,如果使用的是rft_generic算子,那么两个转换就都使用该算子;如果使用的是fft_generic算子,那么两个转换也都使用该算子,在对同一个图像进行空间域和频域的相互转换时,不要交叉使用这两个算子。

当然,从空间域到频域的转换,也可以使用算子fft_image,这个算子也是快速傅里叶变换,其实际效果相当于:

fft_generic(Image,ImageFFT,'to_freq',-1,'sqrt','dc_center','complex')

 

举例说明

1、检测布料表面划痕

image.png

*《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、傅里叶变换之划痕检测

image.png

*微信公众号--机器视觉那些事儿
*检测-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、木板划痕检测

image.png

*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

detect_mura_defects_texture.hdev

官方例子detect_indent_fft,使用了差分两个高斯滤波器

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)

参考文献

  1. 微信公众号:机器视觉那些事儿

  2. 《Halcon机器视觉算法原理与编程实战》杨青


本文出自勇哥的网站《少有人走的路》wwww.skcircle.com,转载请注明出处!讨论可扫码加群:

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

会员中心
搜索
«    2024年4月    »
1234567
891011121314
15161718192021
22232425262728
2930
网站分类
标签列表
最新留言
    热门文章 | 热评文章 | 随机文章
文章归档
友情链接
  • 订阅本站的 RSS 2.0 新闻聚合
  • 扫描加本站机器视觉QQ群,验证答案为:halcon勇哥的机器视觉
  • 点击查阅微信群二维码
  • 扫描加勇哥的非标自动化群,验证答案:C#/C++/VB勇哥的非标自动化群
  • 扫描加站长微信:站长微信:abc496103864
  • 扫描加站长QQ:
  • 扫描赞赏本站:
  • 留言板:

Powered By Z-BlogPHP 1.7.2

Copyright Your skcircle.com Rights Reserved.

鄂ICP备18008319号


站长QQ:496103864 微信:abc496103864