美文网首页游戏王的故事
openCV:图像的梯度

openCV:图像的梯度

作者: SwiftBirds | 来源:发表于2019-09-25 08:01 被阅读0次

    sobel算子

    定义

    Sobel 算子是一个主要用作边缘检测的离散微分算子 (discrete differentiation operator)。 它Sobel算子结合了高斯平滑和微分求导,用来计算图像灰度函数的近似梯度。在图像的任何一点使用此算子,将会产生对应的梯度矢量或是其法矢量。

    步骤

    我们假设被作用图像为 I.然后进行如下的操作:

    1. 分别在x和y两个方向求导。
      • 水平变化: 将 I 与一个奇数大小的内核进行卷积。
      • 垂直变化: 将: I 与一个奇数大小的内核进行卷积。
    sobel_1.png
    1. 在图像的每一点,结合以上两个结果求出近似梯度
    sobel算子公式1.PNG sobel算子公式2.PNG

    API

    dst = cv2.Sobel(src, ddepth, dx, dy, ksize)

    • ddepth:图像的深度
    • dx和dy分别表示水平和竖直方向
    • ksize是Sobel算子的大小

    实例

    import cv2 #opencv读取的格式是BGR
    import numpy as np
    import matplotlib.pyplot as plt#Matplotlib是RGB
    %matplotlib inline 
    
    def cv_showimg(name,img):
        cv2.imshow(name, img)
        cv2.waitKey(0)
        cv2.destroyAllWindows()
    

    原图

    img = cv2.imread('pie.png',cv2.IMREAD_GRAYSCALE)
    cv_showimg('img',img)
    
    原图.PNG

    水平方向

    由sobel算子的卷积核可知,它是固定右减左的,白到黑是正数,黑到白就是负数了,所有的负数会被截断成0,所以实战时通常要做绝对值处理

    # 不做绝对值处理
    obelx = cv2.Sobel(img,cv2.CV_64F,1,0,ksize=3)
    cv_showimg('sobelx',sobelx)
    
    sobel水平方向-不取绝对值.PNG
    # 绝对值处理
    sobelx = cv2.Sobel(img,cv2.CV_64F,1,0,ksize=3)
    sobelx = cv2.convertScaleAbs(sobelx)
    cv_showimg('sobelx',sobelx)
    
    水平方向-绝对值处理.PNG

    垂直方向

    与水平方向同理

    sobely = cv2.Sobel(img,cv2.CV_64F,0,1,ksize=3)
    sobely = cv2.convertScaleAbs(sobely)  
    cv_showimg('sobely',sobely)
    
    垂直方向.PNG

    结果相加

    将两个方向的结果整合到一起,有两种方法:

    • 分别计算x和y,再求和。
    • 直接计算,结果不好,不建议这么做。
    # 方法一:分开计算
    sobelxy = cv2.addWeighted(sobelx,0.5,sobely,0.5,0)
    cv_showimg('sobelxy',sobelxy)
    
    分开计算效果图.PNG
    # 方法二:直接计算
    sobelxy=cv2.Sobel(img,cv2.CV_64F,1,1,ksize=3)
    sobelxy = cv2.convertScaleAbs(sobelxy) 
    cv_showimg('sobelxy',sobelxy)
    
    直接计算.PNG

    Scharr算子

    概念

    当内核大小为 3 时, 我们的Sobel内核可能产生比较明显的误差(毕竟,Sobel算子只是求取了导数的近似值而已)。 为解决这一问题,OpenCV提供了Scharr 函数,但该函数仅作用于大小为3的内核。该函数的运算与Sobel函数一样快,但结果却更加精确,其内核是这样的:

    Scharr算子

    因为Sobel算子结合了高斯平滑和分化(differentiation),因此结果会具有更多的抗噪性。大多数情况下,我们使用sobel函数

    API

    dst = cv2.Scharr(src, ddepth, dx, dy)

    • ddepth:图像的深度
    • dx和dy分别表示水平和竖直方向
    • 没有ksize,因为它的内核大小固定为3

    实例

    scharrx = cv2.Scharr(img,cv2.CV_64F,1,0)
    scharry = cv2.Scharr(img,cv2.CV_64F,0,1)
    scharrx = cv2.convertScaleAbs(scharrx)   
    scharry = cv2.convertScaleAbs(scharry)  
    scharrxy =  cv2.addWeighted(scharrx,0.5,scharry,0.5,0) 
    cv_showimg('scharrxy',scharrxy)
    
    scharr算子结果.PNG

    laplacian算子

    概念

    Laplacian 算子是n维欧几里德空间中的一个二阶微分算子,定义为梯度grad()的散度div()。因此如果f是二阶可微的实函数,则f的拉普拉斯算子定义为:

    1. f的拉普拉斯算子也是笛卡儿坐标系xi中的所有非混合二阶偏导数求和:

    2. 作为一个二阶微分算子,拉普拉斯算子把C函数映射到C函数,对于k ≥ 2。表达式(1)(或(2))定义了一个算子Δ :C(R) → C(R),或更一般地,定义了一个算子Δ : C(Ω) → C(Ω),对于任何开集Ω。

    根据图像处理的原理我们知道,二阶导数可以用来进行检测边缘 。 因为图像是 “二维”, 我们需要在两个方向进行求导。使用Laplacian算子将会使求导过程变得简单。

    Laplacian 算子的定义:


    拉普拉斯算子

    API

    dst = cv2.Laplacian(src, ddepth)

    • ddepth:图像的深度

    实例

    laplacian = cv2.Laplacian(img,cv2.CV_64F)
    laplacian = cv2.convertScaleAbs(laplacian)  
    cv_showimg('laplacian',laplacian)
    
    拉普拉斯算子结果图.PNG

    三种算子在实际图中的比较

    scharr算子比sobel算子更关注细节,边界信息更细致。
    laplacian算子单独使用效果并不是很好,要结合其它的算法一起使用。

    img = cv2.imread('lena.jpg',cv2.IMREAD_GRAYSCALE)
    sobelx = cv2.Sobel(img,cv2.CV_64F,1,0,ksize=3)
    sobely = cv2.Sobel(img,cv2.CV_64F,0,1,ksize=3)
    sobelx = cv2.convertScaleAbs(sobelx)   
    sobely = cv2.convertScaleAbs(sobely)  
    sobelxy =  cv2.addWeighted(sobelx,0.5,sobely,0.5,0)  
    
    scharrx = cv2.Scharr(img,cv2.CV_64F,1,0)
    scharry = cv2.Scharr(img,cv2.CV_64F,0,1)
    scharrx = cv2.convertScaleAbs(scharrx)   
    scharry = cv2.convertScaleAbs(scharry)  
    scharrxy =  cv2.addWeighted(scharrx,0.5,scharry,0.5,0) 
    
    laplacian = cv2.Laplacian(img,cv2.CV_64F)
    laplacian = cv2.convertScaleAbs(laplacian)   
    
    res = np.hstack((sobelxy,scharrxy,laplacian))
    cv_showimg('res',res)
    
    三种算子的比较图.PNG

    相关文章

      网友评论

        本文标题:openCV:图像的梯度

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