使用 Qt 和 OpenCV 读取和处理视频文件的有效方法
Posted
技术标签:
【中文标题】使用 Qt 和 OpenCV 读取和处理视频文件的有效方法【英文标题】:Efficient way to read and process video files with Qt and OpenCV 【发布时间】:2014-08-27 14:18:45 【问题描述】:我有一些视觉算法在实时摄像头流中表现良好;但是,当我在视频文件上运行这些算法时,它还远远不够;流速度太慢了,尽管在不运行视觉算法时它很好,通过调用 VideoAlgoVision->execute( grabbedFrame, &CurrentROI );
来执行
这是我目前阅读视频的方式:
//////////////////////////////////////////////////////////////////
void VisionUnit_widget::Play()
if(IsVideoPause)
ui->pausePushButton->setEnabled(true);
ui->playPushButton->setEnabled(false);
IsVideoPause = false;
TimerOpen->start( (int) (1000/FPS_open) );
return;
else
ui->pausePushButton->setEnabled(true);
ui->stopPushButton ->setEnabled(true);
ui->rewPushButton ->setEnabled(true);
ui->ffdPushButton ->setEnabled(true);
ui->videoSlider ->setEnabled(true);
ui->playPushButton ->setEnabled(false);
if(!VideoCap)
VideoCap = new VideoCapture( FileName.toStdString() );
else
VideoCap->open( FileName.toStdString() );
if( VideoCap->isOpened() )
FrameH = (int) VideoCap->get(CV_CAP_PROP_FRAME_HEIGHT);
FrameW = (int) VideoCap->get(CV_CAP_PROP_FRAME_WIDTH);
FPS_open = (int) VideoCap->get(CV_CAP_PROP_FPS);
NumFrames = (int) VideoCap->get(CV_CAP_PROP_FRAME_COUNT);
ui->videoSlider->setMaximum( (int)NumFrames );
ui->videoSlider->setEnabled(true);
READCOUNT = 0;
TimerOpen->start( (int) (1000/FPS_open) );
//////////////////////////////////////////////////////////////////
void VisionUnit_widget::Pause()
ui->playPushButton->setEnabled(true);
ui->pausePushButton->setEnabled(false);
TimerOpen->stop();
IsVideoPause = true;
//////////////////////////////////////////////////////////////////
void VisionUnit_widget::Stop()
ui->stopPushButton->setEnabled(false);
ui->playPushButton->setEnabled(false);
ui->pausePushButton->setEnabled(false);
ui->rewPushButton->setEnabled(false);
ui->ffdPushButton->setEnabled(false);
FileName = "";
TimerOpen->stop();
READCOUNT = 0;
ui->videoSlider->setSliderPosition(0);
ui->videoSlider->setEnabled(false);
ui->frameLabel->setText( "No camera connected" );
delete TimerOpen;
TimerOpen = 0;
if(VideoCap)
delete VideoCap;
VideoCap = 0;
if(VideoAlgoVision)
delete VideoAlgoVision;
VideoAlgoVision = 0;
//////////////////////////////////////////////////////////////////
void VisionUnit_widget::Read()
READCOUNT++;
// Update Video Player's slider
ui->videoSlider->setValue(READCOUNT);
if(READCOUNT >= NumFrames) // if avi ends
Pause();
return;
Mat grabbedFrame;
// Get next frame
if(VideoCap->isOpened() && VideoCap->read(grabbedFrame))
// Execute the vision filter
if(VideoAlgoVision)
VideoAlgoVision->execute( grabbedFrame, &CurrentROI );
// Convert Mat to QImage
QImage frame = MatToQImage( grabbedFrame );
// Update the display
UpdateFrame( frame );
//////////////////////////////////////////////////////////////////
QImage VisionUnit_widget::MatToQImage(const Mat& mat)
// 8-bits unsigned, NO. OF CHANNELS = 1
if(mat.type()==CV_8UC1)
// Set the color table (used to translate colour indexes to qRgb values)
QVector<QRgb> colorTable;
for (int i=0; i<256; i++)
colorTable.push_back(qRgb(i,i,i));
// Copy input Mat
const uchar *qImageBuffer = (const uchar*)mat.data;
// Create QImage with same dimensions as input Mat
QImage img(qImageBuffer, mat.cols, mat.rows, mat.step, QImage::Format_Indexed8);
img.setColorTable(colorTable);
return img;
// 8-bits unsigned, NO. OF CHANNELS=3
else if(mat.type()==CV_8UC3)
// Copy input Mat
const uchar *qImageBuffer = (const uchar*)mat.data;
// Create QImage with same dimensions as input Mat
QImage img(qImageBuffer, mat.cols, mat.rows, mat.step, QImage::Format_RGB888);
return img.rgbSwapped();
else
return QImage();
那么,我的问题是,有没有比这更好的方法来使用 Qt 和 OpenCV 读取视频文件,包括视频处理?我应该在运行时调整 QTimer 时间吗?我以TimerOpen->start( (int) (1000/FPS_open) );
开头,但显然视觉算法会减慢整个过程。有什么想法吗?
可能需要对视觉算法进行一些优化,但我的观点是它们在我的网络摄像头和 IP 摄像头上表现良好,这让我觉得我阅读/使用视频文件的方式有问题。
谢谢
【问题讨论】:
【参考方案1】:您没有提供完整的代码,但我猜您已将TimerOpen
的timeout()
信号连接到VisionUnit_widget::Read()
插槽。如果是这种情况,您正在累积1000/FPS_open
和处理时间。
将您的设计更改为以下内容将解决它:
int fSpace = 1000 / FPS;
QTime timer;
timer.start();
forever
if(timer.elapsed() < fSpace)
msleep(1);
timer.restart();
..Process the frame..
也许最好把它从主线程移到另一个线程。
【讨论】:
这不太合理......在你的无限循环中,帧处理之前的代码相当于我在TimerOpen和Read之间建立的直接连接...... connect(TimerOpen,SIGNAL(timeout ()),这个,SLOT(读取())); “您正在累积 1000/FPS_open 和处理时间”是什么意思?无论如何,我怀疑你的代码会改变我的问题,它看起来更笨拙。但是,对于您可能是对的线程,它已计划用于下一次迭代。谢谢。以上是关于使用 Qt 和 OpenCV 读取和处理视频文件的有效方法的主要内容,如果未能解决你的问题,请参考以下文章