在使用均值滤波器减少图像噪声的过程中,可能会出现图像变模糊的问题。我们追求的是清晰图像。那么,清晰图像与模糊图像之间的区别究竟在何处呢?从逻辑上分析,图像模糊通常是由于图像中物体的轮廓不够清晰,轮廓边缘的灰度变化不够剧烈,层次感不强所导致的。反之,如果轮廓边缘的灰度变化更明显,层次感更强,图像是否会更清晰呢?
如何定义这种灰度变化的明显程度呢?我们学习过微积分,知道微分是函数变化率的求法,即导数(梯度)。那么,对于图像而言,是否可以用微分来表示图像灰度的变化率呢?当然可以,因为我们之前提到过,图像本身就是一个函数。
在微积分中,一维函数的一阶微分的基本定义是这样的:而图像是一个二维函数f(x,y),其微分自然就是偏微分。因此,有:由于图像是一个离散的二维函数,不能无限小,我们的图像是按照像素来离散的,最小的增量就是1像素。因此,上述图像微分可以转化为如下形式(增量=1):
这分别是图像在(x,y)点处x方向和y方向上的梯度。从上面的表达式可以看出,图像的梯度相当于两个相邻像素之间的差值。
那么,这个梯度(或者说灰度值的变化率)是如何增强图像的清晰度的呢?我们先考虑x方向,选取某个像素,假设其像素值是100,沿x方向的相邻像素分别是90、90、90,根据上述计算,其x方向梯度分别是10、0、0。这里只取变化率的绝对值,表明变化的大小即可。
我们看到,100和90之间的亮度差异为10,并不是很明显,与一大群90的连续灰度值在一起,轮廓必然是模糊的。我们注意到,如果相邻像素灰度值有变化,那么梯度就有值;如果相邻像素灰度值没有变化,那么梯度就为0。如果我们把梯度值与对应的像素相加,那么灰度值没有变化的像素值不变,而有梯度值的像素值变大。
我们看到,相加后的新图像中,原图像像素点100与90亮度只相差10,现在是110与90,亮度相差20了,对比度显然增强了,尤其是图像中物体的轮廓和边缘,与背景的区别大大加强,这就是使用梯度增强图像的原理。
上述只是针对x方向,y方向同理。那么,能否将x方向和y方向的梯度结合起来呢?当然可以。x方向和y方向上的梯度可以用如下式子表示在一起:这里又是平方,又是开方的,计算量比较大,因此一般用绝对值来近似平方和平方根的操作,以降低计算量。接下来,我们将计算月球图像的x方向和y方向结合的梯度图像,以及最终的增强图像。
```python import cv2 ```
```python import numpy as np import cv2
# 读取图像 moon = cv2.imread("moon.tif", 0)
# 获取图像的行和列 row, column = moon.shape
# 创建一个与moon相同的数据类型副本 moon_f = np.copy(moon)
# 将moon_f的数据类型转换为浮点数 moon_f = moon_f.astype("float")
# 初始化梯度数组 gradient = np.zeros((row, column))
# 计算梯度 for x in range(row - 1): for y in range(column - 1): gx = abs(moon_f[x + 1, y] - moon_f[x, y]) gy = abs(moon_f[x, y + 1] - moon_f[x, y]) gradient[x, y] = gx + gy
# 应用梯度,增加图像的对比度 sharp = moon_f + gradient
# 将sharp中的值限制在0到255之间 sharp = np.where(sharp < 0, 0, np.where(sharp > 255, 255, sharp))
# 将梯度数组转换为无符号整数类型 gradient = gradient.astype("uint8") sharp = sharp.astype("uint8")
# 显示原图、梯度和锐化后的图像 cv2.imshow("moon", moon) cv2.imshow("gradient", gradient) cv2.imshow("sharp", sharp)
# 等待用户按键后关闭所有窗口 cv2.waitKey() ```