(Python)从零开始,简单快速学机器仿人视觉Opencv—第十六节:图像金字塔

129
0
2021年1月3日 09时33分

1.原理

 

一般情况下,我们要处理是一副具有固定分辨率的图像。但是特别情况下我们需要对同一个图像的不同分辨率的子图像进行处理,如查找图像中的某个目标,如人脸,我们不知道目标在图像中的尺寸大小。这种情况下,我们需要创建一组图像,这些图像是具有不同分辨率的原始图像。我们把这组图像叫做图像金字塔。就是同一图像的不同分辨率的子图集合。我们把最大的图像放在底部,最小的放在顶部,看起来就像一座金字塔。

 

金字塔常见的有两类:高斯金字塔和拉普拉斯金字塔。

 

1.1高斯金字塔

 

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

 

cv2.pyrDown从一个高分辨率大尺寸的图像向上构建一个金字塔(尺寸变小,分辨率降低)

cv2.U拍从一个小尺寸的图像向上构建一个金字塔(尺寸变大,总体分辨率不变,但因为总体变大了,所以看上去分辨率还是降低的。)

 

import numpy as np
import cv2

img = cv2.imread('1024.jpg')
lower_reso = cv2.pyrDown(img)

while(1):
    cv2.imshow('img',img)
    cv2.imshow('lower_reso',lower_reso)
    if cv2.waitKey() == ord('q'):
        break
cv2.destroyAllWindows()
cv2.pyrUp从一个低分辨率小尺寸的图像向上构建一个金字塔(尺寸变大,但分辨率不会增加)

import numpy as np
import cv2

img = cv2.imread('1024.jpg')
lower_reso = cv2.pyrDown(img)
higher_reso2 = cv2.pyrUp(img)

while(1):
    cv2.imshow('img',img)
    cv2.imshow('lower_reso',lower_reso)
    cv2.imshow('higher_reso2',higher_reso2)
    if cv2.waitKey() == ord('q'):
        break
cv2.destroyAllWindows()

 

要记住的是higher_reso2和higher_reso 是不同的。因为一旦使用cv2.pyrDown图像的分辨率就会降低,信息就会被丢失。而拉普拉斯金字塔的作用就是在于他能够在一定程度上恢复信息的丢失。

 

1.2.拉普拉斯金字塔

 

拉普拉斯金字塔可以由高斯金字塔计算得来。公式如下:

 

在这里插入图片描述

 

公示解读:第i层的拉普拉斯金字塔式是原本的第i+1层的图层经过PyrUp函数变大后,将其与原图中的第i层进行做差得到。得到的也就是信息丢失的部分边界。

 

拉普拉斯金字塔的图像看起来就像是边界图,其中很多像素都是0,常被用在图像压缩中。

 

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

 

在图像缝合中,由于连接区域图像像素的不连续,整幅图看起来会很差,金字塔就可以实现无缝连接。

 

经典例子就是水果融合

 

在这里插入图片描述

 

实现步骤:

·读入两幅图

·构建各自的高斯金字塔(6层)

·根据高斯金字塔计算拉普拉斯金字塔

·在拉普拉斯的每一层进行图像融合

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

·如何重建原始图像过程

 

在这里插入图片描述

 

示例代码:

 

import cv2
#高斯金字塔
def pyramid_demo(image):
    level = 3      #设置金字塔的层数为3
    temp = image.copy()  #拷贝图像
    pyramid_images = []  #建立一个空列表
    for i in range(level):
        dst = cv2.pyrDown(temp)   #先对图像进行高斯平滑,然后再进行降采样(将图像尺寸行和列方向缩减一半)
        pyramid_images.append(dst)  #在列表末尾添加新的对象
        cv2.imshow("pyramid"+str(i), dst)
        temp = dst.copy()
    return pyramid_images
#拉普拉斯金字塔
def lapalian_demo(image):
    pyramid_images = pyramid_demo(image)    #做拉普拉斯金字塔必须用到高斯金字塔的结果
    level = len(pyramid_images)
    for i in range(level-1, -1, -1):
        if (i-1) < 0:
            expand = cv2.pyrUp(pyramid_images[i], dstsize = image.shape[:2])
            lpls = cv2.subtract(image, expand)
            cv2.imshow("lapalian_down_"+str(i), lpls)
        else:
            expand = cv.pyrUp(pyramid_images[i], dstsize = pyramid_images[i-1].shape[:2])
            lpls = cv.subtract(pyramid_images[i-1], expand)
            cv2.imshow("lapalian_down_"+str(i), lpls)
src = cv2.imread('E:/imageload/zixia.jpg')
cv2.namedWindow('input_image', cv.WINDOW_AUTOSIZE) #设置为WINDOW_NORMAL可以任意缩放
cv2.imshow('input_image', src)
lapalian_demo(src)
cv2.waitKey(0)
cv2.destroyAllWindows()

 

示例图:

 

在这里插入图片描述

 

注意:使用拉普拉斯金字塔的时候,图像大小一定要是(2^m, 2^n)的形式!不然代码会报错

 

总结:

(本系列每周不定期更新,谢谢大家的支持!)

 

发表评论

后才能评论