计算机视觉第六次实验-对极几何和基础矩阵

计算机视觉第六次实验-对极几何和基础矩阵


通过对极几何一副图像上的点可以确定另外一幅图像上的一条直线,这种情况用基础矩阵来表示。通过一种映射,一幅图像上的点可以确定另外一副图像上的一个点,这种情况用单应矩阵。
本质矩阵是基础矩阵的一种特殊情况,是在归一化图像坐标下的基础矩阵。

一、对极几何

如果仅看一个相机,我们并不能知道深度信息,可如果有两个相机的话(就像人有两只眼睛)我们就能得到深度的信息,

img

在上图,我们把两相机中心的连线OO’成为基线,把他们与观测物体的平面OO’P成为对极平面,对极平面与两相机图像的交线l和l’称为对极线,而OO’与两图像的交点e,e’就是对极点。

随着观测点P的上下移动,对极平面也会围绕基线旋转

img我们可以看到在左图对极平面旋转时对极点是不变的,而在相机图像上所有对极线都会交于对极点,这个对极点就是另一个相机中心在其图像上的像,当然正如右图所示,对极点可以在图像外。

img

过e, e′的平面 π ,其平面上所有点在两个像平面中的 投影分别为直线 l 与 l’。
上面的左侧视图的图像平面上的点x,反向投影到射线cX上。由于点的深度未知,图像平面上的点x可能是射线上某一深度的3D点X。给定一对图像,当C,C’,x已知,第一幅图像上的每个点,在另外一幅图像上存在一条直线l’与之对应,也就是第二幅向上与点x对应的点x’必定在线l’上。

二、基础矩阵、本质矩阵

存在一个不经过两个相机光心的的平面π,光心C与x的射线与平面π相交与一点X。该点X又投影到第二幅图像平面上的点x′。这个称为点x通过平面π的转移。点x,x′是平面ππ上的3D点X在两个相机平面上的像。对应每一个3D点X都存在一个2D的单应R把每一个x映射到x′。

img

如上图所示,给定一个目标点P,以左摄像头光心Ol为原点。点P相对于光心Ol的观察位置为Pl,相对于光心Or的观察位置为Pr。点P在左摄像头成像平面上的位置为pl,在右摄像头成像平面上的位置为pr。
现在我们要寻找由点P、Ol和Or确定的对极平面的表达式。注意到平面上任意一点x与点a的连线垂直于平面法向量n,即向量 (x-a) 与向量 n 的点积为0:(x-a)·n = 0。在Ol坐标系中,光心Or的位置为T,则P、Ol和Or确定的对极平面可由下式表示:

img

由Pr = R(Pl-T) 和 可得:

另一方面,向量的叉积又可表示为矩阵与向量的乘积,记向量T的矩阵表示为S,得:

img

img

也就可以得到img
就可以得到本质矩阵E=RS。
通过矩阵E我们知道Pl和Pr的关系满足:

img

根据相似三角形定理,pl = flPl/Zl 和 pr = frPr/Zr 我们可以得到点P在左右两个摄像机坐标系中的观察点 pl 和 pr 应满足的极线约束关系为:

img

注意到 E 是不满秩的,它的秩为2,
那么

img

表示的是一条直线,也就是对极线。

基础矩阵
将摄像机的内参信息将摄像头坐标系与图像像素坐标系联系起来。
pl和pr是物理坐标值,对应的像素坐标值为ql和qr,摄像头内参矩阵为M,则有img
也就是根据

img

会得到img最后,便会得到基础矩阵img

以及img

三、实验图片

四、实验代码

绘制sift特征匹配,ransac筛选匹配点,基础矩阵代码

# -*- coding: utf-8 -*-
from PIL import Image
from numpy import *
from pylab import *
import numpy as np
from PCV.geometry import camera
from PCV.geometry import homography
from PCV.geometry import sfm
from PCV.localdescriptors import sift

# 读特征点
im1 = array(Image.open('C:/Users/59287/PycharmProjects/untitled1/jz/3.jpg'))
sift.process_image('C:/Users/59287/PycharmProjects/untitled1/jz/3.jpg', 'C:/Users/59287/PycharmProjects/untitled1/jz/3.sift')
im2 = array(Image.open('C:/Users/59287/PycharmProjects/untitled1/jz/4.jpg'))
sift.process_image('C:/Users/59287/PycharmProjects/untitled1/jz/4.jpg', 'C:/Users/59287/PycharmProjects/untitled1/jz/4.sift')

l1, d1 = sift.read_features_from_file('C:/Users/59287/PycharmProjects/untitled1/jz/3.sift')
l2, d2 = sift.read_features_from_file('C:/Users/59287/PycharmProjects/untitled1/jz/4.sift')

matches = sift.match_twosided(d1, d2)

#使用齐次坐标表示,并使用inv(k)归一化
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()

# 使用RANSAC估计F
model = sfm.RansacModel()
F, inliers = F_from_ransac(x1n, x2n, model, maxiter=5000, match_threshold=1e-5)
print ('基础矩阵F:',F)

#计算投影矩阵
P1 = array([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0]])
P2 = sfm.compute_P_from_fundamental(F)

print ('F:',F)
print ('P2:',P2)

绘制极线代码

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('C:/Users/59287/PycharmProjects/untitled1/jz/3.jpg', 0)  # queryimage # left image
img2 = cv.imread('C:/Users/59287/PycharmProjects/untitled1/jz/4.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()

五、实验结果

5.1左右拍摄

5.1.1sift匹配特征
在这里插入图片描述
5.1.2ransac筛选匹配点
在这里插入图片描述5.3 基础矩阵F

在这里插入图片描述
5.1.4 极点极线绘制
在这里插入图片描述
左右拍摄时极线是稍微有点变动的,不过我运行的时候应该把图片弄反了。

5.2平行拍摄

5.2.1sift匹配特征
在这里插入图片描述
5.2.2ransac筛选匹配点
在这里插入图片描述
5.2.3基础矩阵F
在这里插入图片描述
5.2.4画出极点极线
在这里插入图片描述
由极点极线图可知平移的图片没有出现极点,极线趋于平行。因为极点是对极线与像平面的角点,对极线是对极平面与像平面的交线,两个像平面平行,则对极线肯定也平行,那么极点就是在无穷远的地方。

5.3前后拍摄

5.3.1sift匹配特征点
在这里插入图片描述
5.3.2ransac筛选匹配点
在这里插入图片描述
5.3.3基础矩阵F
在这里插入图片描述
5.3.4画出极点极线在这里插入图片描述
前后的图片出现了极点,并且自由前后变换的图片才会出现极点。所以当图片进行左右或者平移时极点出现在图片外侧,符合实验要求

六、实验小结

此次实验对原理还是不太理解,导致实验执行过程很多问题,期间还出现矩阵出不来,换了新的图片再改了图片大小可以运行。
补:所谓极线实际上是左右投影平面的投影中心,也就是摄像机的光心在相对的图像坐标系中的投影。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值