OpenCV uruchamiany jest głównie na wysokowydajnych platformach obliczeniowych czy mocnych mikroprocesorach, ale pakiet ten może wykonywać kilka rodzajów aplikacji do przetwarzania obrazu na prostych mikrokontrolerach.
Przetwarzanie obrazu stało się częścią naszego życia. Nikogo nie dziwi rozpoznawanie twarzy w smartfonie czy wykrywanie pasa ruchu przez samochód. Obecnie najpowszechniejszą biblioteką wykorzystywaną do tych celów jest OpenCV. Obecnie OpenCV koncentruje się głównie na platformach i mikroprocesorach o wysokiej wydajności (HPC). Chociaż mikrokontrolery wyższej klasy mają zasoby porównywalne z procesorem Pentium II, nadal bardzo rzadko uruchamia się na nich programy wykorzystujące OpenCV.
Jakiś czas temu pokazano już, że istnieje możliwość wykorzystania OpenCV na układach z rodziny STM32 (i innych mikrokontrolerach podobnej klasy). Celem tego artykułu jest zademonstrowanie użycia tej biblioteki na podobnych platformach sprzętowych. Mimo że uzyskano w testach bardzo niską wydajność, to jeszcze do niedawna nie wiedziano, jaka jest przyczyna tego stanu rzeczy. W tym artykule poprawiono oczywiste niedociągnięcia pierwszych testów. Pozwala to osiągnąć wyższą wydajność. Dodatkowo, w poniższym artykule przedstawiono wyniki pomiarów wydajności dla różnych przykładów wykorzystania OpenCV na platformie STM32F7.
Wszystkie przykłady w artykule są oparte na systemie Ebox RTOS i można je odtworzyć, postępując zgodnie z instrukcjami w repozytorium z przykładami. W przykładach używana jest flaga optymalizacji -Os. Wszystkie przykłady używają włączonej pamięci podręcznej procesora. Pliki danych mogą znajdować się na karcie SD. Obrazy przechowywane są w pamięci Flash QSPI, który znajduje się na płytce deweloperskiej, aby uprościć podstawowe instrukcje podczas odtwarzania wyników.
Wykorzystano płytkę demonstracyjną STM32F769i-Discovery. Na płytce znajdują się dwa rodzaje pamięci ROM: 2 MB wbudowanej pamięci Flash i 64 MB zewnętrznej pamięci Flash QSPI. Ponadto dostępne są dwa typy pamięci RAM: 512+16+4 KB na chipie i 16 MB zewnętrznej pamięci SDRAM.
Wykrywanie krawędzi
Zacznijmy przykładu, który był już wcześniej testowany, a mianowicie wykrywania krawędzi. W przykładzie zastosowano algorytm Canny'ego. W artykule prezentowane jest kompletne wyjście z programu dla tego procesu. Dla pozostałych przykładów zawarte są tylko tabelki z porównaniem wyników.
Próbka analizowanego obrazu:
K-means
Ten przykład z OpenCV określa klastry punktów i kreśli koło dookoła nich, opierając się na miarze, którą OpenCV opisuje jako kompaktowość ("compactness") - sumę kwadratów odległości każdego puntu od środka tego okręgu. Zasadniczo jest to metoda, która pozwala na określenie "środka masy" dla punktów.
Skrypt kmeans.cpp generuje obraz o rozdzielczości 480 x 480 z kilkoma klastrami punktów o różnym kolorze. Środek każdego z klastrów jest wybierany losowo, a punkty dodawane są w odległości opisywanej rozkładem normalnym.
Kwadraty
Rozpoznawanie kształtów geometrycznych, w szczególności prostokątów, to jeden ze standardowych przykładów z biblioteki OpenCV. Przykład analizowanego obrazka (pic6.png w tabelce) pokazano poniżej.
Wyniki dla analizy obrazków o rozdzielczości 400×300 umieszczono w poniższej tabelce:
Wykrywanie twarzy
Rozpoznawanie twarzy było pierwotnie przedstawionym celem badań. Chciano oszacować, jak dobrze podobne algorytmy działają na płytkach z mikrokontrolerami. Skorzystano ze standardowego przykładu „wykrywania twarzy” z zestawem pięciu obrazów. Przykłady wykorzystują wykrywanie kaskadowe Haara. Poniżej pokazano przykładowy analizowany obraz:
Rezultaty dla obrazów o rozdzielczości 256×256:
Rezultaty dla obrazów o rozdzielczości 480×480:
Wykrywanie osób
Autorzy testów chcieli także uruchomić bardziej złożone algorytmy, takie jak wykrywanie ludzi. W tym celu uruchomili przykładowy skrypt "peopledetect’ z OpenCV, który oparty jest na analizie histogramów zorientowanych gradientów (HOG). Poniżej pokazano przykładowy obraz:
Wyniki testów:
Kody QR
Kody QR są szeroko wykorzystywane do zapisy informacji, które można łatwo odczytywać. Do analizy kodu QR wykorzystuje się algorytmy rozpoznawania kształtów. W tym przykładzie wykorzystano QR w formie kwadratu, otoczonego ramką. System tyko wykrywa lokalizację kodu, ale w tym przykładzie nie analizuje jego zawartości. Przykładowe zdjęcie zostało pobrane z Internetu.
Wynik:
W tym przykładzie użyto różnych wywołań funkcji, więc do końcowego obrazu wstawiany jest inny kod. Dlatego, gdy próbowano zbudować ten skrypt, nie mógł on korzystać z wewnętrznej pamięci Flash i z tego powodu wyniki pochodzą tylko z analizy z wykorzystaniem danych z QSPI.
Specyfika pracy na mikrokontrolerach
Jest kilka godnych uwagi aspektów, które autorzy porównania wykryli, podczas pracy z OpenCV na mikrokontrolerach. Po pierwsze, kod z pamięci wewnętrznej działa szybciej niż z zewnętrznej pamięci Flash QSPI, nawet przy włączonej pamięci podręcznej.
Drugim, ich zdaniem, również powiązanym z pamięcią podręczną, jest zależność wydajności od lokalizacji kodu. Okazuje się, że drobne zmiany w kodzie, takie jak wstawienie polecenia, które nie jest wywoływane, może zwiększyć lub zmniejszyć wydajność nawet o 5% lub więcej.
Trzeci to ograniczony rozmiar pamięci wewnętrznej. Nie było możliwe szybkie uruchomienie przykładu z wykrywaniem kodów QR z wewnętrznej pamięci Flash.
Kolejna ważna cecha dotyczy samych rdzeni ARM Cortex-M. Wykorzystywano rdzenie procesora obsługujące instrukcje SIMD. Technologia ta pomaga zwiększyć wydajność, wykonując tę samą operację na wielu punktach danych w jednym rejestrze jednocześnie. Aby oszacować, czy ma to wpływ na wydajność w podobnych zadaniach, przeprowadzono pomiary w systemie operacyjnym Linux z obsługą instrukcji SIMD i bez niej i stwierdzono, że w niektórych przykładach, takich jak wykrywanie kwadratów, użycie SIMD zwiększa wydajność nawet o 80%, jednak przyspieszenie zależne jest od zastosowanego algorytmu.
W przypadku wykorzystanych rdzeni procesora istnieje tylko wsparcie w postaci funkcji wewnętrznych. Innymi słowy, konieczne jest ręczne wstawienie tych poleceń. OpenCV wspiera to podejście - można zaimplementować obsługę SIMD dla niestandardowej architektury. Ale w tej chwili obsługa OpenCV w SIMD jest zaprojektowana do pracy tylko z długimi typami danych (128 bitów i więcej), podczas gdy rdzeń Cortex-M7 obsługuje tylko rejestry 32-bitowe. W związku z tym praca ta nie wykorzystuje poprawy wydajności podczas korzystania z SIMD na STM32. Autorzy porównania mają jednak nadzieję, że będzie to kierunek ich przyszłych badań.
Podsumowanie
Wyniki te wskazują, że bardzo złożone oprogramowanie, takie jak OpenCV, może być używane na małych mikrokontrolerach. Kilka przykładów zostało uruchomionych i wszystkie działały pomyślnie. Jednak wydajność jest zauważalnie niższa niż w przypadku większych platform.
Wykorzystanie OpenCV na mikrokontrolerach jest silnie uzależnione od celów. Większość podstawowych algorytmów działa niezauważalnie dla oka. Wykrywanie krawędzi realizuje się w ułamku sekundy; ta wydajność może wystarczyć autonomicznemu robotowi. Można również zastosować złożone algorytmy, takie jak przetwarzanie kodów QR, ale konieczna jest każdorazowa ocena zalet i wad takiego rozwiązania. Z jednej strony 3 sekundy wymagane do zakończenia wykrywania twarzy mogą być dla niektórych aplikacji długim czasem, ale z drugiej strony dla niektórych celów może być to wystarczająco szybkie.
Dlatego okazuje się, że takie platformy nie są jeszcze wystarczająco wydajne, aby rozpoznawać złożone obiekty, na przykład identyfikować osobę. Opóźnienie jest bardzo zauważalne w porównaniu z rozpoznawaniem tego samego obrazu na większym systemie. Musimy jednak również zrozumieć, że w tym badaniu porównano mikrokontrolery z 64-bitowym procesorem Intel-i7 z 8 rdzeniami i zasadniczo inną częstotliwością taktowania - zużycie energii i koszt tych platform są oczywiście zupełnie inne. Poza tym porównanie nie dotyczyło najpotężniejszego mikrokontrolera - STM32 ma serię H7, która ma ponad dwukrotnie większą wydajność niż testowane tutaj elementy.
Na poniższym filmie przedstawiono część testów wykonanych w ramach opisywanego badania:
Powielanie wyników
Możesz odtworzyć wyniki uzyskane w artykule. Potrzebujesz do tego dwóch repozytoriów. Główne repozytorium Ebox (Link) oraz repozytorium z przykładowymi obrazami i gotowymi konfiguracjami dla płyty STM32F769i-discovery (Link). Aby odtworzyć wyniki, postępuj zgodnie z instrukcjami w pliku README z repozytorium próbek.
Można również użyć innych płyt, jednak konieczne może być przygotowanie konkretnej konfiguracji Emboxa dla tych modułów. Można również eksperymentować z innymi obrazami lub przechowywać obrazy na karcie SD, ale wymaga to również zmiany konfiguracji Emboxa.
Źródło: https://www.embedded.com/benchmarking-opencv-on-stm32-mcus/
Przetwarzanie obrazu stało się częścią naszego życia. Nikogo nie dziwi rozpoznawanie twarzy w smartfonie czy wykrywanie pasa ruchu przez samochód. Obecnie najpowszechniejszą biblioteką wykorzystywaną do tych celów jest OpenCV. Obecnie OpenCV koncentruje się głównie na platformach i mikroprocesorach o wysokiej wydajności (HPC). Chociaż mikrokontrolery wyższej klasy mają zasoby porównywalne z procesorem Pentium II, nadal bardzo rzadko uruchamia się na nich programy wykorzystujące OpenCV.
Jakiś czas temu pokazano już, że istnieje możliwość wykorzystania OpenCV na układach z rodziny STM32 (i innych mikrokontrolerach podobnej klasy). Celem tego artykułu jest zademonstrowanie użycia tej biblioteki na podobnych platformach sprzętowych. Mimo że uzyskano w testach bardzo niską wydajność, to jeszcze do niedawna nie wiedziano, jaka jest przyczyna tego stanu rzeczy. W tym artykule poprawiono oczywiste niedociągnięcia pierwszych testów. Pozwala to osiągnąć wyższą wydajność. Dodatkowo, w poniższym artykule przedstawiono wyniki pomiarów wydajności dla różnych przykładów wykorzystania OpenCV na platformie STM32F7.
Wszystkie przykłady w artykule są oparte na systemie Ebox RTOS i można je odtworzyć, postępując zgodnie z instrukcjami w repozytorium z przykładami. W przykładach używana jest flaga optymalizacji -Os. Wszystkie przykłady używają włączonej pamięci podręcznej procesora. Pliki danych mogą znajdować się na karcie SD. Obrazy przechowywane są w pamięci Flash QSPI, który znajduje się na płytce deweloperskiej, aby uprościć podstawowe instrukcje podczas odtwarzania wyników.
Wykorzystano płytkę demonstracyjną STM32F769i-Discovery. Na płytce znajdują się dwa rodzaje pamięci ROM: 2 MB wbudowanej pamięci Flash i 64 MB zewnętrznej pamięci Flash QSPI. Ponadto dostępne są dwa typy pamięci RAM: 512+16+4 KB na chipie i 16 MB zewnętrznej pamięci SDRAM.
Wykrywanie krawędzi
Zacznijmy przykładu, który był już wcześniej testowany, a mianowicie wykrywania krawędzi. W przykładzie zastosowano algorytm Canny'ego. W artykule prezentowane jest kompletne wyjście z programu dla tego procesu. Dla pozostałych przykładów zawarte są tylko tabelki z porównaniem wyników.
Próbka analizowanego obrazu:
| Obraz | Czas przetwarzania przy wykorzystaniu wewnętrznej pamięci Flash (ms) | Czas przetwarzania przy wykorzystaniu zewnętrznej pamięci QSPI Flash (ms) | fruits.png 512×269 | 116 | 120 | fruits.png 512×480 | 254 | 260 |
K-means
Ten przykład z OpenCV określa klastry punktów i kreśli koło dookoła nich, opierając się na miarze, którą OpenCV opisuje jako kompaktowość ("compactness") - sumę kwadratów odległości każdego puntu od środka tego okręgu. Zasadniczo jest to metoda, która pozwala na określenie "środka masy" dla punktów.
Skrypt kmeans.cpp generuje obraz o rozdzielczości 480 x 480 z kilkoma klastrami punktów o różnym kolorze. Środek każdego z klastrów jest wybierany losowo, a punkty dodawane są w odległości opisywanej rozkładem normalnym.
| Kompaktowość | Czas przetwarzania z pamięci ROM (ms) | Czas przetwarzania z pamięci QSPI (ms) | 733589 | 34 | 98 | 160406 | 6 | 18 | 331447 | 14 | 38 | 706280 | 13 | 36 | 399182 | 8 | 25 |
Kwadraty
Rozpoznawanie kształtów geometrycznych, w szczególności prostokątów, to jeden ze standardowych przykładów z biblioteki OpenCV. Przykład analizowanego obrazka (pic6.png w tabelce) pokazano poniżej.
Wyniki dla analizy obrazków o rozdzielczości 400×300 umieszczono w poniższej tabelce:
| Obraz | Czas przetwarzania z pamięci ROM (ms) | Czas przetwarzania z pamięci QSPI (ms) | pic1.png | 1312 | 1668 | pic2.png | 4893 | 7268 | pic3.png | 1263 | 1571 | pic4.png | 2351 | 3590 | pic5.png | 1235 | 1515 | pic6.png | 1575 | 2202 |
Wykrywanie twarzy
Rozpoznawanie twarzy było pierwotnie przedstawionym celem badań. Chciano oszacować, jak dobrze podobne algorytmy działają na płytkach z mikrokontrolerami. Skorzystano ze standardowego przykładu „wykrywania twarzy” z zestawem pięciu obrazów. Przykłady wykorzystują wykrywanie kaskadowe Haara. Poniżej pokazano przykładowy analizowany obraz:
Rezultaty dla obrazów o rozdzielczości 256×256:
| Obraz | Czas przetwarzania z pamięci ROM (ms) | Czas przetwarzania z pamięci QSPI (ms) | seq_256x256/img_000.png | 3389 | 3801 | seq_256x256/img_001.png | 4015 | 4454 | seq_256x256/img_002.png | 4016 | 4464 | seq_256x256/img_003.png | 3315 | 3717 | seq_256x256/img_004.png | 3526 | 3952 |
Rezultaty dla obrazów o rozdzielczości 480×480:
| Obraz | Czas przetwarzania z pamięci ROM (ms) | Czas przetwarzania z pamięci QSPI (ms) | seq_480x480/img_000.png | 14406 | 16149 | seq_480x480/img_001.png | 14784 | 16578 | seq_480x480/img_002.png | 15106 | 16904 | seq_480x480/img_003.png | 12695 | 14352 | seq_480x480/img_004.png | 14655 | 16446 |
Wykrywanie osób
Autorzy testów chcieli także uruchomić bardziej złożone algorytmy, takie jak wykrywanie ludzi. W tym celu uruchomili przykładowy skrypt "peopledetect’ z OpenCV, który oparty jest na analizie histogramów zorientowanych gradientów (HOG). Poniżej pokazano przykładowy obraz:
Wyniki testów:
| Obraz | Czas przetwarzania z pamięci ROM (ms) | Czas przetwarzania z pamięci QSPI (ms) | basketball2.png 640×480 | 40347 | 52587 |
Kody QR
Kody QR są szeroko wykorzystywane do zapisy informacji, które można łatwo odczytywać. Do analizy kodu QR wykorzystuje się algorytmy rozpoznawania kształtów. W tym przykładzie wykorzystano QR w formie kwadratu, otoczonego ramką. System tyko wykrywa lokalizację kodu, ale w tym przykładzie nie analizuje jego zawartości. Przykładowe zdjęcie zostało pobrane z Internetu.
Wynik:
| Obraz | Czas przetwarzania z pamięci ROM (ms) | Czas przetwarzania z pamięci QSPI (ms) | qrcode_600x442.png | – | 3092 |
W tym przykładzie użyto różnych wywołań funkcji, więc do końcowego obrazu wstawiany jest inny kod. Dlatego, gdy próbowano zbudować ten skrypt, nie mógł on korzystać z wewnętrznej pamięci Flash i z tego powodu wyniki pochodzą tylko z analizy z wykorzystaniem danych z QSPI.
Specyfika pracy na mikrokontrolerach
Jest kilka godnych uwagi aspektów, które autorzy porównania wykryli, podczas pracy z OpenCV na mikrokontrolerach. Po pierwsze, kod z pamięci wewnętrznej działa szybciej niż z zewnętrznej pamięci Flash QSPI, nawet przy włączonej pamięci podręcznej.
Drugim, ich zdaniem, również powiązanym z pamięcią podręczną, jest zależność wydajności od lokalizacji kodu. Okazuje się, że drobne zmiany w kodzie, takie jak wstawienie polecenia, które nie jest wywoływane, może zwiększyć lub zmniejszyć wydajność nawet o 5% lub więcej.
Trzeci to ograniczony rozmiar pamięci wewnętrznej. Nie było możliwe szybkie uruchomienie przykładu z wykrywaniem kodów QR z wewnętrznej pamięci Flash.
Kolejna ważna cecha dotyczy samych rdzeni ARM Cortex-M. Wykorzystywano rdzenie procesora obsługujące instrukcje SIMD. Technologia ta pomaga zwiększyć wydajność, wykonując tę samą operację na wielu punktach danych w jednym rejestrze jednocześnie. Aby oszacować, czy ma to wpływ na wydajność w podobnych zadaniach, przeprowadzono pomiary w systemie operacyjnym Linux z obsługą instrukcji SIMD i bez niej i stwierdzono, że w niektórych przykładach, takich jak wykrywanie kwadratów, użycie SIMD zwiększa wydajność nawet o 80%, jednak przyspieszenie zależne jest od zastosowanego algorytmu.
W przypadku wykorzystanych rdzeni procesora istnieje tylko wsparcie w postaci funkcji wewnętrznych. Innymi słowy, konieczne jest ręczne wstawienie tych poleceń. OpenCV wspiera to podejście - można zaimplementować obsługę SIMD dla niestandardowej architektury. Ale w tej chwili obsługa OpenCV w SIMD jest zaprojektowana do pracy tylko z długimi typami danych (128 bitów i więcej), podczas gdy rdzeń Cortex-M7 obsługuje tylko rejestry 32-bitowe. W związku z tym praca ta nie wykorzystuje poprawy wydajności podczas korzystania z SIMD na STM32. Autorzy porównania mają jednak nadzieję, że będzie to kierunek ich przyszłych badań.
Podsumowanie
Wyniki te wskazują, że bardzo złożone oprogramowanie, takie jak OpenCV, może być używane na małych mikrokontrolerach. Kilka przykładów zostało uruchomionych i wszystkie działały pomyślnie. Jednak wydajność jest zauważalnie niższa niż w przypadku większych platform.
Wykorzystanie OpenCV na mikrokontrolerach jest silnie uzależnione od celów. Większość podstawowych algorytmów działa niezauważalnie dla oka. Wykrywanie krawędzi realizuje się w ułamku sekundy; ta wydajność może wystarczyć autonomicznemu robotowi. Można również zastosować złożone algorytmy, takie jak przetwarzanie kodów QR, ale konieczna jest każdorazowa ocena zalet i wad takiego rozwiązania. Z jednej strony 3 sekundy wymagane do zakończenia wykrywania twarzy mogą być dla niektórych aplikacji długim czasem, ale z drugiej strony dla niektórych celów może być to wystarczająco szybkie.
Dlatego okazuje się, że takie platformy nie są jeszcze wystarczająco wydajne, aby rozpoznawać złożone obiekty, na przykład identyfikować osobę. Opóźnienie jest bardzo zauważalne w porównaniu z rozpoznawaniem tego samego obrazu na większym systemie. Musimy jednak również zrozumieć, że w tym badaniu porównano mikrokontrolery z 64-bitowym procesorem Intel-i7 z 8 rdzeniami i zasadniczo inną częstotliwością taktowania - zużycie energii i koszt tych platform są oczywiście zupełnie inne. Poza tym porównanie nie dotyczyło najpotężniejszego mikrokontrolera - STM32 ma serię H7, która ma ponad dwukrotnie większą wydajność niż testowane tutaj elementy.
Na poniższym filmie przedstawiono część testów wykonanych w ramach opisywanego badania:
Powielanie wyników
Możesz odtworzyć wyniki uzyskane w artykule. Potrzebujesz do tego dwóch repozytoriów. Główne repozytorium Ebox (Link) oraz repozytorium z przykładowymi obrazami i gotowymi konfiguracjami dla płyty STM32F769i-discovery (Link). Aby odtworzyć wyniki, postępuj zgodnie z instrukcjami w pliku README z repozytorium próbek.
Można również użyć innych płyt, jednak konieczne może być przygotowanie konkretnej konfiguracji Emboxa dla tych modułów. Można również eksperymentować z innymi obrazami lub przechowywać obrazy na karcie SD, ale wymaga to również zmiany konfiguracji Emboxa.
Źródło: https://www.embedded.com/benchmarking-opencv-on-stm32-mcus/
Fajne? Ranking DIY
