# Stage 33 (read-only): A/B the re-atlased body against its input. A faithful re-atlas should # look the SAME — same skin, same tones — while carrying a completely different UV layout # underneath. Large differences would mean the transfer lost or moved her texture. # # blender --background --python 33_ab.py -- import bpy, sys, os import numpy as np argv = sys.argv[sys.argv.index("--") + 1:] A_DIR, B_DIR = argv[0], argv[1] def load(p): im = bpy.data.images.load(p) w, h = im.size b = np.empty(w * h * 4, dtype=np.float32) im.pixels.foreach_get(b) a = b.reshape(h, w, 4)[:, :, :3].copy() bpy.data.images.remove(im) return a print(f"{'view':<12} {'mean|d|':>9} {'p95|d|':>8} {'p99|d|':>8} {'>0.05':>8} {'>0.15':>8}") tot = [] for name in ("full_front", "full_40", "full_back", "chest", "hip"): pa = os.path.join(A_DIR, name + ".png") pb = os.path.join(B_DIR, name + ".png") if not (os.path.exists(pa) and os.path.exists(pb)): print(f"{name:<12} missing") continue A, B = load(pa), load(pb) if A.shape != B.shape: print(f"{name:<12} shape mismatch {A.shape} vs {B.shape}") continue # only compare where the body is: the background is identical by construction body = (np.abs(A - np.array([0.22, 0.22, 0.24])).max(axis=2) > 0.02) d = np.abs(A - B).max(axis=2)[body] tot.append(d) print(f"{name:<12} {d.mean():9.4f} {np.percentile(d,95):8.4f} {np.percentile(d,99):8.4f} " f"{100.0*(d>0.05).mean():7.2f}% {100.0*(d>0.15).mean():7.2f}%") if tot: d = np.concatenate(tot) print(f"\nALL BODY PIXELS: mean |d| {d.mean():.4f} p99 {np.percentile(d,99):.4f} " f"fraction over 0.05: {100.0*(d>0.05).mean():.2f}%") print("AB_DONE")