我已经能够在这样的 apriltags 板上检测到多个 apriltags:
这是使用 AprilTag 库完成的:https ://github.com/swatbotics/apriltag 。我使用 OpenCV solvePnP() 和 projectPoints() 来获取旋转和平移向量,并将 3D 点投影到 2D 点上以显示这些 apriltags 的位姿。
请参见下面的代码:
# I am getting the tag sizes from a json file for all apriltags
tag_sizes, tvecs, rvecs = get_extrinsics(json_file)
# Convert Images to grayscale
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# AprilTag detector options
options = apriltag.DetectorOptions(families='tag36h11',
border=1,
nthreads=4,
quad_decimate=1.0,
quad_blur=0.0,
refine_edges=True,
refine_decode=False,
refine_pose=True,
debug=False,
quad_contours=True)
detector = apriltag.Detector(options)
# Detect the apriltags in the image
detection_results, dimg = detector.detect(gray, return_image=True)
# Amount of april tags detected
num_detections = len(detection_results)
print('Detected {} tags.\n'.format(num_detections))
imgPointsArr = []
objPointsArr = []
opointsArr = []
if num_detections > 0:
for i, detection in enumerate(detection_results):
print('Detection {} of {}:'.format(i + 1, num_detections))
print()
print(detection.tostring(indent=2))
if mtx is not None:
imagePoints = detection.corners.reshape(1,4,2)
# Get the tag size from .json file
tag_size = tag_sizes[detection.tag_id]
ob_pt1 = [-tag_size/2, -tag_size/2, 0.0]
ob_pt2 = [ tag_size/2, -tag_size/2, 0.0]
ob_pt3 = [ tag_size/2, tag_size/2, 0.0]
ob_pt4 = [-tag_size/2, tag_size/2, 0.0]
ob_pts = ob_pt1 + ob_pt2 + ob_pt3 + ob_pt4
object_pts = np.array(ob_pts).reshape(4,3)
opoints = np.array([
-1, -1, 0,
1, -1, 0,
1, 1, 0,
-1, 1, 0,
-1, -1, -2*1,
1, -1, -2*1,
1, 1, -2*1,
-1, 1, -2*1,
]).reshape(-1, 1, 3) * 0.5*tag_size
imgPointsArr.append(imagePoints)
objPointsArr.append(object_pts)
opointsArr.append(opoints)
# mtx - the camera calibration's intrinsics
good, prvecs, ptvecs = cv2.solvePnP(object_pts, imagePoints, mtx, dcoeffs, flags=cv2.SOLVEPNP_ITERATIVE)
imgpts, jac = cv2.projectPoints(opoints, prvecs, ptvecs, mtx, dcoeffs)
# Draws the edges of the pose onto the image
draw_boxes(img, imgpts, edges)
这非常适合 apriltag 板。但是,现在我正在尝试检测附加了 apriltags 的对象(十二面体:Dodecapen)的姿势。这些已经校准并附带列出每个标签大小的 json 文件,以及对应于正确标签 ID 的旋转和平移向量。
使用该 json 文件中的旋转和平移向量,我需要将所有 apriltags(甚至是在框架中未检测到的那些)覆盖到 OpenCV 窗口上。为此,我将不得不使用对象点内的旋转和平移向量,而不仅仅是使用标签大小来使用来自 json 的向量获取对象点的位置,并将它们用作solvePnP中的3D点( )。我会将罗德里格斯应用于旋转矢量,然后将其应用于对象点,但我不确定如何将它们应用于对象点。
为了始终将所有 apriltags 显示在屏幕上,我在想,一旦我从 solvePnP() 获得旋转和平移,我可以将该旋转和平移应用于对象附带的预定义旋转和平移向量,然后使用 projectPoints() 投影这些点并绘制它,以显示覆盖?
因此,总而言之,在检测到帧中的 1 个或多个 apriltags 时,我试图估计整个对象(十二面体)的姿势,对于未检测到的 apriltags(例如对象后面的那些),我是使用现有的起始姿势(来自 .json 文件的旋转和平移向量)将它们显示在屏幕上。
因此,基于此,我的问题是:
我将如何去做,最好的方法是什么?
如何在对象点内使用为对象提供的旋转和平移向量来获得 3D 世界中的姿势并将它们投影到 2D 图像中,以便所有 apriltags 都显示在 openCV 窗口上,是我认为最好的方法是什么?
如果我要在 for 循环之外提供对象和图像点数组,如下所示:
objPointsArr = np.array(objPointsArr).reshape(-1, 3) imgPointsArr = np.array(imgPointsArr).reshape(-1, 2) opointsArr = np.array(opointsArr).reshape(-1, 3) good, prvecs, ptvecs = cv2.solvePnP(objPointsArr, imgPointsArr, mtx, dcoeffs, flags=cv2.SOLVEPNP_ITERATIVE) imgpts, jac = cv2.projectPoints(opointsArr, prvecs, ptvecs, mtx, dcoeffs) draw_boxes(img, imgpts, edges)
这些数组被附加在第一个代码示例的循环中。在 for 循环中,solvePnP 会正常工作吗?
任何帮助将不胜感激!