今天介绍图像处理邻域中比较常用的一种方法,image pyramid, 也叫图像金字塔。就是将图像进行一层一层的下采样,图像金字塔是为了构建图像的多尺度,让模型能够更好的适应图像的尺度变化,图像金字塔可以广泛应用于图像识别,目标检测,还有光流配准,块匹配都能看到它的身影。图像金字塔主要有两种,一种是高斯金字塔,gaussian pyramid,另外一种是拉普拉斯金字塔,Laplacian Pyramids。
图像金字塔是一种以多分辨率来解释图像的结构,通过对原始图像进行多尺度像素采样的方式,生成N个不同分辨率的图像。把具有最高级别分辨率的图像放在底部,以金字塔形状排列,往上是一系列像素(尺寸)逐渐降低的图像,一直到金字塔的顶部只包含一个像素点的图像,这就构成了传统意义上的图像金字塔。
获得图像金字塔一般包括二个步骤:
1. 利用低通滤波器平滑图像
2. 对平滑图像进行抽样(采样)
有两种采样方式——上采样(分辨率逐级升高)和下采样(分辨率逐级降低)
在OpenCV定义这两个函数:
这个函数主要采用下面高斯平滑算子:
这个函数实现向下高斯平滑和采样,另外一个函数cv.pyrUp向上高斯平滑和采样。可以采用下面的例子来演示:
#python 3.7.4,opencv4.1
#蔡军生 https://blog.csdn.net/caimouse/article/details/51749579
#
import numpy as np
import cv2
from matplotlib import pyplot as plt
#读取图片
A = cv2.imread('dft6.jpg')
#生成高斯金字塔
G = A.copy()
gpA = [G]
for i in range(4): #生成四级
G = cv2.pyrDown(G) #调用高斯金字塔函数pyrDown
gpA.append(G) #保存到队列
G = np.zeros_like(A)
#第1级图像
rowX2 = gpA[1].shape[0]
colX2 = gpA[1].shape[1]
G[:rowX2, :colX2, :] = gpA[1]
#第2级图像
rowX4 = rowX2 // 2
colX4 = colX2 // 2
G[rowX2:rowX2+rowX4, colX2:colX2+colX4, :] = gpA[2]
G[:rowX4, colX2:colX2+colX4, :] = gpA[2]
#第3级图像
rowX8 = rowX4 // 2
colX8 = colX4 // 2
G[rowX2+rowX4:rowX2+rowX4+rowX8, colX2+colX4:colX2+colX4+colX8, :] = gpA[3]
G[ :rowX8, colX2+colX4:colX2+colX4+colX8, :] = gpA[3]
cv2.imshow("Gaussian Pyramid", G)
cv2.waitKey(0)
cv2.destroyAllWindows()
结果输出如下:
上面的例子,只是介绍了向下采样的情况,现在来学习利用图像金字塔完成两幅图像混合,具体步骤如下:
- 加载两幅图像
- 生成两幅图像的高斯金字塔
- 从高斯金字塔生成拉普拉斯金字塔
- 每一级的拉普拉斯金字塔进行一半合并
- 采用向上重构图像
具体例子如下:
#python 3.7.4,opencv4.1
#蔡军生 https://blog.csdn.net/caimouse/article/details/51749579
#
import numpy as np
import cv2
from matplotlib import pyplot as plt
#读取图片
A = cv2.imread('apple1.png')
B = cv2.imread('orange1.png')
h, w = A.shape[:2]
B = cv2.resize(B, (w,h))
#从A生成高斯金字塔
G = np.copy(A)
gpA = [G]
for i in range(6):
G = cv2.pyrDown(G)
gpA.append(G)
#从B生成高斯金字塔
G = np.copy(B)
gpB = [G]
for i in range(6):
G = cv2.pyrDown(G)
gpB.append(G)
#从A生成拉普拉斯金字塔
lpA = [gpA[5]]
for i in range(5,0,-1):
GE = cv2.pyrUp(gpA[i])
x, y = gpA[i-1].shape[0:2]
resizeImg = cv2.resize(GE,(y,x))
L = cv2.subtract(gpA[i-1],resizeImg)
lpA.append(L)
#从B生成拉普拉斯金字塔
lpB = [gpB[5]]
for i in range(5,0,-1):
GE = cv2.pyrUp(gpB[i])
x, y = gpB[i-1].shape[0:2]
resizeImg = cv2.resize(GE,(y,x))
L = cv2.subtract(gpB[i-1],resizeImg)
lpB.append(L)
#拉普拉斯金字塔合并,每个取半边
LS = []
for la,lb in zip(lpA,lpB):
rows,cols,dpt = la.shape
ls = np.hstack((la[:,0:cols//2], lb[:,cols//2:]))
LS.append(ls)
#重构混合图像
ls_ = LS[0]
for i in range(1,6):
ls_ = cv2.pyrUp(ls_)
x, y = LS[i].shape[0:2]
resizeImg = cv2.resize(ls_,(y,x))
ls_ = cv2.add(resizeImg, LS[i])
#从原图直接取半边的合并
cols = w//2
real = np.hstack((A[:,:cols],B[:,cols:]))
cv2.imshow('Pyramid_blending',ls_)
cv2.imshow('Direct_blending',real)
cv2.waitKey(0)
cv2.destroyAllWindows()
结果输出如下:
直接合并的混合效果
采用金字塔方式混合效果
https://blog.csdn.net/caimouse/article/details/102530873
转载:https://blog.csdn.net/caimouse/article/details/102541566
查看评论