ComputerVision (Ruby & OpenCV)


Автор: Людмила Дежкина, Senior Full Stack developer

OpenCV — відома бібліотека комп'ютерного зору широкого призначення з відкритим вихідним кодом. Я розповім, що можна робити за допомогою OpenCV, як працює бібліотека, як її використовувати на Ruby. Я встигла взяти участь у двох проектах, де вона застосовувалася. В обох випадках ми використовували в кінцевому варіанті не Ruby, але саме Ruby дуже зручний на першому етапі, коли потрібно створити прототип майбутньої системи, щоб просто подивитися, як OpenCV буде виконувати необхідні завдання. Якщо все в порядку, після цього додаток пишеться з цим же алгоритмом на іншій мові. А щоб використовувати OpenCV саме на Ruby, є відповідний гем.

Основні частини бібліотеки — інтерпретація зображень та алгоритми машинного навчання. Список можливостей, що надаються OpenCV, досить великий:

  • інтерпретація зображень;
  • калібрування камери по еталону;
  • усунення оптичних спотворень;
  • визначення подібності;
  • аналіз переміщення об'єкта;
  • визначення форми об'єкта і стеження за об'єктом;
  • 3D-реконструкція;
  • сегментація об'єкта;
  • розпізнавання жестів.


Зараз OpenCV використовується у багатьох сферах. Ось кілька цікавих прикладів:

  1. Google
    1. Google self-driving car — в безпілотних автомобілях Google OpenCV використовується для розробки прототипу розпізнавання навколишнього оточення;
      (сьогодні побудована система ґрунтується переважно на LIDAR — у зв'язку з труднощами розпізнавання при поганому освітленні)
    2. Google Glass — в цих окулярах 3D-реконструкція зображення побудована на OpenCV;

    3. Google Mobile;
  2. Робототехніка і Arduino;
  3. Промислове виробництво — іноді який-небудь завод робить на OpenCV систему підрахунку деталей або щось на зразок того.

Складно чи цікаво?
Хоча деколи важко сказати, які дані можна вважати дійсно «великими», у випадку з OpenCV таких сумнівів немає: так, self-driving car може обробляти по приблизних підрахунках близько 1 Гб/с, і це дійсно   великі дані. Для порівняння людський мозок обробляє ~ 45 Мб — 3Гб/с — це залежить, зокрема, від освітленості приміщення.

Що стосується численних алгоритмів OpenCV, серед них є і складні, і прості. Є, зокрема, алгоритми фільтрації, тензори (по суті, одномірні масиви).

Також в OpenCV застосовуються технології машинного (machine learning) та глибинного навчання (deep learning), так як розпізнавання частково побудовано на нейронних мережах. Deep learning і machine learning — дуже цікава тема, вивчати яку раджу курсів на Coursera. Що стосується теми комп'ютерного зору взагалі, я раджу цю книгу:


З чого складається OpenCV?


CXCORE (власне ядро), як не дивно, з точки зору програмування влаштовано елементарно. Воно містить базові структури даних і алгоритми:

  • базові операції над багатовимірними числовими масивами — вони дозволяють, наприклад, помножити матрицю на вектор, перемножити дві матриці і т. д.;
  • матрична алгебра, математичні функції, генератори випадкових чисел — щоб з цим працювати, достатньо знати назву потрібної функції, і все;
  • запис/відновлення структур даних в/з XML;
  • базові функції 2D графіки — з їх допомогою можна, наприклад, намалювати змійку.


CV — це модуль обробки зображень та комп'ютерного зору. Він включає:

  • базові операції над зображеннями (фільтрація, геометричні перетворення, перетворення колірних просторів тощо);
  • аналіз зображень (вибір відмінних ознак, морфологія, пошук контурів, гістограми);
  • аналіз руху, стеження за об'єктами;
  • виявлення об'єктів, зокрема осіб;
  • калібрування камер і елементи відновлення просторової структури.


Геометричні перетворення, між іншим — це дуже важлива частина бібліотеки: адже коли ви намагаєтеся щось побудувати, найчастіше потрібно враховувати поворот і кут камери.

HighGUI   модуль для введення/виводу зображень і відео, створення користувальницького інтерфейсу. Модуль виконує наступні функції:

  • захоплення відео з відео камер і відео файлів, читання/запис статичних зображень;
  • опції для організації простого UI (всі демо-програми використовують HighGUI).


ML   вбудовані алгоритми машинного навчання, які працюють з коробки, хоча у 3-й версії від них поступово відмовляються, бо чтохорошие алгоритми машинного навчання зараз розробляють інші компанії (про них буде сказано далі).

CvCam — все, що ви можете робити з відео, захоплення камери, виявлення, слайсинг і т. д.)

Cvaux — це експериментальні і застарілі функції:

  • просторовий зір: стереокалибрация, самокалибрация;
  • пошук стереосоответствия, кліки в графах;
  • виявлення і опис рис обличчя.


Приклади патентів або стартапів
Хороший приклад одного з останніх успішних стартапів, які використовують OpenCV, —віртуальна примірювальна від компанії Zugara, забезпечує дійсно високу конверсію. Як вона працює? Алгоритм приблизно такий: вона фотографує користувача і вважає відстань до його особи. Потім користувач вводить кілька своїх розмірів, і примірочна обраховує щось з одягу, придивилася покупцеві. Є, втім, і ще одна значна частина у цій системі — AutoCAD-модель: кожна річ перед тим, як ви будете її приміряти, проходить 3D-реконструкцію.

Другий хороший приклад застосування OpenCV — система розпізнавання автомобільних номерів на дорогах. Точність такої системи, проте — до 90 %, так як багато чого залежить від якості зйомки, від швидкості машини, від того, наскільки забруднений номер і т. д.

Нейронні мережі (механізми навчання)
Друга важлива частина OpenCV (після тієї, що відповідає за обробку зображення) — це машинне навчання. Крім вбудованого в OpenCV, зараз існує кілька механізмів машинного навчання:

  • TensorFlow від Google, побудований повністю на тензорах;
  • Theano, PyLearn2 && EcoSystem — це одна з найбільших розробок, дуже складна в застосуванні;
  • Torch — вже застарілий механізм;
  • Caffe — це найкраща система для початківців, яку просто використовувати. Її, між іншим, необов'язково використовувати саме для розпізнавання — ви можете використовувати її, наприклад, у фінансовій сфері. Так, для прототипування банківських маніпуляцій часто використовується саме Caffe. Також є біологічні системи, побудовані на ній.


Труднощі побудови системи
Коли ми будуємо подібну систему (нехай навіть ту ж віртуальну примірювальну або систему розпізнавання номерів), нам доводиться мати справу принаймні з двома дилемами:

  • софт або залізо,
  • алгоритм або нейронна мережа.


Дилема софта і заліза полягає в тому, що, гірше ніж залізо, тим краще потрібно розробити програмну частину, щоб отримати гарний результат. Друга дилема наступна — що краще використовувати в програмній частині: який-небудь алгоритм або нейронну мережу? Насправді, іноді нейронна мережа програє алгоритмом. Я вибираю між алгоритмом і нейронною мережею наступним чином: якщо нейронна мережа займає більше місця, ніж алгоритм, вибираю алгоритм. Алгоритм взагалі надійніше, і в простих випадках я вибирала би саме його. А нейромережа часом не може вирішити навіть дуже просту задачу: так, перцептрон Розенблатта не може зрозуміти, знаходиться точка вище або нижче прямої.

Розпізнавання символів
Поговоримо трохи про розпізнавання символів, що може знадобитися, наприклад, при створенні системи розпізнавання автомобільних номерів.

TesseractOCR   відкрите ПЗ, автоматично распознающее і одиничну букву, і відразу текст. Tesseract зручний тим, що він є для будь-яких ОС, стабільно працює і легко навчаємо. Проте в нього є суттєвий недолік: він дуже погано працює з замиленим, битим, брудним і деформованим текстом. Тому Tesseract навряд чи підійде для розпізнавання номерів, однак він дуже добре впорається з розпізнаванням простого тексту. Т. ч. Tesseract можна відмінно застосовувати, наприклад, у документообігу.

K-nearest — дуже простий для розуміння алгоритм розпізнавання символів, який, незважаючи на свою примітивність, часто може перемагати не найвдаліші реалізації SVM або нейромережевих методів.

Працює він таким чином:

  1. попередньо записуємо пристойну кількість зображень реальних символів, які були перед цим вручну розбиті на класи;
  2. вводимо міру відстані між символами (якщо зображення бинаризованно, операція XOR буде оптимальна);
  3. потім, коли ми намагаємося розпізнати символ, по черзі розраховуємо дистанцію між ним і всіма символами в базі. Серед найближчих сусідів, можливо, будуть представники різних класів. Представників якого класу більше серед сусідів, до того класу варто віднести розпізнати символ.


Типи даних OpenCV
Тут все просто.

CvPoint
  точка (структура з двох змінних (x, y))
CvSize
  розмір (структура з двох змінних (width, height))
CvRect
  прямокутник (структура з 4 змінних (x, y, width, height))
CvScalar
  скаляр (4 числа типу double)
CvArr
  масив — його можна вважати «абстрактним базовим класом» для CvMat і далі IplImage (CvArr -> CvMat -> IplImage)
CvMat
  матриця
IplImage
  зображення

Ось і всі типи даних, які є в OpenCV.

Завантаження картинки
Це вже те, що ви можете зробити на Ruby. Після того, як ви підключите бібліотеку, можете завантажити картинку. Важливо, що, якщо ви хочете його подивитися, її потрібно не забути вивести у вікно.

cvLoadImage( filename, int iscolor=CV_LOAD_IMAGE_COLOR )
 
// вікно для відображення картинки 


В якості параметрів приймаються ім'я файлу і якість зображення:

  • filename
      ім'я файлу
  • iscolor
      визначає як уявити картинку
  • iscolor > 0
     
iscolor == 0
  картинка буде завантажена в форматі GRAYSCALE (градації сірого)
iscolor < 0 
картинка буде завантажена як є

cvNamedWindow("original",CV_WINDOW_AUTOSIZE);
 
// показуємо зображення
 
cvShowImage("original",image); 


Інформація, доступна після завантаження
Тут є близько 25 методів, але я користуюся тільки цими:

  • image->nChannels // число каналів картинки (RGB, хоча в OpenCV — BGR ) (1-4);
  • image->depth // глибина в бітах (це потрібно для накладання певних фільтрів, наприклад);
  • image->width // ширина зображення в пікселях;
  • image->height // висота зображення в пікселях;
  • image->imageSize // пам'ять, зайнята картинкою==image->height*image->widthStep);
  • image->widthStep // відстань між сусідніми по вертикалі точками зображення (число байт в одній сходинці картинки) — може знадобитися для самостійного обходу всіх пікселів зображення.


Метод Віоли-Джонса
Цей метод розпізнавання осіб, винайдений в 2005 р., заснований на ознаках Хаара. Він використовується майже у всіх фотоапаратах для визначення осіб. Ось як він працює.



Величина кожної ознаки обчислюється як сума пікселів в білих прямокутниках, з якої віднімається сума пікселів в чорних областях. Прямокутні ознаки більш примітивні, ніж steerable filter,

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

А якщо говорити людською мовою, береться обличчя і ділиться на дві частини. Область біля носа і під очима буде більш темна, щоки — більш світлими і т. д. Уявімо, що кожен піксель зображення — одне значення вектора: за допомогою цього обчислюється кількість сірих і білих пікселів. На підставі цього робиться висновок, схоже це на особу або ні.

Нейронні мережі


Нейромережі зараз діляться на два типи. Перший тип —старі дво — і трирівневі мережі. Такі мережі навчаються градієнтними методами зі зворотним поширенням помилки. При роботі з ними ви берете вектор, направляєте функцію, після чого, наприклад, йде шар перцептрона. У вас є input (зображення, яке вже опрацьовано — наприклад, береться потрібна його частина, а у випадку з номером — нарізати на прямокутники для кожного символу номери). Після цього розкладається кожен піксель — вектор, і ми вважаємо переходи. Власне, це просто обхід по масиву. Така технологія вже застаріла.

Нові мережі другого типу — глибокі та згорткові, використовують операцію згортки. Операція згортки показує схожість однієї функції з відбитою і зрушеної копією іншого. Вся згортка в OpenCV відбувається по 2D-фільтру:

cvFilter2D( src, dst, kernel, CvPoint anchor CV_DEFAULT(cvPoint(-1,-1)))


Детектор кордонів Canny
Якщо ми хочемо обробляти зображення осіб або номерів, потрібно обчислити границі цих зображень. Це дуже непросте завдання вирішується в OpenCV з допомогою дуже старого вбудованого алгоритму — Canny 1986 р.

Краю (межі) — такі криві на зображенні, уздовж яких відбувається різка зміна яскравості або інших видів неоднорідностей. Простіше кажучи, край — різкий перехід або зміна яскравості.

Причини виникнення країв:
  • зміна освітленості;
  • зміна кольору;
  • зміна глибини сцени (орієнтації поверхні).


Для задіяння алгоритму вам необхідно вказати, де шукати зображення і поріг розмиву, — це необхідно, наприклад, щоб зуміти знайти машину на темній дорозі.

cvCanny( image, edges, threshold1,
 
threshold2, CV_DEFAULT(3) );


image
  одноканальне зображення для обробки (градації сірого);
edges
  одноканальне зображення для зберігання кордонів, знайдених функцією;
threshold1
  поріг мінімуму;
threshold2
  поріг максимуму;
aperture_size
  розмір для оператора Собеля.

Ось як працює алгоритм Canny покроково:

  • Прибирає шум і зайві деталі зображення.
  • Розраховує градієнт зображення.
  • робить краю тонкими (edge thinning).
  • пов'язує краю в контури (edge linking).


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

І сподіваюся, що тема актуальна у зв'язку з настанням Ери робототехніки.
Джерело: Хабрахабр

0 коментарів

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