Laplacian算子邊緣檢測的來源
在邊緣部分求取一階導數,你會看到極值的出現:
如果在邊緣部分求二階導數會出現什么情況?
從上例中我們可以推論檢測邊緣可以通過定位梯度值大于鄰域的相素的方法找到(或者推廣到大 于一個閥值). 從以上分析中,我們推論二階導數可以用來檢測邊緣 。 因為圖像是 “2維”, 我們需要在兩個方向求導。使用Laplacian算子將會使求導過程變得簡單。
Laplacian定義:
代碼實現:
import cv2
import numpy as np img=cv2.imread('lenna.png',0)#為了讓結果更清晰,圖像有3個channel,這里的ksize設為3,
gray_lap=cv2.Laplacian(img,cv2.CV_16S,ksize=3)#拉式算子
dst=cv2.convertScaleAbs(gray_lap)cv2.imshow('laplacian',dst)cv2.waitKey(0)
cv2.destroyAllWindows()
結果展示:
需要注意的幾個點:
注意一:
Laplacian算子的調用函數解析
在OpenCV-Python中,Laplace算子的函數原型如下:
dst = cv2.Laplacian(src, ddepth[, dst[, ksize[, scale[, delta[, borderType]]]]])
第一個參數是需要處理的圖像;
第二個參數是圖像的深度,-1表示采用的是與原圖像相同的深度。目標圖像的深度必須大于等于原圖像的深度;
dst不用解釋了;
ksize是算子的大小,必須為1、3、5、7。默認為1。
scale是縮放導數的比例常數,默認情況下沒有伸縮系數;
delta是一個可選的增量,將會加到最終的dst中,同樣,默認情況下沒有額外的值加到dst中;
borderType是判斷圖像邊界的模式。這個參數默認值為cv2.BORDER_DEFAULT。
注意二:
ddepth(目標圖像深度)為什么是cv2.CV_16S
?
這里引用了OpenCV 圖像梯度 :cv2.Sobel(),cv2.Schar(),cv2.Laplacian() + 數據類型設置:cv2.CV_8U,cv2.CV_16S,cv2.CV_64F
當我們可以通過參數-1 來設定輸出圖像的深度(數據類型)與原圖像保持一致,但是我們在代碼中使用的卻是cv2.CV_64F。這是為什么呢?想象一下一個從黑到白的邊界的導數是整數,而一個從白到黑的邊界點導數卻是負數。如果原圖像的深度是np.int8 時,所有的負值都會被截斷變成0,換句話說就是把把邊界丟失掉。所以如果這兩種邊界你都想檢測到,最好的的辦法就是將輸出的數據類型設置的更高,比如cv2.CV_16S,cv2.CV_64F 等。取絕對值然后再把它轉回到cv2.CV_8U。下面的示例演示了輸出圖片的深度不同造成的不同效果。
注意三:
ksize=3
為什么?
laplace內部是調用sobel來實現,而這個算子的大小實際是sobel的kernel_size,用于計算二階導數的濾波器的孔徑尺寸,大小必須為正奇數(正奇數才能有中心點)