Posted on

圖像處理之圖像金字塔

理論

通常,我們使用尺寸固定的圖像。但在某些情況下,我們需要使用不同分辨率的(相同)圖像。例如,當我們在圖像中搜索物體時,比如人臉,我們並不確定物體出現在圖像中的大小。在這種情況下,我們需要創建一組具有不同分辨率的圖像,並在所有圖像中搜索對象。這些不同分辨率的圖像被稱為圖像金字塔(如果將它們放在一起,最高分辨率的圖像在底部,最低分辨率的圖像在頂部,它看起來像一個金字塔)。

圖像金字塔有兩種:高斯金字塔和拉普拉斯金字塔

高斯金字塔

高斯金字塔的高層(低層)圖像是通過去除低層(高層)圖像中的連續行和列來實現的。再由下一層的5個像素的高斯權值貢獻構成上一層的每個像素。這樣,一個M×N圖像就變成了M/2×N/2圖像。所以面積減少到原來的四分之一。它被稱為Octave。同樣的模式持續到金字塔的上方(即分辨率下降)。同樣地,在擴展過程中,每一層的面積會增加4倍。我們可以使用cv.pyrDown()和cv.pyrUp()函數找到高斯金字塔。

img = cv.imread('messi5.jpg')
lower_reso = cv.pyrDown(higher_reso)

可以使用cv.pyrUp()函數放大圖像

higher_reso2 = cv.pyrUp(lower_reso)

拉普拉斯金字塔

拉普拉斯金字塔是由高斯金字塔形成的。拉普拉斯金字塔圖像就像邊緣圖像。它的大部分元素都是0。它們用於圖像壓縮。拉普拉斯金字塔的層次是由高斯金字塔的這一層次與高斯金字塔上一層次的擴展版之間相減形成的。Laplacian層次的三個層次如下(調整對比度以增強內容):

使用圖像金字塔實現圖像混合

金字塔的一個應用是圖像混合。
例如,在圖像拼接中,你將需要將兩個圖像疊加在一起,但由於圖像之間的不連續性,可能看起來不太好。
在這種情況下,使用金字塔圖像混合可以實現無縫混合,而不會在圖像中留下太多數據。
其中一個經典的例子就是混合兩種水果,橙子和蘋果。
現在看看結果本身來理解我在說什麼:

簡單地說就是這樣做的:
1. 加載蘋果和橘子的兩個圖像
2. 尋找蘋果和橘子的高斯金字塔(在這個例子中,層數是6)
3. 從高斯金字塔,找到他們的拉普拉斯金字塔
4. 現在把蘋果的左半部分和橘子的右半部分加入拉普拉斯金字塔的每一層
5. 最後,從這個聯合圖像金字塔,重建原始圖像。

import cv2 as cv
import numpy as np,sys
A = cv.imread('apple.jpg')
B = cv.imread('orange.jpg')
# generate Gaussian pyramid for A
G = A.copy()
gpA = [G]
for i in range(6):
    G = cv.pyrDown(G)
    gpA.append(G)
# generate Gaussian pyramid for B
G = B.copy()
gpB = [G]
for i in range(6):
    G = cv.pyrDown(G)
    gpB.append(G)
# generate Laplacian Pyramid for A
lpA = [gpA[5]]
for i in range(5,0,-1):
    GE = cv.pyrUp(gpA[i])
    L = cv.subtract(gpA[i-1],GE)
    lpA.append(L)
# generate Laplacian Pyramid for B
lpB = [gpB[5]]
for i in range(5,0,-1):
    GE = cv.pyrUp(gpB[i])
    L = cv.subtract(gpB[i-1],GE)
    lpB.append(L)
# Now add left and right halves of images in each level
LS = []
for la,lb in zip(lpA,lpB):
    rows,cols,dpt = la.shape
    ls = np.hstack((la[:,0:cols/2], lb[:,cols/2:]))
    LS.append(ls)
# now reconstruct
ls_ = LS[0]
for i in range(1,6):
    ls_ = cv.pyrUp(ls_)
    ls_ = cv.add(ls_, LS[i])
# image with direct connecting each half
real = np.hstack((A[:,:cols/2],B[:,cols/2:]))
cv.imwrite('Pyramid_blending2.jpg',ls_)
cv.imwrite('Direct_blending.jpg',real)