Python - opencv (一) 邊緣檢測 - 1
本文開始Python - opencv的學習,因為有一些影象基礎,圖形學的基礎部分(包括影象基本知識、環境部署、灰度直方圖和二值化、影象縮放、腐蝕膨脹、開閉運算)跳過,直接從常用處理和機器學習開始。
本文記錄opencv的邊緣檢測應用。
一. Sobel運算元
sobel運算元的思想,Sobel運算元認為,鄰域的畫素對當前畫素產生的影響不是等價的,所以距離不同的畫素具有不同的權值,對運算元結果產生的影響也不同。一般來說,距離越遠,產生的影響越小。
sobel運算元的原理,對傳進來的影象畫素做卷積,卷積的實質是在求梯度值,或者說給了一個加權平均,其中權值就是所謂的卷積核;然後對生成的新畫素灰度值做閾值運算,以此來確定邊緣資訊。
原圖中的作用點畫素值通過卷積之後為:
可以簡化成:
比如,一下矩陣為原圖中的畫素點矩陣,帶入上式中的A,最終得到的G或者|G|是下面(x,y)處的畫素值,可以自己去搜索下卷積的含義來理解。
另外,卷積核也可以旋轉,用與查詢不與x,y軸平行或垂直的方向上的邊緣。
一般來說,對影象分別進行x和y兩個方向的sobel運算再求和,比先進行一個方向,再進行另一個方向效果要好很多。
例子:
原圖:
程式碼:
1 import cv2 2 3 if __name__ == '__main__': 4 img = cv2.imread('../pics/1.jpg', cv2.IMREAD_GRAYSCALE)5 cv2.imshow('img', img) 6 sobel_x = cv2.Sobel(img, cv2.CV_64F, 1, 0, ksize=3) 7 sobel_x = cv2.convertScaleAbs(sobel_x) 8 sobel_y = cv2.Sobel(img, cv2.CV_64F, 0, 1, ksize=3) 9 sobel_y = cv2.convertScaleAbs(sobel_y) 10 sobel_xy = cv2.addWeighted(sobel_x, 0.5, sobel_y, 0.5, 0) 11cv2.imshow('img', sobel_xy) 12 cv2.waitKey() 13 cv2.destroyAllWindows()
這裡convertScaleAbs函式是一個位深轉化函式,可將任意型別的資料轉化為CV_8UC1。具體資料處理方式如下:
(1). 對於src*alpha+beta的結果如果是負值且大於-255,則直接取絕對值;
(2). 對於src*alpha+beta的結果如果大於255,則取255;
(3). 對於src*alpha+beta的結果是負值,且小於-255,則取255;
(4). 對於src*alpha+beta的結果如果在0-255之間,則保持不變;
對於單方向sobel以後,卷積乘到的賦值進行一個變換,可以實現兩個方向分別求卷積
效果:
人的輪廓基本上能分割出來
二. Scharr運算元和Laplacian運算元
特點:對邊界識別度更高,缺點是對噪聲很敏感
兩者演算法和Sobel很像,都是求卷積
程式碼:
1 import cv2 2 import numpy as np 3 4 if __name__ == '__main__': 5 img = cv2.imread('../pics/1.jpg', cv2.IMREAD_GRAYSCALE) 6 7 scharr_x = cv2.Scharr(img, cv2.CV_64F, 1, 0) 8 scharr_x = cv2.convertScaleAbs(scharr_x) 9 scharr_y = cv2.Scharr(img, cv2.CV_64F, 0, 1) 10 scharr_y = cv2.convertScaleAbs(scharr_y) 11 scharr_xy = cv2.addWeighted(scharr_x, 0.5, scharr_y, 0.5, 0) 12 13 laplacian = cv2.Laplacian(img, cv2.CV_64F) 14 laplacian = cv2.convertScaleAbs(laplacian) 15 16 res = np.hstack((scharr_xy, laplacian)) 17 cv2.imshow('img', res) 18 cv2.waitKey()
效果: