1

我有一个从 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,但我对此表示怀疑)......是这样吗?

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

提前致谢。

问候,Mystère 先生

4

2 回答 2

2

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

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

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

于 2013-05-05T17:39:35.507 回答
2

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

于 2013-05-05T17:00:20.327 回答