在同态滤波器,通过对数变换将图像中的乘性信号转换为加性信号,之后便可以使用线性滤波方法进行处理(基于傅里叶变换)。同态滤波器的处理流程大致如下:
- 对数变换
- 傅里叶变换
- 滤波(比如高通滤波)
- 傅里叶反变换
- 对数反变换
- 归一化
代码如下:
import cv2
import numpy as np
import matplotlib.pyplot as plt
# image: 灰度图像
# cutoff_low \ cutoff_high: 低频和高频滤波器的截止频率
# gamma_l \ gamma_h: 低频和高频区域的增益
def homomorphic_filter(image, cutoff_low=0.3, cutoff_high=0.7, gamma_l=1, gamma_h=3.0):
# 转换为浮动32位类型
image = np.float32(image)
# 对数变换(乘性转为加性,然后使用线性滤波方法处理)
log_image = np.log1p(image) # np.log1p(x) = log(1 + x)
# 傅里叶变换
fft_image = np.fft.fft2(log_image)
fft_shift = np.fft.fftshift(fft_image)
# 生成同态滤波器
rows, cols = image.shape
crow, ccol = rows // 2, cols // 2 # 中心坐标
# 创建带通滤波器
filter_ = np.ones((rows, cols), dtype=np.float32)
for i in range(rows):
for j in range(cols):
# 计算每个点到图像中心的距离
distance = np.sqrt((i - crow) ** 2 + (j - ccol) ** 2)
# 创建带通滤波器:低频部分被抑制,高频部分被增强
if distance < cutoff_low * min(rows, cols)/2:
filter_[i, j] = gamma_l
elif distance > cutoff_high * min(rows, cols)/2:
filter_[i, j] = gamma_h
else:
filter_[i, j] = 1
# 滤波
filtered_fft = fft_shift * filter_
# 逆傅里叶变换
inverse_fft_shift = np.fft.ifftshift(filtered_fft)
inverse_fft_image = np.fft.ifft2(inverse_fft_shift)
# 对数反变换
# inverse_fft_image为复数表示,取模
enhanced_image = np.expm1(np.abs(inverse_fft_image)) # np.expm1(x) = exp(x) - 1
# 归一化到 0-255 范围
# np.clip()用于限制元素值的范围
enhanced_image = np.uint8(np.clip(enhanced_image, 0, 255))
# 整体缩放不可取
# enhanced_image = (enhanced_image - enhanced_image.min()) / (enhanced_image.max() - enhanced_image.min()) * 255
return enhanced_image
# 读取图像并转换为灰度图像
# image = cv2.imread('dai.jpg', cv2.IMREAD_GRAYSCALE)
image = cv2.imread('dai.jpg')
# 使用同态滤波器增强图像
enhanced_image = np.zeros(image.shape, dtype=np.uint8)
enhanced_image[:, :, 0] = homomorphic_filter(image[:, :, 0])
enhanced_image[:, :, 1] = homomorphic_filter(image[:, :, 1])
enhanced_image[:, :, 2] = homomorphic_filter(image[:, :, 2])
enhanced_image_last = cv2.addWeighted(image, 1, enhanced_image, 5, 0)
# 单个通道的对比图
plt.figure(figsize=(15, 5))
plt.subplot(1, 2, 1)
plt.imshow(image1, cmap='gray')
plt.title('image1')
plt.axis('off')
plt.subplot(1, 2, 2)
plt.imshow(enhanced_image[:, :, 0], cmap='gray')
plt.title('enhanced_image[:, :, 0]')
plt.axis('off')
# 显示原始图像和增强后的图像
plt.figure(figsize=(15, 5))
plt.subplot(1, 2, 1)
# plt.imshow(image, cmap='gray')
plt.imshow(cv2.cvtColor(image, cv2.COLOR_BGR2RGB))
plt.title('image')
plt.axis('off')
plt.subplot(1, 2, 2)
plt.imshow(cv2.cvtColor(enhanced_image, cv2.COLOR_BGR2RGB))
plt.title('enhanced_image')
plt.axis('off')
plt.show()