Es handelt sich um ein bekanntes Problem bei RTSP-Streams und zeitaufwändigen Algorithmen wie Deep-Learning-Frameworks. Sie geraten aus der Synchronisierung, wenn die Verarbeitung einzelner Frames länger dauert als die Framerate Ihres Streams. Es kommt zu einer zunehmenden Verzögerung zwischen der Realität und den aufgenommenen Bildern.
Es gibt zwei mögliche Lösungen für dieses Problem.
Der Code spricht für sich. Sie können entweder GStreamer oder FFmpeg verwenden, um den Stream zu öffnen.
Die Anzahl der angeschlossenen Kameras ist nicht begrenzt. Es könnte sogar nur eine Kamera sein.
Je mehr Kameras jedoch vorhanden sind, desto mehr CPU-Zeit wird benötigt, um alle einzelnen Threads zu besuchen.
Um die Anwendung auszuführen, müssen Sie:
Erstellen Sie den Build-Pfad und das Build-Projekt mit cmake wie folgt:
rm -rf build && mkdir -p build && cd build
cmake .. && make
Alternativ können Sie das Projekt auch mit Code::Blocks erstellen, auf dem Sie es installieren müssen ( $ sudo apt-get install codeblocks
).
Verwenden Sie für Ihren RTSP-Stream nur eine kabelgebundene Ethernet-Verbindung. WLAN kann instabil sein.
Da das RTSP-Protokoll bereits auf einen einzigen fehlenden Frame reagiert, kann der Stream leicht abstürzen.
Wenn Sie den Stream in einer Deep-Learning-App verwenden, passen Sie Ihre Auflösung und Bildrate an die Anforderungen des Deep-Learning-Modells an.
Es ist keine gute Idee, einen 1280x960-Stream mit 30 FPS zu senden, wenn Ihr Modell über einen 416x416-Eingang verfügt und 200 mSek. benötigt, um einen einzelnen Frame zu verarbeiten. Es kostet nur zusätzlichen Speicher und Rechenleistung.
Stellen Sie sicher, dass alle Kameras die gleiche Auflösung haben. Im Beispiel reagiert der OpenCV-Verkettungsalgorithmus empfindlich auf unterschiedliche Auflösungen. Es löst eine Ausnahme aus, wenn es unterschiedliche Breiten oder Höhen aufweist.
Bitte beachten Sie, dass die Kameras durch die Threads nicht miteinander synchronisiert werden. Sie können leicht unterschiedliche Verzögerungen haben.
Wenn Sie UDP oder TCP streamen möchten, vergewissern Sie sich vorher, dass die Streams mit der Befehlszeilenaufforderung funktionieren. Wenn nicht, funktionieren sie sicherlich nicht in OpenCV. Häufig werden Fehler durch die Codierung in der Pipeline, die Adressen oder fehlende Module verursacht. Wenn Sie zusätzliche GStreamer-Module installieren müssen, müssen Sie auch Ihr OpenCV neu erstellen! Weitere Informationen finden Sie auf unserer Website.
Um die Anwendung auszuführen, laden Sie die Projektdatei MultiThread.cbp in Code::Blocks.
Wenn Sie einen Jetson Nano verwenden, müssen Sie den Speicherort, an dem OpenCV seine Header-Dateien gespeichert hat, in /usr/include/opencv4
ändern
In Zeile 23 in main.cpp wird der Stream definiert.
Grb1->Init("rtsp://192.168.178.129:8554/test/");
Grb1->Init("udpsrc port=5200 ! application/x-rtp, media=video, clock-rate=90000, payload=96 ! rtpjpegdepay ! jpegdec ! videoconvert ! appsink", cv::CAP_GSTREAMER);
Absender: RaspiCam mit Raspberry Pi Buster OS
gst-launch-1.0 -v v4l2src device=/dev/video0 num-buffers=-1 ! video/x-raw, width=640, height=480, framerate=30/1 ! videoconvert ! jpegenc ! rtpjpegpay ! udpsink host=192.168.178.84 port=5200
Absender: RaspiCam mit Raspberry Pi Bullseye OS
gst-launch-1.0 -v libcamerasrc ! video/x-raw, width=640, height=480, framerate=30/1 ! videoconvert ! jpegenc ! rtpjpegpay ! udpsink host=192.168.178.84 port=5200
Beachten Sie, host=192.168.178.84
die IP-Adresse des Empfängers ist.
Grb1->Init("tcpclientsrc host=192.168.178.129 port=5000 ! jpegdec ! videoconvert ! appsink", cv::CAP_GSTREAMER);
Absender: RaspiCam mit Raspberry Pi Buster OS
gst-launch-1.0 -v v4l2src device=/dev/video0 num-buffers=-1 ! video/x-raw,width=640,height=480, framerate=30/1 ! videoconvert ! jpegenc ! tcpserversink host=192.168.178.32 port=5000
Absender: RaspiCam mit Raspberry Pi Bullseye OS
gst-launch-1.0 -v libcamerasrc ! video/x-raw,width=640,height=480, framerate=30/1 ! videoconvert ! jpegenc ! tcpserversink host=192.168.178.32 port=5000
Beachten Sie, host=192.168.178.32
die IP-Adresse des Absenders ist.
Grb1->Init("libcamerasrc ! video/x-raw, width=640, height=480, framerate=30/1 ! videoconvert ! videoscale ! video/x-raw, width=640, height=480 ! appsink", cv::CAP_GSTREAMER);
Grb1->Init("v4l2src device=/dev/video0 ! video/x-raw, width=640, height=480, framerate=30/1 ! videoconvert ! videoscale ! video/x-raw, width=640, height=480 ! appsink", cv::CAP_GSTREAMER);
Grb1->Init(0);
Grb1->Init(0); //if RaspiCam is not connected
Grb2->Init(1); //if RaspiCam is connected