Main Content

이산 코사인 변환

DCT 정의

이산 코사인 변환(DCT)은 영상을 다양한 크기 및 주파수를 갖는 정현파의 합으로 표현합니다. dct2 함수는 영상의 2차원 이산 코사인 변환(DCT)을 계산합니다. 일반적인 영상에 DCT를 적용하는 경우를 보면 시각적으로 의미있는 영상 정보의 대부분이 단 몇 개의 DCT 계수에 집중된다는 특징이 있습니다. 이러한 이유로 영상 압축 응용 분야에서는 DCT를 자주 사용합니다. 예를 들어, JPEG라는 국제 표준 손실 영상 압축 알고리즘의 중심에는 DCT가 있습니다. (JPEG는 이 표준을 개발한 단체인 Joint Photographic Experts Group의 줄임말로 만든 이름입니다.)

M×N 행렬 A의 2차원 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

BpqADCT 계수입니다. (MATLAB®의 행렬 인덱스는 항상 0이 아닌 1에서 시작하므로 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 계수 B00DC 계수라고 합니다.

DCT 변환 행렬

Image Processing Toolbox™를 사용하여 DCT를 계산하는 방법에는 두 가지가 있습니다. 첫 번째 방법은 dct2 함수를 사용하는 것입니다. dct2는 입력값이 클 때 빠르게 계산하기 위해 FFT 기반 알고리즘을 사용합니다. 두 번째 방법은 DCT 변환 행렬을 사용하는 것입니다. DCT 변환 행렬은 함수 dctmtx에서 반환하며, 8×8, 16×16과 같이 작은 정사각 입력값의 경우 더 효율적일 수 있습니다. M×M 변환 행렬 T는 다음과 같이 표현됩니다.

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

M×M 행렬 A에서 T*A는 각 열이 A 열의 1차원 DCT를 포함하는 M×M 행렬입니다. A의 2차원 DCT는 B=T*A*T'로 계산할 수 있습니다. T는 실수 정규 직교 행렬이므로 그 역은 전치와 같습니다. 따라서 B의 2차원 역 DCT는 T'*B*T로 표현됩니다.

이산 코사인 변환을 사용한 영상 압축

이 예제에서는 이산 코사인 변환(DCT)을 사용하여 영상을 압축하는 방법을 보여줍니다. 이 예제에서는 입력 영상에서 8×8 블록의 2차원 DCT를 계산하고, 각 블록에서 64개의 DCT 계수 중 10개만 남기고 모두 버린 다음(0으로 설정), 각 블록의 2차원 역 DCT를 사용하여 영상을 복원합니다. 이 예제에서는 변환 행렬 계산 방법을 사용합니다.

DCT는 JPEG 영상 압축 알고리즘에서 사용됩니다. 입력 영상을 8×8 또는 16×16 블록으로 나눈 후에 각 블록에 대해 2차원 DCT를 계산합니다. 그런 다음 DCT 계수를 양자화하고 부호화하여 전달합니다. JPEG 수신기(또는 JPEG 파일 판독기)는 양자화된 DCT 계수를 복호화하고, 각 블록의 역 2차원 DCT를 계산한 다음, 이 블록들을 다시 합쳐 하나의 영상으로 만듭니다. 일반적인 영상은 대부분의 DCT 계수가 0에 가까운 값을 갖습니다. 이러한 계수는 버려도 복원된 영상의 품질에 심각한 영향을 주지 않습니다.

영상을 작업 공간으로 읽어 들인 후 double형 클래스로 변환합니다.

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

영상에서 8×8 블록 단위로 2차원 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);

각 블록의 2차원 역 DCT를 사용하여 영상을 복원합니다.

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

원본 영상과 복원 영상을 나란히 표시합니다. 복원된 영상에서 어느 정도의 품질 저하가 발생하긴 하지만 DCT 계수의 85% 정도를 버렸음에도 불구하고 영상을 분명히 알아볼 수 있습니다.

imshow(I)

Figure contains an axes object. The axes object contains an object of type image.

figure
imshow(I2)

Figure contains an axes object. The axes object contains an object of type image.