目標(biāo)
- 學(xué)習(xí)圖像金字塔
- 使用圖像創(chuàng)建一個(gè)新水果:“橘子蘋果”
- 將要學(xué)習(xí)的函數(shù)有:cv2.pyrUp()卡啰,cv2.pyrDown()静稻。
原理
一般情況下,我們要處理是一副具有固定分辨率的圖像匈辱。但是有些情況下振湾,我們需要對(duì)同一圖像的不同分辨率的子圖像進(jìn)行處理。比如亡脸,我們要在一幅圖像中查找某個(gè)目標(biāo)押搪,比如臉,我們不知道目標(biāo)在圖像中的尺寸大小浅碾。這種情況下大州,我們需要?jiǎng)?chuàng)建創(chuàng)建一組圖像,這些圖像是具有不同分辨率的原始圖像垂谢。我們把這組圖像叫做圖像金字塔(簡單來說就是同一圖像的不同分辨率的子圖集合)厦画。如果我們把最大的圖像放在底部,最小的放在頂部埂陆,看起來像一座金字塔苛白,故而得名圖像金字塔。
有兩類圖像金字塔:高斯金字塔和拉普拉斯金字塔焚虱。
高斯金字塔的頂部是通過將底部圖像中的連續(xù)的行和列去除得到的购裙。頂部圖像中的每個(gè)像素值等于下一層圖像中 5 個(gè)像素的高斯加權(quán)平均值。這樣操作一次一個(gè) MxN 的圖像就變成了一個(gè) M/2xN/2 的圖像鹃栽。所以這幅圖像的面積就變?yōu)樵瓉韴D像面積的四分之一躏率。這被稱為 Octave。連續(xù)進(jìn)行這樣的操作我們就會(huì)得到一個(gè)分辨率不斷下降的圖像金字塔民鼓。我們可以使用函數(shù)cv2.pyrDown() 和 cv2.pyrUp() 構(gòu)建圖像金字塔薇芝。函數(shù) cv2.pyrDown() 從一個(gè)高分辨率大尺寸的圖像向上構(gòu)建一個(gè)金子塔(尺寸變小,分辨率降低)丰嘉。
img = cv2.imread('messi5.jpg')
lower_reso = cv2.pyrDown(higher_reso)
下圖是一個(gè)四層的圖像金字塔夯到。函數(shù) cv2.pyrUp() 從一個(gè)低分辨率小尺寸的圖像向下構(gòu)建一個(gè)金子塔(尺寸變大,但分辨率不會(huì)增加)饮亏。
higher_reso2 = cv2.pyrUp(lower_reso)
你要記住的是是 higher_reso2 和 higher_reso 是不同的耍贾。因?yàn)橐坏┦褂?cv2.pyrDown()阅爽,圖像的分辨率就會(huì)降低,信息就會(huì)被丟失荐开。下圖就是從 cv2.pyrDown() 產(chǎn)生的圖像金字塔的(由下到上)第三層圖像使用函數(shù)cv2.pyrUp() 得到的圖像付翁,與原圖像相比分辨率差了很多。
拉普拉金字塔的圖像看起來就像邊界圖晃听,其中很多像素都是 0百侧。他們經(jīng)常被用在圖像壓縮中。下圖就是一個(gè)三層的拉普拉斯金字塔:
使用金字塔進(jìn)行圖像融合
圖像金字塔的一個(gè)應(yīng)用是圖像融合能扒。例如佣渴,在圖像縫合中,你需要將兩幅圖疊在一起赫粥,但是由于連接區(qū)域圖像像素的不連續(xù)性观话,整幅圖的效果看起來會(huì)很差。這時(shí)圖像金字塔就可以排上用場(chǎng)了越平,他可以幫你實(shí)現(xiàn)無縫連接频蛔。這里的一個(gè)經(jīng)典案例就是將兩個(gè)水果融合成一個(gè),看看下圖也許你就明白我在講什么了秦叛。
你可以通過閱讀后邊的更多資源來了解更多關(guān)于圖像融合晦溪,拉普拉斯金字塔的細(xì)節(jié)。
實(shí)現(xiàn)上述效果的步驟如下:
- 讀入兩幅圖像挣跋,蘋果和句子
- 構(gòu)建蘋果和橘子的高斯金字塔(6 層)
- 根據(jù)高斯金字塔計(jì)算拉普拉斯金字塔
- 在拉普拉斯的每一層進(jìn)行圖像融合(蘋果的左邊與橘子的右邊融合)
-
根據(jù)融合后的圖像金字塔重建原始圖像三圆。
下圖是摘自《學(xué)習(xí) OpenCV》展示了金子塔的構(gòu)建,以及如何從金字塔重建原始圖像的過程避咆。
image.png
整個(gè)過程的代碼如下舟肉。(為了簡單,每一步都是獨(dú)立完成的查库,這回消耗更多的內(nèi)存路媚,如果你愿意的話可以對(duì)他進(jìn)行優(yōu)化)
-
import cv2
import numpy as np,sys
img1 = cv2.imread('D:/PYCHARM_WORK/cv/cv_detection/project/guandao_angle_detection/sample1.jpg')
A = cv2.resize(img1, (1024,1024), interpolation=cv2.INTER_AREA)
img2 = cv2.imread('D:/PYCHARM_WORK/cv/cv_detection/project/guandao_angle_detection/sample2.jpg')
B = cv2.resize(img2, (1024,1024), interpolation=cv2.INTER_AREA)
# 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[:,0:int(cols/2)], lb[:,int(cols/2):]))
real = np.hstack((A[:, :int(cols/2)], B[:, int(cols/2):]))
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
cv2.imwrite('Pyramid_blending2.jpg',ls_)
cv2.imwrite('Direct_blending.jpg',real)
import cv2
import numpy as np
__author__ = "boboa"
# 高斯金字塔
def pyramid_demo(image):
level = 3
temp = image.copy()
pyramids_images = [] # 空列表
for i in range(level):
dst = cv2.pyrDown(temp) # 先對(duì)圖像進(jìn)行高斯平滑,然后再進(jìn)行降采樣(將圖像尺寸行和列方向縮減一半)
pyramids_images.append(dst) # 在列表末尾添加新的對(duì)象
cv2.imshow("pyramid_down_"+str(i), dst)
temp = dst.copy()
return pyramids_images
# 拉普拉斯金字塔
def lapalian_demo(image):
pyramids_images = pyramid_demo(image) # 拉普拉斯金字塔必須用到高斯金字塔的結(jié)果
level = len(pyramids_images)
# 遞減
for i in range(level-1, -1, -1):
if i - 1 < 0:
expand = cv2.pyrUp(pyramids_images[i], dstsize=image.shape[0:2])
lpls = cv2.subtract(image, expand)
cv2.imshow("lapalian_down_" + str(i), lpls)
else:
expand = cv2.pyrUp(pyramids_images[i], dstsize=pyramids_images[i - 1].shape[:2])
lpls = cv2.subtract(pyramids_images[i - 1], expand)
cv2.imshow("lapalian_down_" + str(i), lpls)
if __name__ == "__main__":
img = cv2.imread("image/img2.jpg")
cv2.namedWindow("input image", cv2.WINDOW_AUTOSIZE)
cv2.imshow("input image", img)
pyramid_demo(img)
cv2.waitKey(0)
cv2.destroyAllWindows()