学习guide滤波算法

前几天,老大给分陪了新的项目,开始和同事做滤波增强。开始几天看了一点相对好的算法,包括双边滤波,还有一个基于SVM学习的滤波算法(具体名字忘记了),然后就是同事推荐的导向滤波,查了下,确实感觉不错,能够良好的保持边缘特性。

基本思想大致是这样的,通过函数上的某一点与其邻近部分的点成线性关系,一个复杂的函数就可以用很多局部的线性函数来表示,当需求该函数上某一点时,只需要计算包含该店的线性函数的值并做平均即可。这种模型在表示非解析函数上非常有用,同理我们可以认为图像是一个二维函数。

        函数输入输出关系(二维窗口内),满足

q=aI+b  其中q是输出像素的值,I是输入像素的值。   

梯度q=a*梯度I

这个公式解释了输出具有边缘保持效果的原因。


剩下的就是求线性函数系数的回归运算,即希望拟合值与真实值P之间的差距最小

        E(a,b)=sum((aI+b-p))^2 + e*a^2)

        p是待滤波图像并不像I可以是任意其他的图像。

最终求得系数为:

a=(1/|w| * sum (I*P)-u*P)/(var^2+e)

        b=(mean(p)-a/u)

最终的输出q=mean(a)*mean(I)+mean(b)

  |w|是窗口中像素的数量    var^2:方差  u:均值   mean(p)是滤波图像P在窗口中的均值

大体上就是不断计算,zai计算,求取均值,方差协方差等等吧

应项目需求,参考大神们的足迹,也实现了算法,要学的东西很多,希望毕业前做一个,记住一个,积累吧,还得学习编码。据说是 然要有梦想 万一实现了呢,逗比一下自己。

       

/************************************************************************
*  @Author : YG
*  @  Date : 2015/12/30
*  @ Email : 1851506****@163.com
*  function: 引导滤波
*  introduc:引导滤波是最近比较好的,前沿性的滤波方法,利用了线性模型,不仅能够平滑图像,而且保留了边缘特性,通过函数上一点与其领域部分点的线性关系,一个复杂的函数就可以用很多局部的线性函数来表示,当需求该函数上某一点的值时,只计算包含该点的线性函数的值并做平均即可,这种模型在表示解析函数上非常有效。e是尺度参数,平滑参数,为全局参数,大小影响整个分量的估计结果,尤其是细节比较丰富的图像。
************************************************************************/

#include "stdafx.h"
#include "guilt_me.h"
#include <iostream>
#include <windows.h>

using namespace std;
using namespace cv;


//灰度图处理
/*Mat img_do(Mat &img)
{
	if (!img.data)
	{
		cout << "no data of img1" << endl;
	}
	Mat img_gray(img.size(), CV_8UC1);
	cvtColor(img, img_gray, CV_BGR2GRAY);

	return img_gray;

}*/
/************************************************************************/
/*调节半径r,回调 */
/************************************************************************/
void on_guilt_feliter(int, void*)
{
	vector<Mat> bgr_src, bgr_dst;
	split(img1, bgr_src);
	Mat dst_color;
	double time;
	time = (double)GetTickCount();
	Mat q;
	for (int i = 0; i < 3; i++)
	{
		Mat I = img_Get(bgr_src[i]);
		Mat p = I.clone();
		q = guidedfilter(p, I, r, (double)e / 100);
		bgr_dst.push_back(q);
	}
	merge(bgr_dst, dst_color);

	imwrite("filtered.JPG", q * 255);
	time = 1000 * ((double)getTickCount() - time) / getTickFrequency();

	cout << endl << "Time of guided filter for  runs: " << time << " milliseconds." << endl;

	imshow("效果图", dst_color);
	imwrite("result.jpg", dst_color * 255);

	waitKey(0);

}
/************************************************************************/
/* 调节参数e,进行回调*/
/************************************************************************/
void on_guilt_feliter_e(int, void*)
{
	vector<Mat> bgr_src, bgr_dst;
	split(img1, bgr_src);
	Mat dst_color;
	double time;
	time = (double)GetTickCount();
	Mat q;
	for (int i = 0; i < 3; i++)
	{
		Mat I = img_Get(bgr_src[i]);
		Mat p = I.clone();
		q = guidedfilter(p, I, r, (double)e / 100);
		bgr_dst.push_back(q);
	}
	merge(bgr_dst, dst_color);

	imwrite("filtered.JPG", q * 255);
	time = 1000 * ((double)getTickCount() - time) / getTickFrequency();

	cout << endl << "Time of guided filter for  runs: " << time << " milliseconds." << endl;

	imshow("效果图", dst_color);
	imwrite("result.jpg", dst_color * 255);
	while (char(waitKey(1) != 'o'))
	{
	}

}
/************************************************************************/
/* 无模板,自身为模板*/
/************************************************************************/
void _no_model()
{
	img1 = imread("1.jpg", 1);
	namedWindow("原始图");
	imshow("原始图", img1);
	namedWindow("效果图");
	createTrackbar("半径r:", "效果图", &r, 30, on_guilt_feliter);
	createTrackbar("参数e:", "效果图", &e, 1000, on_guilt_feliter_e);
	on_guilt_feliter(r, 0);
	on_guilt_feliter_e(e, 0);

}
/************************************************************************/
/*主函数入口 */
/************************************************************************/
int _tmain(int argc, _TCHAR* argv[])
{
	_no_model();
	cout << "the programe is over!" << endl;
	return 0;
}
引导滤波的算法在下面

#include <opencv.hpp>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>

using namespace std;
using namespace cv;

//声明全局变量
int r = 16;
int e = 1;

//定义显示图像
Mat img1, img2;
Mat o_img;

//调节滑块
static void on_guilt_feliter(int, void*);
static void on_guilt_feliter_e(int, void*);
/************************************************************************/
/*获取图像,定义64深度图,进行乘积运算,防止过界 */
/************************************************************************/
Mat img_Get(Mat &a)
{
	int h = a.rows;
	int w = a.cols;
	Mat I(h, w, CV_64FC1);

	a.convertTo(I, CV_64FC1);

	for (int i = 0; i < h; i++)
	{
		double *p = I.ptr<double>(i);
		for (int j = 0; j < w; j++)
		{
			p[j] = p[j] / 255.0;
		}
	}
	return I;
}
/************************************************************************/
/* 统计sum*/
/************************************************************************/

Mat calculate_Sum(Mat &img_Src, int rc)
{
	int h = img_Src.rows;
	int w = img_Src.cols;
	Mat img_Sum = img_Src.clone();
	if (rc == 1)
	{
		for (int i = 1; i < h; i++)
		{
			for (int j = 0; j < w; j++)
			{
				img_Sum.at<double>(i, j) += img_Sum.at<double>(i - 1, j);
			}
		}
	}

	if (rc == 2)
	{
		for (int i = 0; i < h; i++)
		{
			for (int j = 1; j < w; j++)
			{
				img_Sum.at<double>(i, j) += img_Sum.at<double>(i, j - 1);
			}
		}
	}
	return img_Sum;
}
/************************************************************************/
/*方框滤波函数调用,开源代码 */
/************************************************************************/
Mat boxfilter(Mat &img_Src, int r)
{
	int h = img_Src.rows;
	int w = img_Src.cols;
	Mat img_dst = Mat::zeros(h, w, CV_64FC1);

	Mat img_Sum = calculate_Sum(img_Src, 1);

	for (int i = 0; i < r + 1; i++)
	{
		for (int j = 0; j < w; j++)
		{
			img_dst.at<double>(i, j) = img_Sum.at<double>(i + r, j);
		}
	}

	for (int i = r + 1; i < h - r; i++)
	{
		for (int j = 0; j < w; j++)
		{
			img_dst.at<double>(i, j) = img_Sum.at<double>(i + r, j) - img_Sum.at<double>(i - r - 1, j);
		}
	}

	for (int i = h - r; i < h; i++)
	{
		for (int j = 0; j < w; j++)
		{
			img_dst.at<double>(i, j) = img_Sum.at<double>(h - 1, j) - img_Sum.at<double>(i - r - 1, j);
		}
	}
	img_Sum = calculate_Sum(img_dst, 2);

	for (int i = 0; i < h; i++)
	{
		for (int j = 0; j < r + 1; j++)
		{
			img_dst.at<double>(i, j) = img_Sum.at<double>(i, j + r);
		}
	}

	for (int i = 0; i < h; i++)
	{
		for (int j = r + 1; j < w - r; j++)
		{
			img_dst.at<double>(i, j) = img_Sum.at<double>(i, j + r) - img_Sum.at<double>(i, j - r - 1);
		}
	}

	for (int i = 0; i < h; i++)
	{
		for (int j = w - r; j < w; j++)
		{
			img_dst.at<double>(i, j) = img_Sum.at<double>(i, w - 1) - img_Sum.at<double>(i, j - r - 1);
		}
	}
	return img_dst;
}
/************************************************************************/
/*引导滤波函数u,实现,参考公式,主要计算均值,方差,协方差等 */
/************************************************************************/
Mat guidedfilter(Mat &I, Mat &p, int r, double eps)
{
	int h = I.rows;
	int w = I.cols;

	Mat one = Mat::ones(h, w, CV_64FC1);
	Mat N = boxfilter(one, r);


	Mat mean_I(h, w, CV_64FC1);
	divide(boxfilter(I, r), N, mean_I);


	Mat mean_p(h, w, CV_64FC1);
	divide(boxfilter(p, r), N, mean_p);


	Mat mul_Ip(h, w, CV_64FC1);
	Mat mean_Ip(h, w, CV_64FC1);
	multiply(I, p, mul_Ip);
	divide(boxfilter(mul_Ip, r), N, mean_Ip);


	Mat mul_mean_Ip(h, w, CV_64FC1);
	Mat cov_Ip(h, w, CV_64FC1);
	multiply(mean_I, mean_p, mul_mean_Ip);
	subtract(mean_Ip, mul_mean_Ip, cov_Ip);


	Mat mul_II(h, w, CV_64FC1);
	Mat mean_II(h, w, CV_64FC1);
	multiply(I, I, mul_II);
	divide(boxfilter(mul_II, r), N, mean_II);


	Mat mul_mean_II(h, w, CV_64FC1);
	Mat var_I(h, w, CV_64FC1);
	multiply(mean_I, mean_I, mul_mean_II);
	subtract(mean_II, mul_mean_II, var_I);


	Mat a(h, w, CV_64FC1);
	for (int i = 0; i < h; i++)
	{
		double *p = var_I.ptr<double>(i);
		for (int j = 0; j < w; j++)
		{
			p[j] = p[j] + eps;
		}
	}
	divide(cov_Ip, var_I, a);


	Mat a_mean_I(h, w, CV_64FC1);
	Mat b(h, w, CV_64FC1);
	multiply(a, mean_I, a_mean_I);
	subtract(mean_p, a_mean_I, b);


	Mat mean_a(h, w, CV_64FC1);
	divide(boxfilter(a, r), N, mean_a);
	Mat mean_b(h, w, CV_64FC1);
	divide(boxfilter(b, r), N, mean_b);

	Mat mean_a_I(h, w, CV_64FC1);
	Mat q(h, w, CV_64FC1);
	multiply(mean_a, I, mean_a_I);
	add(mean_a_I, mean_b, q);

	return q;
}







  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值