原理
OpenCV提供了三種類型的梯度過濾器或者高通濾波器,Sobel章贞,Scharr和Laplacian。
1.Sobel和Scharr 導數(shù)
Sobel算子是一個連接高斯平滑和微分運算矾柜,所以它更抗噪音阱驾,你可以指定求導的方向,垂直的或水平的(參數(shù)yorder和xorder)怪蔑。你也可以指定核的大小ksize里覆,如果ksize=-1,會使用一個3x3的Scharr過濾器缆瓣,這個的結果要比3x3的sobel過濾器的結果好喧枷。
2.拉普拉斯導數(shù)
如果通過公式計算圖片的拉布拉斯
用Sobel導數(shù)找到每個導數(shù),如果ksize=1,下面的核用來過濾:
代碼:
下面的代碼在一個圖里顯示了所有算子。核都是5x5的隧甚。圖片的深度傳的是參數(shù)-1來得到np.uint8類型车荔。
import cv2
import numpy as np
from matplotlib import pyplot as plt
img =?cv2.imread('dave.jpg',0)
laplacian = cv2.Laplacian(img,cv2.CV_64F)
sobelx = cv2.Sobel(img,cv2.CV_64F,1,0,ksize=5)
sobely = cv2.Sobel(img,cv2.CV_64F,0,1,ksize=5)
plt.subplot(2,2,1), plt.imshow(img,cmap='gray')
plt.title('Original'), plt.xticks([]), plt.yticks([])
plt.subplot(2,2,2), plt.imshow(laplacian,cmap='gray')
plt.title('Laplacian'), plt.xticks([]), plt.yticks([])
plt.subplot(2,2,3), plt.imshow(sobelx,cmap='gray')
plt.title('Sobel X'), plt.xticks([]), plt.yticks([])
plt.subplot(2,2,4), plt.imshow(sobely,cmap='gray')
plt.title('Sobel Y'), plt.xticks([]), plt.yticks([])
plt.show()
結果:
一個重要的問題!
在上一個例子里戚扳,輸出數(shù)據(jù)類型是cv2.CV_8U或者np.uint8.但是有一點問題忧便。黑到白的轉換是正坡(正值)而白到黑的轉換時負坡(負值)。所以當你把數(shù)據(jù)轉換成np.uint8時帽借,所有的負坡變成0.簡單說珠增,你會丟掉那些邊緣。
如果你想檢測兩個邊緣砍艾,更好的選擇是讓輸出數(shù)據(jù)類型保持高級形式蒂教,像cv2.CV_16S,cv2.CV_64F等脆荷。用他們的絕對值凝垛,然后轉換回cv2.CV_8U。下面的代碼展示了這個過程蜓谋,
import cv2
import numpy as np
from matplotlib import pyplot as plt
img = cv2.imread('box.png',0)
# Output dtype = cv2.CV_8U
sobelx8u = cv2.Sobel(img,cv2.CV_8U,1,0,ksize=5)
# Output dtype = cv2.CV_64F. Then take its absolute and convert to cv2.CV_8U
sobelx64f = cv2.Sobel(img,cv2.CV_64F,1,0,ksize=5)
abs_sobel64f = np.absolute(sobelx64f)
sobel_8u = np.uint8(abs_sobel64f)
plt.subplot(1,3,1), plt.imshow(img,cmap='gray')
plt.title('Original'), plt.xticks([]), plt.yticks([])
plt.subplot(1,3,2), plt.imshow(sobelx8u,cmap='gray')
plt.title('Sobel CV_8U'), plt.xticks([]), plt.yticks([])
plt.subplot(1,3,3), plt.imshow(sobel_8u,cmap='gray')
plt.title('Sobel abs(CV_64F)'), plt.xticks([]), plt.yticks([])
plt.show()
結果: