计算机视觉——对极几何与基础矩阵

对极几何与基础矩阵

一、对极几何

提到对极几何,一定是对二幅图像而言,对极几何实际上是“两幅图像之间的对极几何”,它是图像平面与以基线为轴的平面束的交的几何(这里的基线是指连接摄像机中心的直线),以下图为例:对极几何描述的是左右两幅图像(点x和x’对应的图像)与以CC’为轴的平面束的交的几何!
在这里插入图片描述
对极几何中的重要概念(参考下图):
极点:右相机坐标原点在左像平面上的像;左相机坐标原点在右像平面上的像
极平面:由两个相机坐标原点、和物点组成的平面
级线:极平面与两个像平面的交线
级线约束:两极线上点的对应关系
在这里插入图片描述

二、基础矩阵

2.1归一化8点算法

基础矩阵:描述空间点P在两个相机成像的各自的图像像素坐标系下的关系,换言之,给定了两个相机的相对位置关系和相机内参,F即被确定。
基础矩阵是由下述方程定义: x T F x = 0 x′^TFx=0
其中 x x x↔x′ 是两幅图像的任意一对匹配点。由于每一组点的匹配提供了计算 F F 系数的一个线性方程,当给定至少7个点(3×3的齐次矩阵减去一个尺度,以及一个秩为2的约束),方程就可以计算出未知的 F F 。我们记点的坐标为 x = ( x , y , 1 ) T x=(x,y,1)^T , x = ( x , y , 1 ) T x′=(x′,y′,1)^T ,则对应的方程为

在这里插入图片述
  展开后有 x x f 11 + x y f 12 + x f 13 + y x f 21 + y y f 22 + y f 23 + x f 31 + y f 32 + f 33 = 0 x′xf11​+x′yf12​+x′f13​+y′xf21​+y′yf22​+y′f23​+xf31​+yf32​+f33​=0
  把矩阵 F F 写成列向量的形式,则有:
  在这里插入图片描述
  给定 n n 组点的集合,我们有如下方程:
  在这里插入图片描述
  如果存在确定(非零)解,则系数矩阵 A A 的自由度最多是8。由于 F F 是齐次矩阵,所以如果矩阵 A A 的自由度为8,则在差一个尺度因子的情况下解是唯一的。可以直接用线性算法解得。
如果由于点坐标存在噪声则矩阵 A A 的自由度可能大于8(也就是等于9,由于 A A n n ×9的矩阵)。这时候就需要求最小二乘解,这里就可以用SVD来求解, f f 的解就是系数矩阵 A A 最小奇异值对应的奇异向量,也就是 A A 奇异值分解后 A = U D V T A=UDV^T 中矩阵 V V 的最后一列矢量,这是在解矢量 f f 在约束 f ∥f∥ ​下取 A f ∥Af∥ 最小的解。以上算法是解基本矩阵的基本方法,称为八点算法

由于基本矩阵有一个重要的特点就是奇异性 F F 矩阵的秩是2。如果基本矩阵是非奇异的,那么所计算的对极线将不重合。所以在上述算法解得基本矩阵后,会增加一个奇异性约束。最简便的方法就是修正上述算法中求得的矩阵 F F 。设最终的解为 F F′ ,令 d e t F = 0 detF′=0 下求得Frobenius范数 F F ∥F−F′∥ ​最小的 F F′ 。这种方法的实现还是使用了SVD分解,若 F = U D V T F=UDV^T ,此时的对角矩阵 D = d i a g ( r , s , t ) D=diag(r,s,t) 满足 r s t r≥s≥t ,则 F = U d i a g ( r , s , 0 ) V T F′=Udiag(r,s,0)V^T 最小化范数 F F ∥F−F′∥ ,也就是最终的解。

2.2算法总结

给定 n 8 n≥8 组对应点{ x i x i xi↔xi′ },确定基本矩阵 F F 使得 x i T F x i = 0 x_i′^TFx_i=0
算法:
1.归一化:根据 x ^ i = T x i \hat{x}_i=Tx_i x ^ i = T x i \hat{x'}_i=T'x'_i 变换图像坐标。其中 T T T T′ 是有平移和缩放组成的归一化变换。
2.求解对应匹配的基本矩阵 F ^ \hat{F'}
求线性解:用由对应点集{ x i ^ x i ^ \hat{x_i}↔\hat{x'_i} }确定的系数矩阵 A ^ \hat{A} 的最小奇异值的奇异矢量确定 F ^ \hat{F}
奇异性约束:用SVD对 F ^ \hat{F} 进行分解,令其最小奇异值为0,得到 F ^ \hat{F'} ,使得 d e t F ^ = 0 det\hat{F'}=0
3.解除归一化:令 F = T T F ^ T F=T'^T \hat{F'}T 。矩阵 F F 就是数据 x i x i x_i↔x′_i ​对应的基本矩阵。

三、实验求解图像的基础矩阵

3.1实验要求

  1. 分别用七点、八点、十点(匹配点),计算基础矩阵
    实验图片包含三种情况,即
    (1)左右拍摄,极点位于图像平面上
    (2)像平面接近平行,极点位于无穷远
    (3)图像拍摄位置位于前后
  2. 针对上述情况,画出极点和极线,其中点坐标要均匀分布于各行
    避免只用排在前五特征点的方式

3.2实验准备

实验平台:PyCharm3.3版本
实验数据:我将实验的图像数据集分为了三组,分别是角度变换图像、平移变换图像、远近变换图像,图片如下:
在这里插入图片描述

3.3实验代码

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('img/003.jpg'))
sift.process_image('img/003.jpg', 'im1.sift')

im2 = array(Image.open('img/004.jpg'))
sift.process_image('img/004.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,
                                   8, 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)

7点法和10点法的代码通过修改参数实现

F, ransac_data = ransac.ransac(data.T, model,7/8/10, maxiter, match_threshold, d, return_all=True)

扫描二维码关注公众号,回复: 11034638 查看本文章

画极线代码

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('img/005.jpg', 0)  # queryimage # left image
img2 = cv.imread('img/006.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()

3.4实验结果

3.4.1角度变换图像(从左至右匹配点分别是7点法、8点法、10点法)
在这里插入图片描述
3.4.2平移变换图像(从左至右匹配点分别是7点法、8点法、10点法)
在这里插入图片描述
3.4.3远近变换图像(从左至右匹配点分别是7点法、8点法、10点法)
在这里插入图片描述

小结:通过比较三种不同的匹配点数量和图像拍摄构图方法可以得知
1.匹配点的数量越多,所得到的特征匹配数量也就越多,因此10点法相较与7点法和8点法所得的特征匹配数量更多
2.平移变换图像相比较其他两种构图方式的图像有着较多的特征匹配数,因为平移变换对物体特征点的影响较小,而远近和左右角度变换都会在不同程度上影响到特征点的收集和遮蔽
3.无论是角度变换、平移变换还是远近变换都存在着一定误差,图片中有一些明显不是特征匹配点的也被标记出来,但是相比较之下,匹配点越少的7点法错误的特征匹配点较多,而10点法则更少

极点、极线图以及基础矩阵
3.4.4角度变换
在这里插入图片描述
在这里插入图片描述
3.4.5平移变换
在这里插入图片描述
在这里插入图片描述
3.4.6远近变换
在这里插入图片描述
在这里插入图片描述

小结:通过观察这三幅角度变换、平移变换、远近变换的极点、极线图可以得知
1.由于每两幅图像在匹配的时候都或多或少的存在一些错误的特征匹配点匹配,所以计算的基本矩阵有较大的误差。还有就是,在拍摄过程中,光线明亮或暗淡、角度旋转等等因素都会导致特征匹配点的匹配问题,因此就会得到三个互不相同的 F F 矩阵
2.从这几幅图的左右视图中都可以发现,很多的点落在在对极线附近但并没有完全落在对极线上。
我们可以观察到左右视图的对极线都响应地汇聚到一点,那点就是极点
3.匹配中极点都落在图像内,当然也有些情况对极线会落在图像外

四、实验总结

3.1 图像压缩之后会丢失很多匹配特征点,因此在计算基础矩阵是一定要控制好图像压缩大小;计算 基础矩阵的前提是要先得到其sift特征匹配结果,通过sift特征匹配结果得到 F F 基础矩阵,因此要确保sift寻找出更多的特征匹配点。
3.2 基础矩阵 F F 描述的是3维场景的对极约束关系,和三维场景的结构无关,只依赖于相机的内参数以及外参数其描述的是点和线的约束关系,当已知图像上的点x1和基础矩阵F时是无法获得对应的像素点下x2的,只能获得x1对应的极线。即基础矩阵表示的是像点和另一幅图像上的对极线的映射关系,使用基础矩阵无法得到像点对应点在另一幅图像上的确切位置。
3.3 在实验中遇到:
在这里插入图片描述
这是因为图像sift特征匹配的匹配点数过少,这时候需要修改代码中匹配的阈值。但是,sift特征匹配的匹配对过少的话,会对后续进行ransac算法实现产生影响,所以拍摄图片的时候要特别注意。

发布了14 篇原创文章 · 获赞 8 · 访问量 1582

猜你喜欢

转载自blog.csdn.net/qq_42678341/article/details/105656998