GitHub ↗
CHAPTER 04 OF 10
🎚️

DCT and Quantization

DCT와 양자화 — 변환과 손실의 수학

코덱의 손실은 양자화 한 단계에서만 일어난다. 양자화의 정확한 의미와 CRF·QP 같은 옵션이 실제로 무엇을 하는지 알면, 화질과 용량의 트레이드오프를 손에 잡힌다.

DCT and Quantization cheatsheet
🍌 NANO BANANA CHEATSHEET · CH 04

Overview

개관

3장에서 PTQE 파이프라인의 큰 그림을 봤다. 이번 장은 그 중 가장 신비롭게 들리는 두 단계 — 변환(Transform)양자화(Quantization) — 를 깊이 본다.

이 두 단계의 정확한 의미를 알면 실무에서 자주 만지는 옵션들(CRF, QP, CBR, VBR)이 정확히 무엇을 하는지 보인다. 'CRF 23이 좋은가 28이 좋은가'에 답할 수 있게 된다.

🎯 Learning Goals
  • 2D DCT가 무엇을 하는지 그림으로 설명할 수 있다
  • 양자화 매트릭스가 왜 균일하지 않은지(시각적 중복 활용) 안다
  • QP와 CRF의 관계를 안다
  • CBR/VBR/CRF 세 가지 비트레이트 모드의 차이를 구분한다
  • Rate-Distortion 곡선이 코덱 평가의 핵심임을 이해한다

Sections

본문

4.1 2D DCT — 8×8 블록을 주파수로 분해

DCT(Discrete Cosine Transform)는 이산 코사인 변환. 8×8 픽셀 블록을 입력하면 8×8 계수 행렬을 출력하는데, 이 출력의 의미는 "입력 블록을 64개의 기본 무늬(basis function)의 가중합으로 표현했을 때의 가중치"다.

64개의 기본 무늬는 정해져 있다. 왼쪽 위는 '균일한 회색', 오른쪽 아래는 '체크무늬', 가운데는 '줄무늬' 등. 저주파(부드러운 변화)는 왼쪽 위, 고주파(빠른 변화)는 오른쪽 아래.

핵심 사실: 자연 이미지의 에너지가 저주파 몇 개 계수에 집중된다. 한 8×8 블록에서 64개 계수 중 의미 있는 값은 보통 5~10개 정도. 나머지는 거의 0. 이 성질이 압축의 자원이다.

DCT는 가역적이다. 역DCT(IDCT)로 손실 없이 복원 가능. DCT 자체로는 데이터를 줄이지 않는다 — 데이터를 '양자화하기 좋은 형태'로 옮길 뿐이다.

4.2 양자화 매트릭스 — 시각적 중복의 직접적 사용

DCT 결과를 양자화 매트릭스(Q)로 나누어 정수로 반올림한다. Q는 8×8 행렬이고, 값이 위치마다 다르다. 표준 JPEG Q를 보면:

`` 16 11 10 16 24 40 51 61 12 12 14 19 26 58 60 55 14 13 16 24 40 57 69 56 ... 72 92 95 98 112 100 103 99 ``

왼쪽 위(저주파)는 12~16처럼 작고, 오른쪽 아래(고주파)는 99~112처럼 크다. 저주파는 정밀하게 보존, 고주파는 거칠게 양자화.

왜? 인간 눈은 저주파(부드러운 그라데이션)의 변화에 민감하고, 고주파(미세한 디테일)엔 둔감하기 때문. 시각적 중복의 직접적 활용이다.

JPEG·H.264·H.265·AV1 모두 이 비대칭 양자화를 쓴다. 디테일은 다르지만 정신은 같다.

4.3 QP와 CRF — 사용자가 만지는 손잡이

양자화의 강도를 결정하는 게 QP(Quantization Parameter) 다. 0(완벽)~51(최대 손실). QP를 6 올리면 양자화 스텝이 정확히 2배 커진다.

실제 인코더는 QP를 직접 다루지 않고 CRF(Constant Rate Factor) 라는 추상 레이어를 제공한다. CRF는 "같은 시각적 화질을 유지하도록 QP를 동적으로 조절". 즉 빠른 움직임 장면엔 QP를 올리고(어차피 안 보임), 정적 장면엔 QP를 내림(정밀하게).

CRF 값의 의미: - H.264: CRF 18(거의 무손실) ~ 28(저화질), 기본 23 - H.265: CRF 22 ~ 32, 기본 28 - AV1: CRF 25 ~ 35, 기본 30

같은 CRF여도 코덱이 다르면 결과가 다르다. H.264 CRF 23과 H.265 CRF 28이 비슷한 화질·비슷한 용량. 실무 팁: "H.264 CRF 23 = 좋은 기본값", "H.265 CRF 28 = 좋은 기본값". 외워두면 일상의 90%를 커버.

4.4 CBR vs VBR vs CRF — 세 가지 비트레이트 모드

비트레이트 제어 모드는 세 가지.

CBR (Constant Bit Rate): 비트레이트 일정 유지. 정적 장면도 액션 장면도 같은 비트레이트. 화질이 균일하지 않음(액션에선 깨짐). 라이브 방송에 필수 — 네트워크 대역폭이 일정해야 하니까.

VBR (Variable Bit Rate): 평균 비트레이트 목표, 장면에 따라 가변. 정적엔 적게 쓰고 액션엔 많이 씀. CBR보다 화질 균일. 평균 비트레이트가 고정된 게 핵심.

CRF (Constant Rate Factor): 화질 일정 유지, 비트레이트 가변. 정적은 작고 액션은 크다. 파일 크기를 미리 모름. 다운로드용·아카이브용에 최적.

선택 기준: - 라이브 스트리밍 → CBR (대역폭 보장 필수) - VOD 스트리밍(Netflix 식) → VBR (파일 크기 예측 + 균일 화질) - 다운로드·후반작업 → CRF (최고 효율, 크기 무관) - 일반 사용자가 ffmpeg로 변환 → CRF 23(H.264) 또는 CRF 28(H.265)

4.5 Rate-Distortion 곡선 — 코덱 평가의 표준

코덱을 비교할 때 "화질이 좋다" 는 주관적이라 객관적 측정이 필요하다. 표준은 Rate-Distortion 곡선.

Y축은 화질 측정값(PSNR, SSIM, VMAF), X축은 비트레이트. 각 CRF 값마다 한 점을 찍어 곡선을 만든다. 곡선이 위쪽에 있을수록 좋은 코덱 — 같은 비트레이트에서 더 좋은 화질, 또는 같은 화질에 더 적은 비트레이트.

주요 화질 측정값: - PSNR (Peak Signal-to-Noise Ratio): 픽셀 단위 오차. 단순하지만 사람 인지와 잘 안 맞음. dB 단위. - SSIM: 구조 유사도. PSNR보다 사람 인지에 가까움. - VMAF: Netflix가 만든 머신러닝 기반 메트릭. 현재 산업 표준. 0~100 점수.

AV1이 'H.265 대비 30% 좋다'고 할 때 그 비교가 보통 같은 VMAF 점수에서의 비트레이트 차이를 본다. 엔지니어가 코덱을 평가할 땐 항상 R-D 곡선을 본다 — 한 점만 비교하면 오해 가능.

💡 Analogy · 비유
오케스트라를 압축하기

베토벤 5번 교향곡을 녹음할 때 모든 악기 모든 순간 동등하게 정밀하게 녹음할 필요는 없다. 베이스 라인(저주파)은 정밀해야 한다 — 사람 귀가 베이스의 미세한 변화를 느낀다. 심벌즈의 고주파 노이즈는 거칠게 녹음해도 사람이 못 알아챈다.

그래서 음악 압축은 "저주파에 비트를 많이, 고주파에 비트를 적게" 분배한다. 같은 파일 크기에 사람 귀에 더 좋은 음질.

DCT + 양자화 매트릭스가 정확히 이 일을 한다. 한 8×8 블록을 64개 "음(주파수)"으로 분해한 다음, 저주파 음은 정밀하게, 고주파 음은 거칠게 양자화. 결과: 같은 파일 크기에 사람 눈에 더 좋은 화질. CRF는 그 양자화의 전체 강도를 한 손잡이로 조절하는 것.

CRF 값을 18, 23, 28, 33으로 바꾸면서 같은 영상을 인코딩한 다음, 파일 크기와 VMAF 점수를 측정. Rate-Distortion 곡선의 한 점을 직접 만들어 본다.

python
import subprocess, os, json

INPUT = 'sample.mp4'
results = []

for crf in [18, 23, 28, 33]:
    output = f'out_crf{crf}.mp4'
    # 1) Encode with the given CRF
    subprocess.run([
        'ffmpeg', '-y', '-i', INPUT,
        '-c:v', 'libx264', '-crf', str(crf),
        '-preset', 'medium', '-an', output
    ], check=True, capture_output=True)

    size_mb = os.path.getsize(output) / 1e6

    # 2) Compute VMAF against the original (libvmaf filter)
    out = subprocess.run([
        'ffmpeg', '-i', output, '-i', INPUT,
        '-lavfi', 'libvmaf=log_path=vmaf.json:log_fmt=json',
        '-f', 'null', '-'
    ], check=True, capture_output=True)
    vmaf = json.load(open('vmaf.json'))['pooled_metrics']['vmaf']['mean']

    results.append((crf, size_mb, vmaf))
    print(f'CRF {crf:2d}: {size_mb:6.1f} MB, VMAF={vmaf:5.1f}')

# 결과 예시:
# CRF 18:  85.3 MB, VMAF=98.7  ← 거의 무손실, 거대
# CRF 23:  22.1 MB, VMAF=95.2  ← 표준, 작음
# CRF 28:   7.4 MB, VMAF=88.6  ← 작지만 살짝 깨짐 보임
# CRF 33:   2.8 MB, VMAF=75.4  ← 명확히 화질 떨어짐

CRF 5단계 차이가 파일 크기를 2~3배 바꾼다는 사실이 직접 보인다. VMAF는 90 이상이면 거의 인지 못 함, 80~90은 살짝 보임, 70 이하는 명확히 깨짐. 일반적으로 CRF 23(H.264) 또는 28(H.265)이 VMAF 90~95 정도라 사람 눈에 좋고 파일 크기도 합리적인 sweet spot.

🏭 현업에서의 평가
DCT·양자화·CRF는 비디오 엔지니어 일상의 한가운데. 모든 인코딩 결정이 이 한 손잡이를 어떻게 돌리느냐.

✅ 시니어가 보는 것

  • QP와 CRF의 관계를 정확히 안다
  • CBR/VBR/CRF 선택 기준을 도메인별로 댈 수 있다
  • VMAF·SSIM·PSNR의 차이를 안다
  • Rate-Distortion 곡선으로 코덱 비교 가능

⚠️ 레드 플래그

  • 'CRF 낮을수록 좋다'를 화질 면에서 정확히 모름
  • 라이브 방송에 CRF 모드 쓰려고 함 (CBR이 맞음)
  • 한 점만 보고 코덱 우열 판단
  • PSNR이 화질이라고 생각 (사람 인지와 다름)

🎤 예상 인터뷰 질문

  1. CRF 23과 28의 차이를 H.264·H.265 각각 설명해 주세요
  2. 라이브 방송에 CBR을 쓰는 이유는?
  3. VMAF가 PSNR보다 좋은 메트릭으로 평가받는 이유는?
숙달 vs 익숙함: Familiar는 'CRF 23 쓰면 된다'를 안다. Mastery는 CRF·QP·CBR·VBR의 사용 도메인을 매핑하고, R-D 곡선으로 코덱을 비교하며, VMAF로 객관적 평가를 한다.

Key Takeaways

핵심 정리

DCT

8×8 블록을 주파수 도메인으로. 가역적.

양자화 = 손실

유일한 lossy 단계. 매트릭스로 비대칭 분배.

QP / CRF

양자화 강도. 낮을수록 정밀(고화질·고용량).

CBR vs VBR vs CRF

비트레이트 일정 vs 평균 일정 vs 화질 일정.

라이브엔 CBR

대역폭 보장 필수.

VOD엔 VBR/CRF

파일 크기 vs 화질 균일.

VMAF가 표준

Netflix 기준. 사람 인지에 가까움.

R-D 곡선

코덱 비교의 표준. 한 점만 보면 오해.