OpenCV系列之姿态估计 | 五十
目标
在本章中
我们将学习利用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系列之姿态估计 | 五十相关推荐
- OpenCV系列之图像修补 | 五十九
目标 在本章中, 我们将学习如何通过一种称为"修复"的方法消除旧照片中的小噪音,笔画等. 我们将看到OpenCV中的修复功能. 基础 你们大多数人家里都会有一些旧的旧化照片,上面有 ...
- OpenCV系列之理解SVM | 五十五
目标 在这一章中 我们将对SVM有一个直观的了解 理论 线性可分数据 考虑下面的图像,它具有两种数据类型,红色和蓝色.在kNN中,对于测试数据,我们用来测量其与所有训练样本的距离,并以最小的距离作为样 ...
- OpenCV系列之轮廓分层 | 二十五
目标 这次我们学习轮廓的层次,即轮廓中的父子关系. 理论 在前几篇关于轮廓的文章中,我们已经讨论了与OpenCV提供的轮廓相关的几个函数.但是当我们使用cv.findcontour()函数在图像中找到 ...
- OpenCV系列之相机校准 | 四十九
目标 在本节中,我们将学习 由相机引起的失真类型 如何找到相机的固有和非固有特性 如何根据这些特性使图像不失真 基础 一些针孔相机会给图像带来明显的失真.两种主要的变形是径向变形和切向变形. 径向变形 ...
- OpenCV系列之特征匹配 | 四十四
目标 在本章中, 我们将看到如何将一个图像中的特征与其他图像进行匹配. 我们将在OpenCV中使用Brute-Force匹配器和FLANN匹配器 Brute-Force匹配器的基础 蛮力匹配器很简单. ...
- OpenCV系列之理解特征 | 三十六
目标 在本章中,我们将尝试理解什么是特征,为什么拐角重要等等 解释 你们大多数人都会玩拼图游戏.你会得到很多小图像,需要正确组装它们以形成大的真实图像.问题是,你怎么做?将相同的理论投影到计算机程序上 ...
- OpenCV系列之图像的几何变换 | 十四
目标 学习将不同的几何变换应用到图像上,如平移.旋转.仿射变换等. 你会看到这些函数: cv.getPerspectiveTransform 变换 OpenCV提供了两个转换函数cv.warpAffi ...
- 千道Java面试真题整理系列:MySQL灵魂五十问,在遇面试也不怕.
1.MySQL 中有哪几种锁? 1.表级锁:开销小,加锁快:不会出现死锁:锁定粒度大,发生锁冲突的概率最高,并发度最低. 2.行级锁:开销大,加锁慢:会出现死锁:锁定粒度最小,发生锁冲突的概率最低,并 ...
- 千道Java面试真题整理系列:MySQL灵魂五十问,在遇面试也不怕!
1.MySQL 中有哪几种锁? 表级锁:开销小,加锁快:不会出现死锁:锁定粒度大,发生锁冲突的概率最高,并发度最低. 行级锁:开销大,加锁慢:会出现死锁:锁定粒度最小,发生锁冲突的概率最低,并发度也最 ...
最新文章
- HDU 4869 Turn the pokers(思维+组合公式+高速幂)
- IT人士有哪些保健建议
- Linux操作命令(四)
- C/C++指针函数和函数指针
- 升级PowerShell至4.0版本
- 中间件:ElasticSearch组件RestHighLevelClient用法详解
- PHP中CURL方法curl_setopt()函数的一些参数
- SET化消息中间件架构实现
- 金蝶eas怎么引出凭证_金蝶EAS该如何导出凭证
- NOIP2016D2T2 蚯蚓
- mycat管理mysql_Mycat用户和权限控制管理
- 写插件代码查看单据简单示例分享
- Mac电脑如何播放swf格式文件?
- 关于win10激活工具激活系统,浏览器主页被T999,2345劫持解决方法
- 实验4——Pspice
- gitlab取消邮箱验证(适用gitlab各个版本)
- 小型微利企业税收筹划策略探析
- 程序员讲装修内容思路
- 【Spring笔记--全面版】
- 中国数据标注公司排名前十强有哪些?
热门文章
- IG夺冠5亿变63亿,电竞游戏引全民热潮,区块链游戏的未来在哪里? | 独角兽行研报告
- buildroot 添加 loongarch 2k1000la uboot kernel 编译问题
- safari浏览器附件下载文件中文名字乱码(转) || 苹果IOS 微信浏览器预览PDF乱码 解决方案(转)
- Xplorer² v2.2.0.0 Ultimate x86
- Qt构建工具QBS之一 ——从一个简单的工程开始
- Unity技术手册 - 形状(Shape)子模块 - Sprite、SpriteRenderer及生命周期内速度(Velocity over Lifetime)
- (一)移动端 Web 开发基础
- c语言1GB转成B,计算机应用基础考试题
- 微信安全中心:将处罚使用清理僵尸粉外挂用户
- Core java for impatient 笔记 ch8 流