OpenCV2马拉松第6圈——非线性滤波

收入囊中

在这个教程中,你将学到

  • 中值滤波
  • 双边滤波
  • 自适应双边滤波
葵花宝典
中值滤波
将局部区域的像素按灰度等级进行排序,取该领域中灰度的中值作为当前像素的灰度值。     
中值滤波的步骤为:     
  1. 将滤波模板(含有若干个点的滑动窗口)在图像中漫游,并将模板中心与图中某个像素位置重合;     
  2. 读取模板中各对应像素的灰度值(或者彩色或者4通道);
  3. 将这些灰度值(彩色或者4通道,分开处理)从小到大排列; 
  4. 取这一列数据的中间数据,将其赋给对应模板中心位置的像素。如果窗口中有奇数个元素,中值取元素按灰度值大小排序后的中间元素灰度值。如果窗口中有偶数个元素,中值取元素按灰度值大小排序后,中间两个元素灰度的平均值(OpenCV不支持偶数)。


双边滤波
是结合图像的空间邻近度和像素值相似度的一种折衷处理,同时考虑空域信息和灰度相似性,达到保边去噪的目的。具有简单、非迭代、局部的特点。 双边滤波器的好处是可以做边缘保存(edge preserving),一般过去用的维纳滤波或者高斯滤波去降噪,都会较明显地模糊边缘,对于高频细节的保护效果并不明显。双边滤波器顾名思义比高斯滤波 多了一个高斯方差sigma-d,它是基于空间分布的高斯滤波函数 ,所以在边缘附近,离的较远的像素不会太多影响到边缘上的像素值,这样就保证了边缘附近像素值的保存。但是由于保存了过多的高频信息,对于彩色图像里的高频噪声,双边滤波器不能够干净的滤掉,只能够对于低频信息进行较好的滤波
双边滤波器的输出是由domain filter(相当于原先的高斯滤波)和range filter决定的


  • a图是有噪声的一个输入
  • b图是高斯滤波(domain filter)
  • c图是range filter
  • d图就是合成的双边滤波
  • e图是a用d作滤波后的效果

初识API

中值滤波

C++:  void  medianBlur (InputArray  src, OutputArray  dst, int  ksize )
 
  • src – 输入图像,单或多通道(支持1,3,4)当核大小是3或5,图像深度可以是CV_8UCV_16U, or CV_32F, 更大的时候只能是CV_8U.
  • dst – 输出图像
  • ksize – 核大小,只能是大于1的奇数


双边滤波

C++:  void  bilateralFilter (InputArray  src, OutputArray  dst, int  d, double  sigmaColor, double  sigmaSpace, int borderType=BORDER_DEFAULT  )
 
  • src – 数据类型8bit或者是浮点数,通道数为单通道或者是3通道
  • dst – 输出图像
  • d – 表示在过滤过程中每个像素邻域的直径。如果这个值我们设其为非正数,那么会根据sigmaSpace来计算
  • sigmaColor – 颜色空间滤波器的sigma值。这个参数的值越大,就表明该像素邻域内有更宽广的颜色会被混合到一起,产生较大的半相等颜色区域
  • sigmaSpace – 坐标空间的sigma。他的数值越大,意味着越远的像素会相互影响,从而使更大的区域足够相似的颜色获取相同的颜色。当d<0d正比于sigmaSpace
  • borderType 边界类型

正如前面所讲,双边滤波器可以达到保边去噪However, 但是,它太慢了。

Sigma : 为了简单,你可以让sigmaColor和sigmaSpace相同。如何它们很小(<10),这个滤波器不会有很大的效果,如果大于150就会有很强的效果(卡通效果)

Filter size: 大的d (d > 5) 会导致速度很慢, 所以在real-time应用中推荐设置d为5,对于那些需要heavy noise filtering的离线应用推荐的d值为9.

This filter does not work inplace.

荷枪实弹
首先使用中值滤波
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
using namespace cv;

Mat src,dst;
int i = 1;
static void change_dst(int, void*)
{
	if(i%2 == 0)i++;
	medianBlur ( src, dst, i );
    imshow("dstImage", dst);
}

int main( int, char** argv )
{
   	src = imread( argv[1] );
   	namedWindow("srcImage", 1);
   	namedWindow("dstImage", 1);

	createTrackbar( "median filter:", "dstImage", &i, 20, change_dst);
	change_dst(0, 0);
	
	imshow("srcImage", src);
	waitKey();
	return 0;
}





下面是来自http://blog.sina.com.cn/s/blog_8e6b3fad01016tvu.html的图片

左上是椒盐噪声,左下是高斯噪声,都用中值滤波处理,发现中值滤波对椒盐噪声特别有效,但是对高斯噪声就没效果

再使用双边滤波
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
using namespace cv;

Mat src,dst;
int i = 1;
static void change_dst(int, void*)
{
	bilateralFilter ( src, dst, i, 200, 200);
    imshow("dstImage", dst);
}

int main( int, char** argv )
{
   	src = imread( argv[1] );
   	namedWindow("srcImage", 1);
   	namedWindow("dstImage", 1);

	createTrackbar( "bilateral filter:", "dstImage", &i, 20, change_dst);
	change_dst(0, 0);
	
	imshow("srcImage", src);
	waitKey();
	return 0;
}




举一反三
自适应双边滤波器,可以获得更卡通的效果,如果你想dive into的话,可以去好好研究一下这个API各参数的效果
CVAA的3.3.1中有很多研究迭代自适应平滑的文献
C++:  void  adaptiveBilateralFilter (InputArray  src, OutputArray  dst, Size  ksize, double  sigmaSpace, double  maxSigmaColor=20.0, Point anchor=Point(-1, -1), int  borderType=BORDER_DEFAULT  )
 
  • src – The source image
  • dst – The destination image; will have the same size and the same type as src
  • ksize – The kernel size. This is the neighborhood where the local variance will be calculated, and where pixels will contribute (in a weighted manner).
  • sigmaSpace – Filter sigma in the coordinate space. Larger value of the parameter means that farther pixels will influence each other (as long as their colors are close enough; see sigmaColor). Then d>0, it specifies the neighborhood size regardless of sigmaSpace, otherwise d is proportional to sigmaSpace.
  • maxSigmaColor – Maximum allowed sigma color (will clamp the value calculated in the ksize neighborhood. Larger value of the parameter means that more dissimilar pixels will influence each other (as long as their colors are close enough; see sigmaColor). Then d>0, it specifies the neighborhood size regardless of sigmaSpace, otherwise d is proportional to sigmaSpace.
  • borderType – Pixel extrapolation method.

A main part of our strategy will be to load each raw pixel once, and reuse it to calculate all pixels in the output (filtered) image that need this pixel value. The math of the filter is that of the usual bilateral filter, except that the sigma color is calculated in the neighborhood, and clamped by the optional input value.


#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
using namespace cv;

Mat src,dst;
int i = 1;
static void change_dst(int, void*)
{
	if(i%2 == 0)i++;
	adaptiveBilateralFilter(src, dst, Size(i,i), 20.0);
    imshow("dstImage", dst);
}

int main( int, char** argv )
{
   	src = imread( argv[1] );
   	namedWindow("srcImage", 1);
   	namedWindow("dstImage", 1);

	createTrackbar( "adapative bilateral filter:", "dstImage", &i, 20, change_dst);
	change_dst(0, 0);
	
	imshow("srcImage", src);
	waitKey();
	return 0;
}


计算机视觉交流群:162501053

转载请注明:http://blog.csdn.net/abcd1992719g

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值