opencv - py_calib3d - py_epipolar_geometry 对极几何

news2024/11/15 16:42:35

文章目录

  • Epipolar Geometry 对极几何
    • 目标
    • 基本概念
    • 代码
    • 练​​习

Epipolar Geometry 对极几何

目标

在本节中,

  • 我们将学习多视图几何的基础知识
  • 我们将了解什么是对极点、对极线、对极约束等。

基本概念

当我们使用针孔相机拍摄图像时,我们会丢失一个重要信息,即图像的深度。或者图像中每个点与相机的距离有多远,因为它是 3D 到 2D 的转换。因此,我们能否使用这些相机找到深度信息是一个重要的问题。答案是使用多个相机。我们的眼睛以类似的方式工作,我们使用两个相机(两只眼睛),这称为立体视觉。那么让我们看看 OpenCV 在这一领域提供了什么。

(Gary Bradsky 的《学习 OpenCV》包含大量该领域的信息。)

在介绍深度图像之前,我们先了解一下多视图几何中的一些基本概念。在本节中,我们将讨论对极几何。参见下图,其中显示了两个摄像头拍摄同一场景图像的基本设置。
在这里插入图片描述

如果我们只使用左相机,我们将无法找到图像中与点 x x x 对应的 3D 点,因为线 O X OX OX 上的每个点都投影到图像平面上的同一点。但请考虑右图。现在线 O X OX OX 上的不同点投影到右平面上的不同点 ( x ′ x' x)。因此,通过这两幅图像,我们可以三角测量出正确的 3D 点。这就是整个想法。

O X OX OX 上不同点的投影在右平面上形成一条线(线 l ′ l' l)。我们将其称为与点 x x x 对应的极线。这意味着,要找到右图上的点 x x x,请沿着这条极线进行搜索。它应该在这条线上的某个地方(这样想,要在其他图像中找到匹配点,您无需搜索整个图像,只需沿着极线搜索即可。因此它提供了更好的性能和准确性)。这称为极线约束。同样,所有点在另一幅图像中都会有其对应的极线。平面 X O O ′ XOO' XOO 称为极线平面

O O O O ′ O' O 是相机中心。从上面给出的设置中,您可以看到右相机 O ′ O' O 的投影在左图像上的点 e e e 处可见。它被称为极点。极点是通过相机中心的线与图像平面的交点。类似地, e ′ e' e 是左相机的极点。在某些情况下,您将无法在图像中找到极点,它们可能在图像之外(这意味着一个相机看不到另一个相机)。

所有极线都经过其极点。因此,要找到极点的位置,我们可以找到许多极线并找到它们的交点。

因此,在本节中,我们专注于寻找极线和极点。但要找到它们,我们还需要两个要素,基本矩阵 (F)基本矩阵 (E)。基本矩阵包含有关平移和旋转的信息,它们描述了第二个相机相对于第一个相机在全局坐标中的位置。参见下图(图片来源:Gary Bradsky 的 Learning OpenCV):
在这里插入图片描述

但是我们更喜欢在像素坐标中进行测量,对吗?除了有关两个相机的内在信息之外,基本矩阵还包含与基本矩阵相同的信息,以便我们可以在像素坐标中关联两个相机。(如果我们使用校正后的图像并通过除以焦距来规范化该点,则 F = E F=E F=E)。简而言之,基本矩阵 F 将一个图像中的点映射到另一个图像中的一条线(极线)。这是根据两个图像中的匹配点计算得出的。至少需要 8 个这样的点才能找到基本矩阵(使用 8 点算法)。更多点是首选,并使用 RANSAC 获得更稳健的结果。

代码

因此,首先我们需要在两个图像之间找到尽可能多的匹配项来找到基本矩阵。为此,我们使用 SIFT 描述符和基于 FLANN 的匹配器和比率测试。

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

img1 = cv.imread('myleft.jpg',0)  #queryimage # left image
img2 = cv.imread('myright.jpg',0) #trainimage # right image

sift = cv.SIFT_create()

# 使用 SIFT 找到关键点和描述符
kp1, des1 = sift.detectAndCompute(img1,None)
kp2, des2 = sift.detectAndCompute(img2,None)
# FLANN 参数
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)

pts1 = []
pts2 = []
# 按照 Lowe 的论文进行比率测试
for i,(m,n) in enumerate(matches):
    if m.distance < 0.8*n.distance:
        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)
# 我们只选择内点
pts1 = pts1[mask.ravel()==1]
pts2 = pts2[mask.ravel()==1]

接下来我们找到极线。对应于第一幅图像中的点的极线绘制在第二幅图像上。因此,在这里提到正确的图像很重要。我们得到了一个线数组。所以我们定义了一个新函数来在图像上绘制这些线。

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

现在我们在两幅图像中找到极线并绘制它们。

# 找到对应于右图(第二幅图像)中点的极线和

# 在左图上绘制它的线
lines1 = cv.computeCorrespondEpilines(pts2.reshape(-1,1,2), 2,F)
lines1 = lines1.reshape(-1,3)
img5,img6 = drawlines(img1,img2,lines1,pts1,pts2)

# 找到对应于左图(第一幅图像)中点的极线和

# 在右图上绘制它的线
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. 基本矩阵估计对匹配质量、异常值等很敏感。 当所有选定的匹配都位于同一平面上时,情况会变得更糟。 查看此讨论。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1950174.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

解锁人工智能学习中的数学密钥

一、启航&#xff1a;奠定数学基础 1. 线性代数&#xff1a;AI的入门语言 学习目标&#xff1a;掌握向量、矩阵的基本概念及运算&#xff0c;理解线性空间、线性变换及特征值、特征向量的意义。学习建议&#xff1a;从基础教材入手&#xff0c;如《线性代数及其应用》&#x…

Godot入门 03世界构建1.0版

在game场景&#xff0c;删除StaticBody2D节点&#xff0c;添加TileMap节点 添加TileSet图块集 添加TileSet源 拖动图片到图块&#xff0c;自动创建图块 使用橡皮擦擦除。取消橡皮擦后按住Shift创建大型图块。 进入选择模式&#xff0c;TileMap选择绘制&#xff0c;选中图块后在…

PostgreSQL 数据库 安装

1、官网下载 起源与发展&#xff1a;PostgreSQL最初起源于加州大学伯克利分校的Postgres项目&#xff0c;该项目始于1986年&#xff0c;并一直演进到1994年。在1995年&#xff0c;Postgres项目增加了SQL翻译程序&#xff0c;并更名为Postgres95。随后&#xff0c;在1996年&…

dsp c6657 SYS/BIOS学习笔记

1 SYS/BIOS简介 SYS/BIOS是一种用于TI的DSP平台的嵌入式操作系统&#xff08;RTOS&#xff09;。 2 任务 2.1 任务调度 SYS/BIOS任务线程有0-31个优先级&#xff08;默认0-15&#xff0c;优先级0被空闲线程使用&#xff0c;任务最低优先级为1&#xff0c;最高优先级为15&am…

解决zabbix-server7 中文乱码问题

系统使用centos9 安装中文支持 yum install -y fontconfig langpacks-zh_CN.noarch 检查是否已有中文字体&#xff1a; fc-list :langzh 看到 直接使用GOOGLE的字体 ln -fs /usr/share/fonts/google-noto-cjk/NotoSansCJK-DemiLight.ttc /etc/alternatives/zabbix-web-fo…

Activiti学习之入门个人任务(07)

这里写目录标题 一、分配任务负责人1.1 固定分配1.2 表达式分配1.2.1 UEL表达式1.2.2 使用流程变量分配任务1.2.3 注意事项 1.3 监听器分配 二、查询任务2.1 查询负责人待办2.2 关联businessKey 三、办理任务 一、分配任务负责人 1.1 固定分配 在进行业务流程建模时指定固定的…

上传文件传参 pc端vue的formData

formData let formData new FormData(); formData.append("file", blob, ref ".png"); //添加参数并且重新命名文件名称 if(ref.toString().indexOf(qrcode) > 0) formData.append(noStbg, true)//添加参数 uploadType(formData, sour…

Ruoyi-WMS部署

所需软件 1、JDK&#xff1a;8 安装包&#xff1a;https://www.oracle.com/java/technologies/javase/javase8-archive-downloads.htmlopen in new window 安装文档&#xff1a;https://cloud.tencent.com/developer/article/1698454open in new window 2、Redis 3.0 安装包&a…

算法日记day 20(中序后序遍历序列构造二叉树|最大、合并、搜索二叉树)

一、中序后序序列构造二叉树 题目&#xff1a; 给定两个整数数组 inorder 和 postorder &#xff0c;其中 inorder 是二叉树的中序遍历&#xff0c; postorder 是同一棵树的后序遍历&#xff0c;请你构造并返回这颗 二叉树 。 示例 1: 输入&#xff1a;inorder [9,3,15,20,…

Web动画(lottie篇)

一、Lottie简介 Lottie是一个库&#xff0c;可以解析使用AE制作的动画&#xff08;需要用bodymovin导出为json格式&#xff09;&#xff0c;支持web、ios、android和react native。在web侧&#xff0c;lottie-web库可以解析导出的动画json文件&#xff0c;并将其以svg或者canva…

近期代码报错解决笔记

1.TypeError: ‘bool’ object is not callable 想print("Type of head:", type(entity_emb[head]))&#xff0c;结果报如下错误&#xff1a; 源代码&#xff1a; 因为 print 仍然被当作一个布尔值处理&#xff0c;而不是作为函数调用。这个问题的根源在于 print …

iOS ------ Block的相关问题

Block的定义 Block可以截获局部变量的匿名函数&#xff0c; 是将函数及其执行上下文封装起来的对象。 Block的实现 通过Clang将以下的OC代码转化为C代码 // Clang xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc main.m//main.m #import <Foundation/Foundation.…

7月26日贪心练习-摆动序列专题

前言 大家好&#xff0c;今天学习用贪心思想解决摆动序列问题&#xff0c;共三题&#xff0c;分享自己的思路&#xff0c;请大家多多支持 算法思想 大家可以先看看这道我们后面会讲的题看看怎么个事&#xff0c;. - 力扣&#xff08;LeetCode&#xff09; 由此题题解说明算…

uniapp手写滚动选择器

文章目录 效果展示HTML/Template部分&#xff1a;JavaScript部分&#xff1a;CSS部分&#xff1a;完整代码 没有符合项目要求的选择器 就手写了一个 效果展示 实现一个时间选择器的功能&#xff0c;可以选择小时和分钟&#xff1a; HTML/Template部分&#xff1a; <picker…

谷粒商城实战笔记-66-商品服务-API-品牌管理-JSR303数据校验

文章目录 一&#xff0c;引入JSR 303依赖二&#xff0c;接口参数启用校验功能三&#xff0c;给字段添加校验注解NotBlank 和 NotNull 的区别NotBlankNotNull比较 四&#xff0c;BindingResult获取校验结果五&#xff0c;自定义错误消息六&#xff0c;其他校验规则 在Web应用程序…

如何对视频文件加密_如何加密视频文件_视频文件如何加密

“嘿&#xff0c;小李&#xff0c;你知道咱们公司的新项目资料都是视频形式的吗&#xff1f;这些视频里有很多机密信息&#xff0c;我们需要好好保护起来。” “是啊&#xff0c;我也在想这个问题。你有没有什么好办法来加密这些视频文件呢&#xff1f;” “我听说有个叫域智盾…

html+css前端作业 王者荣耀官网1个页面(带报告)

htmlcss前端作业 王者荣耀官网1个页面&#xff08;带报告&#xff09; 下载地址 https://download.csdn.net/download/qq_42431718/89575045 目录1 目录2 项目视频 王者荣耀首页1个页面&#xff08;无js&#xff09; 页面1

推荐|政务网站部署哪种SSL证书?如何申请?

政务网站作为面向公众提供政务服务的官方平台&#xff0c;对信息安全和公信力有极高的要求。因此&#xff0c;在部署SSL证书时&#xff0c;应慎重选择。下面是关于政务网站SSL证书选择的一些建议&#xff1a; 一、推荐的SSL证书类型 1 选择数据不出境&#xff0c;国内验签的证…

多模态论文一:CLIP模型主要内容讲解【原理+代码】

一、CLIP模型主要内容讲解 CLIP&#xff08;Contrastive Language-Image Pre-training&#xff09;是OpenAI在2021年发布的一种用于图像和文本联合表示学习的模型。CLIP的核心思想是通过对比学习来预训练一个模型&#xff0c;使其能够理解图像和文本之间的关系。以下是CLIP的工…

Ruoyi-WMS本地运行

所需软件 1、JDK&#xff1a;8 安装包&#xff1a;https://www.oracle.com/java/technologies/javase/javase8-archive-downloads.htmlopen in new window 安装文档&#xff1a;https://cloud.tencent.com/developer/article/1698454open in new window 2、Redis 3.0 安装包&a…