Celem opisanego poniżej projektu jest zmodyfikowanie samochodzika RC w taki sposób, aby samodzielnie jeździł po torze: był w stanie wykrywać znak stopu i rozpoznawać światła drogowe i ich kolor. Dodatkowo w układ wbudowano detektor kolizji i przedmiotów znajdujących się z przodu auta.
System składa się z trzech modułów - systemu wejścia: kamery i sensora ultradźwiękowego; jednostki przetwarzającej: komputera i samochodzika RC.
Jednostka wejściowa
Do samochodu zamocowany jest moduł Raspberry Pi B+ z dołączoną kamerą oraz ultradźwiękowym sensorem HC-SR04. Moduł ten odpowiedzialny jest za zbieranie danych. Na komputerze pracują dwa programy, które mają za zadanie przekazywanie strumieni danych - z kamery i z sensora ultradźwiękowego - do komputera poprzez lokalną sieć WiFi. Jednocześnie, program odpowiedzialny za przekazywanie obrazu kamery, skaluje obraz do rozdzielczości QVGA (320 x 240 pikseli), aby uzyskać niskie opóźnienia w transmisji.
Jednostka przetwarzająca dane
Jednostką przetwarzającą dane jest komputer odpowiedzialny za szereg zadań: odbiera dane z Raspberry Pi; kontroluje, uczy i steruje - sieć neuronową oraz zajmuje się detekcją przedmiotów (znaków stop i świateł drogowych), pomiarem odległości na podstawie obrazu oraz wysyła poprzez USB dane do Arduino.
Serwer TCP
Wielowątkowy serwer TCP pracuje cały czas na komputerze i odbiera dane od RPi - klatki obrazu i dane z miernika ultradźwiękowego. Program odpowiedzialny jest także za konwertowanie obrazów do skali szarości i dekodowanie ich do postaci macierzy zrozumiałych dla biblioteki Numpy w Pythonie.
Sieć neuronowa
Jedną z zalet wykorzystywania sieci neuronowej jest fakt, że po wstępnym nauczeniu sieci jej działanie jest bardzo szybkie, co pozwala niezwykle prędko rozpoznawać elementy na obrazach. W wykorzystanym algorytmie jedynie połowa wejściowego obrazu wykorzystywana jest do uczenia sieci i rozpoznawaniu obiektów.
Sieć neuronowa wykorzystuje 38400 (320 x 120) neuronów w warstwie wejściowej i 32 neurony w warstwie ukrytej. Ilość neuronów w ukrytej warstwie została dobrana dosyć arbitralnie. W warstwie wyjściowej są cztery neurony, z których każdy odpowiada za jedną z instrukcji kontrolnych 0 w lewo, w prawo, naprzód i w tył. Ta ostatnia opcja nie jest wykorzystywana w projekcie, ale mimo wszystko została zaimplementowana w warstwie wyjściowej.
Poniżej pokazano dane wykorzystane do uczenia sieci. Każdy obrazek jest przycinany i konwertowany do macierzy numpy. Każdy z obrazków jest następnie opisywany etykietą - manualnie przez człowieka. Wszystkie dane - uczące dane i etykiety - zapisywane są w jednym pliku NPZ. Sieć neuronowa uczona jest w OpenCV, wykorzystując technikę propagacji wstecznej. Po etapie uczenia wagi zapisywane są pliku XML. Aby analizować obrazy, dane z pliku XMLwgrywane są do utworzonej sieci neuronowej.
Detekcja obiektów
W projekcie wykorzystano podejście polegające na detekcji kształtów. Wykorzystane w tym celu zostały klasyfikatory kaskadowe Haara. Jako że wymaga to stworzenia klasyfikatora i uczenia sieci rozpoznawania dla każdego kształtu, autor w projekcie skupił się na detekcji dwóch elementów toru - znaku STOP i świateł drogowych.
Oprogramowanie OpenCV zapewnia system uczenia sieci i detekcji kształtów. Wykorzystując telefon komórkowy z aparatem, autor zebrał próby dodatnie. Zdjęcia przycięte zostały tak, że widoczny na nich był tylko detekowany obiekt. Próbki ujemne zostały zebrane w sposób losowy.
Próbki dodatnie dla świateł drogowych zawierały w sobie identyczną liczbę zdjęć światła zielonego i czerwonego. Do uczenia obu klasyfikatorów wykorzystano te same próbki ujemne. Poniżej pokazano przykładowe próbki - dodatnie i ujemne - wykorzystane do uczenia klasyfikatorów w projekcie.
Do rozpoznawania koloru światła konieczne jest zastosowanie dodatkowej obróbki obrazu, poza opisanym powyżej algorytmem detekcji przedmiotów. Poniższy schemat blokowy opisuje algorytm detekcji koloru światła drogowego.
W pierwszej kolejności wyuczony klasyfikator kaskadowy wykorzystany zostaje do detekcji światła drogowego. Generuje on obrys światła, który posłuży w dalszej części jako ROI (rejon zainteresowania). Następnie, na ROI nakładane jest gaussowskie rozmycie obrazu i algorytm wyszukuje najjaśniejszy punkt na obrazie. Na podstawie lokalizacji tego punktu system determinuje, jakie światło jest zapalone - czerwone czy zielone.
Pomiar odległości
Moduł Raspberry Pi pozwala na podłączenie tylko jednego modułu kamery. Wykorzystanie dwóch kamer na USB byłoby nie wskazane z uwagi na wagę i koszt całego rozwiązania, dlatego autor projektu zdecydował się na pomiar odległości z wykorzystaniem tylko jednej kamery. System bazuje na modelu wykrywania odległości opisanym w pracy Chu, Ji, Guo, Li and Wang (2004).
P jest punktem na celu, do którego mierzona jest odległość, d to odległość od środka optycznego do punktu P. W oparciu o powyższą geometrię równanie (1) pokazuje jak obliczyć odległość d; f to ogniskowa obiektywu kamery ∂ to kąt pochylenia kamery, h to wysokość środka optycznego, punkt (x0, y0) odnosi się do współrzędnych powstałych z przecięcia osi optycznej kamery i płaszczyzny obrazu. Fizyczny wymiar piksela kamery zawarty jest w równaniu jako dx i dy. W takiej sytuacji:
Załóżmy, że $$y_0 = 0$$ oraz $$x_0 = 0$$; wtedy z równań (1) i (2) otrzymujemy:
Gdzie $$a_y = \frac{f}{dy}$$, a v to współrzędne na obrazie w osi y - parametr ten dany jest z algorytmu detekcji obiektów na obrazie. Pozostałe parametry są znane i wynikają z wykorzystanej kamery.
OpenCV umożliwia kalibrację kamery. Matryca kamery ma rozdzielczość 5 MP. W idealnym przypadku parametry a_x i a_y są sobie równe, ich ewentualne różnice wynikać będą z faktu, że piksele w matrycy nie są prostokątne. Pokazana poniżej macierz pokazuje, że moduł kamery zintegrowany z obiektywem o stałej ogniskowej, zapewnia dobre rezultaty, jeśli chodzi o kompensację zniekształceń obrazu.
Powyższa macierz zwraca wyniki w pikselach, a h mierzone jest w centymetrach, równanie (3) pozwala na wyliczenie odległości d, także w centymetrach.
Moduł kontroli samochodu RC
Wykorzystany samochodzik wyposażono w bardzo proste sterowanie. Odbywa się ono poprzez naciskanie przycisków, które powoduje zwieranie pinów układu kontrolującego do masy. Moduł Arduino podłączono do układu tak, aby udawał naciskanie przycisków, zwierając odpowiednie piny do masy. Wykorzystano cztery wyjścia cyfrowe modułu Arduino, które odpowiadają czterem akcjom - ruchowi do przodu i do tyłu oraz skrętom na boki. Moduł Arduino wystawia po prostu na odpowiednim pinie stan niski, gdy samochodzik ma pojechać w dowolnym kierunku. Moduł jest podłączony do komputera poprzez USB, a komputer przesyła do niego dane poprzez interfejs szeregowy emulowany na USB.
Wyniki
Jak pokazały testy algorytm rozpoznaje obiekty z dokładnością około 85%. Dla rozpoznawania obiektów na zbiorze uczącym dokładność ta wynosi 96%. Podczas normalnej pracy algorytm analizuje obraz około 10 razy na sekundę, co jest związane z szybkością nadawania strumienia wideo - 10 klatek na sekundę.
Wykorzystanie klasyfikatora Haara powoduje, że system rozpoznawania obrazów jest czuły na obrót obiektów, jednakże w opisanym przypadku nie jest to problemem, gdyż rozpoznawane obiekty - znak stopu i światła drogowe - zawsze umieszczane są w tej samej pozycji.
Jeśli chodzi o pomiar odległości, sensor ultradźwiękowy jest w stanie mierzyć odległość tylko od przedmiotów znajdujących się bezpośrednio przed pojazdem. Zwraca on dokładne wyniki tylko, gdy działa pod odpowiednim kątem, a powierzchnia, od której mierzy się odległość dobrze odbija ultradźwięki. Wyniki pomiaru odległości na podstawie obrazów autor opisuje jako "dość dobre" - to znaczy wystarczające na potrzeby opisywanego projektu. Poniżej zaprezentowano eksperymentalne dane pochodzące z testów układu.
Na pokazanych powyżej przykładach na dokładność pomiaru odległości wpływ ma szereg czynników: błędy pomiarowe, wariancja obrysu detekowanego przez algorytm obiektu, błędy na etapie kalibracji kamery i nieliniowa zależność pomiędzy współrzędnymi a odległością - im większa odległość, tym szybciej zmieniają się współrzędne kamery, generując większy błąd.
Autor mimo pewnych niedoskonałości projektu jest z niego bardzo zadowolony. Stworzony pojazd jest w stanie bez problemu poruszać się, unikając zderzeń i reagować na napotykane znaki STOPu i światła drogowe.
Źródło: https://zhengludwig.wordpress.com/projects/self-driving-rc-car/
System składa się z trzech modułów - systemu wejścia: kamery i sensora ultradźwiękowego; jednostki przetwarzającej: komputera i samochodzika RC.
Jednostka wejściowa
Do samochodu zamocowany jest moduł Raspberry Pi B+ z dołączoną kamerą oraz ultradźwiękowym sensorem HC-SR04. Moduł ten odpowiedzialny jest za zbieranie danych. Na komputerze pracują dwa programy, które mają za zadanie przekazywanie strumieni danych - z kamery i z sensora ultradźwiękowego - do komputera poprzez lokalną sieć WiFi. Jednocześnie, program odpowiedzialny za przekazywanie obrazu kamery, skaluje obraz do rozdzielczości QVGA (320 x 240 pikseli), aby uzyskać niskie opóźnienia w transmisji.
Jednostka przetwarzająca dane
Jednostką przetwarzającą dane jest komputer odpowiedzialny za szereg zadań: odbiera dane z Raspberry Pi; kontroluje, uczy i steruje - sieć neuronową oraz zajmuje się detekcją przedmiotów (znaków stop i świateł drogowych), pomiarem odległości na podstawie obrazu oraz wysyła poprzez USB dane do Arduino.
Serwer TCP
Wielowątkowy serwer TCP pracuje cały czas na komputerze i odbiera dane od RPi - klatki obrazu i dane z miernika ultradźwiękowego. Program odpowiedzialny jest także za konwertowanie obrazów do skali szarości i dekodowanie ich do postaci macierzy zrozumiałych dla biblioteki Numpy w Pythonie.
Sieć neuronowa
Jedną z zalet wykorzystywania sieci neuronowej jest fakt, że po wstępnym nauczeniu sieci jej działanie jest bardzo szybkie, co pozwala niezwykle prędko rozpoznawać elementy na obrazach. W wykorzystanym algorytmie jedynie połowa wejściowego obrazu wykorzystywana jest do uczenia sieci i rozpoznawaniu obiektów.
Sieć neuronowa wykorzystuje 38400 (320 x 120) neuronów w warstwie wejściowej i 32 neurony w warstwie ukrytej. Ilość neuronów w ukrytej warstwie została dobrana dosyć arbitralnie. W warstwie wyjściowej są cztery neurony, z których każdy odpowiada za jedną z instrukcji kontrolnych 0 w lewo, w prawo, naprzód i w tył. Ta ostatnia opcja nie jest wykorzystywana w projekcie, ale mimo wszystko została zaimplementowana w warstwie wyjściowej.
Poniżej pokazano dane wykorzystane do uczenia sieci. Każdy obrazek jest przycinany i konwertowany do macierzy numpy. Każdy z obrazków jest następnie opisywany etykietą - manualnie przez człowieka. Wszystkie dane - uczące dane i etykiety - zapisywane są w jednym pliku NPZ. Sieć neuronowa uczona jest w OpenCV, wykorzystując technikę propagacji wstecznej. Po etapie uczenia wagi zapisywane są pliku XML. Aby analizować obrazy, dane z pliku XMLwgrywane są do utworzonej sieci neuronowej.
Detekcja obiektów
W projekcie wykorzystano podejście polegające na detekcji kształtów. Wykorzystane w tym celu zostały klasyfikatory kaskadowe Haara. Jako że wymaga to stworzenia klasyfikatora i uczenia sieci rozpoznawania dla każdego kształtu, autor w projekcie skupił się na detekcji dwóch elementów toru - znaku STOP i świateł drogowych.
Oprogramowanie OpenCV zapewnia system uczenia sieci i detekcji kształtów. Wykorzystując telefon komórkowy z aparatem, autor zebrał próby dodatnie. Zdjęcia przycięte zostały tak, że widoczny na nich był tylko detekowany obiekt. Próbki ujemne zostały zebrane w sposób losowy.
Próbki dodatnie dla świateł drogowych zawierały w sobie identyczną liczbę zdjęć światła zielonego i czerwonego. Do uczenia obu klasyfikatorów wykorzystano te same próbki ujemne. Poniżej pokazano przykładowe próbki - dodatnie i ujemne - wykorzystane do uczenia klasyfikatorów w projekcie.
Do rozpoznawania koloru światła konieczne jest zastosowanie dodatkowej obróbki obrazu, poza opisanym powyżej algorytmem detekcji przedmiotów. Poniższy schemat blokowy opisuje algorytm detekcji koloru światła drogowego.
W pierwszej kolejności wyuczony klasyfikator kaskadowy wykorzystany zostaje do detekcji światła drogowego. Generuje on obrys światła, który posłuży w dalszej części jako ROI (rejon zainteresowania). Następnie, na ROI nakładane jest gaussowskie rozmycie obrazu i algorytm wyszukuje najjaśniejszy punkt na obrazie. Na podstawie lokalizacji tego punktu system determinuje, jakie światło jest zapalone - czerwone czy zielone.
Pomiar odległości
Moduł Raspberry Pi pozwala na podłączenie tylko jednego modułu kamery. Wykorzystanie dwóch kamer na USB byłoby nie wskazane z uwagi na wagę i koszt całego rozwiązania, dlatego autor projektu zdecydował się na pomiar odległości z wykorzystaniem tylko jednej kamery. System bazuje na modelu wykrywania odległości opisanym w pracy Chu, Ji, Guo, Li and Wang (2004).
P jest punktem na celu, do którego mierzona jest odległość, d to odległość od środka optycznego do punktu P. W oparciu o powyższą geometrię równanie (1) pokazuje jak obliczyć odległość d; f to ogniskowa obiektywu kamery ∂ to kąt pochylenia kamery, h to wysokość środka optycznego, punkt (x0, y0) odnosi się do współrzędnych powstałych z przecięcia osi optycznej kamery i płaszczyzny obrazu. Fizyczny wymiar piksela kamery zawarty jest w równaniu jako dx i dy. W takiej sytuacji:
$$d = \frac {h}{tan(\delta + arctan(\frac{y-y_0}{f}))}$$ (1)
$$u = \frac{x}{dx}+u_0$$ $$v = \frac {y}{dy}+v_0$$ (2)
$$u = \frac{x}{dx}+u_0$$ $$v = \frac {y}{dy}+v_0$$ (2)
Załóżmy, że $$y_0 = 0$$ oraz $$x_0 = 0$$; wtedy z równań (1) i (2) otrzymujemy:
$$d = \frac {h}{tan(\alpha + arctan(\frac{v-v_0}{a_y}))}]$$ (3)
Gdzie $$a_y = \frac{f}{dy}$$, a v to współrzędne na obrazie w osi y - parametr ten dany jest z algorytmu detekcji obiektów na obrazie. Pozostałe parametry są znane i wynikają z wykorzystanej kamery.
OpenCV umożliwia kalibrację kamery. Matryca kamery ma rozdzielczość 5 MP. W idealnym przypadku parametry a_x i a_y są sobie równe, ich ewentualne różnice wynikać będą z faktu, że piksele w matrycy nie są prostokątne. Pokazana poniżej macierz pokazuje, że moduł kamery zintegrowany z obiektywem o stałej ogniskowej, zapewnia dobre rezultaty, jeśli chodzi o kompensację zniekształceń obrazu.
Powyższa macierz zwraca wyniki w pikselach, a h mierzone jest w centymetrach, równanie (3) pozwala na wyliczenie odległości d, także w centymetrach.
Moduł kontroli samochodu RC
Wykorzystany samochodzik wyposażono w bardzo proste sterowanie. Odbywa się ono poprzez naciskanie przycisków, które powoduje zwieranie pinów układu kontrolującego do masy. Moduł Arduino podłączono do układu tak, aby udawał naciskanie przycisków, zwierając odpowiednie piny do masy. Wykorzystano cztery wyjścia cyfrowe modułu Arduino, które odpowiadają czterem akcjom - ruchowi do przodu i do tyłu oraz skrętom na boki. Moduł Arduino wystawia po prostu na odpowiednim pinie stan niski, gdy samochodzik ma pojechać w dowolnym kierunku. Moduł jest podłączony do komputera poprzez USB, a komputer przesyła do niego dane poprzez interfejs szeregowy emulowany na USB.
Wyniki
Jak pokazały testy algorytm rozpoznaje obiekty z dokładnością około 85%. Dla rozpoznawania obiektów na zbiorze uczącym dokładność ta wynosi 96%. Podczas normalnej pracy algorytm analizuje obraz około 10 razy na sekundę, co jest związane z szybkością nadawania strumienia wideo - 10 klatek na sekundę.
Wykorzystanie klasyfikatora Haara powoduje, że system rozpoznawania obrazów jest czuły na obrót obiektów, jednakże w opisanym przypadku nie jest to problemem, gdyż rozpoznawane obiekty - znak stopu i światła drogowe - zawsze umieszczane są w tej samej pozycji.
Jeśli chodzi o pomiar odległości, sensor ultradźwiękowy jest w stanie mierzyć odległość tylko od przedmiotów znajdujących się bezpośrednio przed pojazdem. Zwraca on dokładne wyniki tylko, gdy działa pod odpowiednim kątem, a powierzchnia, od której mierzy się odległość dobrze odbija ultradźwięki. Wyniki pomiaru odległości na podstawie obrazów autor opisuje jako "dość dobre" - to znaczy wystarczające na potrzeby opisywanego projektu. Poniżej zaprezentowano eksperymentalne dane pochodzące z testów układu.
Na pokazanych powyżej przykładach na dokładność pomiaru odległości wpływ ma szereg czynników: błędy pomiarowe, wariancja obrysu detekowanego przez algorytm obiektu, błędy na etapie kalibracji kamery i nieliniowa zależność pomiędzy współrzędnymi a odległością - im większa odległość, tym szybciej zmieniają się współrzędne kamery, generując większy błąd.
Autor mimo pewnych niedoskonałości projektu jest z niego bardzo zadowolony. Stworzony pojazd jest w stanie bez problemu poruszać się, unikając zderzeń i reagować na napotykane znaki STOPu i światła drogowe.
Źródło: https://zhengludwig.wordpress.com/projects/self-driving-rc-car/
Cool! Ranking DIY