• OpenCV 之 图像平滑


    OpenCV 之 图像平滑

    1  图像平滑

      图像平滑,可用来对图像进行去噪 (noise reduction) 或 模糊化处理 (blurring),实际上图像平滑仍然属于图像空间滤波的一种 (低通滤波)

      既然是滤波,则图像中任一点 (x, y),经过平滑滤波后的输出 g(x, y) 如下:

    g(x,y)=s=aat=bbw(s,t)f(x+s,y+t)g(x,y)=∑s=−aa∑t=−bbw(s,t)f(x+s,y+t)

      以 3X3 的滤波器为例 (即 a=b=1),则矩阵 Mx 和 Mf 对应的元素乘积之和,就是 g(x, y)

      其中,Mx=⎡⎣⎢w(1,1)w(0,1)w(1,1)w(1,0)w(0,0)w(1,0)w(1,1)w(1,1)w(1,1)⎤⎦⎥Mf=⎡⎣⎢f(x1,y1)f(x,y1)f(x+1,y1)f(x1,y)f(x,y)f(x+1,y)f(x1,y+1)f(x+1,y+1)f(x+1,y+1)⎤⎦⎥Mx=[w(−1,−1)w(−1,0)w(−1,1)w(0,−1)w(0,0)w(1,1)w(1,−1)w(1,0)w(1,1)]Mf=[f(x−1,y−1)f(x−1,y)f(x−1,y+1)f(x,y−1)f(x,y)f(x+1,y+1)f(x+1,y−1)f(x+1,y)f(x+1,y+1)]

    2  OpenCV 函数

      OpenCV 中主要有四个函数涉及到图像平滑,分别是盒式滤波 (box),高斯滤波 (Gaussian),中值滤波 (median),双边滤波 (bilateral)

    2.1  盒式滤波

      输出图像的任一像素灰度值,等于其所有邻域像素灰度值的平均值

      模糊化核为,K=α⎡⎣⎢⎢⎢111111............111111⎤⎦⎥⎥⎥K=α[11...1111...11...11...11]  其中,α={1ksize.weidthksize.height1when normalize = trueotherwiseα={1ksize.weidth∗ksize.heightwhen normalize = true1otherwise

    复制代码
    void cv::boxFilter (     
        InputArray   src, // 输入图像
        OutputArray  dst, // 输出图像
        int    ddepth,      // 输出图像深度,-1 表示等于 src.depth()
        Size   ksize,       // 模糊化核 (kernel) 的大小
        Point  anchor = Point(-1,-1),       // 锚点位置,缺省值表示 anchor 位于模糊核的正中心
        bool   normalize = true,            // 是否归一化处理
        int    borderType = BORDER_DEFAULT  // 边界模式
    )
    复制代码

      取 ddepth = 1,normalize = true,则可以得到模糊化函数 (blur)

    boxFilter( src, dst, -1, ksize, anchor, true, borderType );

      模糊化函数 (blur),本质上是一个输入和输出图像深度 (ddepth) 相同,并且做归一化处理的盒式滤波器

    复制代码
    void cv::blur (    
        InputArray  src,  
        OutputArray dst,      
    Size ksize, Point anchor = Point(-1,-1), int borderType = BORDER_DEFAULT )
    复制代码

    2.2  中值滤波

      中值滤波最为简单,常用来消除椒盐噪声

      输出图像中 (x, y) 点处的像素值,等于输入图像以 (x, y) 为中心点的邻域像素 (ksize x ksize) 平均值

    void cv::medianBlur ( 
        InputArray   src,
        OutputArray  dst,
        int  ksize   // 滤波器孔径大小,一般为奇数且大于 1,比如 3, 5, 7, ...
    )     

    2.3  高斯滤波

      高斯滤波最为有用,它是根据当前像素和邻域像素之间,空间距离的不同,计算得出一个高斯核 (邻域像素的加权系数),

      然后,高斯核从左至右、从上到下遍历输入图像,与输入图像的像素值求卷积和,得到输出图像的各个像素值

      G0(x,y)=Ae(xμx)22σ2x+(yμy)22σ2yG0(x,y)=Ae−(x−μx)22σx2+−(y−μy)22σy2

      无须理会公式的复杂,只需要记住一点即可:邻域像素距离当前像素越远 (saptial space),则其相应的加权系数越小

      为了便于直观理解,可看下面这个一维高斯核,推而广之将 G(x) 曲线以 x=0 这条轴为中心线,旋转360度可想象其二维高斯核

        

    复制代码
    void cv::GaussianBlur ( 
        InputArray   src, 
        OutputArray  dst,
        Size    ksize,       // 高斯核的大小
        double  sigmaX,      // 高斯核在x方向的标准差
        double  sigmaY = 0,  // 高斯核在y方向的标准差,缺省为 0,表示 sigmaY = sigmaX
        int     borderType = BORDER_DEFAULT 
    )  
    复制代码

      注意: 高斯核的大小 Size(width, height),w 和 h 二者不必相同但必须都是奇数,若都设为 0,则从 sigma 自动计算得出

    2.4  双边滤波

      上面三种方法都是低通滤波,因此在消除噪声的同时,也常会将边缘信息模糊化。双边滤波和高斯滤波类似,但是它将邻域像素的加权系数分为两部分,

      第一部分与高斯滤波的完全相同,第二部分则考虑当前像素和邻域像素之间灰度值的差异,从而在消除噪声的基础上,也较好的保留了图像的边缘信息

    复制代码
    void cv::bilateralFilter (
        InputArray    src,
        OutputArray   dst,
        int     d,    // 像素邻域直径,若为非正值,则从 sigmaSpace 自动计算得出
        double  sigmaColor,  // 颜色空间的标注方差
        double  sigmaSpace,  // 坐标空间的标准方差
        int     borderType = BORDER_DEFAULT 
    )
    复制代码

       注意 1)  双边滤波相比以上三种滤波方法,其处理速度很慢,因此,一般建议取 d=5 用于实时图像处理,d=9 适合于非实时的图像领域

       注意 2)  sigmaColor 和 sigmaSpace 可取相同值,一般在 10 ~ 150 之间,小于 10,则没什么效果,大于 150,则效果太强烈,看起来明显“卡通化”

    3  代码示例

    3.1 OpenCV

      OpenCV 中的示例,通过逐渐增大像素邻域的大小 Size(w, h),将上述滤波过程动态化,非常形象的展示了邻域大小对滤波效果的影响

      代码摘抄

     View Code

    3.2  滤波对比

      实际中,可直接调用以上四个滤波函数,代码如下:

    复制代码
     1 #include "opencv2/imgproc/imgproc.hpp"
     2 #include "opencv2/highgui/highgui.hpp"
     3 
     4 using namespace std;
     5 using namespace cv;
     6 
     7 int main()
     8 {
     9     Mat src = imread("E:/smooth/bird.jpg");
    10     if(src.empty())    return -1;
    11 
    12     namedWindow("original", CV_WINDOW_AUTOSIZE);
    13     namedWindow("blur", CV_WINDOW_AUTOSIZE);
    14     namedWindow("GaussianBlur", CV_WINDOW_AUTOSIZE);
    15     namedWindow("medianBlur", CV_WINDOW_AUTOSIZE);
    16     namedWindow("bilateralFilter", CV_WINDOW_AUTOSIZE);
    17 
    18     imshow("original", src);
    19 
    20     Mat dst;
    21 
    22     blur(src, dst, Size(3,3));
    23     imshow("blur", dst);
    24     
    25     medianBlur(src,dst,3);
    26     imshow("medianBlur",dst);
    27     
    28     GaussianBlur(src,dst,Size(3,3),0);
    29     imshow("GaussianBlur",dst);
    30 
    31     bilateralFilter(src,dst,9,50,50);
    32     imshow("bilateralFilter",dst);
    33 
    34     waitKey(0);
    35     return 0;
    36 }
    复制代码

      四种滤波方法的效果图,如下所示:

      

    参考资料

     <Digital Image Processing_3rd> chapter 3

     <Learning OpenCV_2nd>

     <OpenCV Tutorials> imgproc module - Smoothing Images

     
     
  • 相关阅读:
    图解设计模式-Visitor模式
    图解设计模式-Decorator模式
    图解设计模式-Strategy模式
    图解设计模式-Bridge模式
    HashMap源码
    LinkedList源码
    Vector源码
    ArrayList源码
    图解设计模式-Abstract Factory模式
    图解设计模式-Builder模式
  • 原文地址:https://www.cnblogs.com/timssd/p/5472401.html
Copyright © 2020-2023  润新知