c++ - JPEG Compression using OpenCV -
i'm trying perform basic jpeg compression (dct + quantization + idct) using opencv not using entropy-encoding/huffman-coding. problem after decompress compressed image, not close in appearance original one.
i'm following these tutorials:
basic jpeg compressing/decompressing simulation
basic jpeg compression using opencv
following 3 images (original, compressed , decompressed images):
i'm using following matrix luminance , chrominance:
double dataluminance[8][8] = { {16, 11, 10, 16, 24, 40, 51, 61}, {12, 12, 14, 19, 26, 58, 60, 55}, {14, 13, 16, 24, 40, 57, 69, 56}, {14, 17, 22, 29, 51, 87, 80, 62}, {18, 22, 37, 56, 68, 109, 103, 77}, {24, 35, 55, 64, 81, 104, 113, 92}, {49, 64, 78, 87, 103, 121, 120, 101}, {72, 92, 95, 98, 112, 100, 103, 99} }; double datachrominance[8][8] = { {17, 18, 24, 27, 99, 99, 99, 99}, {18, 21, 26, 66, 99, 99, 99, 99}, {24, 26, 56, 99, 99, 99, 99, 99}, {47, 66, 99, 99, 99, 99, 99, 99}, {99, 99, 99, 99, 99, 99, 99, 99}, {99, 99, 99, 99, 99, 99, 99, 99}, {99, 99, 99, 99, 99, 99, 99, 99}, {99, 99, 99, 99, 99, 99, 99, 99} };
// edit 1: @micka told problem of using imread/imwrite, edited code use compressed image directly program.
the compression method is:
void imagecompression::compression(){ // getting original image size int height = imgoriginal.size().height; int width = imgoriginal.size().width; // converting image color mat imgcolorconverted; cvtcolor(imgoriginal, imgcolorconverted, cv_bgr2ycrcb); // transforming 2d array in image matrix mat luminance = mat(8,8, cv_64fc1, &dataluminance); mat chrominance = mat(8,8, cv_64fc1, &datachrominance); cout << "luminance: " << luminance << endl << endl; cout << "chrominance" << chrominance << endl << endl; // splitting image 3 planes vector<mat> planes; split(imgcolorconverted, planes); // downsampling chrominance // resizing 1/4 of original image resize(planes[1], planes[1], size(width/2, height/2)); resize(planes[2], planes[2], size(width/2, height/2)); // resizing original image size resize(planes[1], planes[1], size(width, height)); resize(planes[2], planes[2], size(width, height)); // dividing image in blocks 8x8 ( int = 0; < height; i+=8 ){ for( int j = 0; j < width; j+=8 ){ // each plane for( int plane = 0; plane < imgcolorconverted.channels(); plane++ ){ // creating block mat block = planes[plane](rect(j, i, 8, 8)); // converting block float block.convertto( block, cv_64fc1 ); // subtracting block 128 subtract( block, 128.0, block ); // dct dct( block, block ); // applying quantization if( plane == 0 ){ divide( block, luminance, block ); } else { divide( block, chrominance, block ); } // converting unsigned int block.convertto( block, cv_8uc1 ); // copying block original image block.copyto( planes[plane](rect(j, i, 8, 8)) ); } } } merge( planes, finalimage ); }
and decompression method:
imagecompression::decompression{ // getting size of image int height = finalimage.size().height; int width = finalimage.size().width; // transforming 2d array in image matrix mat luminance = mat(8,8, cv_64fc1, &dataluminance); mat chrominance = mat(8,8, cv_64fc1, &datachrominance); // splitting image 3 planes vector<mat> planes; split(finalimage, planes); // dividing image in blocks 8x8 ( int = 0; < height; i+=8 ){ for( int j = 0; j < width; j+=8 ){ // each plane for( int plane = 0; plane < finalimage.channels(); plane++ ){ // creating block mat block = planes[plane](rect(j, i, 8, 8)); // converting block float block.convertto( block, cv_64fc1 ); // applying dequantization if( plane == 0 ){ multiply( block, luminance, block ); } else { multiply( block, chrominance, block ); } // idct idct( block, block ); // adding 128 block add( block, 128.0, block ); // converting unsigned int block.convertto( block, cv_8uc1 ); // copying block original image block.copyto( planes[plane](rect(j, i, 8, 8)) ); } } } merge(planes, finalimage); cvtcolor( finalimage, finalimage, cv_ycrcb2bgr ); imshow("decompressed image", finalimage); waitkey(0); imwrite(".../finalresult.jpg", finalimage); }
does have idea of why i'm getting resulting image?
thank you.
you need add 128 block before converting unsigned int , subtract again in decompression.
add(block, 128.0, block); // converting unsigned int block.convertto(block, cv_8uc1);
.
// converting block float block.convertto(block, cv_64fc1); subtract(block, 128.0, block);
Comments
Post a Comment