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

图像导向滤波:

导向滤波不仅仅能实现双边滤波的边缘平滑,而且在检测到边缘附近有很好的表现,可以应用在图像增强,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为真构造高斯随机变量X
	z0 = 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_I
	Mat mean_I;
	boxFilter(srcImage, mean_I, CV_64FC1, Size(r, r));
	//生成原始均值mean_p
	Mat mean_p;
	boxFilter(srcClone, mean_p, CV_64FC1, Size(r, r));
	//生成互相关均值mean_Ip
	Mat mean_Ip;
	boxFilter(srcImage.mul(srcClone), mean_Ip, CV_64FC1, Size(r, r));
	Mat cov_Ip = mean_Ip - mean_I.mul(mean_p);
	//生成自相关均值mean_II
	Mat 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,b
	Mat 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
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值