opencv_圖像梯度

目錄

  1. 圖像梯度介紹
  2. 圖像梯度的原理
  3. OpenCV中圖像梯度方法
    (1) Sobel和Scharr算子
    (2) Laplacian 算子
    (3) 自定義核函數通過fiter2D實現
  4. 相關知識補充
圖像梯度介紹

圖像梯度可以把圖像看成二維離散函數,圖像梯度其實就是這個二維離散函數的求導
在圖像上表現出來的就是提取圖像的邊緣(無論是橫向的、縱向的、斜方向的等等)

圖像梯度原理

圖像梯度原理介紹

Sobel和Scharr算子

Sobel是普通一階差分,是基於尋找梯度強度。 圖像中邊緣區域,像素值會發生‘跳躍’,對這些像素求導,在其一階導數在邊緣位置時爲極值,這就是sobel算子使用的原理–極值處就是邊緣
每一個算子分別對應這x和y這兩個方向的模板,算子模板爲:
在這裏插入圖片描述
將兩個梯度爲合併:
在這裏插入圖片描述
爲簡化算,用絕對值代替,最終梯度爲

Sobel算子是結合了高斯平滑與微分運算的結合方法,所以它的抗噪聲能力很強,

代碼示例
import cv2 as cv
import numpy as np

def sobel_demo(image):
    grade_x = cv.Sobel(image, cv.CV_32F, 1, 0)  #獲取水平方向的梯度,對x進行一階求導,cv.CV_32F,防止位數不夠,出現截斷或者溢出
    grade_y = cv.Sobel(image, cv.CV_32F, 0, 1)  #獲取y軸方向的梯度
    gradex = cv.convertScaleAbs(grade_x)  #對其取絕對值,並轉換成uint8形式
    gradey = cv.convertScaleAbs(grade_y)
    cv.imshow("grade_x", gradex)
    cv.imshow("grade_y", gradey)
    grade = cv.addWeighted(gradex, 0.5, gradey, 0.5, 0) #對圖片進行融合
    cv.imshow("grade", grade)

print("----------------hello python opencv---------------------")
src = cv.imread("D:/pyhton/PhotoIditifyStuday/photo/manhua.jpg") #讀取原圖片
cv.namedWindow("input_image", cv.WINDOW_AUTOSIZE)
cv.imshow("input_image", src)
sobel_demo(src)
cv.waitKey(0)
cv.destroyAllWindows()

在這裏插入圖片描述
在調用濾波函數時,會遇到一個問題,從黑到白的邊界導數是正數,白到黑是負數,所以sobel函數求完導數後會有負值,還會有大於255的值。而原圖像是uint8,即8位無符號數,所以圖像位數不夠,會出現截斷。要用更高的數據類型,cv.CV_16S,cv._CV_32F等

在OpenCV函數中,在sobel算子的基礎上還有一種Scharr算子,可以獲取更強的邊緣檢測算子模板爲:
在這裏插入圖片描述
scharr算子相當於sobel的加強版,不過這樣其抗噪能力就會減弱

代碼示例
 grade_x = cv.Scharr(image, cv.CV_32F, 1, 0)  #獲取水平方向的梯度,對x進行一階求導,cv.CV_32F防止計算後數據溢出
 grade_y = cv.Scharr(image, cv.CV_32F, 0, 1)  #獲取y軸方向的梯度

在這裏插入圖片描述

拉普拉斯算子

拉普拉斯實現的算法是在sobel的基礎上,再求導,即對圖像求二階導
在這裏插入圖片描述
核模板:
在這裏插入圖片描述

在經過處理後,不能忘記用convertScaleAbs()函數將其轉回原來的uint8類型。否則將無法顯示圖像,而只是一幅灰色的窗口。

代碼示例
def laplacian_demo(image):
    lapl = cv.Laplacian(image, cv.CV_32F)
    dst = cv.convertScaleAbs(lapl)
    cv.imshow("laplacian", dst)


print("----------------hello python opencv---------------------")
src = cv.imread("D:/pyhton/PhotoIditifyStuday/photo/manhua.jpg") #讀取原圖片
cv.namedWindow("input_image", cv.WINDOW_AUTOSIZE)
cv.imshow("input_image", src)
laplacian_demo(src)
cv.waitKey(0)
cv.destroyAllWindows()

在這裏插入圖片描述
自定義核函數通過fiter2D實現

def laplacian_demo(image):
    kernel = np.array([[0, 1, 0], [1, -4, 1], [0, 1, 0]])
    dst = cv.filter2D(image, cv.CV_32F, kernel=kernel)
    lapl = cv.convertScaleAbs(dst)
    cv.imshow("laplaciam", lapl)

def laplacian_plus(image):
    kernel = np.array([[1, 1, 1], [1, -8, 1], [1, 1, 1]])
    dst = cv.filter2D(image, cv.CV_32F, kernel=kernel)
    lapl = cv.convertScaleAbs(dst)
    cv.imshow("laplaciam_plus", lapl)


print("----------------hello python opencv---------------------")
src = cv.imread("D:/pyhton/PhotoIditifyStuday/photo/manhua.jpg") #讀取原圖片
cv.namedWindow("input_image", cv.WINDOW_AUTOSIZE)
cv.imshow("input_image", src)
laplacian_demo(src)
laplacian_plus(src)
cv.waitKey(0)
cv.destroyAllWindows()

在這裏插入圖片描述

相關知識補充

(1) Sobel

Sobel(src, ddepth, dx, dy, dst=None, ksize=None, scale=None, delta=None, borderType=None)

src參數表示輸入需要處理的圖像。

ddepth參數表示輸出圖像深度,針對不同的輸入圖像,輸出目標圖像有不同的深度。

具體組合如下:
  src.depth() = CV_8U, 取ddepth =-1/CV_16S/CV_32F/CV_64F (一般源圖像都爲CV_8U,爲了避免溢出,一般ddepth參數選擇CV_32F)
  src.depth() = CV_16U/CV_16S, 取ddepth =-1/CV_32F/CV_64F
  src.depth() = CV_32F, 取ddepth =-1/CV_32F/CV_64F
  src.depth() = CV_64F, 取ddepth = -1/CV_64F
  注:ddepth =-1時,代表輸出圖像與輸入圖像相同的深度。
dx和dy表示的是求導的階數,0表示這個方向上沒有求導,一般爲0、1、2
其後是可選的參數:
dst參數表示輸出與src相同大小和相同通道數的圖像。
ksize參數表示Sobel算子的大小,必須爲1、3、5、7。
scale參數表示縮放導數的比例常數,默認情況下沒有伸縮係數。
delta參數表示一個可選的增量,將會加到最終的dst中,同樣,默認情況下沒有額外的值加到dst中。
borderType表示判斷圖像邊界的模式。這個參數默認值爲cv2.BORDER_DEFAULT。

(2) convertScaleAbsl

convertScaleAbs(src, dst=None, alpha=None, beta=None)

OpenCV的convertScaleAbs函數將數組轉爲取絕對值並轉換 uint8

src參數表示原數組。
dst參數表示輸出數組 (深度爲 8u)。
alpha參數表示比例因子。
beta參數表示原數組元素按比例縮放後添加的值

(3) addWeighted

addWeighted(src1, alpha, src2, beta, gamma, dst=None, dtype=None)

OpenCV的addWeighted函數是計算兩個數組的加權和
rc1參數表示需要加權的第一個輸入數組。

alpha參數表示第一個數組的權重。
src2參數表示第二個輸入數組,它和第一個數組擁有相同的尺寸和通道數。
beta參數表示第二個數組的權重。
gamma參數表示一個加到權重總和上的標量值。
dst參數表示輸出的數組,它和輸入的兩個數組擁有相同的尺寸和通道數。
dtype參數表示輸出數組的可選深度。當兩個輸入數組具有相同的深度時,這個參數設置爲-1(默認值)

(4) Laplacian

Laplacian(src, ddepth, dst=None, ksize=None, scale=None, delta=None, borderType=None)

ddepth參數表示輸出圖像深度,針對不同的輸入圖像,輸出目標圖像有不同的深度。
dst參數表示輸出與src相同大小和相同通道數的圖像。
ksize參數表示用於計算二階導數濾波器的孔徑大小,大小必須是正數和奇數。,可以通過修改ksize大小來修改算子,ksize默認是1,爲4卷積核,3是8卷積核,可以向上加,邊緣梯度檢測越明顯
scale參數表示計算拉普拉斯算子值的比例因子,默認情況下沒有伸縮係數。
delta參數表示一個可選的增量,將會加到最終的dst中,同樣,默認情況下沒有額外的值加到dst中。
borderType表示判斷圖像邊界的模式。這個參數默認值爲cv2.BORDER_DEFAULT。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章