[Из песочницы] Калибровка камеры Intel RealSense d435 с помощью OpenCV2 и ROS

Всем привет!

Хочу поделиться опытом работы с камерой Intel RealSense, модель d435. Как известно, многие алгоритмы машинного зрения требуют предварительной калибровки камеры. Так уж получилось, что мы на нашем проекте используем ROS для сборки отдельных компонентов автоматизированной интеллигентной системы. Однако, проштудировав русскоязычный интернет, я не обнаружил каких-либо толковых туториалов на эту тему. Данная публикация призвана восполнить этот пробел.

Так как ROS работает на Unix системах, я буду исходить из того, что у нас доступна система Ubuntu 16.04. Я не буду описывать детальные подробности установки, лишь дам ссылки на соответствующие туториалы.

sudo apt-get install python-opencv


  1. Прежде всего, необходимо установить драйверы для камеры.
  2. ROS-пакет для камеры находится тут. На момент публикации последняя версия была 2.0.3. Чтобы установить пакет, необходимо скачать исходный код и распаковать его в домашней директории ROS. Далее, нам необходимо будет установить его:
catkin_make clean
catkin_make -DCATKIN_ENABLE_TESTING=False -DCMAKE_BUILD_TYPE=Release
catkin_make install
echo "source path_to_workspace/devel/setup.bash" >> ~/.bashrc
source ~/.bashrc

После того как мы установили камеру, нам необходимо убедиться что драйвера работают как надо. Для этого мы подключаем камеру через USB и запускаем демку:

roslaunch realsense2_camera demo_pointcloud.launch

Данная команда откроет ROS визуализацию, на которой можно будет увидеть облако точек, зарегистрированные в топике /camera/depth/color/points:

rviz

Ниже представлена адаптированная версия туториала от OpenCV.

import numpy as np
import cv2
import glob

# критерий остановки калибровки
criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001)

# мы используем шахматную доску 8x6
objp = np.zeros((6*8,3), np.float32)
objp[:,:2] = np.mgrid[0:8,0:6].T.reshape(-1,2)

# массивы для хранения объектов и точек всех изображений
objpoints = [] # 3d объекты из реального мира
imgpoints = [] # 2d точки на плоскости изображения

images = glob.glob('/путь_к_изображениям/*.png')

for fname in images:
img = cv2.imread(fname)
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)

# ищем углы шахматной доски
ret, corners = cv2.findChessboardCorners(gray, (8,6),None)

# как только точки найдены, мы добавляем обновляем массивы с объектами и точками
if ret == True:
objpoints.append(objp)
corners2 = cv2.cornerSubPix(gray,corners,(11,11),(-1,-1),criteria)
imgpoints.append(corners2)

# рисуем точки и показываем финальное изображение
img = cv2.drawChessboardCorners(img, (8,6), corners2,ret)
cv2.imshow('img',img)
cv2.waitKey(500)

cv2.destroyAllWindows()

# калибрируем и сохраняем результаты
ret, mtx, dist, rvecs, tvecs = cv2.calibrateCamera(objpoints, imgpoints, gray.shape[::-1],None,None)
np.save('/path_to_images/calibration', [mtx, dist, rvecs, tvecs])

Для того, чтобы данный скрипт заработал, нам необходимы как минимум 10 изображений шахматной доски, полученные с нашей камеры. Для этого мы можем использовать, к примеру, ROS-пакет image_view или любую другую программу, способную делать скриншоты с USB камеры. Снятые изображения следует поместить в любую папку. Пример изображения:

Chess table

После того, как мы исполним скрипт, результаты калибрования будут сохранены в файл
calibration.npy. Эти данные затем можно использовать следующим скриптом:

calibration_data = np.load('path_to_images/calibration.npy')
mtx = calibration_data[0]
dist = calibration_data[1]
rvecs = calibration_data[2]
tvecs = calibration_data[3]

Мы смогли успешно откалибрировать камеру RealSense d435 с помощью OpenCV2 и ROS. Результаты калибровки можно использовать в таких приложениях, как трекинг объектов, маркеров aruco, алгоритмов дополненной реальности и многих других. В следующей статье, я хотел бы поподробнее остановиться на трекинге маркеров aruco.

© Habrahabr.ru