圖像金字塔實現圖像融合(基於opencv-python)

圖像金字塔介紹

  • 圖像金字塔是多尺度表達的一種,是一種以多分辨率來解釋圖像的有效但概念簡單的結構。。一幅圖像的金字塔是一系列以金字塔形狀排列的分辨率逐漸降低並且來源於同一張原始圖像的集合。通過梯次向下採樣獲得,直到某個終止條件才停止採樣。
  • 圖像金字塔說白了就是披着金字塔外衣的圖像縮放。一般有高斯圖像金字塔、拉普拉斯圖像金字塔。

兩種金字塔介紹

高斯金字塔(低通)

高斯金字塔:用於下采樣。高斯金字塔是最基本的圖像塔。
原理:首先將原圖像作爲最底層圖像G0(高斯金字塔的第0層),利用高斯核(5*5)對其進行卷積(高斯平滑),然後對卷積後的圖像進行下采樣(去除偶數行和列)得到上一層圖像G1,將此圖像作爲輸入,重複卷積和下采樣操作得到更上一層圖像,反覆迭代多次,形成一個金字塔形的圖像數據結構,即高斯金字塔

由於上採樣和下采樣是非線性處理,是不可逆的有損處理,因此下采樣後的圖像想要還原回原來的尺寸的話會丟失很多信息,使圖片變模糊。
                在這裏插入圖片描述
上圖就是使用高斯金字塔之後的結果。

拉普拉斯金字塔(帶通金字塔)

拉普拉斯金字塔:用於重建圖像,也就是預測殘差,對圖像進行最大程度的還原
一幅小圖像重建爲一幅大圖原理:用高斯金字塔的每一層圖像減去其上一層圖像上採樣並高斯卷積之後的預測圖像,得到一系列的差值圖像即爲 LP 分解圖像。

拉普拉斯金字塔實際上是通過計算圖片先下采樣再上採樣後的結果和原圖片的殘差來保存缺失信息的,公式爲:L(i)=G(i)PyrUp(G(i+1)) L(i) = G(i) - PyrUp(G(i + 1))
也就是說,拉普拉斯金字塔實際上是由上面的殘差圖片組成的金字塔,它爲還原圖片做準備
求得每個圖像的拉普拉斯金字塔後需要對相應層次的圖像進行融合,最終還原圖像。
拉普拉斯金字塔可以精確還原圖片信息。
還原圖像的過程就是重構的過程。在這裏插入圖片描述
上圖能夠比較好的理解拉普拉斯金字塔的計算過程。

圖像金字塔應用

圖像金字塔非常重要的一個應用就是實現圖像分割。圖像分割的話,先要建立一個圖像金字塔,然後在Gi和Gi+1的像素直接依照對應的關係,建立起”父與子“關係。而快速初始分割可以先在金字塔高層的低分辨率圖像上完成,然後逐層對分割加以優化。

實例1 高斯金字塔和拉普拉斯金字塔顯示:

代碼:

import cv2 as cv
#高斯金字塔
def pyramid_demo(image):
    level = 3      #設置金字塔的層數爲3
    temp = image.copy()  #拷貝圖像
    pyramid_images = []  #建立一個空列表
    for i in range(level):
        dst = cv.pyrDown(temp)   #先對圖像進行高斯平滑,然後再進行降採樣(將圖像尺寸行和列方向縮減一半)
        pyramid_images.append(dst)  #在列表末尾添加新的對象
        cv.imshow("pyramid"+str(i+1), dst)
        temp = dst.copy()
    return pyramid_images
#拉普拉斯金字塔
def lapalian_demo(image):
    pyramid_images = pyramid_demo(image)    #做拉普拉斯金字塔必須用到高斯金字塔的結果
    level = len(pyramid_images)
    for i in range(level-1, -1, -1):
        if (i-1) < 0:
            expand = cv.pyrUp(pyramid_images[i], dstsize = image.shape[:2])
            lpls = cv.subtract(image, expand)
            cv.imshow("lapalian_down_"+str(i+1), lpls)
        else:
            expand = cv.pyrUp(pyramid_images[i], dstsize = pyramid_images[i-1].shape[:2])
            lpls = cv.subtract(pyramid_images[i-1], expand)
            cv.imshow("lapalian_down_"+str(i+1), lpls)
src = cv.imread('F:/test.jpg')
cv.namedWindow('input_image') #設置爲WINDOW_NORMAL可以任意縮放
cv.imshow('input_image', src)
lapalian_demo(src)
cv.waitKey(0)
cv.destroyAllWindows()

顯示結果:
高斯金字塔:
在這裏插入圖片描述
拉普拉斯金字塔:
在這裏插入圖片描述

融合

圖像融合的目的就是使兩幅圖像的重疊區域過渡自然且平滑。
常見融合方法:

  • 1)加權平均法。這個很好理解,即簡單的使用加權的方式從左邊過渡到右邊。這種方法效果一般,但算法實現極其簡單,速度快。
  • 2)羽化算法 。這種方法過渡會比加權平均法自然,但會造成不好的模糊效果。
  • 3)拉普拉斯金字塔融合。有的地方也稱爲多分辨率融合算法。這種方法是將圖像建立一個拉普拉斯金字塔,其中金字塔的每一層都包含了圖像不同的頻段。分開不同頻段進行融合效果出奇的好。

圖像拉普拉斯金字塔分解的目的是將源圖像分別分解到不同的空間頻帶上,融合過程是在各空間頻率層上分別進行的,這樣就可以針對不同分解層的不同頻帶上的特徵與細節,採用不同的融合算子以達到突出特定頻帶上特徵與細節的目的。即有可能將來自不同圖像的特徵與細節融合在一起。

實例2:利用拉普拉斯金字塔實現融合

代碼:

import cv2
import numpy as np,sys
A = cv2.imread('F:/ninny.jpg')
B = cv2.imread('F:/nero.jpg')
# generate Gaussian pyramid for A
G = A.copy()
gpA = [G]
for i in range(6):
    G = cv2.pyrDown(G)
    gpA.append(G)
# generate Gaussian pyramid for B
G = B.copy()
gpB = [G]
for i in range(6):
    G = cv2.pyrDown(G)
    gpB.append(G)
# generate Laplacian Pyramid for A
lpA = [gpA[5]]
for i in range(5,0,-1):
    GE = cv2.pyrUp(gpA[i])
    L = cv2.subtract(gpA[i-1],GE)
    lpA.append(L)
# generate Laplacian Pyramid for B
lpB = [gpB[5]]
for i in range(5,0,-1):
    GE = cv2.pyrUp(gpB[i])
    L = cv2.subtract(gpB[i-1],GE)
    lpB.append(L)
# Now add left and right halves of images in each level
#numpy.hstack(tup)
#Take a sequence of arrays and stack them horizontally
#to make a single array.
LS = []
for la,lb in zip(lpA,lpB):
    rows,cols,dpt = la.shape

    ls = np.hstack((la[:,:cols//2], lb[:,cols//2:]))
    # ls = np.hstack((la[:, :cols // 4], lb[:, cols // 4: cols//2], la[:, cols//2:3 * cols//4], lb[:, 3*cols//4: ]))
    LS.append(ls)
# now reconstruct
ls_ = LS[0]
for i in range(1,6):
    ls_ = cv2.pyrUp(ls_)
    ls_ = cv2.add(ls_, LS[i])
# image with direct connecting each half
real = np.hstack((A[:,:cols//2],B[:,cols//2:]))
# real = np.hstack((A[:,:cols//4],B[:,cols//4: cols//2], A[:, cols//2: 3*cols//4], B[:, 3*cols//4: ]))
cv2.imwrite('F:/ninny_nero.jpg',ls_)
cv2.imwrite('F:/nini_chaochao.jpg',real)

結果:
使用拉普拉斯融合後的圖片:

在這裏插入圖片描述
直接拼接的照片:

在這裏插入圖片描述

問題和解決:

  • 金字塔輸入的圖像大小必須是2的n次方。
  • 調試程序的時候遇到這個報錯:
File "H:/pycharm_pro/pyramid/pyr.py", line 39, in <module>
    ls = np.hstack((la[:, :cols / 4], lb[:, cols // 4: cols//2], la[:, cols//2:3 * cols//4], lb[:, 3*cols//4: ]))
TypeError: slice indices must be integers or None or have an __index__ method

因爲單純的使用除法得到的可能不是整數,但是在索引過程中必須要使用整數索引,所以只取整數部分即可。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章