目标

在本章中

  • 我们将学习利用calib3d模块在图像中创建一些3D效果。

基础

这将是一小部分。在上一次相机校准的会话中,你发现了相机矩阵,失真系数等。给定图案图像,我们可以利用以上信息来计算其姿势或物体在空间中的位置,例如其旋转方式, 对于平面物体,我们可以假设Z = 0,这样,问题就变成了如何将相机放置在空间中以查看图案图像。 因此,如果我们知道对象在空间中的位置,则可以在其中绘制一些2D图以模拟3D效果。 让我们看看如何做。

我们的问题是,我们想在棋盘的第一个角上绘制3D坐标轴(X,Y,Z)。 X轴为蓝色,Y轴为绿色,Z轴为红色。 因此,实际上Z轴应该感觉像它垂直于我们的棋盘平面。

首先,让我们从先前的校准结果中加载相机矩阵和失真系数。

import numpy as np
import cv2 as cv
import glob
# 加载先前保存的数据
with np.load('B.npz') as X:mtx, dist, _, _ = [X[i] for i in ('mtx','dist','rvecs','tvecs')]

现在让我们创建一个函数,绘制,该函数将棋盘上的角(使用cv.findChessboardCorners()获得)和轴点绘制为3D轴。

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

然后,与前面的情况一样,我们创建终止条件,对象点(棋盘上角的3D点)和轴点。 轴点是3D空间中用于绘制轴的点。 我们绘制长度为3的轴(由于我们根据该棋盘尺寸进行了校准,因此单位将以国际象棋正方形的尺寸为单位)。因此我们的X轴从(0,0,0)绘制为(3,0,0),因此对于Y轴。 对于Z轴,从(0,0,0)绘制为(0,0,-3)。 负号表示它被拉向相机。

criteria = (cv.TERM_CRITERIA_EPS + cv.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网格。如果找到,我们将使用子角像素对其进行优化。然后使用函数cv.solvePnPRansac()计算旋转和平移。一旦有了这些变换矩阵,就可以使用它们将轴点投影到图像平面上。简而言之,我们在图像平面上找到与3D空间中(3,0,0),(0,3,0),(0,0,3)中的每一个相对应的点。一旦获得它们,就可以使用draw()函数从第一个角到这些点中的每个点绘制线条。完毕!!!

for fname in glob.glob('left*.jpg'):img = cv.imread(fname)gray = cv.cvtColor(img,cv.COLOR_BGR2GRAY)ret, corners = cv.findChessboardCorners(gray, (7,6),None)if ret == True:corners2 = cv.cornerSubPix(gray,corners,(11,11),(-1,-1),criteria)# 找到旋转和平移矢量。ret,rvecs, tvecs = cv.solvePnP(objp, corners2, mtx, dist)# 将3D点投影到图像平面imgpts, jac = cv.projectPoints(axis, rvecs, tvecs, mtx, dist)img = draw(img,corners2,imgpts)cv.imshow('img',img)k = cv.waitKey(0) & 0xFFif k == ord('s'):cv.imwrite(fname[:6]+'.png', img)
cv.destroyAllWindows()

请参阅下面的一些结果。请注意,每个轴长3个long单位。

绘制立方体

如果要绘制立方体,请如下修改draw()函数和轴点。
修改后的draw()函数:

def draw(img, corners, imgpts):imgpts = np.int32(imgpts).reshape(-1,2)# 用绿色绘制底层img = cv.drawContours(img, [imgpts[:4]],-1,(0,255,0),-3)# 用蓝色绘制高for i,j in zip(range(4),range(4,8)):img = cv.line(img, tuple(imgpts[i]), tuple(imgpts[j]),(255),3)# 用红色绘制顶层img = cv.drawContours(img, [imgpts[4:]],-1,(0,0,255),3)return img

修改的轴点。它们是3D空间中多维数据集的8个角:

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] ])

查看以下结果:

pose_2

如果您对图形,增强现实等感兴趣,则可以使用OpenGL渲染更复杂的图形。

☆☆☆为方便大家查阅,小编已将OpenCV-Python专栏文章统一整理到公众号底部菜单栏,同步更新中,关注公众号,点击左下方“文章”,如图:或点击下方“阅读原文”,进入OpenCV-Python专栏,即可查看系列文章。

OpenCV-Python交流群

关注最新最前沿OpenCV-Python专业知识,扫码添加mthler拉你入群,如果已经是mthler帐号好友直接私信即可。

(加群或私信请注明:交流群)

不断更新资源

获取更多精彩

长按二维码扫码关注

OpenCV系列之姿态估计 | 五十相关推荐

  1. OpenCV系列之图像修补 | 五十九

    目标 在本章中, 我们将学习如何通过一种称为"修复"的方法消除旧照片中的小噪音,笔画等. 我们将看到OpenCV中的修复功能. 基础 你们大多数人家里都会有一些旧的旧化照片,上面有 ...

  2. OpenCV系列之理解SVM | 五十五

    目标 在这一章中 我们将对SVM有一个直观的了解 理论 线性可分数据 考虑下面的图像,它具有两种数据类型,红色和蓝色.在kNN中,对于测试数据,我们用来测量其与所有训练样本的距离,并以最小的距离作为样 ...

  3. OpenCV系列之轮廓分层 | 二十五

    目标 这次我们学习轮廓的层次,即轮廓中的父子关系. 理论 在前几篇关于轮廓的文章中,我们已经讨论了与OpenCV提供的轮廓相关的几个函数.但是当我们使用cv.findcontour()函数在图像中找到 ...

  4. OpenCV系列之相机校准 | 四十九

    目标 在本节中,我们将学习 由相机引起的失真类型 如何找到相机的固有和非固有特性 如何根据这些特性使图像不失真 基础 一些针孔相机会给图像带来明显的失真.两种主要的变形是径向变形和切向变形. 径向变形 ...

  5. OpenCV系列之特征匹配 | 四十四

    目标 在本章中, 我们将看到如何将一个图像中的特征与其他图像进行匹配. 我们将在OpenCV中使用Brute-Force匹配器和FLANN匹配器 Brute-Force匹配器的基础 蛮力匹配器很简单. ...

  6. OpenCV系列之理解特征 | 三十六

    目标 在本章中,我们将尝试理解什么是特征,为什么拐角重要等等 解释 你们大多数人都会玩拼图游戏.你会得到很多小图像,需要正确组装它们以形成大的真实图像.问题是,你怎么做?将相同的理论投影到计算机程序上 ...

  7. OpenCV系列之图像的几何变换 | 十四

    目标 学习将不同的几何变换应用到图像上,如平移.旋转.仿射变换等. 你会看到这些函数: cv.getPerspectiveTransform 变换 OpenCV提供了两个转换函数cv.warpAffi ...

  8. 千道Java面试真题整理系列:MySQL灵魂五十问,在遇面试也不怕.

    1.MySQL 中有哪几种锁? 1.表级锁:开销小,加锁快:不会出现死锁:锁定粒度大,发生锁冲突的概率最高,并发度最低. 2.行级锁:开销大,加锁慢:会出现死锁:锁定粒度最小,发生锁冲突的概率最低,并 ...

  9. 千道Java面试真题整理系列:MySQL灵魂五十问,在遇面试也不怕!

    1.MySQL 中有哪几种锁? 表级锁:开销小,加锁快:不会出现死锁:锁定粒度大,发生锁冲突的概率最高,并发度最低. 行级锁:开销大,加锁慢:会出现死锁:锁定粒度最小,发生锁冲突的概率最低,并发度也最 ...

最新文章

  1. HDU 4869 Turn the pokers(思维+组合公式+高速幂)
  2. IT人士有哪些保健建议
  3. Linux操作命令(四)
  4. C/C++指针函数和函数指针
  5. 升级PowerShell至4.0版本
  6. 中间件:ElasticSearch组件RestHighLevelClient用法详解
  7. PHP中CURL方法curl_setopt()函数的一些参数
  8. SET化消息中间件架构实现
  9. 金蝶eas怎么引出凭证_金蝶EAS该如何导出凭证
  10. NOIP2016D2T2 蚯蚓
  11. mycat管理mysql_Mycat用户和权限控制管理
  12. 写插件代码查看单据简单示例分享
  13. Mac电脑如何播放swf格式文件?
  14. 关于win10激活工具激活系统,浏览器主页被T999,2345劫持解决方法
  15. 实验4——Pspice
  16. gitlab取消邮箱验证(适用gitlab各个版本)
  17. 小型微利企业税收筹划策略探析
  18. 程序员讲装修内容思路
  19. 【Spring笔记--全面版】
  20. 中国数据标注公司排名前十强有哪些?

热门文章

  1. IG夺冠5亿变63亿,电竞游戏引全民热潮,区块链游戏的未来在哪里? | 独角兽行研报告
  2. buildroot 添加 loongarch 2k1000la uboot kernel 编译问题
  3. safari浏览器附件下载文件中文名字乱码(转) || 苹果IOS 微信浏览器预览PDF乱码 解决方案(转)
  4. Xplorer² v2.2.0.0 Ultimate x86
  5. Qt构建工具QBS之一 ——从一个简单的工程开始
  6. Unity技术手册 - 形状(Shape)子模块 - Sprite、SpriteRenderer及生命周期内速度(Velocity over Lifetime)
  7. (一)移动端 Web 开发基础
  8. c语言1GB转成B,计算机应用基础考试题
  9. 微信安全中心:将处罚使用清理僵尸粉外挂用户
  10. Core java for impatient 笔记 ch8 流