三维重建

在计算机视觉和计算机图形学中,三维重建是捕捉真实物体的形状和外观的过程,这个过程可以通过主动或被动的方法来完成。如果允许模型随时间改变形状,这称为非刚性或时空重构。三维重建的研究一直是一个难题。利用三维重建可以确定任意物体的三维轮廓,也可以知道轮廓上任意点的三维坐标。物体的三维重建是一个普遍存在的科学问题,是计算机辅助几何设计(CAGD)、计算机图形学、计算机动画、计算机视觉、医学影像、计算科学、虚拟现实、数字媒体等领域的核心技术。

方法

主动方法

主动方法,即距离数据方法,给出深度图,用数值逼近的方法重建三维剖面,基于模型在场景中建立目标。这些方法利用测距仪对重建对象进行机械或辐射测量,以获取深度图,如结构光、激光测距仪等主动传感技术。机械方法的一个简单例子是使用深度计来测量放置在转盘上的旋转物体的距离。更适用的辐射测量方法是向物体发射辐射,然后测量其反射部分。这些例子包括移动光源、彩色可见光、飞行时间激光、微波或超声波。

深度相机

深度相机介绍见RGB-D深度相机原理

关键问题:点的位置估计,相机位置估计(SLAM中的定位问题)

经典方法:KinectFusion,Kintinuous,ElasticFusion,InfiniTAM,BundleFusion

被动方法

该方法不干扰重建对象;他们只使用一个传感器来测量物体表面反射或发射的辐射,通过对图像的理解来推断出物体的三维结构。通常,传感器是摄像机中对可见光敏感的图像传感器,该方法的输入是一组数字图像(一个、两个或多个)或视频。在本例中,我们讨论了基于图像的重建,输出是一个3D模型。通过与主动方法的比较,被动方法可以应用于更广泛的情况。

1 单目视觉

单目视觉法是指从一个视点(摄像机)获取图像(一幅、两幅或多幅)进行三维构建的方法。它利用了二维特征。轮廓,阴影和纹理)来测量三维形状,这就是为什么它也被命名为shape - from -X,其中X可以是轮廓,阴影,纹理等。通过单眼线索进行三维重建是简单和快速的,只需要一个合适的数字图像,因此只需要一个相机就足够了。从技术上讲,它避免了立体对应,这是相当复杂的。

阴影:通过对图像阴影信息的分析,利用朗伯蒂反射率恢复物体表面法线信息的深度进行重建。

光度立体技术:这种方法比阴影形状方法更复杂。利用不同光照条件下拍摄的图像来求解深度信息。值得一提的是,这种方法需要多个图像。

纹理:假设这样一个物体表面光滑,被复制的纹理单元覆盖,其从3D到2D的投影导致失真和透视。二维图像的畸变和透视为反求物体表面法线信息的深度提供了线索。

2 双目立体视觉

双目立体视觉是在研究人类视觉系统的基础上,从多幅图像中获取物体的三维几何信息。结果以深度图的形式表示。利用两台摄像机同时在不同视角下获取的物体图像,或一台摄像机在不同视角下不同时间获取的物体图像,恢复物体的三维几何信息,重建物体的三维轮廓和位置。这比单目方法,如从阴影形状更直接。
双目立体视觉方法需要两台具有平行光轴的相同摄像机对同一物体进行观察,从不同角度获取两幅图像。在三角关系中,深度信息可以通过视差来计算。双目立体视觉方法发展良好,稳定性好,有利于三维重建,与其他三维结构相比具有更好的性能。不幸的是,它是计算密集型的,此外,当基线距离较大时,它的性能相当差。

2.1 图像采集

二维数字图像采集是三维重建的信息源。常用的三维重建是基于两个或多个图像,虽然在某些情况下可能只使用一个图像。图像采集的方法有很多种,这取决于具体应用的场合和目的。不仅要满足应用的要求,还要考虑摄像机的视差、照度、性能以及场景的特点。

2.2 相机标定

双目立体视觉中摄像机标定是指确定三维场景中图像点P1(u1,v1)与点P2(u2,v2)、空间坐标P(xp, yp, zp)之间的映射关系。摄像机标定是双目立体视觉三维重建的基础和关键环节。

如今便宜的针孔相机会给图像带来很多畸变,两种主要的畸变是径向畸变和切向畸变。由于径向畸变,直线会出现曲线。当我们远离图像中心时,它的效果会更明显。例如,如下图所示,一个棋盘的两条边用红线标出,但是你可以看到边界不是直线也不与红线匹配,所有预期的直线都凸出来了。

这种失真的解决方法如下:

类似地,另一种失真是切向失真,这种失真的发生是由于拍摄的图像没有与成像平面完全平行。所以图像中的一些区域看起来比预期的要近。求解如下:

简而言之,我们需要找到五个参数,称为畸变系数,即:

除此之外,我们还需要找到更多的信息,比如相机的内部参数和外部参数。相机的内部参数是特定的,包括焦距()、光学中心()等信息,也被称为相机矩阵,只依赖于相机,所以一旦计算出来,它就可以存储起来以备将来使用,表示为一个3x3矩阵:

外部参数对应于旋转和平移向量,它们将三维点的坐标转换为对应坐标系。

对于立体相机应用,首先需要纠正这些畸变。要找到所有这些参数,我们必须提供一些定义良好的模式(如棋盘)的示例图像。我们在其中找到了一些特定的点(棋盘上的四角),我们知道它在现实空间中的坐标也知道它在图像中的坐标。利用这些数据,通过解决一些数学问题得到畸变系数。为了得到更好的结果,我们需要至少10个测试模式。

如上所述,我们需要至少10个测试模式来校准相机。OpenCV附带了一些棋盘的图片(见samples/cpp/left01.jpg -- left14.jpg),所以我们会利用它。为了便于理解,只考虑棋盘上的一个图像。摄像机标定所需的重要输入数据是一组三维真实世界点及其对应的二维图像点,二维图像点是可以很容易从图像中找到的(这些图像点是棋盘上两个黑色方块相互接触的位置),那么现实世界中的三维点呢?这些图像是从静态相机拍摄的,棋盘被放置在不同的位置和方向,我们需要知道(X,Y,Z)的值。但为了简单起见,我们可以说棋盘在XY平面上保持静止(所以Z总是0),摄像机也相应地移动。这个考虑帮助我们只找到X,Y的值。现在对于X,Y的值,我们可以简单地传递点(0,0)(1,0)(2,0),…表示点的位置。在这种情况下,我们得到的结果将是棋盘正方形大小的比例。但是,如果我们知道正方形的大小(比如30mm),我们可以将值传递为(0,0)、(30,0)、(60,0)、……,我们得到的结果是mm(在本例中,我们不知道正方形的大小,因为我们没有拍摄这些图像,所以我们用正方形的大小传递)。

三维点称为目标点,二维图像点称为图像点。

因此,为了在棋盘中找到模式,我们使用了函数cv2.findChessboardCorners()。我们还需要传递我们正在寻找的模式,如8x8网格,5x5网格等。在本例中,我们使用7x6网格(通常棋盘有8x8个正方形和7x7个内角),它返回角点和返回值,如果获得模式则返回True,这些角将按顺序排列(从左到右,从上到下)

一旦找到角点,就可以使用cv2.cornerSubPix()提高它们的精度,还可以使用cv2.drawChessboardCorners()绘制模式。所有这些步骤都包含在下面的代码中:

import numpy as np
import cv2
import glob

# termination criteria
criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001)

# prepare object points, like (0,0,0), (1,0,0), (2,0,0) ....,(6,5,0)
objp = np.zeros((6*7,3), np.float32)
objp[:,:2] = np.mgrid[0:7,0:6].T.reshape(-1,2)

# Arrays to store object points and image points from all the images.
objpoints = [] # 3d point in real world space
imgpoints = [] # 2d points in image plane.

images = glob.glob('*.jpg')

for fname in images:
    img = cv2.imread(fname)
    gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)

    # Find the chess board corners
    ret, corners = cv2.findChessboardCorners(gray, (7,6),None)

    # If found, add object points, image points (after refining them)
    if ret == True:
        objpoints.append(objp)

        corners2 = cv2.cornerSubPix(gray,corners,(11,11),(-1,-1),criteria)
        imgpoints.append(corners2)

        # Draw and display the corners
        img = cv2.drawChessboardCorners(img, (7,6), corners2,ret)
        cv2.imshow('img',img)
        cv2.waitKey(500)

cv2.destroyAllWindows()

其中一幅图像如下图所示:

现在有了目标点和图像点,我们可以进行标定了。为此,我们使用函数cv2.calibrateCamera(),它返回相机矩阵、畸变系数、旋转和平移向量等。

ret, mtx, dist, rvecs, tvecs = cv2.calibrateCamera(objpoints, imgpoints, gray.shape[::-1],None,None)

现在我们可以拍摄一张图像,并将其还原。OpenCV有两种方法,我们将同时看到这两种方法。但在此之前,我们可以根据自由缩放参数使用cv2.getOptimalNewCameraMatrix()改进相机矩阵。如果缩放参数alpha=0,则返回具有最小不需要像素的未失真图像。因此,它甚至可能删除图像角上的一些像素。如果alpha=1,所有像素都保留一些额外的黑色图像。它还返回一个图像ROI,可用于裁剪结果。

因此,我们取一张新图像(本例中为left12.jpg,这是本章的第一张图片)

img = cv2.imread('left12.jpg')
h,  w = img.shape[:2]
newcameramtx, roi=cv2.getOptimalNewCameraMatrix(mtx,dist,(w,h),1,(w,h))

法1:使用cv2.undistort(),只需调用该函数并使用上面得到的ROI来裁剪结果。

# undistort
dst = cv2.undistort(img, mtx, dist, None, newcameramtx)

# crop the image
x,y,w,h = roi
dst = dst[y:y+h, x:x+w]
cv2.imwrite('calibresult.png',dst)

法2:使用重映射,首先找到一个从畸变图像到非畸变图像的映射函数,然后使用remap函数。

# undistort
mapx,mapy = cv2.initUndistortRectifyMap(mtx,dist,None,newcameramtx,(w,h),5)
dst = cv2.remap(img,mapx,mapy,cv2.INTER_LINEAR)

# crop the image
x,y,w,h = roi
dst = dst[y:y+h, x:x+w]
cv2.imwrite('calibresult.png',dst)

这两种方法得到了相同的结果。结果如下:

你可以在结果中看到所有的边都是直的。

现在您可以使用Numpy中的写函数(np.savez, np.savetxt等) 存储相机矩阵和畸变系数,以备将来使用。

重投影误差可以很好地估计出所找到的参数的精确程度。这个应该尽可能地接近于零。考虑到图像的内参矩阵、畸变矩阵、旋转矩阵和平移矩阵,我们首先使用cv2.projectPoints()将目标点转换为图像点。然后我们计算得到的绝对范数与求角算法之间的绝对范数。为了求出标定图像的平均误差,计算了所有标定图像误差的算术平均值。

mean_error = 0
for i in xrange(len(objpoints)):
    imgpoints2, _ = cv2.projectPoints(objpoints[i], rvecs[i], tvecs[i], mtx, dist)
    error = cv2.norm(imgpoints[i],imgpoints2, cv2.NORM_L2)/len(imgpoints2)
    tot_error += error

print "total error: ", mean_error/len(objpoints)

2.3 特征提取

特征提取的目的是获得图像的特征,通过特征提取对图像进行立体对应处理。因此,图像的特征与匹配方法的选择密切相关。在双目立体视觉研究中,由于特征提取理论的不统一,导致了立体对应的多样性。

2.4 立体匹配

立体对应是建立图像中原始因子之间的对应关系,即从两幅图像中匹配P1(u1,v1)和P2(u2,v2)。场景中应注意一定的干扰因素,如光照、噪声、表面物理特性等。

2.5 三维重建

根据精确的对应关系,结合摄像机的定位参数,可以很容易地恢复三维几何信息。由于三维重建的精度依赖于对应的精度、相机定位参数的误差等因素,要实现相对准确的三维重建,必须认真完成前面的步骤。

2.6 医学图像三维重建

精确的人体解剖三维模型有助于临床常规的诊断、患者随访、计算机辅助手术、手术计划等。三维重建的主要动机包括

  • 由于多视图聚合提高了准确性。
  • 详细的估计。
  • 可用于计划、模拟、指导或以其他方式协助外科医生执行医疗程序。
  • 可以确定病人解剖的精确位置和方向。
  • 在许多临床领域提供帮助,如放射治疗计划和治疗验证、脊柱外科、髋关节置换、神经干预和主动脉支架置入术。

应用

三维视觉逐渐从传统工业领域走向日常生活,比如AR/VR、SLAM、自动驾驶等,三维重建在许多领域都有应用,有:医学,Free-viewpoint视频重建,机器人建图,城市规划,游戏,虚拟环境与虚拟旅游,地球观测,考古,增强现实,反向工程,动作捕捉,手势识别和手部跟踪,骨骼跟踪等

 

  • 1
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值