1. 程式人生 > >OpenCV探索之路(十八):使用imwrite調整儲存的圖片質量

OpenCV探索之路(十八):使用imwrite調整儲存的圖片質量

近日在用opencv做一些影象處理的操作時,需要對一些高解析度的影象進行儲存。比如,在操作一個容量為230M的影象後,並對該影象儲存為JPG格式後,發現影象容量變為80M了!針對這個問題,忙了大半天,到處翻閱資料,終於知道為什麼了。

先舉個例子說明自己遇到的問題,為了看出效果,我特意用了一個高解析度的圖片做實驗。

比如我有如下的一個233M的圖片

經過下面的程式讀進記憶體,再次儲存後,圖片容量就急劇變小了!

#include<opencv2\opencv.hpp>   
#include<opencv2\highgui\highgui.hpp>

using namespace std;
using namespace cv;


int main(int argc, char** argv)
{
    Mat img = imread("src1.jpg");
    imwrite("test.jpg", img);

    return 0;
}

儲存後的圖片,只剩下126M了!怎麼回事!我什麼都沒做啊,圖片大小怎麼就大大縮水了呢?

通過翻閱一些資料才知道,原來是圖片格式惹得禍。其實有些圖片格式是自帶壓縮的,比如jpg格式,而bmp格式的圖片是不帶任何壓縮,這就是每種圖片的特點,如果對這些知識點不清楚的話,很容易踩坑!平時我們操作的影象大小大多數都以KB為單位,所以經過一番“隱形壓縮”後我們很難發現圖片大小變小了,但是,當我們操作大圖的時候,這種壓縮效果一下子就看出來了。

那麼如果我們在使用imwrite儲存圖片時想提高儲存圖片的質量,該如何操作?

要改變儲存的圖片的質量,關鍵在於imwrite函式的第三個引數。

先看imwrite的宣告

CV_EXPORTS_W bool imwrite( const String& filename, InputArray img, const std::vector<int>& params = std::vector<int>()); 

第三個引數說明:const std::vector

  • 對於JPEG格式的圖片,這個引數表示從0-100的圖片質量(CV_IMWRITE_JPEG_QUALITY),預設值是95.

  • 對於PNG格式的圖片,這個引數表示壓縮級別(CV_IMWRITE_PNG_COMPRESSION)從0-9.較高的值意味著更小的尺寸和更長的壓縮時間而預設值是3.

  • 對於PPM,PGM或PBM格式的圖片,這個引數表示一個二進位制格式標誌(CV_IMWRITE_PXM_BINARY),取值為0或1,而預設值為1.

調整jpg影象格式的儲存質量

opencv的imwrite預設儲存的jpg圖片質量為95,如果想進一步提高儲存圖片的質量,可以這麼寫

#include<opencv2\opencv.hpp>   
#include<opencv2\highgui\highgui.hpp>

using namespace std;
using namespace cv;


int main(int argc, char** argv)
{
    Mat img = imread("src1.jpg");

    vector<int> compression_params;
    compression_params.push_back(CV_IMWRITE_JPEG_QUALITY);  //選擇jpeg
    compression_params.push_back(100); //在這個填入你要的圖片質量

    imwrite("test2.jpg", img, compression_params);

    return 0;
}

可以看出,經過引數調整後,jpg格式儲存的圖片的大小有了很大的提升。

但是無論如何,以jpg格式儲存圖片還是不能百分百儲存原影象的!

但是即使我們把圖片質量寫成100,圖片質量跟原圖還是右一定壓縮的,比如原圖233M,讀入再儲存為jpg格式容量就變為229M。

那當我們不斷讀入圖片,又不斷儲存圖片為jpg格式,圖片的質量就會不斷降低!

所以有以下總結:

第一,opencv的儲存圖片函式imwrite是可以通過第三個函式引數來調整儲存圖片的壓縮比的,比如儲存圖片為jpg格式,我們如果我們寫成

第二,jpg格式的圖片讀進記憶體,如果再儲存為jpg格式後,容量會被壓縮的,這是jpg格式的特性,怎麼調整壓縮比都避免不了失真(損失圖片質量)。

調整PNG影象格式的儲存質量

如果操作的而是png格式的影象,我們同樣可以調整其儲存的質量。

#include<opencv2\opencv.hpp>   
#include<opencv2\highgui\highgui.hpp>

using namespace std;
using namespace cv;


int main(int argc, char** argv)
{
    Mat img = imread("src1.jpg");

    vector<int> compression_params;
    compression_params.push_back(CV_IMWRITE_PNG_COMPRESSION); //PNG格式圖片的壓縮級別  
    compression_params.push_back(9);  //這裡設定儲存的影象質量級別

    imwrite("test3.png", img,compression_params);

    return 0;
}

那如何不損失圖片質量地儲存圖片,那就得將圖片儲存為其他格式的圖片了。現在,就簡單介紹一下我最常用的圖片格式以及他們的特點:

BMP格式(無壓縮)

點陣圖(外語簡稱:BMP、外語全稱:BitMaP)BMP是一種與硬體裝置無關的影象檔案格式,使用非常廣。它採用位對映儲存格式,除了影象深度可選以外,不採用其他任何壓縮,因此,BMP檔案所佔用的空間很大。

JPEG格式(有失真壓縮)

聯合照片專家組(外語簡稱JPEG外語全稱:Joint Photographic Expert Group)JPEG也是最常見的一種影象格式,它是由聯合照片專家組(外語全稱:Joint Photographic Experts Group),檔案後輟名為".jpg"或".jpeg",是最常用的影象檔案格式,由一個軟體開發聯合會組織制定,是一種有失真壓縮格式,能夠將影象壓縮在很小的儲存空間,影象中重複或不重要的資料會被丟失,因此容易造成影象資料的損傷。尤其是使用過高的壓縮比例,將使最終解壓縮後恢復的影象質量明顯降低,如果追求高品質影象,不宜採用過高壓縮比例。但是JPEG壓縮技術十分先進,它用有失真壓縮方式去除冗餘的影象資料,在獲得極高的壓縮率的同時能展現十分豐富生動的影象,換句話說,就是可以用最少的磁碟空間得到較好的影象品質。而且JPEG是一種很靈活的格式,具有調節影象質量的功能,允許用不同的壓縮比例對檔案進行壓縮,支援多種壓縮級別,壓縮比率通常在10:1到40:1之間,壓縮比越大,品質就越低;相反地,壓縮比越小,品質就越好。

PNG格式(無失真壓縮)

行動式網路圖形(外語簡稱PNG、外語全稱:Portable Network Graphics),是網上接受的最新影象檔案格式。PNG能夠提供長度比GIF小30%的無失真壓縮影象檔案。它同時提供24位和48位真彩色影象支援以及其他諸多技術性支援。由於PNG非常新,所以並不是所有的程式都可以用它來儲存影象檔案,但Photoshop可以處理PNG影象檔案,也可以用PNG影象檔案格式儲存。