首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >使用双目相机进行三维重建 第二部分:姿态估计

使用双目相机进行三维重建 第二部分:姿态估计

作者头像
AI研习社
发布2019-05-15 13:24:36
1.3K0
发布2019-05-15 13:24:36
举报
文章被收录于专栏:AI研习社AI研习社AI研习社

原标题 : 3D Reconstruction with Stereo Images - Part 2: Pose Estimation 作者 | Keenan James 翻译 | 酱番梨、Hasekiel_learn 校对 | 酱番梨 审核 | 酱番梨 整理 | 立鱼王 原文链接: https://medium.com/@dc.aihub/3d-reconstruction-with-stereo-images-part-2-pose-estimation-1bcfbba61b26 注:本文的相关链接请访问文末【阅读原文】 查看第一部分,请点击:使用双目相机进行三维重建 第一部分:相机校准

引言:在上一篇文章中我们讲了相机的特征以及这些信息与我们做3D重建有什么关系。通过相机校正,我们确认了一些我们程序要用的相机属性数据,即相机矩阵(camera matrix)和扭曲系数(distortion coefficients)。利用这些信息,我们可以从拍摄的模式图像(patterned image)中计算出现实空间中物体的位置。在我们的例子中,我们会用象棋棋盘图像,并通过3D立方的绘制方向来可视化平面物体的相对位置。

开始

这个练习的目的是给我们的图像画上x,y,z轴,放在棋盘的底部角落。按惯例,3D空间中X坐标轴用蓝色、Y用绿色、Z用红色。这个例子里,我们让Z轴垂直于物体(即Z轴是从棋盘2D平面指向相机的)。

我们首先取出之前练习保存的相机矩阵和扭曲系数。

import cv2import numpy as npimport glob
# Load previously saved datawith np.load('B.npz') as X:    mtx, dist, _, _ = [X[i] for i in ('mtx','dist','rvecs','tvecs')]

接下来要写一个函数来绘制3D坐标轴。这个函数的输入是:棋盘图像、棋盘四个角(坐标)、三个分别代表三坐标轴方向终点的点(坐标)。

棋盘的角落可以用之前的`cv2.findChessboardCorner()`函数,返回的是一个含有4个角位置的数组。这里我们只需要注意底部左手角落,它是数组的第一个元素,如下图`corner[0]`。得到该坐标后,我们就可以利用之前定义的3个终点展开我们的坐标轴了。

def draw(img, corners, imgpts):    corner = tuple(corners[0].ravel())    img = cv2.line(img, corner, tuple(imgpts[0].ravel()), (255,0,0), 5)    img = cv2.line(img, corner, tuple(imgpts[1].ravel()), (0,255,0), 5)    img = cv2.line(img, corner, tuple(imgpts[2].ravel()), (0,0,255), 5)    return img

下一步我们要在3D空间中定义一些点帮助我们绘制坐标轴。回忆一下在上一个练习中,我们令棋盘一个方块的边长等于一个单位。在这个例子中,我们在三个方向上画了长3个单位的坐标轴。Z轴需要标负值,因为这样可以保证轴线面朝相机。

criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001)objp = np.zeros((6*7,3), np.float32)objp[:,:2] = np.mgrid[0:7,0:6].T.reshape(-1,2)
axis = np.float32([[3,0,0], [0,3,0], [0,0,-3]]).reshape(-1,3)

现在我们可以用上我们的绘制函数了。第一步先读取图片,寻找7x6的格子(译者注:指棋盘)。找到之后,我们可以利用`cv2.solvePnPRansac()`计算其旋转角和平移距离(rotation and translation)。现在把3D空间的轴点(axis points)投影到2D图像平面去。识别出坐标轴后,就用绘制函数可视化其方向。

for fname in glob.glob('left*.jpg'):    img = cv2.imread(fname)    gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)    ret, corners = cv2.findChessboardCorners(gray, (7,6),None)
    if ret == True:        corners2 = cv2.cornerSubPix(gray,corners,(11,11),(-1,-1),criteria)
        # Find the rotation and translation vectors.        rvecs, tvecs, inliers = cv2.solvePnPRansac(objp, corners2, mtx, dist)
        # project 3D points to image plane        imgpts, jac = cv2.projectPoints(axis, rvecs, tvecs, mtx, dist)
        img = draw(img,corners2,imgpts)        cv2.imshow('img',img)        k = cv2.waitKey(0) & 0xff        if k == 's':            cv2.imwrite(fname[:6]+'.png', img)
cv2.destroyAllWindows()

如下图,我们看到四张不同棋盘图像被我们程序处理后的结果。

渲染一个立方体

为了描画一个立方体,我们可以按照下文所述修改绘图函数。首先绘制一个3 x 3的正方形,朝向左下角并与我们的棋盘平行。然后我们将添加从该正方形延伸的线,以在面向相机的方向上完成立方体。

def draw(img, corners, imgpts):    imgpts = np.int32(imgpts).reshape(-1,2)
    # draw ground floor in green    img = cv2.drawContours(img, [imgpts[:4]],-1,(0,255,0),-3)
    # draw pillars in blue color    for i,j in zip(range(4),range(4,8)):        img = cv2.line(img, tuple(imgpts[i]), tuple(imgpts[j]),(255),3)
    # draw top layer in red color    img = cv2.drawContours(img, [imgpts[4:]],-1,(0,0,255),3)
    return img

我们必须修改轴点,并以此来囊括立方体的每个角。

axis = np.float32([[0,0,0], [0,3,0], [3,3,0], [3,0,0],                   [0,0,-3],[0,3,-3],[3,3,-3],[3,0,-3] ])

下面的两幅图片已将结果显示出来:

结论

在上述练习之后,我们可以考虑增强现实(AR)的应用。在这里,我们成功地将3D对象包含在真实世界图像中,该图像与所描绘的对象相互作用,允许真实世界和虚拟世界之间的动态链接。

作者:Keenan James,导师:Amit Maraj教授

想要继续查看该篇文章相关链接和参考文献?

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-05-07,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 AI研习社 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 开始
  • 渲染一个立方体
  • 结论
相关产品与服务
图像处理
图像处理基于腾讯云深度学习等人工智能技术,提供综合性的图像优化处理服务,包括图像质量评估、图像清晰度增强、图像智能裁剪等。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档