Main Content

本页对应的英文页面已更新,但尚未翻译。 若要查看最新内容,请点击此处访问英文页面。

离散余弦变换

DCT 定义

离散余弦变换 (DCT) 将图像表示为不同幅值和频率的正弦的总和。dct2 函数计算图像的二维离散余弦变换 (DCT)。对于典型图像,DCT 具有这样的属性,即关于图像的大部分视觉上显著的信息只集中在 DCT 的几个系数中。因此,DCT 经常用于图像压缩应用。例如,DCT 是国际标准有损图像压缩算法 JPEG 的核心。此名称来自制定标准的工作组:联合图像专家组,即 Joint Photographic Experts Group。

M×N 矩阵 A 的二维 DCT 定义如下。

Bpq=αpαqm=0M1n=0N1Amncosπ(2m+1)p2Mcosπ(2n+1)q2N,0pM10qN1αp={1/M,2/M,p=01pM1αq={1/N,2/N,q=01qN1

Bpq 称为 ADCT 系数。(请注意,MATLAB® 中的矩阵索引始终从 1 开始,而不是从 0 开始;因此,MATLAB 矩阵元素 A(1,1)B(1,1) 分别对应于数学量 A00B00。)

DCT 是一种可逆变换,其逆变换由下式给出

Amn=p=0M1q=0N1αpαqBpqcosπ(2m+1)p2Mcosπ(2n+1)q2N,0mM10nN1αp={1/M,2/M,p=01pM1αq={1/N,2/N,q=01qN1

逆 DCT 方程可以理解为任何 M×N 矩阵 A 可写为以下形式的 MN 函数之和:

αpαqcosπ(2m+1)p2Mcosπ(2n+1)q2N,   0pM10qN1

这些函数称为 DCT 的基函数。然后,DCT 系数 Bpq 可视为应用于每个基函数的权重。对于 8×8 矩阵,该图可表示为 64 个基函数。

构成 8×8 矩阵的 64 个基函数

水平频率从左到右递增,垂直频率从上到下递增。左上角的常量值基函数通常称为 DC 基函数,对应的 DCT 系数 B00 通常称为 DC 系数

DCT 变换矩阵

使用 Image Processing Toolbox™ 软件有两种计算 DCT 的方法。第一种方法是使用 dct2 函数。dct2 使用基于 FFT 的算法对大型输入实现快速计算。第二种方法是使用 DCT 变换矩阵,该矩阵由函数 dctmtx 返回,对于小型方阵输入(如 8×8 或 16×16)可能更高效。M×M 变换矩阵 T 由下式给出

Tpq={1M2Mcosπ(2q+1)p2Mp=0,1pM1,0qM10qM1

对于 M×M 矩阵 AT*A 是 M×M 矩阵,其列包含由 A 的列组成的一维 DCT。A 的二维 DCT 可以计算为 B=T*A*T'。由于 T 是实数正交矩阵,它的逆矩阵与它的转置矩阵相同。因此,B 的逆二维 DCT 由 T'*B*T 给出。

使用离散余弦变换的图像压缩

此示例说明如何使用离散余弦变换 (DCT) 压缩图像。该示例计算输入图像中 8×8 个数据块的二维 DCT,丢弃(设置为零)每个数据块中 64 个 DCT 系数中除 10 个以外的所有系数,然后使用每个数据块的二维逆 DCT 重构图像。该示例使用变换矩阵计算方法。

在 JPEG 图像压缩算法中使用 DCT。将输入图像分成 8×8 或 16×16 个数据块,并对每个数据块计算二维 DCT。然后对 DCT 系数进行量化、编码和传输。JPEG 接收器(或 JPEG 文件读取器)对量化的 DCT 系数进行解码,计算每个数据块的逆二维 DCT,然后将这些数据块一起放回单个图像中。对于典型图像,许多 DCT 系数的值接近于零。可以丢弃这些系数,而不会严重影响重构图像的质量。

将图像读入工作区,并将其转换为 double 类。

I = imread('cameraman.tif');
I = im2double(I);

计算图像中 8×8 个数据块的二维 DCT。函数 dctmtx 返回 N×N DCT 变换矩阵。

T = dctmtx(8);
dct = @(block_struct) T * block_struct.data * T';
B = blockproc(I,[8 8],dct);

丢弃每个数据块中 64 个 DCT 系数的大部分系数,仅保留 10 个。

mask = [1   1   1   1   0   0   0   0
        1   1   1   0   0   0   0   0
        1   1   0   0   0   0   0   0
        1   0   0   0   0   0   0   0
        0   0   0   0   0   0   0   0
        0   0   0   0   0   0   0   0
        0   0   0   0   0   0   0   0
        0   0   0   0   0   0   0   0];
B2 = blockproc(B,[8 8],@(block_struct) mask .* block_struct.data);

使用每个数据块的二维逆 DCT 重构图像。

invdct = @(block_struct) T' * block_struct.data * T;
I2 = blockproc(B2,[8 8],invdct);

并排显示原始图像和重构图像。尽管几乎 85% 的 DCT 系数被丢弃,导致重构图像的质量有所下降,但它仍是清晰可辨的。

imshow(I)

figure
imshow(I2)