图像变换编码是将空间域中像素形式描述的图像转换至变换域,以变换系数的形式加以表示,可使图像能量在空间域的分散分布转为在变换域的相对集中分布,已达到去除空间冗余的目的。
变换编码系统通常包括正交变换、变换系数选择和量化编码3个模块。需要说明的是,正交变换本身并不能压缩数据,它只把信号映射到另一个域,但由于变换后系数之同的相关性明显降低,为在变换域里进行有效的压缩创造了有利条件。经过正交变换后,变换系数间相关性基本解除,近似是统计独立的,并且图像的大部分能量主要集中在直流和少数低空间频率的变换系数上,通过选择保留其中一些对重建图像质量重要的变換系数(丟弃一些无关紧要的变换系数),对其进行适当的量化和熵编码就可以有效地压缩图像的数据量。而且图像经某些变换后,系数的空间分布和频率特性能与人眼的视觉特性匹配,因此可以利用人类视觉系统的生理和心理特性,在提高压缩比的同时又保证有较好的主观图像质量。
基于DCT的图像编码
DCT变换,即离散余弦变换,是一种将图像数据从像素域转换到频率域的数学变换。它是一种正交变换,能够将图像信号分解为不同频率的成分。
DCT变换的流程图如下所示。
DCT变换的具体步骤如下:
-
图像分块:将图像分割成大小相等的块,通常是8x8或16x16的块。这是因为DCT变换通常是针对小块数据进行的,这些块可以重叠或不重叠,具体取决于编码算法。
-
颜色空间转换:将图像从RGB颜色空间转换为亮度-色度(YCbCr)颜色空间。Y分量表示图像的亮度,而Cb和Cr分量表示色度。这种转换通常能够更好地利用人眼对亮度和色彩的感知特性。
-
预处理:对每个块进行预处理,通常是将每个像素值减去128(即128中心化)。这是因为DCT变换对中心化的数据效果更好,可以使得变换后的直流分量(DC)集中在块的左上角。
-
执行DCT变换:对每个块应用二维DCT变换,DCT变换将每个块从空间域转换到频域。在频域中,大部分图像信息通常集中在少量的低频分量上,而高频分量则包含了图像的细节信息。
-
量化:DCT变换后的系数通常会被量化。量化是一种损失性压缩技术,它通过舍弃一些信息来减少数据量。在量化过程中,通常对高频分量进行更大程度的量化,因为它们包含的信息相对较少,而对低频分量进行较小程度的量化,以保留图像的主要特征。量化公式为:
其中,Q(u,v) 是量化表中的相应值。 -
编码:量化后的DCT系数接下来会进行编码。这通常包括将二维系数通过zigzag扫描转换为一维序列,然后使用熵编码(如Huffman编码或算术编码)进行压缩。
-
反量化:对解码后的数据进行反量化,以恢复部分损失的信息。
-
反DCT变换:对反量化后的数据进行反DCT变换,将图像从频域转换回空间域。
-
逆色彩空间转换:将图像从YCbCr颜色空间转换回RGB颜色空间,以便输出显示或进一步处理。
基于MATLAB实现DCT变换和反DCT变换
读取图像:使用imread函数读取图像。
转换颜色空间:如果图像是彩色的,使用rgb2ycbcr函数将其转换到YCbCr颜色空间。
分块处理:将图像分割成8x8的块。
执行DCT变换:对每个块应用DCT变换。
执行反DCT变换:对DCT变换后的块应用反DCT变换。
重建图像:将反DCT变换后的块重新组合成图像。
显示结果:显示原始图像和重建图像。
% 读取图像
img = imread('example.jpg');
% 转换到YCbCr颜色空间
img_ycbcr = rgb2ycbcr(img);
% 提取Y分量,因为DCT通常应用于亮度分量
Y = img_ycbcr(:,:,1);
% 分割图像为8x8块
block_size = 8;
num_blocks_row = size(Y, 1) / block_size;
num_blocks_col = size(Y, 2) / block_size;
dct_blocks = cell(num_blocks_row, num_blocks_col);
% 对每个块执行DCT变换
for i = 1:num_blocks_row
for j = 1:num_blocks_col
block = Y((i-1)*block_size+1:i*block_size, (j-1)*block_size+1:j*block_size);
dct_blocks{i,j} = dct2(double(block));
end
end
% 对每个块执行反DCT变换
idct_blocks = cell(num_blocks_row, num_blocks_col);
for i = 1:num_blocks_row
for j = 1:num_blocks_col
idct_blocks{i,j} = idct2(dct_blocks{i,j});
end
end
% 将反DCT变换后的块重新组合成图像
idct_image = zeros(size(Y));
for i = 1:num_blocks_row
for j = 1:num_blocks_col
idct_image((i-1)*block_size+1:i*block_size, (j-1)*block_size+1:j*block_size) = idct_blocks{i,j};
end
end
% 显示结果
subplot(1, 2, 1);
imshow(uint8(Y));
title('Original Image');
subplot(1, 2, 2);
imshow(uint8(idct_image));
title('Reconstructed Image');