1. 程式人生 > 其它 >OpenCV-Python系列之影象金字塔

OpenCV-Python系列之影象金字塔

在上一個教程中,我們談到了關於影象Canny邊緣檢測運算元,同時也是OpenCV中應用最為廣泛的邊緣檢測演算法。

現在我們來談談影象金字塔,它的本質是對影象進行放縮變換。一般情況下,我們要處理是一副具有固定解析度的影象。但是有些情況下,我們需要對同一影象的不同解析度的子影象進行處理。比如,我們要在一幅影象中查詢某個目標,比如臉,我們不知道目標在影象中的尺寸大小。這種情況下,我們需要建立一組影象,這些影象是具有不同解析度的原始影象。我們把這組影象叫做影象金字塔(簡單來說就是同一影象的不同解析度的子圖集合)。如果我們把最大的影象放在底部,最小的放在頂部,看起來像一座金字塔,故而得名影象金字塔。

影象金字塔最初用於機器視覺和影象壓縮,一幅影象的金字塔是一系列以金字塔形狀排列的解析度逐步降低,且來源於同一張原始圖的影象集合。其通過梯次向下取樣獲得,直到達到某個終止條件才停止取樣。金字塔的底部是待處理影象的高解析度表示,而頂部是低解析度的近似。我們將一層一層的影象比喻成金字塔,層級越高,則影象越小,解析度越低。

有兩類影象金字塔:高斯金字塔和拉普拉斯金字塔:

高斯金字塔(Gaussianpyramid): 用來向下取樣,主要的影象金字塔

拉普拉斯金字塔(Laplacianpyramid): 用來從金字塔低層影象重建上層未取樣影象,在數字影象處理中也即是預測殘差,可以對影象進行最大程度的還原,配合高斯金字塔一起使用。

兩者的簡要區別:高斯金字塔用來向下降取樣影象,而拉普拉斯金字塔則用來從金字塔底層影象中向上取樣重建一個影象。要從金字塔第i層生成第i+1層(我們表示第i+1層為G_i+1),我們先要用高斯核對G_1進行卷積,然後刪除所有偶數行和偶數列。當然的是,新得到影象面積會變為源影象的四分之一。按上述過程對輸入影象G_0執行操作就可產生出整個金字塔。

  當影象向金字塔的上層移動時,尺寸和解析度就降低。OpenCV中,從金字塔中上一級影象生成下一級影象的可以用PryDown。而通過PryUp將現有的影象在每個維度都放大兩遍。

影象金字塔中的向上和向下取樣分別通過OpenCV函式 pyrUp 和 pyrDown 實現。

對影象向上取樣:pyrUp函式

對影象向下取樣:pyrDown函式

這裡的向下與向上取樣,是對影象的尺寸而言的(和金字塔的方向相反),向上就是影象尺寸加倍,向下就是影象尺寸減半。而如果我們按上圖中演示的金字塔方向來理解,金字塔向上影象其實在縮小,這樣剛好是反過來了。

但需要注意的是,PryUp和PryDown不是互逆的,即PryUp不是降取樣的逆操作。這種情況下,影象首先在每個維度上擴大為原來的兩倍,新增的行(偶數行)以0填充。然後給指定的濾波器進行卷積(實際上是一個在每個維度都擴大為原來兩倍的過濾器)去估計“丟失”畫素的近似值。

PryDown( )是一個會丟失資訊的函式。為了恢復原來更高的解析度的影象,我們要獲得由降取樣操作丟失的資訊,這些資料就和拉普拉斯金字塔有關係了。

高斯金字塔

高斯金字塔是通過高斯平滑和亞取樣獲得一些列下采樣影象,也就是說第K層高斯金字塔通過平滑、亞取樣就可以獲得K+1層高斯影象,高斯金字塔包含了一系列低通濾波器,其截至頻率從上一層到下一層是以因子2逐漸增加,所以高斯金字塔可以跨越很大的頻率範圍。金字塔的影象如下:

另外,每一層都按從下到上的次序編號,層級 G_i+1 (表示為 G_i+1尺寸小於第i層G_i)。

(1)對影象的向下取樣

為了獲取層級為 G_i+1 的金字塔影象,我們採用如下方法:

1、對影象G_i進行高斯核心卷積

2、將所有偶數行和列去除

得到的影象即為G_i+1的影象,顯而易見,結果影象只有原圖的四分之一。通過對輸入影象G_i(原始影象)不停迭代以上步驟就會得到整個金字塔。同時我們也可以看到,向下取樣會逐漸丟失影象的資訊。以上就是對影象的向下取樣操作,即縮小影象。

我們來看函式原型:

cv2. pyrDown (src, dst=None, dstsize=None, borderType=None)

引數含義:

src:表示輸入影象

dst:表示輸出影象

dstsize:表示輸出影象的大小

borderType:表示影象邊界的處理方式

我們來看原始碼:

import cv2
import numpy as np

img = cv2.imread("cat.jpg")
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
dst = cv2.pyrDown(img)
cv2.imshow("img",img)
cv2.imshow("res",dst)

cv2.waitKey(0)
cv2.destroyAllWindows()

(2)對影象的向上取樣

同樣的,我們來看函式原型:

cv2. pyrUp (src, dst=None, dstsize=None, borderType=None)

引數含義:

src:表示輸入影象

dst:表示輸出影象

dstsize:表示輸出影象的大小

borderType:表示影象邊界的處理方式

直接來看程式碼:

import cv2
import numpy as np

img = cv2.imread("cat.jpg")
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
dst = cv2.pyrUp(img)
cv2.imshow("img",img)
cv2.imshow("res",dst)

cv2.waitKey(0)
cv2.destroyAllWindows()

具體的效果大家可以自己實驗。

拉普拉斯金字塔

與其說是拉普拉斯金字塔,不如叫做殘差金字塔。因為我們剛剛不是說了嗎,影象的降取樣和上取樣不是可逆的。那麼拉普拉斯金字塔的構建方法如下:

假設高斯金字塔就 3 個 level(0, 1,2),那麼,我們先把高斯金字塔的最高層(最小的那個)上取樣(放大)。我們知道,上取樣之後和原金字塔第 1 個 level相比是有資訊丟失的,我們就把原高斯金字塔的第 1 個level 的影象和這個經過 第 2 個level 影象上取樣得到的影象相減(第 2 個 level 影象上取樣之後就和原高斯金字塔第 1 個 level 影象的大小一樣了),相減就會得到一個殘差,這就是拉普拉斯金字塔的最高階(下圖中就應該是 level 1)。

同樣地,把原高斯金字塔的 level 0 的影象 和 原高斯金字塔 level 1 經過上取樣得到的影象相減,就得到了拉普拉斯金字塔的第 0 層。至此,下圖所示的拉普拉斯金字塔就構建完畢了。

值得注意的是:如果一幅影象的高斯金字塔有 N+1 層,那麼其對應的拉普拉斯金字塔就有 N 層。

拉普拉斯金字塔的整個計算過程如上圖所示:

1.左上角的圖片為原始圖片

2.對原始影象進行高斯平滑

3.執行一次下采樣,影象變為原來的1/4

4.執行一次上取樣,影象變為原圖的大小

5.再次執行高斯模糊

6.用原影象減去高斯模糊後的影象,得到拉普拉斯影象

我們來看程式碼實戰:

import cv2
import numpy as np

img = cv2.imread("cat.jpg")
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
down = cv2.pyrDown(img)
dst = cv2.pyrUp(down)
res = img - dst
cv2.imshow("img",img)
cv2.imshow("res",res)

cv2.waitKey(0)
cv2.destroyAllWindows()

影象金字塔實際上是有著很大的用途的,包括影象融合,但這些我們將在後面的專案實戰中介紹到。

天道酬勤 循序漸進 技壓群雄