36_OpenCV中的平滑操作

通常,平滑图像的目的是为了减少噪声和伪影。OpenCv提供5种不同的平滑操作。

目录

1. 简单模糊cv::blur()和方框型滤波器cv::boxFilter()

2. 中值滤波器cv::medianBlur()

3. 高斯滤波器cv::GaussianBlur()

 4. 双边滤波器cv::bilateralFilter()


1. 简单模糊cv::blur()和方框型滤波器cv::boxFilter()

cv::blur()函数实现了简单模糊,目标图像中的每个值都是源图像中相应位置一个(核)中像素的平均值。函数原型如下:

void cv::blur(
	cv::InputArray src,  // input image
	cv::OutputArray dst,  // result image
	cv::Size ksize,  // kernel size
	cv::Point anchor = cv::Point(-1, -1),  // location of anchor point
	int borderType = cv::BORDER_DEFAULT  // border extrapolation to use
);

窗口尺寸由ksize声明,anchor指定计算时核与源图像的对齐方式,默认anchor为cv::Point(-1,-1),表示核相对于滤波器居中。如果源图像是一幅多通道图像,分别对每个通道进行计算。

方框型滤波器是一种矩形的并且滤波器中所有值k[i][j]全部相等的滤波器。通常所有的k[i][j]为1或者1/A,A是滤波器的面积。简单模糊是方框型滤波器的一种特殊形式,也称为归一化方框型滤波器,函数为cv::bocFilter(),函数原型如下:

void cv::boxFilter(
	cv::InputArray src,  // input image
	cv::OutputArray dst,  // result image
	int ddepth,  // output depth
	cv::Size ksize,  // kernel size
	cv::Point anchor = cv::Point(-1,-1),  // location of anchor point
	bool normalize = true,  // if true divide by box area
	int borderType = cv::BORDER_DEFAULT  // border extrapolation to use
);

cv::boxFilter()是一种一般化的形式,cv::blur()是一种特殊化的形式。区别是前者可以非归一化形式调用,并且输出图像深度可以控制。如果ddepth=-1,目标图像的深度与源图像保持一致。

如下分别是原图、简单平滑、方框型滤波的比较:

36_OpenCV中的平滑操作_第1张图片

36_OpenCV中的平滑操作_第2张图片

36_OpenCV中的平滑操作_第3张图片

2. 中值滤波器cv::medianBlur()

中值滤波器将每个像素替换为围绕这个像素的矩形邻域内的中值或“中值”像素(相对于平均像素)。

平均的简单模糊对噪声图像,特别是由较大孤立的异常值非常明暗,少量具有较大偏差的点也会影响均值滤波。中值滤波可以采用取中间点的方式消除异常值。

函数原型:

void cv::medianBlur(
	cv::InputArray src,  // input image
	cv::OutputArray dst,  // result image
	cv::Size kszie  // kernel size
);

中值滤波器是一种非线性核的实例。cv::medianBlur的参数本质上与简单模糊的基本相同:源数组src、目标数组dst和内核大小ksize。cv::medianBlur()默认核的中心点为锚点。

如下分别是原图和中值滤波后图片的比较:

36_OpenCV中的平滑操作_第4张图片

36_OpenCV中的平滑操作_第5张图片

3. 高斯滤波器cv::GaussianBlur()

高斯滤波器对输入数组进行以此规范化的高斯核滤波,然后输出目标数组。

函数原型:

void cv::GaussianBlur(
	cv::InputArray src,  // input image
	cv::OutputArray dst,  // result image
	cv::Size ksize,  // kernel size
	double sigmaX,  // gaussian half-width in x-direction
	double sigmaY = 0.0,  // Gaussian half-width in y-direction
	int borderType = cv::BORDER_DEFAULT  // border extrapolation to use
);

参数ksize指定滤波器窗口的宽度和高度;sigmaX表示高斯核在x方向上的sigma值(最大值的半宽);sigmaY表示y方向上的sigma值,如果只给定了x,同时设置y为0,那么y=x。如果两者都设为0,那么高斯参数将根据下列公式确定:

36_OpenCV中的平滑操作_第6张图片

OpenCv实现的高斯平滑为几个常用的内核提供性能上的优化,3x3、5x5以及7x7的标准sigma核(sigmaX=0.0)相对其他核性能更优。高斯模糊支持单通道/三通道的8位/32位浮点型图像。

如下分别是原图和高斯滤波后图片的比较:

36_OpenCV中的平滑操作_第7张图片

36_OpenCV中的平滑操作_第8张图片

 4. 双边滤波器cv::bilateralFilter()

双边滤波器是一种比较大的图像分析算子,也就是边缘保持平滑。

高斯模糊的过程是减缓像素在空间上的变化,因此与邻域的关系紧密,而随机噪声在像素间的变化幅度会非常的大(即噪声不是空间相关的)。基于这种前提高斯平滑很好地减弱了噪声并且保留了小信号。但是,这种方式破坏了边缘信息,最终结果是高斯模糊把边缘也模糊了。

双边滤波对每个像素及其领域内的像素进行了加权平均。其权重由两部分组成,第一部分同高斯平滑,第二部分也是高斯权重,不同的是它不是基于空间距离而是色彩强度差计算来的。

多通道图像上图像上强度差由各分量的加权累加代替。

可以把双边滤波当作是高斯平滑,只是相似程度更高的像素权值更高,边缘更明显,对比度更高。双边滤波的效果就是将源图像变成一幅水彩画。这在图像分割领域十分有用。

函数原型:

void cv::bilateralFilter(
	InputArray src,
	OutputArray dst, 
	int d, 
	double sigmaColor, 
	double sigmaSpace,
	int borderType =BORDER_DEFAULT 
);
  • 参数d表示像素领域的直径;
  • 参数sigmaColor是颜色空间滤波器的sigma值,与高斯滤波器种的参数sigma相似;
  • 参数sigmaSpace表示坐标空间中滤波器的sigma值

参数sigmaColor越大,平滑时所包括的强度越大,图像的不连续性会更显著。

参数d对算法的效率影响很大,通常视频处理时不大于5,在非实时应用方面可以为9。如果该值设置-1,函数会自动为图像计算sigmaSpace变量的值。

 实际情况中,小的sigmaSpace值比如10会带来一个轻微但也明显的效果,而大的sigmaSpace值比如150会对图像产生非常显著的影响,使图像有一种卡通的效果。

使用示例:

	// OpenCv中的平滑处理
	std::string strFilename = "rocket.jpg";
	cv::Mat image = cv::imread(strFilename);
	if (image.empty()){
		printf("ERROR:image is empty!!!\n");
		return;
	}

	cv::Mat dst;
	cv::Size ksize(3, 3);  // 窗口尺寸
	cv::Point anchor(-1, -1);  // 核与源图像的对齐方式,(-1,-1)表示核相对于滤波器居中
	int border_type = cv::BORDER_DEFAULT;
	cv::blur(image, dst, ksize, anchor, border_type);  // 简单模糊  归一化方框型滤波器,方框型滤波器的一种

	cv::Mat dst1;
	int ddepth = -1;
	bool normalize = true;
	ksize = cv::Size(3, 3);
	cv::boxFilter(image, dst1, ddepth, ksize, anchor, normalize, border_type);  // 方框型滤波器

	int nSize = 3;
	cv::Mat dst2;
	cv::medianBlur(image, dst2, nSize);  // 中值滤波

	cv::Mat dst3;
	double sigmaX, sigmaY;
	sigmaX = sigmaY = 0.0;
	cv::GaussianBlur(image, dst3, ksize, sigmaX, sigmaY, border_type);  // 高斯滤波

	cv::Mat dst4;
	int d = 9;
	double sigmaColor = 80;
	double sigmaSpace = 150;
	cv::bilateralFilter(image, dst4, d, sigmaColor, sigmaSpace, border_type);  // 双边滤波

	cv::imshow("src", image);
	cv::imshow("blur", dst);
	cv::imshow("boxFilter", dst1);
	cv::imshow("medianFilter", dst2);
	cv::imshow("GaussianFilter", dst3);
	cv::imshow("bilateralFilter", dst4);
	cv::waitKey(0);

你可能感兴趣的:(openCv,opencv,计算机视觉,人工智能)