图像处理分析与计算机视觉——算法5.3 高效的中值滤波

  • 算法原理

——博客:https://blog.youkuaiyun.com/Kena_M/article/details/47093639(可参考)

 

  • 代码:(基于OpenCV框架的C++实现)

#include "opencv2/opencv.hpp"
using namespace cv;

//
// 函数名: MedianBlur
// 参数说明: src,原图
//          dst,输出图
//          kernel,窗口大小kernel*kernel
// 函数功能: 非线性平滑,消除噪声,较好地保持边缘信息
//
void MedianBlur(const Mat& src, Mat& dst, int kernel);

int main()
{
	Mat srcImg = imread("img.bmp", 0);
	Mat dstImg;
	dstImg = srcImg.clone();

	MedianBlur(srcImg, dstImg, 3);

	imshow("srcImg: ", srcImg);
	imshow("dstImg: ", dstImg);
	waitKey(0);
	return 0;
}

void MedianBlur(const Mat & src, Mat & dst, int kernel)
{
	int i, j;
	int nWidth = src.cols, nHeight = src.rows;
	int kernel_width = kernel / 2;
	const int t = (kernel*kernel + 1) / 2;
	int medianValue;//中值
	int pixelCountLowerMedian;//小于等于medianValue的像素个数
	uchar* data = src.data;

	for (i = kernel_width; i < nHeight - kernel_width; i++)
	{
		int hist[256] = { 0 };
		//统计局部直方图
		for (int m = 0; m < kernel; m++)
		{
			for (int n = 0; n < kernel; n++)
			{
				hist[data[(i + m - kernel_width)*nWidth + n]]++;
			}
		}
		//求局部的中值 和 小于等于中值的像素个数
		int sum = 0;
		for (int m = 0; m < 256; m++)
		{
			sum += hist[m];
			if (2 * sum > kernel*kernel)
			{
				medianValue = m;
				pixelCountLowerMedian = sum;
				break;
			}
		}
		//右移窗口
		for (j = kernel_width + 1; j < nWidth - kernel_width; j++)
		{
			//更新直方图 和 pixelCountLowerMedian
			for (int m = 0;m < kernel; m++)
			{
				int pixelLeft = data[(i + m - kernel_width)*nWidth + j - kernel_width - 1];
				hist[pixelLeft]--;
				if (pixelLeft <= medianValue)
					pixelCountLowerMedian--;

				int pixelRight = data[(i + m - kernel_width)*nWidth + j + kernel_width];
				hist[pixelRight]++;
				if (pixelRight <= medianValue)
					pixelCountLowerMedian++;
			}
			//更新pixelCountLowerMedian 和 medianValue
			if (pixelCountLowerMedian == t)
			{
			}
			else if (pixelCountLowerMedian > t)
			{
				do 
				{
					if (medianValue == 0)
						break;
					pixelCountLowerMedian -= hist[medianValue];
					medianValue--;					
				} while (pixelCountLowerMedian > t);
			}
			else
			{
				do 
				{
					if (medianValue == 255)
						break;
					medianValue++;
					pixelCountLowerMedian += hist[medianValue];
				} while (pixelCountLowerMedian < t);
			}
			
			dst.data[i*nWidth + j] = medianValue;
		}

	}
}

 

  • 结果显示

img.jpg(原图)

dst.jpg(处理结果)

 

  • 总结分析 

1.上述代码对图像边界的处理采取了回避方式。

2.算法在更新 pixelCountLowerMedian 和 medianValue中,medianValue处于极值时的情况,如果未加考虑,可能出现黑白条纹(原因:medianValue=-1和0)。

3.pixelCountLowerMedian表示局部邻域中小于等于medianValue的像素个数。理论上的medianValue应该为局部邻域中值,算法中采用medianValue--的方式代替邻域中值,对结果并不造成影响。两点原因:一是pixelCountLowerMedian仍表示局部邻域中小于等于中值的像素个数,二是空间相邻灰度值一般相邻。

4. 当中值为0时,局部邻域内至少有5个0(kernel = 3时),pixelCountLowerMedian的值必然=hist[0],当进入else if (pixelCountLowerMedian > t){}代码段中,如果不执行break操作,会导致pixelCountLowerMedian=0,medianValue = -1。导致算法结果错误。中值为255时,同理。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值