É 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 GStreamer ou FFmpeg para abrir o stream.
Os fluxos RTSP geralmente são compactados com H264. Portanto, sua descompactação é sensível a problemas de tempo, como threads interrompidos por algum tempo.
Para executar o aplicativo, você deve:
$ 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.
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 RTSPcam.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 16 de main.cpp o stream é aberto.
cam.Open("rtsp://192.168.178.129:8554/test/");
cam.Open("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.
cam.Open("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.
cam.Open("libcamerasrc ! video/x-raw, width=640, height=480, framerate=30/1 ! videoconvert ! videoscale ! video/x-raw, width=640, height=480 ! appsink", cv::CAP_GSTREAMER);
cam.Open("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);
cam.Open(0);
cam.Open(0); //if RaspiCam is not connected
cam.Open(1); //if RaspiCam is connected
cam.Open("James.mp4");
cam.Open("/home/pi/Pictures/Plants");
cam.Open("/home/pi/Pictures/Garden.jpg");
int main ()
{
cv::Mat frame;
RTSPcam cam;
cv::namedWindow ( " Camera " , cv::WINDOW_AUTOSIZE);
cam. Open ( " rtsp://192.168.178.129:8554/test/ " ); // you can dump anything OpenCV eats. (cv::CAP_ANY) BTW,OpenCV first tries FFmpeg
while ( true )
{
if (!cam. GetLatestFrame (frame)){
cout << " Capture read error " << endl;
break ;
}
// place here your time consuming algorithms
// cout << cam.CurrentFileName << endl;
// show frame
cv::imshow ( " Camera " ,frame);
char esc = cv::waitKey ( 2 );
if (esc == 27 ) break ;
}
cv::destroyAllWindows () ;
return 0 ;
}