回忆下我们之前使用的一阶微分的Robert、Sobel算子或者是二维的拉普拉斯算子,其中各个系数之和都为0。说明了算子在灰度恒定的区域的响应为0,这就导致了我们在锐化之后的图像中,除了边缘处之外的区域都变成了黑色,只有高灰度值的边缘、细节和灰度跳变点作为黑背景中的高灰度部分突出显示。我们更加希望,在基于锐化的图像增强中,可以保留原图像中的信息,所以可以将原图像和锐化后的图像相加来得到比较理想的成果。用公式来表达我们的思路,即
上式中第一种情况是锐化算子的中心参数>0,第二种情况是锐化算子的中心参数<0。
在实际应用中,边缘和细节等处在锐化处理后会得到高灰度值,在经过灰度伸缩之后原图的灰度会被压缩在一个很窄的范围,整体显得较暗。所以我们可以在符合 f(i,j) 和 Sharpen(f(i,j)) 时适当地提高 f(i,j) 的比重。改进后的描述为
回忆前面的滤波算法流程,模板与图像像素点邻域计算后的数值先取绝对值,然后再归一化到0-255的范围。因为关心的是边缘和细节,所以对于低灰度值的边缘或者是高灰度值的边缘——或者说黑色边缘、白色边缘——同个模板计算后一正一负取绝对值后都可以获得较大的数值即可。但是现在我们要和原图像相叠加,那么按照锐化的思路,希望结果中可以看到亮的边缘越亮、暗的边缘越暗的现象,所以不可以在Sharpen的计算结果中加绝对值。
另外,响应值和原图像像素值相加,虽然原图像的像素值有一个大于1的系数A,但是为了显示的清晰我们也希望两项的数值比较接近。所以可以对响应值提前进行归一化,有两种思路,一种是设置-255到255的范围然后直接截断;另一种就是归一化,全部归一化到-255到255的范围上。我们在这里尝试第一种方法,因为直观上看,除了边缘处的数值较大,还有可能遇到一些噪声点,之前也提到二维微分的拉普拉斯算子对于噪声点有明显的响应,直接截断也可以避免这种干扰,也减少了计算量。
from PIL import Image
import numpy as np
def EnhanceFilter(src, dst, A = 1, filter_kind = 1, padding = "replicate"):
imarray = np.array(Image.open(src),dtype='double')
#print(imarray.dtype)
height, width = imarray.shape
new_arr = np.zeros((height, width), dtype = "uint16")
filter1 = np.array([[0,1,0],[1,-4,1],[0,1,0]])
filter2 = np.array([[1,1,1],[1,-8,1],[1,1,1]])
filter3 = np.a