多视图几何——计算机视觉

一、简述

多视,可以是一个相机拍摄的多角度图像,也可以是很多相机拍摄的multi view图像,目标是按照马尔的理论重建三维结构,这是目前人类知识的边界,我们暂时认为人类的视觉认知是通过三维的逐层重建完成的,当然还有其他理论,但这是目前统治的看法。

二、原理

图片以及一些描述来自于:对极几何及单应矩阵
1、对极几何(Epipolar Geometry)
对极几何,用来描述的是如果有一个场景的两个视图以及视图中的对应图像点,那么根据照相机间的空间相对位置关系、照相机的性质以及三维场景点的位置,可以得到对这些图像点的一些几何关系约束。
在这里插入图片描述
极点e和e’:e是左边相机中心在右图像平面上的投影,e’右相机中心在左像平面上的投影
极平面:两个相机中心和点p形成的平面
极线l和l’:极平面分别和两个像平面的交线
在这里插入图片描述
若其中一相机中心e分别与像平面交于ee’,o、o’、p已知,即不知道p点的深度信息的情况下,射线op是p点可能的空间位置,o’p的连线同另一个像平面的交点即为p对应在该平面上的位置,可知P点对应在另一个像平面上的位置总是会在一条直线上,即在极线l’上
2.本质矩阵的求解
对极约束是一个等式为零的约束,因此对他乘以非零常数后依然成立,这称为本质矩阵的尺度等价性。另一方面,由于平移和旋转各有三个自由度,故 E 共有六个自由度,但由于尺度等价性,因此实际上 E 具有5个自由度。
即最少可用5对点来求解 E,但是这种解法比较麻烦。考虑 E 的尺度等价性,可以使用8对点来求解,即经典的八点法,八点法利用了 E 的线性性质,因此可以通过线性代数求解。

在这里插入图片描述
在这里插入图片描述
3.八点法
基本矩阵的定义为:
在这里插入图片描述
其中x↔x’是两幅图像的任意一对匹配点。由于每一组点的匹配提供了计算FF系数的一个线性方程,当给定至少7个点(3×3的齐次矩阵减去一个尺度,以及一个秩为2的约束),方程就可以计算出未知的F。
在这里插入图片描述
展开后有
在这里插入图片描述
把矩阵F写成列向量的形式,则有:
在这里插入图片描述
给定n组点的集合可得:
在这里插入图片描述
如果存在确定(非零)解,则系数矩阵A的秩最多是8。由于F是齐次矩阵,所以如果矩阵A的秩为
8,则在差一个尺度因子的情况下解是唯一的。可以直接用线性算法解得。8点算法是计算基本矩阵的最简单的方法。为了提高解的稳定性和精度,往往会对输入点集的坐标先进行归一化处理。

三、要求

1.分别用七点、八点、十点(匹配点),计算基础矩阵
(1)左右拍摄,极点位于图像平面上
(2)像平面接近平行,极点位于无穷远
(3)图像拍摄位置位于前后
2. 针对上述情况,画出极点和极线,其中点坐标要均匀分布于各行

四、代码

1.先利用sift提取特征RANSAC,去除错误点匹配,再归一化8点算法估计基础矩阵

from PIL import Image
from numpy import *
from pylab import *
import numpy as np

import PCV.geometry.camera as camera
import PCV.geometry.homography as homography
import PCV.geometry.sfm as sfm
import PCV.localdescriptors.sift as sift

im1 = array(Image.open('D:/Study/untitled1/222/11.jpg'))
sift.process_image('D:/Study/untitled1/222/11.jpg', 'im1.sift')

im2 = array(Image.open('D:/Study/untitled1/222/12.jpg'))
sift.process_image('D:/Study/untitled1/222/12.jpg', 'im2.sift')

l1, d1 = sift.read_features_from_file('im1.sift')
l2, d2 = sift.read_features_from_file('im2.sift')

matches = sift.match_twosided(d1, d2)

ndx = matches.nonzero()[0]
x1 = homography.make_homog(l1[ndx, :2].T)
ndx2 = [int(matches[i]) for i in ndx]
x2 = homography.make_homog(l2[ndx2, :2].T)

d1n = d1[ndx]
d2n = d2[ndx2]
x1n = x1.copy()
x2n = x2.copy()

figure(figsize=(16,16))
sift.plot_matches(im1, im2, l1, l2, matches, True)
show()

def F_from_ransac(x1, x2, model, maxiter=5000, match_threshold=1e-3):
    """ Robust estimation of a fundamental matrix F from point
    correspondences using RANSAC (ransac.py from
    http://www.scipy.org/Cookbook/RANSAC).

    input: x1, x2 (3*n arrays) points in hom. coordinates. """

    import PCV.tools.ransac as ransac
    data = np.vstack((x1, x2))
    d = 10 # 20 is the original
    F, ransac_data = ransac.ransac(data.T, model,
                                   7, maxiter, match_threshold, d, return_all=True)
    return F, ransac_data['inliers']

model = sfm.RansacModel()
F, inliers = F_from_ransac(x1n, x2n, model, maxiter=5000, match_threshold=1e-3)
print (F)

P1 = array([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0]])
P2 = sfm.compute_P_from_fundamental(F)

X = sfm.triangulate(x1n[:, inliers], x2n[:, inliers], P1, P2)


cam1 = camera.Camera(P1)
cam2 = camera.Camera(P2)
x1p = cam1.project(X)
x2p = cam2.project(X)

figure(figsize=(16, 16))
imj = sift.appendimages(im1, im2)
imj = vstack((imj, imj))

imshow(imj)

cols1 = im1.shape[1]
rows1 = im1.shape[0]
for i in range(len(x1p[0])):
    if (0<= x1p[0][i]<cols1) and (0<= x2p[0][i]<cols1) and (0<=x1p[1][i]<rows1) and (0<=x2p[1][i]<rows1):
        plot([x1p[0][i], x2p[0][i]+cols1],[x1p[1][i], x2p[1][i]],'c')
axis('off')
show()

d1p = d1n[inliers]
d2p = d2n[inliers]


print (P1)
print (P2)

2.外极点显示

import numpy as np
import cv2 as cv
from matplotlib import pyplot as plt


def drawlines(img1, img2, lines, pts1, pts2):
    ''' img1 - image on which we draw the epilines for the points in img2
        lines - corresponding epilines '''
    r, c = img1.shape
    img1 = cv.cvtColor(img1, cv.COLOR_GRAY2BGR)
    img2 = cv.cvtColor(img2, cv.COLOR_GRAY2BGR)
    for r, pt1, pt2 in zip(lines, pts1, pts2):
        color = tuple(np.random.randint(0, 255, 3).tolist())
        x0, y0 = map(int, [0, -r[2] / r[1]])
        x1, y1 = map(int, [c, -(r[2] + r[0] * c) / r[1]])
        img1 = cv.line(img1, (x0, y0), (x1, y1), color, 1)
        img1 = cv.circle(img1, tuple(pt1), 5, color, -1)
        img2 = cv.circle(img2, tuple(pt2), 5, color, -1)
    return img1, img2


img1 = cv.imread('D:/Study/untitled1/222/31.jpg', 0)  # queryimage # left image
img2 = cv.imread('D:/Study/untitled1/222/32.jpg', 0)  # trainimage # right image
sift = cv.xfeatures2d.SIFT_create()
# find the keypoints and descriptors with SIFT
kp1, des1 = sift.detectAndCompute(img1, None)
kp2, des2 = sift.detectAndCompute(img2, None)
# FLANN parameters
FLANN_INDEX_KDTREE = 1
index_params = dict(algorithm=FLANN_INDEX_KDTREE, trees=5)
search_params = dict(checks=50)
flann = cv.FlannBasedMatcher(index_params, search_params)
matches = flann.knnMatch(des1, des2, k=2)
good = []
pts1 = []
pts2 = []
# ratio test as per Lowe's paper
for i, (m, n) in enumerate(matches):
    if m.distance < 0.8 * n.distance:
        good.append(m)
        pts2.append(kp2[m.trainIdx].pt)
        pts1.append(kp1[m.queryIdx].pt)

pts1 = np.int32(pts1)
pts2 = np.int32(pts2)
F, mask = cv.findFundamentalMat(pts1, pts2, cv.FM_LMEDS)
# We select only inlier points
pts1 = pts1[mask.ravel() == 1]
pts2 = pts2[mask.ravel() == 1]

# Find epilines corresponding to points in right image (second image) and
# drawing its lines on left image
lines1 = cv.computeCorrespondEpilines(pts2.reshape(-1, 1, 2), 2, F)
lines1 = lines1.reshape(-1, 3)
img5, img6 = drawlines(img1, img2, lines1, pts1, pts2)
# Find epilines corresponding to points in left image (first image) and
# drawing its lines on right image
lines2 = cv.computeCorrespondEpilines(pts1.reshape(-1, 1, 2), 1, F)
lines2 = lines2.reshape(-1, 3)
img3, img4 = drawlines(img2, img1, lines2, pts2, pts1)
plt.subplot(121), plt.imshow(img5)
plt.subplot(122), plt.imshow(img3)
plt.show()

五、结果与分析

实验样本:在这里插入图片描述
1.2为图像拍摄位置位于前后
3.4.5为平行
6.7为左右极点

(1)左右极点
sift特征点匹配结果
在这里插入图片描述

外极点
在这里插入图片描述

(2)平行
sift匹配结果
在这里插入图片描述
ransac去错误匹配
在这里插入图片描述
7点法基础矩阵
在这里插入图片描述
8点法基础矩阵
在这里插入图片描述
10点法基础矩阵
在这里插入图片描述
外极点
在这里插入图片描述
(3)远近效果
sift匹配结果
在这里插入图片描述
外极点
在这里插入图片描述

六、总结

当我们有同一场景的多个视图时,三维重建会变得更加准确,包括更多的细节信息。因为基本矩阵只和一对视图相关,所以该过程带有很多图像,和之前的处理有些不同。
在图片远近和左右的实验中出现了ValueError: did not meet fit acceptance criteria
在网上找的时候,始终没有解决该问题,唯一的说法是室内室外的原因,可是平行却是可以的,我觉得不是这个问题,可能是图片角度不好。

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值