OpenCV 笔记(38):同态滤波

1. 同态滤波

同态滤波(Homomorphic Filtering)是一种经典的图像增强 方法,主要用于同时校正图像的 非均匀光照增强细节对比度

同态滤波的核心思想是将图像的光照分量 (低频)和反射分量(高频)分离,并分别进行调整,最终改善图像的对比度和细节。

2. 算法流程

2.1 图像模型

图像可表示为光照分量
和反射分量
的乘积:

其中:

  • :入射光照分量(illumination),通常变化平缓,包含低频信息。

  • :物体的反射分量(reflectance),变化剧烈,包含高频信息(细节、边缘)。

  • :观测到的图像。

2.2 对数变换

为了能够独立处理光照和反射,同态滤波的第一步是对图像的像素值取对数。因为在数学上,乘法运算在取对数后会变成加法运算。

此后,光照分量和反射分量在频域中更易于分离。

2.3 傅里叶变换

对取对数变换后的图像
进行傅里叶变换 ,转换到频域,得到频谱

这样做的目的是将图像分解为不同频率的成分。

2.4 设计滤波器

设计一个合适的滤波器函数
,并在频域中将频谱
与该滤波器相乘,得到滤波后的频谱

根据频率成分的特性进行增强或衰减。一个典型的同态滤波器会衰减低频成分(减少光照不均),并增强高频成分(增强细节和对比度)。

因此,滤波器函数
的设计是同态滤波的关键,不同的滤波器会产生不同的增强效果。

常见的同态滤波器形式包括:

  • 高斯型同态滤波器: 增强高频,衰减低频。过渡平滑,无振铃效应。

  • 巴特沃斯型同态滤波器: 具有更平滑的过渡带。阶数可调,灵活性高。

  • 指数型同态滤波器: 过渡特性介于高斯和巴特沃斯之间。

  • 理想高通同态滤波器: 低频完全抑制,高频完全保留。会导致严重振铃效应,实际应用较少。

这里,我们以高斯型同态滤波器为例,它是一种基于高斯函数设计的频域滤波器,结合同态滤波框架与高斯函数的频域特性,对图像的光照分量(低频)和反射分量(高频)进行差异化调整。我们用以下公式来表示高斯同态滤波器的传递函数:

其中,

  • : 低频增益(通常 <1,抑制光照不均)。

  • : 高频增益(通常 >1,增强细节)。

  • c : 控制滤波器陡峭程度的常数。

  • : 截止频率。

  • :频率点到中心的距离。

这个形式是一种 高斯型高通滤波器,嵌入到同态滤波的增益控制中,用来调节低频(光照分量)和高频(细节分量)的权重。

2.5 傅里叶逆变换

将滤波后的频谱
转换回空间域,得到滤波后的对数图像

2.6 指数运算

对图像
的每个像素值进行指数运算,得到最终的增强图像

这个步骤是为了恢复原始图像的尺度和亮度范围。由于第一步进行了对数运算,这里需要进行指数运算来还原。

总结一下整个算法的流程

原始图像 → 对数变换 → 傅里叶变换 → 同态滤波 → 逆傅里叶变换 → 指数变换 → 输出图像

3. 使用 OpenCV C++ 实现同态滤波

下面的例子,展示了如何基于上述的算法流程构建单通道同态滤波,以及如何构建高斯型高通同态滤波器。对于彩色图像而言,需要先分离出 B、G、R 通道,每个通道单独使用同态滤波,最后再合并回彩色图像。

go 复制代码
#include <opencv2/opencv.hpp>
#include <iostream>

usingnamespace cv;
usingnamespacestd;

// 构造高斯型高通同态滤波器
Mat createHighPassFilter(Size size, float gammaH, float gammaL, float c, float D0) {
    Mat H(size, CV_32F);
    Point center = Point(size.width / 2, size.height / 2);
    for (int u = 0; u < size.height; u++) {
        for (int v = 0; v < size.width; v++) {
            float D = sqrt(pow(u - center.y, 2) + pow(v - center.x, 2));
            H.at<float>(u, v) = (gammaH - gammaL) * (1.0f - exp(-c * (D * D) / (D0 * D0))) + gammaL;
        }
    }
    return H;
}

// 单通道同态滤波
Mat homomorphicFilter(const Mat& image, float gammaH, float gammaL, float c, float D0) {
    Mat floatImg;
    image.convertTo(floatImg, CV_32F);    // 转换为 float 类型,方便后续计算
    floatImg += 1;                      // 防止 log(0) 出现无穷大
    log(floatImg, floatImg);            // 对图像取对数:ln(f(x, y))

    // 对图像扩展到最佳 DFT 尺寸
    int m = cv::getOptimalDFTSize(image.rows);
    int n = cv::getOptimalDFTSize(image.cols);
    Mat padded;
    copyMakeBorder(floatImg, padded, 0, m - image.rows, 0, n - image.cols, BORDER_CONSTANT, Scalar::all(0));

    // 创建复数矩阵,实部为 padded,虚部为 0
    Mat planes[] = { padded, Mat::zeros(padded.size(), CV_32F) };
    Mat complexI;
    merge(planes, 2, complexI);

    // 进行傅里叶变换
    dft(complexI, complexI);

    // 创建高通同态滤波器,尺寸和 padded 一致
    Mat H = createHighPassFilter(padded.size(), gammaH, gammaL, c, D0);

    // 将频谱从笛卡尔坐标转换为极坐标(幅值和相位)
    split(complexI, planes);
    Mat mag, phase;
    cartToPolar(planes[0], planes[1], mag, phase);

    // 在频率域应用滤波器(只对幅值部分)
    mag = mag.mul(H);

    // 将极坐标转换回笛卡尔坐标
    polarToCart(mag, phase, planes[0], planes[1]);
    merge(planes, 2, complexI);

    // 傅里叶逆变换,回到空域
    idft(complexI, complexI);

    // 提取实部,去掉填充部分
    split(complexI, planes);
    Mat realI = planes[0](Rect(0, 0, image.cols, image.rows));

    // 归一化到 [0, 10],避免指数溢出
    normalize(realI, realI, 0, 10, NORM_MINMAX);

    // 对结果取指数,还原到线性空间
    Mat img_out;
    exp(realI, img_out);

    // 最后归一化到 [0, 255] 并转换为 8 位图像
    double minVal, maxVal;
    minMaxLoc(img_out, &minVal, &maxVal);
    img_out.convertTo(img_out, CV_8U, 255.0 / (maxVal - minVal), -minVal * 255.0 / (maxVal - minVal));

    return img_out;
}

int main() {
    Mat src = imread(".../landscape.jpg", IMREAD_UNCHANGED);
    if (src.empty()) {
        cout << "无法加载图像" << endl;
        return-1;
    }

    Mat result;

    if (src.channels() == 1) {
        // 灰度图像处理
        result = homomorphicFilter(src, 1.5f, 0.5f, 1.0f, 30.0f);
    } elseif (src.channels() == 3) {
        // 彩色图像处理(逐通道)
        vector<Mat> channels;
        split(src, channels);
        vector<Mat> resultChannels(3);

        for (int i = 0; i < 3; ++i) {
            resultChannels[i] = homomorphicFilter(channels[i], 1.5f, 0.5f, 1.0f, 30.0f);
        }
        merge(resultChannels, result);
    } else {
        cout << "不支持的图像通道数" << endl;
        return-1;
    }

    imshow("src", src);
    imshow("result", result);
    waitKey(0);

    return0;
}

原图.png 同态滤波后的效果图.png

4. 总结

同态滤波是一种通过频域处理解决图像光照不均的关键技术,其作用在于分离并差异化调整图像的低频光照分量和高频反射分量,增强图像对比度和细节,从而提高图像的视觉质量和可分析性。这在光照条件复杂或需要突出局部特征的应用中具有重要意义。

相关推荐
零壹AI实验室5 分钟前
用AI 10分钟搭建一个监控系统:Prometheus + Grafana 实战
人工智能·grafana·prometheus
志栋智能7 分钟前
超自动化巡检:量化运维成效的标尺
运维·网络·人工智能·自动化
AI科技星8 分钟前
紫金山天文台与6G 超导太赫兹实验对比【乖乖数学】
人工智能·线性代数·机器学习·量子计算·agi
摩尔线程9 分钟前
摩尔线程携手紫光计算机发布《语音识别全栈国产化技术实践白皮书》
人工智能·语音识别·摩尔线程
字节跳动开源10 分钟前
局中局!给 Agent 装上 OpenViking,它们竟然学会了“记仇”和“伪装”?
人工智能·开源·llm
Exploring12 分钟前
通过 Vibe Coding,我开发的第一款鸿蒙 App 上架了,欢迎大家下载体验
人工智能
杀生丸学AI16 分钟前
【VALSE 2026】AI领域年度重要进展
人工智能
TANGLONG22223 分钟前
【C++】继承详解——基类/派生类、作用域、默认函数、菱形继承(超详细)
java·c语言·c++·经验分享·笔记·ajax
沪漂阿龙23 分钟前
面试题:文本表示方法详解——One-hot、Word2Vec、上下文表示、BERT词向量全解析(NLP基础高频考点)
人工智能·神经网络·自然语言处理·bert·word2vec
Luminbox紫创测控27 分钟前
氙灯太阳光模拟器加速老化测试
人工智能·测试工具·测试标准