开启生长之旅!这是我参加「日新计划 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) 中的同态滤波器如下所示:

H(u,v)=(H−L)(11+(D0D(u,v))2n)+LH(u,v)=(\gamma_H-\gamma_L)(\frac 1 {1+(\frac {D_0} {D(u,v)})^{2n}})+\gamma_L

为了防止对数域中错误操作,在输入中添加常数 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 阶的截止频率为 30L\gamma_LH\gamma_H 参数分别设置为 0.31

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()

输出成果如下所示:

使用高通滤波器实现同态滤波

从上图中能够看出,所取得的输出图画中的光照愈加均匀,然后能够看清楚原始图画中黑暗区域的细节/边缘。