【问题标题】:Introducing a delay in OpenCV::VideoCapture在 OpenCV::VideoCapture 中引入延迟
【发布时间】:2013-05-04 22:30:26
【问题描述】:

我有一个继承自 cv::VideoCapture 的 Camera 类,其核心方法是将我从直播流中获取的 cv::Mat 转换为 QImage:

QImage Camera::getFrame() {
    if(isOpened()) {
        cv::Mat image;
        (*this) >> image;
        cv::cvtColor(image, image, CV_BGR2RGB);
        return QImage((uchar*) image.data, image.cols, image.rows, image.step, QImage::Format_RGB888);
    }
    else return QImage();
}

还有一个封装类CameraDelayedView,它调用这个方法并添加一个延迟:

void CameraDelayedView::timerEvent(QTimerEvent *evt) {
    if(cam != NULL) {
        buffer.enqueue(cam->getFrame());

        if(buffer.size() > delay*fps) {
            setPixmap(QPixmap::fromImage(buffer.dequeue()));
        }
    }
}

我可以看到视频的初始显示延迟了 5 秒,但之后运行流畅。看起来图像仍然以某种方式通过指针链接到实时提要(或者 QQeueue 不是正确的 FIFO,但我对此表示怀疑)......是这样吗?

如果是这样,我可以通过这种方式向正在经历相同事情的其他人提供答案,并且我会对一种有效的复制方式(或更有效的上述代码)感兴趣。如果没有,我不知道发生了什么......

提前致谢。

问候, 神秘先生

【问题讨论】:

    标签: qt opencv


    【解决方案1】:

    来自相机的馈送在某种缓冲区中排队。我自己一直在为这个问题苦苦挣扎,使用一个单独的线程解决了这个问题,该线程不断地从缓冲区中获取帧,如果被要求发送一个帧到主线程。

    【讨论】:

    • 感谢您的回答,所以不是那么明显。为了简单起见,简单地复制每一帧的内容本身是否可行?对我来说这听起来很明显,但也可以肯定。如果是这样,我应该如何复制 image.data,它是否以 NULL 字符为界?您一定是复制了它,即使使用线程以后可以发送它们,不是吗?
    • 好吧,我使用纯 OpenCV 的线程。只需cap>>mat; 在无限循环中使用一些互斥锁来提取mat(如果需要)。我建议不要尝试一次性完成,而是将其分成几个步骤,例如清空缓冲区,获取最新帧,将其发送到 qt...
    • 确实,我试图在每一帧将 OpenCV 与 Qt 分开,在存储之前将其转换为 QImage。也许有一种更独立的方式来做到这一点,因为它们仍然以这种方式链接(可能通过 image.data)。
    【解决方案2】:

    在STREAM-ON(v4l 术语)请求之后,所有相机都需要一段时间预热,范围从几毫秒到几秒不等。

    如果您无法承受第一帧的这种延迟,则最好让相机保持开启状态。然后,您可能会发现自己得到了旧框架。在这种情况下,您需要在开始时冲洗相机。那就是:快速丢弃每一个可用的[陈旧]帧。 (你需要能够知道是否有新的图像没有阻塞)

    另一种方法是让线程使用这些图像,并仅在需要时使用它们。

    【讨论】:

    • 感谢您的回答。我现在意识到我可能还没有明确自己的目标:尽管我的声音很疯狂,但我希望相机的馈送有一个可设置的延迟。所以热身对我来说没什么大不了的,只要它在延迟之内。但是,对于我也有的非延迟视图来说,这是很好的了解。
    • 那么你说的是所有相机都应该提供的“帧率”设置。我见过便宜的相机只能提供 30 fps。在这种情况下,您可以让一个线程设置一个“最新图像”图像缓冲区,以防您对它感兴趣。如果没有人阅读它,它就会丢失。然后,从您的线程中读取图像(它会立即出现,因为您只是在读取已经收到的图像),然后等待您需要的时间。
    • 帧率应该保持“平滑”在 30fps(最大值)。这真的就像在堵车的路上停了一段时间,然后让它自己流动:这只是开始时的延迟,所以接收到的图像应该是延迟前看到的。但是对于最后一部分,读取图像并等待所需的时间基本上是我在上面的代码中尝试做的,它只是不起作用......
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-04-15
    • 1970-01-01
    • 1970-01-01
    • 2021-01-02
    • 1970-01-01
    • 2019-05-14
    • 1970-01-01
    相关资源
    最近更新 更多