您好,登錄后才能下訂單哦!
本文小編為大家詳細(xì)介紹“python中的opencv圖像梯度實例分析”,內(nèi)容詳細(xì),步驟清晰,細(xì)節(jié)處理妥當(dāng),希望這篇“python中的opencv圖像梯度實例分析”文章能幫助大家解決疑惑,下面跟著小編的思路慢慢深入,一起來學(xué)習(xí)新知識吧。
圖像梯度計算的是圖像變化的速度。對于圖像的邊緣部分,其灰度值變化較大,梯度值也較大;相反,對于圖像中比較平滑的部分,其灰度值變化較小,相應(yīng)的梯度值也較小。圖像梯度計算需要求導(dǎo)數(shù),但是圖像梯度一般通過計算像素值的差來得到梯度的近似值(近似導(dǎo)數(shù)值)。(差分,離散)
Sobel算子、Scharr算子和Laplacian算子的使用。
Sobel算子是一種離散的微分算子,該算子結(jié)合了高斯平滑和微分求導(dǎo)運(yùn)算。該算子利用局部差分尋找邊緣,計算所得的是一個梯度的近似值。
濾波器通常是指由一幅圖像根據(jù)像素點(x, y)臨近的區(qū)域計算得到另外一幅新圖像的算法。
濾波器是由鄰域及預(yù)定義的操作構(gòu)成的,濾波器規(guī)定了濾波時所采用的形狀以及該區(qū)域內(nèi)像素值的組成規(guī)律。濾波器也被稱為“掩?!?、“核”、“模板”、“窗口”、“算子”等。一般信號領(lǐng)域?qū)⑵浞Q為“濾波器”,數(shù)學(xué)領(lǐng)域?qū)⑵浞Q為“核”。
線性濾波器: 濾波的目標(biāo)像素點的值等于原始像素值及其周圍像素值的加權(quán)和。這種基于線性核的濾波,就是所熟悉的卷積。
將Sobel算子與原始圖像src進(jìn)行卷積計算,可以計算水平方向上的像素值變化情況。
例如,當(dāng)Sobel算子的大小為3×3時,水平方向偏導(dǎo)數(shù)Gx的計算方式為:
當(dāng)Sobel算子的大小為3×3時,垂直方向偏導(dǎo)數(shù)Gy的計算方式為:
使用函數(shù)cv2.Sobel()實現(xiàn)Sobel算子運(yùn)算,其語法形式為:
dst = cv2.Sobel( src, ddepth, dx, dy[, ksize[, scale[, delta[, borderType]]]] )
dst代表目標(biāo)圖像
src代表原始圖像
ddepth代表輸出圖像的深度
dx代表x方向上的求導(dǎo)階數(shù)。
dy代表y方向上的求導(dǎo)階數(shù)。
ksize代表Sobel核的大小。該值為-1時,則會使用Scharr算子進(jìn)行運(yùn)算。
scale代表計算導(dǎo)數(shù)值時所采用的縮放因子,默認(rèn)情況下該值是1,是沒有縮放的。
delta代表加在目標(biāo)圖像dst上的值,該值是可選的,默認(rèn)為0。
borderType代表邊界樣式。
注意點:參數(shù)ddepth
在函數(shù)cv2.Sobel()的語法中規(guī)定,可以將函數(shù)cv2.Sobel()內(nèi)ddepth參數(shù)的值設(shè)置為-1,讓處理結(jié)果與原始圖像保持一致。但是,如果直接將參數(shù)ddepth的值設(shè)置為-1,在計算時得到的結(jié)果可能是錯誤的。
在實際操作中,計算梯度值可能會出現(xiàn)負(fù)數(shù)。如果處理的圖像是8位圖類型,則在ddepth的參數(shù)值為-1時,意味著指定運(yùn)算結(jié)果也是8位圖類型,那么所有負(fù)數(shù)會自動截斷為0,發(fā)生信息丟失。為了避免信息丟失,在計算時要先使用更高的數(shù)據(jù)類型cv2.CV_64F,再通過取絕對值將其映射為cv2.CV_8U(8位圖)類型。
通常要將函數(shù)cv2.Sobel()內(nèi)參數(shù)ddepth的值設(shè)置為“cv2.CV_64F”。
要將偏導(dǎo)數(shù)取絕對值,以保證偏導(dǎo)數(shù)總能正確地顯示出來。
在OpenCV中,使用函數(shù)cv2.convertScaleAbs()對參數(shù)取絕對值,該函數(shù)的語法格式為:
dst = cv2.convertScaleAbs( src [, alpha[, beta]] )
dst代表處理結(jié)果。
src代表原始圖像。
alpha代表調(diào)節(jié)系數(shù),該值是可選值,默認(rèn)為1。
beta代表調(diào)節(jié)亮度值,該值是默認(rèn)值,默認(rèn)為0。
該函數(shù)的作用是將原始圖像src轉(zhuǎn)換為256色位圖,其可以表示為:
dst=saturate(src*alpha+beta)
式中,saturate()表示計算結(jié)果的最大值是飽和值,例如: 當(dāng)“src*alpha+beta”的值超過255時,其取值為255。
**例子:**使用函數(shù)cv2.convertScaleAbs()對一個隨機(jī)數(shù)組取絕對值。
import cv2 import numpy as np img=np.random.randint(-256,256, size=[4,5], dtype=np.int16) rst=cv2.convertScaleAbs(img) print("img=\n", img) print("rst=\n", rst)
在函數(shù)cv2.Sobel()中,參數(shù)dx表示x軸方向的求導(dǎo)階數(shù),參數(shù)dy表示y軸方向的求導(dǎo)階數(shù)。參數(shù)dx和dy通常的值為0或者1,最大值為2。
如果是0,表示在該方向上沒有求導(dǎo)。當(dāng)然,參數(shù)dx和參數(shù)dy的值不能同時為0。
參數(shù)dx和參數(shù)dy可以有多種形式的組合,主要包含:
計算x方向邊緣(梯度):dx=0, dy=1。
計算y方向邊緣(梯度):dx=1, dy=0。
參數(shù)dx與參數(shù)dy的值均為1:dx=1, dy=1。
計算x方向和y方向的邊緣疊加:通過組合方式實現(xiàn)。
例子
“dx=1, dy=0”。當(dāng)然,也可以設(shè)置為“dx=2, dy=0”。此時,會僅僅獲取垂直方向的邊緣信息,此時的語法格式為:
dst = cv2.Sobel( src , ddepth , 1 , 0 )
“dx=0, dy=1”。當(dāng)然,也可以設(shè)置為“dx=0, dy=2”。此時,會僅僅獲取水平方向的邊緣信息,此時的語法格式為:
dst = cv2.Sobel( src , ddepth , 0 , 1 )
“dx=1, dy=1”,也可以設(shè)置為“dx=2, dy=2”,或者兩個參數(shù)都不為零的其他情況。此時,會獲取兩個方向的邊緣信息,此時的語法格式為:
dst = cv2.Sobel( src , ddepth , 1 , 1 )
如果想獲取x方向和y方向的邊緣疊加,需要分別獲取水平方向、垂直方向兩個方向的邊緣圖,然后將二者相加。
dx= cv2.Sobel( src , ddepth , 1 , 0 ) dy= cv2.Sobel( src , ddepth , 0 , 1 ) dst=cv2.addWeighted( src1 , alpha , src2 , beta , gamma )
例子:
使用函數(shù)cv2.Sobel()獲取圖像水平方向的完整邊緣信息
將參數(shù)ddepth的值設(shè)置為cv2.CV_64F,并使用函數(shù)cv2.convertScaleAbs()對cv2.Sobel()的計算結(jié)果取絕對值。
import cv2 o = cv2.imread('Sobel4.bmp', cv2.IMREAD_GRAYSCALE) Sobelx = cv2.Sobel(o, cv2.CV_64F,0,1) Sobelx = cv2.convertScaleAbs(Sobelx) cv2.imshow("original", o) cv2.imshow("x", Sobelx) cv2.waitKey() cv2.destroyAllWindows()
計算函數(shù)cv2.Sobel()在水平、垂直兩個方向疊加的邊緣信息。
import cv2 o = cv2.imread('Sobel4.bmp', cv2.IMREAD_GRAYSCALE) Sobelx = cv2.Sobel(o, cv2.CV_64F,1,0) Sobely = cv2.Sobel(o, cv2.CV_64F,0,1) Sobelx = cv2.convertScaleAbs(Sobelx) Sobely = cv2.convertScaleAbs(Sobely) Sobelxy = cv2.addWeighted(Sobelx,0.5, Sobely,0.5,0) cv2.imshow("original", o) cv2.imshow("xy", Sobelxy) cv2.waitKey() cv2.destroyAllWindows()
在離散的空間上,有很多方法可以用來計算近似導(dǎo)數(shù),在使用3×3的Sobel算子時,可能計算結(jié)果并不太精準(zhǔn)。
OpenCV提供了Scharr算子,該算子具有和Sobel算子同樣的速度,且精度更高。
可以將Scharr算子看作對Sobel算子的改進(jìn),其核通常為:
OpenCV提供了函數(shù)cv2.Scharr()來計算Scharr算子,其語法格式如下:
dst = cv2.Scharr( src, ddepth, dx, dy[, scale[, delta[, borderType]]] )
dst代表輸出圖像。
src代表原始圖像。
ddepth代表輸出圖像深度。該值與函數(shù)cv2.Sobel()中的參數(shù)ddepth的含義相同
dx代表x方向上的導(dǎo)數(shù)階數(shù)。
dy代表y方向上的導(dǎo)數(shù)階數(shù)。
scale代表計算導(dǎo)數(shù)值時的縮放因子,該項是可選項,默認(rèn)值是1,表示沒有縮放。
delta代表加到目標(biāo)圖像上的亮度值,該項是可選項,默認(rèn)值為0。
borderType代表邊界樣式。
在函數(shù)cv2.Sobel()中,如果ksize=-1,則會使用Scharr濾波器。
如下語句:
dst=cv2.Scharr(src, ddepth, dx, dy)
和
dst=cv2.Sobel(src, ddepth, dx, dy, -1)
是等價的。函數(shù)cv2.Scharr()和函數(shù)cv2.Sobel()的使用方式基本一致。參數(shù)ddepth的值應(yīng)該設(shè)置為“cv2.CV_64F”,并對函數(shù)cv2.Scharr()的計算結(jié)果取絕對值,才能保證得到正確的處理結(jié)果。
具體語句為:
dst=Scharr(src, cv2.CV_64F, dx, dy) dst= cv2.convertScaleAbs(dst)
在函數(shù)cv2.Scharr()中,要求參數(shù)dx和dy滿足條件:
dx >= 0 && dy >= 0 && dx+dy == 1
和Sobel 不同, Scharr 的dx+dy 必須為1
參數(shù)dx和參數(shù)dy的組合形式有:
計算x方向邊緣(梯度):dx=0, dy=1。
計算y方向邊緣(梯度): dx=1, dy=0。
計算x方向與y方向的邊緣疊加:通過組合方式實現(xiàn)。
例子
計算x方向邊緣(梯度):dx=1, dy=0
dst=Scharr(src, ddpeth, dx=1, dy=0)
計算y方向邊緣(梯度):dx=0, dy=1
dst=Scharr(src, ddpeth, dx=0, dy=1)
計算x方向與y方向的邊緣疊加
將兩個方向的邊緣相加
dx=Scharr(src, ddpeth, dx=1, dy=0) dy=Scharr(src, ddpeth, dx=0, dy=1) Scharrxy=cv2.addWeighted(dx,0.5, dy,0.5,0)
參數(shù)dx和dy的值不能都為1
Sobel算子的缺點是,當(dāng)其核結(jié)構(gòu)較小時,精確度不高,而Scharr算子具有更高的精度。
Sobel算子和Scharr算子的核結(jié)構(gòu):
Laplacian(拉普拉斯)算子是一種二階導(dǎo)數(shù)算子,其具有旋轉(zhuǎn)不變性,可以滿足不同方向的圖像邊緣銳化(邊緣檢測)的要求。
通常情況下,其算子的系數(shù)之和需要為零。
一個3×3大小的Laplacian算子
Laplacian算子類似二階Sobel導(dǎo)數(shù),需要計算兩個方向的梯度值。
計算結(jié)果的值可能為正數(shù),也可能為負(fù)數(shù)。所以,需要對計算結(jié)果取絕對值,以保證后續(xù)運(yùn)算和顯示都是正確的。
在OpenCV內(nèi)使用函數(shù)cv2.Laplacian()實現(xiàn)Laplacian算子的計算,該函數(shù)的語法格式為:
dst = cv2.Laplacian( src, ddepth[, ksize[, scale[, delta[, borderType]]]] )
dst代表目標(biāo)圖像。
src代表原始圖像。
ddepth代表目標(biāo)圖像的深度。
ksize代表用于計算二階導(dǎo)數(shù)的核尺寸大小。該值必須是正的奇數(shù)。
scale代表計算Laplacian值的縮放比例因子,該參數(shù)是可選的。默認(rèn)情況下,該值為1,表示不進(jìn)行縮放。
delta代表加到目標(biāo)圖像上的可選值,默認(rèn)為0。
borderType代表邊界樣式。
該函數(shù)分別對x、y方向進(jìn)行二次求導(dǎo),具體為:
上式是當(dāng)ksize的值大于1時的情況。當(dāng)ksize的值為1時,Laplacian算子計算時采用的3×3的核如下:
通過從圖像內(nèi)減去它的Laplacian圖像,可以增強(qiáng)圖像的對比度,此時其算子為:
例子: 使用函數(shù)cv2.Laplacian()計算圖像的邊緣信息。
import cv2 o = cv2.imread('Laplacian.bmp', cv2.IMREAD_GRAYSCALE) Laplacian = cv2.Laplacian(o, cv2.CV_64F) Laplacian = cv2.convertScaleAbs(Laplacian) cv2.imshow("original", o) cv2.imshow("Laplacian", Laplacian) cv2.waitKey() cv2.destroyAllWindows()
Sobel算子、Scharr算子、Laplacian算子都可以用作邊緣檢測
Sobel算子和Scharr算子計算的都是一階近似導(dǎo)數(shù)的值。通常情況下,可以將它們表示為:
Sobel算子= |左-右| 或 |下-上|
Scharr算子=|左-右| 或 |下-上|
Laplacian算子計算的是二階近似導(dǎo)數(shù)值,可以將它表示為:
Laplacian算子=|中-左| + |中-右| + |中-下| + |中-上|
讀到這里,這篇“python中的opencv圖像梯度實例分析”文章已經(jīng)介紹完畢,想要掌握這篇文章的知識點還需要大家自己動手實踐使用過才能領(lǐng)會,如果想了解更多相關(guān)內(nèi)容的文章,歡迎關(guān)注億速云行業(yè)資訊頻道。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。