メモリ上での画像データの圧縮
imencode,imdecode関数により,ファイルではなく,メモリ上で圧縮ファイルを書込,読込を行います.この関数では非可逆圧縮であるjpeg,可逆圧縮であるpngを指定可能で,それぞれ圧縮品質を指定出来ます.主に,ネットワークで画像を通信するときなどに利用します.この圧縮品質の指定方法はimwrite関数と共通です.
この関数の内部で使われているlibjpegを用いたその他の実装と符号化性能はこちら[link].
C++
#include <iostream> #include <fstream> #include <cv.h> #include <highgui.h> using namespace std; using namespace cv; double getPSNR(Mat& src1, Mat& src2, int bb=0); int main(int argc, char** argv) { Mat src = imread("lenna.png"); //(1) jpeg compression vector<uchar> buff;//buffer for coding vector<int> param = vector<int>(2); param[0]=CV_IMWRITE_JPEG_QUALITY; param[1]=95;//default(95) 0-100 imencode(".jpg",src,buff,param); cout<<"coded file size(jpg)"<<buff.size()<<endl;//fit buff size automatically. Mat jpegimage = imdecode(Mat(buff),CV_LOAD_IMAGE_COLOR); //(2) png compression param[0]=CV_IMWRITE_PNG_COMPRESSION; param[1]=3;//default(3) 0-9. imencode(".png",src,buff,param); cout<<"coded file size(png)"<<buff.size()<<endl; Mat pngimage = imdecode(Mat(buff),CV_LOAD_IMAGE_COLOR); //(3) intaractive jpeg compression char name[64]; namedWindow("jpg"); int q=95; createTrackbar("quality","jpg",&q,100); int key = 0; while(key!='q') { param[0]=CV_IMWRITE_JPEG_QUALITY; param[1]=q; imencode(".jpg",src,buff,param); Mat show = imdecode(Mat(buff),CV_LOAD_IMAGE_COLOR); double psnr = getPSNR(src,show);//get PSNR double bpp = 8.0*buff.size()/(show.size().area());//bit/pixe; sprintf(name,"quality:%03d, %.1fdB, %.2fbpp",q,psnr,bpp); putText(show,name,Point(15,50), FONT_HERSHEY_SIMPLEX,1,CV_RGB(255,255,255),2); imshow("jpg",show); key = waitKey(33); if(key =='s') { //(4) data writing sprintf(name,"q%03d_%.2fbpp.png",q,bpp); imwrite(name,show); sprintf(name,"q%03d_%.2fbpp.jpg",q,bpp); param[0]=CV_IMWRITE_JPEG_QUALITY; param[1]=q; imwrite(name,src,param);; } } } double getPSNR(Mat& src1, Mat& src2, int bb) { int i,j; double sse,mse,psnr; sse = 0.0; Mat s1,s2; cvtColor(src1,s1,CV_BGR2GRAY); cvtColor(src2,s2,CV_BGR2GRAY); int count=0; for(j=bb;j<s1.rows-bb;j++) { uchar* d=s1.ptr(j); uchar* s=s2.ptr(j); for(i=bb;i<s1.cols-bb;i++) { sse += ((d[i] - s[i])*(d[i] - s[i])); count++; } } if(sse == 0.0 || count==0) { return 0; } else { mse =sse /(double)(count); psnr = 10.0*log10((255*255)/mse); return psnr; } }
(1)jpeg圧縮
encode関数の最後の引数である圧縮オプションを指定するために,CV_IMWRITE_JPEG_QUALITYとその品質(0-100,デフォルトが95)を設定します.数字が多いほど高品質です.encode関数の2番目の引数はvectorで宣言したバッファを入力し,そのサイズは,ちょうど圧縮されたデータのサイズに伸縮します.decode関数はvectorのバッファをMatでキャストして使用します.
(2)png圧縮
jpegの時とほぼ同じです.ただし,圧縮のオプションが,CV_IMWRITE_PNG_COMPRESSION,その圧縮率が, 0-9(デフォルトが3)に変わっています.pngの場合,圧縮率を変化させても画質は原画像とまったく同じままですが,圧縮時間が長くなります.
(3)インタラクティブなjpeg圧縮
jpegの圧縮品質をトラックバーで変更しながら確認します.終了のキーは’q'です.
表示されている数字は品質を指定した数字,その画像品質を表すPSNR,1ピクセル当たり何bitで表現できているかを表すbpp(bit/pixel)です.グレイスケールの時は,8bppのときカラー画像の時は24bppのときに,圧縮がされていないデータを表し,最高品質の例では約1/3に画像が圧縮されています.
(4)画像の保存
‘s’キーで,圧縮により劣化した画像をpngで可逆圧縮,また,原画像をjpegで非可逆圧縮した画像をそれぞれ保存します.
ファイルに書き出す場合は,imwriteでもこのように圧縮率を指定可能です.指定しない場合(この場合pngの圧縮)はデフォルト引数でのパラメータとなります.