# WL-814x 「부위(덩어리)당 색 단계」 측정기 # idmap_.png = 덩어리(팔레트 칸)를 고유색으로 찍은 지도(빛 0) # python AgentScripts/WL814x_steps.py import sys import numpy as np from PIL import Image RAW = sys.argv[1] REN = sys.argv[2] IDM = sys.argv[3] def L(p): return np.asarray(Image.open(RAW + '/' + p + '.png').convert('RGB'), dtype=np.uint8) idm = L(IDM) ren = L(REN) ma = L('mask_all')[:, :, 0] > 127 kid = (idm[:, :, 0].astype(np.int32) << 16) | (idm[:, :, 1].astype(np.int32) << 8) | idm[:, :, 2].astype(np.int32) kre = (ren[:, :, 0].astype(np.int32) << 16) | (ren[:, :, 1].astype(np.int32) << 8) | ren[:, :, 2].astype(np.int32) # 배경(0,0,0)과 마스크 밖 제외. idmap 은 얼굴 렌더러를 끄고 찍었으므로 그 영역도 자동 제외. valid = ma & (kid != 0) ids, cnt = np.unique(kid[valid], return_counts=True) rows = [] for i, c in zip(ids, cnt): if c < 8: continue # 8px 미만 덩어리는 단계 판정 불가 → 제외(개수만 센다) sel = valid & (kid == i) u, uc = np.unique(kre[sel], return_counts=True) o = np.argsort(-uc) cov = np.cumsum(uc[o]) / c n90 = int(np.searchsorted(cov, 0.90) + 1) rows.append((int(c), len(u), n90)) rows.sort(key=lambda r: -r[0]) if rows: a = np.array(rows) big = a[a[:, 0] >= 20] print('%s / %s : 덩어리(팔레트칸) %d개(8px+), 픽셀 %d' % (REN, IDM, len(rows), a[:, 0].sum())) print(' 칸당 고유색 평균 %.1f 최대 %d' % (a[:, 1].mean(), a[:, 1].max())) print(' 칸당 색단계(90%%덮기) 평균 %.2f 최대 %d · 20px+ 칸만: 평균 %.2f 최대 %d' % ( a[:, 2].mean(), a[:, 2].max(), big[:, 2].mean() if len(big) else 0, big[:, 2].max() if len(big) else 0)) print(' 단계 분포:', {k: int((a[:, 2] == k).sum()) for k in sorted(set(a[:, 2].tolist()))}) print(' 가장 큰 칸 6개 (px, 고유색, 단계):', rows[:6]) else: print('no chunks')