本文测试环境:
win10 64位
vistual studio 2019
Emgu CV 4.6.0
环境配置准备:
1 新增控制台项目,.net framework为4.7.2
2 把win-x64目录的native目录下的文件全部拷贝到项目的运行目录Debug目录下
3 项目选择x64
4 添加项目引用Emgu.CV.dll、Emgu.CV.Platform.NetFramework.dll、System.Drawing.dll和System.Runtime.InteropServices.RuntimeInformation.dll
具体配置参考:
Emgu CV4图像处理之环境搭建1(C#)_zxy2847225301的博客-CSDN博客
下面的内容如果有描述得不对的地方,请指正
滤波和通信领域的滤波不太一样,但本质都是都是为了做平滑处理,减少图像上噪声或者失真
方框滤波
方框滤波是指用原图和和核卷积后输出的结果
这里的卷积是指在原图中找一个与核一样大小的区域,和核进行对应位置的相乘后再累加得到输出图的一个像素值。注意看,上图的核共9个格子,那么可以说这个核是3*3的,它们的值加起来等于1(0.1+0.1+0.1+0.1+0.2+0.1+0.1+0.1+0.1=1)
上图原图中红色区域部分记为A,核区域记为B,上图中输出图中的像素值92是这样计算出来的:区域A和区域B的对应位置的值相乘后再累加的结果:(65*0.1+98*0.1+123*0.1)+(65*0.1+96*0.2+115*0.1)+(63*0.1+91*0.1+107*0.1)=92
即本来像素值为65的,拉上相邻的几个像素重新计算作为新的像素值,是不是感觉可以去掉某部分异类的像素值,这样就实现了滤波的效果。
那么输出图中的下一个元素怎么计算呢?拿上图输出图中的92右边的第一个110来说,即把上图红色区域A往右挪一个格子,然后与区域B进行对应位置的值相乘后再累加的结果:
(98*0.1+123*0.1+126*0.1)+(96*0.1+115*0.2+119*0.1)+(91*0.1+107*0.1+113*0.1)= 110
好了,基本的原理说完了,下面描述一下EmguCv中方框滤波的函数原型:
第一个参数src为输出的图像
第二个参数dst为输出的图像
第三个参数ddepth为输出图像的深度,-1表明使用原图深度
第四个参数ksize为核的大小,常写成Size(w,h),w表示宽度,h表示高度。Size(3,3)就表示3x3的核大小,Size(5,5)就表示5x5的核大小
第五个参数anchor 表示锚点(即被平滑的那个点),默认值为Point(-1,-1),表示当前计算的点位于核中心的位置。若是这个点坐标是负值,就表示取核的中心为锚点。在特殊状况下能够指定不一样的点做为锚点,如前文分析的就取核中九个格中的第一个格
第六个参数:normailize表示在滤波时是否进行归一化。当normalize=1或true时,表示要进行归一化处理;计算的就是均值滤波; 当normalize=0或false时,表示不进行归一化处理,就是方框滤波
第七个参数:borderType边界样式,决定了以何种方式处理边界,通常采用默认值便可
代码例子:
pic_noise.png中的原图如下:
可以看到有很多白点噪声
代码如下:
- using Emgu.CV;
- using Emgu.CV.Structure;
- using Emgu.CV.Util;
- using System;
- using System.Collections.Generic;
- using System.Drawing;
- using System.IO;
- using System.Linq;
- using System.Text;
- using System.Threading.Tasks;
-
- namespace EmguCVDemo2
- {
- class Program
- {
- static void Main(string[] args)
- {
-
- Image
srcPic = new Image("pic_noise.png"); - ImgBoxFilter(srcPic);
- CvInvoke.WaitKey(0);
- Console.ReadLine();
- }
-
- ///
- /// 方框滤波
- ///
- ///
- private static void ImgBoxFilter(Image
srcPic ) - {
- CvInvoke.Imshow("srvPic", srcPic);
- Mat dstPic = new Mat();
- //进行方框滤波,new Size(2, 2)表示核为2*2
- CvInvoke.BoxFilter(srcPic, dstPic, Emgu.CV.CvEnum.DepthType.Cv8U, new Size(2, 2), new Point(-1, -1));
- CvInvoke.Imshow("dstPic", dstPic);
- CvInvoke.WaitKey(0);
- }
-
-
- }
- }
运行结果如下:(这是核为2*2的结果,当修改核为3*3时,就有点失真了),可以看到输出图中的白点少了,但图像相对模糊了一点
均值滤波
均值滤波的核是这样的
这个内核一看就明了,就是在求均值,即均值滤波函数封装的就是均值滤波
上图5*5的核中的系数都变成了1/25了,它们累加起来也是等于1
EmguCV中均值滤波的函数原型如下:
第一个参数src为输出的图像
第二个参数dst为输出的图像
第三个参数ksize为核的大小,常写成Size(w,h),w表示宽度,h表示高度。Size(3,3)就表示3x3的核大小,Size(5,5)就表示5x5的核大小
第四个参数anchor 表示锚点(即被平滑的那个点),默认值为Point(-1,-1),表示当前计算的点位于核中心的位置。若是这个点坐标是负值,就表示取核的中心为锚点。在特殊状况下能够指定不一样的点做为锚点,如前文分析的就取核中九个格中的第一个格
第五个参数:borderType边界样式,决定了以何种方式处理边界,通常采用默认值便可
例子代码如下:
- using Emgu.CV;
- using Emgu.CV.Structure;
- using Emgu.CV.Util;
- using System;
- using System.Collections.Generic;
- using System.Drawing;
- using System.IO;
- using System.Linq;
- using System.Text;
- using System.Threading.Tasks;
-
- namespace EmguCVDemo2
- {
- class Program
- {
- static void Main(string[] args)
- {
-
- Image
srcPic = new Image("pic_noise.png"); - BlurFilter(srcPic);
- CvInvoke.WaitKey(0);
- Console.ReadLine();
- }
-
-
-
- ///
- /// 中值滤波,其中new Size(3, 3)表示为3*3的核
- ///
- ///
- private static void BlurFilter(Image
srcPic ) - {
- CvInvoke.Imshow("srvPic", srcPic);
- Mat dstPic = new Mat();
- //进行中值滤波
- CvInvoke.Blur(srcPic, dstPic, new Size(3, 3), new Point(-1, -1));
- CvInvoke.Imshow("dstPic", dstPic);
- CvInvoke.WaitKey(0);
- }
-
- }
- }
运行结果如下: