Bulldogjob pl pattern 530x244 002
DataArt działa od 1997 roku. Zajmuje się konsultingiem i outsourcingiem usług IT. Jej polskie biura zlokalizowane są w Lublinie i Wrocławiu.

Open CV jest popularną biblioteką funkcji wykorzystywanych podczas obróbki obrazu na bazie open source. Opowiem o tym, co można zrobić za pomocą OpenCv, jak funkcjonuje biblioteka i jak używać jej z Ruby. Miałam przyjemność brać udział w dwóch projektach, w których była używana. W obu przypadkach nie korzystaliśmy z Ruby w wersjach końcowych, jednak Ruby jest bardzo przydatny w początkowej fazie, by stworzyć prototyp przyszłego systemu i sprawdzić, jak OpenCV poradzi sobie z wymaganymi zadaniami. Jeśli wszystko jest ok, aplikację pisze się w innym języku, na podstawie tego samego algorytmu. OpenCV w parze z Ruby ma swoje specyficzne zalety.

Najważniejsze części biblioteki to algorytmy uczenia maszynowego i interpretacji obrazów. Lista możliwości OpenCV jest raczej rozległa:

- interpretacja obrazów,

- kalibracja kamery,

- eliminacja odkształceń wizualnych,

- wykrywanie podobieństwa,

- analiza ruchu obiektów,

- identyfikacja kształtu i śledzenie obiektów,

- narzędzia 3d,

- segmentacja obiektów,

- rozpoznawanie gestów.

OpenCV ma szeroki zakres użycia. Mam kilka interesujących przykładów:

 

1. Google

- auto bez kierowcy Google – OpenCV jest używana do rozpoznawania otoczenia (obecny system bazuje głównie na LIDAR, ze względu na problemy z rozpoznawaniem w niedostatecznym oświetleniu);

- Google Glass: rekonstrukcja obrazu 3d bazuje na Open CV;

- Google Mobile;

 

2. Robotics and Arduino

3. Produkcja przemysłowa: zdarza się, że fabryki używają systemów do – na przykład – zliczania części i są one oparte właśnie na OpenCV. 

 

Trudne czy interesujące?

Nawet jeśli czasami nie jest łatwo powiedzieć, jakie dane są naprawdę „big”, w przypadku OpenCV nie mamy do czynienia z tym problemem: samochód pozbawiony kierowcy Google może przetworzyć około 1 GB danych w ciągu sekundy i to prawdziwe big data. Dla kontrastu – ludzki mózg przetwarza od 45 MB do 3GB danych wizualnych w ciągu sekundy (zależy to przede wszystkim od oświetlenia).

W przypadku algorytmów OpenCV mówimy zarówno o prostych jak i skomplikowanych przykładach. Ponadto OpenCv korzysta z uczenia maszynowego i technologii głębokiego uczenia, w związku z tym, że rozpoznawanie jest w części oparte na sieciach neuronowych. Głębokie uczenie i uczenie maszynowe są bardzo ciekawymi zagadnieniami – polecam kursy dostępne online. W przypadku computer vision warto sięgnąć po książkę Computer Vision: A Modern Approach, autorstwa D. A. Forsytha i Jean Ponce.

 

Z czego składa się OpenCV?

CXCORE (rdzeń) – co ciekawe jest bardzo nieskomplikowany z programistycznego punktu widzenia, zawiera podstawowe struktury danych i algorytmy:

  • podstawowe operacje na wielowymiarowych tablicach numerycznych – pozwalają, na przykład, pomnożyć matrycę przez wektor, przemnożyć dwie matryce, etc.;
  • algebra matryc, funkcje matematyczne, generatory losowych liczb: do pracy z wymienionymi rzeczami musisz znać tylko nazwę funkcji – to wszystko;
  • zapisywanie/odzyskiwanie struktur danych do/z XML;
  • podstawowe cechy grafiki 2d: mogą być użyte do narysowania, na przykład, starej, poczciwej gry w „wężyka”;

CV jest jednostką przetwarzającą obrazy i dane wizualne. Obejmuje:

  • podstawowe operacje z użyciem obrazów (filtrowanie, transformacje geometryczne, konwersję kolorów, etc.);
  • analizę obrazów (selekcja cech wyróżniających, morfologię, histogramy);
  • analizę ruchu i śledzenie obiektów;
  • rozpoznawanie obiektów (przede wszystkim twarzy);
  • kalibrację kamery i elementy odtwarzania struktury przestrzennej.

Przy okazji – transformacje geometryczne są bardzo ważną częścią biblioteki ze względu na to, że kiedy starasz się coś zbudować, często musisz brać pod uwagę obrót i kąt aparatu.

HighGUI jest modułem do I/O obrazów i wideoklipów oraz do tworzenia interfejsu użytkownika. Moduł pełni następujące funkcje:

  • przechwytywanie wideo z aparatu i plików wideo, czytanie/zapisywanie obrazów statycznych;
  • funkcje związane z organizacją prostego UI (wszystkie aplikacje demo korzystają z HighGUI).

ML to wbudowane algorytmy uczenia maszynowego, które działają niezależnie, natomiast wersja 3D stopniowo z nich rezygnuje, ze względu na to, że inne firmy rozwijają dobrej jakości algorytmy uczenia maszynowego (przedyskutuję je później).

CvCam – wszystko, co możesz zrobić z wideo (przechwytywanie, wykrywanie, cięcia, itp.)

CvAux – eksperymentalne i przeterminowane funkcje takie jak:

  • widzenie przestrzenne – kalibracja stereo, samokalibracja;
  • wyszukiwanie analogii stereo;
  • lokalizacja i opis cech twarzy.

 

Przykłady użycia computer vision

Dobrym – i jednym z nowszych – przykładem użycia OpenCV z sukcesem przez startup jest wirtualna przymierzalnia stworzona przez firmę Zugara, która owocuje imponującą konwersją. Jak to działa? Sekwencja czynności jest podobna do tej: robione jest zdjęcie użytkownika i przeliczana jest odległość od jego twarzy. Następnie, użytkownik wprowadza odpowiednie wymiary swojej sylwetki, a oprogramowanie przelicza je i prezentuje ubrania, które mogą być odpowiednie dla użytkownika. Ważną częścią tego systemu jest model AutoCAD – każde pojedyncze ubranie przechodzi proces rekonstrukcji 3d zanim będziesz w stanie je przymierzyć.

Kolejnym dobrym przykładem użycia OpenCV jest rozpoznawanie tablic rejestracyjnych. Ale dokładność tego systemu sięga 90%, ponieważ zależy od jakości nagrania, ilości brudu na tablicy, itd.

 

Sieci neuronowe (mechanizmy uczenia)

Kolejna istotną częścią OpenCV (zaraz po tej odpowiedzialnej za przetwarzanie obrazów) jest uczenie maszynowe. Dodatkiem do wbudowanych mechanizmów są inne mechanizmy związane z machine learning:

  • TensorFlow stworzony przez Goole jest w całości oparty o tensory (dynamiczne, wielowymiarowe -macierze danych);
  • Theano, PyLearn2 & EcoSystem – to jedno z największych rozwiązań, które jest trudne w użytkowaniu;
  • Torch – to mechanizm, który wyszedł z użycia;
  • Caffe to najlepszy system dla początkujących, który jest łatwy w użytkowaniu. Przy okazji – można używać go nie tylko do rozpoznawania, ale na przykład w finansach. Caffe jest często wykorzystywany w bankowości do prototypowania aktywności. Istnieją również systemy biologiczne oparte o niego.

 

Wyzwania związane z rozwojem systemu

Kiedy budujemy podobny system (na przykład wirtualną przymierzalnię albo system rozpoznawania tablic rejestracyjnych), musimy zmierzyć się z dwoma dylematami:

  • software czy hardware;
  • algorytm czy sieć neuronowa.

Dylemat nr 1. można podsumować następującym zdaniem: im gorszy hardware, tym lepsze musi być oprogramowanie. Drugi dylemat związany jest z tym, co jest przyjemniejsze do użytkowania – ja wybieram następująco: na algorytmie można polegać bardziej w prostych przypadkach. Sieć neuronowa może czasami mieć trudności z rozwiązaniem nawet prostego zadania – perceptron Rosenblatta nie jest w stanie stwierdzić, czy kropka znajduje się nad czy pod linią.

 

Rozpoznawanie znaków

Rozważmy zagadnienie rozpoznawania znaków, które może być użyte, na przykład, do rozpoznawania tablic rejestracyjnych.

Tesseract OCR jest oprogramowaniem open source, które automatycznie rozpoznaje pojedyncze znaki i tekst. Tesseract cechuje wygoda, ponieważ jest wydajne i wspiera wiele systemów operacyjnych. Ale ma też sporą wadę – rozpoznaje rozmyte, zniszczone i brudne fragmenty tekstu z dużą dozą błędów. Jest więc mało odpowiedni do rozpoznawania tablic rejestracyjnych, ale świetnie radzi sobie z prostym tekstem. W związku z tym można używać go do pracy z dokumentacją.

K-nearest jest algorytmem rozpoznawania, który jest bardzo łatwy do zrozumienia. Algorytm, pomimo swojej prostoty, może być lepszym rozwiązaniem niż SVM czy sieci neuronowe.

Działa w następujący sposób:

  1. Nagrywanie wstępne odpowiedniej ilości rzeczywistych obrazów znaków, które wcześniej zostały manualnie podzielone w klasy;
  2. Wprowadzenie jednostki odległości pomiędzy znakami;
  3. Kiedy próbujemy rozpoznać symbol, wyliczamy dystans między nim a znakami w bazie danych. Wśród najbliższych „sąsiadów” mogą znajdować się przedstawiciele wspomnianych klas. Rozpoznawalny symbol powinien być ujęty w klasie z większą ilością „sąsiadów”.

 

Typy danych OpenCV

W tym przypadku wszystko jest nieskomplikowane:

CvPoint – punkt (struktura z dwóch zmiennych – x, y)

CvSize – rozmiar (struktura z dwóch zmiennych – width, height)

CvRect – prostokąt (struktura z czterech zmiennych – x, y, width, height)

CvScalar - scalar (4 podwójne liczby)

CvArr – tablica, która może być nazwana “abstrakcyjna podstawową klasą”

CvMat - matryca

IplImage - obraz

To wszystkie typy danych w OpenCV.

Ładowanie obrazów

To jest właśnie to, co możesz zrobić w Ruby. Dostajesz się do biblioteki i ładujesz obrazki. Ważne, by pamiętać – jeśli chcesz obejrzeć obraz, nie zapomnij zainicjować wyświetlania go w aktywnym oknie.

cvLoadImage (filename, int iscolor = CV_LOAD_IMAGE_COLOR)
// Window for displaying the image

Nazwa pliku i jakość obrazu są akceptowane jako parametry:

- filename - nazwa pliku

- iscolor - definiuje w jaki sposób wyświetla się obraz

- iscolor > 0 -

iscolor == 0 – obraz będzie wyświetlony w skali szarości
iscolor < 0 – obraz będzie wyświetlony taki, jaki jest
cvNamedWindow ( "original", CV_WINDOW_AUTOSIZE);
// show an image
cvShowImage ( "original", image);

 

Informacje dostępne po załadowaniu

Jest okolo 25 metod, ale ja używam następujących

image-> nChannels // ilość kanałów obrazu;
image-> depth // głębia - bity; 
image-> width // szerokość w px,
image-> height // wysokość w px;
image-> imageSize // pamięc, jakiej wymaga obraz;
image-> widthStep // liczba bitów w jednej linii obrazu;

 

Metoda Viola-Jones

Ta metoda rozpoznawania została wynaleziona w 2005. Jest oparta o cechy Haar. Jest używana w większości aparatów do rozpoznawania twarzy. Działa następująco.

Wartość każdej cechy jest wyliczana jako suma pikseli w białych prostokątach, od której odejmowana jest suma pixeli w czarnych obszarach. Cechy prostokątne są bardziej prymitywne niż steerable filter i - nawet jeśli - są wrażliwe na wertykalne i horyzontalne cechy obrazu, rezultat wyszukiwania jest mniej dokładny.

W uproszczeniu - twarz dzielona jest na dwie części - obszar dookoła nosa i pod oczami będzie ciemniejszy, policzki będą jaśniejsze, itd. Wyobraźmy sobie, że każdy piksel odpowiada jednej wartości wektora - pomaga to wyliczyć ilość szarych i białych pikseli. Na bazie tego system decyduje, czy to, co "widzi" wygląda jak twarz, czy nie.

 

Sieci neuronowe

Sieci neoronowe dziela się na dwa typy. Pierwszy rodzaj obejmuje stare dwupoziomowe i trzypoziomowe sieci. Takie sieci są przyswajane z użyciem metod gradientowych z odwróconym rozproszeniem błędów. Kiedy z nimi pracujesz, posługujesz sie wektorem wskazującym na konkretną funkcję i wtedy, na przykład, znajduje się tam warstwa perceptronu. Masz dane wejściowe (obraz, który już został przetworzony - na przyklad pożądaną jego część; jeśli pracujemy na liczbach, każdy symbol będzie podzielany na prostokątach). Potem każdy piksel (wektor) jest dzielony i przejścia są zliczane. Taka technologia aktualnie wychodzi z użycia.

Nowe sieci drugiego typu obejmują głębokie i konwolucyjne sieci neuronowe. Operacja konwolucji pokazuje podobieństwo jednej funkcji z odbitą i przeniesioną kopią innej. W OpenCv zawsze używany jest filtr 2d. 

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

 

Metoda detekcji krawędzi Canny

Kiedy chcemy przetwarzać obrazy twarzy lub liczb, musimy wyliczyć granice tych obrazów. To bardzo trudny problem, który w OpenCV rozwiązany jest za pomocą bardzo starego, wbudowanego algorytmu Canny, który został stworzony w roku 1986.

Krawędzie to zakrzywienia obrazu, które wiążą się z gwałtowną zmianą jasności albo innymi nieregularnościami. W prostych słowach - krawędź to ostre przejście albo zmiana jasności. 

Skąd biorą się krawędzie:

  • zmiana oświetlenia;
  • zmiana koloru;
  • zmiana głębi obrazu.

By umożliwić pracę algorytmu, musisz określić, gdzie znaleźć ibraz i ocenić nieregularność - to niezbędne, na przykład, do znalezienia samochodu na ciemnej drodze.

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

image – jednokanałowy obraz do przetworzenia (skala szarości);
edges – jednokanałowy obraz do określenia granic znalezionych przez funkcję;
threshold1 – próg minimalny;
threshold2 – próg maksymalny;
aperture_size – rozmiar operatora.

 

Tak, krok po kroku, działa Canny:

  • usuwanie zakłóceń i niepotrzebnych części obrazu
  • wyliczanie gradientu
  • zwężanie krawędzi
  • łączenie krawędzi

Do tych, którzy dotarli do końca tekstu (chciałabym wierzyć, że połowa moich czytelników tutaj dobrnie) - chciałam dodać, że ten artykuł miał na celu zgłębienie zagadnienia - chciała podzielić się z wami moimi obserwacjami. Nie mam wykształcenia technicznego, może tutaj być wiele nieścisłości. Będę się bardzo cieszyła, jesli otrzymam komentarze i poprawki.

Autorka: Lyudmila Dezkhina, Senior Full Stack Developer, DataArt