歡迎光臨
每天分享高質量文章

乾貨 | 用Python做影象處理:影象導數實戰

導讀:數量龐大的影象和影片充斥著我們的生活。我們需要對圖片進行檢索、分類等操作時,利用人工手段顯然是不現實的。於是,計算機視覺相關技術便應運而生,並且得到了快速的發展。本文以時下最流行的Python語言為工具,對影象處理技術的具體操作進行詳細講述,旨在讓零基礎的讀者也可以輕鬆上手!

01 SciPy

SciPy是建立在NumPy基礎上,用於數值運算的開源工具包。SciPy提供很多高效的操作,可以實現數值積分、最佳化、統計、訊號處理,以及對我們來說最重要的影象處理功能。接下來,本節會介紹SciPy中大量有用的模組。SciPy是一個開源工具包,可以從http://scipy.org/Download 下載。

02 影象導數

在整個影象處理的學習過程中可以看到,在很多應用中影象強度的變化情況是非常重要的資訊。強度的變化可以用灰度影象I(對於彩色影象,通常對每個顏色通道分別計算導數)的x和y的方嚮導數進行描述。

影象的梯度向量為:


梯度有兩個重要的屬性,一個是梯度的大小:


它描述了影象變化的強弱,一是梯度的角度:


它描述了影象中在每個點(畫素)上強度變化最大的方向。NumPy中的arctan2()函式傳回弧度表示的有符號角度,角度的變化區間為

我們可以用離散近似的方式來計算影象的導數。影象的導數大多可以透過摺積簡單地實現:


對於,通常選擇Prewitt濾波器:


Prewitt邊緣運算元是一種邊緣樣板運算元,利用畫素點上下,左右鄰點灰度差,在邊緣處達到極值檢測邊緣,對噪聲具有平滑作用。由於邊緣點畫素的灰度值與其領域點畫素的灰度值有顯著不同,在實際應用中通常採用微分運算元和模板配匹方法檢測影象的邊緣。

或者使用Sobel濾波器,Sobel演演算法是一種較成熟的微分邊緣檢測演演算法,它計算簡單,且能產生較好的檢測效果,對噪聲具有平滑作用,可以提供較為精確的邊緣方向資訊。


Sobel運算元是一階導數的邊緣檢測運算元,使用兩個方向運算元(垂直運算元和水平運算元),對影象進行摺積運算,得到兩個矩陣,再求這兩個矩陣對應位置的兩個數的均方根,得到一個新的矩陣,即為灰度影象矩陣中各個畫素點的梯度值。在演演算法實現過程中,透過3×3模板作為核與影象中的每個畫素點做摺積和運算,然後選取合適的閾值以提取邊緣。

其實影象的梯度可以用一階導數和二階偏導數來求解。但是影象以矩陣的形式儲存的,不能像數學理論中對直線或者曲線求導一樣,對一幅影象的求導相當於對一個平面、曲面求導。對影象的操作,我們採用模板對原影象進行摺積運算,從而達到我們想要的效果。而獲取一幅影象的梯度就轉化為:模板(Roberts、Prewitt、Sobel、Lapacian運算元)對原影象進行摺積,不過這裡的模板並不是隨便設計的,而是根據數學中求導理論推匯出來的。

這些導數濾波器可以使用scipy.ndimage.filters模組的標準摺積操作來簡單地實現。

程式碼為:


PIL Image
numpy *
matplotlib.pyplot plt
scipy.ndimage filters

im = array(Image.open().convert())

imx = zeros(im.shape)
filters.sobel(imimx)

imy = zeros(im.shape)
filters.sobel(imimx)

magnitude = sqrt(imx ** + imy ** )

fig = plt.figure(=())

plt.subplot()
plt.axis()
plt.imshow(implt.cm.gray)

plt.subplot()
plt.axis()
plt.imshow(imxplt.cm.gray)

plt.subplot()
plt.axis()
plt.imshow(imyplt.cm.gray)

plt.subplot()
plt.axis()
plt.imshow(magnitudeplt.cm.gray)

plt.show()

輸出結果為:

▲上述輸出結果分別是原始灰度影象、x導數影象、y導數影象、梯度大小影象

這種計算影象導數的方法有一些缺陷,在該方法中,濾波器的尺度需要隨著影象解析度的變化而變化。為了在影象噪聲方面更穩健,以及在任意尺度上計算導數,我們使用高斯導數濾波器:


其中表示在x和y方向上的導數,為標準差為σ的高斯函式。

我們之前用於模糊的filters.gaussian_filter()函式可以接受額外的引數,用來計算高斯導數。可以簡單的按照下麵的方式來處理:

PIL Image
numpy *
matplotlib.pyplot plt
scipy.ndimage filters

im = array(Image.open().convert())

sigma = imx = zeros(im.shape)
filters.gaussian_filter(im(sigmasigma)()imx)

imy = zeros(im.shape)
filters.gaussian_filter(im(sigmasigma)()imy)

fig = plt.figure(=())

plt.subplot()
plt.axis()
plt.imshow(implt.cm.gray)

plt.subplot()
plt.axis()
plt.imshow(imxplt.cm.gray)

plt.subplot()
plt.axis()
plt.imshow(imyplt.cm.gray)

plt.show()

輸出結果為:

(a)

(b)

上面輸出結果(a)、(b)中圖片依次為:原始灰度影象,x導數影象,y導數影象,而(a),(b)的區別為設定不同的標準差之後的高斯濾波處理影象。

作者:Hui

來源:專知(ID:Quan_Zhuanzhi),關於“用Python做影象處理”的更多圖文,可在專知檢視

參考文獻:

python計算機視覺程式設計:

http://yongyuan.name/pcvwithpython/

推薦閱讀

日本老爺爺堅持17年用Excel作畫,我可能用了假的Excel···

看完此文再不懂區塊鏈算我輸:手把手教你用Python從零開始建立區塊鏈

為什麼要學數學?因為這是一場戰略性的投資

180頁PPT,講解人工智慧技術與產業發展

Q: 關於影象處理,你有哪些想法和經驗?

歡迎留言與大家分享

覺得不錯,請把這篇文章分享給你的朋友

轉載 / 投稿請聯絡:baiyu@hzbook.com

更多精彩文章,請在公眾號後臺點選“歷史文章”檢視

贊(0)

分享創造快樂