图像锐化处理的主要目的是突出图像中的细节或者增强被模糊了的细节,这种模糊一般由于错误操作或者是特殊图像获取方法的影响导致的。图像锐化的方法有很多,这里主要说下微分算子的方法来进行图像的锐化处理。总的来说,微分算子的响应强度与图像在该点(应用了算子)的突变程度有关。
数学中的微分描述的是连续函数关于各个变量的变化。但是在图像中,是以众多像素点来组成整张图片,所以,虽然图像有两个方向:水平方向(x方向)和垂直方向(y方向),但是这些方向的值也就是像素点的x值和y值均是离散的。X:1,2,3,…n; Y:1,2,3,…m;那我们就需要用离散的方法来表示出微分。
数学函数的微分可以用不同的术语定义,也有各种方法定义这些差别,然而,对于一阶微分的任何定义都必须保证以下几点:(1)在平坦段(灰度不变的区域)微分值为零;(2)在灰度阶梯或斜坡的起始点处微分值非零;(3)沿着斜坡面微分值非零。任何二阶微分的定义也类似:(1)在平坦区微分值必为零;(2)在灰度阶梯或斜坡的起始点处微分值非零;(3)沿着斜坡面微分值非零。因为我们处理的是数字量,其值是有限的,故最大灰度级的变化也是有限的,变化发生的最短距离是在两相邻像素之间。
1.基于一阶微分的图像增强原理
对于二元函数的一阶偏微分微分表示如下:
定义二元函数的微分为:
这就描述了图像中一个像素点(x,y)的一阶微分变化。简单的总结为一个算子的话就是一个2*2的矩阵如下
此算子在图像中应用的意思就是将(x,y)处像素的值减去(x-1,y)处值,与(x,y)出像素值减去(x,y-1)处的像素值相加替换(x,y)处的像素值。这就表征了图像在(x,y)处的一种变化,将这种变化与(x,y)处原有的值进行叠加,就可以将使这种变化更明显,也就是放大这种变化,从而达到图像锐化的目的。
2.基于二阶微分的图像增强处理。
首先定义一个二阶微分的离散公式,然后构造一个基于此式的滤波器。我们最关注的是一种各向同性滤波器,这种滤波器的响应与滤波器作用的图像的突变方向无关。也就是说,各向同性滤波器是旋转不变的,即将原始图像旋转后进行滤波处理给出的结果与先对图像滤波,然后再旋转的结果相同。
一个二元图像函数f(x,y)的拉普拉斯变换定义为:
因为任意阶微分都是线性操作,所以拉普拉斯变换也是一个线性操作。
为了更适合于数字图像处理,这一方程需要表示为离散形式。通过邻域处理有多种方法定义离散变换,但无论怎样定义,都必须符合3.7.1节中提到的二阶微分处理的性质。在上一节中给出的数字二阶微分处理的定义是最常用的一种。考虑到有两个变量,因此,我们在x方向上对二阶偏微分采用下列定义:
类似地,在y方向上为:
式(3.7.1)中的二维拉普拉斯数字实现可由这两个分量相加得到:
从而得到拉普拉斯算子
意思同上面的一阶微分算子相同。
这里解释一下微分算子的使用,很简单,如上面这个就是在处理每个像素点的RGB值时,将该像素的RGB三个值乘以4然后减去他上向左右四个像素点的RGB值,注意R、G、B分别处理。
这样是变化的表示,我们要想图片锐化,应该把这种变化叠加到原像素就行了,也就是
思路很简单。
一下为自己实现图像基于拉普拉斯算子的锐化过程:
void sharpen(const Mat &img, Mat &result) { for (int j = 1; j < img.rows - 1; ++j) { const uchar *previous = img.ptr<const uchar>(j - 1); const uchar *current = img.ptr<const uchar>(j); const uchar *next = img.ptr<const uchar>(j + 1); uchar *output = result.ptr<uchar>(j); for (int i = 1; i < 3 * (img.cols - 1); ++i)//这里是基于RGB图的,如果非RGB图则无需这样 { *output++ = cv::saturate_cast<uchar>( 5 * current[i] - current[i - 1] - current[i + 1] - previous[i] - next[i]); } } result.row(0).setTo(cv::Scalar(0)); result.row(result.rows - 1).setTo(cv::Scalar(0)); result.col(0).setTo(cv::Scalar(0)); result.col(result.cols - 1).setTo(cv::Scalar(0)); }
以下为使用opencv中的fiter2D函数通过拉普拉斯算子实现锐化操作的代码
int main() { Mat img, resulta; img = imread("C:/Users/Administrator/Desktop/bbb.jpg"); cv::Mat kernela(3, 3, CV_32F, cv::Scalar(0)); // assigns kernel values kernela.at<float>(1, 1) = 5.0; kernela.at<float>(0, 1) = -1.0; kernela.at<float>(2, 1) = -1.0; kernela.at<float>(1, 0) = -1.0; kernela.at<float>(1, 2) = -1.0; filter2D(img, resulta, img.depth(), kernela); //cout << img.rowRange(1, 4).colRange(1, 4) << endl; //cout << result.rowRange(1, 4).colRange(1, 4) << endl; imwrite("C:/Users/Administrator/Desktop/solved.jpg", resulta); //imshow("origin", img); //imshow("锐化结果", resulta); waitKey(0); return 0; }
原始图片
锐化后图片