我是Qt的全新品牌,我觉得它非常有价值。我正在尝试将一些现有的C ++代码与新的Qt GUI合并。基本上,我们的想法是在后端处理从.avi文件中提取的图像,然后在屏幕上QLabel
显示。我设法得到以下代码来正确显示帧:
while (frame = cvQueryFrame(capture))
{
// Some processing code...
QImage qImageFrame((uchar*) frame->imageData, frame->width, frame->height, frame->widthStep, QImage::Format_RGB888);
qImageFrame = qImageFrame.rgbSwapped();
QPixmap qFrame;
qFrame.convertFromImage(qImageFrame);
label->setPixmap(qFrame);
label->repaint();
cvWaitKey(10);
}
然而,现在,这显然意味着UI停止响应用户输入,直到显示电影的所有帧。怎么样这样呢?
注意:我正在使用openCV库执行处理,该库需要特定格式的图像。例如,我认为我不能做的一件事就是直接在Qt域中使用.avi文件。
答案 0 :(得分:3)
我不同意Tamás的建议,即他的答案是“最简单”的解决方案。
对您的问题最快,最少侵入性的解决方案是将qApp->processEvents();
添加到您的循环中。我会在label->repaint();
之后放弃它,看看会发生什么。
答案 1 :(得分:1)
你应该看看Qt Phonon multimedia framework。可能无法通过媒体文件获得OpenCV的控制级别,但值得深入研究。
对于您的原始问题:您必须在不同的主题中进行处理。这很棘手,因为你只能从UI线程调用GUI函数,而你(我想)不想过多地复制图像数据。
要获得良好的破败(以及指向Qt文档的提示),请查看Qt signaling across threads, one is GUI thread?。请注意,如果您想直接传递QImage
,则需要额外的工作。
答案 2 :(得分:1)
有时最简单的解决方案是最好的。通过继承QRunnable来创建工作线程,以解码帧并将信号发送回GUI以更新帧。当Qt信号通过线程发出时,它们会被排队并正确分派。特别是在单个工作线程的情况下,由于并发问题,您不会感到头痛。复制QImage不是问题,因为它使用implicit sharing。要编写自己的隐式共享数据类,请使用QSharedDataPointer(据我所知,Qt也在内部使用它。)
答案 3 :(得分:0)
使用线程并不是唯一(或者确实是必然首选)方法。
您的UI正在阻止,因为您正在使用阻止睡眠(cvWaitKey)。如果您使用QTimer并将其超时信号连接到绘制下一帧的插槽,那么您的UI应保持响应。