Комп'ютерне зір і мобільні роботи. Частина 1 — V-REP, Python, OpenCV



Коли прочитав публікацію про запуск безпілотних гоночних автомобілів — подумав, було б цікаво зробити щось подібне. Звичайно не гоночний болід, але принаймні мобільний робот, що орієнтується в просторі за допомогою камери — розпізнаванням образів.

У нашому хакспейсе — створити робота не така велика проблема. Але не у всіх і не завжди є можливість експериментувати з реальним «залізом» — тому цікаво було спробувати вирішити завдання — у віртуальному середовищі, і після вже оживити «залізо».

Так і виникла ідея серії статей, про рішення найпростішої задачі орієнтації робота в просторі — від віртуальної симуляції, до втілення в реальному мобільному роботі:

Частина 1. Налаштування віртуальної середовища, інтеграція з python і OpenCV для розпізнавання образів з віртуального світу.
Частина 2. Створення віртуального мобільного робота, алгоритм автономного переміщення (пошук об'єкта)
розділ 3. Створення реального робота, перенесення логіки на нього.

Хочеться домогтися такого результату — щоб python скрипт, керуючий віртуальним роботом — був би максимально ідентичним тому, що буде керувати реальним роботом.

Мозком робота буде мікрокомп'ютер RaspberryPi2 — на якому без проблем працює і python, і OpenCV. Таким чином необхідно зістикувати систему віртуальної робототехніки V-REP — з Python і OpenCV. Ось про це і буде перша частина — дана публікація.

Відео, що вийшло (пошук зеленого об'єкта)На верхньому вікні — пряме зображення з відео-камери в 3д віртуальному світі, на нижньому вікні — результат виконання python скрипта, що отримує зображення передає її OpenCV і малює маркер, навколо знайденого об'єкта.

Намалюємо архітектуру нашого мобільного робота.

Архітектура мобільного робота
Реальний робот, буде виглядає приблизно так (ще камеру додамо)


Архітектурно:


Як ми бачимо — «мозок» робота отримує зображення, що розпізнається за допомогою OpenCV) і передає керуючі команди на колеса. І замінивши зображення з камери на 3д зображення, а управління колесами — на управління віртуальними колесами 3д робота у віртуальному світі — ми отримаємо стенд для відпрацювання логіки.

Отримуємо таку архітектуру для віртуального стенду:


У нашої сьогоднішньої першої частини — нам необхідно вирішити задачу зв'язки V-REP з зовнішнім python скриптом, який виконує розпізнавання образів за допомогою OpenCV, і виводить маркер навколо знайденого об'єкта.

Виходить така архітектура:


Установка V-REP
Про безкоштовну систему робо-моделювання V-REP — було кілька російськомовних публікацій:
Тому встановлення і перші кроки — можна подивитися в них.

Сцена
Вважаємо, що V-REP встановлений і працює. Нам необхідно створити сцену.

На сцені буде камера, що переглядає область, на якій є різні 3д об'єкти, це зображення необхідно транслювати зовнішнього python скрипту, який повинен викликати OpenCV для розпізнавання і формування маркера, та повернення цього зображення назад в V-REP — для контролю.

На щастя серед прикладів який поставляються з V-REP був подібний приклад, правда він використовував ROS (для поточних завдань не потрібен):


На базі цього демо з'явилася наступна сцена:
  • рухливий штатив, що обертається
  • на штативі закріплена камера v0 (vision sensor)
  • розміщено v1 сенсор, дані на який передаються з зовнішньої системи
Сцену scene.ttt можна скачати звідси.

Python API
Вважаємо, що Python у вас встановлений (тестувалося на 2.7.6)

При запуску V-REP автоматично завантажується плагін забезпечує зв'язку Python API. Для роботи з API через python скрипт необхідна наявність трьох файлів:
  • remoteApi.so (або remoteApi.dll)
  • vrep.py
  • vrepConst.py
Їх можна скопіювати з V-REP каталогу (programming/remoteApiBindings/perl/python, programming/remoteApiBindings/lib/lib/). Після цього можна імпортувати модуль V-REP:
import vrep

Простий скрипт, що підключається до API, виглядає так:
import vrep

vrep.simxFinish(-1) # just in case, close all connections opened

clientID = vrep.simxStart('127.0.0.1', 19997, True, True, 5000, 5)

if clientID!=-1:
print 'Connected to remote server API'

while (vrep.simxGetConnectionId(clientID) != -1):
print "some work"
else:
print "Failed to connect to remote Server API"
vrep.simxFinish(clientID)


На нашій сцені є два об'єкти — v0 і v1 — це Visual Sensor — з першого ми зчитуємо картинку, на другий ми повинні записувати результат. Тому ми повинні отримати ці об'єкти в контексті нашого python скрипта, робиться це за допомогою API команди vrep.simxGetObjectHandle

res, v0 = vrep.simxGetObjectHandle(clientID, 'v0', vrep.simx_opmode_oneshot_wait)
res, v1 = vrep.simxGetObjectHandle(clientID, 'v1', vrep.simx_opmode_oneshot_wait)

Звертаємо увагу, що всі функції доступні через API — так само доступні через внутрішні скрипти (Lua), єдина відмінність, що в назві замість simx — sim, тобто в нашому випадку виклик функції на Lua буде «simGetObjectHandle».

Для отримання з Vision Sensor картинки і записи — є дві функції: vrep.simxGetVisionSensorImage і vrep.simxSetVisionSensorImage відповідно.

І в python коді це буде виглядати так (де v0 і v1 — відповідні об'єкти):
# одержання зображення з сенсора v0
err, resolution, image = vrep.simxGetVisionSensorImage(clientID, v0, 0, vrep.simx_opmode_buffer)
# запис зображення в сенсор v1
vrep.simxSetVisionSensorImage(clientID, v1, image, 0, vrep.simx_opmode_oneshot)

Єдино, для Vision Sensor що отримує дані із зовнішнього джерела, в параметрах треба виставити відповідний прапор:


Ретрансляція зображення
Таким чином зараз ми можемо зробити python скрипт, що через V-REP API бере зображення з відео-сенсора і ретранслює його:
simple_image_retranslate.py
# simple_image_retranslate.py

import vrep
import time

vrep.simxFinish(-1)

clientID = vrep.simxStart('127.0.0.1', 19997, True, True, 5000, 5)

if clientID!=-1:
print 'Connected to remote server API'

# get vision sensor objects
res, v0 = vrep.simxGetObjectHandle(clientID, 'v0', vrep.simx_opmode_oneshot_wait)
res, v1 = vrep.simxGetObjectHandle(clientID, 'v1', vrep.simx_opmode_oneshot_wait)


err, resolution, image = vrep.simxGetVisionSensorImage(clientID, v0, 0, vrep.simx_opmode_streaming)
time.sleep(1)

while (vrep.simxGetConnectionId(clientID) != -1):
err, resolution, image = vrep.simxGetVisionSensorImage(clientID, v0, 0, vrep.simx_opmode_buffer)
якщо err == vrep.simx_return_ok:
vrep.simxSetVisionSensorImage(clientID, v1, image, 0, vrep.simx_opmode_oneshot)
elif err == vrep.simx_return_novalue_flag:
print "no image yet"
else:
print err
else:
print "Failed to connect to remote Server API"
vrep.simxFinish(clientID)

Для перевірки ми повинні стартувати сцену (кнопка «Play» вгору), і після цього в командному рядку запустити файл simple_image_retranslate.py

І ось результат (v1 — відображає зображення з python скрипта):


Ок, базова заготівля є, тепер необхідно підключити розпізнавання образів (комп'ютерне зір)

Комп'ютерне зір, OpenCV
Думаю всі чули про відкриту систему комп'ютерного зору, OpenCV, яку розробив
Gary Bradski
Gary Bradski відвідав стенд нашого хакспейса на иннопроме 2014
По перше OpenCV треба встановити, установка opencv2 на Linux Mint (Ubuntu) виглядала досить просто:
sudo apt-get install libopencv-dev python-opencv


Після цього з'явилася можливість підключати бібліотеку python коді:
import cv2

Тепер необхідно реалізувати найпростішу функцію розпізнавання. В якості бази був узяти приклад, пошуку зеленого м'яча на картинці.

З'явилася функція def track_green_object(image), що повертає координати зеленого об'єкта, якщо знайдений.

І так само треба відзначити маркером навколо знайденого об'єкта, для цього ми скористаємося базової OpenCV функцією для малювання прямокутника: cv2.rectangle.

І наш фрагмент коду, що:
  1. отримує зображення (v0)
  2. знаходить об'єкт (щось зелене)
  3. додає маркер жовтий прямокутник)
  4. повертає зображення (v1)
виглядає так:
# get image from vision sensor 'v0'
err, resolution, image = vrep.simxGetVisionSensorImage(clientID, v0, 0, vrep.simx_opmode_buffer)
якщо err == vrep.simx_return_ok:
image_byte_array = array.array('b', image)
image_buffer = I. frombuffer("RGB", (resolution[0],resolution[1]), image_byte_array, "raw", "RGB", 0, 1)
img2 = numpy.asarray(image_buffer)

# try to find something green
ret = track_green_object(img2)

# overlay rectangle marker if something is found by OpenCV
if ret:
cv2.rectangle(img2,(ret[0]-15,ret[1]-15), (ret[0]+15,ret[1]+15), (0xff,0xf4,0x0d), 1)

# return image sensor to 'v1'
img2 = img2.ravel()
vrep.simxSetVisionSensorImage(clientID, v1, img2, 0, vrep.simx_opmode_oneshot)


Результат

Тепер залишилося запустити всі разом: стартуємо сцену, запускаємо скрипт і дивимося, що відбувається:


Вихідний код проекту можна знайти на github.

У наступній частині ми будемо створювати робота в V-REP, і програмувати його для пошуку зеленого м'яча.

Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.