gpt4 book ai didi

c++ - 使用 OpenCV 进行 JPEG 压缩

转载 作者:塔克拉玛干 更新时间:2023-11-03 07:50:39 25 4
gpt4 key购买 nike

我正在尝试使用 OpenCV 执行基本的 JPEG 压缩(DCT + 量化 + IDCT),而不是使用熵编码/霍夫曼编码。问题是在我解压缩压缩图像后,它的外观与原始图像甚至都不接近。

我正在学习这些教程:

Basic JPEG Compressing/Decompressing Simulation

Basic JPEG Compression using OpenCV

以下是 3 个图像(原始图像、压缩图像和解压缩图像): Original Image

Compressed Image

Final Image

我使用以下矩阵来表示亮度和色度:

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}
};

//编辑 1:@Micka 讲述了使用 imread/imwrite 的问题,所以我编辑了我的代码以直接从我的程序中使用压缩图像。

压缩方式为:

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 the image into 3 planes
vector<Mat> planes;
split(imgColorConverted, planes);

// Downsampling chrominance
// Resizing to 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 to original image size
resize(planes[1], planes[1], Size(width, height));
resize(planes[2], planes[2], Size(width, height));

// Dividing image in blocks 8x8
for ( int i = 0; i < height; i+=8 ){
for( int j = 0; j < width; j+=8 ){
// For each plane
for( int plane = 0; plane < imgColorConverted.channels(); plane++ ){

// Creating a block
Mat block = planes[plane](Rect(j, i, 8, 8));

// Converting the block to float
block.convertTo( block, CV_64FC1 );

// Subtracting the block by 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 it back to unsigned int
block.convertTo( block, CV_8UC1 );

// Copying the block to the original image
block.copyTo( planes[plane](Rect(j, i, 8, 8)) );
}
}
}

merge( planes, finalImage );
}

还有我的解压方法:

ImageCompression::decompression{
// Getting the size of the 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 the image into 3 planes
vector<Mat> planes;
split(finalImage, planes);

// Dividing the image in blocks 8x8
for ( int i = 0; i < height; i+=8 ){
for( int j = 0; j < width; j+=8 ){
// For each plane
for( int plane = 0; plane < finalImage.channels(); plane++ ){

// Creating a block
Mat block = planes[plane](Rect(j, i, 8, 8));

// Converting the block to 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 to the block
add( block, 128.0, block );

// Converting it back to unsigned int
block.convertTo( block, CV_8UC1 );

// Copying the block to the 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);
}

有人知道我为什么会得到结果图像吗?

谢谢。

最佳答案

在将其转换回 unsigned int 之前,您需要将 128 添加回 block ,然后在解压时再次减去它。

            add(block, 128.0, block);

// Converting it back to unsigned int
block.convertTo(block, CV_8UC1);

.

        // Converting the block to float
block.convertTo(block, CV_64FC1);

subtract(block, 128.0, block);

关于c++ - 使用 OpenCV 进行 JPEG 压缩,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29638440/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com