OpenCv中值滤波

问题1:什么是中值滤波?

使用像素点邻域附近的像素的中值代替该点的像素值。通俗点来说,在这个像素的左边找五个像素点,右边找五个像素点,将这些像素进行排序,排序过后产生一个中值,啊哈哈,就是中间大小的值,来代替该像素的值。

问题2:中值滤波有什么利弊?

中值滤波可以有效的去除斑点和椒盐噪声。但是效率低,其运算时间 为均值滤波的五倍以上。

问题3:相关API的了解

void medianBlur( InputArray src, OutputArray dst, int ksize );

参数 InputArray src: 输入得图像  通道可以为1 or 3 or 4通道的图像。

参数 OutputArray dst: 经过中值滤波的输出图像。

参数 int ksize: 模板尺寸  此参数必须为大于1的奇数,参数为 3 or 5时图像深度只能为CV_8U、CV_16U、CV_32F中的一个,如而对于较大孔径尺寸的图片,图像深度只能是CV_8U。 

问题4:上面提到了 CV_8U、CV_16U这些内容,他们到底是啥呢?

在opencv中Mat这个东西存在各种对象,其中Mat.type()就是其中一个 那么这个东西有什么用呢 ?他是用来测试这个图像的类型参数的,举个例子来说 :

image = imread("Test.jpg",IMREAD_UNCHANGED);
        cout << image.type() << endl;

此时控制台输出16  这是啥意思呢  结合下面的一个图片理解即可 ,Mat.type()函数可以返回该Mat的类型。类型表示了矩阵中元素的类型以及矩阵的通道个数,它是一系列的预定义的常量,其命名规则为CV_(位数)+(数据类型)+(通道数)

那么16就带代表这个图像是一个八位无符号字符型数据  三通道。

中值滤波代码实现: 起到了滤波的效果 但是还不如OpenCv中自带的滤波器效果好。也没找出来原因 嘿嘿

#include<opencv.hpp>
#include<iostream>
using namespace cv;
using namespace std;
void salt(Mat &image, Mat & result, int k)
{
	image.copyTo(result);
	for (; k > 0; k--)
	{
		int i = rand() % result.rows;
		int j = rand() % result.cols;
		if (result.channels() == 1)
		{
			result.at<uchar>(i, j) = 255;
		}
		if (result.channels() == 3)
		{
			result.at<Vec3b>(i, j)[0] = 255;
			result.at<Vec3b>(i, j)[1] = 255;
			result.at<Vec3b>(i, j)[2] = 255;
		}
	}
}
uchar sort(uchar n1, uchar n2, uchar n3, uchar n4,uchar n5, uchar n6, uchar n7, uchar n8, uchar n9)
{
	uchar *ptr = new uchar [9];
	uchar temp;
	*ptr = n1;
	*(ptr + 1) = n2;
	*(ptr + 2) = n3;
	*(ptr + 3) = n4;
	*(ptr + 4) = n5;
	*(ptr + 5) = n6;
	*(ptr + 6) = n7;
	*(ptr + 7) = n8;
	*(ptr + 8) = n9;

	for(int i = 0; i < 9; i++)
	{
		for (int j = 0; j < 9; j++)
		{
			if (ptr[i] > ptr[j])
			{
				temp = ptr[i];
				ptr[i] = ptr[j];
				ptr[j] = temp;
			}
		}
	}
	
	temp = ptr[4];
	delete[] ptr;
	return temp;
}
void middleFilter(Mat& image, Mat & result)
{
	image.copyTo(result);
	for (int i = 0; i < result.rows; i++)
	{
		for (int j = 0; j < result.cols; j++)
		{
			if ((i > 0) && (i < result.rows - 1) && (j > 0) && (j < result.cols-1))
			{
				
				result.at<Vec3b>(i, j)[0] = sort(result.at<Vec3b>(i - 1, j - 1)[0],result.at<Vec3b>(i - 1, j)[0] ,result.at<Vec3b>(i - 1, j + 1)[0]
					, result.at<Vec3b>(i, j - 1)[0] , result.at<Vec3b>(i, j)[0] , result.at<Vec3b>(i, j + 1)[0]
					,result.at<Vec3b>(i + 1, j - 1)[0] , result.at<Vec3b>(i + 1, j)[0] ,result.at<Vec3b>(i + 1, j + 1)[0]);

				result.at<Vec3b>(i, j)[1] = sort(result.at<Vec3b>(i - 1, j - 1)[1], result.at<Vec3b>(i - 1, j)[1], result.at<Vec3b>(i - 1, j + 1)[1]
					, result.at<Vec3b>(i, j - 1)[1], result.at<Vec3b>(i, j)[1], result.at<Vec3b>(i, j + 1)[1]
					, result.at<Vec3b>(i + 1, j - 1)[1], result.at<Vec3b>(i + 1, j)[1], result.at<Vec3b>(i + 1, j + 1)[1]);

				result.at<Vec3b>(i, j)[2] = sort(result.at<Vec3b>(i - 1, j - 1)[2], result.at<Vec3b>(i - 1, j)[2], result.at<Vec3b>(i - 1, j + 1)[2]
					, result.at<Vec3b>(i, j - 1)[2], result.at<Vec3b>(i, j)[2], result.at<Vec3b>(i, j + 1)[2]
					, result.at<Vec3b>(i + 1, j - 1)[2], result.at<Vec3b>(i + 1, j)[2], result.at<Vec3b>(i + 1, j + 1)[2]);
			}
		}
	}
}
int main()
{
	Mat image,result1, result2,result3;
	cout << int(sort(1, 4, 8, 0, 2, 3, 5, 6, 7)) << endl;
	image = imread("Test.jpg",IMREAD_UNCHANGED);
	salt(image, result1, 3000);
	middleFilter(result1, result2);
	medianBlur(result1,result3,3);
	imshow("椒盐噪声", result1);
	imshow("中值滤波", result2);
	imshow("medianBlur", result3);
	waitKey(0);
	return 0;
}

 

 

 

 

 

 

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值