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. 总结

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

相关推荐
敦普水性工业漆3 分钟前
汽车紧固件防腐3.0时代:敦普水性漆用无铬锌铝涂层定义「零氢脆」标准
笔记·汽车
新加坡内哥谈技术21 分钟前
亚马逊推出新型仓储机器人 Vulcan:具备“触觉”但不会取代人类工人
人工智能
Alter123023 分钟前
从一城一云到AI CITY,智慧城市进入新阶段
人工智能·智慧城市
科技小E28 分钟前
国标GB28181视频平台EasyCVR安防系统部署知识:如何解决异地监控集中管理和组网问题
大数据·网络·人工智能·音视频
chat2tomorrow1 小时前
如何使用 QuickAPI 推动医院数据共享 —— 基于数据仓库场景的实践
大数据·数据仓库·人工智能·医院·sql2api
lcw_lance1 小时前
数字孪生[IOC]常用10个技术栈(总括)
大数据·运维·人工智能
AI蜗牛车1 小时前
【LLM+Code】Devin Prompt&Tools详细解读
人工智能·语言模型·prompt·copilot·agent
极小狐1 小时前
如何使用极狐GitLab 软件包仓库功能托管 ruby?
开发语言·数据库·人工智能·git·机器学习·gitlab·ruby
UI设计兰亭妙微1 小时前
APP 设计中的色彩心理学:如何用色彩提升用户体验
人工智能·ux
Jamence1 小时前
多模态大语言模型arxiv论文略读(六十五)
人工智能·语言模型·自然语言处理