[英]Efficient way to read and process video files with Qt and OpenCV
我有一些视觉算法,可以在实时摄像机流中表现良好 ; 但是,当我在视频文件上运行这些算法时,效果并不理想。 尽管未在视觉算法上运行很好,但通过调用VideoAlgoVision->execute( grabbedFrame, &CurrentROI );
来执行时,流的速度减慢了很多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) );
启动它TimerOpen->start( (int) (1000/FPS_open) );
但是显然视觉算法会减慢整个过程。 任何想法?
视觉算法可能需要进行一些优化,但是我的意思是,它们在我的网络摄像头和IP摄像机上都表现出色,让我认为读取/使用视频文件的方式出了问题。
谢谢
您没有提供完整的代码,但是我想您已经将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..
}
最好将其从主线程移到另一个线程。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.