[OpenCV Qt教程] 如何在内存中压缩图像

本文译自:http://www.robot-home.it/blog/en/software/tutorial-opencv-qt-comprimere-un-immagine-in-memoria/

修正了原程序中的文字错误。


在这个简短的教程中,我会展示一个压缩图像的简单步骤。这个操作用处很大,比如获取网络摄像头的图像,这些图像要发送到另一台设备上必须经过压缩。

这个程序充分利用了我们之前看到的两个教程,如果你还没有看过,我建议你先阅读之前的教程,它分为第一部分第二部分

与先前的教程不同,这次我们要显示两个widget:一个显示原始图像,另一个显示压缩过的图像。这使得我们能直观的评估压缩质量。

压缩质量可通过一个滑块调节:0代表最低质量、最高压缩率,100代表最高质量、最低压缩率。

你还可以选择JPEG或PNG两种压缩格式,你会看到JPEG图像比PNG的图像质量要低,但是体积更小。

将之前的教程作为参考,我们要做的修改只有一个函数:TimerEvent ( QTimerEvent * event) :

void MainWindow::timerEvent(QTimerEvent *event)
{
    Q_UNUSED(event);

    cv::Mat raw;
    mCapture >> raw;

    // >>>>> Params from widgets
    QString comprType;
    int quality = ui->horizontalSlider_quality->value();
    int compr;

    if( ui->radioButton_jpeg->isChecked() )
    {
        comprType = ".jpg";
        compr = cv::IMWRITE_JPEG_QUALITY;
    }
    else
    {
        comprType = ".png";
        quality = qMin( 9, quality/10 ); // PNG quality is in [0,9] range
        compr = cv::IMWRITE_PNG_COMPRESSION;
    }
    // <<<<< Params from widgets

    // >>>>> FPS Calculation
    static int frameCount = 0;
    static qreal timeAcc = 0;
    static qreal fps=0.0;

    int nFrm = 10; // 10 frames

    qreal elapsed = (qreal)mFpsTimer.elapsed();
    timeAcc += elapsed;
    frameCount++;

    if(frameCount%nFrm==0) // Update every "nFrm" frames
    {
        fps = 1000.0/(timeAcc/nFrm);
        timeAcc=0;
        frameCount=0;
    }

    mFpsTimer.restart();
    // <<<<< FPS Calculation

    if( !raw.empty() )
    {
        // >>>>> Jpeg compression in memory
        vector<uchar> buf; // Memory buffer
        vector<int> params;

        params.push_back( compr );
        params.push_back( quality ); // Quality of compression

        cv::imencode( comprType.toLocal8Bit().data(), raw, buf, params );
        cv::Mat compressed;
        cv::imdecode( cv::Mat(buf), cv::IMREAD_COLOR, &compressed );

        mInfoLabel.setText( tr("<b>Compression quality:</b> %1 - <b>Raw data:</b> %2 bytes - <b>Compressed data:</b> %3 bytes - <b>FPS:</b> %4")
                            .arg(quality).arg(raw.cols*raw.rows*raw.channels()).arg(buf.size()).arg(fps) );
        // <<<<< Jpeg compression in memory

        // Show the images
        ui->widget_raw->showImage( raw );

        if( !compressed.empty())
            ui->widget_compressed->showImage( compressed );
    }
}

在8到25行,读取由GUI设置的的参数。26到45行,计算FPS来表示压缩占用的资源。压缩操作是在第56行使用OpenCV的 imencode 函数完成的,传入与压缩类型有关的参数以及压缩质量。

第58行,从缓存中解压缩图像,使图像可以在右侧的widget中显示。

在客户端/服务器程序中,第56行由服务器在发送图像之前执行,而第58行则由客户端在收到图像数据时执行。

本例代码:http://www.robot-home.it/blog/download/Tutorial/ImageCompressionDemo.rar

posted @ 2017-02-23 13:52  叶空Frank  阅读(2594)  评论(0编辑  收藏  举报