[Перевод] Машинное стереозрение для новичков: две камеры Raspberry Pi и Python

Стажируясь в правительственном технологическом агентстве Сингапура, автор работал над экспериментом по созданию альтернативы камере Intel Relsence. Оказалось, что учебных материалов на тему машинного зрения мало, поэтому он решил помочь новичкам. К старту флагманского курса по Data Science приглашаем под кат за подробностями.


Вы когда-нибудь задумывались, как на самом деле видят мир Терминаторы? Как узнаю́т о приближении врага? Ответ — в двух демонических глазах на картинке выше. Глаза терминатора способны смотреть в одном направлении, что даёт ему бинокулярное зрение. На самом деле эти научно-фантастические роботы, включая их глаза, основаны на человеческом теле почти полностью.

Каждый глаз фиксирует отдельные двухмерные изображения, а магия восприятия глубины на самом деле происходит в мозге, который экстраполирует сходства и различия двух изображений.

Простой стеноп основан на физике человеческого глаза и, подобно глазу, из-за перспективной проекции теряет информацию о глубине. Но как же мы будем измерять глубину с помощью камер? Мы используем две камеры.

Почему это важно?

До погружения в ответ на вопрос «как», давайте разберёмся с вопросом «почему». Представьте, что вам нужен робот — уборщик мусора, но вы не хотите вкладываться в тяжёлую технологию лидаров, чтобы определять, насколько далеко расположена корзина. Здесь и вступает в игру стереоскопическое зрение.

Использование двух обычных стенопов не только для определения глубины, но и для задач машинного обучения, таких как обнаружение объектов, может сэкономить значительные средства. Более того, эта технология может достигать результатов, похожих на результаты других технологий, если не лучших результатов.

Даже такая организация, как Tesla, сказала нет использованию лидаров в своих автономных автомобилях и полагается на концепцию объёмного зрения радаров. Посмотрите это видео от Tesla:

Очевидно, вместо 2 камер Тесла используют 8, также как другие сенсоры, например радары.

Погружение в стереозрение — отличный способ начать работу с компьютерным зрением и проектами, которые связаны с изображениями, поэтому продолжим, чтобы узнать об объёмном зрении больше.

Основы многоракурсной геометрии

Эпиполярная геометрия:

OpenCV
OpenCV

Рассмотрим две камеры с отверстиями — О и О′. Каждая из них видит только двухмерную плоскость. Если сфокусироваться на камере O, то x проецируется только в одну точку на плоскости изображения. Однако на изображении от O′ видно, как различные точки X соответствуют точкам X′.

В этих обстоятельствах через выравнивание слева направо возможно триангулировать корректные точки данных в трёхмерном пространстве — и ощутить глубину. Чтобы изучить полярную геометрию глубже, ознакомьтесь с этой статьёй из Университета Торонто.

Что приведёт нас к объёмному зрению?

Добиться объёмного зрения можно в 4 этапа.

1. Коррекция искажений. Она подразумевает удаление радиальных и тангенциальных искажений, возникающих в изображениях из-за объективов камер.

2. Ректификация двух камер — это трансформация для проекции изображений на общую плоскость.

Rodriguez Florez, Sergio. (2010). Contributions by Vision Systems to Multi-sensor Object Localization and Tracking for Intelligent Vehicles.
Rodriguez Florez, Sergio. (2010). Contributions by Vision Systems to Multi-sensor Object Localization and Tracking for Intelligent Vehicles.

3. Сопоставление точек, где мы находим соответствующие друг другу точки камер, выпрямляя левое и правое изображения. Обычно для выпрямления используется изображение шахматной доски.

Сопоставление точек
Сопоставление точек

4. Создание карты глубины.

Можно ли сделать такой проект самостоятельно?

Определённо да. Чтобы начать проект, потребуется всего несколько вещей.

  1. Jetson Nano Developer Kit B01 (с двумя слотами камер CSI).

  2. Две камеры Raspberry Pi.

  3. Интерес!

Я понял, что учебных материалов по теме не так много, поэтому написал серию статей, чтобы поделиться с такими же, как я, новичками и энтузиастами, помочь им ускорить обучение и реализацию проектов. Чтобы начать разработку собственной машины отображение глубины, просто читайте дальше.

Этот проект — хороший способ для новичков шагнуть не только в область компьютерного зрения, но и в компьютерные науки в целом, приобретая навыки работы с Python и OpenCV.


Карта глубины

Результат
Результат

Теперь, когда мы понимаем концепцию объёмного зрения, приступим к созданию карты глубины.

Запустим камеру

Все используемые в этом уроке скрипты написаны на Python. Чтобы начать, клонируйте репозиторий StereoVision.

Требования

Если у вас нет Jetson Nano, пожалуйста, посетите этот сайт. Предполагая, что Jetson Nano у вас уже установлена, установим зависимости Python 3.6:

sudo apt-get install python3-pip

Пакет разработки Python 3.6:

sudo apt-get install libpython3-dev

И зависимости:

pip3 install -r requirements.txt

Если вы хотите установить зависимости вручную, выполните этот код:

pip3 install cython # Install cython
pip3 install numpy # Install numpy
pip3 install StereoVision # Install StereoVision library

Если во время работы над проектом вы столкнулись с какими-то ошибками, пожалуйста, обратитесь к этому разделу моего репозитория.

Тестируем камеры

Прежде чем создавать корпус или подставку для стереокамеры, проверим, подключаются ли камеры. Подключить две камеры Raspberry Pi и проверить, запускаются ли они, можно этой командой:

# sensor_id selects the camera: 0 or 1 on Jetson Nano B01
$ gst-launch-1.0 nvarguscamerasrc sensor_id=0 ! nvoverlaysink

Попробуйте её с sensor_id=0, чтобы проверить, работают ли обе камеры.

Если вы столкнулись с ошибкой GStreamer вроде этой:

то введите в терминале команду ниже и попробуйте снова.

sudo service nvargus-daemon restart

Иногда при завершении работы программы пайплайн GStreamer не закрывается должным образом. Поэтому команда очень полезна, её следует запомнить. Если проблема постоянная, убедитесь, что камера подключена правильно, и перезапустите Jetson Nano.

Розовый оттенок

Если вы видите розовый оттенок, чтобы убрать его, пожалуйста, следуйте рекомендациям из этой статьи.

Подготовка железа

До того как продолжить, у вас должна быть стабильная стереокамера с двумя объективами Raspberry Pi, расположенными на фиксированном расстоянии друг от друга, — это базовая линия. Важно, чтобы она всегда оставалась неподвижной.

Моя оптимальная базовая линия — 5 см, но вы можете попробовать разные расстояния разделения и оставить комментарий о результатах. Есть много способов сделать это, включите воображение!

Мой корпус до и после
Мой корпус до и после

Сначала я воспользовался BluTac, чтобы приклеить камеры к старому iPhone и коробке Jetson Nano. И решил использовать onShape, чтобы спроектировать простую 3D-модель в CAD, лазерным резаком вырезал детали из акрила — и получился корпус вроде вольера, который вы видите справа.

Если вам интересно, вы можете посмотреть мой дизайн. А если хотите разработать собственную модель, то можете загрузить основу модели 3D STEP здесь.

Запускаем камеры

Убедившись, что камеры подключены правильно, запустим их. В терминале перейдите в каталог /StereoVision/main_scripts/, запустите команду python3 start_cameras.py. Вы должны увидеть прямую трансляцию с двух камер слева и справа. Если при запуске камеры возникли ошибки, посетите эту страницу.

Подготовка шахматной доски

Доска. Источник: OpenCV
Доска. Источник: OpenCV

Распечатайте изображение. Убедитесь, что оно не вписывается в страницу и не изменяет масштаб и наклейте его на твёрдую поверхность. Самый простой способ — использовать изображение шахматной доски. Но, если хотите использовать свою доску, измените скрипт 3_calibration.py в строках 16 и 19. Получим 30 изображений с интервалами в 5 секунд.

Вот что ещё я предлагаю

  • не стойте слишком далеко. Убедитесь, что доска занимает бо́льшую часть кадра камеры;

  • покрыты все углы кадра;

  • обязательно перемещайте и поворачивайте доску между снимками, чтобы получить фотографии с разных ракурсов.

Понемногу перемещайте доску между изображениями и следите за тем, чтобы не обрезать часть: изображения с обеих камер будут сшиты и сохранены как один файл. Чтобы сделать снимки, выполните этот код:

python3 1_taking_pictures.py

Если при запуске камер вы столкнулись с ошибкой Failed to load module "canberra-gtk-module", попробуйте выполнить эту команду:

sudo apt-get install libcanberra-gtk-module

Если захочется увеличить временно́й промежуток или общее количество снимков, измените скрипт 1_taking_pictures.py. Настройки фотосъёмки вы найдёте в самом верху файла. Измените его:

#These are the first few lines from 1_take_pictures.py
import cv2
import numpy as np
from start_cameras import Start_Cameras
from datetime import datetime
import time
import os
from os import path #Photo Taking presets
total_photos = 30 # Number of images to take
countdown = 5 # Interval for count-down timer, seconds
font = cv2.FONT_HERSHEY_SIMPLEX # Cowntdown timer font

А если захочется остановить любую программу из этой серии статей, нажмите клавишу Q. Вы получите папку images со всеми сохранёнными изображениями.

Работа с изображениями

Для гарантии, что изображения калибровки качественные, будем просматривать каждую сделанную фотографию и принимать или отклонять её. Для этого запустим команду python3 2_image_selection.py.

Пробегитесь по всем изображениям: Y — принять изображение, N — отклонить его. Изображения от левой и правой камер сохраним отдельно, в папке pairs.

Калибровка

Это самый важный шаг всей серии статей. Чтобы получить карту неравенства, нужно выпрямить и откалибровать камеры. Подробнее о ректификации камеры.

Благодаря библиотеке для стереозрения Дэниэла Ли нам не нужно много работать в плане кода. Чтобы выполнить калибровку, пройдём по всем сохранённым на предыдущем шаге изображениям шахматной доски и рассчитаем матрицы коррекции. Программа сопоставит точки и попытается найти края шахматной доски точка. Если вам кажется, что результаты неточны, попробуйте сделать повторные снимки.

Процесс сопоставления точек
Процесс сопоставления точек

Чтобы выполнить калибровку, запустим команду python3 calibration.py.

rectified_left.png
rectified_left.png
rectified_right.png
rectified_right.png

Если результаты калибровки выглядят немного странно, как показано выше, вы можете попробовать повторить шаги 1–3. Ваши ректификационные изображения никогда не будут выглядеть идеально, поэтому не бойтесь результатов и переходите к следующему шагу. Вы всегда сможете вернуться.

Настройка карты глубины

Настройка графического интерфейса
Настройка графического интерфейса

Теперь, когда камера готова работать, начнём настройку карты глубины. Выполните скрипт 4_tuning_depthmap.py. Чтобы разобраться с переменными этого скрипта, посмотрите README в репозитории.

Диапазоны настроек могут немного отличаться от указанных в пояснениях: из-за ограничений в трекбарах мне пришлось изменить отображаемые в графическом интерфейсе параметры. В окне настройки вы увидите ректифицированные левое и правое изображения в градациях серого.

Карта глубины

Вот и всё. Можно запустить скрипт 5_depthmap.py: python3 5_depthmap.py. Вот она, полнофункциональная карта глубины, которую мы создали c нуля.

Расстояния до объектов

Карта глубины, которую вы видите выше, — это двухмерная матрица. Почему бы не получить из неё информацию о глубине? Чтобы узнать расстояние до конкретного объекта в кадре, щёлкните по этому объекту — и вы увидите относительное расстояние до терминала в сантиметрах. Оно определяет, насколько пиксель удалён от камеры.

Что это значит?

Нужно понимать одну вещь: измеряемое расстояние — это не точное расстояние от центра системы камер, а расстояние от системы камер по оси Z.

Значит, измеряемое расстояние на самом деле равно расстоянию Y, а не X.

Другие туториалы

  1. StereoPi — создание карты глубины.

  2. JetsonHacks и камеры Raspberry Pi.

Продолжить изучение машинного зрения и Python с самого начала или прокачать ваши навыки вы сможете на наших курсах:

Выбрать другую востребованную профессию.

Краткий каталог курсов и профессий

Data Science и Machine Learning

Python, веб-разработка

Мобильная разработка

Java и C#

От основ — в глубину

А также

Читайте так же: