繁体   English   中英

使用Qt和OpenCV读取和处理视频文件的有效方法

[英]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摄像机上都表现出色,让我认为读取/使用视频文件的方式出了问题。

谢谢

您没有提供完整的代码,但是我想您已经将TimerOpentimeout()信号连接到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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM