目錄
邊緣檢測
一、sobel算子邊緣檢測
(1)原理
1、X軸方向的邊緣檢測
2、Y軸方向的邊緣檢測????????
(2)sobel算子參數
(3)X軸方向邊緣檢測代碼演示
1、顯示圓的圖像
2、x方向上的邊緣檢測,即使用Gx卷積核
3、 轉換數據類型保存圖像的負數信息
4、x方向上的邊緣,包括負數信息,進行取絕對值的操作,右端的負值信息就可以顯示出來了,使用cv2.convertScaleAbs()方法
(4)Y軸方向邊緣檢測代碼演示
1、y方向上的邊緣檢測,即使用Gy卷積核
2、 轉換數據類型保存圖像的負數信息,同時,y方向上的邊緣,包括負數信息,進行取絕對值的操作,右端的負值信息就可以顯示出來了,使用cv2.convertScaleAbs()方法
(5)同時對x,y方向做邊緣檢測(不建議使用)
(6)使用圖像加權運算組合x和y方向的2個邊緣。????????
(7)讀取人物圖像觀看sobel算子效果
二、Scharr 算子
(1)原理
三、拉普拉斯算子
(1)原理
2、參數及代碼
四、canny邊緣檢測
(1)Canny邊緣檢測的優點
(2)canny邊緣檢測分為4個部分
1、圖像降噪
2、梯度計算
3、非極大值抑制NMS(Non-Maximal Suppression)
4、雙閾值邊界跟蹤
(3)參數解釋及代碼
邊緣檢測
邊緣檢測:是圖形圖像處理、計算機視覺和機器視覺中的一個基本工具,通常用于特征提取和特征檢測,旨在檢測一張數字圖像中有明顯變化的邊緣或者不連續的區域。
一、sobel算子邊緣檢測
(1)原理
Sobel 算子是一種離散的微分算子,該算子結合了高斯平滑(離像素點越遠的值越小)和微分求導運算(像素變化率, 從左到右或右到左)。該算子利用局部差分尋找邊緣,計算所得的是一個梯度的近似值。
Sobel算子包含2組3×3的矩陣,分別為橫向和縱向模板,將之與圖像作平面卷積,即可分別得出橫向及縱向的亮度差分近似值。
1、X軸方向的邊緣檢測
????????Gx這個卷積核會從圖像的左上角,從左到右從上到下移動,每移動到一個新的位置都會按卷積核計算。在縱向方向上進行加權計算。
????????當卷積框出現在”1“這個位置時,卷積框左側為黑色,數值為接近0的數;卷積框右側為白色,數值為接近255的數,卷積計算之后的值大于255正值。
????????當卷積框出現在”2“位置時,卷積框左右對稱計算之后數值接近0,顯示為黑色。
????????當卷積框出現在”3“位置時,卷積框左側為白色,數值為接近255的數;卷積框右側為黑色,數值為接近0的數,卷積計算之后的值為小于255負值。
????????由于負數在opencv的圖像中顯示不出來,所以會出現圓的左半部分會顯示,右半部分顯示不出來。
2、Y軸方向的邊緣檢測????????
Gy這個卷積核會從圖像的左上角,從左到右從上到下移動,每移動到一個新的位置都會按卷積核計算。在橫向方向上進行加權計算。
????????當卷積框出現在”1“這個位置時,卷積框上側為黑色,數值為接近0的數;卷積框下側為白色,數值為接近255的數,卷積計算之后的值大于255正值。
????????當卷積框出現在”2“位置時,卷積框左右對稱計算之后數值接近0,顯示為黑色。
?????????當卷積框出現在”3“位置時,卷積框上側為白色,數值為接近255的數;卷積框下側為黑色,數值為接近0的數,卷積計算之后的值為小于255負值。
????????由于負數在opencv的圖像中顯示不出來,所以會出現圓的上半部分會顯示,下半部分顯示不出來。
(2)sobel算子參數
cv2.Sobel(src, ddepth, dx, dy[, ksize[, scale[, delta[, borderType]]]])
參數:
src:輸入圖像
ddepth: 輸出圖像的深度(可以理解為數據類型),-1表示與原圖像相同的深度
dx,dy:當組合為dx=1,dy=0時求x方向的一階導數,當組合為dx=0,dy=1時求y方向的一階導數(如果同時為1,通常效果不佳)
ksize:(可選參數)Sobel算子的大小,必須是1,3,5或者7,默認為3
(3)X軸方向邊緣檢測代碼演示
目標:檢測白色圓的邊緣,得到一個完整的圓環。
1、顯示圓的圖像
yuan = cv2.imread('yuan.png')
cv2.imshow('yuan',yuan)
cv2.waitKey(0)
?
2、x方向上的邊緣檢測,即使用Gx卷積核
x方向上的邊緣,包括負數信息(右端),但顯示不出來,因為范圍是(0~255)
yuan_x = cv2.Sobel(yuan,-1,dx=1,dy=0)
cv2.imshow('yuan_x',yuan_x)
cv2.waitKey(0)
?
3、 轉換數據類型保存圖像的負數信息
opencv讀取圖像默認是uint8類型,-1表示與原圖像相同的深度即相同的數據類型也就是uint8類,型,使用cv2.CV_64F這個數據類型也就是float64位,將邊緣檢測的中遇到的負數保存下來,但是在圖像中還沒體現出來。
yuan_x_64 = cv2.Sobel(yuan,cv2.CV_64F,dx=1,dy=0)#默認uint8改為float64,可保存負數
cv2.imshow('yuan_x_64',yuan_x_64)
cv2.waitKey(0)
?
4、x方向上的邊緣,包括負數信息,進行取絕對值的操作,右端的負值信息就可以顯示出來了,使用cv2.convertScaleAbs()方法
yuan_x_full = cv2.convertScaleAbs(yuan_x_64)#轉換為絕對值,負數轉換為正數
cv2.imshow('yuan_x_full',yuan_x_full)
cv2.waitKey(0)
?
(4)Y軸方向邊緣檢測代碼演示
1、y方向上的邊緣檢測,即使用Gy卷積核
yuan_y = cv2.Sobel(yuan,-1,dx=0,dy=1)
cv2.imshow('yuan_y',yuan_y)
cv2.waitKey(0)
?
y方向上的邊緣,包括負數信息(下端),但顯示不出來,因為范圍是(0~255)
2、 轉換數據類型保存圖像的負數信息,同時,y方向上的邊緣,包括負數信息,進行取絕對值的操作,右端的負值信息就可以顯示出來了,使用cv2.convertScaleAbs()方法
yuan_y_64 = cv2.Sobel(yuan,cv2.CV_64F,dx=0,dy=1)#默認int8改為float64,可保存負數
yuan_y_full = cv2.convertScaleAbs(yuan_y_64)#轉換為絕對值,負數轉換為正數
cv2.imshow('yuan_y_full',yuan_y_full)
cv2.waitKey(0)
?
(5)同時對x,y方向做邊緣檢測(不建議使用)
yuan_xy = cv2.Sobel(yuan,-1,dx=1,dy=1)
cv2.imshow('yuan_xy',yuan_xy)
cv2.waitKey(100000)
?
(6)使用圖像加權運算組合x和y方向的2個邊緣。
????????
從上面的圖像看出只做X軸的邊緣檢測左右兩邊是可以得到完整的圓弧,只做Y軸的邊緣檢測上下兩側可以得到完整的圓弧,因此我們考慮將兩者加權在一起就可以得到完整的圓弧。
yuan_xy_full = cv2.addWeighted(yuan_x_full,1,yuan_y_full,1,0)
cv2.imshow('yuan_xy_full',yuan_xy_full)
cv2.waitKey(0)
?
(7)讀取人物圖像觀看sobel算子效果
zl = cv2.imread('zl.png',cv2.IMREAD_GRAYSCALE)#不用灰度試試效果
zl_x_64 = cv2.Sobel(zl,cv2.CV_64F,dx=1,dy=0)#默認int8改為float64,可保存負數
zl_x_full = cv2.convertScaleAbs(zl_x_64)#轉換為絕對值,負數轉換為正數
zl_y_64 = cv2.Sobel(zl,cv2.CV_64F,dx=0,dy=1)#默認int8改為float64,可保存負數
zl_y_full = cv2.convertScaleAbs(zl_y_64)#轉換為絕對值,負數轉換為正數
zl_xy_sobel_full = cv2.addWeighted(zl_x_full,1,zl_y_full,1,0)
cv2.imshow('zl_xy_sobel_full',zl_xy_sobel_full)
cv2.waitKey(0)
二、Scharr 算子
(1)原理
????????Scharr 算子是 Soble 算子在 ksize=3 時的優化,與 Soble 的速度相同,且精度更高。Scharr 算子與 Sobel 算子的不同點是在平滑部分,其中心元素占的權重更重,相當于使用較小標準差的高斯函數,也就是更瘦高的模板。
(2)參數及代碼
cv.Scharr(src, ddepth, dx, dy[, dst[, scale[, delta[, borderType]]]])
src:輸入圖像
ddepth:輸出圖片的數據深度,由輸入圖像的深度進行選擇
dx:x 軸方向導數的階數
dy:y 軸方向導數的階數
zl = cv2.imread('zl.png',cv2.IMREAD_GRAYSCALE)
zl_x_64 = cv2.Scharr(zl,cv2.CV_64F,dx=1,dy=0)#默認int8改為float64,可保存負數
zl_x_full = cv2.convertScaleAbs(zl_x_64)#轉換為絕對值,負數轉換為正數
zl_y_64 = cv2.Scharr(zl,cv2.CV_64F,dx=0,dy=1)#默認int8改為float64,可保存負數
zl_y_full = cv2.convertScaleAbs(zl_y_64)#轉換為絕對值,負數轉換為正數
zl_xy_Scharr_full = cv2.addWeighted(zl_x_full,1,zl_y_full,1,0)
cv2.imshow('zl_xy_Scharr_full',zl_xy_Scharr_full)
cv2.waitKey(0)
三、拉普拉斯算子
(1)原理
不再以x和y的方向計算,而是以圓方向計算變化率。因此不需要Gx+Gy。
2、參數及代碼
cv2.Laplacian(src, ddepth[, dst[, ksize[, scale[, delta[, borderType]]]]])
參數說明:
src:輸入圖像,可以是灰度圖像,也可以是多通道的彩色圖像
ddepth:輸出圖片的數據深度:
ksize:計算二階導數濾波器的孔徑大小,必須為正奇數,可選項
scale:縮放比例因子,可選項,默認值為 1
delta:輸出圖像的偏移量,可選項,默認值為 0
zl = cv2.imread('zl.png',cv2.IMREAD_GRAYSCALE)
zl_lap = cv2.Laplacian(zl,cv2.CV_64F)
zl_lap_full = cv2.convertScaleAbs(zl_lap)#轉換為絕對值,負數轉換為正數
cv2.imshow('zl_lap_full',zl_lap_full)
cv2.waitKey(0)
?
四、canny邊緣檢測
(1)Canny邊緣檢測的優點
低錯誤率。因為一般的邊緣檢測算子可能存在檢測到偽邊緣的情況,因此Canny算法檢測到的邊緣盡可能地是真實的邊緣。
較好地定位邊緣點。由檢測器標記的邊緣點與真實邊緣點中心盡可能地接近。
單一的邊緣響應。圖像中的邊緣只標記出一次。
(2)canny邊緣檢測分為4個部分
1、圖像降噪
圖像去噪是進行邊緣檢測的第一步,通過去噪可以去除圖像中的一些噪點,從而使邊緣檢測時免受噪點干擾。高斯濾波。
2、梯度計算
要進行邊緣檢測,就需要得到圖像梯度信息,根據圖像的梯度幅值和梯度方向來確定邊緣,一般均采用sobel算子對圖像進行梯度幅值與梯度方向計算。
根據得到的這兩幅梯度圖(和)找到邊界的梯度和方向。
3、非極大值抑制NMS(Non-Maximal Suppression)
????????一階微分在灰度值斜坡過渡時不為零且存在較粗的邊緣,較粗的邊緣會增大邊緣檢測的誤差,因此需要細化邊緣,一種較為常用的方法是非極大值抑制.
????????非極大值抑制:即在梯度圖像中尋找梯度方向上的最大值作為邊緣,不是梯度方向上的最大值則抑制為0。因為梯度方向是灰度變化最大的方向。比較梯度圖像中每一點的灰度值與梯度方向上至少兩個梯度圖像像素點灰度值的大小,根據上述大小關系來確定是否保留該點的灰度值。
4、雙閾值邊界跟蹤
雙閾值處理就是根據實際情況需要設置一個灰度高閾值和一個灰度低閾值對NMS后的圖像進行過濾,使得得到的邊緣盡可能是真實的邊緣。
雙閾值的基本處理步驟為:
fH 和 fL 分別表示 大閾值和小閾值, 由用戶設定
????????
若像素點所在的邊緣存在強邊緣像素,則保留,否則置0
(3)參數解釋及代碼
cv.Canny( image, threshold1, threshold2[, apertureSize[, L2gradient]])
image 為輸入圖像。
threshold1 表示處理過程中的第一個閾值。fL
threshold2 表示處理過程中的第二個閾值。fH
zl = cv2.imread('zl.png',cv2.IMREAD_GRAYSCALE)
cv2.imshow('zl',zl)
cv2.waitKey(0)
zl_canny = cv2.Canny(zl,100,150)#低,高
cv2.imshow('zl_canny',zl_canny)
cv2.waitKey(0)
?
總結:canny邊緣檢測的能力較強,使用簡單,其他的邊緣檢測都是基于sobel算子的原理,都需要做處理。