OpenCV之图像金字塔与图像融合(Python)

    xiaoxiao2023-11-19  168

    图像金字塔

    参考的博文:https://www.cnblogs.com/silence-hust/p/4193208.html 最近在学习OpenCV中图像特征描述算法(SIFT,SURF,ORB等)。其中涉及了图像金字塔的内容,在参考了很多博文之后,在这里记录下自己对图像金字塔以及图像融合浅显的认识。 1. 高斯金字塔   高斯金字塔是最基本的图像塔。首先将原图像作为最底层图像G0(高斯金字塔的第0层,这里可以将原图像进行处理最好处理成2的n次方,便于处理),利用高斯核(55)对其进行卷积,然后对卷积后的图像进行下采样(去除偶数行和列)得到上一层图像G1,将此图像作为输入,重复卷积和下采样操作得到更上一层图像,上一层图像是下一层图像的1/4 。反复迭代多次,形成一个金字塔形的图像数据结构,即高斯金字塔。换句话说就是:高斯金字塔的顶部是通过将底部图像中行和列按照相应规则去除而得到的。 **高斯金字塔的构建过程为:**假设高斯金字塔的第L层图像为Gl: 式中N为高斯金字塔顶层层号,Rl和Cl分别为高斯金字塔第l层的行数和列数W(m,n)是一个二维可分离的55窗口函数,表达式为:   由G0,G1,,,GN,就构成了一个高斯金字塔,其中G0为高斯金字塔的底层(与原图像相同)GN为金字塔的顶层。由此可见高斯金字塔的当前层图像就是对其前一层图像首先进行高斯低通滤波,然后再进行隔行和隔列的降2采样而生成的。前一层图像大小依次为当前层图像大小的4倍。经过这样连续操作后,我们就会的到下图所示的一个分辨率不断下降的图像金字塔。(这个过程也类似于肉眼由进到远观看一幅图的清晰度过程) OpenCV中提供了生成高斯金字塔的函数 pyrDown(src, dst=None, dstsize=None, borderType=None) 和 pyrUp(src, dst=None, dstsize=None, borderType=None),cv2.pyrDown()从一个相对高分辨率的大尺寸的图像上构建一个金字塔,结果就是,图像变小,分辨率降低(降采样)。 而cv2.pyrUp()是一个上采样的过程,尽管相对尺寸变大,但是分辨率不会增加,图像会变得更模糊。

    2. 拉普拉斯金字塔   拉普拉斯金字塔是可以由高斯金字塔计算得来,计算公式如下:(Li代表拉普拉斯金字塔的层数)    L(i) = G(i) − PyrUp( G(i+1) ) 具体需要多少层需要是具体情况而定。 PS:此处在做图像矩阵减法得用cv2.subtract(img1,img2),因为对于元素类型为uint8 数据类型的图像矩阵而言,cv2.subtract(img1,img2)方法使得元素相减为负数时,该元素变为0。而img1 - img2元素相减为负数时,该元素为 255(显然不符合要求)。

    3. 重构  拉普拉斯金字塔的一个重要用是图像重建和融合,下图给出了利用拉式金字塔进行重建过程。    对融合后的拉普拉斯金字塔,从其顶层开始逐层从上至下按下式进行递推,可以恢复其对应的高斯金字塔,并最终可得到原图像G0。就是从最高层开始使用内插的方法。

    图像融合

    图像金字塔一个典型的应用就是图像融合。图像融合的实现步骤为:

    读入两幅大小相同的图像 img1, img2构建 img1 ,img2的 高斯金字塔,层数根据需要设定(这里定为6层)根据高斯金字塔和拉普拉斯金字塔的关系,推出拉普拉斯金字塔的Li(也为6层,第一层大小和原图相同)在拉普拉斯图层的每一层进行图像融合根据融合后的图像金字塔重建原始图像

    实现代码

    import cv2 as cv import numpy as np def Pyramid(A,B): # 构建苹果和橘子高斯金字塔 G = A.copy() G1 = B.copy() gpA = [G] gpB = [G1] for i in range(6): G = cv.pyrDown(G) # print(G.shape) G1 = cv.pyrDown(G1) # print(G.shape) gpA.append(G) gpB.append(G1) # 构建苹果的拉普拉斯金字塔 LA = [gpA[5]] for i in range(5, 0, -1): LA.append(cv.subtract(gpA[i-1],cv.pyrUp(gpA[i]))) # 构建橘子的拉普拉斯金字塔 LB = [gpB[5]] for i in range(5, 0, -1): LB.append(cv.subtract(gpB[i - 1], cv.pyrUp(gpB[i]))) # 将苹果的左边和橘子的右边无缝融合 LeftA = [] RightA = [] Merge = [] for level in LA: LeftA.append(level[:, :int(level.shape[1]/2)] ) for level in LB: RightA.append(level[:, int(level.shape[1]/2) :]) for i in range(6): Merge.append(np.hstack((LeftA[i], RightA[i]))) result = Merge[0] for i in range(1, 6): result = cv.pyrUp(result) result = cv.add(result, Merge[i]) return result if __name__ == "__main__": img1 = cv.imread("sources/apple.jpg") img2 = cv.imread("sources/orange.jpg") rows, cols, dpt = img1.shape real = np.hstack((img1[:, :int(cols/2)], img2[:, int(cols/2):])) cv.imshow("Direct", real) cv.imshow("Laplace", Pyramid(img1, img2)) cv.waitKey(0)

    效果图: 分析: 参照相关文档,对比了直接融合 与 通过拉式金字塔融合效果。拉式金字塔牺牲了清晰度,换来了无缝连接。但直接连接有明显的缝隙。

    最新回复(0)