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个)有序的两个 ...
随机推荐
- 线程sleep,wait,notify,join,yield方法解析
线程的五种状态 线程从创建到销毁一般分为五种状态,如下图: 1) 新建 当用new关键字创建一个线程时,就是新建状态. 2) 就绪 调用了 start 方法之后,线程就进入了就绪阶段.此时,线程不会立 ...
- 6487. 【GDOI2020模拟02.29】列强争霸war
题目描述 区间绝对众数 即出现次数>len/2下取整的数 对于区间[L,R]扫一遍,维护一个数x和出现次数s 当前数=x则s+1,否则s-1,若s已为0则把x设为当前数 若区间内存在绝对众数,那 ...
- http面试问题集锦
1.http的请求报文和响应报文? http请求报文:请求行(请求方法+url).请求头,请求体 http响应报文:状态行(http版本+状态码).响应头.响应体 2.常用的http请求类型? 请 ...
- Windows 使用激活服务器激活操作步骤
最近装了win10企业版系统,总结下激活步骤,激活后是正版,半年后需要重新激活,不介意的小伙伴可以试试,这不是重点,重点是企业版超级clean...... 服务器激活系统步骤,打开cmd或者xshel ...
- 绕过Referer和Host检查
1.我们在尝试抓取其他网站的数据接口时,某些接口需要经过请求头中的Host和Referer的检查,不是指定的host或referer将不予返回数据,且前端无法绕过这种检查 此时通过后端代理解决 在vu ...
- ELK springboot日志收集
一.安装elasticsearch 可以查看前篇博客 elasticsearch安装.elasticsearch-head 安装 二.安装 配置 logstash 1.安装logstash 下载地址: ...
- 28 复杂的使用Specification查询
/** * Specification的多表查询 */ @Test public void testFind() { Specification<LinkMan> spec = new S ...
- ECMAScript进化史(1):话说Web脚本语言王者JavaScript的加冕历史
互联网起火-Web时代的来临 在行文之前,反手就安利一下<浏览器史话中chrome霸主地位的奠定与国产浏览器的割据混战>. 浏览器始祖NCSA Mosaic在1993年1月发布(于1992 ...
- selenium+options配置文件
from selenium.webdriver.chrome.options import Options from selenium import webdriver chrome_options ...
- vue-cli2.0项目 添加骨架屏
1.创建项目 npm init webpack project 3.下载 vue-skeleton-webpack-plugin 插件 npm install vue-skeleton-webpa ...