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

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

相关推荐
拾忆-eleven19 分钟前
NLP学习路线图(十四):词袋模型(Bag of Words)
人工智能·学习·自然语言处理·nlp
sbc-study1 小时前
精英-探索双群协同优化(Elite-Exploration Dual Swarm Cooperative Optimization, EEDSCO)
人工智能
白熊1881 小时前
【机器学习基础】机器学习入门核心算法:XGBoost 和 LightGBM
人工智能·算法·机器学习
泉飒2 小时前
lua注意事项
开发语言·笔记·lua
微学AI2 小时前
智能穿戴新标杆:SD NAND (贴片式SD卡)与 SOC 如何定义 AI 眼镜未来技术路径
人工智能·ai·sd
拾忆-eleven2 小时前
NLP学习路线图(十五):TF-IDF(词频-逆文档频率)
人工智能·学习·自然语言处理·nlp
封奚泽优3 小时前
使用Python绘制节日祝福——以端午节和儿童节为例
人工智能·python·深度学习
全域智图3 小时前
元胞自动机(Cellular Automata, CA)
人工智能·算法·机器学习
富唯智能3 小时前
复合机器人:纠偏算法如何重塑工业精度与效率?
人工智能·工业机器人·智能机器人
s153353 小时前
3.RV1126-OPENCV 图像叠加
人工智能·opencv·计算机视觉