You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何仅对图像的非零区域应用同态滤波(频域高通)

图像同态滤波的局部应用问题

我有一个用于图像同态滤波的Python函数,处理光照不均的图像时效果良好:

处理光照不均图像的效果

但处理带有黑色背景的图像时,会出现异常效果:

处理黑背景图像的效果

请问如何仅对这类图像的非零区域应用该滤波?

原始代码

import cv2
import matplotlib.pyplot as plt
from scipy import fftpack as fft
import numpy as np

def homomorphic_filter(img, low_cutoff=0.05, high_cutoff=0.5, order=2, boost=25):
    rows, cols = img.shape
    rh, rl, c = high_cutoff, low_cutoff, boost
    
    # 创建高斯滤波器
    x = np.linspace(-1, 1, cols)
    y = np.linspace(-1, 1, rows)
    X, Y = np.meshgrid(x, y)
    d = np.sqrt(X**2 + Y**2)
    mask = (rh - rl) * (1 - np.exp(-c * d**order)) + rl
    
    # 应用同态滤波
    img_log = np.log1p(img)
    img_fft = fft.fft2(img_log)
    img_fft_shift = fft.fftshift(img_fft)
    img_fft_filt = img_fft_shift * mask
    img_filt = np.real(fft.ifft2(fft.ifftshift(img_fft_filt)))
    img_exp = np.expm1(img_filt)
    img_norm = cv2.normalize(img_exp, None, 0, 255, cv2.NORM_MINMAX)

    return img_norm

# 读取图像
image = cv2.imread('/image_1.jpeg')

# 转换到HSV色彩空间
hsv_image = cv2.cvtColor(image, cv2.COLOR_RGB2HSV)
h, s, v = cv2.split(hsv_image)

# 对整个亮度通道应用同态滤波
v_filtered = homomorphic_filter(v)
v_filtered = v_filtered.astype(np.uint8)  # 转换为与色调、饱和度通道一致的类型

hsv_filtered = cv2.merge((h, s, v_filtered)) 
image_out = cv2.cvtColor(hsv_filtered, cv2.COLOR_HSV2RGB)

# 显示图像
plt.subplot(121), plt.imshow(image)
plt.title('Original Image'), plt.xticks([]), plt.yticks([])
plt.subplot(122), plt.imshow(image_out)
plt.title('Homomorphic Filtered Image'), plt.xticks([]), plt.yticks([])
plt.show()

解决方案

要实现仅对非零区域应用滤波,核心是提取非零区域掩码,对掩码内的区域单独做滤波,再将结果与原背景合并。修改后的代码如下:

import cv2
import matplotlib.pyplot as plt
from scipy import fftpack as fft
import numpy as np

def homomorphic_filter(img, low_cutoff=0.05, high_cutoff=0.5, order=2, boost=25):
    rows, cols = img.shape
    rh, rl, c = high_cutoff, low_cutoff, boost
    
    # 创建高斯滤波器
    x = np.linspace(-1, 1, cols)
    y = np.linspace(-1, 1, rows)
    X, Y = np.meshgrid(x, y)
    d = np.sqrt(X**2 + Y**2)
    mask = (rh - rl) * (1 - np.exp(-c * d**order)) + rl
    
    # 应用同态滤波
    img_log = np.log1p(img)
    img_fft = fft.fft2(img_log)
    img_fft_shift = fft.fftshift(img_fft)
    img_fft_filt = img_fft_shift * mask
    img_filt = np.real(fft.ifft2(fft.ifftshift(img_fft_filt)))
    img_exp = np.expm1(img_filt)
    img_norm = cv2.normalize(img_exp, None, 0, 255, cv2.NORM_MINMAX)

    return img_norm

# 读取黑背景图像
image = cv2.imread('/image_2.jpeg')

# 转换到HSV色彩空间(修正:cv2.imread默认读BGR,对应COLOR_BGR2HSV)
hsv_image = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
h, s, v = cv2.split(hsv_image)

# 生成非零区域掩码(针对亮度通道v)
mask = (v > 0).astype(np.uint8) * 255
# 可选:膨胀掩码优化边缘过渡,避免断层
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5,5))
mask = cv2.dilate(mask, kernel, iterations=1)

# 提取非零区域的ROI
non_zero_coords = np.where(mask > 0)
min_y, max_y = np.min(non_zero_coords[0]), np.max(non_zero_coords[0])
min_x, max_x = np.min(non_zero_coords[1]), np.max(non_zero_coords[1])
v_roi = v[min_y:max_y+1, min_x:max_x+1]

# 对ROI应用同态滤波
v_roi_filtered = homomorphic_filter(v_roi)
v_roi_filtered = v_roi_filtered.astype(np.uint8)

# 合并滤波结果与原背景
v_filtered = v.copy()
v_filtered[min_y:max_y+1, min_x:max_x+1] = v_roi_filtered

# 转换回RGB并显示
hsv_filtered = cv2.merge((h, s, v_filtered)) 
image_out = cv2.cvtColor(hsv_filtered, cv2.COLOR_HSV2RGB)

plt.subplot(121), plt.imshow(cv2.cvtColor(image, cv2.COLOR_BGR2RGB))
plt.title('Original Image'), plt.xticks([]), plt.yticks([])
plt.subplot(122), plt.imshow(image_out)
plt.title('Homomorphic Filtered Image'), plt.xticks([]), plt.yticks([])
plt.show()

关键修改说明

  • 生成掩码:通过v > 0提取亮度通道的非零区域,生成二值掩码,可选膨胀操作优化边缘过渡。
  • 提取ROI:根据掩码定位非零区域的边界,截取对应的亮度通道子区域。
  • 局部滤波合并:仅对ROI应用同态滤波,再将结果放回原亮度通道的对应位置,保留背景区域不变。

内容的提问来源于stack exchange,提问作者qwerty123

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 13:23:11