GitHub ↗
CHAPTER 05 OF 10
🏃

Motion Estimation and Compensation

모션 추정과 보상 — 시간적 중복의 핵심

프레임 사이의 시간적 중복을 활용하는 핵심 기술. 모션 벡터를 얼마나 정확하고 빠르게 찾느냐가 인터 예측의 품질을 결정한다.

Motion Estimation and Compensation cheatsheet
🍌 NANO BANANA CHEATSHEET · CH 05

Overview

개관

비디오의 압축률이 폭증하는 결정적 이유는 모션 보상이다. I-프레임만으로는 1/10도 어렵지만 P/B-프레임이 들어가면 1/100~1/300이 가능. 그 마법의 중심에 모션 추정이 있다.

이번 장은 모션 벡터가 어떻게 만들어지고, 왜 인코더의 연산 비용 80%를 차지하며, 코덱의 진화가 어떻게 이 단계를 더 정교하게 만들어 왔는지 본다.

🎯 Learning Goals
  • 모션 추정과 모션 보상의 정확한 의미와 순서를 안다
  • Block matching 알고리즘이 무엇인지 설명할 수 있다
  • Sub-pixel 정확도가 왜 필요하고 어떻게 구현되는지 안다
  • 인코더의 가장 큰 연산 비용이 이 단계임을 이해한다
  • Reference frame 개수가 압축률·연산 비용에 미치는 영향을 안다

Sections

본문

5.1 모션 추정과 모션 보상의 구분

둘은 짝이지만 다른 일이다.

모션 추정 (Motion Estimation)인코더만 하는 일. 현재 프레임의 블록 하나를 잡고, 참조 프레임에서 가장 비슷한 블록을 찾는다. 그 위치 차이가 모션 벡터.

모션 보상 (Motion Compensation)인코더·디코더 둘 다 하는 일. 모션 벡터를 받아 참조 프레임에서 그 위치의 블록을 가져와 "예측"으로 사용. 잔차 = 현재 - 예측을 계산하고 그것만 압축.

왜 이 구분이 중요한가? 인코더는 모션 추정에서 압도적 시간을 쓰지만, 디코더는 그 결과(모션 벡터)만 받아 모션 보상하면 끝. 그래서 인코딩은 느리고 디코딩은 빠르다. 이게 "라이브 방송엔 H.264, 저장엔 H.265/AV1"의 근거 중 하나다.

코덱 진화는 사실상 "모션 추정을 더 영리하게, 모션 보상을 더 정교하게"의 누적이다.

5.2 Block Matching — 모션 벡터 찾기

가장 단순한 모션 추정 알고리즘이 block matching. 현재 프레임의 한 블록(보통 16×16)을 참조 프레임의 주변 영역(예: ±32 픽셀)에서 모든 위치와 비교, 가장 비슷한 위치를 찾는다.

비슷한 정도를 측정하는 함수: - SAD (Sum of Absolute Differences): 차이 절댓값 합. 빠름. - SATD (Sum of Absolute Transformed Differences): SAD를 Hadamard 변환 후. 더 정확. - SSE (Sum of Squared Errors): 차이 제곱 합.

Full search (모든 위치 다 비교)는 정확하지만 느리다. 32×32 범위면 한 블록당 1024번 비교. 1080p 30fps이면 초당 수십억 번. 비현실적.

그래서 실제 인코더는 빠른 검색 알고리즘을 쓴다: - Diamond search: 다이아몬드 패턴으로 검색 → 빠르지만 local minimum 위험 - Hexagon search: 육각형 패턴 → 균형 - EPZS (Enhanced Predictive Zonal Search): 인접 블록의 모션 벡터로 시작점 예측 → x264·x265 기본

Preset(-preset slow vs -preset ultrafast)이 결정하는 게 바로 이 검색의 철저함이다.

5.3 Sub-pixel 정확도 — 1/4·1/8 픽셀

정수 픽셀 단위 모션 벡터로는 부족하다. 카메라가 0.5픽셀 움직였다면 정수로 표현 못 함. 그래서 sub-pixel 정확도.

- H.264: 1/4 픽셀 정확도 - H.265: 1/4 픽셀 정확도 - AV1: 1/8 픽셀 정확도

0.25 픽셀 위치의 "픽셀 값"이 뭔가? 보간(interpolation)으로 만든다. H.264는 6-tap FIR 필터, H.265는 8-tap, AV1은 8-tap + warping까지.

왜 중요한가: sub-pixel 정확도가 높을수록 더 정확한 예측 → 더 작은 잔차 → 더 좋은 압축. H.264 → AV1로 가면서 압축률 향상의 한 축이 여기다.

비용: 보간 필터를 모든 모션 추정 후보 위치에 적용해야 하니 연산이 폭증. 인코더 비용의 큰 부분.

5.4 Reference Frames — 여러 참조 프레임

초창기 코덱(MPEG-2)은 바로 직전 프레임 1개만 참조했다. H.264부터는 여러 참조 프레임 지원. 최대 16장까지(메모리·연산 비용 한계 내에서).

왜 도움이 되나? 어떤 객체가 잠깐 가려졌다가 다시 나타나는 경우 — "직전 프레임에선 안 보이지만 5프레임 전엔 보인다". 그 5프레임 전을 참조하면 예측이 잘 맞는다.

H.265의 CRA(Clean Random Access)·IDR·BLA 같은 키프레임 정책이 reference frame 관리의 일부.

B-프레임의 경우 양방향 참조 — 이전 프레임 + 이후 프레임 둘 다 사용. "이 블록은 직전 프레임의 (x+3, y-1)이거나 직후 프레임의 (x-2, y+1)의 평균"이라고 예측. 더 정확.

참조 프레임 개수의 트레이드오프: - 많으면 → 더 좋은 예측 → 더 작은 파일 - 많으면 → 더 많은 메모리 → 디코더가 더 강력해야 함 - 많으면 → 인코딩이 더 느림 (각 참조 프레임마다 검색)

5.5 AV1의 새 무기 — Warped Motion과 Global Motion

H.264·H.265는 "평행이동(translation)"만 다룬다. 즉 블록이 옆으로·위아래로 움직였다는 가정. 하지만 실제로는 회전·줌·perspective 변화도 일어난다.

AV1의 Warped Motion: 블록 단위 회전·확대·shear까지 표현. "이 블록은 참조 프레임에서 (x+5, y-2) 위치에서 가져오되, 10도 회전 + 1.05배 확대"라고 표현 가능.

Global Motion: 카메라 패닝·줌처럼 화면 전체가 같은 방향으로 움직이는 경우, 프레임 단위로 전역 변환을 정의. 모든 블록의 모션 벡터 대신 한 번에 처리.

이 두 기법이 AV1이 H.265 대비 30% 더 좋은 압축률을 달성하는 주요 이유 중 하나. 자연 영상에서 회전·줌·패닝은 매우 흔하다.

단점: 모션 추정의 검색 공간이 폭증해서 인코딩이 H.265보다 5~10배 느려진다. AV1 도입의 가장 큰 장벽.

💡 Analogy · 비유
CCTV에서 도난범 추적

한 사람이 가게에서 물건을 훔쳐 도망갔다. CCTV 영상을 보고 추적할 때, 1번 카메라(밤 9시)의 그 사람을 찾아 그 사람의 모습을 기억한다. 그 다음 2번 카메라(밤 9시 5분) 영상에서 "같은 사람이 어디 있을까?" 찾는다. 옷·키·걸음걸이가 비슷한 사람을 발견 — 가게에서 동쪽으로 100m 떨어진 위치에서 발견했다고 치자.

이 "100m 동쪽"이 모션 벡터다. 그리고 이 정보를 가지고 "5분 뒤엔 같은 사람이 동쪽으로 100m 더 갔을 거다"라고 예측하는 게 모션 보상이다.

비디오 코덱이 정확히 이걸 한다. 한 블록의 "같은 모습"을 다음 프레임에서 찾아 위치 차이만 기록(모션 벡터), 그 위치에서 픽셀을 가져와 다음 프레임을 만든다(모션 보상). 차이는: CCTV 추적은 한 사람 한 명, 비디오 코덱은 한 프레임에 수천 블록 동시에. 그래서 빠른 검색 알고리즘이 핵심.

두 프레임 사이의 모션 벡터를 직접 계산해 보자. 단순한 SAD 기반 block matching.

python
import cv2
import numpy as np

cap = cv2.VideoCapture('sample.mp4')
_, frame_prev = cap.read()
_, frame_curr = cap.read()
cap.release()

BLOCK = 16
SEARCH = 16  # ± 16 pixels around the original position

def sad(a, b):
    return np.abs(a.astype(int) - b.astype(int)).sum()

def find_mv(curr_block, prev_frame, cx, cy):
    """Return the best (dx, dy) and its SAD."""
    best, best_mv = float('inf'), (0, 0)
    h, w = prev_frame.shape[:2]
    for dy in range(-SEARCH, SEARCH + 1):
        for dx in range(-SEARCH, SEARCH + 1):
            x, y = cx + dx, cy + dy
            if x < 0 or y < 0 or x + BLOCK > w or y + BLOCK > h:
                continue
            candidate = prev_frame[y:y+BLOCK, x:x+BLOCK]
            cost = sad(curr_block, candidate)
            if cost < best:
                best, best_mv = cost, (dx, dy)
    return best_mv, best

# Compute MVs for the whole current frame
h, w = frame_curr.shape[:2]
mvs = []
for cy in range(0, h - BLOCK, BLOCK):
    for cx in range(0, w - BLOCK, BLOCK):
        curr_block = frame_curr[cy:cy+BLOCK, cx:cx+BLOCK]
        mv, cost = find_mv(curr_block, frame_prev, cx, cy)
        mvs.append((cx, cy, mv[0], mv[1], cost))

# Stats: how much motion?
mv_array = np.array([(m[2], m[3]) for m in mvs])
print(f'모션 벡터 평균: dx={mv_array[:,0].mean():.2f}, dy={mv_array[:,1].mean():.2f}')
print(f'  → 화면 전체가 평균 ({mv_array[:,0].mean():.1f}, {mv_array[:,1].mean():.1f}) 픽셀 움직임 = 카메라 패닝')
print(f'\n0 모션 블록 비율: {(np.abs(mv_array).sum(axis=1) == 0).mean()*100:.1f}%')
print(f'  → 정적 영역의 비율. 모션 보상이 없어도 되는 블록')

이 단순 구현으로 모션 벡터 분포가 보인다. 일반 비디오에서 카메라 패닝이 있으면 모든 블록의 MV가 같은 방향, 정적 장면이면 거의 모든 MV가 0. 실제 x264/x265는 이보다 100배 빠른 EPZS·Hex 검색을 쓰지만 핵심 아이디어는 동일. 특히 "모션 벡터의 평균이 카메라 움직임"이라는 점이 AV1의 Global Motion 발상의 근거.

🏭 현업에서의 평가
모션 추정은 인코더 비용의 80%. 코덱 성능 차이의 가장 큰 부분이 이 단계의 정교함.

✅ 시니어가 보는 것

  • 모션 추정·보상의 구분을 명확히 안다
  • Block matching의 검색 알고리즘 종류와 trade-off를 안다
  • Sub-pixel 정확도가 왜 필요한지 안다
  • x264·x265의 preset이 무엇을 바꾸는지 설명 가능

⚠️ 레드 플래그

  • 모션 추정과 모션 보상을 혼동
  • Full search가 실용적이라고 생각
  • Sub-pixel 보간이 손실이라고 오해
  • Reference frame 개수가 디코더 비용에 미치는 영향 모름

🎤 예상 인터뷰 질문

  1. 모션 추정과 모션 보상의 차이는?
  2. 왜 sub-pixel 모션 벡터가 필요한가요?
  3. x264의 -preset slow-preset ultrafast의 가장 큰 차이는?
숙달 vs 익숙함: Familiar는 '모션 벡터로 다음 프레임 예측한다'를 안다. Mastery는 검색 알고리즘·서브픽셀·multiple reference·warped motion까지 매핑하고, preset 선택이 인코더의 모션 추정 비용을 어떻게 바꾸는지 안다.

Key Takeaways

핵심 정리

추정 vs 보상

인코더가 MV 찾기 vs 둘 다 MV로 예측.

Block matching

참조 프레임에서 비슷한 블록 찾기.

비용의 80%

인코더 시간의 대부분이 모션 추정.

Sub-pixel

1/4·1/8 픽셀 보간. 더 정확한 예측.

Multi-reference

여러 프레임 참조. 가려졌다 나타난 객체.

B-frame 양방향

이전+이후 둘 다 참조. 가장 효율적.

Warped/Global motion

AV1의 신무기. 회전·줌·패닝 직접 표현.

Preset = 검색 철저함

ultrafast~slow가 검색 깊이를 조절.