Pierwsze kroki z Raspberry Pi: aplikacje wideo bazujące na OpenCV

Współcześnie produkowane mikroprocesory kilkukrotnie przewyższają możliwościami obliczeniowymi nasze komputery biurkowe sprzed kilkunastu lat. W „wyścigu mocy obliczeniowych” naszych procesorów bardzo rzadko zauważamy jednak, że współczesne minikomputery nie tylko dorównały mocą niedawno używanym urządzeniom stacjonarnym, ale także „zmniejszyły” je do rozmiarów karty kredytowej (wymiary zestawu Raspberry Pi to tylko 85,60 × 53,98 mm). Taka miniaturyzacja stawia przed projektantami urządzeń elektronicznych nowe możliwości, także w zakresie metod cyfrowego przetwarzania obrazów, którym pragnę poświęcić niniejszy artykuł.

W artykule omówiony zostanie proces kompilacji biblioteki OpenCV na platformę Raspberry Pi, przedstawione zostaną proste projekty przetwarzania (filtracje, detekcja krawędzi, itp.) oraz detekcji twarzy na obrazach statycznych. Po zdobyciu elementarnej wiedzy na temat pracy z biblioteką OpenCV, w kolejnej części artykułu będziemy zajmować się przetwarzaniem obrazów w czasie rzeczywistym, wykorzystując do tego celu moduł kamery Raspberry Pi (dostępnej w KAMAMI.PL).

Sklep KAMAMI.pl oferuje zarówno komputery Raspberry Pi jak i dedykowane kamery do współpracy z tym komputerem.

 

Biblioteka OpenCV

OpenCV jest otwartoźródłową, opracowaną i udostępnioną przez firmę Intel na licencji BSD (licencja umożliwia darmowe wykorzystanie aplikacji w rozwiązaniach komercyjnych) biblioteką funkcji wykorzystywanych do realizacji cyfrowej obróbki obrazu. Jak podają jej autorzy, OpenCV posiada ponad 2500 zoptymalizowanych algorytmów. Możliwości biblioteki można przetestować w systemach operacyjnych Mac OS X, Windows, Linux oraz Android i iOS. Do realizacji projektów wykorzystamy kody źródłowe w wersji 2.4.5 (jest to najnowsza stabilna wersja biblioteki dostępna do pobrania w momencie przygotowywania artykułu). Sam kod źródłowy napisany jest w języku C i C++, jednak z możliwości biblioteki można korzystać również w językach Python i Java.

 

Instalacja biblioteki OpenCV na platformie Raspberry Pi

Źródła biblioteki OpenCV w wersji 2.4.5 są dostępne do pobrania na stronie:

Ponieważ kompilacji biblioteki będziemy dokonywać natywnie (wykorzystując do tego celu bezpośrednio zestaw Raspberry Pi), wersję dla systemu Linux pobieramy bezpośrednio do pamięci minikomputera. Następnie wypakowujemy pobrane archiwa:

Po sukcesywnym pobraniu i rozpakowaniu bibliotek, uzupełnijmy nasz system w niezbędne do procesu kompilacji paczki. W tym celu za pomocą terminala zestawu Raspberry Pi wykonujemy polecenie:

Do przeprowadzenia procesu konfiguracji OpenCV użyjemy darmowego narzędzia CMake (w odróżnieniu od znanego Make, CMake nie dokonuje kompilacji, a jedynie tworzy skrypty, jak np. Makefile). Na potrzeby narzędzia CMake, w rozpakowanym archiwum utworzymy katalog o nazwie release :

Wywołamy teraz narzędzie CMake z odpowiednimi opcjami konfiguracyjnymi w których wskażemy ścieżkę instalacji:

Po wygenerowaniu pliku Makefile możemy przystąpić do kompilacji i instalacji przekompilowanych bibliotek:

Ponieważ sam proces kompilacji natywnej na Raspberry Pi jest dość czasochłonny (kompilacja może trwać około 6. godzin) sugeruję w międzyczasie przeprowadzić identyczny sposób kompilacji na komputerze stacjonarnym wyposażonym w system Linux. Przebieg kompilacji i instalacji na urządzeniu stacjonarnym jest identyczny (testowano na Ubuntu 12.04), a wszystkie kody źródłowe są w pełni przenośne pomiędzy maszynami, tym samym więc zaoszczędzimy trochę czasu na poznawanie podstaw OpenCV.

 

Pierwsza aplikacja wykorzystująca biblioteki OpenCV

Zadaniem pierwszej zaprezentowanej aplikacji będzie wyświetlenie wskazanego w programie obrazka. Złożoność kodu pierwszej aplikacji jest niewielka, jednak jej analiza pozwoli zapoznać się z podstawowymi funkcjami biblioteki. Utwórzmy plik sample_1.c w którym umieścimy pierwszy program, napisany z wykorzystaniem nowo zainstalowanych bibliotek. Kod programu przedstawiono na listingu 1.

List. 1.

Program przedstawiony na Listingu 1 jest nieskomplikowany i dzięki bardzo czytelnym nazwom funkcji można łatwo prześledzić i zrozumieć jego budowę. Na początku działania programu deklarujemy strukturę danych typu IplImage, która jest wykorzystywana do operacji związanymi z wczytywaniem, wyświetlaniem i zapisywaniem obrazów. Za pomocą funkcji cvLoadImage() wczytujemy obraz ze wskazanego poprzez argument pliku. Funkcja ta ma następującą budowę:

gdzie filename to nazwa pliku z obrazem, natomiast iscolor określa, czy dany obraz jest kolorowy:

iscolor > 0 – obraz kolorowy

iscolor = 0 – obraz w skali szarości

iscolor < 0 – zależy od ilości kanałów w obrazie

Ponieważ nie wskazaliśmy całej ścieżki dostępu do pliku z obrazem linux.jpg, plik ten musi zostać umieszczony w katalogu wraz z plikiem wykonywalnym. Brak pliku lub nieobsługiwany format powoduje zwrócenie przez funkcję cvLoadImage() wartości NULL. Kolejnie linie kodu to utworzenie nowego okna oraz wyświetlenie wczytanego obrazu. Funkcja cvNamedWindow() pozwala nadać nazwę wyświetlanemu oknu, co w przypadku pracy z kilkoma obrazami jest niezwykle użyteczne. Funkcje cvDestroyWindow() oraz cvReleaseImage() odpowiednio kasują wyświetlane okno oraz zwalniają zaalokowaną pamięć. Funkcje te zostaną wykonane dopiero po wybraniu z klawiatury dowolnego przycisku, co jest realizowane poprzez funkcję cvWaitKey().

Przystąpmy więc do kompilacji naszego programu. W katalogu w którym umieściliśmy nasz kod źródłowy wykonujemy polecenie:

Jeśli proces przebiegł bezbłędnie i mamy już umieszczony w katalogu z plikiem wykonywalnym obraz linux.jpg, to uruchomiamy naszą aplikację poleceniem:

Efekt działania programu został zaprezentowany na rysunku 1.

Rys. 1. Wynik działania aplikacji z listingu 1

Rys. 1. Wynik działania aplikacji z listingu 1

 

Do pobrania

O autorze

Łukasz Skalski

Łukasz Skalski – absolwent Politechniki Gdańskiej, miłośnik FLOSS,
autor książki “Linux. Podstawy i aplikacje dla systemów embedded” oraz szeregu artykułów dotyczących programowania systemów wbudowanych.
Zawodowo związany z firmą Samsung. Wszystkie wolne chwile poświęca projektowaniu i programowaniu urządzeń wyposażonych w mikroprocesory 8-/16- i 32-bitowe. Szczególnym zainteresowaniem obejmuje tematykę systemu Linux w aplikacjach na urządzenia embedded.