同态滤波的主要目的是为了消除光照不均,将空间域的图像信息转换为频率域进行处理,通过滤波器对频率域图像进行滤波,降低光照不均匀现象的影响,完成滤波后,再将图像转换到空间域中。
【1】源码
//同态滤波
#include"HomoFilter.h"
#include <iostream>
#include<opencv2/core.hpp>
#include<opencv.hpp>
#include<time.h>
#include <math.h>
using namespace cv;
using namespace std;
Mat HomoFilter(Mat inputImg) {
Mat homoImg = inputImg.clone();
Mat orginalImg = inputImg.clone();
homoImg.convertTo(homoImg, CV_64FC1);
int rows = homoImg.rows;
int cols = homoImg.cols;
int m = rows % 2 == 1 ? rows + 1 : rows;
int n = cols % 2 == 1 ? cols + 1 : cols;
copyMakeBorder(homoImg, homoImg, 0, m - rows, 0, n - cols, BORDER_CONSTANT, Scalar::all(0));
rows = homoImg.rows;
cols = homoImg.cols;
Mat homo_result_Img(rows, cols, CV_64FC1);
//1. ln
for (int i = 0; i < rows; i++) {
double *srcdata = homoImg.ptr<double>(i);
double *logdata = homoImg.ptr<double>(i);
for (int j = 0; j < cols; j++) {
logdata[j] = log(srcdata[j] + 0.0001);
}
}
//2. dct 离散余弦变换
Mat mat_dct = Mat::zeros(rows, cols, CV_64FC1);
dct(homoImg, mat_dct);
//3. 高斯同态滤波器
Mat H_u_v;
double gammaH = 3;//>1 高频增益
double gammaL = 0.1;//<1 低频增益
double C = 0.6; //斜面锐化常数 斜率
double d0 = (homoImg.rows / 2) * (homoImg.rows / 2) + (homoImg.cols / 2) * (homoImg.cols / 2);//截止频率
//double d0 = 150;//5-200 截止频率 越大越亮
double d2 = 0;
H_u_v = Mat::zeros(rows, cols, CV_64FC1);
for (int i = 0; i < rows; i++) {
double * dataH_u_v = H_u_v.ptr<double>(i);
for (int j = 0; j < cols; j++) {
d2 = pow((i- homoImg.rows / 2), 2.0) + pow((j- homoImg.cols / 2), 2.0);
dataH_u_v[j] = (gammaH - gammaL) * (1 - exp(-C * (d2 / d0))) + gammaL;
}
}
H_u_v.ptr<double>(0)[0] = 1.1;
mat_dct = mat_dct.mul(H_u_v);
//4. idct
idct(mat_dct, homo_result_Img);
//exp
for (int i = 0; i < rows; i++) {
double *srcdata = homo_result_Img.ptr<double>(i);
double *dstdata = homo_result_Img.ptr<double>(i);
for (int j = 0; j < cols; j++) {
dstdata[j] = exp(srcdata[j]);
}
}
homo_result_Img.convertTo(homo_result_Img, CV_8UC1);
return homo_result_Img;
}
//YUV空间
Mat YHomoFilter(Mat orginalImg)
{
int original_rows = orginalImg.rows;
int original_cols = orginalImg.cols;
Mat dst(original_rows, original_cols, CV_8UC3);
cvtColor(orginalImg, orginalImg, COLOR_BGR2YUV);
vector <Mat> yuvImg;
split(orginalImg, yuvImg);
Mat nowY = yuvImg[0];
Mat newY = HomoFilter(nowY);
Mat tempY(original_rows, original_cols, CV_8UC1);
for (int i = 0; i < original_rows; i++) {
for (int j = 0; j < original_cols; j++) {
tempY.at<uchar>(i, j) = newY.at<uchar>(i, j);
}
}
yuvImg[0] = tempY;
merge(yuvImg, dst);
cvtColor(dst, dst, COLOR_YUV2BGR);
return dst;
}
int main()
{
Mat src = imread("04.jpg");
Mat homoImg=YHomoFilter(src);
imwrite("04homoImg.jpg", homoImg);
//Mat allImg=SpliteImg(src);
waitKey(0);
return 0;
}
【2】结果
【3】参考
(3)https://github.com/lilingyu/homofilter/blob/master/hello_opencv/homo_filter.cpp