Opencv图像处理系列(八)—— 图像金字塔

栏目: 编程工具 · 发布时间: 6年前

内容简介:在某些情况下,我们需要处理同一图像的不同分辨率的图像。例如在搜索图像中的某些对象时,比如人脸,我们不确定对象在图像中的大小,在这种情况下,我们需要创建一组不同分辨率的图像,并在所有图像中搜索对象。这些具有不同分辨率的图像集就被称为图像金字塔(因为它们保存在一个堆栈中,底部是最大的图像,顶部是最小的图像,看起来就像一个像金字塔)。图像金字塔有两种:1.高斯金字塔和 2.拉普拉斯金字塔。高斯金字塔中较高级别的图像(低分辨率)是通过删除低级别(高分辨率)图像中的连续行和列而形成的。

在某些情况下,我们需要处理同一图像的不同分辨率的图像。例如在搜索图像中的某些对象时,比如人脸,我们不确定对象在图像中的大小,在这种情况下,我们需要创建一组不同分辨率的图像,并在所有图像中搜索对象。这些具有不同分辨率的图像集就被称为图像金字塔(因为它们保存在一个堆栈中,底部是最大的图像,顶部是最小的图像,看起来就像一个像金字塔)。

图像金字塔有两种:1.高斯金字塔和 2.拉普拉斯金字塔。

1. 高斯金字塔

高斯金字塔中较高级别的图像(低分辨率)是通过删除低级别(高分辨率)图像中的连续行和列而形成的。

首先,对较低层次图像上的每个像素计算5x5像素的高斯权值,然后删除图像的偶数行和列,这样M×N图像就会被处理成M/2×N/2的图像,面积减少到原来面积的四分之一。

用通用的方法继续计算,就可以得到分辨率不断下降的高斯金字塔。

当面积扩大时,首先在每个方向分别间隔插入一行像素,新插入的像素填充0,然后使用同样的内核进行高斯卷积,就得到了放大后的金字塔图片。

可以使用cv2.pyrdown()和cv2.pyrUp()函数计算高斯金字塔。

img = cv2.imread('test.jpg') # 750*994
img = cv2.resize(img, None, fx=0.5, fy=0.5, interpolation=cv2.INTER_CUBIC) #375*497
l1 = cv2.pyrDown(img)
l2 = cv2.pyrDown(l1)
l3 = cv2.pyrDown(l2)
display = img
for item in [l1,l2,l3]:
    pad = np.pad(item,((0, img.shape[0]-item.shape[0]),(0,0),(0,0)),'constant')
    display = np.concatenate((display, pad) , axis=1)
cv2.imshow('image', display)
cv2.waitKey(0)
cv2.destroyAllWindows()

Opencv图像处理系列(八)—— 图像金字塔

img = cv2.imread('test.jpg') # 750*994
img = cv2.resize(img, (45, 90), interpolation=cv2.INTER_CUBIC) #45*90
up1 = cv2.pyrUp(img)
up2 = cv2.pyrUp(up1)
up3 = cv2.pyrUp(up2)
display = np.pad(img,((0,up3.shape[0]-img.shape[0]),(0,0),(0,0)),'constant')
for item in [up1, up2, up3]:
    pad = np.pad(item, ((0, up3.shape[0] - item.shape[0]), (0, 0), (0, 0)), 'constant')
    display = np.concatenate((display, pad), axis=1)
cv2.imshow('image', display)
cv2.waitKey(0)
cv2.destroyAllWindows()

Opencv图像处理系列(八)—— 图像金字塔

2. 拉普拉斯金字塔

拉普拉斯金字塔是基于高斯金字塔生成的,它的大部分元素都是零,有点像边缘图像,一般用于图像压缩/图像融合等。

设第i层的拉普拉斯金字塔为Li,高斯金字塔为Gi,则拉普拉斯金字塔的定义如下

Opencv图像处理系列(八)—— 图像金字塔

其中-后面的部分指将Gi+1像素映射到长宽扩大一倍的图像像,然后用5x5的内核卷积,实际上就是个pyrUp的过程,所以Li也可以表示为:

Opencv图像处理系列(八)—— 图像金字塔

一张图先pyrDown,再pyrUp,不是可逆的操作,而会在pyrDown的过程中丢失一些细节,拉皮拉斯金字塔表示的正是这部分丢失的细节。

3.使用图像金字塔融合图片

图像金字塔的一个应用场景是图像融合。在对两张图片进行融合的时候,由于图像之间的不连续性,边界的地方像素变化会显得十分突兀。使用图像金字塔来做图像融合,则能做到无缝融合的效果。

基本思路:

  1. 为待融合的两张图像分别计算高斯金字塔(如:G0,G1,G2,G3,G4,G5 共6层)
  2. 基于高斯金字塔计算出各层的拉普拉斯金字塔(L5,L4,L3,L2,L1 共5层)
  3. 将两张图最高层级的高斯金字塔(G5)、各个层级的拉普拉斯金字塔(L1~L5)直接融合
  4. 对G5融合结果pyrUp操作,然后从L5中还原第1步中pyrDown的时候G4到G5丢失的部分细节,重复此步骤直到L1~L5的细节全部重建完成

在各级拉普拉斯金字塔融合图像中,由于边界部分分辨率降低,两幅图像的细节都有包含,因此重建之后,边界部分的融合看起来比较自然,而非边界部分还是还原了各自的细节,下面来一下分解动作。

随便在网上下载两张500x500的图,直接拼接:

def showAll(imgs,zoom=1):
    maxHeight = max([img.shape[0] for img in imgs])
    display = np.pad(imgs[0],((0,maxHeight - imgs[0].shape[0]),(0,0),(0,0)),'constant')
    for i in range(1, len(imgs)):
        pad = np.pad(imgs[i], ((0, maxHeight - imgs[i].shape[0]), (0, 0), (0, 0)), 'constant')
        display = np.concatenate((display, pad), axis=1)
    display = cv2.resize(display, None, fx=zoom,fy=zoom)
    cv2.imshow('image', display)
    cv2.waitKey(0)
    cv2.destroyAllWindows()

img1 = cv2.imread("t1.jpg")
img2 = cv2.imread("t2.jpg")
height,width = img1.shape[0:2]
blend1 = img1.copy()
half = int(width/2)
blend1[0:height,half:width] = img2[0:height,half:width]
showAll([img1,img2,blend1],0.5)

Opencv图像处理系列(八)—— 图像金字塔

可以看到拼接处十分的突兀。接下来用图像金字塔来融合。

步骤1,对两张图像分别计算6层高斯金字塔。

G = img1.copy()
    gp1 = [G]
    for i in range(6):
        G = cv2.pyrDown(G)
        gp1.append(G)
    G = img2.copy()
    gp2 = [G]
    for i in range(6):
        G = cv2.pyrDown(G)
        gp2.append(G)

Opencv图像处理系列(八)—— 图像金字塔

Opencv图像处理系列(八)—— 图像金字塔

步骤2,基于高斯金字塔计算出各层的拉普拉斯金字塔

lp1 = [gp1[5]]
    for i in range(5, 0, -1):
        GE = cv2.pyrUp(gp1[i])
        GE = cv2.resize(GE,gp1[i-1].shape[0:2])
        L = cv2.subtract(gp1[i - 1], GE)
        lp1.append(L)
    lp2 = [gp2[5]]
    for i in range(5, 0, -1):
        GE = cv2.pyrUp(gp2[i])
        GE = cv2.resize(GE, gp2[i - 1].shape[0:2])
        L = cv2.subtract(gp2[i - 1], GE)
        lp2.append(L)
    showAll(lp1+lp2,0.5)

(数组中第一个元素为高斯金字塔的最顶层的一张图)

Opencv图像处理系列(八)—— 图像金字塔

步骤3, 拉普拉斯金字塔各级融合

LS = []
for la, lb in zip(lp1, lp2):
    rows, cols, dpt = la.shape
    ls = np.hstack((la[:, 0:int(cols / 2)], lb[:, int(cols / 2):]))
    LS.append(ls)
showAll(LS, 0.8)

Opencv图像处理系列(八)—— 图像金字塔

步骤4,融合后的结果由低到高逐级还原细节

ls_ = LS[0]
    for i in range(1, 6):
        ls_ = cv2.pyrUp(ls_)
        ls_ = cv2.resize(ls_, LS[i].shape[0:2])
        ls_ = cv2.add(ls_, LS[i])
    showAll([ls_])

Opencv图像处理系列(八)—— 图像金字塔

可以看到,与直接融合相比,边缘部分明显要平滑很多。


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Beginning XML with DOM and Ajax

Beginning XML with DOM and Ajax

Sas Jacobs / Apress / 2006-06-05 / USD 39.99

Don't waste time on 1,000-page tomes full of syntax; this book is all you need to get ahead in XML development. Renowned web developer Sas Jacobs presents an essential guide to XML. Beginning XML with......一起来看看 《Beginning XML with DOM and Ajax》 这本书的介绍吧!

图片转BASE64编码
图片转BASE64编码

在线图片转Base64编码工具

HTML 编码/解码
HTML 编码/解码

HTML 编码/解码

Base64 编码/解码
Base64 编码/解码

Base64 编码/解码