2021-04-25
Posted 差不多女生
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2021-04-25相关的知识,希望对你有一定的参考价值。
计算机视觉实验—创建全景图
创建全景图主要做的是基于sift特征匹配然后使用RANSAC全景图像拼接
1.RANSAC
1.RANSAC(随机一致性采样)概述
RANSAC,该方法是用来找到正确模型来拟合带有噪声数据的迭代方法。
基本思想:数据中包含正确的点和噪声点,合理的模型应该能够在描述正确数据点的同时摒弃噪声点。
例如;当用一条直线你和带有噪声的数据的点集。简单的最小二乘法可能无法完成,但是RANSAC能够挑出正确的点,然后获取能够正确拟合的直线。
在本实验中就利用到RANSAC算法来求解单应性矩阵。
2.单应性矩阵
单应性矩阵可以由两幅图像(或者平面)中对应点对计算出来。每个对应点可以写出两个方程,分别对应与x和y坐标。因此,计算单应性矩阵H至少需要4对匹配点
可以每次从所有的匹配点中选出4对,计算单应性矩阵,然后选出内点个数最多的作为最终的结果。计算距离方法如下:
3.拼接图象
使用RANSAC算法计算出图像间单应性矩阵,我们选取中心的图像作为公共平面,将中心图像左右的区域以0填充,这样就可以将扭曲后的图像拼接到腾出的空间当中。
2.步骤
1、检测并提取图像的特征和关键点
2、匹配两个图像之间的描述符
3、使用RANSAC算法使用我们匹配的特征向量估计单应矩阵
4、拼接图像
步骤一和步骤二过程是运用SIFT局部描述算子检测图像中的关键点和特征,SIFT特征是基于物体上的一些局部外观的兴趣点而与影像的大小和旋转无关。对于光线、噪声、些微视角改变的容忍度也相当高,所以用来检测要拼接图像的特征及关键点就很有优势。
步骤三是使用RANSAC算法求解单应性矩阵,由ransac选择4个对应点对,然后拟合一个单应性矩阵,再对每个对应点对使用该单应性矩阵,然后返回相应的平方距离和,最后再用一个阈值决定合理的单应性矩阵 。
3.拼接图像
估计出单应性矩阵H后,我们需要将所有图像扭曲到一个公共的图像平面上。通常,这里的公共平面为中心平面(否则,需要进行大量变形)。一种方法是创建一个很大的图像,比如将平面中全部填充为0,使其和中心图像平行,然后将所有的图像扭曲到上面。我们可以使用一个比较简单的步骤:
(1)将中心图的左边或右边的区域填充为0(以便为扭曲的图像腾出空间)
(2)实现像素间的映射(计算像素和和单应性矩阵H相乘,然后对齐次坐标进行归一化)
(3)判断图像填补位置(查看H中的平移量,左边为正,右边为负)
(4)在单应性矩阵中加入平移量(平移量可以决定应该将图像填补到左边还是右边),进行alpha图填充
4.程序代码
from array import array
from matplotlib._layoutbox import vstack
from numpy import dot
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
# 设置数据文件夹的路径
featname = [r'C:\\Users\\17912\\PycharmProjects\\untitled\\q' + str(i + 1) + '.sift' for i in range(5)]
imname = [r'C:\\Users\\17912\\PycharmProjects\\untitled\\q' + str(i + 1) + '.jpg' for i in range(5)]
# 使用sift特征自动找到匹配对应
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])
# 可视化两张图像
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)
# 将匹配项转化为特征点
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
# 估计单应性矩阵
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
# 扭曲图像
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')
show()
5.实验效果
特征点匹配:
全景效果:
6.实验总结
遇到的错误:
解决方法:因为图片太大,修改图片大小或压缩图片即可。
小结:
1.全景图像拼接通过SIFT得到特征匹配,通过RANSAC筛选正确的特征匹配得到透视矩阵,利用透视变换完成图像的拼接,循环这个流程迭代所有图像就可以完成多张图像的全景图拼接。也因为基于SIFT特征匹配,对于不同平面下的图像,拼接效果一般,拼接缝也较为明显。
2RANSAC中get_error()返回相应的平方距离和,。距离的阈值和最小期望的点对数目可以在**H_from_ransac()**函数当中指定,而最大迭代次数决定此次点对筛选的时间效率和准确度,太少会导致拟合模型中正确结果被剔除留下错误结果,太多占用大量运行时间。
3在拍摄图像时相机应尽量保持在同一位置,同一水平线上移动,每次取景的位移基本相同则可以得到较好的全景效果
以上是关于2021-04-25的主要内容,如果未能解决你的问题,请参考以下文章
2023-02-14:魔物了占领若干据点,这些据点被若干条道路相连接, roads[i] = [x, y] 表示编号 xy 的两个据点通过一条道路连接。 现在勇者要将按照以下原则将这些据点逐一夺回: