opencv - py_calib3d - py_pose 姿势估计

文章目录

Pose Estimation 姿势估计

目标

在本节中,

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

基础知识

这将是一个小部分。在上一节关于相机校准的课程中,您已经找到了相机矩阵、失真系数等。给定一个图案图像,我们可以利用上述信息来计算其姿势,或者物体在空间中的位置,例如它如何旋转、如何位移等。对于平面物体,我们可以假设 Z=0,这样,问题就变成了相机在空间中的位置,以便看到我们的图案图像。因此,如果我们知道物体在空间中的位置,我们可以在其中绘制一些 2D 图来模拟 3D 效果。让我们看看如何做到这一点。

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

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

python 复制代码
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')]

现在让我们创建一个函数 draw,它使用棋盘中的角点(使用 cv.findChessboardCorners() 获得)和 axis points 来绘制 3D 轴。

python 复制代码
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)。负数表示它朝向相机绘制。

python 复制代码
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() 函数从第一个角到每个点绘制线。完成了 !!!

python 复制代码
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)
	
	    # Find the rotation and translation vectors.
	    ret,rvecs, tvecs = cv.solvePnP(objp, corners2, mtx, dist)
	
	    # project 3D points to image plane
	    imgpts, jac = cv.projectPoints(axis, rvecs, tvecs, mtx, dist)
	
	    img = draw(img,corners2,imgpts)
	    cv.imshow('img',img)
	    k = cv.waitKey(0) & 0xFF
	    if k == ord('s'):
	        cv.imwrite(fname[:6]+'.png', img)

		cv.destroyAllWindows()

请参阅下面的一些结果。请注意,每个轴的长度为 3 个正方形。:

渲染立方体

如果您想绘制立方体,请按如下方式修改 draw() 函数和轴点。

修改后的 draw() 函数:

python 复制代码
def draw(img, corners, imgpts):
    imgpts = np.int32(imgpts).reshape(-1,2)

	# draw ground floor in green
	img = cv.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 = cv.line(img, tuple(imgpts[i]), tuple(imgpts[j]),(255),3)
	
	# draw top layer in red color
	img = cv.drawContours(img, [imgpts[4:]],-1,(0,0,255),3)
	
	return img

修改后的axis points。它们是 3D 空间中立方体的 8 个角:

python 复制代码
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] ])

并查看下面的结果:

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

相关推荐
晨间晓15 小时前
图片里的高频和低频是什么?用华为云码道开发 OpenCV 傅里叶频谱分析工具
opencv·计算机视觉·华为云
晨间晓15 小时前
图片里的阴影能不能减弱?用华为云码道开发 OpenCV 光照校正工具
人工智能·opencv·华为云
晨间晓1 天前
图片里的细小噪点怎么平滑?用华为云码道开发 OpenCV 图像滤波对比工具
人工智能·opencv·华为云
偷吃米饭1 天前
图片特征怎么描述?用华为云码道开发 OpenCV ORB 特征提取工具
人工智能·opencv·华为云
晨间晓1 天前
图片里的关键点怎么找?用华为云码道开发 OpenCV FAST 特征点检测工具
人工智能·opencv·华为云
晨间晓1 天前
二值图里的噪点怎么去掉?用华为云码道开发 OpenCV 形态学操作工具
人工智能·opencv·华为云
晨间晓2 天前
图片里的角点在哪里?用华为云码道开发 OpenCV Harris 角点检测工具
人工智能·opencv·华为云
晨间晓2 天前
图片细节丰富不丰富?用华为云码道开发 OpenCV 纹理复杂度分析工具
人工智能·opencv·华为云
richard_yuu2 天前
OpenCV 实战第 15 篇:G-API 图计算,工业流水线的 CPU/GPU 混合执行
人工智能·opencv·计算机视觉
老唐7773 天前
OpenCV5实测:纯CPU跑YOLO26目标检测
图像处理·人工智能·opencv·yolo·目标检测·计算机视觉