Python图像处理之图像拼接

Python图像处理之图像拼接
⼀、算法⽬的
  在同⼀位置(即图像的相机位置相同)拍摄两张以上图⽚,这些图⽚是单应性相关的,即图⽚之间有相同的拍摄区域。基于此将图⽚进⾏缝补,拼成⼀个⼤的图像来创建全景图像。
⼆、基本原理
  要实现两张图⽚的简单拼接,其实只需出两张图⽚中相似的点 (⾄少四个,因为 homography 矩阵的计算需要⾄少四个点),计算⼀张图⽚可以变换到另⼀张图⽚的变换矩阵 (homography 单应性矩阵),⽤这个矩阵把那张图⽚变换后放到另⼀张图⽚相应的位置,就是相当于把两张图⽚中定好的四个相似的点重合在⼀起。如此,就可以实现简单的全景拼接。
三、实现步骤
  1、读⼊连续图⽚并使⽤SIFT特征查匹配对应点对
import sift
featname = ['D:/LearnSrc/PythonSrc/Homework/Lecture05/images'+str(i+1)+'.sift'for i in range(5)]
imname = ['D:/LearnSrc/PythonSrc/Homework/Lecture05/images'+str(i+1)+'.jpg'for i in range(5)]
l = {}
d = {}
for i in range(5):
sift.process_image(imname[i],featname[i])
l[i],d[i] = ad_features_from_file(featname[i])
matches = {}
for i in range(4):
matches[i] = sift.match(d[i+1],d[i])
  测试结果
  sift算⼦存在错误的匹配点,因此需要⽤Ransac算法剔除错误匹配点。
  2、利⽤RANSAC算法计算变换矩阵
    2.1 RANSAC算法发光模组
氧气止回阀
    RANSAC是"RANdom SAmple Consensus"(随机⼀致采样)的缩写。该⽅法是⽤来到正确模型来拟合带有噪声数据的迭代⽅法。给定⼀个模型,例如点集之间的单应性矩阵。基本的思想是:数据中包含正确的点和噪声点,合理的模型应该能够在描述正确数据点的同时摒弃噪声点。
  求解单应性矩阵:
class RansacModel(object):
def__init__(self,debug=False):
self.debug = debugdef fit(self, data):
""" 计算选取四个对应的单应性矩阵 """
# 将其转置,来调⽤H_from_points()计算单应性矩阵
data = data.T
#映射的起始点
fp = data[:3,:4]
# 映射的⽬标点
tp = data[3:,:4]
#计算单应性矩阵然后返回
return H_from_points(fp,tp)
def get_error( self, data, H):
""" 对所有的对应计算单应性矩阵,然后对每个变换后的点,返回相应的误差 """
data = data.T
#映射的起始点
fp = data[:3]
# 映射的⽬标点
tp = data[3:]
#变换fp
fp_transformed = dot(H,fp)
#归⼀化齐次坐标
for i in range(3):
fp_transformed[i] /= fp_transformed[2]
return sqrt( sum((tp-fp_transformed)**2,axis=0) )
  以上可看出,这个类包含fit()⽅法,仅接受由ransac算法选择的4个对应点对(data中的前4个点对),然后拟合⼀个单应性矩阵。get_error()⽅法对每个对应点对使⽤该单应性矩阵,然后返回相应的平⽅距离之和。因此ransac算法能够判定正确与错误的点。在实际中,还需在距离上使⽤⼀个阈值来决定合理的单应性矩阵是哪些。
  3.拼接图像:
估计出图像间的单应性矩阵后(使⽤RANSAC算法),需要将所有的图像扭曲到⼀个公共的图像平⾯上。通常,这⾥的公共平⾯为中⼼图像平⾯(否则需要进⾏⼤量变形)。⼀种⽅法是创建⼀个很⼤的图像,⽐如图像中全部填充0,使其和中⼼图像平⾏,然后将所有的图像扭曲到上⾯。由于我所有的图像是由照相机⽔平旋转拍摄的,因此可使⽤⼀个较简单的步骤:将中⼼图像左边或右边的区域填充0,以便为扭曲的图像腾出空间。
  代码:
from array import array
from numpy import dot
from numpy.ma import vstack
from pylab import *
from PIL import Image
# If you have PCV installed, these imports should work
ry import homography, warp
from PCV.localdescriptors import sift
"""
This is the panorama example from section 3.3.
"""
# set paths to data folder
featname = ['D:/LearnSrc/PythonSrc/Homework/Lecture05/images/0' + str(i + 1) + '.sift'for i in range(5)]
imname = ['D:/LearnSrc/PythonSrc/Homework/Lecture05/images/0' + 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] = ad_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("example5.png", dpi=300)
show()
四、实验结果
  注:图⽚不能太⼤,要拼接的图⽚的分辨率必须都相同。
  第⼀次运⾏结果:
  图⽚:
  以第⼀张图为开始的结果:
  由第三张图为中⼼拼接的结果:
  从上⾯个结果可以看出,拼接的效果很不好。想过是不是因为拍摄的图⽚不好,周围建筑太相似⽽造成这种结果,所以重新拍摄了3张新照⽚测试:
  运⾏结果:
  可以发现右边的拼接效果⽐左边好很多,回头看前⼏次的运⾏结果,同样也是右边的效果⽐左边好⼀些。
  看代码似乎与拼接的⽅向有关,但改成从右边往左拼接也没得到⽐较好的效果。
  最后将图⽚的顺序改成倒序,并以第三张为中⼼拼接,得到的效果最好....同时也可以看出上⾯说的太多相似建筑⽽导致拼接效果不好的想法是不成⽴的。
  从上⾯的结果可以看到,这种⽅法可以得到⼀个⽐较好的拼接效果。但仍然存在许多问题,⽐如图⽚有些拼接部位倾斜拉伸严重,有些地⽅的拼接缝⽐较明显。还有上⾯出现的断开的情况。这可能是由于拍摄时没有站在固定的⼀个点⽽造成的结果。
  选的图⽚不是固定点拍摄、以及拼接的顺序不对的话,怎么做拼接效果都会很差。。
参考:

本文发布于:2024-09-22 01:39:23,感谢您对本站的认可!

本文链接:https://www.17tex.com/tex/1/228112.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:拼接   图像   矩阵   单应性   结果   效果   拍摄
留言与评论(共有 0 条评论)
   
验证码:
Copyright ©2019-2024 Comsenz Inc.Powered by © 易纺专利技术学习网 豫ICP备2022007602号 豫公网安备41160202000603 站长QQ:729038198 关于我们 投诉建议