• 【OpenCV-Python】教程:3-4 平滑去噪,高斯平滑,均值滤波,中值滤波


    OpenCV Python 平滑去噪

    【目标】

    • 利用不同的低通滤波器对图像进行平滑去噪(平均、高斯、中值、双边)
    • 使用自己定制的滤波器

    • 5x5 平均滤波器

    K = 1 25 [ 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 ] K= \frac{1}{25}

    [1111111111111111111111111]" role="presentation">[1111111111111111111111111]
    K=251 1111111111111111111111111

    • 3x3 平均滤波器

    K = 1 9 [ 1 1 1 1 1 1 1 1 1 ] K= \frac{1}{9}

    [111111111]" role="presentation">[111111111]
    K=91 111111111

    【代码】

    • 自定义平滑滤波器

    在这里插入图片描述

    和一维信号一样,图像也可以通过低通滤波器和高通滤波器进行滤波;低通滤波器可以模糊图像和去除噪声,高通滤波器可以用于找图像边缘。

    import numpy as np
    import cv2
    
    img = cv2.imread('opencv-logo-white.png')
    kernel = np.ones((5, 5), np.float32)/25
    dst = cv2.filter2D(img, -1, kernel)
    
    cv2.imshow("src", img)
    cv2.imshow("filter2D", dst)
    cv2.waitKey(0)
    cv2.destroyAllWindows()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 模糊

    在这里插入图片描述

    以一个像素为中心,取周边的像素平均值作为该像素的像素值
    如果不想用归一化的滤波器,那就用 cv2.boxFilter, 并且传入 normalize=False

    import cv2
    import numpy as np
    
    img = cv2.imread('opencv-logo-white.png')
    blur = cv2.blur(img,(5,5))
    
    cv2.imshow("src", img)
    cv2.imshow("blur", blur)
    cv2.waitKey(0)
    cv2.destroyAllWindows()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 高斯模糊

    在这里插入图片描述

    import cv2
    import numpy as np
    
    img = cv2.imread('opencv-logo-white.png')
    blur = cv2.GaussianBlur(img, (5, 5), 0)
    
    cv2.imshow("src", img)
    cv2.imshow("GaussianBlur", blur)
    cv2.waitKey(0)
    cv2.destroyAllWindows()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 中值滤波

    在这里插入图片描述

    中值滤波和其他滤波器不一样,中值滤波取的像素值为图像内部的像素值,其他滤波是通过计算得到的。中值滤波器的核宽为正奇数。非常适合处理椒盐噪声。

    import numpy as np
    import cv2
    
    def addPepperSalt(src: cv2.Mat, snr: float = 0.99) -> cv2.Mat:
        """
        addPepperSalt 给彩色图像添加黑白椒盐噪声
    
        _extended_summary_
    
        Args:
            src (cv2.Mat): 输入图像
            snr (float): 信噪比
        """
        if src is None:
            return None
    
        dst = src.copy()
    
        h, w, _ = src.shape
        imgsz = h * w
        pepperSaltNum = int(imgsz * (1.0 - snr))
    
        for i in range(pepperSaltNum):
            randx = np.random.randint(1, w-1)
            randy = np.random.randint(1, h-1)
    
            if np.random.random() <= 0.5:
                dst[randy, randx] = 0
            else:
                dst[randy, randx] = 255
        return dst
    
    
    img = cv2.imread('sheets.png')
    cv2.imshow("src", img)
    
    pepperSaltIm = addPepperSalt(img, 0.99)
    cv2.imshow("peppersalt", pepperSaltIm)
    
    median = cv2.medianBlur(pepperSaltIm, 5)
    blur = cv2.bilateralFilter(pepperSaltIm, 15, 180, 180)
    
    cv2.imshow("median", median)
    cv2.imshow("blur", blur)
    
    cv2.waitKey(0)
    cv2.destroyAllWindows()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 双边滤波

    在这里插入图片描述

    在这里插入图片描述

    可以非常有效的去除噪声的同时保留边缘信息,但是非常耗时。
    NOTE: 双边滤波对椒盐噪声效果非常不友好,具体原理请看 参考2

    import cv2
    import numpy as np
    
    img = cv2.imread('bilateral.png')
    blur = cv2.bilateralFilter(img,9,75,75)
    
    cv2.imshow("src", img)
    cv2.imshow("bilateralFilter", blur)
    cv2.waitKey(0)
    cv2.destroyAllWindows()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    在这里插入图片描述

    【接口】

    • cv2.filter2D
    void cv::filter2D	(	InputArray 	src,
    OutputArray 	dst,
    int 	ddepth,
    InputArray 	kernel,
    Point 	anchor = Point(-1,-1),
    double 	delta = 0,
    int 	borderType = BORDER_DEFAULT 
    );
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    cv2.filter2D(	src, ddepth, kernel[, dst[, anchor[, delta[, borderType]]]]	) ->	dst
    
    • 1

    通过卷积核对图像进行卷积

    • src: 输入图像
    • dst: 输出图像
    • ddepth: 输出图像的深度
    • kernel: 卷积核
    • anchor: 默认为(-1, -1) 是在卷积核的中心
    • delta: 在存储前加到滤波后的像素值上
    • borderType: 填充类型,不支持 BORDER_WRAP

    ddepth:

    borderType:

    在这里插入图片描述

    • cv2.blur
    void cv::blur	(	InputArray 	src,
    OutputArray 	dst,
    Size 	ksize,
    Point 	anchor = Point(-1,-1),
    int 	borderType = BORDER_DEFAULT 
    );
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    cv2.blur(	src, ksize[, dst[, anchor[, borderType]]]	) ->	dst
    
    • 1

    利用 boxFilter 对图像进行模糊处理

    • src: 输入图像
    • dst: 输出图像
    • ksize: 模糊核的大小
    • anchor: 默认为(-1, -1) 是在卷积核的中心
    • borderType: 填充类型,不支持 BORDER_WRAP
    • cv2.boxFilter
    void cv::boxFilter	(	InputArray 	src,
    OutputArray 	dst,
    int 	ddepth,
    Size 	ksize,
    Point 	anchor = Point(-1,-1),
    bool 	normalize = true,
    int 	borderType = BORDER_DEFAULT 
    );
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    cv2.boxFilter(	src, ddepth, ksize[, dst[, anchor[, normalize[, borderType]]]]	) ->	dst
    
    • 1
    • src: 输入图像
    • dst: 输出图像
    • ddepth: 输出图像的深度
    • ksize: 模糊核的大小
    • anchor: 默认为(-1, -1) 是在卷积核的中心
    • normalize: 归一化标志
    • borderType: 填充类型,不支持 BORDER_WRAP
    • cv2.GaussianBlur
    void cv::GaussianBlur	(	InputArray 	src,
    OutputArray 	dst,
    Size 	ksize,
    double 	sigmaX,
    double 	sigmaY = 0,
    int 	borderType = BORDER_DEFAULT 
    );
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    cv2.GaussianBlur(	src, ksize, sigmaX[, dst[, sigmaY[, borderType]]]	) ->	dst
    
    • 1

    高斯模糊

    • src: 输入图像
    • dst: 输出图像
    • ksize: 模糊核的大小
    • sigmaX: 高斯核X方向的方差
    • sigmaY: 高斯核Y方向的方差,如果设置为0,则被设置为 sigmaX, 如果都设置为0,则通过窗口计算。最好是都设置。
    • borderType: 填充类型,不支持 BORDER_WRAP
    • cv2.bilateralFilter
    void cv::bilateralFilter	(	InputArray 	src,
    OutputArray 	dst,
    int 	d,
    double 	sigmaColor,
    double 	sigmaSpace,
    int 	borderType = BORDER_DEFAULT 
    );
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    cv2.bilateralFilter(	src, d, sigmaColor, sigmaSpace[, dst[, borderType]]	) ->	dst
    
    • 1

    对图像应用双边滤波

    • src: 输入图像
    • dst: 输出图像
    • d: 滤波使用的像素邻域直径,如果是负数,则通过 sigmaSpace 计算。
    • sigmaColor: 颜色空间的方差,如果设置很大,则认定像素差很大的像素为邻域像素;
    • sigmaSpace: 坐标空间的方差,如果设置很大,意味着很远的像素为邻域像素,如果 d > 0, 由坐标决定是否为邻域。
    • borderType: 填充类型,不支持 BORDER_WRAP

    【参考】

    1. OpenCV 官方文档
    2. 双边滤波的介绍与应用
  • 相关阅读:
    PHP毕业设计毕设辅导课(6):PHP 字符串变量
    centos 6使用yum安装软件
    宝宝入托,爸妈要避开这5种心态
    Docker部署selenium程序-从本地到云服务器-详细步骤
    基于Android的学生信息管理App设计(Android studio开发)
    Qt学习总结之QPushbutton详解
    安全狗核心产品入选《云原生产品目录》云原生安全实力备受认可!
    Java 获得任意一个时间的 下一天的时间
    F. Minimum Maximum Distance Codeforces Round 903 (Div. 3)
    行情订阅&分钟合成
  • 原文地址:https://blog.csdn.net/zhoujinwang/article/details/127935511