学习图像金字塔
使用图像创建一个新水果:“橘子苹果”
学习的函数有: cv2.pyrUp(), cv2.pyrDown()
一般情况下,我们要处理是一副具有固定分辨率的图像,但是有些情况下,需要对同一图像的不同分辨率的子图像进行处理。比如,我们要在一幅图像中查找某个目标,比如脸,我们不知道目标在图像中的尺寸大小,这种情况下,我们需要创建创建一组图像,这些图像是具有不同分辨率的原始图像。我们把这组图像叫做图像金字塔(简单来说就是同一图像的不同分辨率的子图集合)。如果我们把最大的图像放在底部,最小的放在顶部,看起来像一座金字塔,故而得名图像金字塔。
有两类图像金字塔:高斯金字塔和拉普拉斯金字塔。
高斯金字塔的顶部是通过将底部图像中的连续的行和列去除得到的,顶部图像中的每个像素值等于下一层图像中 5 个像素的高斯加权平均值。这样操作一次一个 MxN 的图像就变成了一个 M/2xN/2 的图像。所以这幅图像的面积就变为原来图像面积的四分之一,这被称为 Octave。连续进行这样的操作我们就会得到一个分辨率不断下降的图像金字塔。使用函数
cv2.pyrDown() 和 cv2.pyrUp() 构建图像金字塔。
函数 cv2.pyrDown() 从一个高分辨率大尺寸的图像向上构建一个金字塔(尺寸变小,分辨率降低)。
import cv2
import numpy as np
from matplotlib import pyplot as plt
img = cv2.imread('image/lufei.jpeg',255)
img1 = cv2.pyrDown(img)
img2 = cv2.pyrDown(img1)
plt.subplot(131), plt.imshow(cv2.cvtColor(img,cv2.COLOR_BGR2RGB))
plt.title("Original")
plt.subplot(132), plt.imshow(cv2.cvtColor(img1,cv2.COLOR_BGR2RGB))
plt.title("Gaussion_1")
plt.subplot(133), plt.imshow(cv2.cvtColor(img2,cv2.COLOR_BGR2RGB))
plt.title("Gaussion_2")
plt.show()
结果图:
从坐标轴看大小,图像缩小了一倍。像素上可以看出变得更模糊。
函数 cv2.pyrUp() 从一个低分辨率小尺寸的图像向下构建一个金子塔(尺寸变大,但分辨率不会)
import cv2
import numpy as np
from matplotlib import pyplot as plt
img = cv2.imread('image/lufei.jpeg',255)
img1 = cv2.pyrDown(img)
img2 = cv2.pyrUp(img1)
plt.subplot(131), plt.imshow(cv2.cvtColor(img,cv2.COLOR_BGR2RGB))
plt.title("Original")
plt.subplot(132), plt.imshow(cv2.cvtColor(img1,cv2.COLOR_BGR2RGB))
plt.title("down")
plt.subplot(133), plt.imshow(cv2.cvtColor(img2,cv2.COLOR_BGR2RGB))
plt.title("up")
plt.show()
结果图:
拉普拉斯金字塔可以有高斯金字塔计算得来,公式如下:
拉普拉金字塔的图像看起来就像边界图,其中很多像素都是 0,经常被用在图像压缩中。
import cv2
import numpy as np
from matplotlib import pyplot as plt
img = cv2.imread('image/lufei.jpeg')
img1 = cv2.pyrDown(img)
temp1 = cv2.pyrDown(img1)
temp2 = cv2.pyrUp(temp1)
img2 = img1 - temp2
plt.subplot(131), plt.imshow(cv2.cvtColor(img,cv2.COLOR_BGR2RGB))
plt.title("Original")
plt.subplot(132), plt.imshow(cv2.cvtColor(img1,cv2.COLOR_BGR2RGB))
plt.title("Gaussion")
plt.subplot(133), plt.imshow(cv2.cvtColor(img2,cv2.COLOR_BGR2RGB))
plt.title("Laplacian")
plt.show()
图像金字塔的一个应用是图像融合。例如,在图像缝合中,你需要将两幅图叠在一起,但是由于连接区域图像像素的不连续性,整幅图的效果看起来会很差,这时图像金字塔就可以排上用场了,可以实现无缝连接。
下图是摘自《学习 OpenCV》展示了金子塔的构建,以及如何从金字塔重建原始图像的过程。
这里的一个经典案例就是将两个水果融合成一个。
实现水果融合的步骤如下:
1. 读入两幅图像,苹果和句子
2. 构建苹果和橘子的高斯金字塔(6 层)
3. 根据高斯金字塔计算拉普拉斯金字塔
4. 在拉普拉斯的每一层进行图像融合(苹果的左边与橘子的右边融合)
5. 根据融合后的图像金字塔重建原始图像。
import cv2
import numpy as np
from matplotlib import pyplot as plt
def sameSize(img1, img2):
rows, cols, dpt = img2.shape
dst = img1[:rows,:cols]
return dst
apple = cv2.imread('image/apple.jpeg')
orange = cv2.imread('image/orange.jpeg')
G = apple.copy()
gp_apple = [G]
for i in xrange(6):
G = cv2.pyrDown(G)
gp_apple.append(G)
G = orange.copy()
gp_orange = [G]
for j in xrange(6):
G = cv2.pyrDown(G)
gp_orange.append(G)
lp_apple = [gp_apple[5]]
for i in xrange(5,0,-1):
GE = cv2.pyrUp(gp_apple[i])
L = cv2.subtract(gp_apple[i-1], sameSize(GE,gp_apple[i-1]))
lp_apple.append(L)
lp_orange = [gp_orange[5]]
for i in xrange(5,0,-1):
GE = cv2.pyrUp(gp_orange[i])
L = cv2.subtract(gp_orange[i-1], sameSize(GE,gp_orange[i-1]))
lp_orange.append(L)
LS = []
for la,lb in zip(lp_apple,lp_orange):
rows,cols,dpt = la.shape
ls = np.hstack((la[:,0:cols/2],lb[:,cols/2:]))
LS.append(ls)
ls_reconstruct = LS[0]
for i in xrange(1,6):
ls_reconstruct = cv2.pyrUp(ls_reconstruct)
ls_reconstruct = cv2.add(sameSize(ls_reconstruct,LS[i]), LS[i])
r,c,depth = apple.shape
real = np.hstack((apple[:,0:c/2],orange[:,c/2:]))
plt.subplot(221), plt.imshow(cv2.cvtColor(apple,cv2.COLOR_BGR2RGB))
plt.title("apple"),plt.xticks([]),plt.yticks([])
plt.subplot(222), plt.imshow(cv2.cvtColor(orange,cv2.COLOR_BGR2RGB))
plt.title("orange"),plt.xticks([]),plt.yticks([])
plt.subplot(223), plt.imshow(cv2.cvtColor(real,cv2.COLOR_BGR2RGB))
plt.title("real"),plt.xticks([]),plt.yticks([])
plt.subplot(224), plt.imshow(cv2.cvtColor(ls_reconstruct,cv2.COLOR_BGR2RGB))
plt.title("laplace_pyramid"),plt.xticks([]),plt.yticks([])
plt.show()