高效均值濾波的方法與實現

均值濾波的基本原理很簡單,就是用滑動窗口內所有像素的平均值代替窗口中心像素的灰度值


高效均值濾波的原理如下:

wKiom1SOzwKyBjkQAAEOXumd4Eo206.jpg

wKioL1SOz6DhvqB9AAFUR8_YdWM428.jpg




代碼:

//高效均值濾波
void Blur(const Mat &image_Src, Mat &image_Dst, Size size_Aperture)
{
	//////////step 1.重新分配圖像(如果需要)/////////////////
	//新圖像的大小
	int width_Dst=image_Src.cols;
	int height_Dst=image_Src.rows;
	image_Dst.create(Size(width_Dst,height_Dst),CV_8UC1);//如果重新分配,之前的空間會扔掉
	image_Dst.setTo(Scalar(0));

	//滑動窗口
	int width_Aperture=size_Aperture.width;
	int height_Aperture=size_Aperture.height;
	int pixelCount=width_Aperture*height_Aperture;
	int *sum_PerCol=new int[width_Dst];//每列的灰度值


	//計算起點座標
	int startX=width_Aperture>>1;
	int startY=height_Aperture>>1;

	//第一行
	//三個關鍵的指針,這三個指針綁定在一起,一起滑動
	//1.2:需要被處理的像素
	//3:滑動窗口第一個元素,用來操作滑動窗口
	uchar *row_Src=image_Src.data+startY*width_Dst+startX;
	uchar *row_Dst=image_Dst.data+startY*width_Dst+startX;
	uchar *row_Aperture_Src=image_Src.data;
	for (int y=startY;y<=height_Dst-startY-1;++y)
	{
		//列
		uchar *col_Src=row_Src;
		uchar *col_Dst=row_Dst;
		uchar *col_Aperture_Src=row_Aperture_Src;
		
		//計算每列height_Aperture個像素的灰度值和
		//第一行,計算所有列的和
		if (y==startY)
		{
			
			for (int k=0;k<=width_Dst-1;++k)
			{
				sum_PerCol[k]=0;
				//每列第一個指針
				uchar *col_PerLine=col_Aperture_Src+k;
				for (int t=0;t<=height_Aperture-1;++t)
				{
					sum_PerCol[k]+=col_PerLine[0];
					col_PerLine+=width_Dst;//下一行
				}

			}
		}
		else//非第一行
		{
			for (int k=0;k<=width_Dst-1;++k)
			{
				//每列第一個指針
				uchar *col_=col_Aperture_Src+k;
				sum_PerCol[k]-=col_[0-width_Dst];//減上面
				sum_PerCol[k]+=col_[0+(height_Aperture-1)*width_Dst];//加下面
			}

		}
		
		//計算width_Aperture行的列總和
		int sum_Aperture=0;
		for (int x=startX;x<=width_Dst-startX-1;++x)
		{
			//每行第一個元素,求width_Aperture個列和
			if (x==startX)
			{
				for (int k=x-startX;k<=x+startX;++k)
				{
					sum_Aperture+=sum_PerCol[k];
				}
			}
			else//非第一個元素
			{
				//減去左邊
				sum_Aperture-=sum_PerCol[x-1-startX];
				
				//加上右邊
				sum_Aperture+=sum_PerCol[x+startX];
			}
			
			//求均值
			uchar meanValue=sum_Aperture/pixelCount;
			col_Dst[0]=meanValue;

			//滑動一個像素
			col_Dst++;
			col_Src++;
		}
		//下一行
		row_Dst+=width_Dst;
		row_Src+=width_Dst;
		row_Aperture_Src+=width_Dst;
	}
}


使用大小爲3行5列的窗口,運行效果圖:

wKioL1SO0NrTst0xAAIjCcxKUGI750.jpg

wKiom1SO0DyQExnjAAGaB-AqlSk441.jpg


運行這段代碼之前,需要配置一下OpenCV,算法核心和OpenCV沒有太大關聯。

注意:算法沒有處理邊界的情況,還不太清楚怎麼處理邊界,有會的朋友,希望能夠一起分享一下邊界處理的一些技巧

代碼寫的不是特別規範,大家有什麼看不懂的地方,可以提出來

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章