图像拼接技术就是将数张有重叠部分的图像(可能是不同时间、不同视角或者不同传感器获得的)拼成一幅无缝的全景图或高分辨率图像的技术。
特征提取 Feature Extraction:在所有输入图像中检测特征点
图像配准 Image Registration:建立了图像之间的几何对应关系,使它们可以在一个共同的参照系中进行变换、比较和分析。
大致可以分为以下几个类
图像变形 Warping:
图像变形是指将其中一幅图像的图像重投影,并将图像放置在更大的画布上。
图像融合 Blending
图像融合是通过改变边界附近的图像灰度级,去除这些缝隙,创建混合图像,从而在图像之间实现平滑过渡。混合模式(Blend modes)用于将两层融合到一起。
上一篇博客有介绍https://blog.csdn.net/qq_41958347/article/details/104632766
图像配准是将两张场景相关的图像进行映射,寻找其中的关系,多用在医学图像配准、图像拼接、不同摄像机的几何标定等方面,其研究也较为成熟。
图像配准寻找一种空间变换把一幅图像映射到另一幅图像,使变化后的图像能与上一张图像拼接,但是两张图片之间的景深不同,所以如果直接将两张图片映射到一张,就会产生鬼影,这种现象是无法避免的。而apap算法则是将图像分为若干个区域,在每个小区域内进行图像的匹配和映射,这样能够减少因为景深而带来的鬼影现象
Apap算法原理https://blog.csdn.net/warrenwg/article/details/49759779
Apap虽然能够较好地完成配准,但非常依赖于特征点对。若图像高频信息较少,特征点对过少,配准将完全失效,并且对大尺度的图像进行配准,其效果也不是很好,一切都决定于特征点对的数量。
图像分割就是把图像分成若干个特定的、具有独特性质的区域并提出感兴趣目标的技术和过程。它是由图像处理到图像分析的关键步骤。
运用最大流最小割定理,可以找出两张图片拼接成的图片中找出最小割沿着最小割将图片分外两部分,两个部分分别使用对应的图片映射,这样得到的拼接图片会有更好的效果
Multi-Band算法就是将图像分解为不同频带的分量之加和,图像的宏观特征在它的低频分量图里,而局域特征在高频分量图里。
计算输入图像的高斯金字塔
计算输入图像的拉普拉斯金字塔
将处于同一级的拉普拉斯金字塔进行融合。可以是简单的线性融合。
将高层的拉普拉斯金字塔依次扩展直至和源图像相同分辨率
from pylab import *
from numpy import *
from PIL import Image
# If you have PCV installed, these imports should work
from PCV.geometry import homography, warp
from PCV.localdescriptors import sift
import numpy as np
"""
This is the panorama example from section 3.3.
"""
np.seterr(divide='ignore', invalid='ignore')
# set paths to data folder
featname = ['E:/picture/imageMosaic/' + str(i + 1) + '.sift' for i in range(5)]
imname = ['E:/picture/imageMosaic/' + str(i + 1) + '.jpg' for i in range(5)]
# extract features and match
l = {}
d = {}
for i in range(5):
sift.process_image(imname[i], featname[i])
l[i], d[i] = sift.read_features_from_file(featname[i])
matches = {}
for i in range(4):
matches[i] = sift.match(d[i + 1], d[i])
# visualize the matches (Figure 3-11 in the book)
for i in range(4):
im1 = array(Image.open(imname[i]))
im2 = array(Image.open(imname[i + 1]))
figure()
#sift.plot_matches(im2, im1, l[i + 1], l[i], matches[i], show_below=True)
# function to convert the matches to hom. points
def convert_points(j):
ndx = matches[j].nonzero()[0]
fp = homography.make_homog(l[j + 1][ndx, :2].T)
ndx2 = [int(matches[j][i]) for i in ndx]
tp = homography.make_homog(l[j][ndx2, :2].T)
# switch x and y - TODO this should move elsewhere
fp = vstack([fp[1], fp[0], fp[2]])
tp = vstack([tp[1], tp[0], tp[2]])
return fp, tp
# estimate the homographies
model = homography.RansacModel()
fp, tp = convert_points(1)
H_12 = homography.H_from_ransac(fp, tp, model)[0] # im 1 to 2
fp, tp = convert_points(0)
H_01 = homography.H_from_ransac(fp, tp, model)[0] # im 0 to 1
tp, fp = convert_points(2) # NB: reverse order
H_32 = homography.H_from_ransac(fp, tp, model)[0] # im 3 to 2
tp, fp = convert_points(3) # NB: reverse order
H_43 = homography.H_from_ransac(fp, tp, model)[0] # im 4 to 3
# warp the images
delta = 2000 # for padding and translation
im1 = array(Image.open(imname[1]), "uint8")
im2 = array(Image.open(imname[2]), "uint8")
im_12 = warp.panorama(H_12, im1, im2, delta, delta)
im1 = array(Image.open(imname[0]), "f")
im_02 = warp.panorama(dot(H_12, H_01), im1, im_12, delta, delta)
im1 = array(Image.open(imname[3]), "f")
im_32 = warp.panorama(H_32, im1, im_02, delta, delta)
im1 = array(Image.open(imname[4]), "f")
im_42 = warp.panorama(dot(H_32, H_43), im1, im_32, delta, 2 * delta)
figure()
imshow(array(im_42, "uint8"))
axis('off')
savefig("imageMosaic.png", dpi=300)
show()
摄像机位置不变角度相同 景深大
摄像机位置不同拍摄同一近景物体
拼接结果
对于相同物体的多角度拼接效果不好,可以看出是将物体分成了两个部分,从物体左边拍摄的两张图片拼接成了一张,物体右边拍摄的图片拼接成了一张.
1 在获取图像集时要注意图片直接的水平差不能太大,每张图片与相邻图片的重合度最少要达到15%左右,要不然代码无法实现图像拼接
2 在选择图片集的过程中发现,如果对场景比较单一的图片集,拼接的效果不好,可能是因为场景单一,而导致图片直接的特征点数量较少,所以对拼接结果造成了影响。
3 景深大的图集拼接效果更好