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:
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