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 通道,每个通道单独使用同态滤波,最后再合并回彩色图像。
#include <opencv2/opencv.hpp>#include <iostream>using namespace cv;using namespace std;// 构造高斯型高通同态滤波器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); } else if (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); return 0;}
4. 总结
同态滤波是一种通过频域处理解决图像光照不均的关键技术,其作用在于分离并差异化调整图像的低频光照分量和高频反射分量,增强图像对比度和细节,从而提高图像的视觉质量和可分析性。这在光照条件复杂或需要突出局部特征的应用中具有重要意义。