开启生长之旅!这是我参加「日新计划 12 月更文挑战」的第26天,点击检查活动详情
前语
同态滤波是一种去除图画中乘性噪声的技能,常用于校对图画中的不均匀照明。根据图画形成的光照反射模型,图画 f(x,y)f(x,y) 能够由以下两个重量表征:
- 入射到场景中的光源量
- 场景中目标反射的光量
根据光照反射模型模型,图画中像素的强度(即目标上的点反射的光)是场景照明和场景中目标反射的成果。傅立叶改换在加法下是线性相关的,但在乘法下并不相关。因此,傅立叶方法仅在将噪声作为原始图画的附加项建模时,才适合从图画中去除噪声。
可是,如果图画的缺点(例如,不均匀的照明)有必要建模为乘法而非加法,则直接运用傅立叶改换并不适宜。此时,咱们便需求运用同态滤波:首要,通过运用对数将乘法转化为加法;然后,运用对数域中的 HPF
来删去低频照明重量,一起保留高频反射率重量。
同态滤波中的根本过程如下,输入图画为 f(x,y)f(x,y),滤波器的输出为 g(x,y)g(x,y):
完成同态滤波
在本节中,咱们将学习怎么运用 Butterworth HPF
完成同态滤波器。
(1) 首要,导入所需 Python
库,并界说相关函数:
import cv2
import numpy as np
import matplotlib.pyplot as plt
from skimage.color import rgb2gray
from skimage.filters import sobel, threshold_otsu
def dft2(im):
freq = cv2.dft(np.float32(im), flags = cv2.DFT_COMPLEX_OUTPUT)
freq_shift = np.fft.fftshift(freq)
mag, phase = freq_shift[:,:,0], freq_shift[:,:,1]
return mag + 1j*phase
def idft2(freq):
real, imag = freq.real, freq.imag
back = cv2.merge([real, imag])
back_ishift = np.fft.ifftshift(back)
im = cv2.idft(back_ishift, flags=cv2.DFT_SCALE)
im = cv2.magnitude(im[:,:,0], im[:,:,1])
return im
def butterworth(sz, D0, n=1):
h, w = sz
u, v = np.meshgrid(range(-w//2,w//2), range(-h//2,h//2)) #, sparse=True)
return 1 / (1 + (D0/(0.01+np.sqrt(u**2 + v**2)))**(2*n))
(2) 界说同态滤波函数,频域 H(u,v)H(u,v) 中的同态滤波器如下所示:
为了防止对数域中错误操作,在输入中添加常数 1
,以确保对数的输入一直 ≥1
,最终,从输出中减去 1
:
def homomorphic_filter(im, D0, g_l=0, g_h=1, n=1):
im_log = np.log(im.astype(np.float)+1)
im_fft = dft2(im_log)
H = (g_h - g_l) * butterworth(im.shape, D0, n) + g_l
#H = np.fft.ifftshift(H)
im_fft_filt = H*im_fft
#im_fft_filt = np.fft.ifftshift(im_fft_filt)
im_filt = idft2(im_fft_filt)
im = np.exp(im_filt.real)-1
im = np.uint8(255*im/im.max())
return im
(3) 读取输入图画(带有不均匀照明),将其转化为灰度图画(确保像素值在 0-255
范围内),然后通过调函数 homomorphic_filter()
运用同态滤波器。
其间,Butterworth
滤波器 n=2
阶的截止频率为 30
,L\gamma_L 和 H\gamma_H 参数分别设置为 0.3
和 1
:
image = rgb2gray(plt.imread('1.png'))
image_filtered = homomorphic_filter(image, D0=30, n=2, g_l=0.3, g_h=1)
(4) 运用 sobel
滤波器从原始图画中提取边缘,运用 OTSU
最佳阈值创立二值图画如下:
image_edges = sobel(image)
image_edges = image_edges <= threshold_otsu(image_edges)
(5) 运用 sobel
滤波器通过从同态滤波器转化的图画中提取边缘:
image_filtered_edges = sobel(image_filtered)
image_filtered_edges = image_filtered_edges <= threshold_otsu(image_filtered_edges)
(6) 最终,制作输入图画和运用同态滤波器取得的输出图画,以及提取的边缘:
plt.figure(figsize=(21,17))
plt.gray()
plt.subplots_adjust(0,0,1,0.95,0.01,0.05)
plt.subplot(221), plt.imshow(image), plt.axis('off'), plt.title('original image', size=10)
plt.subplot(222), plt.imshow(image_filtered), plt.axis('off'), plt.title('filtered image', size=10)
plt.subplot(223), plt.imshow(image_edges), plt.axis('off'), plt.title('original image edges', size=10)
plt.subplot(224), plt.imshow(image_filtered_edges), plt.axis('off'), plt.title('filtered image edges', size=10)
plt.show()
输出成果如下所示:
从上图中能够看出,所取得的输出图画中的光照愈加均匀,然后能够看清楚原始图画中黑暗区域的细节/边缘。