当前位置:   article > 正文

Opencv实验合集——实验九:姿势估计_cv.line(img, tuple(imgpts[i]), tuple(imgpts[j]), (

cv.line(img, tuple(imgpts[i]), tuple(imgpts[j]), (0,255,0), 6) indexerror: i

在上一章节(相机校准),你已经找到了相机矩阵,畸变系数等等参数。给出一个图案图像,我们便可以利用上面的信息用于计算其姿势,或者物体在空间中位于何处,比如如何旋转,如何移动等等问题。对于一个平面物体,我们可以假定 Z = 0,这样,问题现在便转化为了如何放置摄像机才能查看到我们的图案图像。所以如果我们知道物体在空间中的位置,我们便可以绘制一些 2D 图像用以模拟 3D 效果。

我们的问题是,我们想在我们棋盘的第一个角上绘制 3D 坐标系(x, y, z 坐标系),其中 X 轴是蓝色,Y 轴是绿色,Z 轴是红色。所以从效果上讲,Z 轴应该感觉像是与棋盘垂直的。

1.定义

姿势估计是指通过分析图像或传感器数据来推断物体、人体或相机在三维空间中的姿势,即位置和方向。姿势通常由平移和旋转两个主要组成部分构成。

2.有关的函数方法

本节与上一个实验密切相关,重复的方法就不再一一赘述了

cv2.projectPoints 函数是 OpenCV 中用于将 3D 点投影到图像平面的函数。它是摄像机标定和相机投影中常用的一个函数。该函数的签名如下:

cv2.projectPoints(objectPoints, rvec, tvec, cameraMatrix, distCoeffs[, imagePoints[, jacobian[, aspectRatio]]]) → imagePoints, jacobian

  • objectPoints: 三维物体点的坐标,是一个 numpy 数组,形状为 (N, 3),N 是点的数量。
  • rvec: 旋转向量,描述了物体坐标系相对于相机坐标系的旋转。是一个长度为 3 的 numpy 数组。
  • tvec: 平移向量,描述了物体坐标系相对于相机坐标系的平移。是一个长度为 3 的 numpy 数组。
  • cameraMatrix: 相机内参矩阵,是一个 3x3 的矩阵。
  • distCoeffs: 相机的畸变系数,是一个包含畸变参数的 numpy 数组。
  • imagePoints (可选): 输出参数,是一个 numpy 数组,包含了三维点在图像平面上的投影坐标。
  • jacobian (可选): 输出参数,是一个 numpy 数组,包含了投影函数的导数信息。
  • aspectRatio (可选): 相机的纵横比,即图像的宽高比。

3.代码演示

首先我们先在棋盘上的三个点上建立三角坐标系XYZ,通过绘图进行展示,上个实验已经讲述了如何从世界坐标系转化相机坐标系,获得一系列参数(旋转,平移参数等),如何通过转化成相机坐标系再通过方法将3D点投影到图像平面上。

  1. import numpy as np
  2. import cv2 as cv
  3. import glob
  4. # 终止标准
  5. criteria = (cv.TERM_CRITERIA_EPS + cv.TERM_CRITERIA_MAX_ITER, 30, 0.001)
  6. # 准备对象点, 如 (0,0,0), (1,0,0), (2,0,0) ....,(6,5,0)
  7. objp = np.zeros((6*7,3), np.float32)
  8. objp[:,:2] = np.mgrid[0:7,0:6].T.reshape(-1,2)
  9. axis = np.float32([[3,0,0], [0,3,0], [0,0,-3]]).reshape(-1,3)
  10. #axis是世界坐标系中的三个点,用来绘制图像上的相机坐标系
  11. # 用于存储所有图像对象点与图像点的矩阵
  12. objpoints = [] # 在真实世界中的 3d 点
  13. imgpoints = [] # 在图像平面中的 2d 点
  14. # images = glob.glob('*.jpg')
  15. images = [r'C:\Users\xiaoou\Desktop\picture\chess.jpg']
  16. def draw(img, corners, imgpts):#在一个角点上建立相机平面坐标系
  17. corner = tuple(corners[0].ravel())#在检测的众多角点中随机抽取一个
  18. img = cv.line(img, np.int32(corner), np.int32(tuple(imgpts[0].ravel())), (255,0,0), 5)
  19. img = cv.line(img, np.int32(corner), np.int32(tuple(imgpts[1].ravel())), (0,255,0), 5)
  20. img = cv.line(img, np.int32(corner), np.int32(tuple(imgpts[2].ravel())), (0,0,255), 5)
  21. return img
  22. for fname in images:
  23. img = cv.imread(fname)
  24. gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
  25. # 找到棋盘上所有的角点
  26. ret, corners = cv.findChessboardCorners(gray, (7,6), None)
  27. # 如果找到了,便添加对象点和图像点(在细化后)
  28. if ret == True:
  29. objpoints.append(objp)
  30. corners2 = cv.cornerSubPix(gray,corners, (11,11), (-1,-1), criteria)
  31. imgpoints.append(corners)
  32. # 绘制角点
  33. # cv.drawChessboardCorners(img, (7,6), corners2, ret)
  34. ret, mtx, dist, rvecs, tvecs = cv.calibrateCamera(objpoints, imgpoints, gray.shape[::-1], None, None)
  35. imgpts, jac = cv.projectPoints(axis,rvecs[0],tvecs[0],mtx,dist)
  36. img = draw(img, corners2, imgpts)
  37. cv.imshow('img', img)
  38. cv.waitKey(0)

现在把投影的点扩大为8个,构成一个长方体,绘制底部为绿色,顶部为红色,来让姿势估计更加具体。

  1. import numpy as np
  2. import cv2 as cv
  3. import glob
  4. # 终止标准
  5. criteria = (cv.TERM_CRITERIA_EPS + cv.TERM_CRITERIA_MAX_ITER, 30, 0.001)
  6. # 准备对象点, 如 (0,0,0), (1,0,0), (2,0,0) ....,(6,5,0)
  7. objp = np.zeros((6*7,3), np.float32)
  8. objp[:,:2] = np.mgrid[0:7,0:6].T.reshape(-1,2)
  9. axis = np.float32([ [0,0,0], [0,1,0], [1,1,0], [1,0,0],
  10. [0,0,-1],[0,1,-1],[1,1,-1],[1,0,-1] ])
  11. # 用于存储所有图像对象点与图像点的矩阵
  12. objpoints = [] # 在真实世界中的 3d 点
  13. imgpoints = [] # 在图像平面中的 2d 点
  14. images = [r'C:\Users\xiaoou\Desktop\picture\chess.jpg']
  15. def cube_draw(img, imgpts):#对8个平面的点建立相连建立一个长方体
  16. imgpts = np.int32(imgpts).reshape(-1,2)
  17. # 将底面绘制为绿色
  18. img = cv.drawContours(img, [imgpts[:4]], -1, (0,255,0), -3)
  19. # 将支柱绘制为蓝色
  20. for i,j in zip(range(4), range(4,8)):
  21. img = cv.line(img,tuple(imgpts[i]), tuple(imgpts[j]), (255,0,0), 3)
  22. # 将顶面绘制为红色
  23. img = cv.drawContours(img, [imgpts[4:]], -1, (0,0,255), 3)
  24. return img
  25. for fname in images:
  26. img = cv.imread(fname)
  27. gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
  28. # 找到棋盘上所有的角点
  29. ret, corners = cv.findChessboardCorners(gray, (7,6), None)
  30. # 如果找到了,便添加对象点和图像点(在细化后)
  31. if ret == True:
  32. objpoints.append(objp)
  33. corners2 = cv.cornerSubPix(gray,corners, (11,11), (-1,-1), criteria)
  34. imgpoints.append(corners)
  35. ret, mtx, dist, rvecs, tvecs = cv.calibrateCamera(objpoints, imgpoints, gray.shape[::-1], None, None)
  36. imgpts, jac = cv.projectPoints(axis,rvecs[0],tvecs[0],mtx,dist)
  37. img = cube_draw(img, imgpts)
  38. cv.imshow('img', img)
  39. cv.waitKey(0)

 本次实验主要演示了三维重建中的姿势估计,主要通过将世界坐标系中的目标点转化为平面中的投影点,以此用来估计目标点在平面上的形状。

如有错误或遗漏,希望小伙伴批评指正!!!! 

希望这篇博客对你有帮助!!!!

实验八:Opencv实验合集——实验八:相机校准-CSDN博客

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/繁依Fanyi0/article/detail/341162
推荐阅读
相关标签
  

闽ICP备14008679号