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

2/22/2017来源:ASP.NET技巧人气:650

本文译自: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