- Konfiguracja Raspberry Pi z Buster i OpenCV
- Dodanie brzęczyka do 5-calowego wyświetlacza Raspberry Pi
- Programowanie Raspberry Pi do wykrywania ruchu CCTV
- Detekcja ruchu w OpenCV przy użyciu Raspberry Pi
- Ustawianie alarmu wykrywania ruchu
- Monitorowanie temperatury i użycia procesora
- Uruchomienie czujnika ruchu Pi CCTV
OpenCV to potężne narzędzie, które w połączeniu z Raspberry Pi może otworzyć drzwi do wielu przenośnych inteligentnych urządzeń. W naszym poprzednim artykule dotyczącym monitoringu CCTV Raspberry Pi dowiedzieliśmy się, jak uzyskać wideo CCTV na żywo z DVR za pomocą RTSP i wyświetlić na Raspberry Pi, sprawdź to przed kontynuowaniem. W tym artykule dowiemy się, jak wykorzystać moc OpenCV i zbudować system wykrywania ruchu Raspberry Pi na naszych nagraniach CCTV na żywo. Jeśli nie masz zainstalowanego CCTV, nadal możesz zbudować system nadzoru Raspberry Pi, podłączając kamery USB bezpośrednio do Pi. A jeśli nie jesteś wielkim fanem Pi i Pythona, możesz zbudować coś podobnego z ESP32, zapoznaj się z dzwonkiem do drzwi Wi-Fi ESP32, aby uzyskać więcej informacji.
Napiszemy skrypt w języku Python, który będzie w stanie monitorować wszystkie cztery kamery CCTV jednocześnie pod kątem dowolnych działań (ruchu). Jeśli aktywność zostanie wykryta w dowolnej kamerze, nasz Raspberry Pi automatycznie przełączy się na ten konkretny ekran kamery i podświetli, która aktywność miała miejsce, a wszystko to w czasie rzeczywistym z zaledwie 1,5-sekundowym opóźnieniem. Dodałem również funkcję alarmu, taką jak brzęczyk, który może ostrzec użytkownika sygnałem dźwiękowym, jeśli zostanie wykryta aktywność. Ale możesz łatwo skalować to w górę, aby wysłać wiadomość lub e-mail, czy nie! Ekscytujące prawda !! Zacznijmy
Konfiguracja Raspberry Pi z Buster i OpenCV
Używam Raspberry Pi 3 B + z uruchomionym systemem operacyjnym Buster i wersją OpenCV jest 4.1. Jeśli jesteś zupełnie nowy, wykonaj poniższe samouczki, zanim zaczniesz.
Celem jest, aby Twoje Pi było gotowe do rozwoju. W porządku jest mieć dowolną wersję systemu operacyjnego Raspbian na swoim Pi, ale upewnij się, że wersja OpenCV to 4.1 lub nowsza. Możesz postępować zgodnie z powyższym samouczkiem, aby skompilować OpenCV, który zajmie godziny, ale jest bardziej niezawodny w przypadku ciężkich projektów, lub po prostu zainstalować go bezpośrednio z pip za pomocą następujących poleceń.
$ pip zainstaluj opencv-contrib-python == 4.1.0.25
Jeśli instalujesz OpenCV z pipem po raz pierwszy, musisz zainstalować również inne zależności. Użyj do tego poniższych poleceń.
$ sudo apt-get install libavcodec-dev libavformat-dev libswscale-dev libv4l-dev $ sudo apt-get install libxvidcore-dev libx264-dev $ sudo apt-get install libatlas-base-dev gfortran $ sudo apt-get install libhdf5- dev libhdf5-serial-dev libhdf5-103 $ sudo apt-get install libqtgui4 libqtwebkit4 libqt4-test python3-pyqt5
Zbudowaliśmy już wiele projektów Raspberry Pi OpenCV, możesz też sprawdzić, aby uzyskać więcej inspiracji.
Dodanie brzęczyka do 5-calowego wyświetlacza Raspberry Pi
Po stronie sprzętowej nie mamy nic innego niż 5-calowy wyświetlacz i brzęczyk. Po połączeniu 5-calowego wyświetlacza z Raspberry Pi, możemy bezpośrednio zamontować brzęczyk z tyłu wyświetlacza, co rozszerzyło dla nas kilka pinów GPIO. Podłączyłem mój Buzzer, jak pokazano poniżej-
Jeśli jesteś zainteresowany wykorzystaniem większej liczby pinów I / O, przydatny będzie poniższy opis pinów. Jak widać wśród rozszerzonych pinów, większość pinów jest wykorzystywana przez sam wyświetlacz jako interfejs ekranu dotykowego. Ale nadal mamy piny 3,5,7,8,10,11,12,13,15,16 i 24, które nie mają połączenia i możemy go użyć do własnej aplikacji. W tym samouczku podłączyłem brzęczyk do GPIO 3.
Programowanie Raspberry Pi do wykrywania ruchu CCTV
Kompletny skrypt Pythona dla tego projektu można znaleźć na dole tej strony, ale omówmy każdy segment kodu, aby zrozumieć, jak to działa.
Monitorowanie wielu kamer bez opóźnień na Raspberry Pi przy użyciu RTSP
Wyzwaniem w wykonaniu tej pracy było zmniejszenie obciążenia Raspberry pi, aby uniknąć opóźnień w przesyłaniu strumieniowym. Początkowo próbowałem przełączać się między wszystkimi czterema kamerami, aby szukać ruchu, ale było to bardzo opóźnione (około 10 sekund). Więc połączyłem wszystkie cztery kamery w jeden obraz i wykonałem wszystkie działania związane z wykrywaniem ruchu na tym obrazie. Napisałem dwie funkcje, a mianowicie stworzyć aparat i czytać aparat.
Funkcja tworzenia kamery służy do otwierania kamery z odpowiednim numerem kanału. Zwróć uwagę, że adres URL RTSP kończy się na „02”, co oznacza, że używam źródła wideo podstrumienia, które będzie miało niską rozdzielczość i dzięki temu będzie szybsze do odczytania. Ponadto typ kodeka wideo, którego używasz, również przyczynia się do szybkości, eksperymentowałem z różnymi kodami i stwierdziłem, że FFMPEG jest wśród wszystkich na czczo.
def create_camera (channel): rtsp = "rtsp: //" + rtsp_username + ":" + rtsp_password + "@" + rtsp_IP + ": 554 / Streaming / Channels /" + channel + "02" # zmień adres IP, aby dopasować yours cap = cv2.VideoCapture (rtsp, cv2.CAP_FFMPEG) cap.set (3, cam_width) # Numer identyfikacyjny szerokości to 3 cap.set (4, cam_height) # Numer identyfikacyjny wysokości to 480 cap.set (10, 100) # Numer identyfikacyjny jasności to 10 ogranicznika powrotu
W funkcji odczytu kamery odczytujemy wszystkie cztery kamery, mianowicie cam1, cam2, cam3 i cam4, aby połączyć je wszystkie w jeden obraz o nazwie Main_screen . Gdy ten główny ekran będzie gotowy, wykonamy wszystkie nasze prace związane z OpenCV na tym obrazie.
def read_camera (): sukces, current_screen = cam1.read () Main_screen = current_screen Success, current_screen = cam2.read () Main_screen = current_screen Success, current_screen = cam3.read () Main_screen = current_screen success, current_screen = cam4.read () Main_screen = current_screen return (Main_screen)
Główny obraz ekranu z połączonymi wszystkimi czterema kamerami będzie wyglądał jak na poniższym obrazku.
Detekcja ruchu w OpenCV przy użyciu Raspberry Pi
Teraz, gdy mamy już gotowy obraz, możemy rozpocząć wykrywanie ruchu. Wewnątrz pętli while zaczynamy od odczytania dwóch różnych ramek, a mianowicie ramki1 i klatki2, a następnie konwertujemy je na skalę szarości
frame1 = read_camera () # Przeczytaj pierwszą klatkę grayImage_F1 = cv2.cvtColor (frame1, cv2.COLOR_BGR2GRAY) # Konwertuj na szary frame2 = read_camera () # Przeczytaj drugą ramkę grayImage_F2 = cv2.cvtColor (frame2, cv2.COLY_B)
Następnie bierzemy różnicę między tymi dwoma obrazami, aby zobaczyć, co się zmieniło, i z progiem grupujemy wszystkie miejsca, w których nastąpiła zmiana, trochę jak kropla. Powszechne jest również rozmycie i rozszerzenie obrazu w celu uniknięcia ostrych krawędzi.
diffImage = cv2.absdiff (grayImage_F1, grayImage_F2) # pobierz różnicę - to jest fajne rozmycieImage = cv2.GaussianBlur (diffImage, (5,5), 0) _, prógImage = cv2.threshold (blurImage, 20,255, cv2.THRESH_BINARY) dilatedImage = cv2.dilate (prógImage, kernal, iterations = 5)
Następnym krokiem jest znalezienie liczników i sprawdzenie powierzchni każdego licznika, znajdując obszar, możemy dowiedzieć się, jak duży jest ruch. Jeśli obszar jest większy niż określona wartość w zmiennej motion_detected , wówczas traktujemy to jako czynność i narysujemy ramkę wokół zmiany, aby zaznaczyć ją użytkownikowi.
contours, _ = cv2.findContours (dilatedImage, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) #find contour to magiczna funkcja dla konturu w konturach: # dla każdej wykrytej zmiany (x, y, w, h) = cv2.boundingRect (contour) # pobierz lokalizację, w której znaleziono zmianę, jeśli cv2.contourArea (contour)> motion_threshold: cv2.rectangle (ramka1, (x, y), (x + w, y + h), (255, 255, 0), 1) display_screen = find_screen ()
Funkcja find_screen () służy do znalezienia miejsca, w którym doszło do działania spośród czterech kamer. Możemy to stwierdzić, ponieważ znamy wartości x i y ruchu. Porównujemy te wartości xiy z lokalizacją każdego ekranu, aby znaleźć ekran, który wywołał aktywność, i ponownie przycinamy ten konkretny ekran, abyśmy mogli go wyświetlić na ekranie dotykowym pi.
def find_screen (): if (x <cam_width): if (y <cam_height): screen = frame1 print ("Activity in cam screen 1") else: screen = frame1 print ("Activity in cam screen 2") else: if (y <cam_height): screen = frame1 print ("Aktywność na ekranie kamery 3") else: screen = frame1 print ("Aktywność na ekranie kamery 4") return (screen)
Ustawianie alarmu wykrywania ruchu
Gdy już wiemy, na którym ekranie został wykryty ruch, łatwo jest dodać dowolny typ alarmu, jakiego potrzebujemy. Tutaj wydamy sygnał dźwiękowy brzęczyka podłączonego do GPIO 3. Instrukcja if sprawdza, czy ruch został wykryty na ekranie 3 i zwiększa wartość zmiennej o nazwie trig_alarm . Możesz wykryć dowolny wybrany ekran lub nawet na wielu ekranach.
if ((x> cam_width) i (y
Jeśli wartość trig_alarm osiągnie więcej niż 3, raz wydamy sygnał dźwiękowy. Powodem tego liczenia jest to, że czasami zauważyłem cienie lub ptaki stworzyły fałszywy alarm. W ten sposób tylko w przypadku ciągłej aktywności przez 3 klatki otrzymamy alarm.
if (trig_alarm> = 3): # czekaj na ruchy conts 3 #Beep the Buzzer GPIO.output (BUZZER, 1) time.sleep (0.02) GPIO.output (BUZZER, 0) trig_alarm = 0
Monitorowanie temperatury i użycia procesora
System jest przystosowany do pracy w trybie 24x7 i dlatego Pi może się bardzo nagrzewać, więc decyduję się monitorować temperaturę i użycie procesora, wyświetlając te wartości na ekranie. Uzyskaliśmy te informacje za pomocą biblioteki gpiozero.
cpu = CPUTemperature () load = LoadA Average () cpu_temperature = str ((cpu.temperature) // 1) load_average = str (load.load_average) #print (cpu.temperature) #print (load.load_average) cv2.putText (display_screen, cpu_temperature, (250,250), cv2.FONT_HERSHEY_SIMPLEX, 0.4, (0,0,255), 1) cv2.putText (display_screen, load_average, (300,250), cv2.FONT_HERSHEY_SIMPLEX, 0,4, (0,255,0), 2)
Uruchomienie czujnika ruchu Pi CCTV
Testowałem to przez wiele dni i działa za każdym razem i była to naprawdę fajna kompilacja, dopóki nie uszkodziłem jednej kamery,