OpenCV-Python 对极几何 | 五十一
目标
在本节中
- 我们将学习多视图几何的基础知识
- 我们将了解什么是极点,极线,极线约束等。
基础概念
当我们使用针孔相机拍摄图像时,我们失去了重要信息,即图像深度。 或者图像中的每个点距相机多远,因为它是3D到2D转换。 因此,是否能够使用这些摄像机找到深度信息是一个重要的问题。 答案是使用不止一台摄像机。 在使用两台摄像机(两只眼睛)的情况下,我们的眼睛工作方式相似,这称为立体视觉。 因此,让我们看看OpenCV在此字段中提供了什么。
(通过Gary Bradsky学习OpenCV在该领域有很多信息。)
在深入图像之前,让我们首先了解多视图几何中的一些基本概念。在本节中,我们将讨论对极几何。请参见下图,该图显示了使用两台摄像机拍摄同一场景的图像的基本设置。
如果仅使用左摄像机,则无法找到与图像中的点相对应的3D点,因为线上的每个点都投影到图像平面上的同一点。但也要考虑正确的形象。现在,直线OXOXOX上的不同点投射到右侧平面上的不同点(x′x'x′)。因此,使用这两个图像,我们可以对正确的3D点进行三角剖分。这就是整个想法。
不同点的投影在右平面OXOXOX上形成一条线(linel′l'l′)。我们称其为对应于该点的Epiline。这意味着,要在正确的图像上找到该点,请沿着该轮廓线搜索。它应该在这条线上的某处(以这种方式考虑,可以在其他图像中找到匹配点,而无需搜索整个图像,只需沿着Epiline搜索即可。因此,它可以提供更好的性能和准确性)。这称为对极约束。类似地,所有点在另一幅图像中将具有其对应的Epiline。该平面称为对极面。
OOO和O′O'O′是相机中心。从上面给出的设置中,您可以看到在点处的左侧图像上可以看到右侧摄像机O′O'O′的投影。它称为极点。极点是穿过相机中心和图像平面的线的交点。左摄像机的极点也同理。在某些情况下,您将无法在图像中找到极点,它们可能位于图像外部(这意味着一个摄像机看不到另一个摄像机)。
所有的极线都通过其极点。因此,要找到中心线的位置,我们可以找到许多中心线并找到它们的交点。
因此,在节中,我们将重点放在寻找对极线和极线。但是要找到它们,我们需要另外两种成分,即基础矩阵(F)和基本矩阵(E),基础矩阵包含有关平移和旋转的信息,这些信息在全局坐标中描述了第二个摄像头相对于第一个摄像头的位置。参见下图(图像由Gary Bradsky提供:Learning OpenCV):
但是我们会更喜欢在像素坐标中进行测量,对吧? 基本矩阵除包含有关两个摄像头的内在信息之外,还包含与基本矩阵相同的信息,因此我们可以将两个摄像头的像素坐标关联起来。(如果我们使用的是校正后的图像,并用焦距除以标准化该点,F=EF=EF=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) #索引图像 # left image
img2 = cv.imread('myright.jpg',0) #训练图像 # right image
sift = cv.SIFT()
# 使用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)
good = []
pts1 = []
pts2 = []
# 根据Lowe的论文进行比率测试
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)
# 我们只选择内点
pts1 = pts1[mask.ravel()==1]
pts2 = pts2[mask.ravel()==1]
接下来,我们找到Epilines。在第二张图像上绘制与第一张图像中的点相对应的Epilines。因此,在这里提到正确的图像很重要。我们得到了一行线。因此,我们定义了一个新功能来在图像上绘制这些线条。
def drawlines(img1,img2,lines,pts1,pts2):
''' img1 - 我们在img2相应位置绘制极点生成的图像
lines - 对应的极点 '''
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
现在,我们在两个图像中都找到了Epiline并将其绘制。
# 在右图(第二张图)中找到与点相对应的极点,然后在左图绘制极线
lines1 = cv.computeCorrespondEpilines(pts2.reshape(-1,1,2), 2,F)
lines1 = lines1.reshape(-1,3)
img5,img6 = drawlines(img1,img2,lines1,pts1,pts2)
# 在左图(第一张图)中找到与点相对应的Epilines,然后在正确的图像上绘制极线
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()
以下是我们得到的结果:
您可以在左侧图像中看到所有极点都收敛在右侧图像的外部。那个汇合点就是极点。
为了获得更好的结果,应使用具有良好分辨率和许多非平面点的图像。
附加资源
练习
- 一个重要的主题是相机的前移。然后,将在两个位置的相同位置看到极点,并且从固定点出现极点。 请参阅此讨论。
- 基本矩阵估计对匹配,离群值等的质量敏感。如果所有选定的匹配都位于同一平面上,则情况会变得更糟。检查此讨论。
欢迎关注磐创博客资源汇总站:
http://docs.panchuang.net/
欢迎关注PyTorch官方中文教程站:
http://pytorch.panchuang.net/
OpenCV中文官方文档:
http://woshicver.com/
OpenCV-Python 对极几何 | 五十一的更多相关文章
- 第三百五十一节,Python分布式爬虫打造搜索引擎Scrapy精讲—将selenium操作谷歌浏览器集成到scrapy中
第三百五十一节,Python分布式爬虫打造搜索引擎Scrapy精讲—将selenium操作谷歌浏览器集成到scrapy中 1.爬虫文件 dispatcher.connect()信号分发器,第一个参数信 ...
- 孤荷凌寒自学python第五十一天初次尝试使用python连接Firebase数据库
孤荷凌寒自学python第五十一天初次尝试使用python连接Firebase数据库 (完整学习过程屏幕记录视频地址在文末) 今天继续研究Firebase数据库,利用google免费提供的这个数据库服 ...
- Python第五十一天 python2升级为python3
Python第五十一天 python2升级为python3 公司使用的生产环境系统是centos7,所以这里以centos7系统为基础,讲解将python2升级为python3的方法 centos7 ...
- 【图像处理】OpenCV+Python图像处理入门教程(五)阈值处理
这篇随笔介绍使用OpenCV进行图像处理的第五章 阈值处理. 5 阈值处理 阈值是指像素到达某临界值.阈值处理表示像素到达某临界值后,对该像素点进行操作和处理. 例如:设定一幅图像素阈值为200,则 ...
- OpenCV Python教程(3、直方图的计算与显示)
转载请详细注明原作者及出处,谢谢! 本篇文章介绍如何用OpenCV Python来计算直方图,并简略介绍用NumPy和Matplotlib计算和绘制直方图 直方图的背景知识.用途什么的就直接略过去了. ...
- 孤荷凌寒自学python第六十五天学习mongoDB的基本操作并进行简单封装4
孤荷凌寒自学python第六十五天学习mongoDB的基本操作并进行简单封装4 (完整学习过程屏幕记录视频地址在文末) 今天是学习mongoDB数据库的第十一天. 今天继续学习mongoDB的简单操作 ...
- Ubuntu系统---安装Caffe (+OpenCV+Python+CPU-only)
安装配置Ubuntu14.04+Caffe (+OpenCV+Python+CPU-only) 记录 [作者:Wu Ping.时间:20180428.] 本人已经安装很多次的Caffe了:从开始的初探 ...
- 自学笔记系列:《Python学习手册 第五版》 -写在开始之前
今年双十一,在当当网上买了这本书,很厚很厚的一本书,大概有将近1700页左右,的确是一个“大工程”, 关于这本书的学习,我想采用一种博客的方式进行,既是写给自己,也想分享给每一个对Python学习感兴 ...
- python学习心得第五章
python学习心得第五章 1.冒泡排序: 冒泡是一种基础的算法,通过这算法可以将一堆值进行有效的排列,可以是从大到小,可以从小到大,条件是任意给出的. 冒泡的原理: 将需要比较的数(n个)有序的两个 ...
随机推荐
- Go技术日报(2020-02-28)
go 语言中文网(每日资讯)_2020-02-28 一.Go 语言中文网 Gopher 学习效率低怎么办?曹大谈工程师应该怎么学习 Go 的 http 包中默认路由匹配规则 [每日一库]Web 表单验 ...
- WordPress 安装主题、插件时问题解决办法
--当能够在外网访问到自己的博客时,很多人都会很兴奋吧!如果环境是自己配置的,而不是用的集成环境肯定也会有点小小的成就感. --但是在我兴奋的时候遇到了个小麻烦,下载插件提示我输入FTP信任凭据,输了 ...
- android逆向---charles抓包
手机与电脑处于同一网络环境,且正确设置代理后,charles显示CONNECT失败,提示信息SSL handshake with client failed: An unknown issue occ ...
- Cenots 7 安装mysql cluster 通过rpm 包
环境:Cenots 7 MG:192.168.0.105 NDB:192.168.0.108 NDB:192.168.0.109 SQL:192.168.0.111 SQL:192.168.0.107 ...
- 微信小程序入门讲解
微信小程序 注册 由于发文限制,请自行到微信公众平台注册 项目结构 project.config.json 配置文件(不需要动) app.json(用户配置) 路由pages window 整个程序样 ...
- LeetCode python实现题解(持续更新)
目录 LeetCode Python实现算法简介 0001 两数之和 0002 两数相加 0003 无重复字符的最长子串 0004 寻找两个有序数组的中位数 0005 最长回文子串 0006 Z字型变 ...
- c/s用户与服务器之间的传输
####第一页 <%@ page language="java" contentType="text/html; charset=UTF-8" pageE ...
- 生产要不要开启MySQL查询缓存
一.前言 在当今的各种系统中,缓存是对系统性能优化的重要手段.MySQL Query Cache(MySQL查询缓存)在MySQL Server中是默认打开的,但是网上各种资料以及有经验的DBA都建议 ...
- boostrap3 bootstrap-datetimepicker.min.js设置中文语言
问题 bootstrap3中使用bootstrap-datetimepicker遇到设置中文语言的问题 解决办法 bootstrap-datetimepicker在使用的时候要先引入momentjs中 ...
- svg和css3创建环形渐变进度条
在负责的项目中,有一个环形渐变读取进度的效果的需求,于是在网上查阅相关资料整理一下.代码如下: <!DOCTYPE html> <html lang="en"&g ...