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 个基函数

64 basis functions are arranged in an 8-by-8 grid. As the row and column indices in the grid increase, the basis functions have higher vertical and horizontal frequencies, respectively.

水平频率从左到右递增,垂直频率从上到下递增。左上角的常量值基函数通常称为 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)