一、概念
图像金字塔是由一幅图像的多个不同分辨率的子图所构成的图像集合。这个图像集合是由原图像不断下采样;产生的,最底层是原图像,该层的上层图像是该层图像下采样产生,因此,图像的大小就是 : NN —N/2N/2----…一直到顶点1*1。
根据下采样前使用的卷积核操作的不同,图像金字塔可以分为高斯金字塔、拉普拉斯金字塔等等。下采样的一般步骤为:先将图片滤波,然后将滤波后的图像去掉其偶数行和偶数列,在滤波器的选择上我们有多种方式,cv包中使用的默认滤波器为高斯滤波器。
由于采样后的图像将越来越小,因此可以通过上采样来对图像进行尺寸扩大,每经历一次上采样,图像的大小都将扩大二倍。由于上采样需要我们创造原来没有的像素点,因此该像素点值的填充有多种方式,比如最近邻插值法、零填充法等等。使用零填充法就是将新创建的周围像素点的像素值填充为0, 然后再使用高斯滤波进行平滑处理。
拉普拉斯金字塔:
上面方法创建的金字塔称为高斯金字塔,高斯金字塔是通过对一幅图像进行一系列大的下采样产生。而有时候我们想要得到小图像中的大尺寸清晰图像,这个时候就要用到拉普拉斯金字塔。其公式为:
L_IMG = IMG - pyrUp(img + 1)
拉普拉斯金字塔的作用在于能够恢复高分辨率的图像,由于使用下采样操作,会使原图像中的一部分特征(像素点)丢失,因此即使是上采样后的图像也不能与原图保持特征一致。但使用拉普拉斯金字塔可以做到恢复高分辨率,实现步骤见下代码。
二、程序中的实现
1、下采样实现函数:
img_down = cv.pyrDown(img1)
2、上采样实现的函数
img_up = cv.pyrUp(img)
3、创建一层拉普拉斯金字塔图像
img1 = cv.imread("car_red.jpg", cv.IMREAD_GRAYSCALE)
img1 = cv.resize(img1, (420, 280))
img = cv.pyrDown(img1)
img_up = cv.pyrUp(img)
result = np.hstack((img1, img1 - img_up))
将原图像放在左边,拉普拉斯金字塔图像放在右边,结果如图:
4、创建拉普拉斯金字塔并最后复原图像
由于使用cv显示图像每次都要写三句话,因此这里做一个封装函数cv_show():
def cv_show(img):
cv.imshow("hh", img)
cv.waitKey(0)
cv.destroyAllWindows()
金字塔代码:
def L_G_pyr():
img = cv.imread("car_red.jpg", cv.IMREAD_GRAYSCALE)
# 首先创建一个高斯金字塔
level_0 = cv.resize(img, (432, 288))
level_1 = cv.pyrDown(level_0)
level_2 = cv.pyrDown(level_1)
level_3 = cv.pyrDown(level_2)
level_4 = cv.pyrDown(level_3)
# 在高斯金字塔的基础上,生成拉普拉斯金字塔
laplace0 = level_0 - cv.pyrUp(level_1)
laplace1 = level_1 - cv.pyrUp(level_2)
laplace2 = level_2 - cv.pyrUp(level_3)
laplace3 = level_3 - cv.pyrUp(level_4)
# 复原的图像
result = laplace0 + cv.pyrUp(level_1)
# 拼接两个金字塔的每一层
img_list = [np.hstack((level_3, laplace3)), np.hstack((level_2, laplace2)),
np.hstack((level_1, laplace1)), np.hstack((level_0, laplace0)),
np.hstack((level_0, result))]
for item in img_list:
cv_show(item)
# 判断复原图像与原图像差异
print("图像差异为:", np.sum(abs(result-level_0)))
说明复原图像与原图像素一模一样,细心观察发现,其实复原图像与原图一模一样的原因在于,对于复原图像的计算公式:
result = laplace0 + cv.pyrUp(level_1)
将laplace0的计算式带入上面公式,其结果就等于原图像。利用拉普拉斯金字塔,可以复原高斯金字塔的每一层高分辨率图像。在实际中,金字塔更多的用在图片特征提取上,对不同层的金字塔图片提取有用信息特征。