# PythonComputerVision-4-ImageMosaic
全景图像拼接技术———在同一位置(即图像的照相机位置相同)拍摄的两幅或者多福图像是单应性相关的(p.s上一篇文章中详细介绍了“单应性相关概念”),我们经常使用该约束将很多图像缝补起来,拼成一个大的图像来创建全景图像。在本文中,将要探讨如何创建全景图像。
## 一.原理介绍
在进行图像拼接时,首先要解决的是找到图像之间的匹配的对应点。本文采用SIFT算法来实现特征点的匹配,SIFT是很强大的描述子,它能产生很少的错误的匹配,但仍然还是存在错误的对应点。所以需要用一种算法对SIFT算法产生的特征描述符进行剔除误匹配点。
### 1)RANSAC
RANSAC是“RANdom SAmple Consensus”(随机一致性采样)的缩写。RANSAC算法是一种经典的消除误匹配的方法,具有匹配精度高、可靠度强等优点,该方法是用来找到正确模型来拟合带有噪声数据的迭代方法。RANSAC的标准例子:用一条直线拟合带有噪声数据的点集。简单的最小二乘在该例子中可能会失效,但RANSAC可以挑选出正确的点,然后获取能够正确拟合的直线。
#### 示例
从一组观测数据中找出合适的2维直线。所给出的观测数据中包含正确点和错误点,正确点可以相似的被直线所通过,而错误点远离于直线,分布在其两侧。普通的最小二乘法找不到那条贯穿全部点的直线,因为它会努力的去适应包括错误点在内的所有点。而RANSAC算法能得出一个仅仅用正确点的计算模型,且命中率很高。但尽管如此,它也不能保证100%正确。
![image](https://github.com/Nocami/PythonComputerVision-4-ImageMosaic/blob/master/images/1.png)![image](https://github.com/Nocami/PythonComputerVision-4-ImageMosaic/blob/master/images/2.png)
图-包含很多点的数据集               图-RANSAC拟合的直线
### 2)单应性矩阵估计
在任何模型中都可以使用RANSAC模块,这里使用可能的对应点集来自动找到用于全景图像的单应性矩阵--使用SIFT特征自动找到匹配对应,可也使用如下代码:
~~~python
import sift
featname = ['./images5/'+str(i+1)+'.sift' for i in range(2)]
imname = ['./images5/'+str(i+1)+'.jpg' for i in range(2)]
l = {}
d = {}
for i in range(2):
sift.process_image(imname[i],featname[i])
l[i],d[i] = sift.read_features_from_file(featname[i])
matches = {}
for i in range(1):
matches[i] = sift.match(d[i+1],d[i])
~~~
**其中,第一个range(i)中i的值为要拼接的图像个数,第二个为第一个i-1。**
运行此例代码,我们可以看到,图像中的对应点并不是完全正确,还存在很多错误配对:
![image](https://github.com/Nocami/PythonComputerVision-4-ImageMosaic/blob/master/images/%E6%99%AF%E6%B7%B1%E5%B0%8FA1.jpg)
![image](https://github.com/Nocami/PythonComputerVision-4-ImageMosaic/blob/master/images/%E5%AE%A4%E5%86%851.jpg)
![image](https://github.com/Nocami/PythonComputerVision-4-ImageMosaic/blob/master/images/%E6%99%AF%E6%B7%B1%E5%A4%A71.jpg)
## 二.图像拼接
估计出图像见的单应性矩阵(使用RANSAC算法)后,将所有图像扭曲到一个公共平面上,就完成了一副简单的全景图像。一般的,这个公共平面选择为中心图像的平面,不然会发生大量的形变。因为我们的图像是由照相机水平旋转拍摄成的,所以我们可以使用一个简单的步骤:将中心图像左边或右边的区域填充0,为扭曲图像腾出空间。
**p.s需要注意的是:**若拼接图为两张,则影响不会很大,中心图像做为平面中心的操作在多福图像拼接时会有明显的效果。
### 1)代码:
~~~python
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
"""
This is the panorama example from section 3.3.
"""
# set paths to data folder
featname = ['./images5/'+str(i+1)+'.sift' for i in range(2)]
imname = ['./images5/'+str(i+1)+'.jpg' for i in range(2)]
# extract features and match
l = {}
d = {}
for i in range(2):
sift.process_image(imname[i],featname[i])
l[i],d[i] = sift.read_features_from_file(featname[i])
matches = {}
for i in range(1):
matches[i] = sift.match(d[i+1],d[i])
# visualize the matches (Figure 3-11 in the book)
for i in range(1):
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(0)
H_01 = homography.H_from_ransac(fp,tp,model)[0] #im 0 to 1
#fp,tp = convert_points(1)
#H_12 = homography.H_from_ransac(fp,tp,model)[0] #im 1 to 2
#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[0]), "uint8")
im2 = array(Image.open(imname[1]), "uint8")
im_12 = warp.panorama(H_01,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_12, "uint8"))
axis('off')
savefig("example1.png",dpi=300)
show()
~~~
此代码段为2图图像拼接,若需要多幅图,只需将其中的注释部分取消即可,图像顺序为自右向左。
### 2)实例效果
下面我们看看实际效果:
#### 双图-室外情况下、景深较小:
![image](https://github.com/Nocami/PythonComputerVision-4-ImageMosaic/blob/master/images/%E6%99%AF%E6%B7%B1%E5%B0%8FA1.jpg)
![image](https://github.com/Nocami/PythonComputerVision-4-ImageMosaic/blob/master/images/%E6%99%AF%E6%B7%B1%E5%B0%8FA2.jpg)
nice!看起来毫无PS痕迹!
再看一组同样条件下的照片:
![image](https://github.com/Nocami/PythonComputerVision-4-ImageMosaic/blob/master/images/%E6%99%AF%E6%B7%B1%E5%B0%8FB1.jpg)
![image](https://github.com/Nocami/PythonComputerVision-4-ImageMosaic/blob/master/images/%E6%99%AF%E6%B7%B1%E5%B0%8FB2.jpg)
这一组可以看到明显的拼接缝隙,这是由照片的色差造成的,我们可以看到整体效果还不错。
#### 双图-室外情况下、景深较大:
![image](https://github.com/Nocami/PythonComputerVision-4-ImageMosaic/blob/master/images/%E6%99%AF%E6%B7%B1%E5%A4%A71.jpg)
![image](https://github.com/Nocami/PythonComputerVision-4-ImageMosaic/blob/master/images/%E6%99%AF%E6%B7%B1%E5%A4%A72.jpg)
当物体景深过大时,会产生尺度问题,影响拼接图像的质量,我们可以看到右下角树干有明显瑕疵。
#### 双图-室内情况、焦距近、图像杂乱:
![image](https://github.com/Nocami/PythonComputerVision-4-ImageMosaic/blob/master/images/%E5%AE%A4%E5%86%851.jpg)
![image](https://github.com/Nocami/PythonComputerVision-4-ImageMosaic/blob/master/images/%E5%AE%A4%E5%86%852.jpg)
在这种情况下,算法效果就不是很好了,出现成功拼接�
没有合适的资源?快使用搜索试试~ 我知道了~
温馨提示
全景图像拼接_使用Python+SIFT算法实现特征点匹配实现全景图像拼接_项目源码_优质项目实战
资源推荐
资源详情
资源评论
收起资源包目录
全景图像拼接_使用Python+SIFT算法实现特征点匹配实现全景图像拼接_项目源码_优质项目实战.zip (43个子文件)
全景图像拼接_使用Python+SIFT算法实现特征点匹配实现全景图像拼接_项目源码_优质项目实战
.git
index 1KB
HEAD 23B
refs
heads
master 41B
tags
remotes
origin
HEAD 32B
objects
pack
pack-1fb7e1968932f5c8354aae7b798760565740b2bf.rev 272B
pack-1fb7e1968932f5c8354aae7b798760565740b2bf.idx 3KB
pack-1fb7e1968932f5c8354aae7b798760565740b2bf.pack 674KB
info
description 73B
packed-refs 114B
info
exclude 240B
logs
HEAD 199B
refs
heads
master 199B
remotes
origin
HEAD 199B
hooks
post-update.sample 189B
sendemail-validate.sample 2KB
prepare-commit-msg.sample 1KB
commit-msg.sample 896B
pre-receive.sample 544B
update.sample 4KB
pre-commit.sample 2KB
pre-rebase.sample 5KB
applypatch-msg.sample 478B
fsmonitor-watchman.sample 5KB
push-to-checkout.sample 3KB
pre-applypatch.sample 424B
pre-push.sample 1KB
pre-merge-commit.sample 416B
config 351B
t3.py 2KB
images
景深小A2.jpg 55KB
景深大1.jpg 109KB
景深小A1.jpg 75KB
景深小B1.jpg 76KB
s 1B
1.png 6KB
室内2.jpg 35KB
景深大2.jpg 87KB
室内1.jpg 77KB
fin2.jpg 54KB
景深小B2.jpg 52KB
2.png 9KB
fin1.jpg 33KB
README.md 8KB
共 43 条
- 1
资源评论
- gxy2zyx2024-04-25支持这个资源,内容详细,主要是能解决当下的问题,感谢大佬分享~
极智视界
- 粉丝: 2w+
- 资源: 1419
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功