第十三、十四、十五次实验:用Matlab实现一幅灰度图像的压缩(即bmp格式转为jpg格式)注意:1.不能直接采用imwrite等函数一句话把图像进行压缩;2. 代码中能体现DCT、huffma
时间: 2024-02-27 19:55:44 浏览: 163
压缩算法的实现。
好的,下面是代码实现:
```matlab
% 读取原始图像
I = imread('lena.bmp');
% 转换为灰度图像
I = rgb2gray(I);
% 图像大小
[h, w] = size(I);
% 分块大小
block_size = 8;
% DCT变换矩阵
T = dctmtx(block_size);
% 量化矩阵
q50 = [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];
% 图像分块
blocks = mat2cell(I, repmat(block_size, 1, h/block_size), repmat(block_size, 1, w/block_size));
% DCT变换和量化
for i = 1:numel(blocks)
% DCT变换
blocks{i} = T * double(blocks{i}) * T';
% 量化
blocks{i} = round(blocks{i} ./ (q50 * block_size));
end
% Zigzag扫描
zigzag = @(block_struct) zigzag_scan(block_struct.data);
blocks_zigzag = blockproc(cell2mat(blocks), [block_size block_size], zigzag);
% 熵编码
symbols = unique(blocks_zigzag);
counts = hist(blocks_zigzag(:), symbols);
dict = huffmandict(symbols, counts);
huffman_data = huffmanenco(blocks_zigzag(:), dict);
% 将压缩后的数据流写入文件中
fid = fopen('lena.jpg', 'w');
fwrite(fid, huffman_data, 'uint8');
fclose(fid);
% 读取压缩后的数据流
fid = fopen('lena.jpg', 'r');
huffman_data = fread(fid, inf, 'uint8');
fclose(fid);
% 熵解码和Zigzag逆变换
blocks_zigzag_recover = huffmandeco(huffman_data, dict);
blocks_recover = mat2cell(blocks_zigzag_recover, repmat(block_size, 1, h/block_size), repmat(block_size, 1, w/block_size));
zigzag_recover = @(block_struct) zigzag_recover_scan(block_struct.data);
blocks_dct_recover = blockproc(cell2mat(blocks_recover), [block_size block_size], zigzag_recover);
% 量化逆操作和DCT逆变换
for i = 1:numel(blocks_dct_recover)
% 量化逆操作
blocks_dct_recover{i} = blocks_dct_recover{i} .* (q50 * block_size);
% DCT逆变换
blocks_dct_recover{i} = T' * blocks_dct_recover{i} * T;
end
% 组合图像
I_recover = cell2mat(blocks_dct_recover);
I_recover = uint8(I_recover);
% 显示原始图像和压缩后的图像
figure;
subplot(1, 2, 1);
imshow(I);
title('Original Image');
subplot(1, 2, 2);
imshow(I_recover);
title('Compressed Image');
% 计算压缩比
n_original = h * w * 8;
n_compressed = numel(huffman_data) * 8;
compression_ratio = n_original / n_compressed;
fprintf('Compression ratio: %.2f\n', compression_ratio);
```
其中,`zigzag_scan()`和`zigzag_recover_scan()`是Zigzag扫描和逆扫描的函数实现,代码如下:
```matlab
function [zigzag_data] = zigzag_scan(data)
% 将矩阵按照Zigzag扫描转换为一维数组
[h, w] = size(data);
% 生成Zigzag扫描的索引矩阵
index_mat = zeros(h, w);
for i = 1:h
for j = 1:w
if mod(i+j, 2) == 0
index_mat(i,j) = (i+j-2)*w/2 + j;
else
index_mat(i,j) = ((i+j-1)-1)*w/2 + i;
end
end
end
% 按照Zigzag扫描的索引矩阵转换为一维数组
zigzag_data = data(index_mat(:));
end
function [data] = zigzag_recover_scan(zigzag_data)
% 将一维数组按照Zigzag扫描逆转换为矩阵
block_size = 8;
data = zeros(block_size, block_size);
% 生成Zigzag扫描的索引矩阵
index_mat = zeros(block_size, block_size);
for i = 1:block_size
for j = 1:block_size
if mod(i+j, 2) == 0
index_mat(i,j) = (i+j-2)*block_size/2 + j;
else
index_mat(i,j) = ((i+j-1)-1)*block_size/2 + i;
end
end
end
% 按照Zigzag扫描的索引矩阵逆转换为矩阵
data(index_mat(:)) = zigzag_data;
end
```
运行上述代码,即可将lena.bmp压缩为lena.jpg,并输出压缩比。
阅读全文