• 【opencv图像处理】--4. 低、高通滤波,卷积和各种算子


    系列所有代码,复制粘贴即可运行。
    希望有能力的朋友还是拿C++运行一下。

    本节讨论图像的低通滤波(卷积,方盒,中值双边,高斯),高通滤波(Sobel,Scharr,Laplace,canny)

    一、低通滤波

    1. 卷积

    用卷积核对每个像素做线性运算,最终得到的小图像称作convolved Feature卷积特征

    • 步长:卷积核扫描一次移动的像素单位

    • padding: 对图像做卷积之后,长宽都会变小,padding就是在外围补充0的圈数,结构上类似于HTML中的padding,可以通过公式计算出需要填充0的圈数

    • 卷积核的大小一般都是奇数,padding不好补,另外这种卷积核有中心

    • 卷积核案例:
      cv2.filter2D

    1. ddepth是卷积之后图片位深,即图片数据类型,一般设-1与原图数据一致
    2. kernel是卷积核大小,用元组或ndarray表示,数据必须float
    3. anchor 锚点,卷积核的中心点,默认-1,-1
    4. delta 卷积之后额外加的值,线性方程中的偏差,默认是0
    5. borderType 边界类型一般不设置
    import cv2
    import numpy as np
    
    cat = cv2.imread('cat.jpeg')
    
    #均为1 每个点都被周围25个平均 变模糊 必须是float型
    
    
    #模糊卷积核
    #kernel = np.ones((5,5), np.float32) /25
    #轮廓卷积核
    #kernel = np.array([[-1, -1, -1], [-1, 8, -1], [-1, -1, -1]])
    #浮雕卷积核
    kernel = np.array([[0, -1, -1], [1, 0, -1], [1, 1, 0]])
    #锐化卷积核
    #kernel = np.array([[0, -1, 0], [-1, 5, -1], [0, -1, 0]])
    
    #-1 与原图数据类型一致
    dst = cv2.filter2D(cat, -1, kernel)
    
    cv2.imshow('cat', np.vstack((cat, dst)))
    
    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

    2. 方盒滤波与均值滤波

    滤波实际是去除噪点变模糊的过程,方盒滤波,卷积核内数值全为1,卷积核外乘一系数a。

    • 方盒滤波 boxFilter()
    1. normolize = True时,1/a=w*h,保证卷积核之和为1
    2. normolize = False时, a = 1,什么也没做,一般不这样设置
    • 均值滤波 blur
    1. 当方盒滤波的normolize为True时,去掉位深ddepth的方盒滤波等于均值滤波
    cat = cv2.imread('cat.jpeg')
    #方盒滤波 指定normalize
    #dst = cv2.boxFilter(cat, -1, (5,5), normalize=True)
    #均值滤波,没有参数位深和normalize
    dst = cv2.blur(cat, (5,5))
    
    • 1
    • 2
    • 3
    • 4
    • 5

    3. 高斯滤波

    符合正态分布的概率密度函数,md高斯分布二维的数学公式:
    G ( x , y ) = 1 2 π σ 2 e − x 2 + y 2 2 σ 2 G(x,y) = \frac{1}{2 \pi \sigma^2}e^{-\frac{x^2+y^2}{2\sigma ^2}} G(x,y)=2πσ21e2σ2x2+y2

    • 高斯滤波就是用符合高斯分布的卷积核对图片进行卷积操作,重点是计算该卷积核(高斯模板)

    • 例3X3卷积核,中间为x,y,上为x,y+1 左为x-1, y(其中x=0, y=0,因为在高斯中心)

    • **归一化:**通过高斯函数算出来的值,还要保证加起来值为1,需要除以它们的和,才是最终的高斯模板

    • 有些高斯模板归一化的方法是,卷积核内的值均除以左上角的值,然后取整

    • GaussianBlur(src, ksize, sigmaX[, dst[, sigmaY[, borderType]]])

    1. kernel 高斯核大小
    2. sigmaX, X轴的标准差
    3. sigmaY, Y轴的标准差,默认0,这是sigmaX=sigmaY
    4. 如果没有指定sigma值,会分别从ksize的宽度和高度中计算sigma。
    • 选择不同的sigma值会得到不同的平滑效果,sigma越大,平滑效果越明显/也越模糊
    dst = cv2.GaussianBlur(cat, (5,5), sigmaX=10)
    
    • 1

    4. 中值滤波

    适合胡椒噪音/椒盐噪声的去除,假设有一个数组,取中位数作为卷积之后的结果即可。

    • opencv的一个坑的地方,东西同样,但是API接口类型不同
    #这里的ksize确是一个数字
    dst = cv2.medianBlur(cat,5)
    
    • 1
    • 2

    5. 双边滤波

    可实现美颜,磨皮效果,是考虑了灰度距离和空间距离的两个高斯函数相乘,保留边缘信息。

    • 灰度距离: 像素与像素之间色阶不连续,像素之差,呈现断崖式下跌(边缘)
    • cv2.bilateralFilter
    1. sigmaColor: 计算像素信息使用的sigma
    2. sigmaSpace:计算空间信息使用的sigma
    dst = cv2.bilateralFilter(cat, 7, sigmaColor=20, sigmaSpace=50)
    
    • 1

    二、高通滤波

    用来找边界,特征提取,对象检测,模式识别等

    1. Sobel(索贝尔)算子

    边缘:像素值发生跃迁的地方。

    • Sobel算子对图像求一阶导数,值越大说明边缘信号越强烈
    • 沿着宽度和高度两个方向进行,使用水平和垂直两个方向卷积核
    #X方向 获取垂直边缘
    #Sobel要分别计算x,y的梯度
    #dx = cv2.Sobel(cat, cv2.CV_64F, 1, 0, ksize=3)
    dx = cv2.Sobel(cat, -1, dx=1, dy=0, ksize=3)
    #dy = cv2.Sobel(cat, cv2.CV_64F, 0, 1, ksize=3)
    dy = cv2.Sobel(cat, -1, dx=0, dy=1, ksize=3)
    
    #dx只有垂直的边缘
    #dy只有水平的边缘轮廓
    dst = cv2.add(dx, dy)
    cv2.imshow('cat_ori', cat)
    cv2.imshow('cat_merge', dst)
    cv2.imshow('cat', np.vstack((dx, dy)))
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    2. Scharr(沙尔)算子

    • 当SOBEL的卷积核大小为3时,可能产生明显误差,因为是取导数的近似值;
    • 是对Sobel算子的进化,但是它仅作用于大小为3的内核。与Sobel算子一样快,但结果却更加精确。
    • Scharr算子与Sobel很类似,不过使用了不同的kernel值放大了像素变换的情况
    • Scharr只能求x或y方向的边缘
    • Sobel算子的ksize设置为-1就是Scharr算子
    • Scharr擅长寻找细小的边缘,一般用的较少
    dx = cv2.Scharr(cat, -1, 1, 0)
    dy = cv2.Scharr(cat, -1, 0, 1)
    
    #dx只有垂直的边缘
    #dy只有水平的边缘轮廓
    dst = cv2.add(dx, dy)
    cv2.imshow('cat_ori', cat)
    cv2.imshow('cat_merge', dst)
    cv2.imshow('cat', np.vstack((dx, dy)))
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    3. Laplace(拉普拉斯)算子

    拉普拉斯算子是求二阶导,对于边缘变化的反应更加敏锐。有的无意义的地方数值为0,需要去噪

    • Laplacian(src, ddepth[, dst[, ksize[, scale[, delta[, borderType]]]]])
    1. 因为是二阶导,所以可以同时求两个方向的边缘
    2. 对噪音敏感,一般要先去噪再调用拉普拉斯
    dst = cv2.Laplacian(cat, -1, ksize=3)
    
    • 1

    4. canny算子

    被人认为是最有边缘检测算法,多级边缘检测算法

    • canny边缘检测一般步骤
    1. 去噪
    2. 计算梯度:对去噪后的图像用sobel算子计算梯度和方向
    3. 非极大值抑制(NMS)
    4. 滞后阈值:没有和其他边界点相连,不算做边界
    • Canny(image, threshold1, threshold2[, edges[, apertureSize[, L2gradient]]])
    #设定阈值大小,值小,边缘比较丰富
    #值越大,边缘越少
    dst = cv2.Canny(cat, 100, 200)
    dst2 = cv2.Canny(cat, 64, 128)
    
    • 1
    • 2
    • 3
    • 4
  • 相关阅读:
    第九章:最新版零基础学习 PYTHON 教程—Python 元组(第三节 -访问Python元组的前后元素)
    京东JD开放平台API接口调用采集商品详情数据获取商品规格信息、销量、卖家信息抓取案例
    opencv-python 2 图像基本操作
    python播放声音库playsound以及获取路径以及修改库源码
    能带你起飞的【数据结构】成王第十二篇:堆2
    X-ray diffraction
    QT学习日记21——五子棋AI
    能与远方家人分享生活瞬间的网络相册
    CentOS 7 源码安装 Zabbix 6.0
    C杂讲 结构体对齐
  • 原文地址:https://blog.csdn.net/Eric_Sober/article/details/126053086