Aruco Code Pose Estimation - SolvePnP issues

158 views Asked by At

I'm currently working on ArUco Code Pose Estimation using OpenCV's library. Due to using the latest OpenCV version (4.8.1.78), I've encountered limitations with most of the functions commonly used in tutorials and GitHub repositories. I'm attempting to perform pose estimation utilizing solvePnP. The translation and rotation vectors provided by this method should represent the pose of the ArUco code in relation to the camera. To verify this, I'm displaying these vectors on each frame.

However, upon reviewing the video output, I'm noticing that the frame isn't correctly aligned with the ArUco code; instead, it's displayed somewhere in space at the bottom left corner of the frames.

I've thoroughly reviewed my code but haven't been able to identify the issue. The markers are detected accurately, but the pose estimation doesn't seem to yield the expected results. Any insights or guidance on resolving this discrepancy would be greatly appreciated.

from utils import ARUCO_DICT, aruco_display
import cv2
import numpy as np
import matplotlib.pyplot as plt
import csv


def detect_aruco(camera, video, type, output_video_path, marker_size):
    if camera:
        video_capture = cv2.VideoCapture(0)
        cv2.waitKey(2000)
    else:
        if video is None:
            print("[Error] Video file location is not provided")
            return

        video_capture = cv2.VideoCapture(video)

    if type not in ARUCO_DICT:
        print(f"ArUCo tag type '{type}' is not supported")
        return

    aruco_dict = cv2.aruco.getPredefinedDictionary(ARUCO_DICT[type])
    aruco_params = cv2.aruco.DetectorParameters()


    fourcc = cv2.VideoWriter.fourcc(*'mp4v')
    output_width = int(video_capture.get(cv2.CAP_PROP_FRAME_WIDTH))
    output_height = int(video_capture.get(cv2.CAP_PROP_FRAME_HEIGHT))
    output_video = cv2.VideoWriter(output_video_path, fourcc, 20.0, (output_width, output_height))

    all_tvecs = []
    all_rvecs = []

    while True:
        ret, frame = video_capture.read()
        print(ret)

        if not ret:
            false_count += 1
            if false_count >= 2:
                break  # If 'ret' is False twice consecutively, exit the loop
            continue  # Skip to the next frame

        # Reset false_count if 'ret' is True
        false_count = 0

        h, w, _ = frame.shape
        width = 1000
        height = int(width * (h / w))
        frame = cv2.resize(frame, (width, height), interpolation=cv2.INTER_CUBIC)
        gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

        corners, ids, rejected = cv2.aruco.detectMarkers(gray, aruco_dict)
        detected_markers = aruco_display(corners, ids, rejected, frame)

        markerPoints = np.array([[0, 0, 0],
                                 [marker_size, 0, 0],
                                 [marker_size, marker_size, 0],
                                 [0, marker_size, 0]], dtype=np.float32)

        if np.all(ids is not None):
            for i in range(0, len(ids)):
                trash, rvec, tvec = cv2.solvePnP(markerPoints, corners[i], camera_matrix,
                                                 distortion_coefficients, False, cv2.SOLVEPNP_IPPE_SQUARE)


                all_tvecs.append(tvec)
                all_rvecs.append(rvec)

                cv2.aruco.drawDetectedMarkers(frame, corners)
                cv2.drawFrameAxes(frame, camera_matrix, distortion_coefficients, np.array(rvec), np.array(tvec), 0.1)

        cv2.imshow("Image", detected_markers)

        key = cv2.waitKey(1) & 0xFF
        if key == ord("q"):
            break

    cv2.destroyAllWindows()
    video_capture.release()
    output_video.release()

    return all_tvecs

Thank you for any suggestions!

I did check the camera calibration process but couldt find any issues.

0

There are 0 answers