OpenCV学习笔记(十一)图像导向滤波

来源:互联网 发布:手机淘宝悬浮红包设置 编辑:程序博客网 时间:2024/05/16 19:09

图像导向滤波:

导向滤波不仅仅能实现双边滤波的边缘平滑,而且在检测到边缘附近有很好的表现,可以应用在图像增强,HDR压缩,图像抠图及图像去雾等场景中。

直接看实现吧:

#include <iostream>#include <opencv2/highgui/highgui.hpp>#include <opencv2/imgproc/imgproc.hpp>using namespace cv;using namespace std;double generateGaussianNoise(double mu, double sigma){//定义一个特别小的值const double epsilon = numeric_limits<double>::min();//返回目标数据类型能表示的最逼近1的正数和1的差的绝对值static double z0, z1;static bool flag = false;flag = !flag;//flag为假,构造高斯随机变量if (!flag)return z1*sigma + mu;double u1, u2;//构造随机变量do{u1 = rand()*(1.0 / RAND_MAX);u2 = rand()*(1.0 / RAND_MAX);} while (u1 <= epsilon);//flag为真构造高斯随机变量Xz0 = sqrt(-2.0*log(u1))*cos(2 * CV_PI * u2);z1 = sqrt(-2.0*log(u1))*sin(2 * CV_PI * u2);return z0*sigma + mu;}Mat addGaussianNoise(Mat& srcImage){Mat resultImage = srcImage.clone();    //深拷贝,克隆int channels = resultImage.channels();    //获取图像的通道int nRows = resultImage.rows;    //图像的行数int nCols = resultImage.cols*channels;   //图像的总列数//判断图像的连续性if (resultImage.isContinuous())    //判断矩阵是否连续,若连续,我们相当于只需要遍历一个一维数组 {nCols *= nRows;nRows = 1;}for (int i = 0; i < nRows; i++){for (int j = 0; j < nCols; j++){//添加高斯噪声int val = resultImage.ptr<uchar>(i)[j] + generateGaussianNoise(2, 0.8) * 32;if (val < 0)val = 0;if (val > 255)val = 255;resultImage.ptr<uchar>(i)[j] = (uchar)val;}}return resultImage;}Mat guidedfilter(Mat &srcImage, Mat &srcClone, int r, double eps){srcImage.convertTo(srcImage, CV_64FC1);srcImage.convertTo(srcClone, CV_64FC1);int nRows = srcImage.rows;int nCols = srcImage.cols;Mat boxResult;//计算均值boxFilter(Mat::ones(nRows, nCols, srcImage.type()), boxResult, -1, Size(r, r));//生成导向均值mean_IMat mean_I;boxFilter(srcImage, mean_I, CV_64FC1, Size(r, r));//生成原始均值mean_pMat mean_p;boxFilter(srcClone, mean_p, CV_64FC1, Size(r, r));//生成互相关均值mean_IpMat mean_Ip;boxFilter(srcImage.mul(srcClone), mean_Ip, CV_64FC1, Size(r, r));Mat cov_Ip = mean_Ip - mean_I.mul(mean_p);//生成自相关均值mean_IIMat mean_II;//盒滤波器计算相关均值boxFilter(srcImage.mul(srcImage), mean_II, CV_64FC1, Size(r, r));//步骤二:计算相关系数Mat var_I = mean_II - mean_I.mul(mean_I);Mat var_Ip = mean_Ip - mean_I.mul(mean_p);//步骤三:计算参数系数a,bMat a = cov_Ip / (var_I + eps);Mat b = mean_p - a.mul(mean_I);//步骤四:计算系数a,b的均值Mat mean_a;boxFilter(a, mean_a, CV_64FC1, Size(r, r));mean_a = mean_a / boxResult;Mat mean_b;boxFilter(b, mean_b, CV_64FC1, Size(r, r));//步骤五:生成输出矩阵Mat resultMat = mean_a.mul(srcImage) + mean_b;return resultMat;}int main(){Mat srcImage = imread("D:\\1.jpg");if (srcImage.empty())return -1;Mat dstImage = addGaussianNoise(srcImage);vector<Mat> vDstImage, vResultImage;split(dstImage, vDstImage);Mat resultMat;for (int i = 0; i < 3; i++){Mat tempImage;vDstImage[i].convertTo(tempImage, CV_64FC1, 1.0 / 255.0);Mat p = tempImage.clone();//分别进行导向滤波Mat resultImage = guidedfilter(tempImage, p, 4, 0.01);vResultImage.push_back(resultImage);}merge(vResultImage, resultMat);imshow("srcImage", srcImage);imshow("dstImage", dstImage);imshow("resultMat", resultMat);waitKey(0);return 0;}

源图像:


高斯噪声图像:


导向滤波:


1 0