OpenCV与EmguCV中的空间滤波

图像滤波,即在尽量保留图像细节特征的条件下对目标图像的噪声进行抑制,是图像预处理中不可缺少的操作,其处理效果的好坏将直接响到后续图像处理和分析的有效性和可靠性。(滤波就是要去除没用的信息,保留有用的信息,可能是低频,也可能是高频)

滤波一词借用于频域处理。本意是指信号有各种频率的成分,滤掉不想要的成分,即为滤掉常说的噪声,留下想要的成分,这既是滤波的过程,也是滤波的目的。

滤波分为两种:

空间滤波与频域滤波。

空间滤波是将输入图像与滤波器模板相卷积,将最终计算结果之和作为输出的像素值。

频率域滤波是将图像从空间域转换到频率域,再利用变换系数反映某些图像特征的性质进行图像滤波的方法。

这一节我们先来了解空间滤波。

空间滤波分类

空间滤波按滤波器是否线性,可分为线性空间滤波和非线性空间滤波。

按照用途来分,可分为平滑空间滤波器和锐化空间滤波器。

在OpenCV中提供了以下三种线性滤波器,方框滤波、均值滤波、高斯滤波。

非线性滤波主要提供了,中值滤波和双边滤波。

空间滤波机理

空间滤波是一种采用滤波处理的图像增强方法。其理论基础是空间卷积和空间相关。目的是改善图像质量。

空间滤波的模板被称为空间滤波器。

在图像中的任意一点(x,y),滤波器的响应g(x,y)是滤波器系数与该滤波器包围的图像像素的乘积之和。

一般来说,用大小为m * n的滤波器对大小为M * N的图像进行线性空间滤波,可由下式表示:

w是滤波器的系数,f是像素值。对于m * n的模板,我们假设m = 2a + 1,n = 2b + 1,a,b为正整数。

http://blog.csdn.net/u013162930/article/details/48244515

①方框滤波 box Filter

OpenCV中函数原型如下:

void boxFilter(InputArray src,OutputArray dst, int ddepth, Size ksize, Point anchor=Point(-1,-1), boolnormalize=true, int borderType=BORDER_DEFAULT )
  • 第一个参数,InputArray类型的src,输入图像,即源图像。
  • 第二个参数,OutputArray类型的dst,即目标图像,需要和源图片有一样的尺寸和类型。
  • 第三个参数,int类型的ddepth,输出图像的深度,-1代表使用原图深度,即src.depth()。
  • 第四个参数,Size类型的ksize,内核的大小。一般这样写Size( w,h )来表示内核的大小( 其中,w 为像素宽度, h为像素高度)。Size(3,3)就表示3x3的核大小,Size(5,5)就表示5x5的核大小,也就是滤波器模板的大小。
  • 第五个参数,Point类型的anchor,表示锚点(即被平滑的那个点),默认值为Point(-1,-1)。如果这个点坐标是负值的话,就表示取核的中心为锚点,所以默认值Point(-1,-1)表示这个锚点在核的中心。
  • 第六个参数,bool类型的normalize,默认值为true,一个标识符,表示内核是否被其区域归一化(normalized)了。
  • 第七个参数,int类型的borderType,用于推断图像外部像素的某种边界模式。有默认值BORDER_DEFAULT,我们一般不去管它。

eg。

Mat srcImage = imread("M:/图像处理实验/boxFilter/src.bmp");
boxFilter(srcImage, srcImage, -1,Size(5, 5));
imwrite("M:/图像处理实验/boxFilter/dst.bmp", srcImage);

 

EmguCV中函数原型如下:

Public Shared Sub BoxFilter(src As Emgu.CV.IInputArray, dst As Emgu.CV.IOutputArray, ddepth As Emgu.CV.CvEnum.DepthType, ksize As System.Drawing.Size, anchor As System.Drawing.Point, Optional normalize As Boolean = True, Optional borderType As Emgu.CV.CvEnum.BorderType = Reflect101)

参数含义与openCV boxFilter函数的参数含义相同

eg。

Dim img As Image(Of Bgr, Byte) = New Image(Of Bgr, Byte)("M:\图像处理实验\boxFilter\src.bmp")
CvInvoke.BoxFilter(img, img, Emgu.CV.CvEnum.DepthType.Cv8U, New System.Drawing.Size(5, 5), New System.Drawing.Point(-1, -1), True, Emgu.CV.CvEnum.BorderType.Reflect101)
img.Save("M:\图像处理实验\boxFilter\src-result.bmp")

运行结果与OpenCV中的运行结果相同。

boxFilter()函数所用的滤波器模板为:

当normalize=true的时候,方框滤波就变成了我们熟悉的均值滤波。也就是说,均值滤波是方框滤波归一化(normalized)后的特殊情况。其中,归一化就是把要处理的量都缩放到(0,1)内,以便统一处理和直观量化。

而非归一化(Unnormalized)的方框滤波用于计算每个像素邻域内的积分特性,比如密集光流算法(dense optical flow algorithms)中用到的图像倒数的协方差矩阵(covariance matrices of image derivatives)

②均值滤波 blur

OpenCV中函数原型如下:

void blur(InputArray src, OutputArraydst, Size ksize, Point anchor=Point(-1,-1), int borderType=BORDER_DEFAULT )
  • 第一个参数,InputArray类型的src,输入图像,即源图像,填Mat类的对象即可。该函数对通道是独立处理的,且可以处理任意通道数的图片,但需要注意,待处理的图片深度应该为CV_8U, CV_16U, CV_16S, CV_32F 以及 CV_64F之一。
  • 第二个参数,OutputArray类型的dst,即目标图像,需要和源图片有一样的尺寸和类型。比如可以用Mat::Clone,以源图片为模板,来初始化得到如假包换的目标图。
  • 第三个参数,Size类型(对Size类型稍后有讲解)的ksize,内核的大小。一般这样写Size( w,h )来表示内核的大小( 其中,w 为像素宽度, h为像素高度)。Size(3,3)就表示3x3的核大小,Size(5,5)就表示5x5的核大小
  • 第四个参数,Point类型的anchor,表示锚点(即被平滑的那个点),注意他有默认值Point(-1,-1)。如果这个点坐标是负值的话,就表示取核的中心为锚点,所以默认值Point(-1,-1)表示这个锚点在核的中心。
  • 第五个参数,int类型的borderType,用于推断图像外部像素的某种边界模式。有默认值BORDER_DEFAULT,我们一般不去管它。

eg。

Mat srcImage = imread("M:/图像处理实验/blur/src.bmp");
blur(srcImage, srcImage,Size(5, 5), Point(-1,-1));
imwrite("M:/图像处理实验/blur/dst.bmp", srcImage);

EmguCV中函数原型如下:

PublicSharedSubBlur ( srcAsIInputArray, dstAsIOutputArray, ksizeAsSize, anchorAsPoint, Optional borderTypeAsBorderType = BorderType.Reflect101 )

参数含义与openCV boxFilter函数的参数含义相同

eg。

Dim img As Image(Of Bgr, Byte) = New Image(Of Bgr, Byte)("M:\图像处理实验\blur\src.bmp")
CvInvoke.Blur(img, img, New System.Drawing.Size(5, 5), New System.Drawing.Point(-1, -1), Emgu.CV.CvEnum.BorderType.Reflect101)
img.Save("M:\图像处理实验\blur\src-result.bmp")

均值滤波,是最简单的一种滤波操作,输出图像的每一个像素是核窗口内输入图像对应像素的像素的平均值( 所有像素加权系数相等),它也是归一化后的方框滤波。

均值滤波是滤波器模板邻域内像素的简单平均值。可以刻把它归入低通滤波器。

http://blog.csdn.net/u013162930/article/details/48595763

下面这幅图中的是均值滤波器模板

邻域越大平滑的效果越好。但是邻域过大,平滑会使边缘信息损失的越大,从而使输出的图像变得模糊,因此需要合理的选择邻域的大小。

需要注意的是,与Matlab不同,OpenCV的滤波操作处理后的图像与输入图像的大小是相同的。为了达到这一效果,OpenCV在图像的边界之外创造了虚拟的像素,默认情况下通过对边缘的复制来实现。

模板的大小由那些即将融入背景中的物体R的尺寸来决定。

滤波后的图像中可能会有黑边。这是由于我们用0(黑色)填充原图像的边界,经滤波后,再去除填充区域的结果,某些黑的混入了滤波后的图像。对于使用较大滤波器平滑的图像,这就成了问题。

③高斯滤波 GaussianBlur

OpenCV中函数原型如下:

void GaussianBlur(InputArray src,OutputArray dst, Size ksize, double sigmaX, double sigmaY=0, intborderType=BORDER_DEFAULT )
  • 第一个参数,InputArray类型的src,输入图像,即源图像,填Mat类的对象即可。它可以是单独的任意通道数的图片,但需要注意,图片深度应该为CV_8U,CV_16U, CV_16S, CV_32F 以及 CV_64F之一。
  • 第二个参数,OutputArray类型的dst,即目标图像,需要和源图片有一样的尺寸和类型。比如可以用Mat::Clone,以源图片为模板,来初始化得到如假包换的目标图。
  • 第三个参数,Size类型的ksize高斯内核的大小。其中ksize.width和ksize.height可以不同,但他们都必须为正数和奇数。或者,它们可以是零的,它们都是由sigma计算而来。
  • 第四个参数,double类型的sigmaX,表示高斯核函数在X方向的的标准偏差。
  • 第五个参数,double类型的sigmaY,表示高斯核函数在Y方向的的标准偏差。若sigmaY为零,就将它设为sigmaX,如果sigmaX和sigmaY都是0,那么就由ksize.width和ksize.height计算出来。
  • 为了结果的正确性着想,最好是把第三个参数Size,第四个参数sigmaX和第五个参数sigmaY全部指定到。
  • 第六个参数,int类型的borderType,用于推断图像外部像素的某种边界模式。有默认值BORDER_DEFAULT,我们一般不去管它。

eg。

Mat srcImage = imread("M:/图像处理实验/GaussianBlur/src.bmp");
Mat dstImage;
GaussianBlur(srcImage, dstImage, Size(5, 5), 0, 0);
imwrite("M:/图像处理实验/GaussianBlur/dst.bmp", dstImage);

Emgu中函数原型如下:

Public Shared Sub GaussianBlur(src As Emgu.CV.IInputArray, dst As Emgu.CV.IOutputArray, ksize As System.Drawing.Size, sigmaX As Double, Optional sigmaY As Double = 0.0, Optional borderType As Emgu.CV.CvEnum.BorderType = Reflect101)

参数含义与openCV boxFilter函数的参数含义相同。

eg。

Dim img As Image(Of Bgr, Byte) = New Image(Of Bgr, Byte)("M:\图像处理实验\GaussianBlur\src.bmp")
CvInvoke.GaussianBlur(img, img, New System.Drawing.Size(5, 5), 0, 0)
img.Save("M:\图像处理实验\GaussianBlur\src-result.bmp")

高斯滤波是一种线性平滑滤波,适用于服从正太分布的噪声,广泛应用于图像处理的减噪过程。通俗的讲,高斯滤波就是对整幅图像进行加权平均的过程,每一个像素点的值,都由其本身和邻域内的其他像素值经过加权平均后得到。高斯滤波的具体操作是:用一个模板(或称卷积、掩模)扫描图像中的每一个像素,用模板确定的邻域内像素的加权平均灰度值去替代模板中心像素点的值。

在图像处理中,高斯滤波一般有两种实现方式,一是用离散化窗口滑窗卷积,另一种通过傅里叶变换。最常见的就是第一种滑窗实现,只有当离散化的窗口非常大,用滑窗计算量非常大(即使用可分离滤波器的实现)的情况下,可能会考虑基于傅里叶变化的实现方法。

OpenCV的GaussianBlur就是基于离散化窗口卷积实现的。

大家常常说高斯滤波最有用的滤波操作,虽然它用起来,效率往往不是最高的。

高斯模糊技术生成的图像,其视觉效果就像是经过一个半透明屏幕在观察图像,这与镜头焦外成像效果散景以及普通照明阴影中的效果都明显不同。高斯平滑也用于计算机视觉算法中的预先处理阶段,以增强图像在不同比例大小下的图像效果(参见尺度空间表示以及尺度空间实现)。从数学的角度来看,图像的高斯模糊过程就是图像与正态分布做卷积。由于正态分布又叫作高斯分布,所以这项技术就叫作高斯模糊。

图像与圆形方框模糊做卷积将会生成更加精确的焦外成像效果。由于高斯函数的傅立叶变换是另外一个高斯函数,所以高斯模糊对于图像来说就是一个低通滤波操作。

所谓的加权平均是指,用不同的系数去乘以像素。即一些像素的重要性(权重)比另外一些像素的重要性更大。

系数越大,在计算中可以为该像素提供更大的权重。

这种加权重的策略的目的是,在平滑处理中,试图降低模糊。

④中值滤波 MedianBlur

OpenCV中函数原型如下:

void medianBlur(InputArray src,OutputArray dst, int ksize) 
  • 第一个参数,InputArray类型的src,函数的输入参数,填1、3或者4通道的Mat类型的图像;当ksize为3或者5的时候,图像深度需为CV_8U,CV_16U,或CV_32F其中之一,而对于较大孔径尺寸的图片,它只能是CV_8U。
  • 第二个参数,OutputArray类型的dst,即目标图像,函数的输出参数,需要和源图片有一样的尺寸和类型。
  • 第三个参数,int类型的ksize,孔径的线性尺寸(aperture linear size),注意这个参数必须是大于1的奇数

eg。

Mat srcImage=imread("M:/图像处理实验/MedianBlur/src.bmp");
Mat dstImage;
medianBlur( srcImage, out, 5);
imwrite("M:/图像处理实验/MedianBlur/dst.bmp", dstImage);

EmguCV中的函数原型如下:

Public Shared Sub MedianBlur(src As Emgu.CV.IInputArray, dst As Emgu.CV.IOutputArray, ksize As Integer)

参数含义与OpenCV中相同

eg。

Dim img As Image(Of Bgr, Byte) = New Image(Of Bgr, Byte)("M:\图像处理实验\MedianBlur\src.bmp")
CvInvoke.MedianBlur(img, img, 7)
img.Save("M:\图像处理实验\MedianBlur\src-result.bmp")

中值滤波器是一种统计排序滤波器,这种滤波器的响应以滤波器包围的图像的像素的排序为基础,然后用统计排序结果决定的值来代替中心像素的值。中值滤波器就是以像素邻域内的灰度值的中值代替该像素的值。

中值滤波器的使用非常的普遍,它对于一定类型的随机噪声提供了一种优秀的去噪能力。而且比同尺寸的线性平滑滤波器的模糊程度明显要低。不足之处就是中值滤波花费的时间是均值滤波的5倍以上。

中值滤波器对于处理脉冲噪声非常有效,这种噪声称为椒盐噪声,因为这种噪声是以黑白点的形式叠加在图像上的。

中值滤波器的主要功能是使拥有不同灰度的点看起来更接近于他们的相邻点。

http://blog.csdn.net/u013162930/article/details/48595763

⑤双边滤波 bilateralFilter

OpenCV中的函数原型如下:

void bilateralFilter(InputArray src, OutputArraydst, int d, double sigmaColor, double sigmaSpace, int borderType=BORDER_DEFAULT)
  • 第一个参数,InputArray类型的src,输入图像,即源图像,需要为8位或者浮点型单通道、三通道的图像。
  • 第二个参数,OutputArray类型的dst,即目标图像,需要和源图片有一样的尺寸和类型。
  • 第三个参数,int类型的d,表示在过滤过程中每个像素邻域的直径。如果这个值我们设其为非正数,那么OpenCV会从第五个参数sigmaSpace来计算出它来。
  • 第四个参数,double类型的sigmaColor,颜色空间滤波器的sigma值。这个参数的值越大,就表明该像素邻域内有更宽广的颜色会被混合到一起,产生较大的半相等颜色区域。
  • 第五个参数,double类型的sigmaSpace坐标空间中滤波器的sigma值,坐标空间的标注方差。他的数值越大,意味着越远的像素会相互影响,从而使更大的区域足够相似的颜色获取相同的颜色。当d>0,d指定了邻域大小且与sigmaSpace无关。否则,d正比于sigmaSpace。
  • 第六个参数,int类型的borderType,用于推断图像外部像素的某种边界模式。注意它有默认值BORDER_DEFAULT。

eg。

Mat srcImage=imread("M:/图像处理实验/bilateralFilter/src.bmp");
Mat dstImage;
bilateralFilter( srcImage, dstImage, 25, 25*2, 25/2 );
imwrite("M:/图像处理实验/bilateralFilter/dst.bmp", dstImage);

EmguCV中的函数原型如下:

Public Shared Sub BilateralFilter(src As Emgu.CV.IInputArray, dst As Emgu.CV.IOutputArray, d As Integer, sigmaColor As Double, sigmaSpace As Double, Optional borderType As Emgu.CV.CvEnum.BorderType = Reflect101)

参数含义与OpenCV中相同

eg。

‘对于彩色图像,像素值的接近与否不能使用RGB空间值,双边滤波的原始文献建议使用CIE颜色空间。
Dim img As Image(Of Gray, Byte) = New Image(Of Gray, Byte)("M:\图像处理实验\bilateralFilter\src.bmp")
CvInvoke.BilateralFilter(img, img, 7, 7 * 2, 7 / 2)
img.Save("M:\图像处理实验\bilateralFilter\src-result.bmp")

%%VB.net中Emgu的双边滤波运行时卡死,暂未实现。。

双边滤波是一种可以保边去噪的滤波器。之所以可以达到此去噪效果,是因为滤波器是由两个函数构成。一个函数是由几何空间距离决定滤波器系数。另一个由像素差值决定滤波器系数。http://blog.csdn.net/abcjennifer/article/details/7616663

在边缘附近,离的较远的像素不会太多影响到边缘上的像素值,这样就保证了边缘附近像素值的保存。但是由于保存了过多的高频信息,对于彩色图像里的高频噪声,双边滤波器不能够干净的滤掉,只能够对于低频信息进行较好的滤波。

双边滤波输出像素的值依赖于邻域像素的值的加权组合

权重系数w(i,j,k,l)取决于定义域核

和值域核

的乘积

同时考虑了空间域与值域的差别,而Gaussian Filter和α均值滤波分别只考虑了空间域和值域差别。

时间: 2024-10-06 01:20:18

OpenCV与EmguCV中的空间滤波的相关文章

OpenCV与EmguCV中的漫水填充

漫水填充算法,是根据选定的种子点,用一种自定义的颜色填充种子点的联通区域,通过设置可连通像素的上下限以及连通方式来达到不同的填充效果. 漫水填充经常被用来标记或分离图像的一部分以便对其进行进一步处理或分析. 所谓漫水填充,简单来说,就是自动选中了和种子点相连的区域,接着将该区域替换成指定的颜色. 漫水填充也可以用来从输入图像获取掩码区域,掩码会加速处理过程,或者只处理掩码指定的像素点. 在OpenCV中,漫水填充是填充算法中最通用的方法.且在OpenCV 2.X中,使用C++重写过的FloodF

OpenCV与EmguCV中的图像轮廓提取

轮廓是图像中表示边界的一系列点的集合. 虽然边缘检测算法可以根据像素间的差异检查出轮廓边界的像素,但是它并没有把轮廓做为一个整体表示出来.所以下一步工作是把这些边缘检测出来的像素组装成轮廓. openCV中可以用findContours()函数来从二值图像中提取轮廓. openCV中一般用序列来存储轮廓信息.序列中的每一个元素是曲线中一个点的位置. 函数findContours()从二值图像中寻找轮廓.findContours()处理的图像可以是Canny()后得到的有边缘像素的的图像,也可以是

浅入浅出EmguCv(一)OpenCv与EmguCv

最近接触计算机视觉方面的东西,于是准备下手学习opencv,从官网下载windows的安装版,配置环境,一系列步骤走完后,准备按照惯例弄个HelloWord.也就是按照网上的教程,打开了那个图像处理领域非常有名的lena图片(据说是个裸女\(^o^)/~). 正当我摩拳擦掌准备开始opencv学习之旅的时候,习惯了GUI的我突然觉得用C++做开发弄界面很麻烦,不如用C#来的方便,于是又发现了一个封装了opencv的.net库,可以被VC++,VC#,VB.net调用,即EmguCV.网上对于Em

OpenCv,EmguCv及.net之间的互动(The Interaction of OpenCv, EmguCv AND .net)

http://www.cnblogs.com/xrwang/archive/2010/01/26/TheInteractionOfOpenCv-EmguCvANDDotNet.html 前言 在.net中使用OpenCv和EmguCv时,必须在三者支持的图像格式之间进行转换..net中用Bitmap类来承载图像,OpenCv中用IplImage指针来承载图像,EmguCv中用Image<TColor,TDepth>来承载图像.本文主要讲述如何在IplImage.Image<TColor,

利用Opencv在PictureControl中显示照片

利用Opencv在PictureControl中显示IplImage格式的照片. bool MyDlg::IfExistFile(CString strFilePath) { CFile file; if (file.Open(strFilePath,CFile::modeRead)) { file.Close(); return true; } return false; } bool MyDlg::FillBlankToPicCtrl(const int& nID) { CDC *pDC =

OpenCV 3.0中IplImage* 转cv::Mat

在OpenCV 2.0中使用: IplImage * ipl1, *ipl2; // ... const cv::Mat m = cv::Mat(ipl,false); cv::Mat m2 = ipl2; 在OpenCV 3.0中: IplImage * ipl = ...; cv::Mat m = cv::cvarrToMat(ipl);

基于Opencv的自适应中值滤波函数selfAdaptiveMedianBlur()

终于搞出来了:) #include <iostream> #include <opencv2/opencv.hpp> #include <vector> #include <algorithm> using namespace cv; using namespace std; //下面的宏,定义了在矩阵src的第m行.n列,ks*ks覆盖的矩形区域内的像素,并将像素压到矢量v中 //该覆盖区域的左上角坐标为(m,n),宽为ks,高为ks,要求src必须是单通

OpenCV 源码中分水岭算法 watershed 函数源码注解

为了研究分水岭算法,阅读了OpenCV 2.4.9 中watershed函数的源码实现部分,代码位于 opencv\sources\modules\imgproc\src\segmentation.cpp 文件中.先贴出加了注解的代码,以后补充对分水岭算法的解释. #include "precomp.hpp" /******************************************************* Watershed **********************

利用OpenCV检测图像中的长方形画布或纸张并提取图像内容

基于知乎上的一个答案.问题如下: 也就是在一张照片里,已知有个长方形的物体,但是经过了透视投影,已经不再是规则的长方形,那么如何提取这个图形里的内容呢?这是个很常见的场景,比如在博物馆里看到一幅很喜欢的画,用手机找了下来,可是回家一看歪歪斜斜,脑补原画内容又觉得不对,那么就需要算法辅助来从原图里提取原来的内容了.不妨把应用的场景分为以下: 纸张四角的坐标(图中红点)已知的情况 也就是上面的左图中4个红点是可以准确获取,比如手动标注,那么就简单了:用OpenCV的Perspective Trans