图像增强就是指通过某种图像处理方法对退化的某些图像特征,如边缘、轮廓、对比度等进行处理,以改善图像的视觉效果,提高图像的清晰度,或是突出图像中的某些“有用”,压缩其他“无用”信息,将图像转换为更适合人或计算机分析处理的形式。
图像增强可以分为两类:空间域法和频域法。
空间域可以简单地理解为包含图像像素的空间,空间域法是指空间域中,也就是图像本身,直接对图像进行各种线性或非线性运算,对图像的像素灰度值做增强处理。
频域法则是在图像的变换域中把图像看成一种二维信号,对其进行基于二维傅里叶变换的信号增强。对其进行基于二维傅里叶变换的信号增强。
空间域法又分为点运算和模板处理两大类。点运算是作用于单个像素邻域的处理方法,包括图像灰度变换、直方图修正、伪彩色增强技术;模板处理是作用于像素领域的处理方法,包括图像平滑、图像锐化等技术。
频域法常用的方法包括低通滤波、高通滤波以及同态滤波等。
如图概括了常用的图像增强的方法:
一、灰度变换
1.1线性灰度变换
一般不改变像素点的坐标信息,只改变像素点的灰度值。
算子1:scale_image —— 缩放图像的灰度值。
void ScaleImage(const HObject& Image, HObject* ImageScaled,
const HTuple& Mult, const HTuple& Add)
原理:算子scale_image对输入的图像(Image)进行如下变换:
g' := g * Mult + Add
可以通过灰度范围[GMin,GMax],然后用以下公式来确定参数
作用:拉开图像的对比度,让图像中黑的地方更黑,亮的地方更亮。
算子2:emphasize —— 增强图像的对比度。
void Emphasize(const HObject& Image, HObject* ImageEmphasize,
const HTuple& MaskWidth, const HTuple& MaskHeight,
const HTuple& Factor)
首先,程序使用低通(平均图像)进行滤波。根据获得的灰度值(平均值)和原始灰度值(原始值)计算得到的灰度值(res),如下所示:
通过参数3、4控制均值滤波模板的大小,数值越大,则图像对比度越强,一般配合参数5—Factor(对比度强度)一起对图像进行增强处理。
作用:增强图像的高频区域(边缘和拐角),使图像看起来更清晰。
1.2非线性灰度变换
单纯的线性灰度变换可以在一定程度上解决视觉上的图像整体对比度问题,但是对图像细节部分的增强较为有限,结合非线性变换技术可以解决这一问题。非线性变换不是对图像的整个灰度范围进行扩展,而是有选择的对某一灰度范围进行扩展,其他范围的灰度则有可能被压缩。常用的非线性变换有对数变换和指数变换。
算子1:log_image —— 对图像做对数变换
void LogImage(const HObject& Image, HObject* LogImage,
const HTuple& Base)
图像灰度的对数变换可以扩张数值较小的灰度范围或者压缩数值较大的灰度范围。对数变换是一种有用的非线性映射交换函数,可以用于扩展图像中范围较窄的低灰度值像素,压缩输入图像中范围较宽的高灰度值像素,使得原本低灰度值的像素部分能更清晰的呈现出来。
对图像的灰度值取对数,得到新的灰度值,第3个参数为对数的底,默认值为’e’
算子2:pow_image — 对图像做指数变换
void PowImage(const HObject& Image, HObject* PowImage,
const HTuple& Exponent)
指数变换映射关系与对数变换的不同之处在于,指数变换可以根据伽马Exponent 的不同取值有选择性地增强低灰度区域的对比度或是高灰度区域的对比度。其变换原则如下:
1.3直方图均衡化
直方图均衡就是从图像的灰度图入手,建立一个0~255灰度值的直方图,统计每个灰度值在直方图中出现的次数,将灰度图中对应点的灰度值记录在直方图中,接着对该直方图进行均衡化操作,使像素的灰度值分布得更加均匀,从而增强图像整体对比度效果,使图像更加清晰。
算子1:equ_histo_image — 图像的直方图线性化
void EquHistoImage(const HObject& Image, HObject* ImageEquHisto)
起点是输入图像的直方图。对字节图像执行以下简单的灰度值转换f(g):
h(x)描述灰度值x发生的相对频率。对于uint2图像,唯一的区别是值255被替换为另一个最大值。如果设置了此值,则从与输入图像一起存储的有效位数来计算最大值。如果没有设置,则使用系统参数“ int2_bits”的值(如果设置了该值(即,不同于-1))。如果两个值均未设置,则有效位数设置为16。
原始图直方图:
效果图直方图:
二、图像锐化
图像锐化是补偿图像的轮廓,增强图像的边缘及灰度跳变的部分,使图像变得清晰。图像锐化是为了突出图像上地物的边缘、轮廓,或某些线性目标要素的特征。
算子1:shock_filter — 对图像应用冲击过滤器。
void ShockFilter(const HObject& Image, HObject* SharpenedImage,
const HTuple& Theta, const HTuple& Iterations,
const HTuple& Mode, const HTuple& Sigma)
实例代码:
read_image (Image, 'datacode/ecc200/ecc200_cpu_015')
fill_interlace (Image, ImageFilled, 'odd')
shock_filter (ImageFilled, SharpenedImage, 0.5, 10, 'laplace', 1.5)
三、图像平滑
频率特征是图像的灰度变化特征。低频特征是灰度变化不明显,代表图像整体轮廓。高频特征是图像灰度变化剧烈,代表图像噪声。中频特征则代表图像边缘、纹理等细节。
什么时候使用傅里叶变换进行频域分析?
具有一定纹理特征的图像,纹理可以理解为条纹,如布匹、木板、纸张等材质容易出现。
需要提取对比度低或者信噪比低的特征。
图像尺寸较大或者需要与大尺寸滤波器进行计算,此时转换至频域计算,具有速度优势。因为空间域滤波为卷积过程(加权求和),频域计算直接相乘。
在halcon中,使用频域进行检测,有两个步骤是比较关键的:①生成合适的滤波器;②空间域和频域之间的转换。
3.1均值滤波
均值滤波的原理就是将像素灰度值与其邻域内的像素灰度值相加取平均值,该滤波器区域就如同一个小小的“窗口”,在图像左上角开始滑动,将该“窗口”内的像素灰度值相加取均值,然后将该值赋值给“窗口”中的每一个像素。
算子1:mean_image — 平均平滑。
void MeanImage(const HObject& Image, HObject* ImageMean,
const HTuple& MaskWidth, const HTuple& MaskHeight)
该算子对所有输入图像(图像)的灰度值进行线性平滑。滤波器矩阵由个数(相等)组成,大小为MaskHeight x MaskWidth。卷积的结果除以MaskHeight x MaskWidth。对于边界处理,灰度值反映在图像边缘。
3.2中值滤波
中值滤波的原理与均值滤波相似,不同的是,它以像素为中心,取一个指定形状的邻域作为滤波器,该形状可以是正方形,也可以是圆形。然后将区域内的像素灰度值进行排序,以排序结果的中值,将该中值赋值给该区域内的像素。
算子1:median_image — 用各种掩模计算中值滤波器。
void MedianImage(const HObject& Image, HObject* ImageMedian,
const HTuple& MaskType, const HTuple& Radius,
const HTuple& Margin)
MaskType是邻域的形状,Radius是卷积核的尺寸,Margin是边界的处理方式,因为边界处往往无法移动滤波窗口,因此需要对像素做一些补充,
“continued”:表示延伸边界像素
“cyclic”:表示循环延伸边界像素
作用:适合去除一些孤立的噪点,保留大部分边缘信息。
3.3高斯滤波
高斯滤波是调用一个二维离散的高斯函数,适合去除高斯噪声。
算子1:gauss_filter — 使用离散高斯函数平滑。
void GaussFilter(const HObject& Image, HObject* ImageGauss,
const HTuple& Size)
使用的离散高斯函数是
四、频域滤波
频率特征是图像的灰度变化特征。低频特征是灰度变化不明显,代表图像整体轮廓。高频特征是图像灰度变化剧烈,代表图像噪声。中频特征则代表图像边缘、纹理等细节。
什么时候使用傅里叶变换进行频域分析?
具有一定纹理特征的图像,纹理可以理解为条纹,如布匹、木板、纸张等材质容易出现。
需要提取对比度低或者信噪比低的特征。
图像尺寸较大或者需要与大尺寸滤波器进行计算,此时转换至频域计算,具有速度优势。因为空间域滤波为卷积过程(加权求和),频域计算直接相乘。
在halcon中,使用频域进行检测,有两个步骤是比较关键的:①生成合适的滤波器;②空间域和频域之间的转换。
4.1高通滤波法
图像中的边缘或细条等细节部分与图像频谱的高频分量相对应,因此采用高通滤波让高频分量顺利通过,使图像的边缘或细条等细节变得清楚,实现图像的锐化。高通滤波可用空频法或频域法来实现。在空间域是用卷积方法,与空域低通滤波的邻域平均法类似,不过其中的冲激响应方阵H不同。
算子1:gen_gauss_filter — 在频域生成高斯滤波器
void GenGaussFilter(HObject* ImageGauss, const HTuple& Sigma1,
const HTuple& Sigma2, const HTuple& Phi,
const HTuple& Norm, const HTuple& Mode,
const HTuple& Width, const HTuple& Height)
注意这里是频域的,而对图像进行平滑处理的高斯滤波是时域的高斯滤波器,其使用卷积模板滤除噪声。
原理:首先产生一个高斯核,然后根据输入的参数对这个高斯核矩阵做傅里叶变换(实现从空域或时域到频域的转换工具),得到特定模式和特定分辨率的所谓频域的滤波器,例如我要进行rft_generic的变换,那么我的高斯滤波器模式就要写为‘rft’。并通过设置参数保持频域滤波器和原图像一致。
算子2:rft_generic — 计算图像的实值快速傅里叶变换。
void RftGeneric(const HObject& Image, HObject* ImageFFT,
const HTuple& Direction, const HTuple& Norm,
const HTuple& ResultType, const HTuple& Width)
原理:其实gen_gauss_filter得到的滤波器,就是一个图像,虽然是频域滤波器,但是单纯看物理意义,他就是一个图像。与时域空间卷积核的物理意义是相同的。对这幅频域图进行卷积(卷积过程与时域无差别),卷积之后图像就产生了变化,比如外环得到减弱,内环得到保留(高低通滤波器的效果),或者在某个方向上得到保留(gabor滤波器的效果),再还原到时域,发现跟原图变化很大。
算子2:convol_fft — 用频域滤波器卷积图像。
void ConvolFft(const HObject& ImageFFT, const HObject& ImageFilter,
HObject* ImageConvol)
原理:将复合图像ImageFFT的像素乘以滤波图像滤波器的对应像素。
实例代码:
dev_close_window ()
dev_update_off ()
Path := 'lcd/mura_defects_blur_'
read_image (Image, Path + '01')
get_image_size (Image, Width, Height)
dev_open_window_fit_size (0, 0, Width, Height, 640, 480, WindowHandle)
set_display_font (WindowHandle, 14, 'mono', 'true', 'false')
dev_set_draw ('margin')
dev_set_line_width (3)
dev_set_color ('red')
ScaleFactor := 0.4
calculate_lines_gauss_parameters (17, [25,3], Sigma, Low, High)
for f := 1 to 3 by 1
read_image (Image, Path + f$'.2i')
decompose3 (Image, R, G, B)
* correct side illumination
rft_generic (B, ImageFFT, 'to_freq', 'none', 'complex', Width)
gen_gauss_filter (ImageGauss, 100, 100, 0, 'n', 'rft', Width, Height)
convol_fft (ImageFFT, ImageGauss, ImageConvol)
rft_generic (ImageConvol, ImageFFT1, 'from_freq', 'none', 'byte', Width)
sub_image (B, ImageFFT1, ImageSub, 2, 100)
* perform the actual inspection
zoom_image_factor (ImageSub, ImageZoomed, ScaleFactor, ScaleFactor, 'constant')
* avoid border effects when using lines_gauss()
get_domain (ImageZoomed, Domain)
erosion_rectangle1 (Domain, RegionErosion, 7, 7)
reduce_domain (ImageZoomed, RegionErosion, ImageReduced)
lines_gauss (ImageReduced, Lines, Sigma, Low, High, 'dark', 'true', 'gaussian', 'true')
hom_mat2d_identity (HomMat2DIdentity)
hom_mat2d_scale_local (HomMat2DIdentity, 1 / ScaleFactor, 1 / ScaleFactor, HomMat2DScale)
affine_trans_contour_xld (Lines, Defects, HomMat2DScale)
*
dev_display (Image)
dev_display (Defects)
if (f < 3)
disp_continue_message (WindowHandle, 'black', 'true')
stop ()
endif
endfor