1.原理
一般情況下,我們要處理是一副具有固定分辨率的圖像。但是特別情況下我們需要對同一個圖像的不同分辨率的子圖像進行處理,如查找圖像中的某個目標,如人臉,我們不知道目標在圖像中的尺寸大小。這種情況下,我們需要創建一組圖像,這些圖像是具有不同分辨率的原始圖像。我們把這組圖像叫做圖像金字塔。就是同一圖像的不同分辨率的子圖集合。我們把最大的圖像放在底部,最小的放在頂部,看起來就像一座金字塔。
金字塔常見的有兩類:高斯金字塔和拉普拉斯金字塔。
1.1高斯金字塔
高斯金字塔的頂部是通過將底部圖像中的連續的行和列去除得到的。頂部圖像中的每個像素值等於下一層圖像中5個像素的高斯加權平均值。這樣操作一次一個MxN的圖像就變成了一個M/2xN/2的圖像。所以這幅圖像的面積就變爲原來圖像面積的四分之一。這被稱爲Octave。連續這樣的操作,我們就會得到一個分辨率不斷下降的圖像金字塔。可以使用函數cv2.pyrDown()和cv2.pyrUp()構建圖像金字塔。
cv2.pyrDown從一個高分辨率大尺寸的圖像向上構建一個金字塔(尺寸變小,分辨率降低)
cv2.U拍從一個小尺寸的圖像向上構建一個金字塔(尺寸變大,總體分辨率不變,但因爲總體變大了,所以看上去分辨率還是降低的。)
import numpy as np
import cv2
img = cv2.imread('1024.jpg')
lower_reso = cv2.pyrDown(img)
while(1):
cv2.imshow('img',img)
cv2.imshow('lower_reso',lower_reso)
if cv2.waitKey() == ord('q'):
break
cv2.destroyAllWindows()
cv2.pyrUp從一個低分辨率小尺寸的圖像向上構建一個金字塔(尺寸變大,但分辨率不會增加)
import numpy as np
import cv2
img = cv2.imread('1024.jpg')
lower_reso = cv2.pyrDown(img)
higher_reso2 = cv2.pyrUp(img)
while(1):
cv2.imshow('img',img)
cv2.imshow('lower_reso',lower_reso)
cv2.imshow('higher_reso2',higher_reso2)
if cv2.waitKey() == ord('q'):
break
cv2.destroyAllWindows()
要記住的是higher_reso2和higher_reso 是不同的。因爲一旦使用cv2.pyrDown圖像的分辨率就會降低,信息就會被丟失。而拉普拉斯金字塔的作用就是在於他能夠在一定程度上恢復信息的丟失。
1.2.拉普拉斯金字塔
拉普拉斯金字塔可以由高斯金字塔計算得來。公式如下:
公示解讀:第i層的拉普拉斯金字塔式是原本的第i+1層的圖層經過PyrUp函數變大後,將其與原圖中的第i層進行做差得到。得到的也就是信息丟失的部分邊界。
拉普拉斯金字塔的圖像看起來就像是邊界圖,其中很多像素都是0,常被用在圖像壓縮中。
2.使用金字塔進行圖像融合
在圖像縫合中,由於連接區域圖像像素的不連續,整幅圖看起來會很差,金字塔就可以實現無縫連接。
經典例子就是水果融合
實現步驟:
·讀入兩幅圖
·構建各自的高斯金字塔(6層)
·根據高斯金字塔計算拉普拉斯金字塔
·在拉普拉斯的每一層進行圖像融合
·根據融合後的圖像金字塔重建原始圖像。
·如何重建原始圖像過程
示例代碼:
import cv2
#高斯金字塔
def pyramid_demo(image):
level = 3 #設置金字塔的層數爲3
temp = image.copy() #拷貝圖像
pyramid_images = [] #建立一個空列表
for i in range(level):
dst = cv2.pyrDown(temp) #先對圖像進行高斯平滑,然後再進行降採樣(將圖像尺寸行和列方向縮減一半)
pyramid_images.append(dst) #在列表末尾添加新的對象
cv2.imshow("pyramid"+str(i), 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 = cv2.pyrUp(pyramid_images[i], dstsize = image.shape[:2])
lpls = cv2.subtract(image, expand)
cv2.imshow("lapalian_down_"+str(i), lpls)
else:
expand = cv.pyrUp(pyramid_images[i], dstsize = pyramid_images[i-1].shape[:2])
lpls = cv.subtract(pyramid_images[i-1], expand)
cv2.imshow("lapalian_down_"+str(i), lpls)
src = cv2.imread('E:/imageload/zixia.jpg')
cv2.namedWindow('input_image', cv.WINDOW_AUTOSIZE) #設置爲WINDOW_NORMAL可以任意縮放
cv2.imshow('input_image', src)
lapalian_demo(src)
cv2.waitKey(0)
cv2.destroyAllWindows()
示例圖:
注意:使用拉普拉斯金字塔的時候,圖像大小一定要是(2^m, 2^n)的形式!不然代碼會報錯
總結:
(本系列每週不定期更新,謝謝大家的支持!)