1. 程式人生 > >opencv學習筆記 python實現 影象梯度與影象邊緣

opencv學習筆記 python實現 影象梯度與影象邊緣

        影象梯度即求導數,導數能反映出影象變化最大的地方,影象變化最大的地方也就是影象的邊緣。

        詳細見程式碼註釋,通俗易懂

  •   sobel運算元與scharr運算元

    在sobel運算元不能明顯反映影象邊緣時就換用scharr運算元

      

                                  

import cv2 as cv


def sobel_image(img):
    grad_x = cv.Sobel(img, cv.CV_32F, 1, 0)#x方向一階導數
    #影象  影象深度,支援src.depth()和ddepth的組合  x方向上差分階數 y方向差分階數
    grad_y = cv.Sobel(img, cv.CV_32F, 0, 1)#y方向一階導數
    #print(grad_x)
    gradx = cv.convertScaleAbs(grad_x)#可通過print檢視區別
    #線性輸入陣列轉化為無符號(絕對值)8為整形
    #print(gradx)
    grady = cv.convertScaleAbs(grad_y)
    cv.imshow("x", gradx)
    cv.imshow("y", grady)
    gradxy = cv.addWeighted(grad_x, 0.5, grad_y, 0.5, 0)#將兩幅影象整合
    #第一個陣列  第一個陣列的權重  第二個陣列 第二個陣列的權重 gamma
    #dst = src1[I]*alpha+ src2[I]*beta + gamma;輸出影象式子
    cv.imshow("x&&y", gradxy)


img = cv.imread("d://work//1.jpg")
sobel_image(img)
cv.waitKey(0)
cv.destroyAllWindows()

sobel到scharr改變求導方式即可

def scharr_image(image):
    grad_x = cv.Scharr(image, cv.CV_32F, 1, 0)
    grad_y = cv.Scharr(image, cv.CV_32F, 0, 1)
    gradx = cv.convertScaleAbs(grad_x)
    grady = cv.convertScaleAbs(grad_y)
    cv.imshow("x", grad_x)
    cv.imshow("y", grad_y)
    gradxy = cv.addWeighted(gradx, 0.5, grady, 0.5, 0)
    cv.imshow("x&y_s", gradxy)

相比sobel運算元把變化描述地更明顯

再介紹一種lpls運算元

lpls 運算元有四領域和8領域的,內建函式預設是四領域

def lpls_image(image):
    dst = cv.Laplacian(image, cv.CV_32F)
    lpls = cv.convertScaleAbs(dst)
    cv.imshow("lpls", lpls)
def lpls_image(image):
    #dst = cv.Laplacian(image, cv.CV_32F)
    #lpls = cv.convertScaleAbs(dst)
    dst = np.array([[1, 1, 1], [1, -8, 1], [1, 1, 1]])
    lpls = cv.filter2D(image, cv.CV_32F, dst)
    lpls = cv.convertScaleAbs(lpls)
    cv.imshow("lpls", lpls)

                                                       

              左邊為4領域 ,右邊為8領域suan運算元

總程式碼:

import cv2 as cv
import  numpy as np

#索貝爾運算元
def sobel_image(img):
    grad_x = cv.Sobel(img, cv.CV_32F, 1, 0)#x方向一階導數
    #影象  影象深度,支援src.depth()和ddepth的組合  x方向上差分階數 y方向差分階數
    grad_y = cv.Sobel(img, cv.CV_32F, 0, 1)#y方向一階導數
    #print(grad_x)
    gradx = cv.convertScaleAbs(grad_x)#可通過print檢視區別
    #線性輸入陣列轉化為無符號(絕對值)8為整形
    #print(gradx)
    grady = cv.convertScaleAbs(grad_y)
    cv.imshow("x", gradx)
    cv.imshow("y", grady)
    gradxy = cv.addWeighted(grad_x, 0.5, grad_y, 0.5, 0)#將兩幅影象整合
    #第一個陣列  第一個陣列的權重  第二個陣列 第二個陣列的權重 gamma
    #dst = src1[I]*alpha+ src2[I]*beta + gamma;輸出影象式子
    cv.imshow("x&&y", gradxy)

def scharr_image(image):
    grad_x = cv.Scharr(image, cv.CV_32F, 1, 0)
    grad_y = cv.Scharr(image, cv.CV_32F, 0, 1)
    gradx = cv.convertScaleAbs(grad_x)
    grady = cv.convertScaleAbs(grad_y)
    cv.imshow("x", grad_x)
    cv.imshow("y", grad_y)
    gradxy = cv.addWeighted(gradx, 0.5, grady, 0.5, 0)
    cv.imshow("x&y_s", gradxy)

#拉普拉斯 內建4領域 和手動8領域寫法
def lpls_image(image):
    dst = cv.Laplacian(image, cv.CV_32F)
    lpls = cv.convertScaleAbs(dst)
    #dst = np.array([[1, 1, 1], [1, -8, 1], [1, 1, 1]])
    #lpls = cv.filter2D(image, cv.CV_32F, dst)
    #lpls = cv.convertScaleAbs(lpls)
    cv.imshow("lpls", lpls)


img = cv.imread("d://work//1.jpg")
lpls_image(img)
cv.waitKey(0)
cv.destroyAllWindows()