梯度簡單來說就是求導,在圖像上表現出來的就是提取圖像的邊緣(無論是橫向的、縱向的、斜方向的等等),所須要的無非也是一個核模板。模板的不同結果也不同。所以能夠看到,全部的這些個算子函數,歸結究竟都能夠用函數cv2.filter2D()來表示,不同的方法給予不同的核模板,然后演化為不同的算子而已。而且這僅僅是這類濾波函數的一個用途,以前寫過一個關於matlab下濾波函數imfilter()的擴展應用(等同於opencv的cv2.filter2D函數):
就是非常多復雜的計算都是能夠通過這個濾波函數組合實現,這種話速度快。
(一)關於Sobel算子與Scharr算子
Sobel算子是高斯平滑與微分操作的結合體。所以其抗噪能力非常強,用途較多。一般的sobel算子包含x與y兩個方向,算子模板為:
在opencv函數中,還能夠設置卷積核(ksize)的大小,假設ksize=-1,就演變為3*3的Scharr算子,模板無非變了個數字:
貼一個相關具體參考:
(二)關於拉普拉斯(Laplacian)算子
拉普拉斯算子能夠實現圖像的二階倒數的定義,至於二階倒數有什么意義,能夠看這位博主的具體介紹:
OpenCV-Python教程(7、Laplacian算子)
其核模板為:
以下是對上述三種模板的實例:
import cv2
import numpy as np
import matplotlib.pyplot as plt
img = cv2.imread('flower.jpg',0)
sobelx = cv2.Sobel(img,cv2.CV_64F,1,0,ksize=3)#默認ksize=3
sobely = cv2.Sobel(img,cv2.CV_64F,0,1)
sobelxy = cv2.Sobel(img,cv2.CV_64F,1,1)
laplacian = cv2.Laplacian(img,cv2.CV_64F)#默認ksize=3
#人工生成一個高斯核,去和函數生成的比較
kernel = np.array([[0,-1,0],[-1,4,-1],[0,-1,0]],np.float32)#
img1 = np.float64(img)#轉化為浮點型的
img_filter = cv2.filter2D(img1,-1,kernel)
sobelxy1 = cv2.Sobel(img1,-1,1,1)
plt.subplot(221),plt.imshow(sobelx,'gray')
plt.subplot(222),plt.imshow(sobely,'gray')
plt.subplot(223),plt.imshow(sobelxy,'gray')
plt.subplot(224),plt.imshow(laplacian,'gray')
plt.figure()
plt.imshow(img_filter,'gray')
上述一個非常重要的問題須要明確的就是。在濾波函數第二個參數,當我們使用-1表示輸出圖像與輸入圖像的數據類型一致時,假設原始圖像是uint8型的,那么在經過算子計算以后,得到的圖像可能會有負值,假設與原圖像數據類型一致,那么負值就會被截斷變成0或者255,使得結果錯誤,那么針對這種問題有兩種方式改變(上述程序中都有):一種就是改變輸出圖像的數據類型(第二個參數cv2.CV_64F)。還有一種就是改變原始圖像的數據類型(此時第二個參數能夠為-1,與原始圖像一致)。
上述程序從結果上也說明使用函數cv2.filter2D也能達到同樣的效果。
(三)Canny邊緣檢測算子
關於canny邊緣檢測算子,細究的話還算比較的復雜,給出一個介紹比較具體的博客吧:
那么opencv中的函數也非常easy,直接cv2.Canny(),這個函數須要五個參數,原始圖像,兩個范圍控制值minVal和maxVal(見上述原理介紹),第四個參數用於規定核模板的大小(默認3)。最后一個是true與false(默認)的選擇。有一點不同,不太重要。能夠試着那個好用那個。
import cv2
import matplotlib.pyplot as plt
img = cv2.imread('flower.jpg',0)
edges = cv2.Canny(img,100,200)#其它的默認
plt.subplot(121),plt.imshow(img,'gray')
plt.subplot(122),plt.imshow(edges,'gray')

