高效中值滤波(采用copyMakeBorder处理边界像素)

修改了之前滤波中的中值滤波算法,采用copyMakeBorder处理边界像素

void MedianBlur(const Mat &image_Src, Mat &image_Dst, int width_Aperture)
{
	/////////////////////////////重新分配图像(如果需要)/////////////////////////////////////////////
	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));//置为0

	//滑动窗口
	int pixelCount=width_Aperture*width_Aperture;//窗口内像素总个数
	Mat image_Aperture(width_Aperture,width_Aperture,CV_8UC1);//滑动窗口图像

	//直方图
	Mat histogram;
	int histogramSize=256;//灰度等级
	int thresholdValue=pixelCount/2+1;//step1.设置阈值(步骤参考:图像的高效编程要点之四)

	//计算起点坐标
	int startX=width_Aperture/2;
	int startY=width_Aperture/2;

	///////////////////////////////扩充图像边界///////////////////////////////////////////
	int height_Extend=startY;
	int width_Extend=startX;
	Mat image_New;
	copyMakeBorder(image_Src,image_New,height_Extend,height_Extend,width_Extend,width_Extend,BORDER_DEFAULT);//默认采用BORDER_REFLECT
	int height_New=image_New.rows;
	int width_New=image_New.cols;
	//第一行
	//这里需要设置3个指针,一起滑动
	//1.源图像中被处理的像素
	//2.目标图像被处理的像素
	//3.源图像滑动窗口
	uchar *row_New=image_New.data+startY*width_New+startX;//新图像
	uchar *row_Dst=image_Dst.data;//目标图像
	uchar *row_Aperture_New=image_New.data;//源图像中的滑动窗口

	for (int y=startY;y<=height_New-startY-1;++y)
	{
		//列
		uchar *col_New=row_New;
		uchar *col_Dst=row_Dst;
		uchar *col_Aperture_New=row_Aperture_New;//操作整个滑动窗口

		///////////////////////////////对滑动窗口操作///////////////////////////////////////////
		//计算每行第一个滑动窗口直方图
		//提取滑动窗口图像
		uchar *row_Aperture=image_Aperture.data;//滑动窗口图像
		uchar *row_Aperture_New_2=col_Aperture_New;
		for (int k=0;k<=width_Aperture-1;++k)
		{
			//列
			uchar *col_ApertureImage=row_Aperture;
			uchar *col_Aperture_New_2=row_Aperture_New_2;

			for (int w=0;w<=width_Aperture-1;++w)
			{
				//处理每个像素
				col_ApertureImage[0]=col_Aperture_New_2[0];

				//下一个像素
				col_ApertureImage++;
				col_Aperture_New_2++;
			}

			//下一行
			row_Aperture+=width_Aperture;
			row_Aperture_New_2+=width_New;
		}

		//step 2.确定中值,并记录亮度<=中值的像素点个数
		//求直方图
		calcHist(&image_Aperture,
			1,//Mat的个数
			0,//用来计算直方图的通道索引,通道索引依次排开
			Mat(),//Mat()返回一个空值,表示不用mask,
			histogram, //直方图
			1, //直方图的维数,如果计算2个直方图,就为2
			&histogramSize, //直方图的等级数(如灰度等级),也就是每列的行数
			0//分量的变化范围
			);

		//求亮度中值和<=中值的像素点个数
		int medianValue,pixleCountLowerMedian;
		CalculateImage_MedianGray_PixelCount(histogram,pixelCount,medianValue,pixleCountLowerMedian);
		//////////////////////////////滑动窗口操作结束////////////////////////////////////////////

		//滤波
		col_Dst[0]=(uchar)medianValue;

		//滑动一个像素(三个指针在一起移动)
		col_Dst++;
		col_New++;
		col_Aperture_New++;
		for (int x=startX+1;x<=width_New-startX-1;++x)//从每行第二个滤波像素开始
		{
			//////////////////////////////////维持滑动窗口直方图////////////////////////////////////////
			//step 3.去掉左侧
			uchar *col_Left=col_Aperture_New-1;
			float *data=(float*)histogram.data;
			for (int k=0;k<=width_Aperture-1;++k)
			{
				int gray=col_Left[0];
				data[gray]-=1.0;
				if (gray<=medianValue)
				{
					pixleCountLowerMedian--;
				}
				col_Left+=width_New;
			}

			//step 4.增加右侧
			uchar *col_Right=col_Aperture_New+width_Aperture-1;
			for (int k=0;k<=width_Aperture-1;++k)
			{
				int gray=col_Right[0];
				data[gray]+=1.0;
				if (gray<=medianValue)
				{
					pixleCountLowerMedian++;
				}
				col_Right+=width_New;
			}

			//搜索新的中值
			if (pixleCountLowerMedian>thresholdValue)//step 6.
			{
				while(1)
				{
					pixleCountLowerMedian-=data[medianValue];
					medianValue--;
					if (pixleCountLowerMedian<=thresholdValue)
					{
						break;
					}
				}

			}
			else
			{
				while(pixleCountLowerMedian<thresholdValue)//step 5
				{
					medianValue++;
					pixleCountLowerMedian+=data[medianValue];

				}

			}

			//滤波
			col_Dst[0]=(uchar)medianValue;

			//滑动一个像素
			col_New++;
			col_Dst++;
			col_Aperture_New++;
		}//end of x

		//下一行
		row_New+=width_New;
		row_Dst+=width_Dst;
		row_Aperture_New+=width_New;
	}//end of y

}

原图:

时间: 2024-12-22 19:50:36

高效中值滤波(采用copyMakeBorder处理边界像素)的相关文章

高效中值滤波的方法及实现

中值滤波的原理很简单:就是用滑动窗口中灰度中值代替窗口中心像素的灰度值 高效中值滤波: 代码实现: //中值滤波 //窗口大小为width_Aperture*width_Aperture的正方形 void MedianBlur(const Mat &image_Src, Mat &image_Dst, int width_Aperture) { /////////////重新分配图像(如果需要)///////////////////// int width_Dst=image_Src.co

高效均值滤波(采用copyMakeBorder处理边界像素)

修改了之前的滤波算法,采用了copyMakeBorder扩充边界像素,给处理边界像素带来了很大的方便 <span style="font-size:14px;">void Blur(const Mat &image_Src, Mat &image_Dst, Size size_Aperture) { /////////////////////////////step 1.重新分配图像(如果需要)////////////////////////////////

中值滤波与图像锐化

本文主要包括以下内容 中值滤波及其改进算法 图像锐化, 包括梯度算子.拉普拉斯算子.高提升滤波和高斯-拉普拉斯变换 本章的典型囊例分析 对椒盐噪声的平滑效果比较 Laplacian与LoG算子的锐化效果比较 中值滤波 中值滤波本质上是一种统计排序滤波器. 对于原图像中某点(i,j), 中值滤波以该点为中 心的邻域内的所有像素的统计排序中值作为(i, j) 点的响应. 中值不同于均值, 是指排序队列中位于中间位置的元素的值,例如=采用3x3 中值滤披 器, 某点.(i,j) 的8 个邻域的一系列像

数字图像处理------中值滤波

一 中值滤波概念 中值滤波算法以某像素的领域图像区域中的像素值的排序为基础,将像素领域内灰度的中值代替该像素的值[1]: 如:以3*3的领域为例求中值滤波中像素5的值 图1 1)int pixel[9]中存储像素1,像素2...像素9的值: 2)对数组pixel[9]进行排序操作: 3)像素5的值即为数组pixel[9]的中值pixel[4]. 中值滤波对处理椒盐噪声非常有效. 二 中值滤波代码实现 项目工程:https://github.com/ranjiewwen/Everyday_Prac

中值滤波

中值滤波是一种典型的非线性滤波技术,在一定条件下可以克服线性滤波器(如均值滤波)带来的图像细节模糊. 优点:消除杂散噪声点而不会或较小程度地造成边缘模糊. 缺点:对于图像中含有较多点.线.尖角细节的,不适宜采用中值滤波. 基本思想:将模板(如方形.线形.十字形.菱形等)中的像素值从小到大排序,将中值代替模板中间的或者指定位置的像素值. 下面给出模板为3x3大小方形的中值滤波C++源代码: /**************中值滤波************** //Luma for( y = 1; y

实时高速实现改进型中值滤波算法_爱学术_免费下载

[摘要]在图像采集和处理过程中会引入噪声,必须先对图像进行预处理.本文介绍一种快速中值滤波算法,该算法在硬件平台上实现实时处理功能.综合考虑,选择现场可编程门阵列(FPGA)作为硬件平台,采用硬件描述语言Verilog实现改进型中值滤波算法.经Modelsim仿真结果表明:基于FPGA硬件平台实现改进型中值滤波算法不仅速度快,而且实时处理效果佳,提高了图像处理的效率. [作者] 杨晶  王元庆 转载至爱学术:https://www.ixueshu.com/document/29bcda14996

基于记忆性的中值滤波O(r)与O(1)复杂度的算法实现

本文参考博客:https://www.cnblogs.com/Imageshop/archive/2013/04/26/3045672.html 原生的中值滤波是基于排序算法的,这样的算法复杂度基本在O(r2)左右,当滤波半径较大时,排序算法就显得很慢.对此有多种改进算法,这里介绍经典 的Huang算法与O(1)算法,两者都是基于记忆性的算法,只是后者记性更强. 排序算法明显的一个不足之处就是无记忆性.当核向右移动一列后,只是核的最左和最右列数据发生了变化,中间不变的数据应当被存储起来,而排序算

基于Opencv的自适应中值滤波函数selfAdaptiveMedianBlur()

终于搞出来了:) #include <iostream> #include <opencv2/opencv.hpp> #include <vector> #include <algorithm> using namespace cv; using namespace std; //下面的宏,定义了在矩阵src的第m行.n列,ks*ks覆盖的矩形区域内的像素,并将像素压到矢量v中 //该覆盖区域的左上角坐标为(m,n),宽为ks,高为ks,要求src必须是单通

中值滤波讲解-Matlab

一.原理: 1:通过从序列中取出奇数个数(偶数也可)据进行排序 2:用排序后的中值,(若取数为偶数,则求中间两数的均值)来取代要处理的数据即可 二.除去高频波动分量和奇异点(即离基本分布点很远的噪点) 三.实例说明 图1-整体效果图 图2-局部效果图 四.代码说明 %中值滤波-Lab10 file='Datanog7'; x=importdata([file,'/A_x.txt']); subplot(2,1,1); plot(x); b=medfilt1(x,1000); subplot(2,