十五天掌握OpenCV——对极几何(Epipolar Geometry)

魏老师学生——Cecil:学习OpenCV-机器视觉之旅


Aim:
学习多视角几何基础;
学习极点、极线、对极约束。

基本概念

  1. 使用针孔相机时,由于是从3D到2D的转换,丢失大量信息,比如:图像深度、图像上点和摄像机的距离。
  2. 如何计算深度信息:使用多个相机,称为立体视觉。
  3. 使用两台摄像机同时对一个场景拍摄的示意图。1
  4. 由于OX连线上的每个点投影到图像平面上的点相同,直线OX上的点又投影到右侧图像上的不同位置。所以根据两幅图像,可以使用三角测量计算出3D空间中的点到摄像机的距离。
  5. 与X点对应的极线:直线OX上的不同点投射到右侧图像上形成的线L‘。
  6. 对极约束:X点在极线上的某个位置,从而将二维搜索转变为对极线的一维搜索。
  7. 对极平面:所有的点在其他图像中都有与之相对的极线,即为此平面。
  8. 极点:摄像机中心连线与图像平面的交点。极点若在图像外则图像中找不到极点,说明两个摄像机不能拍摄到彼此。
  9. 极线的交点是极点、
  10. 本征矩阵 E :包含物理空间中两个摄像机相关的旋转和平移信息。2
  11. 基础矩阵 F:除了包含E的信息,还包含两个摄像机的内参数。故可以在像素坐标系将两台摄像机关联起来。使用校正后的图像并通过除以焦距进行归一化后,F=E。
  12. 基础矩阵F将一副图像上的点映射到另一幅图像的线上,通过匹配两幅图像上的点实现。至少8个点(8点算法)才能计算基础矩阵。点越多越好,可以使用RANSAC算法得到更稳定的结果。

代码演示

为了在两幅图像中找到尽量多的匹配点得到基础矩阵,使用SIFT描述符、FLANN匹配器和比值检测。

#coding=utf-8
import cv2
import numpy as np
from  matplotlib import pyplot as plt

img1=cv2.imread('./image2/mario.jpg',0)
img2=cv2.imread('./image2/coin.jpg',0)

sift=cv2.SIFT()

kp1,des1=sift.detectAndCompute(img1,None)
kp2,des2=sift.detectAndCompute(img2,None)

FLANN_INDEX_KDTREE=0
index_params=dict(algorithm=FLANN_INDEX_KDTREE,trees=5)
search_params=dict(checks=50)

flann=cv2.FlannBasedMatcher(index_params,search_params)
matches=flann.knnMatch(des1,des2,k=2)

good=[]
pts1=[]
pts2=[]

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=cv2.findFundamentalMat(pts1,pts2,cv2.FM_LMEDS)

pts1=pts1[mask.ravel()==1]
pts2=pts2[mask.ravel()==1]

#找出极线,得到包含很多线的数组。
#定义函数将线绘制到图像中
def drawlines(img1,img2,lines,pts1,pts2):
    r,c=img1.shape
    img1=cv2.cvtColor(img1,cv2.COLOR_GRAY2BGR)
    img2=cv2.cvtColor(img2,cv2.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=cv2.line(img1,(x0,y0),(x1,y1),color,1)
        img1=cv2.circle(img1,tuple(pt1),5,color,-1)
        img2=cv2.circle(img2,tuple(pt2),5,color,-1)
    return img1,img2
#在两幅图像中计算并绘制极线
lines1=cv2.computeCorrespondEpilines()
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值