欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

OpenCV-Python 中文教程14——图像金字塔

程序员文章站 2022-07-14 17:03:18
...
OpenCV-Python 中文教程14——图像金字塔

参考博客:

1、https://blog.csdn.net/jjddss/article/details/73469348

目标

学习图像金字塔

使用图像创建一个新水果:“橘子苹果”

将要学习的函数有: cv2.pyrUp()cv2.pyrDown() 

1、高斯金字塔和拉普拉斯金字塔的原理

       一般情况下,要处理是一副具有固定分辨率的图像,但在有些情况下,假如我们需要对同一图像的不同分辨率的子图像进行处理。比如,我们要在一幅图像中查找某个目标,比如脸,我们不知道目标在图像中的尺寸大小。这种情况下,我们需要创建创建一组图像,这些图像是具有不同分辨率的原始图像。我们把这组图像叫做图像金字塔(简单来说就是同一图像的不同分辨率的子图集合)。如果我们把最大的图像放在底部,最小的放在顶部,看起来像一座金字塔,故而得名图像金字塔有两类图像金字塔:高斯金字塔和拉普拉斯金字塔。具体参考博客:

a、https://blog.csdn.net/xbcReal/article/details/52629465

b、https://blog.csdn.net/keith_bb/article/details/54583514

(1)高斯金字塔

        高斯金字塔的顶部是通过将底部图像中的连续的行和列去除得到的。顶部图像中的每个像素值等于下一层图像中 5 个像素的高斯加权平均值,这样操作一次一个 MxN 的图像就变成了一个 M/2xN/2 的图像,所以这幅图像的面积就变为原来图像面积的四分之一,这被称为 Octave,连续进行这样的操作我们就会得到一个分辨率不断下降的图像金字塔。我们可以使用函数cv2.pyrDown() cv2.pyrUp() 构建图像金字塔。函数 cv2.pyrDown() 从一个高分辨率大尺寸的图像向上构建一个金子塔(尺寸变小,分辨率降低)。

       这两个函数的特点是:cv2.pyrUp()(尺寸变大,但分辨率不会增加 ),cv2.pyrDown()(图像尺寸变小,分辨率降低)。cv2.pyrUp()与cv2.pyrDown()的示例代码:

import numpy as np
import cv2
import matplotlib.pyplot as plt


img=cv2.imread('haimianbaobao.jpg')
lower_reso = cv2.pyrDown(img)
higer_reso = cv2.pyrUp(lower_reso)

cv2.namedWindow("img")
cv2.imshow("img",img)

cv2.namedWindow("lower_reso")
cv2.imshow("lower_reso",lower_reso)


cv2.namedWindow("higer_reso")
cv2.imshow("higer_reso",higer_reso)
cv2.waitKey(0)
cv2.destroyAllWindows()
运行结果:

OpenCV-Python 中文教程14——图像金字塔

OpenCV-Python 中文教程14——图像金字塔

OpenCV-Python 中文教程14——图像金字塔


(2)拉普拉斯金字塔

       在高斯金字塔的运算过程中,图像经过卷积和下采样操作会丢失部分高频细节信息。为描述这些高频信息,人们定义了拉普拉斯金字塔(Laplacian Pyramid, LP)。即,用高斯金字塔的每一层图像减去其上一层图像上采样并高斯卷积之后的预测图像,得到一系列的差值图像即为 LP 分解图像。计算公式为:

OpenCV-Python 中文教程14——图像金字塔

       拉普拉斯金字塔的图像看起来就像边界图,其中很多像素都是 0,经常被用在图像压缩中,下图就是一个三层的拉普拉斯金字塔:

import cv2

img = cv2.imread('haimianbaobao.jpg')
img1 = cv2.pyrDown(img)
tmp_img1 = cv2.pyrDown(img1)
tmp_img2 = cv2.pyrDown(tmp_img1)
tmp = cv2.pyrUp(tmp_img2)
img2 = tmp_img1 - tmp

cv2.namedWindow("img")
cv2.imshow("img",img)

cv2.namedWindow("pyrDown")
cv2.imshow("pyrDown",tmp_img1)

cv2.namedWindow("laplacian_pyramid")
cv2.imshow("laplacian_pyramid",img2)
cv2.waitKey(0)
cv2.destroyAllWindows()

运行结果:

OpenCV-Python 中文教程14——图像金字塔


2、使用金字塔进行图像融合

       图像金字塔的一个应用是图像融合。例如,在图像缝合中,你需要将两幅图叠在一起,但是由于连接区域图像像素的不连续性,整幅图的效果看起来会很差。这时图像金字塔就可以排上用场,可以帮你实现无缝连接。
  

import cv2
import numpy as np
A = cv2.imread('apple.jpg')
B = cv2.imread('orange.jpg')
# generate Gaussian pyramid for A
G = A.copy()
gpA = [G]
for i in np.arange(6):     #将苹果进行高斯金字塔处理,总共六级处理
    G = cv2.pyrDown(G)
    gpA.append(G)
# generate Gaussian pyramid for B
G = B.copy()
gpB = [G]
for i in np.arange(6):  # #将橘子进行高斯金字塔处理,总共六级处理
    G = cv2.pyrDown(G)
    gpB.append(G)
# generate Laplacian Pyramid for A
lpA = [gpA[5]]               
for i in np.arange(5,0,-1):    #将苹果进行拉普拉斯金字塔处理,总共5级处理
    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 np.arange(5,0,-1):    #将橘子进行拉普拉斯金字塔处理,总共5级处理
    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:cols//2], lb[:,cols//2:]))    #将两个图像的矩阵的左半部分和右半部分拼接到一起
    LS.append(ls)
# now reconstruct
ls_ = LS[0]   #这里LS[0]为高斯金字塔的最小图片
for i in xrange(1,6):                        #第一次循环的图像为高斯金字塔的最小图片,依次通过拉普拉斯金字塔恢复到大图像
    ls_ = cv2.pyrUp(ls_)
    ls_ = cv2.add(ls_, LS[i])                #采用金字塔拼接方法的图像
# image with direct connecting each half
real = np.hstack((A[:,:cols/2],B[:,cols/2:]))   #直接的拼接
cv2.imwrite('Pyramid_blending2.jpg',ls_)
cv2.imwrite('Direct_blending.jpg',real)

运行结果:

OpenCV-Python 中文教程14——图像金字塔


实现上述效果的步骤如下:

(1) 读入两幅图像,苹果和句子

(2)构建苹果和橘子的高斯金字塔(6 层)

(3)根据高斯金字塔计算拉普拉斯金字塔

(4)在拉普拉斯的每一层进行图像融合(苹果的左边与橘子的右边融合)

(5)根据融合后的图像金字塔重建原始图像。

下图是摘自《学习 OpenCV》展示了金子塔的构建,以及如何从金字塔重建原始图像的过程:

OpenCV-Python 中文教程14——图像金字塔


更多资料:Image Blending