| name | autorig-threshold-rel |
| description | AUTORIG 추출/분리 단계의 *절대 매직넘버*(008 아카네 픽셀에 손튜닝된 lum<150·MIN_PX=5000·LUM_MAX=150 등)를 *이미지 자체 통계*(피부 중앙값·MAD·앵커 면적 비율·영역 분위수)로 바꿔 캐릭터가 바뀌어도 안 깨지게 한다. 무회귀 A/B($0, 006/007/008 재추출 비교)로 검증. 트리거 — "임계값 상대화", "하드코딩 임계값", "캐릭터 바뀌면 추출 깨짐", "새 캐릭터 추출 일반화", "adaptive thresholds", "절대값 상대화", "추출 임계값 캐릭터 적응", "threshold relativization", "AUTORIG-THRESHOLD-REL". |
임계값 상대화 (AUTORIG-THRESHOLD-REL-001)
추출/분리가 한 캐릭터 픽셀에 맞춘 절대 임계값에 의존하면, 새 캐릭터(피부톤·머리색·입크기)에서
추출이 깨진다. 임계값을 그 이미지의 자체 통계로 산출해 코드 0줄 수정으로 캐릭터를 추가한다.
0. 핵심 원칙 (어떤 절대값이 취약한가 — 다 바꾸지 말 것)
- 취약(상대화 대상): 피부색·머리색에 의존하는 컷. lum<150(입선)·LUM_MAX=150(머리)·살구색 밴드·
DIFF_T(변화강도). 실측: LUM_MAX=150이 007 파란머리 93%를 잘라 분리 실패시켰다.
- 취약(크기): 절대 px 게이트. MIN_PX=5000·MIN_STATE_PX=150·px<2000 → 작은 입이 미달해 폴백.
- 상대화하면 손해 (유지가 정답):
- 마젠타키 입안 팔레트(lum<100 입안·lum>190 이빨) — 캐릭터 무관 일관, 퍼센타일이 오히려 흔들림(dark=bottom 40~49%).
- 관대 게이트(validators) — P5 실측: 살구색 skin_ratio 0.15
0.28(상한 0.80)·레이어 px가 floor의 7470배.
"빈/garbage 검출" 관대 floor라 상대화=2048²서 무변경(무익) or 더 빡빡(게이트 약화·유해).
- 검증 fixture 없는 차원: 다크/쿨 피부 살구색 밴드는 진짜 취약하나 테스트 캐릭터가 없어 상대화하면
미검증 추측(성역 위반·괴물 사건). yaml 피부힌트로 연기하고 fixture 생길 때 착수.
- 추측 말고 측정으로 판정 — 006/007/008 실측 후에만 상대화 여부 결정.
1. 인프라 (이미 있음 — 재사용)
scripts/lib/adaptive_thresholds.py: mode()(env AUTORIG_THRESHOLDS), pick(m, legacy, adaptive_fn, spec_override), skin_stats, cut(center, spread, k, direction, floor), rel_px, rel_cov,
region_percentile, spec_value. legacy 모드 = 호출측 상수 그대로(byte 무변경) → 무회귀 보장.
- 슬롯
color_thresholding: legacy|adaptive (config/pipeline_profile.default.yaml + lib/pipeline_slots.py
threshold_mode). 러너가 env로 서브프로세스에 전파. 기본 legacy(현행 무변경) → A/B 통과 후 adaptive 승격.
- yaml 오버라이드:
characters/<id>.yaml의 thresholds.<key> → at.spec_value로 통제(자동 실패 시).
2. 상대화 절차 (한 클러스터씩 — 빅뱅 금지)
- 실측 먼저(성역): 그 임계값이 006/007/008에서 피부/머리 통계 대비 무엇인지 측정. 예:
150/skin_lum ≈ 0.66(셋 일관) → lum_cut = skin_lum*0.66. 일관 계수가 안 나오면 상대화 방식 재검토.
at.pick(mode, legacy값, lambda: 적응식) 으로 교체. 적응식은 008에서 legacy를 재현하도록 계수 보정.
- 크래시 금지 견고성: refinement 단계(shoulder_hair 등)는 깨끗이 못 하면 우아한 스킵(return 0,
의상/원본 보존). 종전 exit 1은 파이프라인을 크래시시켰다(잠재 버그).
- 스케일 기준 신중히: px 캡을 입폭(mouth_w) 기준으로 하면 006(얇은 애니입 19px)에서 폭주.
목/얼굴 기하는 face 높이 기준이 옳다(006/007/008 안정). 008 보정 fraction으로.
- in-place 출력의 A/B: clear_face_mouth는 face_base를 제자리 수정 → 커밋本은 이미 입이 지워져
dark가 비고 fallback(임계값 미발동·공허 A/B). 입이 살아있는 master.png를 surrogate 입력으로 발동시킨다.
- floor가 안 걸리는 경우: eyes SKIN_T_FLOOR는 008에서 3·MAD(~100)이 항상 우세해 binding 안 됨 →
상대화는 008 무영향(무회귀 자동)·저대비 캐릭터 방어용. 그래도 같은 패턴으로 상대화(p90×0.15)해 둔다.
3. 검증 — $0 무회귀 A/B (성역: 실픽셀 ground truth)
기존 마스터·reskin 레이어가 디스크에 있으므로 재생성 없이 두 모드로 재추출·비교:
python3 scripts/verify_threshold_relativization.py --list
python3 scripts/verify_threshold_relativization.py --cluster <name>
판정: 008 무회귀(covΔ≈1.0±0.15·bbox≤12px·αL1≤2) + 006/007 정상(에러 없이 끝남 — 깨끗 추출이든
우아한 스킵이든) + 크래시 0. 몽타주 1장(baseline|legacy|adaptive × 캐릭터)으로 육안 확인. 신규
클러스터는 CLUSTERS 딕셔너리에 (argv·out·baseline) 등록.
- 알파 불변·RGB만 변경(clear_face_mouth): cov/bbox가 안 움직이니
compare:"rgb"로 등록 → RGB L1 비교
(regression_verdict_rgb, 008 rgbL1≤3). crop으로 몽타주를 변경 영역(입)만 보이게.
4. 가드레일
- 슬롯 adaptive 승격 완료(전 8클러스터 A/B PASS):
config/pipeline_profile.default.yaml=adaptive
(새 캐릭터 코드 0줄). **배포된 008은 config/pipeline_profile.008-akane.yaml(legacy 핀)**으로 byte-동일 재현.
DEFAULT_PROFILE(첫 active=legacy)은 비파이프라인 호출 안전 폴백 보존.
- 008 무회귀는 절대선: 배포된 아카네 빌드 품질 손실 0(핀으로 byte-동일). covΔ 흔들리면 적응식 계수 재보정(무료 반복).
- 측정으로 판정: "이 절대값은 취약하다"는 가정 금지. 006/007/008 실측으로 정말 피부/머리 의존인지 확인.
- 진행: P1~P5 완료(헬퍼·슬롯·하네스·입4·머리어깨·얼굴입·목·눈·validators판정). 남음=P5b(다크/쿨
피부 yaml힌트 — fixture 생길 때). 상세 SSOT:
docs/ref/pipeline/AUTORIG-THRESHOLD-REL-001.md.