【OpenCV】5种图像滤波辨析:方框、均值、高斯、中值、双边

图像滤波

什么是图像滤波

图像滤波,即在尽量保留图像细节特征的条件下对目标图像的噪声进行抑制,是图像预处理中不可缺少的操作,其处理效果的好坏将直接影响到后续图像处理和分析的有效性和可靠性。(摘自网络)

图像滤波的目的

1,消除图像中混入的噪声
2,为图像识别抽取出图像特征

图像滤波的要求

1,不能损坏图像轮廓及边缘
2,图像视觉效果应当更好

滤波器的定义

滤波器,顾名思义,是对波进行过滤的器件。(摘自网络)
以上的定义是针对物理器件的,但对于图像滤波而言显然也是适用的。

大家都用过放大镜,这里就以此举一个例子:你将放大镜移动的过程中可以看到放大的物体,滤波器就是一个承载着加权系数的镜片,这里就是透过镜片可以看到经过平滑处理过的图像,透过镜片以及伴随着镜片的移动你可以逐渐所有的图像部分。

滤波器的种类

3种线性滤波:方框滤波、均值滤波、高斯滤波
2种非线性滤波:中值滤波、双边滤波

方框滤波

方框滤波所用到的核:

当normalize为true时,方框滤波也就成了均值滤波。也就是说均值滤波是方框滤波归一化后的特殊情况。

归一化就是将要处理的量缩放到一定范围,比如(0,1)。

(函数解析均在后文中统一提供)

均值滤波

如上所说,均值滤波就是normalize为true的情况,此时就是在平均值。均值滤波在去噪的同时破坏了图像的细节部分,也使得图像变得更加模糊。

高斯滤波

高斯滤波则不同,其能够很好的消除噪声。高斯滤波过程中,每个像素点都是由本身和邻域内的其他像素值经过加权平均后得到的。

从数学的角度来看,图像的高斯模糊过程就是图像与正态分布做卷积,由于正态分布也被称为高斯分布,因此这项技术被称为高斯模糊。

由于高斯函数的傅里叶变换是另外一个高斯函数,所以高斯模糊对图像来说就是一个低通滤波器。

N维空间正态分布方程和二维空间正态分布分别为:

中值滤波

中值滤波的基本思想是用像素点邻域灰度值的中值来代替该像素的灰度值,该方法在去除脉冲噪声、椒盐噪声的同时还能保留图像的细节部分。

中值滤波花费的时间比均值滤波更久,但其在噪声的消除能力上更强。

双边滤波

双边滤波是结合图像的空间邻近度和像素值相似度的一种折中处理,同时考虑空域信息和灰度相似性,达到保留边缘且去除噪声的目的。

函数原型

方框滤波

void boxFilter(InputArray src, OutputArray dst, int ddepth, Size ksize, Point anchor = Point(-1,-1),
    bool normalize = true, int borderType = BORDER_DEFAULT)

均值滤波

void blur(Input src, OutputArray dst, Size ksize, Point anchor = Point(-1,-1),
    int borderType = BORDER_DEFAULT)

高斯滤波

void GaussianBlur(InputArray src, OutputArray dst, Size ksize, double sigmaX, double sigmaY = 0,
    int borderType = BORDER_DEFAULT)

中值滤波

void medianBlur(InputArray src, OutputArray dst, int ksize)

双边滤波

void bilateralFilter(InputArray src, OutputArray dst, int d, double sigmaColor, double sigmaSpace,
    int borderType = BORDER_DEFAULT)

具体参数解析

InputArray src:
    输入图像(源图像),Mat类型对象,图像深度应该是CV_8U、CV_16U、CV_16S、CV_32F、CV_64F之一。
    而对于中值滤波而言,如果ksize为3或者5时,图像深度必须是CV_8U、CV_16U、CV_32F之一,如果孔径较大,则只能是CV_8U。
OutputArray dst:
    输出图像(目标图像),和源图像的尺寸和类型均一样。
int ddepth:
    输出图像的深度,-1表示原图像深度(即src.depth())。
Size ksize:
    内核大小,用Size(w,h)来表示,w和h分别表示宽和高。
Point anchor:
    锚点,也就是被平滑的点,如果该点坐标为负值表示取核的中心,因此默认的(-1,-1)就表示锚点在核中心。
bool normalize:
    标识符,为true时表示内核被其余区域归一化(normalized)了。
int borderType:
    推断图像外部像素的某种边界模式。
double sigmaX:
    表示高斯核函数在X方向的标准偏差。
double sigmaY:
    表示高斯核函数在Y方向的标准偏差。
    当sigmaY为0时,就将其设为sigmaX;如果两者均为0,则由ksize.with和ksize.height计算出来,
    因此在高斯滤波函数中,ksize的w和h均必须是正数和奇数,或0,两者可以不同。
int ksize:
    孔径的线性空间,必须是大于1的奇数。
int d:
    过滤过程中每个像素邻域的直径,如果其值为非正数,则该值由sigmaSpace计算出来。
double sigmaColor:
    颜色空间滤波器的sigma值,这个参数的值越大,就表明该像素邻域内有越宽广的颜色会被混合到一起,产生较大的半相等颜色区域。
double sigmaSpace:
    坐标空间中滤波器的sigma值,坐标空间的标注方差。它的数值越大,意味着越远的像素会相互影响,从而使更大的区域中足够相似的颜色获取相同的颜色。
    当d>0时,d制定了邻域大小与sigmaSpace无关。否则,d正比于sigmaSpace。

示例

示例代码

#include <iostream>
#include <opencv2\core\core.hpp>
#include <opencv2\highgui\highgui.hpp>
#include <opencv2\imgproc\imgproc.hpp>

using namespace std;
using namespace cv;

Mat g_srcImage;     // 全局的源图像
// 分别对应全局的方框滤波、均值滤波、高斯滤波、中值滤波、双边滤波的输出图像以及内核值/参数值
Mat g_dstImgBox, g_dstImgBlur, g_dstImgGaussian, g_dstImgMedian, g_dstImgBilateral;
int g_BoxFilterVal = 5;
int g_BlurVal = 12;
int g_GaussianBlurVal = 5;
int g_MedianBlurVal = 12;
int g_BilateralFilterVal = 12;

static void on_BoxFilter(int, void *);
static void on_Blur(int, void *);
static void on_GaussianBlur(int, void *);
static void on_MedianBlur(int, void *);
static void on_BilateralFilter(int, void*);

int main()
{
    // 读取图像到g_srcImage
    g_srcImage = imread("D:\\OpenCV\\ms2.png");
    if (!g_srcImage.data) {
        printf("读取的图片不存在…… \n");
        return false;
    }

    // 分别克隆原图到5中滤波所需的图像中,均为Mat类型
    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();

    // 显示原图
    namedWindow("【原图】", 1);
    imshow("【原图】", g_srcImage);

    // 方框滤波
    namedWindow("【方框滤波】", 1);
    createTrackbar("内核值", "【方框滤波】", &g_BoxFilterVal, 30, on_BoxFilter);
    on_BoxFilter(g_BoxFilterVal, 0);

    namedWindow("【均值滤波】", 1);
    createTrackbar("内核值", "【均值滤波】", &g_BlurVal, 30, on_Blur);
    on_Blur(g_BlurVal, 0);             

    namedWindow("【高斯滤波】", 1);
    createTrackbar("内核值", "【高斯滤波】", &g_GaussianBlurVal, 30, on_GaussianBlur);
    on_GaussianBlur(g_GaussianBlurVal, 0);      

    namedWindow("【中值滤波】", 1);
    createTrackbar("内核值", "【中值滤波】", &g_MedianBlurVal, 30, on_MedianBlur);
    on_MedianBlur(g_MedianBlurVal, 0);  

    namedWindow("【双边滤波】", 1);
    createTrackbar("内核值", "【双边滤波】", &g_BilateralFilterVal, 30, on_BilateralFilter);
    on_BilateralFilter(g_BilateralFilterVal, 0);      

    cout << "按下“q”键时,程序退出……\n";
    while (char(waitKey(1)) != 'q') {}   

    return 0;
}

static void on_BoxFilter(int, void *)
{
    boxFilter(g_srcImage, g_dstImgBox, -1, Size(g_BoxFilterVal + 1, g_BoxFilterVal + 1));
    imshow("【方框滤波】", g_dstImgBox);
}

static void on_Blur(int, void *)
{
    blur(g_srcImage, g_dstImgBlur, Size(g_BlurVal + 1, g_BlurVal + 1),
        Point(-1, -1));
    imshow("【均值滤波】", g_dstImgBlur);
}

static void on_GaussianBlur(int, void *)
{
    GaussianBlur(g_srcImage, g_dstImgGaussian, Size(g_GaussianBlurVal * 2 + 1,
        g_GaussianBlurVal * 2 + 1), 0, 0);
    imshow("【高斯滤波】", g_dstImgGaussian);
}

static void on_MedianBlur(int, void *)
{
    medianBlur(g_srcImage, g_dstImgMedian, g_MedianBlurVal * 2 + 1);
    imshow("【中值滤波】", g_dstImgMedian);
}

static void on_BilateralFilter(int, void*)
{
    bilateralFilter(g_srcImage, g_dstImgBilateral, g_BilateralFilterVal,
        g_BilateralFilterVal * 2, g_BilateralFilterVal / 2);
    imshow("【双边滤波】", g_dstImgBilateral);
}

图像示例

原图

方框滤波

均值滤波

高斯滤波

中值滤波

双边滤波

总结

通过上面各个图片的观察:方框和均值还是比较相似的;高斯的话对于用Windows 7和Windows 10的朋友应该都比较清楚了;中值看上去就是一种涂抹的感觉;而双边的话则和原图很接近了,我是没看出来有什么区别的。

时间: 2024-10-02 16:55:43

【OpenCV】5种图像滤波辨析:方框、均值、高斯、中值、双边的相关文章

图像处理(三)彩图的中值滤波与cuda形式

灰度图像为一通道图像,如8位的灰度图的每一个像素点的数据由一个uchar类型来储存,uchar的值代表图像的亮度,灰度图像的中值滤波是根据像素值的3×3的领域内,像素值排序后的中值像素代表该点的像素值值: 而彩色图像一般为RGB图片,像素点的颜色由红绿蓝三通道决定,数据由一个uchar3型存储,如同灰度图的中值滤波一样,彩色图像的中值滤波也是根据图像的亮度来选取相应的像素点的值. RGB图像的亮度计算: F(x,y)=(R(x,y)+G(x,y)+B(x,y))/3 F(X,Y)是处理后该点的亮

vc++-VC++MFC工程做自适应中值滤波

问题描述 VC++MFC工程做自适应中值滤波 求完整的自适应中值滤波程序,要求有源程序,可执行程序.之前在网上找的都不太好模仿,希望直接在view里做,不要各种引申函数,就在一个大括号里做完的.拜托拜托!!急啊! 解决方案 恕我直言题主,您的第二张图片中的代码完全看不清楚 解决方案二: CXXXXXDoc* pDoc = GetDocument(); int iH,iW; LPSTR lpDIB; LPSTR lpDIBBits; lpDIB = (LPSTR) ::GlobalLock((HG

[家里蹲大学数学杂志]第055期图像滤波中的方向扩散模型

$\bf 摘要$: 本文给出了王大凯等编的<图像处理中的偏微分方程方法>第 5.4.1 节的详细论述.   $\bf 关键词$: 图像滤波; 方向扩散模型; matlab 编程   1. 模型的建立 从保护图像边缘的观点出发, 我们希望扩散是沿着平行于边缘的切线方向 (即垂直于 $\n I$ 的方向) 进行. 于是得到如下 PDE: $$\bee\label{1:df} I_t=I_{\xi\xi}, \eee$$ 其中 $\xi(\perp \n I)$ 为单位矢量. 我们化简 \eqref

轨迹系列——一种基于中值滤波的轨迹纠偏方法和几点思考

文章版权由作者李晓晖和博客园共有,若转载请于明显处标明出处:http://www.cnblogs.com/naaoveGIS/ 1.背景 在无路网的情况下,如何进行轨迹纠偏也是一个很多人在研究的内容,各种方案均有很多,有基于不同滤波算法的,也有基于机器学习的,等等.这里,我探讨一种实现相对简单的基于中值滤波来进行轨迹纠偏的方法. 2.中值滤波简介 中值滤波是基于排序统计理论的一种能有效抑制噪声的非线性信号处理技术,中值滤波的基本原理是把数字图像或数字序列中一点的值用该点的一个邻域中各点值的中值代

【OpenCV】访问图像中每个像素的值 (I)

最近要做的东西要对每个像素值进行处理,所以上网搜... 居然发现搜出来的好文章都是一个人写的,而且还是一个妹子..于是收藏之...按时间顺序发! 转载请注明出处:http://blog.csdn.net/xiaowei_cqu/article/details/7557063 !!此篇是基于IplImage* (C接口或者说2.1之前版本的接口,新的Mat的访问方式请参考博文: <访问Mat图像中每个像素的值>) IplImage是OpenCV中CxCore部分基础的数据结构,用来表示图像,其中

OpenCV入门:图像边缘提取

本文将介绍如何利用OpenCV进行边缘提取,源代码如下: // // main.cpp // Edge_Detection // // Created by 黄露 on 16/3/21. // Copyright 2016年 huanglu_thu13. All rights reserved. // #include "cv.h" #include "highgui.h" int main(int argc, const char * argv[]) { //创建

无法解析的外部符号-opencv简单的图像程序,总是出现下面的错误,解决不了!

问题描述 opencv简单的图像程序,总是出现下面的错误,解决不了! opencv简单的图像程序,总是出现下面的错误,解决不了啊!vs2013,vs2010都一样!!!谢谢各位帮帮我!! 我被折磨好几天了!!都重装几次了!!快哭了!!网上也没找到准确的解决方法!!! 谢谢大神们帮助!!没有C币... 解决方案 你的opencv环境配置过没?建议按教程配置下 解决方案二: 需要添加lib库文件http://blog.csdn.net/zyxlinux888/article/details/8048

opencv怎样实现图像投影

问题描述 opencv怎样实现图像投影 就是知道x,y转化后的坐标x'y'要怎么将图像上的点进行转换,是要用矩阵吗,这方面的知识欠缺,求问各位大神! 解决方案 http://blog.csdn.net/superdont/article/details/24959481 解决方案二: http://blog.sina.com.cn/s/blog_6b556c2f0102v2q3.html 解决方案三: OpenCV实现图像在水平方向上投影[OpenCV]图像的投影校正opencv实现图像旋转 解

Android高手进阶教程(二十二)之Android中几种图像特效处理的集锦汇总!!_Android

大家好,这一节给大家分享的是Android中几种图像特效处理的小技巧,比如圆角,倒影,还有就是图片缩放,Drawable转化为Bitmap,Bitmap转化为Drawable等等. 废话少说了,直接讲解今天的实例,本例主要是先获取壁纸(getWallpaper()),然后对当前壁纸的一些特效处理.大家按步骤一步一步来: 第一步:新建一个Android工程命名为ImageDemo,工程结构如下: 第二步:新建一个.Java文件,命名为ImageUtil.java,在里面定义一些图片处理方法,代码如