![]() |
Pełny kod źródłowy |
W dzisiejszym wpisie chciałem pokazać proste rozwiązanie problemu detekcji ruchu z wykorzystaniem biblioteki OpenCV. Skorzystam tutaj z opisanej powyżej koncepcji sprawdzania, które punkty obrazu zmieniają swoją wartość na kolejnych obrazach w sekwencji wideo. Najłatwiej w tym celu skorzystać z operacji odejmowania obrazów, a następnie binaryzacji obrazu wynikowego w celu określenia, jaka zmiana wartości pikseli powinna zostać uznana za ruch obiektu, a jaka za brak ruchu. Najczęściej stosuje się tutaj jedną z dwoch strategii odejmowania obrazów:
- odejmowanie dwóch sąsiednich obrazów, tzn. odejmowanie od bieżącej klatki, klatki poprzedniej,
- odejmowanie od bieżącej klatki, pierwszej klatki, która została zarejestrowana i która jest uznawana jako tło (zakładamy oczywiście, że na pierwszej klatce nie ma obiektów, które później będą zmieniać swoje położenie).
Implementacja opisanych metod w OpenCV nie nastręcza wiele problemów. Obydwa sposoby mogą być zaimplementowane z pomocą poniższego fragmentu kodu:
//TESTED WITH OpenCV 2.2 int diffType = atoi( argv[1] ); int thresval = atoi( argv[2] ); Mat cam_frame, img_gray, img_prev, img_diff, img_bin; bool first_frame = true; // LOOP FOR GRABBING IMAGE FROM WEBCAM cap >> cam_frame; cvtColor(cam_frame, img_gray, CV_BGR2GRAY); if (first_frame) { img_prev=img_gray.clone(); first_frame = false; continue; } absdiff(img_gray, img_prev, img_diff); threshold(img_diff, img_bin, thresval, 255, THRESH_BINARY); erode(img_bin, img_bin, Mat(), Point(-1,-1), 3); dilate(img_bin, img_bin, Mat(), Point(-1,-1), 1); imshow(win_cam, cam_frame); imshow(win_gray, img_gray); imshow(win_diff, img_bin); if (diffType == 1) img_prev=img_gray.clone(); // END LOOP
Analizując powyższy kod łatwo zauważyć, że jego działaniem możemy sterować za pomocą dwóch zmiennych:
- diffType - określa, którą klatkę należy odejmować od klatki bieżącej, czy poprzednią (wartość = 1), czy też pierwszą (wartość = 2). To sprawdzanie odbywa się w ostatniej linijce powyższego kodu, gdzie jest ustawiana klatka, która będzie odejmowana.
- thresval - zmienna ta będzie służyć do określania, co uznajemy za ruch obiektu, a co nie. Polecam ustawiać ją w przedziale od 30 do 100 (60 powinno być w miarę bezpieczną, a zarazem skuteczną wartością progu).
- W pierwszym przebiegu pętli zapamiętujemy jedynie pierwszą klatkę obrazu. Dzięki temu w drugiej iteracji będziemy mieli co odejmować od klatki bieżącej.
- absdiff - bezwzględne odjęcie (pomijamy znak) dwóch klatek od siebie.
- threshold - operacja progowania wykonywana na obrazie różnicowym. Pomijamy punkty, które nieznacznie zmieniły swoją wartość.
- erode - usunięcie drobnych elementów, oraz wygładzenie krawędzi tych większych. Skutkiem ubocznym tej operacji jest zmniejszenie rozmiaru wszystkich obiektów.
- dilate - dylatację stosujemy po etapie erozji, aby delikatnie powiększyć obiekty, tak aby miały podobny rozmiar jak to było przed erozją.
4 komentarze:
Czy są dostępne materiały w języku polskim do biblioteki opneCV? Chętnie bym się tym zainteresował.
Po polsku kojarzę jedynie książkę "Algorytmy przetwarzania obrazów i wstęp do pracy z biblioteka OpenCV". Jednak porusza ona jedynie bardzo elementarne zagadnienia.
Polecam za to dwie książki anglojęzyczne:
1. Learning OpenCV
2. OpenCV 2 Computer Vision Application Programming Cookbook
No i oczywiście dokumentację biblioteki. A do tego dużo własnej pracy i testów :-)
11:46am pst 11/20 copied from your YT channel. Help?
Rafal, if you might be so kind as to direct me to this software with a GUI wrapper that takes video FILES as input, I'd be forever grateful! (I'm having a HELL of a time locating same and I'm a C/C++/ASM programmer! ;D) Also, heavily censored, by our Jewish communist 'commisars'; they're on both sides! (Family name here is Zuroski, btw, and from the great Poland, before fall.)
ps: Beware of anything j00gle, as they're censoring this communist takeover of Americans and then the WORLD!
Prześlij komentarz