十三、梯度與顏色空間
梯度:
之前前言裡的邊界檢測能檢測到很多邊界,不僅是道路線的還包括了各種景物,車,路標等干擾因素。
但是我們知道我們要找的道路線應該是相對比較垂直於路面的,所以我們可以把找到的線和圖片的x軸和y軸再計算梯度。
索貝爾運算元(Sobel Operator):
兩個大於等於3並且大小為奇數的方形矩陣,用和影象的乘積來判斷在矩陣範圍內,影象的顏色在x軸和y軸方向上的變化大小。
如果結果矩陣各數值之和為0說明影象顏色在該軸上沒有變化。
預設的運算元矩陣大小(kernel size)是3,如果加大的話可以平滑一些無用的強烈梯度。
有用的函式:
gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
注:如果是用mpimg.imread()讀的圖片那麼用cv2.COLOR_RGB2GRAY,如果用cv2.imread()讀的圖片那麼用cv2.COLOR_BGR2GRAY。
在x和y方向上的梯度:
sobelx = cv2.Sobel(gray, cv2.CV_64F, 1, 0, ksize=sobel_kernel)
sobely = cv2.Sobel(gray, cv2.CV_64F, 0, 1, ksize=sobel_kernel)
abs_sobelx = np.absolute(sobelx)
scaled_sobel = np.uint8(255*abs_sobelx/np.max(abs_sobelx)) (注:這雖然不是必須的但是統一規格有助於以後統一閾值)
thresh_min = 20
thresh_max = 100
sbinary = np.zeros_like(scaled_sobel)
sbinary[(scaled_sobel >= thresh_min) & (scaled_sobel <= thresh_max)] = 1
plt.imshow(sxbinary, cmap='gray')
由實驗可知,道路線會在x軸梯度上更明顯,但是y軸梯度上也能看到。
梯度的大小(絕對值)可通過梯度的平方開根號得到。如果是計算兩軸的梯度大小,那麼就是梯度平方和開根號。
梯度的方向就是arctan(sobely/sobelx),理論上計算結果的範圍在+/−π之間,但是由於sobelx會被取絕對值所以結果會在+/−π/2之間。
程式碼中用np.arctan2().
將梯度大小,兩軸梯度大小和方向的閾值結合,調整引數至可以檢測出道路線
顏色空間:
前面我們將圖片轉化為灰度圖之後損失了顏色資訊,有時候這可能會讓我們更難分辨出道路線(如黃色的線變成灰度之後顏色會和灰色的道路很接近),所以我們需要顏色空間為我們提供更多的資訊。
除了RGB之外,還有HSV (hue色相, saturation飽和度, value明度) 和HLS (hue色相, lightness亮度, saturation飽和度) 顏色空間。
色相指的是和亮度無關的顏色,也就是說往該顏色上加黑色或者白色,將顏色變得更深或者更淺,對色相是沒有影響的。
明度和亮度都是用來表示顏色的明暗或者深淺。
飽和度指的是顏色的鮮豔程度,比如和白色更接近的顏色飽和度更低,和亮紅,亮黃,亮藍接近的顏色飽和度高。
這些顏色的表達方法是通過人類視覺感知或者是為了電視視訊/電腦影象的顯示而被開發出來的。
有用的函式:
hls = cv2.cvtColor(im, cv2.COLOR_RGB2HLS) (這裡順便會把RGB值轉化為0-1之間的值)
也可以使用純數學的方法完成轉換,要知道的是RGB值,算出其中最大的值(Vmax = max(R,G,B))和最小的值(Vmin = min(R,G,B))之後進行一系列運算。
通過比較用顏色值的閾值(分0,1)提取R,G,B,灰度圖,H,L,S圖中的道路線,會發現S圖出的效果最好,而且穩定性也好(不會因為光線影響結果)。
但是R圖在白線的處理上可能比S圖的結果還好,所以可以考慮結合各種影象的閾值得到一個穩定的結果。