请给出Matlab实现一幅灰度图像的压缩(即bmp格式转为jpg格式)的代码。 注意: 不能直接采用imwrite等函数一句话把图像进行压缩; 代码中能体现DCT、huffman等步骤,步骤中功能函数可以直接调用; 对比显示效果、计算压缩比。
时间: 2024-02-27 18:53:14 浏览: 67
基于matlab利用DCT变换对灰度图像进行压缩,求出压缩比;对比不同压缩比的图像
5星 · 资源好评率100%
好的,以下是基于您的要求编写的Matlab代码,该代码可以将一幅灰度图像(BMP格式)压缩为JPEG格式:
```matlab
% 读取原始图像
img = imread('input.bmp');
gray_img = rgb2gray(img);
% 设置DCT块大小
block_size = 8;
% 将图像分块
img_size = size(gray_img);
num_blocks = prod(floor(img_size/block_size));
blocks = zeros(block_size^2, num_blocks);
col = 1;
for i = 1:block_size:img_size(1)-block_size+1
for j = 1:block_size:img_size(2)-block_size+1
blocks(:,col) = reshape(gray_img(i:i+block_size-1, j:j+block_size-1), [], 1);
col = col + 1;
end
end
% 对每个块进行DCT变换
dct_blocks = zeros(size(blocks));
for i = 1:num_blocks
dct_blocks(:,i) = dct2(reshape(blocks(:,i), block_size, block_size));
end
% 设置量化矩阵
quant_matrix = [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];
% 量化DCT系数
quant_blocks = zeros(size(dct_blocks));
for i = 1:num_blocks
quant_blocks(:,i) = round(dct_blocks(:,i)./quant_matrix(:));
end
% 对量化后的系数进行哈夫曼编码
symbols = unique(quant_blocks(:));
counts = histc(quant_blocks(:), symbols);
p = counts/sum(counts);
dict = huffmandict(symbols, p);
huffman_codes = huffmanenco(quant_blocks(:), dict);
% 保存压缩后的数据到JPEG文件
output_file = 'output.jpg';
fid = fopen(output_file, 'wb');
fwrite(fid, dict(:), 'uint8');
fwrite(fid, numel(huffman_codes), 'uint32');
fwrite(fid, huffman_codes, 'ubit1');
fclose(fid);
% 读取压缩后的JPEG文件
fid = fopen(output_file, 'rb');
dict = fread(fid, 256, 'uint8');
dict = reshape(dict, 2, [])';
huffman_size = fread(fid, 1, 'uint32');
huffman_codes = fread(fid, huffman_size, 'ubit1');
fclose(fid);
% 对哈夫曼编码进行解码
quant_blocks = huffmandeco(huffman_codes, dict);
% 反量化DCT系数
dct_blocks = zeros(size(quant_blocks));
for i = 1:num_blocks
dct_blocks(:,i) = quant_blocks(:,i).*quant_matrix(:);
end
% 对每个块进行IDCT变换
recon_blocks = zeros(size(blocks));
for i = 1:num_blocks
recon_blocks(:,i) = idct2(reshape(dct_blocks(:,i), block_size, block_size));
end
% 合并块为压缩后的图像
recon_img = zeros(size(gray_img));
col = 1;
for i = 1:block_size:img_size(1)-block_size+1
for j = 1:block_size:img_size(2)-block_size+1
recon_img(i:i+block_size-1, j:j+block_size-1) = reshape(recon_blocks(:,col), block_size, block_size);
col = col + 1;
end
end
% 显示原始图像和压缩后的图像
figure;
subplot(1,2,1);
imshow(gray_img);
title('Original Image');
subplot(1,2,2);
imshow(uint8(recon_img));
title('Compressed Image');
% 计算压缩比
orig_size = prod(img_size);
compressed_size = numel(dict) + 4 + numel(huffman_codes)/8;
compression_ratio = orig_size/compressed_size;
fprintf('Compression Ratio: %.2f\n', compression_ratio);
```
需要注意的是,由于JPEG压缩是有损压缩,因此压缩后的图像质量会有所下降。我们可以通过调整量化矩阵来平衡压缩率和图像质量。另外,这个示例中还有很多可以改进的地方,比如添加DC系数的编码、使用Zigzag扫描方式等等。
阅读全文