美文网首页
Python+OpenCV教程番外篇8:图像梯度

Python+OpenCV教程番外篇8:图像梯度

作者: e8bcb7ff1632 | 来源:发表于2018-01-10 16:36 被阅读900次

    主站:http://ex2tron.wang
    原文:Python+OpenCV教程番外篇8:图像梯度


    (数学公式显示如果有问题,请点击原文查看!)

    了解图像梯度和边缘检测的相关概念。图片等可到源码处下载。

    还记得前面平滑图像中提到的滤波与模糊的区别吗?我们说低通滤波器是模糊,高通滤波器是锐化,这节我们就来看看高通滤波器。

    图像梯度

    如果你还记得高数中用一阶导数来求极值的话,就很容易理解了:把图片想象成连续函数,因为边缘部分的像素值是与旁边像素明显有区别的,所以对图片局部求极值,就可以得到整幅图片的边缘信息了。不过图片是二维的离散函数,导数就变成了差分,这个差分就称为图像的梯度。

    当然,大部分人应该是早忘记高数了( ̄▽ ̄)",所以看不懂的话,就把上面的解释划掉,我们重新从卷积的角度来看看。

    垂直边缘提取

    滤波是应用卷积来实现的,卷积的关键就是卷积核,我们来考察下面这个卷积核:

    k1 = \left[ \begin{matrix} -1 & 0 & 1 \newline -2 & 0 & 2 \newline -1 & 0 & 1 \end{matrix} \right]

    这个核是用来提取图片中的垂直边缘的,怎么做到的呢?看下图:

    当前列左右两侧的元素进行差分,由于边缘的值明显小于(或大于)周边像素,所以边缘的差分结果会明显不同,这样就提取出了垂直边缘。同理,把上面那个矩阵转置一下,就是提取水平边缘。这种差分操作就叫图像的梯度计算:

    k2 = \left[ \begin{matrix} -1 & -2 & -1 \newline 0 & 0 & 0 \newline 1 & 2 & 1 \end{matrix} \right]

    垂直和水平边缘提取

    还记得滤波函数cv2.filter2D()吗?(番外篇:卷积基础)我们来手动实现上面的功能:

    import cv2
    import numpy as np
    
    img = cv2.imread('sudoku.jpg', 0)
    
    # 自己进行垂直边缘提取
    kernel = np.array([[-1, 0, 1],
                       [-2, 0, 2],
                       [-1, 0, 1]], dtype=np.float32)
    dst_v = cv2.filter2D(img, -1, kernel)
    # 自己进行水平边缘提取
    dst_h = cv2.filter2D(img, -1, kernel.T)
    # 横向并排对比显示
    cv2.imshow('edge', np.hstack((img, dst_v, dst_h)))
    cv2.waitKey(0)
    

    Sobel算子

    上面的这种差分方法就叫Sobel算子,它先在垂直方向计算梯度Gx=k1×src,再在水平方向计算梯度Gy=k2×src,最后求出总梯度:\(G=\sqrt{Gx2+Gy2}\)

    我们可以把前面的代码用Sobel算子更简单地实现:

    sobelx = cv2.Sobel(img, -1, 1, 0, ksize=3)  # 只计算x方向
    sobely = cv2.Sobel(img, -1, 0, 1, ksize=3)  # 只计算y方向
    

    经验之谈:很多人疑问,Sobel算子的卷积核这几个值是怎么来的呢?事实上,并没有规定,你可以用你自己的。当然,3×3下另外一个卷积核相比Sobel更好用,叫Scharr算子,大家可以了解下:

    K = \left[ \begin{matrix} -3 & 0 & 3 \newline -10 & 0 & 10 \newline -3 & 0 & 3 \end{matrix} \right]

    Laplacian算子

    好开心,又要扯到高数的东西辣( ̄_, ̄ )高数中用一阶导数求极值,在这些极值的地方,二阶导数为0,所以可以通过求二阶导计算梯度:\(dst=\frac{\partial^2 f}{\partial x2}+\frac{\partial2 f}{\partial y^2}\)

    这就是Laplacian算子,了解了之后,最关键的是要会用:

    laplacian = cv2.Laplacian(img, -1)  # 使用Laplacian算子
    

    练习

    1. (选做)同志们有空补补高数姿势(知识)呗!(✿◕‿◕✿)

    引用

    相关文章

      网友评论

          本文标题:Python+OpenCV教程番外篇8:图像梯度

          本文链接:https://www.haomeiwen.com/subject/kgionxtx.html