0

I'm trying to calibrate my camera with OpenCV, but it keeps returning this error:

error: OpenCV(4.5.5) D:\a\opencv-python\opencv-python\opencv_contrib\modules\aruco\src\aruco.cpp:1769: error: (-215:Assertion failed) nMarkersInThisFrame > 0 in function 'cv::aruco::calibrateCameraAruco'

This is the code for it, every part of it works besides the part under "#Actual Calibration"

def calibrate_aruco(num_markers_row, num_markers_column, side_length, marker_separation, marker_separation_x):
    """Calibrates Camera Using ArUco Tags"""
    
    aruco_dict = aruco.Dictionary_get(aruco.DICT_5X5_250)
    arucoParams = aruco.DetectorParameters_create()
    
    tag_corners = []
    sep_array_y = [0, marker_separation + side_length, marker_separation + side_length, 0]
    sep_array_x = [0, 0, marker_separation_x + side_length, marker_separation_x + side_length]
    for i in range(num_markers_column*num_markers_row):
        top_left = np.array([sep_array_x[i], side_length + sep_array_y[i], 0], dtype = np.float32)
        top_right = np.array([side_length + sep_array_x[i], side_length + sep_array_y[i], 0], dtype = np.float32)
        bottom_right = np.array([side_length + sep_array_x[i], sep_array_y[i], 0], dtype = np.float32)
        bottom_left = np.array([sep_array_x[i], sep_array_y[i], 0], dtype = np.float32)
        tag_corners.append(np.array([top_left, top_right, bottom_right, bottom_left]))
    
    board_ids = np.array( [[0],[1],[2],[3]], dtype=np.int32)
    
    board = aruco.Board_create(tag_corners, aruco_dict, board_ids)

    # Find the ArUco markers inside target image
    image = cv2.imread(r"D:\Downloads\target_1.png")
    img_gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    
    #cv2.imshow("obama", img_gray)
    cv2.waitKey(0)
    cv2.destroyAllWindows()
    
    corners, ids, rejected = aruco.detectMarkers(
        img_gray, 
        aruco_dict, 
        parameters=arucoParams
    )
    
    # Actual calibration
    ret, mtx, dist, rvecs, tvecs = aruco.calibrateCameraAruco(
        corners, 
        ids, 
        num_markers_row*num_markers_column, 
        board, 
        img_gray.shape, 
        None,
        None
    )
    return ret, mtx, dist, rvecs, tvecs

I prefaced this method with the following inputs:

import cv2
import cv2.aruco as aruco
import numpy as np

num_markers_row = 2 #number of rows
num_markers_column = 2 #numbers of columns

side_length = 5 #side length of ar tags in cm

dist_to_circle = 3.75 #distance between the y coordinate of ar tag and the y coordinate of circle
dist_between_centers = 2 * dist_to_circle
marker_separation = dist_between_centers - side_length

dist_to_circle_x = 10
dist_between_centers_x = 2 * dist_to_circle_x
marker_separation_x = dist_between_centers_x - side_length

print(marker_separation)
print(marker_separation_x)

I got most of the code from here; the only part I edited was changing the ArUco tags from following a GridBoard format to following a general board format. I also changed the program to feed the CalibrateCameraAruco function a single frame instead of multiple. The image I'm using to calibrate is the following:enter image description here

Hudson Liu
  • 49
  • 9

1 Answers1

1

I managed to fix this issue by feeding the calibrateCameraAruco function multiple frames instead of a single image. The full code is below:

# -*- coding: utf-8 -*-
"""
Created on Sat Apr 16 12:26:08 2022

ArUco OpenCV Calibration
Only needs to be ran once
Run calibration only after Astrobee is at Target 1

@author: hudso
"""
import cv2
import cv2.aruco as aruco
import numpy as np
import glob
import os

def create_ArUco_board_format():
    """Defines constants and the general format of the ArUco Tags"""
    
    #These are the only changable variables
    num_markers_row = 2 #number of rows
    num_markers_column = 2 #numbers of columns
    side_length = 5 #side length of ar tags in cm
    
    #Calculates the marker separation as if in a grid
    dist_to_circle = 3.75
    dist_between_centers = 2 * dist_to_circle
    marker_separation = dist_between_centers - side_length
    
    dist_to_circle_x = 10
    dist_between_centers_x = 2 * dist_to_circle_x
    marker_separation_x = dist_between_centers_x - side_length
    
    #Downloads ArUco 5x5 250 Tag Dictionary
    aruco_dict = aruco.Dictionary_get(aruco.DICT_5X5_250)
    
    #Creates custom ArUco Board type object "board"
    tag_corners = []
    sep_array_y = [0, marker_separation + side_length, marker_separation + side_length, 0]
    sep_array_x = [0, 0, marker_separation_x + side_length, marker_separation_x + side_length]
    for i in range(num_markers_column*num_markers_row):
        top_left = np.array([sep_array_x[i], side_length + sep_array_y[i], 0], dtype = np.float32)
        top_right = np.array([side_length + sep_array_x[i], side_length + sep_array_y[i], 0], dtype = np.float32)
        bottom_right = np.array([side_length + sep_array_x[i], sep_array_y[i], 0], dtype = np.float32)
        bottom_left = np.array([sep_array_x[i], sep_array_y[i], 0], dtype = np.float32)
        tag_corners.append(np.array([top_left, top_right, bottom_right, bottom_left]))
    
    #Assigns the respective "board_ids" of the ArUco tags
    board_ids = np.array([[0],[1],[2],[3]], dtype=np.int32)
    
    #Creates board
    board = aruco.Board_create(tag_corners, aruco_dict, board_ids)
    
    return board, aruco_dict
    
def calibrate_aruco(board, aruco_dict):
    """Calibrates Camera Using ArUco Tags"""
    
    #Search through directory of Calibration Images
    cwd = os.getcwd()
    path = r"\Calibration_Images"
    os.chdir(cwd + path)
    files = glob.glob('*.{}'.format("jpg"))
    
    arucoParams = aruco.DetectorParameters_create()
    
    #Iterate over each calibration image and find markers
    all_corners = np.array([])
    all_ids = np.array([])
    num_detected_markers = []
    for file in files:
        #Open File
        image = cv2.imread(file)
        img_gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
        cv2.imshow("obama", img_gray)
        cv2.waitKey(0)
        cv2.destroyAllWindows()
        
        #Detect markers
        corners, ids, rejected = aruco.detectMarkers(
            img_gray, 
            aruco_dict, 
            parameters=arucoParams
        )
        
        #Append marker data
        if np.size(all_corners) == 0:
            all_corners = corners
            all_ids = ids
        else:
            all_corners = np.append(all_corners, corners, axis=0)
            all_ids = np.append(all_ids, ids, axis=0)
        num_detected_markers.append(len(ids))
        
    num_detected_markers = np.array(num_detected_markers)

    #Uses markers to calibrate camera
    ret, mtx, dist, rvecs, tvecs = aruco.calibrateCameraAruco(
        all_corners, 
        all_ids, 
        num_detected_markers, 
        board, 
        img_gray.shape, 
        None, 
        None 
    )
    return ret, mtx, dist, rvecs, tvecs

#The actual execution of the methods
board, aruco_dict = create_ArUco_board_format()
ret, mtx, dist, rvecs, tvecs = calibrate_aruco(board, aruco_dict)
print(mtx) #Camera Matrix
print(dist) #Distortion Coefficients
Hudson Liu
  • 49
  • 9