空域滤波的后半部分主要讲图像的锐化相关操作。
图像锐化:
由于成像机理和成像设备的限制,尤其是对于一些专用成像设备,如医学成像,遥感成像和视频捕获等等,所成图像可能会变得模糊。图像锐化的作用就是增强图像的边缘和细节,减弱或清除灰度变化缓慢的区域,如边缘增强、边缘检测(提取)等。然而,图像锐化在增强图像灰度变化的同事,也放大了噪声。查分算子的响应程度和图像在这一点处的灰度值的突变有关,因此,图像的锐化使用差分算子。
总的来说,图像锐化的目的就是提高图像的对比度,从而使图像清晰起来,在图像的平滑中,为了使图像变得模糊,通常采用邻域平均的方法缩小邻域内像素之间的灰度差异,因此在图像的锐化中,可以采用相反的手段,也就是提高邻域内像素灰度差来提高图像的对比度。
因此,在图像的锐化过程中,被增强的像素点应该是与邻域内其他像素有较大差异的,因此原始图中国灰度相同的区域不应受锐化处理的影响,这一点在图像的锐化处理中应该格外的引起注意。
在数学上,常用的相关算子有一阶差分算子和二阶差分算子,通过对比他们的响应,我们可以得出下面的结论:
(1.一阶差分算子通常会产生比较宽的边缘
(2.二阶差分算子对孤立点和细线有较强的响应,其次是对细线的响应
(3.一阶差分算子一般对灰度阶跃的响应较强
(4.二阶差分算子对灰度阶跃的相应产生从正到负的过渡,在一幅图像中表现为“双边效应”
----因此,通常情况下,一阶差分算子利用图像梯度突出边缘和细节,主要用于图像的边缘检测。
----二阶差分算子是线性算子,通过线性算子提取的边缘和细节叠加在原图像上,主要用于图像的边缘增强。
下面分别介绍一阶差分算子和二阶差分算子。
1.一阶差分模板——梯度算子
在图像处理中,梯度是通过一阶差分来实现的。将一维的差分定义扩展到二维离散函数f(x,y),沿x(垂直)方向和y(水平)方向上的一阶差分Δfx(x,y)和Δfy(x,y)的定义为:
对于一幅图像f(x,y),在像素(x,y)处的梯度向量▽f(x,y)定义为:
其中,为了简化表示,Gx和Gy分别代表x方向和y方向上一阶差分
梯度向量的幅度▽f(x,y)由下式给出:
上式中,mag{·}表示幅度函数,但是为了避免复杂度较高的平方和开放运算,梯度经常近似为
上面这个式子计算简单并且保持了灰度的相对变化。
说完幅度,再考虑梯度的方向,梯度的方向指向像素值f(x,y)在(x,y)处增长最快的方向,它关于x轴的角度为
上式中,α(x,y)表示像素(x,y)处梯度向量关于x轴的方向角,该店凸度方向垂直于该点的边缘方向
下面给出最常用的Sobel模板,更多的一阶差分模板将在以后的边缘检测中给出,图(1)中的zi表示的是像素值,图(2)和图(3)分别为计算x方向和y方向上一阶差分的Sobel模板,模板尺寸为3x3。行或列使用中心权重为2的作用是在平滑处理中突出中心像素的作用。
Sobel模板计算x和y方向上偏导数的近似值为:
其中,Sobel模板中的系数之和为0,表明灰度恒定区域的响应为0.
因为一阶差分算子大多用来进行边缘检测,这里先不给出详细程序,在之后的文章介绍边缘检测时会详细给出。
2.二阶差分模板——拉普拉斯算子
拉普拉斯算子是最简单的各向同性二阶差分算子。各向同性滤波器是旋转不变的,也就是将图像旋转后在进行滤波处理的结果和对图像先滤波再旋转的结果相同。二维函数f(x,y)的拉普拉斯变换定义如下:
对于二维离散函数,常用二阶差分代替二阶偏导数,所以,数字图像f(x,y)的拉普拉斯变换表示为
上式中,第一项表示x(垂直)方向的二阶差分,第二项表示y(水平)方向的二阶差分,为了计算方便,在数字图像处理中,常用下式进行近似
分别带入二维离散函数拉普拉斯算子的表达式中,可以得出,在数字图像f(x,y)的拉普拉斯变换可以由下面一个式子表达出:
由于拉普拉斯是查分算子,因此它将突出图像中灰度的跃变,而清除灰度变化缓慢的区域。又由于拉普拉斯是线性算子,它在图像处理中最主要的应用是边缘增强,也就是我们常说的 锐化 。将拉普拉斯图像叠加在原图像上,能够同时保持拉普拉斯图像的边缘信息和源图像的灰度信息。需要注意的是,当拉普拉斯图像和源图像叠加时,必须考虑符号上的差别。使用拉普拉斯变换对图像进行锐化滤波的基本方法可表示为:
上式表示,如果所用的模板具有正的中心系数,则将源图像加上拉普拉斯模板,若所用的模板具有负的中心系数,则将源图像减去拉普拉斯系数,从而产生锐化滤波图像。学要说明的是,这两种方法产生的结果是完全相同的。
将源图像加在拉普拉斯模板上,就得到了拉普拉斯锐化模板。
在OpenCV中,使用filter2D函数可以很方便的对图像进行拉普拉斯锐化,将卷积内核设置为{0,-1,0;-1,5,-1;0,-1,0};具体程序如下:
//使用程序实现拉普拉斯锐化的过程
#include <iostream>
#include <opencv2\core\core.hpp>
#include <opencv2\highgui\highgui.hpp>
#include <opencv2\imgproc\imgproc.hpp>
using namespace cv;
using namespace std;
Mat L_sharpen(Mat srcImage);
int main()
{
Mat srcImage = imread("2345.jpg",0);
if (!srcImage.data)
{
cout << "读入图片有误!" << endl;
system("pause");
return 0;
}
imshow("原图像", srcImage);
Mat dstImage(srcImage.size(), srcImage.type());
dstImage = L_sharpen(srcImage);
imshow("拉普拉斯锐化图像", dstImage);
waitKey();
return 0;
}
Mat L_sharpen(Mat srcImage)
{
Mat resultImage(srcImage.size(), srcImage.type());
//构造核函数因子
Mat kern = (Mat_<float>(3, 3) << 0, -1, 0,
-1, 5, -1,
0, -1, 0);
filter2D(srcImage, resultImage, srcImage.depth(), kern);
return resultImage;
}
执行程序后,输出的效果图如下:
可以很明显的看出经过锐化处理后源图像的边缘更加明显,下面再给出只对只对拉普拉斯边缘检测的效果