1

我已经能够在这样的 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 文件的旋转和平移向量)将它们显示在屏幕上。

因此,基于此,我的问题是:

  1. 我将如何去做,最好的方法是什么?

  2. 如何在对象点内使用为对象提供的旋转和平移向量来获得 3D 世界中的姿势并将它们投影到 2D 图像中,以便所有 apriltags 都显示在 openCV 窗口上,是我认为最好的方法是什么?

  3. 如果我要在 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 会正常工作吗?

任何帮助将不胜感激!

4

0 回答 0