本文中我们准备探索允许3D重建在实践中工作的核心概念。具体来说,我们将了解多视图或对极几何的基础知识。

让我们来看一下现代针孔相机的功能。当一幅图像被拍摄时,它的信息呈现在二维平面上,在二维平面上,每个点(或像素)与相机镜头之间的距离是不存在的。但这正是我们为了使用2D图像执行3D重建所需的信息。我们的解决方案的关键在于使用第二个摄像头拍摄同一物体的照片,并比较每个图像来提取深度信息。我们的眼睛在类似的情况下执行着同样的任务。不过,OpenCV包含的工具可以帮助我们在非人类针孔相机拍摄的图像中看到深度。

我们先分析下面这张图,该图说明了两个摄像机拍摄同一场景照片的场景中多视图几何的一些基本概念。

通过检查从左侧摄像机的中心点发出的上图所示的OX线,我们可以看到该沿线有3个点,我们需要知道它们与O点的距离。如前所述我们并不能够仅从左侧相机中提取此信息。然而,对于右侧相机,我们可以看到X的3个点可以沿其图像平面上的一条直线投影(直线用:l '表示)。这条线被称为核线(epiline); 必须出现沿着OX线的任何点X的线。重要的是,当我们在右侧相机的图像中搜索X的匹配点时,我们已经知道它将沿着该核线出现,因此大大减少了我们的搜索工作量。此外,我们可以假设在左侧图像中出现的每个点将始终具有在右侧图像中找到的伴随的核线。这被称为极线约束。

需要注意的另一个重要方面是核点(epipole)。核点是连接到每个摄像机中心点的线在核面内的交点。在上面的图中,0和0 '分别表示在两端。点e和e'是对方相机的中心点出现在对应图像中的点。通过将点X(我们试图提取其深度值的点)包含在核点线上,我们可以导出这个平面表示为X00'的平面。该平面称为极线平面。

我们还可以在上图中看到,右侧图像中的X点的投影与相对的相机(e')的核点相交。这显示了所有的极线将如何通过图像中找到的核点(相对照相机的真实中心点将出现的图像点)。这一点的重要性在于我们能够通过找到多个核线相交的图像点来精确计算出核点在我们的图像中的位置。我们还应该注意,在很多情况下,在相对图像的帧中可能没有捕获一个或两个相机中心点,这意味着该极点将落在其2D像素矩阵之外。尽管如此,我们仍然可以通过分析核线精确地计算出虚构的核点位置,从而达到提取深度信息的最终目标。

由于我们现在已经涵盖了对极几何的基础知识,我们现在可以解决另外两个元素,以便找到核点和核线。

基本矩阵包含有关平移和旋转的信息,它描述了相机相对于其对应物的位置。下图展示了基本矩阵。

但是对于我们的解决方案,我们希望根据相机像素坐标进行计算。这是基本矩阵发挥作用的地方,因为它包含与实际矩阵相同的信息,但也包括关于两个相机的内在信息,以便我们可以用这样的术语将两者联系起来。虽然基本矩阵中的信息来源于我们相机的真实世界定位,但实际矩阵必须自己计算。基本矩阵允许我们做的是将一个图像中的单个点映射到另一个图像中的相应的极线,为我们提供一个起点,以便之后找到两个摄像机中心点和极平面之间的核线。

但是我们如何计算实际矩阵?我们可以使用OpenCV从每个图像中的一组已知匹配点推导出这个矩阵。这基本上是一个校准过程,建议从图像中找到最少8个匹配点,并用于达到所需的准确度。为此,我们使用OpenCV分析两个图像并提取其最佳匹配像素坐标。在下面的Python代码中,我们使用SIFT描述符和基于FLANN的matcher和ratio文本提取这些点。

import cv2import numpy as npfrom matplotlib import pyplot as pltimg1 = cv2.imread('myleft.jpg',0) #queryimage # left imageimg2 = cv2.imread('myright.jpg',0) #trainimage # right imagesift = cv2.SIFT()# find the keypoints and descriptors with SIFTkp1, des1 = sift.detectAndCompute(img1,None)kp2, des2 = sift.detectAndCompute(img2,None)# FLANN parametersFLANN_INDEX_KDTREE = 0index_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)

这将为我们提供两个图像中最佳像素匹配的列表,然后可以将其发送以计算实际矩阵,我们将在下面使用OpenCV的功能进行计算。Python代码如下:

pts1 = np.int32(pts1)pts2 = np.int32(pts2)F, mask = cv2.findFundamentalMat(pts1,pts2,cv2.FM_LMEDS)# We select only inlier pointspts1 = pts1[mask.ravel()==1]pts2 = pts2[mask.ravel()==1]

让我们花点时间创建一个Python函数,它将在我们的图像上绘制线条,这些线条稍后将用于可视化核线。

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 = 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

现在我们继续计算与相对图像中的点相对应的核线。在这个阶段,我们还需要注意我们正在使用哪个相机,因为我们将在一个图像中找到点,并在其对应物上绘制核线。下面的代码将生成一个行数组,我们可以随后将其发送到绘图函数。Python代码如下:

# Find epilines corresponding to points in right image (second image) and# drawing its lines on left imagelines1 = cv2.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 imagelines2 = cv2.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()

结果显示两幅带有核线的图像,它们代表了来自相反图像的点数组。我们可以注意到,每一组线的集合点都在摄像机视图之外。这个虚构的点是核点(即在三维空间中,相对摄像机的中心点)。

最后,我们应该认识到在尝试进行3D重建时相机分辨率的重要性。这是由于在我们的过程中,第一步我们必须使用一种算法来识别每幅图像中非常匹配的像素,这样我们就可以产生一个精确的基本矩阵。分辨率越低,我们处理的信息就越少,因此极大地阻碍了保持精度的能力。尽管如此,我们仍在用立体图像进行全面三维重建的,我们的最后一步是使用第二个相应的极线计算第一个图像上的点的深度。

基于几何学习图像的三维重建发展_立体图像的三维重建-对极几何相关推荐

  1. 基于深度学习的目标检测发展历程:deep_learning_object_detection

    目标检测论文从 2014-2018 模型表现表格 Detector VOC07 (mAP@IoU=0.5) VOC12 (mAP@IoU=0.5) COCO (mAP) Published In R- ...

  2. 基于几何学习图像的三维重建发展_基于深度学习的三维重建算法:MVSNet、RMVSNet、PointMVSNet、Cascade系列...

    欢迎关注微信公众号"3D视觉学习笔记",分享博士期间3D视觉学习收获 MVSNet:香港科技大学的权龙教授团队的MVSNet(2018年ECCV)开启了用深度做多视图三维重建的先河 ...

  3. 基于深度学习的图像识别模型发展

    一.简介 AlexNet:(2012)主要贡献扩展 LeNet 的深度,并应用一些 ReLU.Dropout 等技巧.AlexNet 有 5 个卷积层和 3 个最大池化层,它可分为上下两个完全相同的分 ...

  4. 外星人图像和外星人太空船_卫星图像:来自太空的见解

    外星人图像和外星人太空船 By Christophe Restif & Avi Hoffman, Senior Software Engineers, Crisis Response 危机应对 ...

  5. python双目视觉三维重建代码_双目立体视觉的三维重建方法与流程

    本发明为双目立体视觉的三维重建方法,属于图像处理与机器视觉领域,涉及halcon软件,具体涉及空间场景的三维重建. 背景技术: 三维重建技术作为计算机视觉领域的一个重要分支,在人工智能.虚拟现实.非接 ...

  6. 提取图像感兴趣区域_从图像中提取感兴趣区域

    提取图像感兴趣区域 Welcome to the second post in this series where we talk about extracting regions of intere ...

  7. 图像 异常检测算法_检测图像异常的算法

    图像 异常检测算法 Modern applications are generating enormous amounts of image data. And in the last years, ...

  8. python检测图像中的矩形_检测图像中的矩形并裁剪

    如果你努力的话,那是件容易的事.这是我的输出(图像和它的一小部分) 我做了什么?先调整图像的大小,因为它在我的屏幕上太大了 侵蚀.扩张以去除小点并加厚线条 阈值图像 洪水泛滥,从正确的点开始 倒洪 找 ...

  9. 最新综述 | 基于深度学习的SLAM方法:面向空间机器智能时代

    最新综述 | 基于深度学习的SLAM方法:面向空间机器智能时代 A Survey on Deep Learning for Localization and Mapping Towards the A ...

最新文章

  1. Hibernate缓存原理与策略 Hibernate缓存原理:
  2. Chrome 技巧篇-浏览器网页设置编码,解决网页乱码问题,最新版charset插件获取,UTF-8编码设置
  3. VC小技巧(三)视图
  4. 为什么S/4HANA的生产订单创建后会自动release
  5. go 捕获网卡http_接口测试工具Postman(三)使用postman抓包捕获HTTP请求-Go语言中文社区...
  6. HDU - 5877 Weak Pair (dfs序+树状数组+离散化)
  7. Mysql8.0可以使用解压版 这个比较快 好像现在都是解压版了
  8. 最易忽视的肾虚4件事
  9. 关于liaoxuefeng的python3教程实战第四天
  10. 信息学奥赛一本通 1115:直方图 | OpenJudge NOI 1.9 09
  11. cpython是什么_CPython是什么?PyPy是什么?Python和这两个东西有什么关系?
  12. PCB设计中电源与地之间电容的作用(具体放置面积, 大小等等)
  13. linux+gif+编辑,Linux下GIF制作指南
  14. 红色警戒2:尤里的复仇 中文绿色版
  15. 算法高级(21)-如何通过IP地址进行定位?
  16. Waited too long for library cache load lock
  17. 信用卡被风控的原因是什么?如何应对风控?
  18. 2011年20大3D网站
  19. Request Line is too large (xxxx > 4094) 问题处理
  20. 运用图像处理解决基于MRI的脑肿瘤图像分割问题

热门文章

  1. PyQt5随笔:QTextEdit和QTextBrowser文本框多次设置输入内容时,显示全部内容的方法
  2. layui 树形表格
  3. 孙武玩《魔兽》?有图有真相
  4. 不可重复读和可重复读的理解
  5. java复核审查_java对接七牛后台进行内容审核(鉴黄、敏感人物、暴恐)
  6. 开启Mac自带apache和PHP开发环境
  7. 2022-4-19 HTTP头部有限状态机《Linux高性能服务器》笔记
  8. WPF自定义样式与模板
  9. GIF图片怎么压缩?如何快速缩小GIF图片?
  10. 软件系统分析与设计作业1