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

同态滤波低光图像增强代码疑问:为何需反转归一化图像?

同态滤波低光图像增强代码问题排查

我基于IEEE论文实现低光图像增强项目,核心步骤应为log变换→FFT→应用同态滤波器→IFFT→exp变换,但复现时代码最后一步需要用255 - 归一化图像才能得到正常结果,同时不确定代码是否存在其他问题。

现有代码

def log_reflection_compute(img, variance):
    log_reflection = np.log10(img) - np.log10(cv2.GaussianBlur(img, (0, 0), variance))
    return log_reflection

def log_illumination_compute(img, log_reflection):
    log_illumination = np.log10(img) - log_reflection
    return log_illumination

def homomorphic_filter(reflection, illumination, sigma, yH, yL, c=1):
    ln_reflection = np.log(reflection)
    ln_illumination = np.log(illumination)

    fft_reflection = np.fft.fft2(ln_reflection, axes=(0, 1))
    fft_illumination = np.fft.fft2(ln_illumination, axes=(0, 1))

    fft_shift_reflection = np.fft.fftshift(fft_reflection)
    fft_shift_illumination = np.fft.fftshift(fft_illumination)

    rows, cols = fft_shift_reflection.shape[:2]
    crow, ccol = rows // 2, cols // 2
    x = np.linspace(-ccol, ccol, cols)
    y = np.linspace(-crow, crow, rows)
    x, y = np.meshgrid(x, y)
    D = np.sqrt(x**2 + y**2)

    H = 1 - np.exp(- c *(D**2) / (2 * (sigma**2)))
    H = (yH - yL) * H + yL

    reflection_filtered = np.multiply(fft_shift_reflection, H)
    illumination_filtered = np.multiply(fft_shift_illumination, H)

    reflection_filtered = np.fft.ifftshift(reflection_filtered)
    illumination_filtered = np.fft.ifftshift(illumination_filtered)

    reflection_filtered = np.fft.ifft2(reflection_filtered, axes=(0, 1))
    illumination_filtered = np.fft.ifft2(illumination_filtered, axes=(0, 1))

    reflection_magnitude = np.abs(reflection_filtered)
    illumination_magnitude = np.abs(illumination_filtered)

    img_homomorphic = (np.exp(reflection_magnitude) * np.exp(illumination_magnitude)) - 1
    img_homomorphic = 255 - cv2.normalize(img_homomorphic, None, 0, 255, cv2.NORM_MINMAX).astype(np.uint8)

    return img_homomorphic

图像对比

  • 原图:原图
  • 未反转图像:未反转像素的图像
  • 反转后图像:反转像素后的图像

问题分析与修正

1. 核心逻辑错误:反射/光照分量拆分

同态滤波的基础模型是图像=反射分量×光照分量($I(x,y)=R(x,y) \times L(x,y)$),取对数后应为:
$$\log(I) = \log(R) + \log(L)$$
你现在的log_reflection_compute用减法拆分分量,完全违背了这个模型,导致后续处理的是错误的分量,最终图像反转,不得不通过255-修正。

2. 冗余操作:对两个分量分别滤波

同态滤波不需要提前拆分反射和光照,而是直接对整个图像的对数域做傅里叶变换,应用滤波器后再逆变换还原。滤波器会自动对高频(反射分量,对应细节)和低频(光照分量,对应全局亮度)施加不同增益。

3. 其他细节问题

  • 混用np.log10和np.log:两者底数不同,后续用np.exp还原对应自然对数,应统一用np.log;
  • 未处理图像0值:log(0)无意义,需给图像加微小偏移量避免报错;
  • 逆变换取绝对值:傅里叶逆变换的结果应为实数(数值误差可能带微小虚部),应取实部而非绝对值。

修正后的代码

import numpy as np
import cv2

def homomorphic_filter(img, sigma, yH, yL, c=1):
    # 预处理:转浮点型,避免0值导致log报错
    img_float = img.astype(np.float32) + 1e-8
    # 对数变换
    log_img = np.log(img_float)
    # 傅里叶变换
    fft_img = np.fft.fft2(log_img)
    # 移频到中心
    fft_shift = np.fft.fftshift(fft_img)
    
    rows, cols = img.shape[:2]
    crow, ccol = rows // 2, cols // 2
    # 构建距离矩阵
    x = np.linspace(-ccol, ccol - 1, cols)
    y = np.linspace(-crow, crow - 1, rows)
    x, y = np.meshgrid(x, y)
    D = np.sqrt(x**2 + y**2)
    
    # 构建高通同态滤波器:提升高频细节,压制低频光照
    H = (yH - yL) * (1 - np.exp(-c * (D**2) / (2 * sigma**2))) + yL
    
    # 应用滤波器
    fft_filtered = fft_shift * H
    # 逆移频
    ifft_shift = np.fft.ifftshift(fft_filtered)
    # 逆傅里叶变换
    ifft_img = np.fft.ifft2(ifft_shift)
    # 取实部消除数值误差带来的虚部
    log_filtered = np.real(ifft_img)
    # 指数变换还原图像
    img_homomorphic = np.exp(log_filtered)
    # 归一化到0-255并转成uint8格式
    img_homomorphic = cv2.normalize(img_homomorphic, None, 0, 255, cv2.NORM_MINMAX).astype(np.uint8)
    
    return img_homomorphic

修正后效果

修正后的代码无需再用255-反转图像,直接输出正常的低光增强结果,符合同态滤波的数学逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 15:48:10