DZWON

Są tacy, którzy czytają tę wiadomość przed tobą.
Zapisz się, aby otrzymywać najnowsze artykuły.
E-mail
Imię
Nazwisko
Jak chcesz przeczytać The Bell
Bez spamu

Podczas rozwiązywania problemów z widzeniem komputerowym nie można obejść się bez użycia specjalistycznego oprogramowania. Chcę wam przedstawić to - OpenCV - bibliotekę open source w C ++. Posiada zestaw narzędzi do digitalizacji obrazu, późniejszego przetwarzania za pomocą algorytmów numerycznych lub sieci neuronowej.

Podstawowe algorytmy przetwarzania obrazu: interpretacja obrazu, kalibracja kamery względem wzorca, eliminacja zniekształceń optycznych, wykrywanie podobieństwa, analiza ruchu obiektu, określanie kształtu i śledzenie obiektu, rekonstrukcja 3D, segmentacja obiektów, rozpoznawanie gestów.

Możesz pobrać bibliotekę z oficjalnej strony http://sourceforge.net/projects/opencvlibrary/

Struktura biblioteki OpenCV

cxcore - rdzeń
* zawiera podstawowe struktury danych i algorytmy:
- podstawowe operacje na wielowymiarowych tablicach numerycznych
- algebra macierzy, funkcje matematyczne, generatory liczb losowych
- Zapisywanie / przywracanie struktur danych do / z XML
- podstawowe funkcje grafiki 2D

CV - moduł przetwarzania obrazu i wizji komputerowej
- podstawowe operacje na obrazach (filtrowanie, przekształcenia geometryczne, przekształcanie przestrzeni barw itp.)
- analiza obrazu (dobór cech charakterystycznych, morfologia, poszukiwanie konturów, histogramy)
- analiza ruchu, śledzenie obiektów
- wykrywanie obiektów, w szczególności twarzy
- kalibracja kamer, elementy odbudowy struktury przestrzennej

Highgui - moduł do wejścia / wyjścia obrazu i wideo, tworzenia interfejsu użytkownika
- przechwytywanie wideo z kamer i plików wideo, odczytywanie / zapisywanie obrazów statycznych.
- funkcje do organizowania prostego interfejsu użytkownika (wszystkie aplikacje demonstracyjne używają HighGUI)

Cvaux - funkcje eksperymentalne i przestarzałe
- spacje. wizja: kalibracja stereo, samokalibracja
- wyszukiwanie dopasowania stereo, klikanie na wykresach
- znajdowanie i opisywanie rysów twarzy

CvCam - przechwytywanie wideo
- pozwala na przechwytywanie wideo z cyfrowych kamer wideo (wsparcie zostało przerwane iw ostatnich wersjach brakuje tego modułu)


Instalowanie OpenCV w systemie Linux

Po pobraniu najnowszej wersji OpenCV ze strony programisty http://sourceforge.net/projects/opencvlibrary/, musisz rozpakować archiwum i skompilować za pomocą CMake w wersji 2.6 lub wyższej.

Instalowanie CMake jest standardem:

Sudo apt-get install cmake

Aby wyświetlić okna OpenCV, musisz zainstalować biblioteki GTK + 2.x i libgtk2.0-dev

Apt-get install libgtk2.0-dev

Budowa biblioteki:

Tar -xjf OpenCV-2.2.0.tar.bz2 cd OpenCV-2.2.0 cmake -D CMAKE_BUILD_TYPE \u003d RELEASE -D CMAKE_INSTALL_PREFIX \u003d / usr / local ./ make make install

Aby przetestować zainstalowaną bibliotekę, możesz zbudować przykłady i uruchomić coś:

Próbki CD / c / chmod + x build_all.sh ./build_all.sh ./delaunay

Jeśli zamiast obrazu testowego pojawi się błąd „błąd podczas ładowania bibliotek współdzielonych: libopencv_core.so.2.2: nie można otworzyć pliku obiektu współdzielonego: nie ma takiego pliku lub katalogu”, oznacza to, że program nie może znaleźć bibliotek. Musisz jawnie określić ścieżkę do nich:

$ export LD_LIBRARY_PATH \u003d / usr / local / lib: $ LD_LIBRARY_PATH

Jeśli po tym znowu błąd:
Błąd OpenCV: nieokreślony błąd (Funkcja nie jest zaimplementowana. Odbuduj bibliotekę z obsługą Windows, GTK + 2.x lub Carbon. Jeśli korzystasz z Ubuntu lub Debian, zainstaluj libgtk2.0-dev i pkg-config, a następnie ponownie uruchom cmake or configure script) w cvNamedWindow, plik /usr/src/OpenCV-2.2.0/modules/highgui/src/window.cpp, linia 274 kończy się wywoływana po rzuceniu instancji „cv :: Exception” what (): / usr /src/OpenCV-2.2.0/modules/highgui/src/window.cpp:274: błąd: (-2) Funkcja nie jest zaimplementowana. Odbuduj bibliotekę z obsługą Windows, GTK + 2.x lub Carbon. Jeśli korzystasz z systemu Ubuntu lub Debian, zainstaluj libgtk2.0-dev i pkg-config, a następnie ponownie uruchom cmake lub skonfiguruj skrypt w funkcji cvNamedWindow
Więc zapomniałeś zainstalować GTK + 2.x: libgtk2.0-dev. Uruchom instalację (patrz wyżej).

Po zakończeniu instalacji pliki nagłówkowe będą dostępne w katalogu / usr / local / include / opencv, a pliki bibliotek w / usr / local / lib

Zbudujmy program z OpenCV:

test.cpp

// // do testowania // // robocraft.ru // #include #zawierać #zawierać #zawierać int main (int argc, char * argv) (IplImage * image \u003d 0, * dst \u003d 0; // nazwa obrazu char filename \u003d "Image0.jpg"; // pobierz obraz image \u003d cvLoadImage (filename, 1); printf ( "[i] image:% s \\ n", filename); assert (image! \u003d 0); // pokaż obraz cvNamedWindow ("image"); cvShowImage ("image", image); // poczekaj na naciśnięcie klawisza cvWaitKey ( 0); // wolne zasoby cvReleaseImage (& image); cvReleaseImage (& dst); // usuń okna cvDestroyAllWindows (); return 0;)

Makefile

CC: \u003d g ++ CFLAGS: \u003d -I / usr / local / include / opencv -L / usr / local / lib OBIEKTY: \u003d BIBLIOTEKI: \u003d -lopencv_core -lopencv_imgproc -lopencv_highgui. FONIA: wszystko czyste wszystko: test test: $ (CC ) $ (CFLAGS) -o test test.cpp $ (LIBRARIES) clean: rm -f * .o

Rozpocznij kompilację za pomocą polecenia make.


Witaj świecie!

OpenCV jest zainstalowany i gotowy do pracy. Napiszmy naszą pierwszą aplikację Hello World!

#zawierać #zawierać int main (int argc, char ** argv) (// ustaw wysokość i szerokość obrazu int height \u003d 620; int width \u003d 440; // ustaw punkt wyświetlania tekstu CvPoint pt \u003d cvPoint (height / 4, width / 2); // Utwórz 8-bitowy, 3-kanałowy obraz IplImage * hw \u003d cvCreateImage (cvSize (height, width), 8, 3); // wypełnij obraz czarnym cvSet (hw, cvScalar (0,0,0)); / / inicjalizacja czcionki CvFont font; cvInitFont (& font, CV_FONT_HERSHEY_COMPLEX, 1.0, 1.0, 0, 1, CV_AA); // używając czcionki wyświetlamy tekst na obrazku cvPutText (hw, "OpenCV Step by Step", pt, & font, CV_RGB (150, 0, 150)); // utwórz okno cvNamedWindow ("Hello World", 0); // pokaż obrazek w utworzonym oknie cvShowImage ("Hello World", hw); // poczekaj na naciśnięcie klawisza cvWaitKey (0); // zwolnij zasoby cvReleaseImage (& hw); cvDestroyWindow ("Hello World"); return 0;)

Ładowanie obrazu

Ten przykład będzie podstawą dla wszystkich twoich programów OpenCV. Wczytujemy obraz z pliku Image0.jpg do środowiska.

#zawierać #zawierać #zawierać #zawierać IplImage * image \u003d 0; IplImage * src \u003d 0; int main (int argc, char * argv) (// nazwa obrazka jest ustawiana przez pierwszy parametr char * filename \u003d argc \u003d\u003d 2? argv: "Image0.jpg"; // pobierz obrazek image \u003d cvLoadImage (filename, 1); // sklonuj obraz src \u003d cvCloneImage (obraz); printf ("[i] obraz:% s \\ n", nazwa pliku); assert (src! \u003d 0); // okno do wyświetlania obrazu cvNamedWindow ("original", CV_WINDOW_AUTOSIZE); / / pokaż obraz cvShowImage ("oryginał", obraz); // wypisz informacje o obrazku do konsoli printf ("[i] kanały:% d \\ n", obraz-\u003e nChannels); printf ("[i] głębia pikseli:% d bitów \\ n ", obraz-\u003e głębia); printf (" [i] szerokość:% d pikseli \\ n ", obraz-\u003e szerokość); printf (" [i] wysokość:% d piksele \\ n ", obraz- \u003e wysokość); printf ("[i] rozmiar obrazu:% d bajtów \\ n", image-\u003e imageSize); printf ("[i] width step:% d bytes \\ n", image-\u003e widthStep); // poczekaj na klawisz naciśnij cvWaitKey (0); // zwolnij zasoby cvReleaseImage (& image); cvReleaseImage (& src); // usuń okno cvDestroyWindow ("original"); return 0;)

Obsługiwane typy formatów obrazu:

  • Mapy bitowe Windows - BMP, DIB
  • Pliki JPEG - JPEG, JPG, JPE
  • Przenośna grafika sieciowa - PNG
  • Przenośny format obrazu - PBM, PGM, PPM
  • Rastry słoneczne - SR, RAS
  • Pliki TIFF - TIFF, TIF

Aby uzyskać dostęp do obrazu, możesz wykonać następujące połączenia:

Obraz-\u003e nChannels // liczba kanałów obrazu (RGB, chociaż w OpenCV - BGR) (1-4) obraz-\u003e głębokość // głębokość w bitach obraz-\u003e szerokość // szerokość obrazka w pikselach obraz-\u003e wysokość // wysokość obrazka w pikselach image-\u003e imageSize // pamięć zajmowana przez obraz (\u003d\u003d image-\u003e height * image-\u003e widthStep) image-\u003e widthStep // odległość między pionowo sąsiednimi punktami obrazu (liczba bajtów w jednej linii obrazu - może być wymagana do samodzielnego przejścia wszystkie piksele obrazu)

Prześlij wideo

Ładowanie wideo nie jest dużo trudniejsze niż ładowanie obrazu, z wyjątkiem tego, że będzie pętla przechodząca przez klatki.
Opóźnienie między ramkami jest ustawione na 33 milisekundy. to opóźnienie umożliwia przetwarzanie strumienia wideo ze standardową szybkością 30 klatek na sekundę.

#zawierać #zawierać #zawierać #zawierać IplImage * frame \u003d 0; int main (int argc, char * argv) (// nazwa pliku jest określona przez pierwszy parametr char * filename \u003d argc \u003d\u003d 2? argv: "test.avi"; printf ("[i] file:% s \\ n", nazwa pliku ); // okno do wyświetlenia obrazu cvNamedWindow ("original", CV_WINDOW_AUTOSIZE); // pobierz informacje o pliku wideo CvCapture * capture \u003d cvCreateFileCapture (filename); while (1) (// pobierz następną klatkę frame \u003d cvQueryFrame (capture) ; if (! frame) (break;) // tutaj możesz wstawić // procedurę przetwarzania // pokaż ramkę cvShowImage ("original", frame); char c \u003d cvWaitKey (33); if (c \u003d\u003d 27) (// jeśli wciśnięty jest ESC, zakończ przerwę;)) // zwolnij zasoby cvReleaseCapture (& capture); // usuń okno cvDestroyWindow ("original"); return 0;)

Aby przechwycić wideo z kamery, musisz nieco zmodyfikować kod - zamiast funkcji cvCreateFileCapture () zostanie użyta cvCreateCameraCapture (). Naciśnięcie ESC przerwie odtwarzanie i zamknie okno, a wciśnięcie Enter zapisze bieżącą klatkę do pliku jpg.

#zawierać #zawierać #zawierać #zawierać int main (int argc, char * argv) (// pobierz dowolną podłączoną kamerę CvCapture * capture \u003d cvCreateCameraCapture (CV_CAP_ANY); // cvCaptureFromCAM (0); assert (capture); // cvSetCaptureProperty (capture, CV_CAP_PROP_THFRAME) 640 / 1280); // cvSetCaptureProperty (przechwytywanie, CV_CAP_PROP_FRAME_HEIGHT, 480); // 960); // sprawdź szerokość i wysokość ramki double width \u003d cvGetCaptureProperty (capture, CV_CAP_PROP_FRAME_WIDTH); podwójna wysokość \u003d cvGetCaptureProperty (przechwytywanie, CV_CAP_PROP_FRAME_HEIGHT); printf ("[i]% .0f x% .0f \\ n", szerokość, wysokość); IplImage * frame \u003d 0; cvNamedWindow ("przechwytywanie", CV_WINDOW_AUTOSIZE); printf ("[i] naciśnij Enter, aby przechwycić obraz i Esc, aby zakończyć! \\ n \\ n"); int counter \u003d 0; nazwa pliku char; while (true) (// pobierz ramkę frame \u003d cvQueryFrame (capture); // show cvShowImage ("capture", frame); char c \u003d cvWaitKey (33); if (c \u003d\u003d 27) (// naciśnięto przerwę ESC; ) else if (c \u003d\u003d 13) (// Enter // zapisz ramkę do pliku sprintf (nazwa pliku, "Obraz% d.jpg", licznik); printf ("[i] przechwyć ...% s \\ n", filename); cvSaveImage (filename, frame); counter ++;)) // wolne zasoby cvReleaseCapture (& capture); cvDestroyWindow ("przechwytywanie"); return 0; )

OpenCV v1.0 wyświetla i zapisuje obraz z minimalną rozdzielczością kamery 320x240.


Rozpoznawanie obiektów według wzorca

Funkcja cvMatchTemplate () jest dostępna do rozpoznawania wzorców obszarów w obrazie źródłowym. Funkcja narzuca szablon obrazu na bieżący obraz i wyszukuje korelację między nimi zgodnie z wybranym algorytmem. Określenie granic znalezionego wzoru na oryginalnym obrazie jest wykonywane przez funkcję cvMinMaxLoc oraz w celu znormalizowania algorytmu wyszukiwania, cvNormalize ().

// // przykład cvMatchTemplate () // porównaj obraz z szablonem // #include #zawierać #zawierać #zawierać IplImage * image \u003d 0; IplImage * templ \u003d 0; int main (int argc, char * argv) (// nazwa obrazka jest określona przez pierwszy parametr char * filename \u003d argc\u003e \u003d 2? argv: "Image0.jpg"; // pobierz obrazek image \u003d cvLoadImage (filename, 1); printf ( "[i] obraz:% s \\ n", nazwa pliku); assert (obraz! \u003d 0); // znak szablonu * nazwa_pliku2 \u003d argc\u003e \u003d 3? argv: "oko.jpg"; printf ("[i] szablon :% s \\ n ", filename2); templ \u003d cvLoadImage (nazwa_pliku2,1); assert (templ! \u003d 0); cvNamedWindow (" origianl ", CV_WINDOW_AUTOSIZE); cvNamedWindow (" template ", CV_WINDOW_AUTOSIZE); cvNamedWind" , CV_WINDOW_AUTOSIZE); cvNamedWindow ("res", CV_WINDOW_AUTOSIZE); // rozmiar szablonu int width \u003d templ-\u003e width; int height \u003d templ-\u003e height; // oryginał i szablon cvShowImage ("origianl", obraz); cvShowImage (" template ", templ); // obraz do przechowywania wyniku porównania // rozmiar wyniku: jeśli obraz WxH i templ wxh, to result \u003d (W-w + 1) x (H-h + 1) IplImage * res \u003d cvCreateImage (cvSize ((obraz-\u003e szerokość-templ-\u003e szerokość + 1), (obraz-\u003e wysokość-templ-\u003e wysokość + 1)), IPL_DEPTH_32F, 1); // porównaj obrazek z szablonem cvMatchTemplate (obraz, szablon, res, CV_TM_SQDIFF); // pokaż, co mamy cvShowImage ("res", res); // określenie najlepszej pozycji do porównania // (wyszukanie minimów i maksimów na obrazku) double minval, maxval; CvPoint minloc, maxloc; cvMinMaxLoc (res, & minval, & maxval, & minloc, & maxloc, 0); // normalizuj cvNormalize (res, res, 1,0, CV_MINMAX); cvNamedWindow ("res norm", CV_WINDOW_AUTOSIZE); cvShowImage ("res norm", res); // zaznacz obszar za pomocą prostokąta cvRectangle (image, cvPoint (minloc.x, minloc.y), cvPoint (minloc.x + templ-\u003e width-1, minloc.y + templ-\u003e height-1), CV_RGB (255, 0 , 0), 1, 8); // pokaż obrazek cvShowImage ("Match", image); // czekaj na klawisz naciśnij cvWaitKey (0); // wolne zasoby cvReleaseImage (& image); cvReleaseImage (& templ); cvReleaseImage (& res); cvDestroyAllWindows (); return 0; )

Witaj! Stałem przed zadaniem zaimplementowania rozpoznawania znaków drogowych ze strumienia wideo. Ponieważ nie spotkałem się wcześniej z tego rodzaju zadaniami, sam proces wdrażania zakłada wstępne, długie „palenie” forów i bezlitosne kpienie z przykładów innych ludzi. Dlatego postanowiłem zebrać wszystko, co przeczytałem w jednym miejscu dla przyszłych pokoleń, a także w trakcie opowiadania zadać Habrowi kilka pytań.

Preludia.

Tak więc, po przestudiowaniu wszystkich narzędzi, które można wykorzystać do wykonania zadania, zdecydowałem się na środowisko programistyczne Microsoft Visual Studio © 2010, korzystając ze wspaniałej biblioteki OpenCV.

Sam proces pracy z OpenCV obejmuje tańce wstępne z tamburynem, o których są dość szczegółowe opisy:

Drugi akt tańca z tamburynem.

W efekcie zwróciłem się w stronę kaskad treningowych. Paląc w tym kierunku, zdałem sobie sprawę, że potrzebuję dwóch narzędzi do tworzenia balsamów i tresury. Ale nie miałem ich exe i odmówiłem kompilacji. W tym czasie wersja OpenCV, którą miałem, to 2.4.4, skonfigurowana programowo, w tym samym artykule, który po raz pierwszy przeczytałem o używaniu Cmake podczas instalacji. W rezultacie zdecydowałem się pobrać wersję 2.3.1 i ponownie zainstalować bibliotekę. Potem mogłem uruchomić niezbędne narzędzia za pomocą wiersza poleceń i pojawiło się pytanie, jak z nimi pracować. Wszystkie kropki nad „i” mają kropkowane artykuły, które pokazują parametry, z którymi należy uruchomić program createampes i haartraining wraz ze szczegółowym opisem tych parametrów.

Czysty kod.

Po całkowitym porzuceniu starej metody kod został przepisany, aby zastąpić wyuczone kaskady.

Kod 2.0

#include „stdafx.h” #include #zawierać #zawierać przy użyciu przestrzeni nazw cv; int main (int argc, char ** argv) (Mat frame, gray; string object_cascade \u003d "haarustupi.xml"; CascadeClassifier haar (object_cascade); VideoCapture cap (0); namedWindow ("Video", 1); vector przedmioty; while (true) (cap \u003e\u003e frame; cvtColor (ramka, szary, CV_BGR2GRAY); haar.detectMultiScale (gray, objects, 1.9, 10, 0, Size (50, 50)); for (vector :: const_iterator r \u003d objects.begin (); r! \u003d objects.end (); r ++) prostokąt (ramka, r-\u003e tl (), r-\u003e br (), Skalar (0, 0, 255)); imshow ("Wideo", ramka); if (waitKey (33)\u003e \u003d 0) przerwa; ) return (EXIT_SUCCESS); )

Środowisko konfigurujemy w taki sam sposób, jak w poprzednim projekcie.

Powtórzenia Jestem ojcami nauki.

Do „małych” należy trenowanie kaskad).
Tu zaczyna się zabawa. Wtedy postanowiłem napisać o tych wszystkich doświadczeniach na Habrze i poprosić o radę.
Przygotowałem 500 zdjęć w formacie 1600x1200. i jeden obraz ze znakiem 80x80. Wystarczy jeden obraz, bo wykrywamy konkretny obiekt, a nie dużą różnorodność twarzy.

A więc po przygotowaniu zdjęć i utworzeniu pliku neg.dat ze strukturą

Ujemny / n (1) .jpg Negatywny / n (2) .jpg Negatywny / n (3) .jpg Negatywny / n (4) .jpg ... Negatywny / n (500) .jpg

uruchom plik opencv_createsamples.exe przez CMD z następującymi parametrami

C: OpenCV2.3.1buildcommonx86opencv_createsamples.exe -vec C: OpenCV2.3.1buildcommonx86positive.vect -bg C: OpenCV2.3.1buildcommonx86neg.dat -img C: OpenCV2.3.1buildcommonx86ustupi.jpg -num 500 -wcolor -bgthresh 0 -show

parametr -show pokazuje wygenerowane pozytywne zdjęcia, ale w przeciwieństwie do tych wskazanych w innych artykułach
zdjęcia, okazuje się, że tak

mały

Oznacza to, że narzędzie przycina obraz bg do rozmiaru obrazu pozytywowego. Zmiana parametrów -w i -h nie przynosi żadnego efektu, a tło jest nadal prawie niewidoczne. Jeśli nagle ktoś wie, o co chodzi, podziel się swoimi przemyśleniami... Rozmiar negatywów został zmniejszony do 800x600 - ten sam wynik.

C: OpenCV2.3.1buildcommonx86opencv_haartraining.exe -data C: OpenCV2.3.1buildcommonx86haarustupi -vec C: OpenCV2.3.1buildcommonx86positive.vect -bg C: OpenCV2.3.1buildcommonx86neg.dat -npos 500n -nnegpl 20 -h 24-pamięć 1536-tryb ALL -nonsym -minhitrate 0,999 -maxfalsealarm 0,5

po czym otrzymasz długo oczekiwany plik xml, który można załadować do kodu źródłowego programu.
W rezultacie kaskada trochę się uczy i, przy dużej liczbie fałszywych alarmów, reaguje na mój ulubiony obraz znaku ustępowania.
Ale nie mogę uzyskać dokładnych odpowiedzi, jak mi się wydaje, ze względu na fakt, że tło jest przycięte na pozytywnych obrazach. A zdjęcia nie wyglądają jak w instrukcjach. Istnieje jednak możliwość zwiększenia ilości etapów treningowych i po załadowaniu komputera na cały dzień poczekać, aż kaskada będzie bardziej „wyedukowana”. To właśnie planuję zrobić, zanim pojawią się inne pomysły.

Epilog

To jest mój pierwszy artykuł HelloHabr. Czekam na Twoje uwagi dotyczące stylu prezentacji. I oczywiście wskazówki na ten temat.
Mam nadzieję, że po otrzymaniu porady będzie coś, co będzie kontynuowało historię.

Główną ideą jest uwzględnienie zależności statystycznych między lokalizacją punktów antropometrycznych twarzy. Na każdym zdjęciu twarzy punkty są numerowane w tej samej kolejności. Porównanie twarzy odbywa się na podstawie ich względnej pozycji.

Aby porównać twarze, możesz użyć tej samej pozycji twarzy względem aparatu. Bardziej korzystne do tego.

Przechwytywanie strumienia wideo z kamery i wybieranie twarzy

#zawierać przy użyciu przestrzeni nazw cv; int main () (// Załaduj kaskadę twarzy (plik .xml) CascadeClassifier face_cascade; face_cascade.load ("haarcascade_frontalface_alt2.xml"); Mat img; VideoCapture cap (0); while (true) (cap \u003e\u003e img; // cvtColor (img, img, CV_BGR2GRAY); // Wykryj twarze std :: vector twarze; face_cascade.detectMultiScale (img, faces, 1.1, 2, 0 | CV_HAAR_SCALE_IMAGE, rozmiar (30, 30)); // Rysuj okręgi na wykrytych twarzach dla (int i \u003d 0; i< faces.size(); i++) { Point center(faces[i].x + faces[i].width*0.5, faces[i].y + faces[i].height*0.5); ellipse(img, center, Size(faces[i].width*0.5, faces[i].height*0.5), 0, 0, 360, Scalar(255, 0, 255), 4, 8, 0); } imshow("Detected Face", img); waitKey(1); } return 0; }

Pliki kaskadowe znajdują się w katalogu c: \\ opencv \\ build \\ etc \\ ... Umieść wymaganą kaskadę w katalogu projektu, w tym samym miejscu, co plik źródłowy main.cpp.

Podkreślanie punktów twarzy

Aplikacja oparta jest na kodzie C ++ dla OpenCV Facemark

#zawierać #zawierać #zawierać #zawierać #zawierać #zawierać #include „drawLandmarks.hpp” using namespace std; przy użyciu przestrzeni nazw cv; używając przestrzeni nazw cv :: face; int main (int argc, char ** argv) (// Załaduj wykrywacz twarzy CascadeClassifier faceDetector ("haarcascade_frontalface_alt2.xml"); // Utwórz instancję Facemark Ptr facemark \u003d FacemarkLBF :: create (); // Załaduj facemark detektora punktów orientacyjnych-\u003e loadModel ("lbfmodel.yaml"); // Konfiguracja kamery internetowej do przechwytywania wideo VideoCapture cam (0); // Zmienna do przechowywania klatki wideo i jej skali szarości Ramka mat, szara; // Czytaj ramkę while (cam.read (frame)) (// Znajdź wektor twarzy twarze; // Konwertuj ramkę na skalę szarości, ponieważ // faceDetector wymaga obrazu w skali szarości. cvtColor (ramka, szary, COLOR_BGR2GRAY); // Wykryj twarze faceDetector.detectMultiScale (szary, twarze); // Zmienna dla punktów orientacyjnych. // Punkty orientacyjne dla jednej twarzy to wektor punktów // Na obrazie może znajdować się więcej niż jedna twarz. Dlatego // używamy wektora wektorów punktów. wektor< vector \u003e punkty orientacyjne; // Uruchom wykrywacz punktów orientacyjnych bool success \u003d facemark-\u003e< faces.size(); i++) { cv::rectangle(frame, faces[i], Scalar(0, 255, 0), 3); } for (int i = 0; i < landmarks.size(); i++) { drawLandmarks(frame, landmarks[i]); /*for (size_t j = 0; j < landmarks[i].size(); j++) circle(frame, Point(landmarks[i][j].x, landmarks[i][j].y), 1, Scalar(255, 0, 0), 2);*/ } } // Display results imshow("Facial Landmark Detection", frame); // Exit loop if ESC is pressed if (waitKey(1) == 27) break; } return 0; }

W projekcie aplikacji, w tym samym miejscu, co plik main.cpp, Wysłane pliki haarcascade_frontalface_alt2.xml, drawLandmarks.hpp i lbfmodel.yaml do których odwołuje się kod. Pliki kaskadowe znajdują się w katalogu c: \\ opencv \\ build \\ etc \\ .... drawLandmarks.hpp i lbfmodel.yaml dostępne w archiwum Facemark_LBF.rar.

Po wklejeniu kodu pojawiły się błędy związane z tym, że w OpenCV 3.4.3-vc14-vc15 brakuje kilku bibliotek potrzebnych do uruchomienia aplikacji. Połączyłem moją bibliotekę (pobierz opencv_new.zip) i zainstalowałem ją w katalogu głównym dysku C (C: \\ opencv-new).

Teraz wszystkie ustawienia, które zostały wykonane, muszą zostać wykonane dla opencv-new:

Dokonywanie ustawień w systemie Windows... Przechodzę do okna „Zmień zmienną środowiskową” (przyciski Windows -\u003e Narzędzia systemowe -\u003e Panel sterowania -\u003e System i zabezpieczenia -\u003e System -\u003e Zaawansowane ustawienia systemu -\u003e Zmienne środowiskowe -\u003e Ścieżka -\u003e Zmień). W tym oknie tworzę zmienną C: \\ opencv-new\\ x64 \\ vc14 \\ bin. Uruchom ponownie system Windows.

We właściwościach projektu odwołaj się również do biblioteki opencv_new (zamiast opencv). W oknie „Strony właściwości” wykonuję następujące czynności:

  • C / C ++ -\u003e Ogólne -\u003e Dodatkowe katalogi dołączania -\u003e C: \\ opencv-new\\ zawierać
  • Konsolidator -\u003e Ogólne -\u003e Dodatkowe katalogi biblioteczne -\u003e C: \\ opencv-new\\ x64 \\ vc14 \\ lib
  • Linker -\u003e Dane wejściowe -\u003e Dodatkowe zależności -\u003e opencv_core400.lib; opencv_face400.lib; opencv_videoio400.lib; opencv_objdetect400.lib; opencv_imgproc400.lib; opencv_highgui400.lib

Podczas uruchamiania program generuje błąd, jeśli w ustawieniach projektu Debug. W przypadku wydania, uruchomienie powiodło się.


Wybieranie funkcji filtrowania obrazu i rozpoznawania twarzy

Kropkowana ramka twarzy jest wyświetlana na różne sposoby w zależności od czynników obiektywnych i subiektywnych.

Czynniki obiektywne to pozycja twarzy w stosunku do aparatu.

Czynniki subiektywne - nierównomierne lub słabe oświetlenie, zniekształcenie twarzy spowodowane emocjami, mrużenie oczu itp. W takich przypadkach model szkieletowy może nie być poprawny, punkty mogą nawet zostać oderwane od twarzy:

Podczas nagrywania wideo czasami takie obrazy również się ślizgają. Należy je odfiltrować - zarówno podczas treningu, jak i rozpoznawania.

Niektóre punkty są najbardziej stabilne i zawierają dużo informacji. Są sztywno przymocowane do twarzy, niezależnie od jej położenia względem aparatu. Ponadto dobrze charakteryzują specyfikę twarzy. Punkty te mogą służyć jako podstawa do modelowania systemu cech.

Aby porównać powierzchnie, można użyć modelu szkieletowego punktowego 2D o tej samej pozycji powierzchni. Jakie położenie twarzy względem aparatu jest najbardziej pouczające? Oczywiście frontalny. Nie bez powodu kryminalistyka robi zdjęcie całej twarzy i profilu. Na razie ograniczmy się do pełnej twarzy.

Wszystkie znaki (odległości) powinny być bezwymiarowe (znormalizowane), tj. Skorelowane z pewnym rozmiarem (odległością). Myślę, że najbardziej odpowiednim rozmiarem jest odległość między punktami środkowymi narożników oczu. Dlaczego nie, na przykład, zewnętrzne narożniki oczu, które są faktycznie zdefiniowane w tablicy punktów orientacyjnych? Faktem jest, że narożniki oczu oddalają się (zbliżają), gdy reagują na zmianę koloru, wyraz zaskoczenia, mruganie itp. Odległość między punktami środkowymi oczu neutralizuje te wibracje i dlatego jest bardziej korzystna.

Jaką cechę weźmiemy za podstawę w pierwszym przybliżeniu? Przyjmuję odległość od górnej części grzbietu nosa do dolnej części brody. Sądząc po zdjęciu, znak ten może się znacznie różnić dla różnych osób.

Tak więc przed utworzeniem cech do treningu i porównania konieczne jest odfiltrowanie ramek punktowych twarzy uzyskanych podczas przechwytywania wideo, które z przyczyn subiektywnych lub obiektywnych nie są prawidłowym obrazem twarzy z przodu (pełna twarz).

Pozostawiamy tylko te modele szkieletowe punktów, które spełniają następujące kryteria:

  • Linia prosta przechodząca przez skrajne punkty oczu (linia oczu) jest prostopadła do linii przechodzącej przez skrajne punkty nosa (linia nosa).
  • Linia oczu jest równoległa do prostej przechodzącej przez kąciki ust (linia ust).
  • Powyższe punkty są symetryczne względem linii nosa.
  • Narożniki oczu (zewnętrzne i wewnętrzne) znajdują się na tej samej linii prostej.

Przykładowe obrazy frontalne, które podążają za wszystkimi znakami:

Przykładowe obrazy, które są filtrowane:

Spróbuj sam określić, który ze znaków nie przekazuje obrazów.

W jaki sposób sformalizowane są funkcje zapewniające filtrowanie i rozpoznawanie twarzy? Zasadniczo opierają się na warunkach określania odległości między punktami, warunkach równoległości i prostopadłości. Zadanie sformalizowania takich znaków jest rozważane w temacie.

Algorytm rozpoznawania twarzy poprzez model szkieletowy 2D punktów

Współrzędne punktów modelu krawędziowego twarzy są początkowo ustawiane w układzie współrzędnych, który jest zakotwiczony w lewym górnym punkcie okna. Oś Y jest skierowana w dół.

Dla ułatwienia identyfikowania elementów używamy niestandardowego układu współrzędnych (LUW), którego oś X przechodzi przez segment między punktami środkowymi oczu, a oś Y jest prostopadła do tego segmentu przez środek w kierunku do góry. Współrzędne LUW (od -1 do +1) są znormalizowane - skorelowane z odległością między środkami oczu.

LUW zapewnia wygodę i prostotę w identyfikacji elementów. Na przykład położenie twarzy w widoku z przodu jest określone przez znak symetrii odpowiednich punktów oczu w stosunku do linii nosa. Cecha ta jest formalizowana przez zbieżność linii nosa z osią Y, czyli X1 \u003d X2 \u003d 0, gdzie X1 i X2 to współrzędne skrajnych punktów nosa (27 i 30) w LUW.

Określenie względem okna SC

Współrzędne punktów środkowych lewego i prawego oka (lewego i prawego):

XL \u003d (X45 + X42) / 2; YL \u003d (Y45 + Y42) / 2; XR \u003d (X39 + X 36) / 2; YR \u003d (Y39 + Y 36) / 2;

Początek LUW:

X0 \u003d (XL + XR) / 2; Y0 \u003d (YL + YR) / 2;

Odległości między punktami środkowymi oczu wzdłuż osi X i Y:

DX \u003d XR - XL; DY \u003d YR - YL;

Rzeczywista odległość L między środkami oczu (zgodnie z twierdzeniem Pitagorasa):

L \u003d sqrt (DX ** 2 + DY ** 2)

Funkcje trygonometryczne kąta obrotu LUW:

Przejdź od współrzędnych w oknie CS do współrzędnych w LUWza pomocą parametrów X0, Y0, L, sin AL, cos AL:

X_User_0 \u003d 2 (X_Window - X0) / L;

Y_User_0 \u003d - 2 (Y_Window - Y0) / L;

X_User \u003d X_User_0 * cos_AL - Y_User_0 * sin_AL;

Y_User \u003d X_User_0 * sin_AL + Y_User_0 * cos_AL;

Wdrażanie filtrowania obrazu konsekwentne sprawdzanie znaków:

1. oznaka prostopadłości zmarszczek nosa i oczu, a także symetrii narożników oczu... Linię nosa wyznaczają punkty 27 i 30 (patrz rysunek c). Oba znaki są spełnione, jeśli współrzędne tych punktów w LUW wynoszą X1 \u003d X2 \u003d 0 (tj. Linia nosa pokrywa się z osią Y).

2. Znak równoległości linii oczu i linii ust... Linia ust jest określona punktami 48 i 54 (patrz rysunek c). Charakterystyka jest spełniona, jeśli w UCS Y1-Y2 \u003d 0.

3. Znak symetrii narożników ust... Linia ust jest określona punktami 48 i 54 (patrz rysunek c). Cecha jest spełniona, jeśli w LUW X1 + X2 \u003d 0

4. Znak „Narożniki oczu znajdują się na tej samej linii prostej”... Linie wyznaczają pary punktów: (36 i 45) oraz (39 i 42). Ponieważ test na atrybut 1 został już zaliczony, wystarczy zdefiniować atrybut Y2-Y1 \u003d 0 w LUW tylko dla punktów 36 i 39.

Nie może być absolutnej równości do zera, więc cechy porównuje się z wprawdzie małą wartością.

Program do porównywania twarzy dla jednej funkcji

Odległość między punktami grzbietu nosa i podbródka jest traktowana jako znak (punkty orientacyjne 27 i 8, patrz rysunek c). Cecha, znormalizowana, jest definiowana w LUW przez stosunek: (Y1 - Y2) / L, gdzie L to odległość między środkami oczu. Podczas treningu programu o znaku dla konkretnej osoby decyduje liczba wyświetlana obok śledzonej osoby (ta część kodu jest w programie komentowana). Podczas rozpoznawania wartość cechy jest porównywana z określoną cechą wprowadzoną do programu dla każdej osoby. Jeśli porównanie jest pozytywne, jego identyfikator pojawia się obok twarzy.

Program rozpoznaje również ze zdjęcia, na którym jestem 15 lat młodsza, a nawet z wąsami. Różnica na zdjęciu jest znacząca, nie każdy złapie. Ale programu komputerowego nie da się oszukać.

Zadania kontrolne:

  1. Zapoznaj się z programem.
  2. Określ znaczenie funkcji dla swojej twarzy i kilku współpracowników.
  3. Przetestuj program do identyfikacji osób (własnych i współpracowników).

#zawierać #zawierać #zawierać #zawierać #zawierać #zawierać #include „drawLandmarks.hpp” using namespace std; przy użyciu przestrzeni nazw cv; używając przestrzeni nazw cv :: face; int main (int argc, char ** argv) (// Load Face Detector CascadeClassifier faceDetector ("haarcascade_frontalface_alt2.xml"); // Utwórz instancję Facemark Ptr facemark \u003d FacemarkLBF :: create (); // Załaduj facemark detektora punktów orientacyjnych-\u003e loadModel ("lbfmodel.yaml"); // Konfiguracja kamery internetowej do przechwytywania wideo VideoCapture cam (0); // Zmienna do przechowywania klatki wideo i jej skali szarości Ramka mat, szara; // Czytaj ramkę while (cam.read (frame)) (// Znajdź wektor twarzy twarze; // Konwertuj ramkę na skalę szarości, ponieważ // faceDetector wymaga obrazu w skali szarości. cvtColor (ramka, szary, COLOR_BGR2GRAY); // Wykryj twarze faceDetector.detectMultiScale (szary, twarze); // Zmienna dla punktów orientacyjnych. // Punkty orientacyjne dla jednej twarzy to wektor punktów // Na obrazie może znajdować się więcej niż jedna twarz. Dlatego // używamy wektora wektorów punktów. wektor< vector \u003e punkty orientacyjne; // Uruchom detektor punktów orientacyjnych bool success \u003d facemark-\u003e fit (ramka, twarze, punkty orientacyjne); if (success) (// Jeśli się powiedzie, wyrenderuj punkty orientacyjne na twarzy dla (size_t i \u003d 0; i< faces.size(); i++) { cv::rectangle(frame, faces[i], Scalar(0, 255, 0), 3); } for (int i = 0; i < landmarks.size(); i++) { //if((i >\u003d 30) && (i<= 35)) drawLandmarks(frame, landmarks[i]); for (size_t j = 0; j < landmarks[i].size(); j++) { circle(frame, Point(landmarks[i][j].x, landmarks[i][j].y), 1, Scalar(255, 0, 0), 2); } line(frame, Point(landmarks[i].x, landmarks[i].y), Point(landmarks[i].x, landmarks[i].y), Scalar(0, 0, 255), 2); float XL = (landmarks[i].x + landmarks[i].x) / 2; float YL = (landmarks[i].y + landmarks[i].y) / 2; float XR = (landmarks[i].x + landmarks[i].x) / 2; float YR = (landmarks[i].y + landmarks[i].y) / 2; line(frame, Point(XL, YL), Point(XR, YR), Scalar(0, 0, 255), 2); float DX = XR - XL; float DY = YR - YL; float L = sqrt(DX * DX + DY * DY); float X1 = (landmarks[i].x); float Y1 = (landmarks[i].y); float X2 = (landmarks[i].x); float Y2 = (landmarks[i].y); float DX1 = abs(X1 - X2); float DY1 = abs(Y1 - Y2); float L1 = sqrt(DX1 * DX1 + DY1 * DY1); float X0 = (XL + XR) / 2; float Y0 = (YL + YR) / 2; float sin_AL = DY / L; float cos_AL = DX / L; float X_User_0 = (landmarks[i].x - X0) / L; float Y_User_0 = -(landmarks[i].y - Y0) / L; float X_User27 = X_User_0 * cos_AL - Y_User_0 * sin_AL; float Y_User27 = X_User_0 * sin_AL + Y_User_0 * cos_AL; X_User_0 = (landmarks[i].x - X0) / L; Y_User_0 = -(landmarks[i].y - Y0) / L; float X_User30 = X_User_0 * cos_AL - Y_User_0 * sin_AL; float Y_User30 = X_User_0 * sin_AL + Y_User_0 * cos_AL; if (abs(X_User27 - X_User30) <= 0.1) { //putText(frame, std::to_string(abs(L1 / L)), Point(landmarks[i].x, landmarks[i].y), 1, 2, Scalar(0, 0, 255), 2); if (abs((L1 / L) - 1.6) < 0.1) { putText(frame, "Roman", Point(landmarks[i].x, landmarks[i].y), 1, 2, Scalar(0, 0, 255), 2); } if (abs((L1 / L) - 1.9) < 0.1) { putText(frame, "Pasha", Point(landmarks[i].x, landmarks[i].y), 1, 2, Scalar(0, 0, 255), 2); } if (abs((L1 / L) - 2.1) < 0.1) { putText(frame, "Svirnesvkiy", Point(landmarks[i].x, landmarks[i].y), 1, 2, Scalar(0, 0, 255), 2); } } putText(frame, "Incorrect", Point(landmarks[i].x, landmarks[i].y), 1, 2, Scalar(0, 0, 255), 2); } } // Display results imshow("Facial Landmark Detection", frame); // Exit loop if ESC is pressed if (waitKey(1) == 27) break; } return 0; }

Evgeny Borisov Poniedziałek, 24 lipca 2017 r

Ten artykuł zawiera omówienie metod wyszukiwania obiektu na obrazie.

1. Wstęp

Wiele praktycznych zadań od automatyzacji sterowania w produkcji po projektowanie zrobotyzowanych pojazdów jest bezpośrednio związanych z zadaniem znajdowania obiektów na obrazie. Aby go rozwiązać, możesz użyć dwóch różnych strategii, które zależą od warunków fotografowania - modelowanie tła i modelowanie obiektów.
  1. Symulacja w tle - to podejście można zastosować, jeśli kamera jest nieruchoma, tj. mamy tło, które niewiele się zmienia, więc możemy je modelować. Wszystkie punkty obrazu, które znacznie odbiegają od modelu tła, są uważane za obiekty pierwszego planu. W ten sposób można rozwiązać problemy związane z wykrywaniem i śledzeniem obiektów.
  2. Modelowanie obiektów - to podejście jest bardziej ogólne, stosuje się je w przypadkach, gdy tło stale i znacząco się zmienia. W przeciwieństwie do poprzedniego przypadku, tutaj musimy wiedzieć, co dokładnie chcemy znaleźć, tj. konieczne jest zbudowanie modelu obiektu, a następnie sprawdzenie punktów obrazu pod kątem zgodności z tym modelem.
Czasami warunki problemu pozwalają na połączenie obu podejść, co może znacznie poprawić wyniki. Rozwiązanie problemu z modelowaniem tła dla stacjonarnej kamery można znaleźć w pliku. Następnie rozważymy zastosowanie drugiej strategii, tj. modelowanie obiektu wyszukiwania.

2. Przegląd metod

W tej sekcji przedstawimy listę podejść, które można zastosować do skutecznego rozwiązania problemu znalezienia obiektu na obrazie, w kolejności rosnącej złożoności.
  1. Filtry barwne - jeśli obiekt znacząco odstaje kolorem na tle tła, można wybrać odpowiedni filtr.
  2. Selekcja i analiza konturów - jeśli wiemy, że obiekt ma kształt np. Koła, to na obrazie możemy poszukać okręgów.
  3. Dopasowywanie wzorców - mamy obraz obiektu, szukamy obszarów na innym obrazku, które pasują do tego obrazu obiektu.
  4. Pracując z punktami specjalnymi - na zdjęciu z obiektem szukamy cech (np. Kątów), które staramy się dopasować do takich cech na innym obrazie.
  5. Metody uczenia maszynowego - szkolimy klasyfikator na obrazkach z obiektem, w pewien sposób dzielimy obraz na części, sprawdzamy każdą część klasyfikatorem na obecność obiektu.
Przyjrzymy się tym metodom bardziej szczegółowo poniżej.

3. Filtry kolorowe

Metodę filtrów barwnych można zastosować w przypadkach, gdy obiekt znacznie różni się kolorem od tła, a oświetlenie jest jednolite i nie zmienia się. Możesz przeczytać więcej o metodzie filtra kolorów w.

4. Ekstrakcja i analiza konturów

Jeśli obiekt na tle nie wyróżnia się znacząco kolorem i / lub ma złożoną kolorystykę, wówczas zastosowanie metody filtrów barwnych nie da dobrych rezultatów. W takim przypadku możesz spróbować zastosować metodę wyboru i analizy konturu. Aby to zrobić, wybieramy granice obrazu. Granice to miejsca, w których gradient jasności zmienia się gwałtownie i można je znaleźć za pomocą metody Canny. Następnie możemy sprawdzić wybrane linie graniczne pod kątem zgodności z geometrycznymi konturami obiektu, można to zrobić metodą Hough Transform, np. Możemy przeszukiwać w granicach koła.





Rys. 4:znajdowanie kręgów

Ta metoda może być również używana w połączeniu z filtrami kolorów. Możesz przeczytać więcej o wyborze i analizie konturów w. Można pobrać kod źródłowy przykładu wyszukiwania w kręgach.

5. Dopasowanie wzorców

Jeśli obraz zawiera wiele drobnych szczegółów, analiza krawędzi może być trudna. W takim przypadku możesz skorzystać z metody dopasowywania szablonów. Polega ona na tym, że robimy zdjęcie z obiektem (ryc. 5) i szukamy na dużym obrazie obszarów, które pokrywają się z obrazem obiektu (ryc. 6,7).


Rys. 5: obiekt do wyszukiwania

Możesz wysłuchać dokładniej wykładu na temat metody dopasowania wzorców. Można pobrać kod źródłowy przykładu.

6. Praca z punktami specjalnymi

Metoda dopasowania wzorców opisana w poprzedniej sekcji szuka dokładnych dopasowań między punktami wzoru i punktami obrazu. Jeśli obraz jest obracany lub skalowany względem parametrów szablonu, ta metoda nie działa dobrze. Aby przezwyciężyć te ograniczenia, stosuje się metody oparte na tzw. punkty osobliwe, rozważymy je poniżej. Kluczowym punktem jest mały obszar, który znacznie się wyróżnia na obrazie. Istnieje kilka metod wyznaczania takich punktów, mogą to być kąty (wykrywacz narożników Harrisa) lub kropelki (kropla, kropla), tj. małe obszary o tej samej jasności, z dość wyraźną obwódką, która wyróżnia się na tle ogólnym. Na specjalny punkt tzw. deskryptor - charakterystyka danego punktu. Deskryptor jest obliczany z danego sąsiedztwa punktu osobliwego, jako kierunki gradientów jasności w różnych częściach tego sąsiedztwa. Istnieje kilka metod obliczania deskryptorów punktów specjalnych: SIFT, SURF, ORB itp. Należy zauważyć, że niektóre metody obliczania deskryptorów są opatentowane (na przykład SIFT), a ich komercyjne wykorzystanie jest ograniczone. Możesz bardziej szczegółowo wysłuchać wykładu na temat szczególnych punktów na obrazach i metod pracy z nimi. Do znalezienia obiektu na obrazie można użyć punktów specjalnych. Aby to zrobić, musimy mieć obraz żądanego obiektu, a następnie wykonać następujące czynności.
  1. Na obrazku z obiektem szukamy specjalnych punktów obiektu i obliczamy ich deskryptory.
  2. Na analizowanym obrazie szukamy również punktów specjalnych i obliczamy dla nich deskryptory.
  3. Porównujemy deskryptory specjalnych punktów obiektu i deskryptory specjalnych punktów znalezionych na obrazku.
  4. Jeśli zostanie znaleziona wystarczająca liczba dopasowań, zaznacz obszar odpowiednimi punktami.
Rysunek 8 poniżej przedstawia wyniki metody wyszukiwania obiektu według punktów osobliwych.


Rys. 8: detektor obiektów za pomocą specjalnych punktów

Można pobrać kod źródłowy przykładu.

7. Metody uczenia maszynowego

Metoda znajdowania obiektów poprzez porównywanie zbiorów punktów specjalnych ma swoje wady, z których jedną jest słaba zdolność uogólniania. Jeśli mamy za zadanie np. Wybrać twarze osób na zdjęciu, to nasza metoda będzie szukać jednego konkretnego zdjęcia po specjalnych punktach. Na zdjęciu, na którym wybrano punkty specjalne, pozostałe twarze będą się wyróżniać gorzej, ponieważ najprawdopodobniej odpowiadają innym zestawom punktów specjalnych. Efekty mogą być jeszcze gorsze, jeśli zmienisz kąt kamery. Aby rozwiązać te problemy, potrzebujemy już metod uczenia maszynowego, a nie tylko jednego obrazu z obiektem, ale całych zestawów treningowych składających się z setek (aw niektórych przypadkach setek tysięcy) różnych obrazów przedstawiających obiekt w różnych warunkach. W drugiej części tego artykułu przyjrzymy się wykorzystaniu metod uczenia maszynowego do znajdowania obiektów na obrazie.

Literatura

  1. ES Borisov Detektor obiektów do kamer stacjonarnych.
    - http: //site/cv-backgr.html
  2. ES Borisov Przetwarzanie wideo: detektor obiektów oparty na filtrach kolorów.
    - http: //site/cv-detector-color.html
  3. ES Borisov Podstawowe metody przetwarzania obrazu.
    - http: //site/cv-base.html
  4. Anton Konushin Computer vision (2011). Wykład 3. Proste metody analizy obrazu. Pasujące wzory.
    - http://www.youtube.com/watch?v\u003dTE99wDbRrUI
  5. Dokumentacja OpenCV: Harris Corner Detection
    - http://docs.opencv.org/3.0-beta/doc/py_tutorials/py_feature2d/py_features_harris/py_features_harris.html
  6. Wikipedia: Blob_detection
    - http://en.wikipedia.org/wiki/Blob_detection
  7. Anton Konushin Computer vision (2011). Wykład 5. Cechy lokalne
    - http://www.youtube.com/watch?v\u003dvFseUICis-s

Biblioteka widzenia komputerowego i uczenia maszynowego typu open source. Zawiera ponad 2500 algorytmów, które obejmują zarówno klasyczne, jak i nowoczesne algorytmy widzenia komputerowego i uczenia maszynowego. Ta biblioteka posiada interfejsy w różnych językach, w tym Python (używamy go w tym artykule), Java, C ++ i Matlab.

Instalacja

Można wyświetlić instrukcje instalacji dla systemu Windows, a dla systemu Linux -.

Importowanie i przeglądanie obrazu

import cv2 image \u003d cv2.imread ("./ path / to / image.extension") cv2.imshow ("Image", image) cv2.waitKey (0) cv2.destroyAllWindows ()

Uwaga Podczas czytania powyższej metody obraz jest w przestrzeni kolorów nie RGB (jak wszyscy są przyzwyczajeni), ale BGR. Na początku może to nie być takie ważne, ale gdy już zaczniesz pracować z kolorem, warto wiedzieć o tej funkcji. Istnieją 2 rozwiązania:

  1. Zamień pierwszy kanał (R - czerwony) na trzeci kanał (B - niebieski), a wtedy kolor czerwony będzie (0,0,255), a nie (255,0,0).
  2. Zmień przestrzeń kolorów na RGB: rgb_image \u003d cv2.cvtColor (image, cv2.COLOR_BGR2RGB)

    A potem w kodzie do pracy już nie z obrazem, ale z rgb_image.

Uwaga Naciśnij dowolny klawisz, aby zamknąć okno, w którym wyświetlany jest obraz. Jeśli użyjesz przycisku zamykania okna, możesz natknąć się na zawieszenie.

W całym artykule do wyświetlania obrazów zostanie użyty następujący kod:

Importuj cv2 def viewImage (image, name_of_window): cv2.namedWindow (name_of_window, cv2.WINDOW_NORMAL) cv2.imshow (name_of_window, image) cv2.waitKey (0) cv2.destroyAllWindows ()

Uprawa

Piesek po przycięciu

Importuj przycięte cv2 \u003d widok obrazu (przycięte, „Piesek po przycięciu”)

Gdzie obraz jest obrazem.

Zmiana rozmiaru

Po zmianie rozmiaru o 20%

Importuj cv2 scale_percent \u003d 20 # Procent oryginalnego rozmiaru width \u003d int (img.shape * scale_percent / 100) height \u003d int (img.shape * scale_percent / 100) dim \u003d (width, height) resized \u003d cv2.resize (img, dim , interpolation \u003d cv2.INTER_AREA) viewImage (zmieniony rozmiar, „Po zmianie rozmiaru o 20%”)

Ta funkcja bierze pod uwagę proporcje oryginalnego obrazu. Widoczne są inne funkcje zmiany rozmiaru obrazu.

Skręcać

Pies po obróceniu o 180 stopni

Importuj cv2 (h, w, d) \u003d image.shape center \u003d (w // 2, h // 2) M \u003d cv2.getRotationMatrix2D (center, 180, 1.0) rotated \u003d cv2.warpAffine (image, M, (w , h)) viewImage (obrócony, "Pies po obrocie o 180 stopni")

image.shape zwraca wysokość, szerokość i kanały. M - matryca rotacji - obraca obraz o 180 stopni wokół środka. -ve to obrót obrazu w prawo, a + ve to obrót w lewo.

Progi w odcieniach szarości i czerni i bieli

Piesek w skali szarości

Piesek czarno-biały

Importuj cv2 gray_image \u003d cv2.cvtColor (image, cv2.COLOR_BGR2GRAY) ret ,reshold_image \u003d cv2.threshold (im, 127, 255, 0) viewImage (gray_image, "piesek w skali szarości") viewImage (próg_image, "Czarno-biały piesek) ")

gray_image to jednokanałowa wersja obrazu.

Funkcja progu zwraca obraz, w którym wszystkie piksele ciemniejsze (mniejsze niż) 127 są zastępowane przez 0, a wszystkie piksele jaśniejsze (większe niż) 127 są zastępowane przez 255.

Dla jasności inny przykład:

Ret, próg \u003d cv2.threshold (im, 150, 200, 10)

Tutaj wszystko, co jest ciemniejsze niż 150, jest zastępowane przez 10, a wszystko, co jest jaśniejsze, jest zastępowane przez 200.

Pozostałe funkcje progowe zostały opisane.

Rozmycie / wygładzanie

Rozmyty piesek

Importuj niewyraźne cv2 \u003d cv2.GaussianBlur (obraz, (51, 51), 0) viewImage (rozmyte, „Niewyraźny piesek”)

Funkcja GaussianBlur przyjmuje 3 parametry:

  1. Oryginalny obraz.
  2. Krotka 2 dodatnich liczb nieparzystych. Im wyższe liczby, tym większa siła wygładzania.
  3. sigmaX i sigmaY... Jeśli te parametry pozostaną równe 0, to ich wartość zostanie obliczona automatycznie.

Rysowanie prostokątów

Narysuj prostokąt wokół pyska psa

Importuj wyjście cv2 \u003d image.copy () cv2.rectangle (output, (2600, 800), (4100, 2400), (0, 255, 255), 10) viewImage (output, "Nakreśl pysk psa prostokątem")

Ta funkcja przyjmuje 5 parametrów:

  1. Sam obraz.
  2. Współrzędna lewego górnego rogu (x1, y1).
  3. Współrzędna prawego dolnego rogu (x2, y2).
  4. Kolor prostokąta (GBR / RGB w zależności od wybranego modelu kolorów).
  5. Szerokość linii prostokąta.

Rysowanie linii

2 psy oddzielone linią

Importuj wyjście cv2 \u003d image.copy () cv2.line (output, (60, 20), (400, 200), (0, 0, 255), 5) viewImage (output, "2 psy oddzielone linią")

Funkcja liniowa przyjmuje 5 parametrów:

  1. Sam obraz, na którym rysowana jest linia.
  2. Współrzędna pierwszego punktu (x1, y1).
  3. Współrzędna drugiego punktu (x2, y2).
  4. Kolor linii (GBR / RGB w zależności od wybranego modelu kolorów).
  5. Szerokość linii.

Tekst na obrazie

Obraz z tekstem

Importuj wyjście cv2 \u003d image.copy () cv2.putText (wyjście, „We<3 Dogs", (1500, 3600),cv2.FONT_HERSHEY_SIMPLEX, 15, (30, 105, 210), 40) viewImage(output, "Изображение с текстом")

Funkcja putText przyjmuje 7 parametrów:

  1. Bezpośrednio obraz.
  2. Tekst obrazu.
  3. Współrzędna początku tekstu (x, y) w lewym dolnym rogu.
  4. Wykryte twarze: 2

    Importuj cv2 image_path \u003d "./path/to/photo.extension" face_cascade \u003d cv2.CascadeClassifier ("haarcascade_frontalface_default.xml") image \u003d cv2.imread (image_path) gray \u003d cv2.cvtColor (image, cv2.COLOR_BGR .detectMultiScale (gray, scaleFactor \u003d 1.1, minNeighbors \u003d 5, minSize \u003d (10, 10)) faces_detected \u003d "Wykryto twarze:" + format (len (twarze)) print (faces_detected) # Rysuj kwadraty wokół twarzy dla (x, y , w, h) w twarzach: cv2.rectangle (image, (x, y), (x + w, y + h), (255, 255, 0), 2) viewImage (image, faces_detected)

    detectMultiScale to ogólna funkcja rozpoznawania twarzy i obiektów. Aby funkcja wyszukała twarze, przekazujemy jej odpowiednią kaskadę.

    Funkcja DetectMultiScale przyjmuje 4 parametry:

    1. Przetworzony obraz w skali szarości.
    2. Parametr ScaleFactor. Niektóre twarze mogą być większe od innych, ponieważ są bliżej niż inne. Ten parametr kompensuje perspektywę.
    3. Algorytm rozpoznawania wykorzystuje przesuwane okienko podczas rozpoznawania obiektów. Parametr minNeighbors określa liczbę obiektów wokół twarzy. Oznacza to, że im większa wartość tego parametru, tym więcej podobnych obiektów potrzebuje algorytm, aby zdefiniować bieżący obiekt jako ścianę. Zbyt mała wartość zwiększy liczbę fałszywych alarmów, a zbyt duża spowoduje, że algorytm będzie bardziej wymagający.
    4. minSize to rzeczywisty rozmiar tych obszarów.

    Kontury - rozpoznawanie obiektów

    Rozpoznawanie obiektów odbywa się za pomocą segmentacji kolorów obrazu. Do tego służą dwie funkcje: cv2.findContours i cv2.drawContours.

    W tym artykule opisano szczegółowo wykrywanie obiektów za pomocą segmentacji kolorów. Jest tam wszystko, czego potrzebujesz dla niej.

    Zapisywanie obrazu

    import cv2 image \u003d cv2.imread ("./ import / path.extension") cv2.imwrite ("./ export / path.extension", image)

    Wniosek

    OpenCV to świetna biblioteka z lekkimi algorytmami, których można używać w renderowaniu 3D, zaawansowanej edycji obrazów i wideo, śledzeniu i identyfikowaniu obiektów i osób w filmach, znajdowaniu identycznych obrazów z zestawu i wielu, wielu innych.

    Ta biblioteka jest bardzo ważna dla każdego, kto opracowuje projekty związane z uczeniem maszynowym w dziedzinie obrazów.

DZWON

Są tacy, którzy czytają tę wiadomość przed tobą.
Zapisz się, aby otrzymywać najnowsze artykuły.
E-mail
Imię
Nazwisko
Jak chcesz przeczytać The Bell
Bez spamu