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개의 기저 함수

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 계수 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.