FROM:http://blog.csdn.net/nomasp/article/details/50218419
图像滤波
什么是图像滤波
图像滤波,即在尽量保留图像细节特征的条件下对目标图像的噪声进行抑制,是图像预处理中不可缺少的操作,其处理效果的好坏将直接影响到后续图像处理和分析的有效性和可靠性。(摘自网络)
图像滤波的目的
1,消除图像中混入的噪声
2,为图像识别抽取出图像特征
图像滤波的要求
1,不能损坏图像轮廓及边缘
2,图像视觉效果应当更好
滤波器的定义
滤波器,顾名思义,是对波进行过滤的器件。(摘自网络)
以上的定义是针对物理器件的,但对于图像滤波而言显然也是适用的。
大家都用过放大镜,这里就以此举一个例子:你将放大镜移动的过程中可以看到放大的物体,滤波器就是一个承载着加权系数的镜片,这里就是透过镜片可以看到经过平滑处理过的图像,透过镜片以及伴随着镜片的移动你可以逐渐所有的图像部分。
滤波器的种类
3种线性滤波:方框滤波、均值滤波、高斯滤波
2种非线性滤波:中值滤波、双边滤波
方框滤波
方框滤波所用到的核:
当normalize为true时,方框滤波也就成了均值滤波。也就是说均值滤波是方框滤波归一化后的特殊情况。
归一化就是将要处理的量缩放到一定范围,比如(0,1)。
(函数解析均在后文中统一提供)
均值滤波
如上所说,均值滤波就是normalize为true的情况,此时就是在平均值。均值滤波在去噪的同时破坏了图像的细节部分,也使得图像变得更加模糊。
高斯滤波
高斯滤波则不同,其能够很好的消除噪声。高斯滤波过程中,每个像素点都是由本身和邻域内的其他像素值经过加权平均后得到的。
从数学的角度来看,图像的高斯模糊过程就是图像与正态分布做卷积,由于正态分布也被称为高斯分布,因此这项技术被称为高斯模糊。
由于高斯函数的傅里叶变换是另外一个高斯函数,所以高斯模糊对图像来说就是一个低通滤波器。
N维空间正态分布方程和二维空间正态分布分别为:
中值滤波
中值滤波的基本思想是用像素点邻域灰度值的中值来代替该像素的灰度值,该方法在去除脉冲噪声、椒盐噪声的同时还能保留图像的细节部分。
中值滤波花费的时间比均值滤波更久,但其在噪声的消除能力上更强。
双边滤波
双边滤波是结合图像的空间邻近度和像素值相似度的一种折中处理,同时考虑空域信息和灰度相似性,达到保留边缘且去除噪声的目的。
函数原型
方框滤波
<code class="hljs glsl has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> boxFilter(InputArray src, OutputArray dst, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> ddepth, Size ksize, Point anchor = Point(-<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>,-<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>), <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">bool</span> <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">normalize</span> = <span class="hljs-literal" style="color: rgb(0, 102, 102); box-sizing: border-box;">true</span>, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> borderType = BORDER_DEFAULT)</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li></ul>
均值滤波
<code class="hljs mathematica has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">void blur(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">Input</span> src, OutputArray dst, Size ksize, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">Point</span> anchor = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">Point</span>(-<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>,-<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>), int borderType = BORDER_DEFAULT)</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li></ul>
高斯滤波
<code class="hljs cs has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> GaussianBlur(InputArray src, OutputArray dst, Size ksize, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">double</span> sigmaX, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">double</span> sigmaY = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> borderType = BORDER_DEFAULT)</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li></ul>
中值滤波
<code class="hljs cs has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> medianBlur(InputArray src, OutputArray dst, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> ksize)</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li></ul>
双边滤波
<code class="hljs cs has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> bilateralFilter(InputArray src, OutputArray dst, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> d, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">double</span> sigmaColor, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">double</span> sigmaSpace, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> borderType = BORDER_DEFAULT)</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li></ul>
具体参数解析
<code class="hljs has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">InputArray src: 输入图像(源图像),Mat类型对象,图像深度应该是CV_8U、CV_16U、CV_16S、CV_32F、CV_64F之一。 而对于中值滤波而言,如果ksize为3或者5时,图像深度必须是CV_8U、CV_16U、CV_32F之一,如果孔径较大,则只能是CV_8U。</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li></ul>
<code class="hljs has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">OutputArray dst: 输出图像(目标图像),和源图像的尺寸和类型均一样。</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li></ul>
<code class="hljs cs has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> ddepth: 输出图像的深度,-<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>表示原图像深度(即src.depth())。</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li></ul>
<code class="hljs has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">Size ksize: 内核大小,用Size(w,h)来表示,w和h分别表示宽和高。</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li></ul>
<code class="hljs mathematica has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">Point</span> anchor: 锚点,也就是被平滑的点,如果该点坐标为负值表示取核的中心,因此默认的(-<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>,-<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>)就表示锚点在核中心。</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li></ul>
<code class="hljs glsl has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">bool</span> <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">normalize</span>: 标识符,为<span class="hljs-literal" style="color: rgb(0, 102, 102); box-sizing: border-box;">true</span>时表示内核被其余区域归一化(normalized)了。</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li></ul>
<code class="hljs cs has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> borderType: 推断图像外部像素的某种边界模式。</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li></ul>
<code class="hljs cs has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">double</span> sigmaX: 表示高斯核函数在X方向的标准偏差。</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li></ul>
<code class="hljs d has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">double</span> sigmaY: 表示高斯核函数在Y方向的标准偏差。 当sigmaY为<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>时,就将其设为sigmaX;如果两者均为<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>,则由ksize.<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">with</span>和ksize.height计算出来, 因此在高斯滤波函数中,ksize的w和h均必须是正数和奇数,或<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>,两者可以不同。</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li></ul>
<code class="hljs cs has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> ksize: 孔径的线性空间,必须是大于<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>的奇数。</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li></ul>
<code class="hljs cs has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> d: 过滤过程中每个像素邻域的直径,如果其值为非正数,则该值由sigmaSpace计算出来。</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li></ul>
<code class="hljs cs has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">double</span> sigmaColor: 颜色空间滤波器的sigma值,这个参数的值越大,就表明该像素邻域内有越宽广的颜色会被混合到一起,产生较大的半相等颜色区域。</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li></ul>
<code class="hljs cs has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">double</span> sigmaSpace: 坐标空间中滤波器的sigma值,坐标空间的标注方差。它的数值越大,意味着越远的像素会相互影响,从而使更大的区域中足够相似的颜色获取相同的颜色。 当d><span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>时,d制定了邻域大小与sigmaSpace无关。否则,d正比于sigmaSpace。</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li></ul>
示例
示例代码
<code class="hljs cpp has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">#include <iostream></span> <span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">#include <opencv2\core\core.hpp></span> <span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">#include <opencv2\highgui\highgui.hpp></span> <span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">#include <opencv2\imgproc\imgproc.hpp></span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">using</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">namespace</span> <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">std</span>; <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">using</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">namespace</span> cv; Mat g_srcImage; <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 全局的源图像</span> <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 分别对应全局的方框滤波、均值滤波、高斯滤波、中值滤波、双边滤波的输出图像以及内核值/参数值</span> Mat g_dstImgBox, g_dstImgBlur, g_dstImgGaussian, g_dstImgMedian, g_dstImgBilateral; <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> g_BoxFilterVal = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">5</span>; <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> g_BlurVal = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">12</span>; <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> g_GaussianBlurVal = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">5</span>; <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> g_MedianBlurVal = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">12</span>; <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> g_BilateralFilterVal = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">12</span>; <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">static</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> on_BoxFilter(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span>, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> *); <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">static</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> on_Blur(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span>, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> *); <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">static</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> on_GaussianBlur(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span>, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> *); <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">static</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> on_MedianBlur(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span>, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> *); <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">static</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> on_BilateralFilter(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span>, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span>*); <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> main() { <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 读取图像到g_srcImage</span> g_srcImage = imread(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"D:\\OpenCV\\ms2.png"</span>); <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (!g_srcImage.data) { <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">printf</span>(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"读取的图片不存在…… \n"</span>); <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">false</span>; } <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 分别克隆原图到5中滤波所需的图像中,均为Mat类型</span> g_dstImgBox = g_srcImage.clone(); g_dstImgBlur = g_srcImage.clone(); g_dstImgGaussian = g_srcImage.clone(); g_dstImgMedian = g_srcImage.clone(); g_dstImgBilateral = g_srcImage.clone(); <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 显示原图</span> namedWindow(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"【原图】"</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>); imshow(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"【原图】"</span>, g_srcImage); <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 方框滤波</span> namedWindow(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"【方框滤波】"</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>); createTrackbar(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"内核值"</span>, <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"【方框滤波】"</span>, &g_BoxFilterVal, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">30</span>, on_BoxFilter); on_BoxFilter(g_BoxFilterVal, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>); namedWindow(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"【均值滤波】"</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>); createTrackbar(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"内核值"</span>, <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"【均值滤波】"</span>, &g_BlurVal, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">30</span>, on_Blur); on_Blur(g_BlurVal, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>); namedWindow(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"【高斯滤波】"</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>); createTrackbar(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"内核值"</span>, <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"【高斯滤波】"</span>, &g_GaussianBlurVal, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">30</span>, on_GaussianBlur); on_GaussianBlur(g_GaussianBlurVal, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>); namedWindow(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"【中值滤波】"</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>); createTrackbar(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"内核值"</span>, <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"【中值滤波】"</span>, &g_MedianBlurVal, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">30</span>, on_MedianBlur); on_MedianBlur(g_MedianBlurVal, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>); namedWindow(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"【双边滤波】"</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>); createTrackbar(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"内核值"</span>, <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"【双边滤波】"</span>, &g_BilateralFilterVal, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">30</span>, on_BilateralFilter); on_BilateralFilter(g_BilateralFilterVal, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>); <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">cout</span> << <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"按下“q”键时,程序退出……\n"</span>; <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">while</span> (<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">char</span>(waitKey(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>)) != <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'q'</span>) {} <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>; } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">static</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> on_BoxFilter(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span>, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> *) { boxFilter(g_srcImage, g_dstImgBox, -<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>, Size(g_BoxFilterVal + <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>, g_BoxFilterVal + <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>)); imshow(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"【方框滤波】"</span>, g_dstImgBox); } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">static</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> on_Blur(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span>, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> *) { blur(g_srcImage, g_dstImgBlur, Size(g_BlurVal + <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>, g_BlurVal + <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>), Point(-<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>, -<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>)); imshow(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"【均值滤波】"</span>, g_dstImgBlur); } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">static</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> on_GaussianBlur(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span>, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> *) { GaussianBlur(g_srcImage, g_dstImgGaussian, Size(g_GaussianBlurVal * <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span> + <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>, g_GaussianBlurVal * <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span> + <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>), <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>); imshow(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"【高斯滤波】"</span>, g_dstImgGaussian); } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">static</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> on_MedianBlur(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span>, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> *) { medianBlur(g_srcImage, g_dstImgMedian, g_MedianBlurVal * <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span> + <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>); imshow(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"【中值滤波】"</span>, g_dstImgMedian); } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">static</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> on_BilateralFilter(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span>, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span>*) { bilateralFilter(g_srcImage, g_dstImgBilateral, g_BilateralFilterVal, g_BilateralFilterVal * <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>, g_BilateralFilterVal / <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>); imshow(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"【双边滤波】"</span>, g_dstImgBilateral); }</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li><li style="box-sizing: border-box; padding: 0px 5px;">29</li><li style="box-sizing: border-box; padding: 0px 5px;">30</li><li style="box-sizing: border-box; padding: 0px 5px;">31</li><li style="box-sizing: border-box; padding: 0px 5px;">32</li><li style="box-sizing: border-box; padding: 0px 5px;">33</li><li style="box-sizing: border-box; padding: 0px 5px;">34</li><li style="box-sizing: border-box; padding: 0px 5px;">35</li><li style="box-sizing: border-box; padding: 0px 5px;">36</li><li style="box-sizing: border-box; padding: 0px 5px;">37</li><li style="box-sizing: border-box; padding: 0px 5px;">38</li><li style="box-sizing: border-box; padding: 0px 5px;">39</li><li style="box-sizing: border-box; padding: 0px 5px;">40</li><li style="box-sizing: border-box; padding: 0px 5px;">41</li><li style="box-sizing: border-box; padding: 0px 5px;">42</li><li style="box-sizing: border-box; padding: 0px 5px;">43</li><li style="box-sizing: border-box; padding: 0px 5px;">44</li><li style="box-sizing: border-box; padding: 0px 5px;">45</li><li style="box-sizing: border-box; padding: 0px 5px;">46</li><li style="box-sizing: border-box; padding: 0px 5px;">47</li><li style="box-sizing: border-box; padding: 0px 5px;">48</li><li style="box-sizing: border-box; padding: 0px 5px;">49</li><li style="box-sizing: border-box; padding: 0px 5px;">50</li><li style="box-sizing: border-box; padding: 0px 5px;">51</li><li style="box-sizing: border-box; padding: 0px 5px;">52</li><li style="box-sizing: border-box; padding: 0px 5px;">53</li><li style="box-sizing: border-box; padding: 0px 5px;">54</li><li style="box-sizing: border-box; padding: 0px 5px;">55</li><li style="box-sizing: border-box; padding: 0px 5px;">56</li><li style="box-sizing: border-box; padding: 0px 5px;">57</li><li style="box-sizing: border-box; padding: 0px 5px;">58</li><li style="box-sizing: border-box; padding: 0px 5px;">59</li><li style="box-sizing: border-box; padding: 0px 5px;">60</li><li style="box-sizing: border-box; padding: 0px 5px;">61</li><li style="box-sizing: border-box; padding: 0px 5px;">62</li><li style="box-sizing: border-box; padding: 0px 5px;">63</li><li style="box-sizing: border-box; padding: 0px 5px;">64</li><li style="box-sizing: border-box; padding: 0px 5px;">65</li><li style="box-sizing: border-box; padding: 0px 5px;">66</li><li style="box-sizing: border-box; padding: 0px 5px;">67</li><li style="box-sizing: border-box; padding: 0px 5px;">68</li><li style="box-sizing: border-box; padding: 0px 5px;">69</li><li style="box-sizing: border-box; padding: 0px 5px;">70</li><li style="box-sizing: border-box; padding: 0px 5px;">71</li><li style="box-sizing: border-box; padding: 0px 5px;">72</li><li style="box-sizing: border-box; padding: 0px 5px;">73</li><li style="box-sizing: border-box; padding: 0px 5px;">74</li><li style="box-sizing: border-box; padding: 0px 5px;">75</li><li style="box-sizing: border-box; padding: 0px 5px;">76</li><li style="box-sizing: border-box; padding: 0px 5px;">77</li><li style="box-sizing: border-box; padding: 0px 5px;">78</li><li style="box-sizing: border-box; padding: 0px 5px;">79</li><li style="box-sizing: border-box; padding: 0px 5px;">80</li><li style="box-sizing: border-box; padding: 0px 5px;">81</li><li style="box-sizing: border-box; padding: 0px 5px;">82</li><li style="box-sizing: border-box; padding: 0px 5px;">83</li><li style="box-sizing: border-box; padding: 0px 5px;">84</li><li style="box-sizing: border-box; padding: 0px 5px;">85</li><li style="box-sizing: border-box; padding: 0px 5px;">86</li><li style="box-sizing: border-box; padding: 0px 5px;">87</li><li style="box-sizing: border-box; padding: 0px 5px;">88</li><li style="box-sizing: border-box; padding: 0px 5px;">89</li><li style="box-sizing: border-box; padding: 0px 5px;">90</li><li style="box-sizing: border-box; padding: 0px 5px;">91</li><li style="box-sizing: border-box; padding: 0px 5px;">92</li><li style="box-sizing: border-box; padding: 0px 5px;">93</li><li style="box-sizing: border-box; padding: 0px 5px;">94</li><li style="box-sizing: border-box; padding: 0px 5px;">95</li><li style="box-sizing: border-box; padding: 0px 5px;">96</li><li style="box-sizing: border-box; padding: 0px 5px;">97</li><li style="box-sizing: border-box; padding: 0px 5px;">98</li><li style="box-sizing: border-box; padding: 0px 5px;">99</li><li style="box-sizing: border-box; padding: 0px 5px;">100</li><li style="box-sizing: border-box; padding: 0px 5px;">101</li><li style="box-sizing: border-box; padding: 0px 5px;">102</li></ul>
图像示例
原图
方框滤波
均值滤波
高斯滤波
中值滤波
双边滤波
总结
通过上面各个图片的观察:方框和均值还是比较相似的;高斯的话对于用Windows 7和Windows 10的朋友应该都比较清楚了;中值看上去就是一种涂抹的感觉;而双边的话则和原图很接近了,我是没看出来有什么区别的。