1.影像金字塔

為同一影像不同解析度的子圖集合。當透過原影像不斷向下採樣,會由高解析度影像產生低解析度的近似影像。

向下取樣,列數與行數都會是原圖的1/2倍,因此,輸出影像會是原圖的1/4倍。反之,向上取樣,列數與行數都會是原圖的2倍,因此,輸出影像會是原圖的4倍。

向下取樣的結果如下圖:

<source:Greatway9999>

向上取樣的效果如下圖所示:

<source:Greatway9999>


2.取樣可逆性

不論是向下取樣再向上取樣,或是向上取樣再向下取樣,雖然輸出圖像尺寸和原圖一樣,但因在計算過程中,資料會遺失,因此像素值已經不同了。


3.拉普拉斯金字塔

由於向上取樣非向下取樣的逆運算,為了在向上取樣時能恢復原始影像,就要先取得取樣過程中所遺失的資訊。這些遺失的資訊就可以組成拉普拉斯金字塔。

拉普拉斯金字塔第 i 層 = 高斯金字塔第 i 層 - 高斯金字塔第 i + 1 層的向上取樣結果


取樣後要恢復成原圖

高斯金字塔第 i 層 拉普拉斯金字塔第 i 層 + 高斯金字塔第 i + 1 層的向上取樣結果

恢復後的圖與原圖相減,所得像素值應全部為0。


如下圖所示,第一列的圖為高斯金字塔所產生的圖,第二列的圖為各層遺失的資訊所組成的拉普拉斯金字塔,用來恢復原圖所用。

<source:Greatway9999>


4.完整程式

4.1. 影像金字塔

#為同一影像不同解析度的子圖集合。當透過原影像不斷向下採樣,會由高解析度影像產生低解析度的近似影像。

#向下取樣,列數與行數都會是原圖的1/2,因此,輸出影像會是原圖的1/4。

import numpy as np

import cv2

img = cv2.imread('Lenna.jpg')


#向下取樣

d1 = cv2.pyrDown(img)

d2 = cv2.pyrDown(p1)

d3 = cv2.pyrDown(p2)


print('original shape=', img.shape)

print('d1=', d1.shape)

print('d2=', d2.shape)

print('d3=', d3.shape)


cv2.imshow('img', img)

cv2.imshow('d1', d1)

cv2.imshow('d2', d2)

cv2.imshow('d3', d3)


#向上取樣

u1 = cv2.pyrUp(d3)

u2 = cv2.pyrUp(u1)

u3 = cv2.pyrUp(u2)


print('u1=', u1.shape)

print('u2=', u2.shape)

print('u3=', u3.shape)


cv2.imshow('u1', u1)

cv2.imshow('u2', u2)

cv2.imshow('u3', u3)


cv2.waitKey()

cv2.destroyAllWindows()


4.2. 取樣可逆性驗證

#不論是向下取樣再向上取樣,或是向上取樣再向下取樣,雖然輸出圖像尺寸和原圖一樣,但因在計算過程中,資料會遺失,因此像素值已經不同了。


import numpy as np

import cv2

img = cv2.imread('Lenna.jpg', cv2.IMREAD_GRAYSCALE)


img_down_first = cv2.pyrDown(img)

img_up = cv2.pyrUp(img_down_first)

diff_down_first = img_up - img


cv2.imshow('img_down_first', img_down_first)

cv2.imshow('diff_down_first', diff_down_first)


img_up_first = cv2.pyrUp(img)

img_down = cv2.pyrDown(img_up_first)

diff_up_first = img_down - img


cv2.imshow('img_up_first', img_up_first)

cv2.imshow('diff_up_first', diff_up_first)


cv2.waitKey()

cv2.destroyAllWindows()


4.3.拉普拉斯金字塔

#由於向上取樣非向下取樣的逆運算,為了在向上取樣時能恢復原始影像,就要先取得取樣過程中所遺失的資訊。

#這些遺失的資訊就組成拉普拉斯金字塔


#拉普拉斯金字塔第 i 層 = 高斯金字塔第 i 層 + 高斯金字塔第 i + 1 層的向上取樣結果


import numpy as np

import cv2

P0 = cv2.imread('Lenna.jpg') #,cv2.IMREAD_GRAYSCALE

P1 = cv2.pyrDown(P0)

P2 = cv2.pyrDown(P1)


L0 = P0 - cv2.pyrUp(P1)

L1 = P1 - cv2.pyrUp(P2)

print('L0 shape=', L0.shape)

print('L1 shape=', L1.shape)


cv2.imshow('original', img)

cv2.imshow('P1', P1)

cv2.imshow('P2', P2)

cv2.imshow('L0', L0)

cv2.imshow('L1', L1)


recover_P0 = L0 + cv2.pyrUp(P1)

result = recover_P0 - P0

print(abs(result))


cv2.waitKey()

cv2.destroyAllWindows()

---

參考資料:

#影像金字塔 #向上取樣 #向下取樣 #拉普拉斯金字塔

0 留言