[OpenCV筆記] 9. 影像金字塔實作
1.影像金字塔
為同一影像不同解析度的子圖集合。當透過原影像不斷向下採樣,會由高解析度影像產生低解析度的近似影像。
向下取樣,列數與行數都會是原圖的1/2倍,因此,輸出影像會是原圖的1/4倍。反之,向上取樣,列數與行數都會是原圖的2倍,因此,輸出影像會是原圖的4倍。
向下取樣的結果如下圖:
向上取樣的效果如下圖所示:
<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 留言