Opencv均值滤波

这里是本人根据资料所写的均值滤波算子,可供参考,如有好的建议,可以指出。

#include <opencv2/core.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv.hpp>
#include <limits.h>
#include <iostream>
#include <ctime>
#include <limits>
#include <vector>
#include "opencv_Filter.h"
/*
	功能:单通道常规均值滤波器算法
	参数:
		src:输入原图像
		dst:输出图像
		size:表示核大小
	返回值:无
*/

void MeanFilter(cv::Mat &src, cv::Mat &dst, cv::Size wsize)
{
	//图像的边缘扩充:窗口的半径
	if (wsize.height % 2 == 0 || wsize.width % 2 == 0)//判断是否为奇数
	{
		fprintf(stderr, "Please enter odd size!");
			exit(-1);
	}

	int hh = (wsize.height - 1) / 2;//半径
	int ww = (wsize.width - 1) / 2;//半径

	cv::Mat newSrc;
	cv::copyMakeBorder(src, newSrc, hh, hh, ww, ww, cv::BORDER_REFLECT_101);//以边缘为轴,对称
	//cv::imshow("test", newSrc);
	dst = cv::Mat::zeros(src.size(), src.type());


	//均值滤波
	int sum = 0;//窗口像素值之和
	int mean = 0;//均值

	for (int i = hh; i < src.rows + hh; ++i)
	{
		for (int j = ww; j < src.cols + ww; ++j)
		{
			for (int r = i - hh; r <= i + hh; ++r)
			{
				for (int c = j - ww; c <= j + ww; ++c)
				{
					sum = newSrc.at<uchar>(r, c) + sum;
				}
			}
			mean = sum / (wsize.area());
			dst.at<uchar>(i - hh, j - ww) = mean;
			sum = 0;
			mean = 0;
		}
	}
	//cv::imshow("test", dst);
}

void meanImage(cv::Mat &src, cv::Mat &dst, cv::Size wsize)
{
	//初始化输出图像
	dst = cv::Mat::zeros(src.size(),src.type());

	//确保掩模宽高相等
	if (wsize.height != wsize.width)
	{
		wsize.height = wsize.width;
	}
	//确保为奇数
	if (wsize.height % 2 == 0 || wsize.width % 2 == 0)//判断是否为奇数
	{
		wsize.height = wsize.height + 1;
		wsize.width = wsize.height;
	}

	//取窗口的半径
	int hh = (wsize.height - 1) / 2;//半径
	int ww = (wsize.width - 1) / 2;//半径

	//扩充边缘
	cv::Mat newSrc;
	cv::copyMakeBorder(src, newSrc, hh, hh, ww, ww, cv::BORDER_REFLECT_101);//以边缘为轴,对称

	//遍历除边界像素外的所有像素
	int sum = 0;//区域像数值的和

	for (int r = hh; r < src.rows + hh; r++) {
		for (int c = ww; c < src.cols + ww; c++) {
			//计算掩模覆盖的所有像素值的和		
			for (int i = r - hh; i <= r + hh; i++) {
				for (int j = c - ww; j <= c + ww; j++) {
					sum += newSrc.at<uchar>(i, j);
				}
			}
			//求均值并赋值给相应位置的像素
			dst.at<uchar>(r - hh, c - ww) = sum / wsize.area();
			sum = 0;
		}
	}
}

/*
	功能:单通道快速均值滤波(积分图快速均值滤波)
	参数:
	src:输入原图像
	dst:生成目标图像
	wsize:核大小
	返回值:无
*/
void Fast_MeanFilter(cv::Mat &src, cv::Mat &dst, cv::Size wsize)
{
	//图像边界扩充
	//图像的边缘扩充:窗口的半径
	if (wsize.height % 2 == 0 || wsize.width % 2 == 0)//判断是否为奇数
	{
		fprintf(stderr, "Please enter odd size!");
		exit(-1);
	}

	int hh = (wsize.height - 1) / 2;//半径
	int ww = (wsize.width - 1) / 2;//半径

	cv::Mat newSrc;
	cv::copyMakeBorder(src, newSrc, hh, hh, ww, ww, cv::BORDER_REFLECT_101);//以边缘为轴,对称
	//cv::imshow("test", newSrc);
	dst = cv::Mat::zeros(src.size(), src.type());

	//imshow("test1", newSrc);

	//计算积分图
	cv::Mat inte;
	//Im_integral(newSrc, inte);
	Fast_integral(newSrc, inte);

	//imshow("test2", inte);
	//均值滤波
	double mean = 0;
	for (int i = hh + 1; i < src.rows + hh + 1; ++i)
	{
		for (int j = ww + 1; j < src.cols + ww + 1; ++j)
		{
			double top_left = inte.at<double>(i - hh - 1, j - ww - 1);
			double top_right = inte.at<double>(i - hh - 1, j + ww);
			double buttom_left = inte.at<double>(i + hh, j - ww - 1);
			double buttom_right = inte.at<double>(i + hh, j + ww);

			mean = (top_left + buttom_right - top_right - buttom_left) / wsize.area();


			if (mean < 0)
			{
				mean = 0;
			}
			else if (mean > 255)
			{
				mean = 255;
			}
			dst.at<uchar>(i - hh - 1, j - ww - 1) = static_cast<uchar>(mean);
		}
	}
}

/*
	功能:计算积分图 常规方法
	参数:
	src:原图像
	dst:生成目标图像
	返回值:无
*/
void Im_integral(cv::Mat &src, cv::Mat &dst)
{
	int row = src.rows;
	int column = src.cols;
	//imshow("test3", src);
	//dst = cv::Mat::zeros(src.size(), src.type());
	//创建一个目标图像标准格式
	dst = cv::Mat::zeros(row + 1, column + 1, CV_64F);

	for (int i = 1; i < dst.rows; ++i)
	{
		for (int j = 1; j < dst.cols; ++j)
		{
			double top_left = dst.at<double>(i - 1, j - 1);
			double top_right = dst.at<double>(i - 1, j);
			double buttom_left = dst.at<double>(i, j - 1);

			int buttom_right = src.at<uchar>(i - 1, j - 1);

			dst.at<double>(i, j) = buttom_left + top_right - top_left + buttom_right;
		}
	}
	//imshow("test4", dst);
}

/*
	功能:计算积分图 快速方法
	参数:
	src:原图像
	dst:生成目标图像
	返回值:无
*/
void Fast_integral(cv::Mat &src, cv::Mat &dst)
{
	int row = src.rows;
	int column = src.cols;
	//imshow("test3", src);
	//dst = cv::Mat::zeros(src.size(), src.type());
	//创建一个目标图像标准格式
	dst = cv::Mat::zeros(row + 1, column + 1, CV_64F);
	int sum = 0;
	for (int i = 1; i < dst.rows; ++i)
	{//列扫描
		for (int j = 1,sum = 0; j < dst.cols; ++j)
		{//行累加
			sum += src.at<uchar>(i - 1, j - 1);
			dst.at<double>(i, j) = dst.at<double>(i-1,j) + sum;
		}
	}
	//imshow("test4", dst);
}


/*
	功能:给图像添加椒盐噪声
	参数:
	src 输入原图像
	n 椒盐噪声个数
	返回值:
	dstImage 返回椒盐结果图像
*/
Mat addSaltNoise(const Mat srcImage, int n)
{
	Mat dstImage = srcImage.clone();
	for (int k = 0; k < n; k++)
	{
		//随机取值行列  
		int i = rand() % dstImage.rows;
		int j = rand() % dstImage.cols;
		//图像通道判定  
		if (dstImage.channels() == 1)
		{
			dstImage.at<uchar>(i, j) = 255;       //盐噪声  
		}
		else
		{
			dstImage.at<Vec3b>(i, j)[0] = 255;
			dstImage.at<Vec3b>(i, j)[1] = 255;
			dstImage.at<Vec3b>(i, j)[2] = 255;
		}
	}
	for (int k = 0; k < n; k++)
	{
		//随机取值行列  
		int i = rand() % dstImage.rows;
		int j = rand() % dstImage.cols;
		//图像通道判定  
		if (dstImage.channels() == 1)
		{
			dstImage.at<uchar>(i, j) = 0;     //椒噪声  
		}
		else
		{
			dstImage.at<Vec3b>(i, j)[0] = 0;
			dstImage.at<Vec3b>(i, j)[1] = 0;
			dstImage.at<Vec3b>(i, j)[2] = 0;
		}
	}
return dstImage;
}


/*
	功能:多通道均值滤波  动态地址实现
	参数:
	返回值:
*/
void AverFiltering(const Mat& srcImage, Mat& dstImage)
{
	if (!srcImage.data)
		return;
	dstImage.create(srcImage.size(), srcImage.type());
	for (int i = 1; i < srcImage.rows-1; i++)
	{
		for (int j = 1; j < srcImage.cols-1; ++j)
		{
			//if (((i - 1) >= 0) && ((j - 1) >= 0) && ((i + 1) < srcImage.rows) && ((j + 1) < srcImage.cols))
			//{
				dstImage.at<Vec3b>(i, j)[0] = (srcImage.at<Vec3b>(i - 1, j - 1)[0] + srcImage.at<Vec3b>(i, j - 1)[0] + srcImage.at<Vec3b>(i + 1, j - 1)[0] + 
					srcImage.at<Vec3b>(i - 1, j)[0] + srcImage.at<Vec3b>(i, j)[0] + srcImage.at<Vec3b>(i + 1, j)[0] + srcImage.at<Vec3b>(i - 1, j + 1)[0] + 
					srcImage.at<Vec3b>(i, j + 1)[0] + srcImage.at<Vec3b>(i + 1, j + 1)[0]) / 9;
				
				dstImage.at<Vec3b>(i, j)[1] = (srcImage.at<Vec3b>(i - 1, j - 1)[1] + srcImage.at<Vec3b>(i, j - 1)[1] + srcImage.at<Vec3b>(i + 1, j - 1)[1] +
					srcImage.at<Vec3b>(i - 1, j)[1] +     srcImage.at<Vec3b>(i, j)[1] +     srcImage.at<Vec3b>(i + 1, j)[1] +
					srcImage.at<Vec3b>(i - 1, j + 1)[1] + srcImage.at<Vec3b>(i, j + 1)[1] + srcImage.at<Vec3b>(i + 1, j + 1)[1]) / 9;

				dstImage.at<Vec3b>(i, j)[2] = (srcImage.at<Vec3b>(i - 1, j - 1)[2] + srcImage.at<Vec3b>(i, j - 1)[2] + srcImage.at<Vec3b>(i + 1, j - 1)[2] +
					srcImage.at<Vec3b>(i - 1, j)[2] + srcImage.at<Vec3b>(i, j)[2] + srcImage.at<Vec3b>(i + 1, j)[2] +
					srcImage.at<Vec3b>(i - 1, j + 1)[2] + srcImage.at<Vec3b>(i, j + 1)[2] + srcImage.at<Vec3b>(i + 1, j + 1)[2]) / 9;
		//	}
			//else
			//{
			//	//边缘处理  无需处理
			//	/*dstImage.at<Vec3b>(i, j)[0] = srcImage.at<Vec3b>(i, j)[0];
			//	dstImage.at<Vec3b>(i, j)[1] = srcImage.at<Vec3b>(i, j)[1];
			//	dstImage.at<Vec3b>(i, j)[2] = srcImage.at<Vec3b>(i, j)[2];*/
			//}
		}
	}
}

/*
	功能:多通道均值滤波  动态地址实现
	参数:
	返回值:
*/
void AverFilteringPonter(Mat& srcImage, Mat& dstImage)
{
	//dstImage = srcImage.clone();
	dstImage.create(srcImage.size(), srcImage.type());
	int channels = srcImage.channels();

	for (int i = 1; i < srcImage.rows - 1; ++i)
	{
		uchar *proPtr = srcImage.ptr<uchar>(i - 1);
		uchar *curPtr = srcImage.ptr<uchar>(i);
		uchar *nextPtr = srcImage.ptr<uchar>(i + 1);

		uchar *data = dstImage.ptr<uchar>(i);
		for (int j = channels; j < (srcImage.cols-1)*channels; ++j)
		{
			data[j] = (proPtr[j - channels] + proPtr[j] + proPtr[j + channels] +
				curPtr[j - channels] + curPtr[j] + curPtr[j + channels] +
				nextPtr[j - channels] + nextPtr[j] + nextPtr[j + channels]) / 9;

			if (data[j] < 1)
			{
				data[j] = 0;
			}
		}
	}
}

/*
	常规方法均值滤波 指针 单 三
*/
void myBlur(Mat& srcimage, Mat& dstimage, Size wsize)
{
	if (wsize.height % 2 == 0 || wsize.width % 2 == 0)//判断是否为奇数
	{
		fprintf(stderr, "Please enter odd size!");
		exit(-1);
	}

	int hh = (wsize.height - 1) / 2;//半径
	int ww = (wsize.width - 1) / 2;//半径
	
	cv::Mat newSrc;
	cv::copyMakeBorder(srcimage, newSrc, hh, hh, ww, ww, cv::BORDER_REFLECT_101);//以边缘为轴,对称
	
	dstimage.create(srcimage.size(), srcimage.type());
	
	//均值滤波
	int channels = newSrc.channels();
	int i;
	for (i = 0; i < newSrc.rows-wsize.height; i++)
	{			
		uchar *data = dstimage.ptr<uchar>(i);//此处的i只能是dstimage的位置  不可以与newSrc的混淆

		int sum = 0;
		int mean = 0;
		
		for (int j = 0; j < (newSrc.cols - hh)*channels; ++j)
		{
			int count = 0;
			for(int s = i;s<i+wsize.height;s++)//分配多少个指针
				for (int x = 0; x < wsize.height; x++)
				{
					sum += newSrc.ptr(s)[j + x * channels];
					count++;
				}
			mean = sum / (wsize.height*wsize.width);
			data[j + hh*channels] = mean;
			sum = 0;
			mean = 0;
		}
	}
}

/*
	均值滤波 指针  三
*/
void myBlurPointer(Mat& srcimage, Mat& dstimage, Size wsize)
{
	if (wsize.height % 2 == 0 || wsize.width % 2 == 0)//判断是否为奇数
	{
		fprintf(stderr, "Please enter odd size!");
		exit(-1);
	}

	int hh = (wsize.height - 1) / 2;//半径
	int ww = (wsize.width - 1) / 2;//半径

	cv::Mat newSrc;
	cv::copyMakeBorder(srcimage, newSrc, hh, hh, ww, ww, cv::BORDER_REFLECT_101);//以边缘为轴,对称

	dstimage.create(srcimage.size(), srcimage.type());
	//imshow("hello", newSrc);
	//均值滤波
	int sumR = 0;
	int sumG = 0;
	int sumB = 0;

	int averageR = 0;
	int averageG = 0;
	int averageB = 0;

	int count = 0;
	for (int i = hh; i < srcimage.rows + hh; ++i)
	{
		for (int j = ww; j < srcimage.cols + ww; ++j)
		{
			for (int r = i - hh; r <= i + hh; r++)
			{
				Vec3b* data1 = newSrc.ptr<Vec3b>(r);//指针 行
				for (int k = j - hh; k <= j + hh; k++)
				{
					sumR += data1[k][0];
					sumG += data1[k][1];
					sumB += data1[k][2];
					count++;
				}
			}
			/*std::cout << count << std::endl;
			count = 0;*/
			averageR = sumR / wsize.area();
			averageG = sumG / wsize.area();
			averageB = sumB / wsize.area();

			//赋值给目标图像
			Vec3b* data = dstimage.ptr<Vec3b>(i - hh);
			data[j - ww][0] = averageR;
			data[j - ww][1] = averageG;
			data[j - ww][2] = averageB;

			 sumR = 0;
			 sumG = 0;
			 sumB = 0;

			 averageR = 0;
			 averageG = 0;
			 averageB = 0;
		}
	}

}


/*
	积分均值滤波
*/
void myBlurFlation(Mat& srcimage, Mat& dstimage, Size wsize)
{
	if (wsize.height % 2 == 0 || wsize.width % 2 == 0)//判断是否为奇数
	{
		fprintf(stderr, "Please enter odd size!");
		exit(-1);
	}

	int hh = (wsize.height - 1) / 2;//半径
	int ww = (wsize.width - 1) / 2;//半径

	cv::Mat newSrc;
	cv::copyMakeBorder(srcimage, newSrc, hh, hh, ww, ww, cv::BORDER_REFLECT_101);//以边缘为轴,对称
	dstimage = cv::Mat::zeros(srcimage.size(), srcimage.type());
	//dstimage.create(srcimage.size(), srcimage.type());
	
	Mat inte;
	//均值滤波积分
	//blurIntegral(newSrc,inte);
	testIntegral(newSrc, inte);
	//myBlurIntegral(newSrc, inte);

	//均值滤波
	double mean1 = 0;
	double mean2 = 0;
	double mean3 = 0;

	for (int i = hh + 1; i <= srcimage.rows + hh - 1; ++i)
	{
		for (int j = ww + 1; j <= srcimage.cols + ww + 1; ++j)
		{
			double top_left1 = inte.at<Vec3d>(i - hh - 1, j - ww - 1)[0];
			double top_left2 = inte.at<Vec3d>(i - hh - 1, j - ww - 1)[1];
			double top_left3 = inte.at<Vec3d>(i - hh - 1, j - ww - 1)[2];

			double top_right1 = inte.at<Vec3d>(i - hh - 1, j + ww)[0];
			double top_right2 = inte.at<Vec3d>(i - hh - 1, j + ww)[1];
			double top_right3 = inte.at<Vec3d>(i - hh - 1, j + ww)[2];

			double buttom_left1 = inte.at<Vec3d>(i + hh, j - ww - 1)[0];
			double buttom_left2 = inte.at<Vec3d>(i + hh, j - ww - 1)[1];
			double buttom_left3 = inte.at<Vec3d>(i + hh, j - ww - 1)[2];

			double buttom_right1 = inte.at<Vec3d>(i + hh, j + ww)[0];
			double buttom_right2 = inte.at<Vec3d>(i + hh, j + ww)[1];
			double buttom_right3 = inte.at<Vec3d>(i + hh, j + ww)[2];

			mean1 = (top_left1 + buttom_right1 - top_right1 - buttom_left1) / wsize.area();
			mean2 = (top_left2 + buttom_right2 - top_right2 - buttom_left2) / wsize.area();
			mean3 = (top_left3 + buttom_right3 - top_right3 - buttom_left3) / wsize.area();


			if (mean1 < 0 )
			{
				mean1 = 0;
			}
			else if (mean1 > 255)
			{
				mean1 = 255;
			}

			if (mean2 < 0)
			{
				mean2 = 0;
			}
			else if (mean2 > 255)
			{
				mean2 = 255;
			}

			if (mean3 < 0)
			{
				mean3 = 0;
			}
			else if (mean3 > 255)
			{
				mean3 = 255;
			}

			dstimage.at<Vec3b>(i - hh - 1, j - ww - 1)[0] = static_cast<int>(mean1);
			dstimage.at<Vec3b>(i - hh - 1, j - ww - 1)[1] = static_cast<int>(mean2);
			dstimage.at<Vec3b>(i - hh - 1, j - ww - 1)[2] = static_cast<int>(mean3);
			
		}
		std::cout << std::endl;
	}
}

void blurIntegral(cv::Mat &src, cv::Mat &dst)
{
	int row = src.rows;
	int column = src.cols;
	
	//创建一个目标图像标准格式
	dst = cv::Mat::zeros(row + 1, column + 1,CV_64FC3);

	double sum1 = 0;
	double sum2 = 0;
	double sum3 = 0;

	for (int i = 1; i < dst.rows; ++i)
	{//列扫描
		for (int j = 1,sum1 = 0,sum2 = 0,sum3 = 0; j < dst.cols; ++j)
		{//行累加
			//行累加,因为积分图相当于在原图上方加一行,
			//左边加一列,所以积分图的(1,1)对应原图(0,0),(i,j)对应(i-1,j-1)
			sum1 += src.at<Vec3b>(i - 1, j - 1)[0];		
			sum2 += src.at<Vec3b>(i - 1, j - 1)[1];		
			sum3 += src.at<Vec3b>(i - 1, j - 1)[2];		
			dst.at<Vec3d>(i, j)[0] = dst.at<Vec3d>(i - 1, j)[0] + sum1;
			dst.at<Vec3d>(i, j)[1] = dst.at<Vec3d>(i - 1, j)[1] + sum2;
			dst.at<Vec3d>(i, j)[2] = dst.at<Vec3d>(i - 1, j)[2] + sum3;	 
		}
	}
}

void myBlurIntegral(cv::Mat &src, cv::Mat &dst)
{
	int row = src.rows;
	int column = src.cols;

	//创建一个目标图像标准格式
	dst = cv::Mat::zeros(row + 1, column + 1, CV_64FC3);

	for (int i = 1; i < dst.rows; ++i)
	{
		for (int j = 1; j < dst.cols; ++j)
		{
			double top_left0 = dst.at<Vec3d>(i - 1, j - 1)[0];
			double top_left1 = dst.at<Vec3d>(i - 1, j - 1)[1];
			double top_left2 = dst.at<Vec3d>(i - 1, j - 1)[2];

			double top_right0 = dst.at<Vec3d>(i - 1, j)[0];
			double top_right1 = dst.at<Vec3d>(i - 1, j)[1];
			double top_right2 = dst.at<Vec3d>(i - 1, j)[2];

			double buttom_left0 = dst.at<Vec3d>(i, j - 1)[0];
			double buttom_left1 = dst.at<Vec3d>(i, j - 1)[1];
			double buttom_left2 = dst.at<Vec3d>(i, j - 1)[2];

			double buttom_right0 = src.at<Vec3b>(i - 1, j - 1)[0];
			double buttom_right1 = src.at<Vec3b>(i - 1, j - 1)[1];
			double buttom_right2 = src.at<Vec3b>(i - 1, j - 1)[2];

			dst.at<Vec3d>(i, j)[0] = buttom_left0 + top_right0 - top_left0 + buttom_right0;
			dst.at<Vec3d>(i, j)[1] = buttom_left1 + top_right1 - top_left1 + buttom_right1;
			dst.at<Vec3d>(i, j)[2] = buttom_left2 + top_right2 - top_left2 + buttom_right2;
		}
		//std::cout <<"一行结束" <<std::endl;
	}
}

/*
	指针形式积分
	未完善
*/
void test(Mat& src, Mat& dst, Size wsize)
{
	if (wsize.height % 2 == 0 || wsize.width % 2 == 0)//判断是否为奇数
	{
		fprintf(stderr, "Please enter odd size!");
		exit(-1);
	}

	int hh = (wsize.height - 1) / 2;//半径
	int ww = (wsize.width - 1) / 2;//半径
	std::cout << wsize.area()<<std::endl;
	cv::Mat newSrc;
	cv::copyMakeBorder(src, newSrc, hh, hh, ww, ww, cv::BORDER_REFLECT_101);//以边缘为轴,对称

	int row = newSrc.rows;
	int col = newSrc.cols;

	Mat inte;
	//均值滤波
	testIntegral(newSrc, inte);
	dst.create(src.size(), CV_8UC3);

	for (int i = hh + 1; i < row - hh - 1; ++i)
	{
		for (int j = ww  + 1; j < col - ww - 1; ++j)
		{
			double sum0 = (inte.ptr<Vec3d>(i + hh)[j + ww][0] - inte.ptr<Vec3d>(i - hh - 1)[j + ww][0] 
							- inte.ptr<Vec3d>(i + hh)[j - ww - 1][0] + inte.ptr<Vec3d>(i - hh - 1)[j - ww - 1][0]);

			dst.ptr<Vec3b>(i - hh-1)[j - ww-1][0] =static_cast<int>(sum0 / wsize.area());
		
			double sum1 = (inte.ptr<Vec3d>(i + hh)[j + ww][1] - inte.ptr<Vec3d>(i - hh - 1)[j + ww][1]
				- inte.ptr<Vec3d>(i + hh)[j - ww - 1][1] + inte.ptr<Vec3d>(i - hh - 1)[j - ww - 1][1]);

			dst.ptr<Vec3b>(i - hh -1)[j - ww-1][1] = static_cast<int>(sum1 / wsize.area());

			double sum2 = (inte.ptr<Vec3d>(i + hh)[j + ww][2] - inte.ptr<Vec3d>(i - hh - 1)[j + ww][2]
				- inte.ptr<Vec3d>(i + hh)[j - ww - 1][2] + inte.ptr<Vec3d>(i - hh - 1)[j - ww - 1][2]);

			dst.ptr<Vec3b>(i - hh-1)[j - ww-1][2] = static_cast<int>(sum2 / wsize.area());
		}
	}
}

void testIntegral(cv::Mat &src, cv::Mat &dst)
{
	int row = src.rows;
	int column = src.cols;
	//imshow("test3", src);
	//dst = cv::Mat::zeros(src.size(), src.type());
	//创建一个目标图像标准格式
	dst = cv::Mat::zeros(row + 1, column + 1, CV_64FC3);//创建一个黑色图像

	for (int i = 1; i < dst.rows; ++i)
	{
		for (int j = 1; j < dst.cols; ++j)
		{
			double top_left0 = dst.ptr<Vec3d>(i - 1)[j - 1][0];
			double top_left1 = dst.ptr<Vec3d>(i - 1)[j - 1][1];
			double top_left2 = dst.ptr<Vec3d>(i - 1)[j - 1][2];

			double top_right0 = dst.ptr<Vec3d>(i - 1)[j][0];
			double top_right1 = dst.ptr<Vec3d>(i - 1)[j][1];
			double top_right2 = dst.ptr<Vec3d>(i - 1)[j][2];

			double buttom_left0 = dst.ptr<Vec3d>(i)[j - 1][0];
			double buttom_left1 = dst.ptr<Vec3d>(i)[j - 1][1];
			double buttom_left2 = dst.ptr<Vec3d>(i)[j - 1][2];

			double buttom_right0 = src.ptr<Vec3b>(i - 1)[j - 1][0];
			double buttom_right1 = src.ptr<Vec3b>(i - 1)[j - 1][1];
			double buttom_right2 = src.ptr<Vec3b>(i - 1)[j - 1][2];

			dst.ptr<Vec3d>(i)[j][0] = buttom_left0 + top_right0 - top_left0 + buttom_right0;
			dst.ptr<Vec3d>(i)[j][1] = buttom_left1 + top_right1 - top_left1 + buttom_right1;
			dst.ptr<Vec3d>(i)[j][2] = buttom_left2 + top_right2 - top_left2 + buttom_right2;

		}
		
	}
	std::cout << std::endl;

}


/*
	通道分离实现积分均值滤波
*/
void testSplit(Mat& src, Mat& dst, Size size)
{
	dst = src.clone();
	std::vector<cv::Mat>channels1;
	split(src, channels1);
	std::vector<cv::Mat>channels2;
	split(dst, channels2);

	Fast_MeanFilter(channels1[0], channels2[0], size);
	Fast_MeanFilter(channels1[1], channels2[1], size);
	Fast_MeanFilter(channels1[2], channels2[2], size);

	merge(channels2, dst);
}

/*
	功能:综合均值滤波
*/
void MyBlur(Mat& src, Mat& dst, Size size)
{
	if (src.channels() == 1)
	{
		Fast_MeanFilter(src, dst,size);
	}
	else if (src.channels() == 3)
	{
		//myBlurPointer(src, dst, size);
		//myBlurFlation(src,dst,size);
		test(src, dst, size);
	}
	else
	{
		myBlur(src, dst, size);
	}
}


本人在这里写了很多的算子,其测试结果大部分都一样,时间和效果有一点不同。以下是测试的原图和均值滤波图。
在这里插入图片描述
在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值