图像处理之图像拼接(python)

图像处理之图像拼接(python)
⼀、算法⽬的
在同⼀位置拍摄两张以上图⽚,这些图⽚是单应性相关的,即图⽚之间有相同的拍摄区域。基于此将图⽚进⾏缝补,拼成⼀个⼤的图像来创建全景图像。
⼆、基本原理
要实现两张图⽚的简单拼接,其实只需出两张图⽚中相似的点 (⾄少四个,因为 homography 矩阵的计算需要⾄少四个点), 计算⼀张图⽚可以变换到另⼀张图⽚的变换矩阵 (homography 单应性矩阵),⽤这个矩阵把那张图⽚变换后放到另⼀张图⽚相应的位置 ,就是相当于把两张图⽚中定好的四个相似的点重合在⼀起。如此,就可以实现简单的全景拼接。高硅氧布
实现步骤
1. 读⼊连续图⽚并使⽤SIFT特征查匹配对应点对
import sift条纹码
#sift程序应与运⾏图⽚在同⼀⽂件夹下
featname = ['C:/Users/Administrator/Documents/python/jmu'+str(i+1)+'.sift' for i in range(5)]
imname = ['C:/Users/Administrator/Documents/python/jmu'+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"(随机⼀致采样)的缩写。该⽅法是⽤来到正确模型来拟合带有噪声数据的迭代⽅法。给定⼀个模型,例如点集之间的单应性矩阵。基本的思想是:数据中包含正确的点和噪声点,合理的模型应该能够在描述正确数据点的同时摒弃噪声点。
⽰例
⼀个简单的例⼦是从⼀组观测数据中出合适的2维直线。假设观测数据中包含局内点和局外点,其中局内点近似的被直线所通过,⽽局外点远离于直线。简单的最⼩⼆乘法不能到适应于局内点的直线,原因是最⼩⼆乘法尽量去适应包括局外点在内的所有点。相反,RANSAC能得出⼀个仅仅⽤局内点计算出模型,并且概率还⾜够⾼。但是,RANSAC并不能保证结果⼀定正确,为了保证算法有⾜够⾼的合理概率,我们必须⼩⼼的选择算法的参数。
概述
RANSAC算法的输⼊是⼀组观测数据,⼀个可以解释或者适应于观测数据的参数化模型,⼀些可信的参数。 通过反复选择数据中的⼀组随机⼦集来达成⽬标。被选取的⼦集被假设为局内点,并⽤下述⽅法进⾏验证:金属防水接头
(1) 先随机假设⼀⼩组局内点为初始值。然后⽤此局内点拟合⼀个模型,此模型适应于假设的局内点,所有的未知参数都能从假设的局
内点计算得出。
压延加工
(2) ⽤1中得到的模型去测试所有的其它数据,如果某个点适⽤于估计的模型,认为它也是局内点,将局内点扩充。
(3) 如果有⾜够多的点被归类为假设的局内点,那么估计的模型就⾜够合理。
(4) ⽤所有假设的局内点去重新估计模型,因为此模型仅仅是在初始的假设的局内点估计的,后续有扩充后,需要更新。
(5)通过估计局内点与模型的错误率来评估模型。
整个这个过程为迭代⼀次,此过程被重复执⾏固定的次数,每次产⽣的模型有两个结局:
a. 因为局内点太少,效果不如前⼀次的模型,⽽被舍弃,
b. 存在⽐现有的更好的模型⽽被选⽤。
求解单应性矩阵:
class RansacModel(object):
""" Class for testing homography fit with ransac.py from
/Cookbook/RANSAC"""
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.进⾏图像拼接
估计出图像间的单应性矩阵后,需要将所有的图像扭曲到⼀个公共的图像平⾯上。通常,这⾥的公共平⾯为中⼼图像平⾯(否则需要进⾏⼤量变形)。⼀种⽅法是创建⼀个很⼤的图像,⽐如图像中全部填充0,使其和中⼼图像平⾏,然后将所有的图像扭曲到上⾯。由于我所有的图像是由照相机⽔平旋转拍摄的,因此可使⽤⼀个较简单的步骤:将中⼼图像左边或右边的区域填充0,以便为扭曲的图像腾出空间。
运⾏代码
from pylab import *
from numpy 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 = ['C:/Users/Administrator/Documents/python/jmu'+str(i+1)+'.sift' for i in range(5)]
imname = ['C:/Users/Administrator/Documents/python/jmu'+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 = {}
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([fp[1],fp[0],fp[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 = 1200 # 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("example.png",dpi=300)
show()
三、实现结果
3.1 室内场景
初始图像
拼接后的图像
室内图⽚拼接图⽚中出现问题。
分析:
1、分割明显
2、照⽚歪斜严重
3、物体变形严重
原因分析:
1、建筑物相似
2、⾓度选取不佳
3、第⼆张和最后⼀张明显的匹配标志物

本文发布于:2024-09-22 00:53:45,感谢您对本站的认可!

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

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

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