正如我之前的许多人一样,我正在努力实施冈萨雷斯和伍兹的图像锐化示例"数字图像处理"书。
我创建一个负拉普拉斯内核(-1,-1,-1; -1,8,-1; -1,-1,-1)并将其与图像卷积,然后从原始结果中减去结果图片。 (我也尝试采用正拉普拉斯算子(1,1,1; 1,-8,1; 1,1,1)并将其添加到图像中)。在每个阶段,我执行将结果拟合到(0,255)范围内,标准化的拉普拉斯算子看起来很好并且灰色正如它所假设的那样。
import matplotlib.cm as cm
import scipy.misc
import scipy.ndimage.filters
#Function for plotting abs:
pic_n = 1
def show_abs(I, plot_title):
plt.title(plot_title)
plt.tight_layout()
plt.axis('off')
plt.imshow(abs(I), cm.gray)
#Reading the image into numpy array:
A = scipy.misc.imread('moon1.jpg', flatten=True)
plt.figure(pic_n)
pic_n += 1
show_abs(A, 'Original image')
A -= np.amin(A) #map values to the (0, 255) range
A *= 255.0/np.amax(A)
#Kernel for negative Laplacian
kernel = np.ones((3,3))*(-1)
kernel[1,1] = 8
#Convolution of the image with the kernel:
Lap = scipy.ndimage.filters.convolve(A, kernel)
#Laplacian now has negative values in range (-255, 255):
print('L', np.amax(Lap), np.amin(Lap))
plt.figure(pic_n)
pic_n += 1
show_abs(Lap, 'Laplacian')
#Map Laplacian to the (0, 255) range:
Lap -= np.amin(Lap)
Lap *= 255.0/np.amax(Lap)
print('L', np.amax(Lap), np.amin(Lap))
plt.figure(pic_n)
pic_n += 1
show_abs(Lap, 'Normalized Laplacian')
A += Lap #Add negative Laplacian to the original image
print('A', np.amax(A), np.amin(A))
A -= np.amin(A)
A *= 255.0/np.amax(A)
print('A', np.amax(A), np.amin(A))
plt.figure(pic_n)
pic_n += 1
show_abs(A, 'Laplacian filtered img')
plt.show()
问题是最终的锐化图像看起来褪色和灰色。我尝试进行直方图均衡化以使其更具对比度,但结果却很奇怪。我想过应用伽马校正,但我不喜欢自愿选择伽玛系数。
似乎必须有一种简单方便的方法将图像恢复到原始动态范围。我会很感激代码的想法和意见。谢谢!
答案 0 :(得分:2)
两年后回到同一任务,我对代码进行了如下修改:
import numpy as np
import matplotlib.pyplot as plt
import scipy.misc
import scipy.ndimage.filters
# Function for plotting abs:
pic_num = 1
def show_abs(I, plot_title, pic_num):
plt.figure(pic_num)
plt.title(plot_title)
plt.tight_layout()
plt.axis('off')
plt.imshow(abs(I), plt.cm.gray)
return pic_num+1
# Reading of the image into numpy array:
A0 = scipy.misc.imread('moon1.jpg', flatten=True)
# Map values to the (0, 255) range:
A0 = (A0 - np.amin(A0))*255.0 /(np.amax(A0)-np.amin(A0))
# Kernel for negative Laplacian:
kernel = np.ones((3,3))*(-1)
kernel[1,1] = 8
# Convolution of the image with the kernel:
Lap = scipy.ndimage.filters.convolve(A0, kernel)
#Map Laplacian to some new range:
ShF = 100 #Sharpening factor!
Laps = Lap*ShF/np.amax(Lap)
# Add negative Laplacian to the original image:
A = A0 + Laps
# Set negative values to 0, values over 255 to 255:
A = np.clip(A, 0, 255)
# Image the result:
pic_num = show_abs(Laps, 'Scaled Laplacian', pic_num)
pic_num = show_abs(A, 'Sharpened image', pic_num)
plt.show()
因此,以上代码的注释都是正确的:我不应该重新缩放拉普拉斯算子,并且通过numpy-clipping将锐化后的图像拟合为(0,255)会得到不错的结果。到目前为止,无需OpenCV和直方图均衡化。
答案 1 :(得分:0)
在我看来,问题的一部分与你如何重新调整Lap
有关。我认为你不想减去最小值 - 锐化应该降低某些像素的强度以及增加其他像素的强度。您可能还希望使用乘以Lap
的缩放因子来控制锐化程度(255可能过于极端)。
背景在最终图像中看起来是灰色的原因可能是因为在添加负拉普拉斯后,月亮中的像素将比背景更暗(图像的这部分拉普拉斯的幅度将更大它包含更多的本地结构)。这意味着您重新缩放背景像素将映射到某个值> 0.如果你没有从Lap
减去min,那么这些较暗的像素将具有负值,因此你可以在结果图像中剪切像素值,使得它们全部> 0。这样你就会得到纯黑色的背景。
答案 2 :(得分:0)
在将代码更正为 ali_m 建议之后,我应用了局部直方图均衡 - 它会减慢代码速度并增加对OpenCV库的依赖性,但生成的图像看起来很好。
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.cm as cm
import scipy.misc
import scipy.ndimage.filters
import cv2
#Function for plotting abs:
pic_n = 1
def show_abs(I, plot_title):
plt.title(plot_title)
plt.tight_layout()
plt.axis('off')
plt.imshow(abs(I), cm.gray)
#Reading of the image into numpy array:
A0 = scipy.misc.imread('moon1.jpg', flatten=True)
A0 -= np.amin(A0)#map values to the (0, 255) range
A0 *= 255.0/np.amax(A0)
print('Img ', np.amax(A0), np.amin(A0))
#>>> Img 255.0 0.0
#Kernel for negative Laplacian
kernel = np.ones((3,3))*(-1)
kernel[1,1] = 8
#Convolution of the image with the kernel:
Lap = scipy.ndimage.filters.convolve(A0, kernel)
#Laplacian now has negative values
print('Original Lap', np.amax(Lap), np.amin(Lap))
#>>> Original Lap 1151.0 -1166.0
#Map Laplacian to some new range:
Laps = Lap*100.0/np.amax(Lap) #Sharpening factor!
print('Scaled Lap ', np.amax(Laps), np.amin(Laps))
#>>> Scaled Lap 100.0 -101.303
plt.figure(pic_n)
pic_n += 1
plt.subplot(1,2,1)
show_abs(Lap, 'Laplacian')
plt.subplot(1,2,2)
show_abs(Laps, 'Scaled Laplacian')
A = A0 + Laps #Add negative Laplacian to the original image
print('SharpImg ', np.amax(A), np.amin(A))
#>>> SharpImg 350.917 -81.06
A = abs(A) #Get rid of negative values
print('SharpImg abs', np.amax(A), np.amin(A))
A *= 255.0/np.amax(A)
print('SharpImg after scaling', np.amax(A), np.amin(A))
#>>> SharpImg abs 350.917 0.0
# Local Histogram Equalization with OpenCV:
A_cv2 = A
A_cv2 = A_cv2.astype(np.uint8)
tile_s0 = 4
tile_s1 = 4
clahe = cv2.createCLAHE(clipLimit=1, tileGridSize=(tile_s0,tile_s1))
A_cv2 = clahe.apply(A_cv2)
plt.figure(pic_n)
pic_n += 1
plt.subplot(2,1,1)
plt.hist(A_cv2)
plt.title('Original Histogram')
plt.subplot(2,1,2)
plt.hist(A_cv2)
plt.title('Locally Equalized Histogram')
plt.figure(pic_n)
pic_n += 1
plt.subplot(1,3,1)
show_abs(A0, 'Original image')
plt.subplot(1,3,2)
show_abs(A, 'Laplacian filtered img')
plt.subplot(1,3,3)
show_abs(A_cv2, 'Local Hist equalized img')
plt.show()
答案 3 :(得分:0)
我最近还在努力解决这个问题,直到我意识到,冈萨雷斯和加拿大的例子。 Woods是用Matlab完成的,似乎imshow函数截断了double值(0以下的所有值都设置为0 - 上面的所有值都设置为1)。
所以做这样的事情对我有用:
imgfloat = L.astype(np.float32) / 255
imgLaplacian = cv2.filter2D(imgfloat, cv2.CV_32F, self.sharpeningKernel)
res = imgfloat - imgLaplacian
res[res < 0.0] = 0.0
res[res > 1.0] = 1.0
res = (res * 255).astype(np.uint8)
将sharpeningKernel定义为
self.sharpeningKernel = np.zeros((3,3),np.float32)
self.sharpeningKernel[0,1] = 1.0
self.sharpeningKernel[1,0] = 1.0
self.sharpeningKernel[1,1] = -4.0
self.sharpeningKernel[1,2] = 1.0
self.sharpeningKernel[2,1] = 1.0