Вопрос или проблема
Я пытаюсь выполнить калибровку камеры с использованием OpenCV, версии 4.10.0.
У меня уже есть рабочая версия для обычной шахматной доски, но я не могу понять, как это работает с charuco. Я был бы благодарен за любой рабочий пример кода.
С наилучшими пожеланиями
Мариус
Что я пробовал: Я следовал этому учебнику: https://medium.com/@ed.twomey1/using-charuco-boards-in-opencv-237d8bc9e40d
Похоже, что отсутствуют важные функции, такие как: cv.aruco.interpolateCornersCharuco
и cv.aruco.interpolateCornersCharuco
. Даже в документации указана существующая реализация на Python, см.: https://docs.opencv.org/4.10.0/d9/d6a/group__aruco.html#gadcc5dc30c9ad33dcf839e84e8638dcd1
Я также пробовал следовать официальной документации для C++, см. https://docs.opencv.org/4.10.0/da/d13/tutorial_aruco_calibration.html
У ArucoDetector в Python нет метода detectBoard
. Поэтому невозможно полностью следовать этому учебнику.
Но я предполагаю, что по намеку в документации функции, использованные в Medium, устарели? Но нигде не отмечены как «удаленные»!
Я уже получил обнаруженные маркеры:
Но затем получить объект и точки изображения не удается:
`object_points_t, image_points_t = charuco_board.matchImagePoints( marker_corners, marker_ids)`
Любая помощь или рабочий код будут весьма оценены.
P.S.: Мой вывод метода “detectMarkers” кажется действительным. Обнаруженные углы имеют тип
std::vector<std::vector<Point2f>.
(Таким образом, переведено на Python как массив массивов, содержащий 4 точки с 2 координатами каждая.) ID — это
std::vector<int>
так что в Python это список целых чисел.
Так что я полагаю, что функция python “matchImagePoints” получает то, что ей нужно!
Обнаружение маркеров, похоже, успешно. Я уже пробовал изменить массив углов: метод detectMarkers возвращает кортеж. Я использовал следующий код, чтобы создать желаемый массив формы (X, 4, 2). (X — это количество обнаруженных маркеров. Каждый имеет 4 угла с 2 координатами x и y.)
marker_corners = np.array(marker_corners)
marker_corners = np.squeeze(marker_corners)
Таким образом, у меня есть следующее:
marker_corners = [
[[8812. 5445.]
[8830. 5923.]
[8344. 5932.]
[8324. 5452.]],
[[7172. 5469.]
[7184. 5947.]
[6695. 5949.]
[6687. 5476.]],
[[3896. 5481.]
[3885. 5952.]
[3396. 5951.]
[3406. 5483.]],
...
]
marker_ids = [
[11],
[27],
[19],
...
]
Оба варианта, передача оригинального результата, который я получаю от
detector.detectMarkers
в функцию и передача моего измененного массива, терпят неудачу. (Также не использование squeeze и ввод массива (X, 1, 4, 2) не удается!)
Я больше не могу продвинуться.
Минимальный рабочий пример:
import cv2 as cv
import numpy as np
image = cv.imread("charuco_board.png")
im_gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)
charuco_marker_dictionary = cv.aruco.getPredefinedDictionary(cv.aruco.DICT_6X6_250)
charuco_board = cv.aruco.CharucoBoard(
size=(11, 8),
squareLength=500,
markerLength=300,
dictionary=charuco_marker_dictionary
)
params = cv.aruco.DetectorParameters()
detector = cv.aruco.ArucoDetector(charuco_marker_dictionary, params)
marker_corners, marker_ids, rejected_candidates = detector.detectMarkers(im_gray)
marker_corners = np.array(marker_corners)
marker_corners = np.squeeze(marker_corners)
print(marker_corners, marker_ids)
try:
object_points_t, image_points_t = charuco_board.matchImagePoints(
marker_corners,
marker_ids
)
except cv.error as err:
print(err)
Ответ или решение
Для калибровки камеры с использованием Charuco-доски в OpenCV 4.10.0 необходимо учесть несколько ключевых аспектов. Давайте разберемся, как правильно выполнить эту задачу, используя корректный подход и примеры кода.
Подготовка
Перед началом убедитесь, что у вас установлена библиотека OpenCV версии 4.10.0 с поддержкой ArUco. Это можно сделать с помощью следующей команды pip:
pip install opencv-python==4.10.0 opencv-contrib-python==4.10.0
Пример кода для калибровки камеры с использованием Charuco-доски
Ниже представлен пример кода, который демонстрирует процесс калибровки камеры с использованием Charuco-доски:
import cv2 as cv
import numpy as np
# Определение параметров Charuco-доски
squares_x = 11 # количество квадратов по горизонтали
squares_y = 8 # количество квадратов по вертикали
square_length = 0.04 # длина стороны квадрата в метрах
marker_length = 0.03 # длина стороны маркера в метрах
charuco_dict = cv.aruco.getPredefinedDictionary(cv.aruco.DICT_6X6_250)
charuco_board = cv.aruco.Charucoboard_create(squares_x, squares_y, square_length, marker_length, charuco_dict)
# Параметры детектора
detector_params = cv.aruco.DetectorParameters_create()
# Списки для хранения точек
all_object_points = []
all_image_points = []
# Загрузка изображений с Charuco-доской для калибровки
image_files = ['path_to_image1.jpg', 'path_to_image2.jpg'] # здесь укажите ваши изображения
for file in image_files:
image = cv.imread(file)
gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)
# Детектирование маркеров
marker_corners, marker_ids, rejected_candidates = cv.aruco.detectMarkers(gray, charuco_dict, parameters=detector_params)
if marker_ids is not None:
# Интерполяция углов Charuco
retval, charuco_corners, charuco_ids = cv.aruco.interpolateCornersCharuco(marker_corners, marker_ids, gray, charuco_board)
if retval > 0:
# Добавление объектных и изображенческих точек
all_object_points.append(charuco_board.chessboardCorners)
all_image_points.append(charuco_corners)
# Калибровка камеры
ret, camera_matrix, dist_coeffs, rvecs, tvecs = cv.calibrateCamera(all_object_points, all_image_points, gray.shape[::-1], None, None)
# Сохранение матрицы камеры и коэффициентов искажения
np.savez("camera_calibration.npz", ret=ret, camera_matrix=camera_matrix, dist_coeffs=dist_coeffs)
print("Калибровка завершена!")
print("Матрица камеры:\n", camera_matrix)
print("Коэффициенты искажения:\n", dist_coeffs)
Объяснение кода
- Импорт библиотек: Импортируются необходимые библиотеки, включая OpenCV и NumPy.
- Создание Charuco-доски: Устанавливаются параметры Charuco-доски, такие как количество маркеров, размеры и длины сторон.
- Параметры детектора: Устанавливаются параметры для детектирования маркеров.
- Обработка изображений: Загружаются изображения с Charuco-доской. Для каждого изображения:
- Изображение конвертируется в градации серого.
- Детектируются маркеры.
- Интерполируются углы Charuco из обнаруженных маркеров.
- Если найдены углы, они добавляются в списки изображенческих и объектных точек.
- Калибровка камеры: Вызов функции
calibrateCamera()
для получения матрицы камеры и коэффициентов искажения. - Сохранение результатов: Результаты калибровки сохраняются в файл для дальнейшего использования.
Примечания
- Убедитесь, что изображения содержат достаточно маркеров, чтобы успешно интерполировать углы Charuco.
- Возможно, вам потребуется настроить параметр
marker_length
в зависимости от ваших изображений. - Проверяйте, что изображения, использованные для калибровки, имеют хорошее освещение и четкие маркеры.
В случае возникновения вопросов или необходимости в разъяснениях, пожалуйста, не стесняйтесь спрашивать. Удачи в ваших начинаниях!