当我使用 rtsp 摄像头流时,opencv 视频捕获滞后

Posted

技术标签:

【中文标题】当我使用 rtsp 摄像头流时,opencv 视频捕获滞后【英文标题】:lag in opencv videocapture when i use rtsp camera stream 【发布时间】:2017-03-13 10:30:02 【问题描述】:

所以我目前正在做一个需要在 rtsp ip cam 上进行面部识别的项目,我设法毫无问题地获得了 rtsp 提要,但是在应用面部识别时,视频提要变得太慢了并显示出很大的延迟,我什至使用多线程来使它更好,但没有成功,这是我的代码,我仍然是多线程问题的初学者,所以任何帮助将不胜感激。

    #include <iostream>
#include <thread>
#include "opencv2/opencv.hpp"

#include <vector>
using namespace std;
using namespace cv;
void detect(Mat img, String strCamera) 
    string cascadeName1 = "C:\\ocv3.2\\Build\\install\\etc\\haarcascades\\haarcascade_frontalface_alt.xml";
    CascadeClassifier facedetect;
    bool loaded1 = facedetect.load(cascadeName1);
    Mat original;
    img.copyTo(original);
    vector<Rect> human;
    cvtColor(img, img, CV_BGR2GRAY);
    equalizeHist(img, img);
    facedetect.detectMultiScale(img, human, 1.1, 2, 0 | 1, Size(40, 80), Size(400, 480));
    if (human.size() > 0)
    
        for (int gg = 0; gg < human.size(); gg++)
        
            rectangle(original, human[gg].tl(), human[gg].br(), Scalar(0, 0, 255), 2, 8, 0);
        
    
    imshow("Detect " + strCamera, original);
    int key6 = waitKey(40);
    //End of the detect

void stream(String strCamera) 
    VideoCapture cap(strCamera);
    if (cap.isOpened()) 
        while (true) 
            Mat frame;
            cap >> frame;
            resize(frame, frame, Size(640, 480));
            detect(frame, strCamera);
        
    

int main() 
    thread cam1(stream, "rtsp://admin:password@ipaddress:554/live2.sdp?tcp");
    thread cam2(stream, "rtsp://admin:password@ipaddress/live2.sdp?tcp");
    cam1.join();
    cam2.join();
    return 0;

【问题讨论】:

【参考方案1】:

我遇到了类似的问题,并且能够通过将帧捕获与图像处理完全隔离来解决这些问题。我还将 OpenCV 更新到了可用的最新版本 (3.2.0),但我认为这也将解决早期版本的问题。

void StreamLoop(String strCamera, LFQueue1P1C<Mat> *imageQueue, bool *shutdown) 
    VideoCapture cap(strCamera, CV_CAP_FFMPEG);
    Mat image;

    while(!(*shutdown) && cap.isOpened())
        *cap >> image;
        imageQueue->Produce(image);
    



int main()
    Mat aImage1;
    bool shutdown(false);
    LFQueue1P1C<Mat> imageQueue;
    string rstp("rtsp://admin:password@ipaddress:554/live2.sdp?tcp");
    thread streamThread(StreamLoop, rtsp, &imageQueue, &shutdown);

...

    while(!shutdownCondition)
        if(imageQueue.Consume(aImage1)) 
            // Process Image
            resize(aImage1, aImage1, Size(640, 480));
            detect(aImage1, rtsp);
        
    

    shutdown = true;
    if(streamThread.joinable()) streamThread.join();

...
    return 0;

OpenCV 中的 rtsp 似乎存在一些问题,如果在拾取帧时甚至有轻微的停顿,它很容易挂断。只要我在没有太多停顿的情况下拾取帧,我就没有看到问题。

另外,当摄像机直接连接到我的本地网络时,我没有这个问题。直到我们将它们部署在远程站点上,我才开始遇到问题。将帧检索和处理分离到单独的线程中解决了我的问题,希望其他人可能会发现此解决方案有用。

注意:我使用的队列是一个自定义队列,用于将项目从一个线程传递到另一个线程。我发布的代码是根据我的原始代码修改的,使其更具可读性和适用于这个问题。

我仍然是多线程问题的初学者,所以任何帮助将不胜感激

拥有无法退出的线程会在将来给您带来问题。即使是测试代码,也要养成确保代码有退出路径的习惯。举个例子:您可能稍后复制并粘贴一段代码,却忘记了其中有一个无限循环,这将导致您稍后试图追查为什么神秘崩溃或您的资源被锁定的原因。

【讨论】:

什么是LFQueue1P1C!?【参考方案2】:

我不是 C++ 开发人员,但我在 Java 中遇到了同样的问题。我通过调用 VideoCapture.grab() 函数 before 读取相机帧解决了我的问题。根据OpenCV Doc,抓取功能的使用是:

该功能的主要用途是在多相机环境中, 尤其是当相机没有硬件同步时。

此外,在 java 应用程序中,您应该在每次读取新帧时释放帧的 Mat 对象。

【讨论】:

以上是关于当我使用 rtsp 摄像头流时,opencv 视频捕获滞后的主要内容,如果未能解决你的问题,请参考以下文章

通过 RTSP 流式传输 opencv 视频

使用 RTSP 从 Opencv 处理后,视频从 PC 流式传输到 Android

有关opencv无法解码网络摄像头rtsp流的解决办法

OpenCV 之 网络摄像头

来自 Foscam FI9805W 的 Java openCV 3.0 VideoCapture rtsp 流

OpenCV - 如何捕获 rtsp 视频流