É um problema conhecido com fluxos RTSP e algoritmos demorados, como estruturas de aprendizagem profunda. Você ficará fora de sincronia se os quadros individuais demorarem mais do que a taxa de quadros do seu stream para serem processados. Há um atraso cada vez maior entre a realidade e as imagens capturadas.
Existem duas soluções possíveis para este problema.
O código fala por si. Você pode usar o GStreamer do FFmpeg para abrir o stream.
O número de câmeras conectadas não é limitado. Pode ser apenas uma câmera.
No entanto, quanto mais câmeras, mais tempo de CPU será necessário para visitar todos os threads separados.
Para executar o aplicativo, você deve:
Crie o caminho de construção e o projeto com cmake da seguinte maneira:
rm -rf build && mkdir -p build && cd build
cmake .. && make
Alternativamente, você também pode construir o projeto usando Code::Blocks nos quais você precisa instalá-lo ( $ sudo apt-get install codeblocks
).
Use apenas uma conexão Ethernet com fio para seu fluxo RTSP. O Wi-Fi pode ser instável.
Como o protocolo RTSP é sensível até mesmo a apenas um quadro ausente, o fluxo pode travar facilmente.
Se você estiver usando o stream em um aplicativo de aprendizado profundo, ajuste a resolução e a taxa de quadros de acordo com os requisitos do modelo de aprendizado profundo.
Não é uma boa ideia enviar um fluxo de 1280x960 a 30 FPS se o seu modelo tiver uma entrada de 416x416 e levar 200 mseg para processar um único quadro. Custa apenas memória extra e poder de processamento.
Certifique-se de que todas as câmeras tenham a mesma resolução. No exemplo, o algoritmo de concatenação OpenCV é sensível a diferentes resoluções. Ele lança uma exceção quando enfrenta larguras ou alturas diferentes.
Observe que as câmeras não são sincronizadas entre si pelos threads. Eles podem ter atrasos ligeiramente diferentes.
Se você deseja transmitir UDP ou TCP, certifique-se de que os fluxos funcionem previamente com o prompt da linha de comando. Caso contrário, certamente não funcionarão no OpenCV. Freqüentemente, os erros são causados pela codificação no pipeline, pelos endereços ou pela falta de módulos. Se precisar instalar módulos GStreamer adicionais, você também precisará reconstruir seu OpenCV! Para mais informações, consulte nosso site.
Para executar a aplicação carregue o arquivo de projeto MultiThread.cbp em Code::Blocks.
Se você estiver usando um Jetson Nano , será necessário alterar o local onde o OpenCV armazenou seus arquivos de cabeçalho para /usr/include/opencv4
Na linha 23 em main.cpp o fluxo é definido.
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);
Remetente: RaspiCam com 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
Remetente: RaspiCam com sistema operacional Raspberry Pi Bullseye
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
Observe que host=192.168.178.84
é o endereço IP do receptor.
Grb1->Init("tcpclientsrc host=192.168.178.129 port=5000 ! jpegdec ! videoconvert ! appsink", cv::CAP_GSTREAMER);
Remetente: RaspiCam com 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
Remetente: RaspiCam com sistema operacional Raspberry Pi Bullseye
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
Observe que host=192.168.178.32
é o endereço IP do remetente.
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