1. 什么是图像金字塔
图像金字塔是图像处理和计算机视觉中常用到的概念,常常用于多尺度处理领域(multiscale processing),尤其早年的图像匹配、识别、图像分割等算法中都用到了图像金字塔。一幅图像的金字塔是一系列以金字塔形状排列的分辨率逐步降低,且来源于同一张原始图的图像集合。其通过梯次向下采样获得,直到达到某个终止条件才停止采样。金字塔的底部是待处理图像的高分辨率表示,而顶部是低分辨率的表示。我们将一层一层的图像比喻成金字塔,层级越高,则图像越小,分辨率越低。
2. 图像金字塔的分类
2.1 高斯金字塔(Gaussian pyramid):
金字塔的底层为原始图像,每向上一层则是通过高斯滤波和1/2采样得到(去掉偶数行和列),主要是用来下采样(cv2.pyrDown())的。
金字塔为一层一层的图像,层级越高,图像越小。
-
每一层都按从下到上的次序编号, 层级 (表示为 尺寸小于层级 ())。
-
为了获取层级为 的金字塔图像,我们采用如下方法:
-
将 与高斯内核卷积:
-
将所有偶数行和列去除。
-
-
显而易见,结果图像只有原图的四分之一。通过对输入图像 (原始图像) 不停迭代以上步骤就会得到整个金字塔.
2.2 拉普拉斯金字塔(Laplacian pyramid):
在进行高斯金字塔运算时,由于不断的进行高斯滤波和下采样,我们丢失了很多高频信号,而拉普拉斯金字塔的目的就是保存这些高频信号,保存这些高频信号所采用的方式就是保存差分图像。比如,拉普拉斯金字塔的第0层,就是原始图像和原始图像下采样(Reduce)后再次上采样 cv2.pyrUp()(Expand)的图像的差值。用来从金字塔低层图像重建上层未采样图像,在数字图像处理中也即是预测残差,可以对图像进行最大程度的还原,配合高斯金字塔一起使用。
上采样:将图像在每个方向扩大为原来的两倍,新增的行和列以0填充;使用先前同样的内核(乘以4)与放大后的图像卷积,获得 “新增像素”的近似值,得到的图像即为放大后的图像,但是与原来的图像相比会发觉比较模糊,因为在缩放的过程中已经丢失了一些信息,如果想在缩小和放大整个过程中减少信息的丢失,将原始图像和下采样再上采样后的图像做差值,这些数据形成了拉普拉斯金字塔。
2.3 DOG金字塔(差分金字塔)
DOG(Difference of Gaussian)金字塔是在高斯金字塔的基础上构建起来的,其实生成高斯金字塔的目的就是为了构建DOG金字塔。DOG金字塔的第1组第1层是由高斯金字塔的第1组第2层减第1组第1层得到的。以此类推,逐组逐层生成每一个差分图像,所有差分图像构成差分金字塔。概括为DOG金字塔的第0组第l层图像是由高斯金字塔的第0组第i+1层减第0组第i层得到的。
注:上采样cv2.pyrUp()函数和下采样cv2.pyrUp()函数中输入图像的宽、高必须一样,不然会报错。
cv2.pyrDown(src, dst=None, dstsize=None, borderType=None) 上采样参数同下采样。
参数说明: 1. src 输入图像 2. dst 输出图像 3. dstsize 输出图像的大小 4. borderTypre 边界处理方式。
3. 代码实现:
import cv2 as cv
import numpy as np# 图像金字塔和拉普拉斯金字塔(L1 = g1 - expand(g2)):reduce:高斯模糊+降采样,expand:扩大+卷积
# PyrDown降采样,PyrUp还原
def pyramid_demo(image):level = 3temp = image.copy()pyramid_images = []for i in range(level):dst = cv.pyrDown(temp)pyramid_images.append(dst)# cv.imshow("pyramid_down_"+str(i+1), dst)temp = dst.copy()return pyramid_imagesdef laplace_demo(image): # 注意:图片必须是宽、高一样pyramid_images = pyramid_demo(image)level = len(pyramid_images)for i in range(level-1, -1, -1):if i-1 < 0: # 对原图进行处理expand = cv.pyrUp(pyramid_images[i], dstsize=image.shape[:2])lpls = cv.subtract(image, expand)cv.imshow("laplace_demo"+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)cv.imshow("laplace_demo"+str(i), lpls)if __name__ == '__main__':src = cv.imread("../images/lena.jpg") # 读入图片放进src中# cv.imshow("demo", src) # 将src图片放入该创建的窗口中# pyramid_demo(src)laplace_demo(src)cv.waitKey(0) # 等有键输入或者1000ms后自动将窗口消除,0表示只用键输入结束窗口cv.destroyAllWindows() # 关闭所有窗口