인물 회피 자막 (완전/가급적 가리지 않음)
0. 두 가지 목표 구분
- "완전히 가리지 않음": 각 문자 상자와 모든 프레임의 인물 마스크 간 교집합 = 0. 단점은 문자를 양쪽/상단 좁은 열에만 배치할 수 있고, 글자 크기가 제한됨.
- "가급적 가리지 않음": 날개 가장자리/배경과의 겹침은 허용하지만, 얼굴과 몸통은 반드시 깨끗해야 함. 큰 글자 스타일(S4/S6 등)을 계속 사용할 수 있으며, 근접 샷 프레임만 확인.
이 스킬은 기본적으로 "완전히 가리지 않음" 을 수행하며 검증 가능한 데이터를 제공합니다. 사용자가 "화려한/큰 글자/아트 폰트"를 요청하면 후자일 가능성이 높습니다.
1. 핵심 알고리즘 (빠른 버전: bbox만 사용)
더 이상 픽셀 단위 정밀 매트를 계산하지 않고, 인물의 경계 상자(bounding box) 만 필요로 하며, 1/4 해상도로 계산하여 매우 빠릅니다:
- 배경판
bg_half.npy(1280×540, subject-color-grade의 2.1/3.1 참조). - 각 프레임을 640×270으로 축소하고 배경판과 차분 계산:
d = |frame-bg|.max(axis=2), 임계값 38 (낮은 임계값은 LOVE 조명/광점을 포함시킴). MaxFilter(5)팽창 → 최대 연결 성분(BFS, 640×270에서 매우 빠름) → bbox 추출 후 ×4 하여 전체 해상도로 복원.- 가사 문장 창(window) 내에서 각 프레임의 bbox를 합집합(한 문장 내에서 인물이 움직이므로 문장 전체의 가장 넓은 범위 사용)하여 각 문장에 대해
bounds = (left,right,top,bottom)를 얻음. - 레이아웃: 텍스트 열을
left-50왼쪽 /right+50오른쪽 / 상단 / 하단에 배치; 사용 가능한 너비에 따라 글자 크기 축소. - 프레임별 재검증: 각 문자 상자를 640×270으로 매핑하고 각 프레임의 마스크와 교집합을 계산하여 worst hit 보고; 0이 아니면 전체 글자 크기를 줄여 다시 검증, 0이 될 때까지 반복.
2. 바로 재사용 가능한 구현
字幕\build\avoid_side2.py (권장, 전체 버전: pass1 bbox 측정 → layout → verify → 렌더링 → 키프레임):
$py='C:\Users\35530\.dsh\dsh-runtimes\dsh-primary-runtime\dependencies\python\python.exe'
& $py '字幕\build\avoid_side2.py'
이 스크립트는 고정된 구버전(0001-4956)의 15.4초 구간을 처리합니다. 다른 구간/다른 영상으로 변경하려면 다음 상수를 수정하세요:
SRC/OUT/T0,T1CUES(각 문장의 시작/끝, 구간 기준)EL내의 글자 크기/위치 후보 (L/R열, y, fs)LEFT_MARGIN/오른쪽 사용 가능 너비 로직 산출물:NEON_avoid_15s.ass+ 렌더링 영상 + 키프레임 표. 구버전 (합성 데모):avoid_demo.py,avoid_debug.py,avoid_layout.py(점유 핫스팟 이미지分析_占位与选位.jpg).
3. 본 프로젝트 실측 데이터 (구버전 영상 0:51–1:06.4)
- 고정 하단 레이아웃: 6/6 문장이 인물과 겹침, 인물 영역 가림률 7%–12%.
- 측면 열 회피: 0/6 문장이 인물과 겹침, 단일 문장 가림률 ≤0.2%; 프레임별 재검증 0 픽셀.
- 각 문장의 사용 가능한 측면 열 (구버전, 전체 2560 너비): 왼쪽 열 약 0–500px, 오른쪽 열 약 2100–2560px, 문장마다 다르므로 반드시 실시간 계산해야 함.
- 인물이 화면 중앙에 있고 날개를 펼칠 때 너비 점유율 약 48%–82%; 근접/클로즈업 샷에서는 거의 화면을 가득 채움 → 클로즈업 프레임에서는 문자를 상하단 모서리에만 배치 가능.
4. 레이아웃 전략 (인물을 가리지 않으면서도 보기 좋게)
- 주 가사는 왼쪽 열, 보조 단어는 오른쪽 열에 배치하여 "좌우 대창" 느낌을 연출;
- 상단에는 긴 문장(
MAKING EVERYBODY GO등)을 배치하고, 하단에는 작은 글자/등간격 정보만 남김; - 각 문장에는 하나의 "시각적 주인공"만 두고 나머지 단어는 작게 처리하여 전체 문장이 커서 측면 열에 들어가지 않도록 방지;
- 문자 상자 추정은 보수적으로: ASCII 너비 ≈ fs×0.66, CJK ≈ fs×1.06; 10–14px 패딩 유지.
5. 검증 체크리스트
- 각 문장 창의 bbox가 날개 끝/머리 위를 누락하지 않았는지 확인 (
分析_占用区域.jpg참조) - 프레임별 재검증 worst hit = 0 (스크립트가 출력함)
- 3–4프레임을 샘플링하여: 문자가 가장자리에 너무 가깝거나 잘리는지, 새끼손가락/날개를 가리는지 확인
- 근접/클로즈업 프레임은 별도로 샘플 확인
- "가급적 가리지 않음" 모드를 허용할 경우, 날개가 가려진 프레임을 기록 (허용 가능)
6. 알려진 문제점
- 배경의 LOL 조명/광점이 프레임 차분에서 오탐될 수 있음 → 임계값 38 + 최대 연결 성분으로 일반적으로 제거 가능; 그래도 안 되면 공간 사전 정보 추가 (인물은 중앙에 위치).
- 인물의 그림자가 인물로 잘못 탐지될 수 있음 (bbox가 커짐) → 회피에는 안전함 (그림자도 피하게 되지만 측면 열이 더 좁아짐).
- 필터
MaxFilter는 640×270에서 전체 해상도 기준 약 8px 외곽 확장에 해당하므로, 재검증 시 추가 패딩을 넣지 마십시오. - 새 영상/새 카메라 위치로 변경할 경우, 모든 bounds를 다시 계산해야 하며 기존 영상 숫자를 재사용할 수 없습니다.