OpenCV 2.4+ C++ 平滑处理

原理 html

平滑也称模糊, 是一项简单且使用频率很高的图像处理方法。 数组

平滑处理时须要用到一个滤波器。 最经常使用的滤波器是线性滤波器,线性滤波处理的输出像素值(例如:g(i,j))是输入像素值(例如:f(i+k,j+l))的加权平均: 函数

    g(i,j) = \sum_{k,l} f(i+k, j+l) h(k,l)

h(k,l)称为核, 它仅仅是一个加权系数。 ui

 

均值平滑 spa

下面是一个使用blur函数的均值平滑: .net

复制代码
#include "opencv2/core/core.hpp" #include "opencv2/highgui/highgui.hpp" #include "opencv2/imgproc/imgproc.hpp" #include <stdio.h> using namespace cv; int main( int argc, char** argv ){ Mat image; image = imread( argv[1]); if( argc != 2 || !image.data ){ printf("没有图片\n"); return -1; } namedWindow( "平滑处理-输入" ); namedWindow( "平滑处理-输出" ); imshow( "平滑处理-输入", image ); Mat out; blur( image, out, Size(3, 3)); imshow( "平滑处理-输出", out ); waitKey( 0 ); }
复制代码

blur函数API资料: code

使用归一化块滤波器进行模糊图片操做。 htm

C++: void blur(InputArray  src, OutputArray  dst, Size  ksize, Point  anchor=Point(-1,-1), int borderType=BORDER_DEFAULT )
参数
  • src – 输入图片,可使是任意通道数,该函数对通道是独立处理的,可是深度只能是CV_8U,CV_16U, CV_16S, CV_32F or CV_64F。
  • dst – 输出图片,和输入图片相同大小和深度。
  • ksize – 模糊内核大小。
  • anchor – 锚点,默认值是(-1,-1),也就是锚点在内核的中心。
  • borderType – 用于判断图像边界的模式。

该函数对图片进行平滑处理利用了下面的内核: blog

\texttt{K} =  \frac{1}{\texttt{ksize.width*ksize.height}} \begin{bmatrix} 1 & 1 & 1 &  \cdots & 1 & 1  \\ 1 & 1 & 1 &  \cdots & 1 & 1  \\ \hdotsfor{6} \\ 1 & 1 & 1 &  \cdots & 1 & 1  \\ \end{bmatrix}

调用blur(src, dst, ksize, anchor, borderType)至关于调用boxFilter(src,dst, src.type(), anchor, true, borderType)。 图片

blur使用的是归一化块滤波器,输出像素值是核窗口内像素值的均值( 全部像素加权系数相等)。

 

高斯平滑

下面代码使用了GaussianBlur来实现平滑:

复制代码
#include "opencv2/core/core.hpp" #include "opencv2/highgui/highgui.hpp" #include "opencv2/imgproc/imgproc.hpp" #include <stdio.h> using namespace std; using namespace cv; int main( int argc, char** argv ){ Mat image; image = imread( argv[1]); if( argc != 2 || !image.data ){ printf("没有图片\n"); return -1; } namedWindow( "平滑处理-输入" ); namedWindow( "平滑处理-输出" ); imshow( "平滑处理-输入", image ); Mat out; GaussianBlur( image, out, Size( 3, 3 ), 0, 0 ); imshow( "平滑处理-输出", out ); waitKey( 0 ); }
复制代码

GaussianBlur函数API资料:

使用高斯滤波器进行模糊操做

C++: void GaussianBlur(InputArray  src, OutputArray  dst, Size  ksize, double  sigmaX, double  sigmaY=0, int  borderType=BORDER_DEFAULT)
参数
  • src – 输入图片,可使是任意通道数,该函数对通道是独立处理的,可是深度只能是CV_8U, CV_16U, CV_16S, CV_32F or CV_64F.
  • dst – 输出图片,和输入图片相同大小和深度。
  • ksize – 高斯内核大小。ksize.width和ksize.height容许不相同但他们必须是正奇数。或者等于0,由参数sigma的伺机决定。
  • sigmaX – 高斯内核在X方向的标准误差。
  • sigmaY – 高斯内核在Y方向的标准误差。若是sigmaY为0,他将和sigmaX的值相同,若是他们都为0,那么他们由ksize.width和ksize.height计算得出。
  • borderType – 用于判断图像边界的模式。

最有用的滤波器 (尽管不是最快的)。 高斯滤波是将输入数组的每个像素点与高斯内核卷积将卷积和看成输出像素值。

http://www.cnblogs.com/http://www.cnblogs.com/_images/Smoothing_Tutorial_theory_gaussian_0.jpg

参考一维高斯函数,咱们能够看见,他是个中间大两边小的函数。

因此高斯滤波器其加权数是中间大,四周小的。

其二维高斯函数为:

    G_{0}(x, y) = A  e^{ \dfrac{ -(x - \mu_{x})^{2} }{ 2\sigma^{2}_{x} } +  \dfrac{ -(y - \mu_{y})^{2} }{ 2\sigma^{2}_{y} } } 

其中 \mu 为均值 (峰值对应位置),\sigma 表明标准差 (变量x 和 变量y 各有一个均值,也各有一个标准差)。

 

中值平滑

使用medianBlur执行中值平滑:

复制代码
#include "opencv2/core/core.hpp" #include "opencv2/highgui/highgui.hpp" #include "opencv2/imgproc/imgproc.hpp" #include <stdio.h> using namespace std; using namespace cv; int main( int argc, char** argv ){ Mat image; image = imread( argv[1]); if( argc != 2 || !image.data ){ printf("没有图片\n"); return -1; } namedWindow( "平滑处理-输入" ); namedWindow( "平滑处理-输出" ); imshow( "平滑处理-输入", image ); Mat out; medianBlur( image, out, 3); imshow( "平滑处理-输出", out ); waitKey( 0 ); }
复制代码

medianBlur函数API资料:

使用中值滤波器进行模糊操做

C++: void medianBlur(InputArray  src, OutputArray  dst, int  ksize)
Parameters:
  • src – 支持一、三、4通道图片输入,当ksize为3或者5时,图片的深度只能是CV_8U,,CV_16U,或者 CV_32F,对于其余大孔径尺寸只支持深度为CV_8U。
  • dst – 输出图片,和输入图片相同大小和深度。
  • ksize – 线性直径大小,只能是一个大于1的奇数,例如:3, 5, 7 ...

中值滤波将图像的每一个像素用邻域 (以当前像素为中心的正方形区域)像素的中值代替 。 

 

双边平滑

使用bilateralFilter执行双边平滑:

复制代码
#include "opencv2/core/core.hpp" #include "opencv2/highgui/highgui.hpp" #include "opencv2/imgproc/imgproc.hpp" #include <stdio.h> using namespace std; using namespace cv; int main( int argc, char** argv ){ Mat image; image = imread( argv[1]); if( argc != 2 || !image.data ){ printf("没有图片\n"); return -1; } namedWindow( "平滑处理-输入" ); namedWindow( "平滑处理-输出" ); imshow( "平滑处理-输入", image ); Mat out; bilateralFilter ( image, out, 3, 3*2, 3/2 ); imshow( "平滑处理-输出", out ); waitKey( 0 ); }
复制代码

bilateralFilter的API资料:

对一个图片应用双边滤波器。

C++: void bilateralFilter(InputArray  src, OutputArray  dst, int  d, double  sigmaColor, double  sigmaSpace, int borderType=BORDER_DEFAULT )
Parameters:
  • src – 源必须是8位或者浮点数,1或者3通道图片。
  • dst – 输出图片,和输入图片相同大小和深度。
  • d – 在滤波过程当中使用的各像素邻域直径,若是这是一个非整数,则这个值由sigmaSpace决定。
  • sigmaColor – 颜色空间的标准方差。数值越大,意味着越远的的颜色会被混进邻域内,从而使更大的颜色段得到相同的颜色。
  • sigmaSpace – 坐标空间的标注方差。 数值越大,觉得着越远的像素会相互影响,从而使更大的区域足够类似的颜色获取相同的颜色。当d>0,d指定了邻域大小且与sigmaSpace无关。不然,d正比于sigmaSpace。

原理可参考:

http://www.dai.ed.ac.uk/CVonline/LOCAL_COPIES/MANDUCHI1/Bilateral_Filtering.html

目前咱们了解的滤波器都是为了平滑图像, 问题是有些时候这些滤波器不单单削弱了噪声, 连带着把边缘也给磨掉了。 为避免这样的情形 (至少在必定程度上 ), 咱们可使用双边滤波。 

相似于高斯滤波器,双边滤波器也给每个邻域像素分配一个加权系数。 这些加权系数包含两个部分, 第一部分加权方式与高斯滤波同样,第二部分的权重则取决于该邻域像素与当前像素的灰度差值。

 

被山寨的原文

Smoothing Images . OpenCV.org

Image Filtering API . OpenCV.org

相关文章
相关标签/搜索