import bpy, sys import numpy as np W = r"C:\Users\Jeremy\tinqs\animation\characters\female\lena_nude\hires_claude" bpy.ops.wm.open_mainfile(filepath=W + r"\03_sculpted.blend") ob = max([o for o in bpy.data.objects if o.type=='MESH'], key=lambda o: len(o.data.vertices)) me = ob.data n_v = len(me.vertices) co = np.empty(n_v*3); me.vertices.foreach_get("co", co); co = co.reshape(-1,3) # face normals -> vertex normal variance (crease detector) n_f = len(me.polygons) fn = np.empty(n_f*3); me.polygons.foreach_get("normal", fn); fn = fn.reshape(-1,3) lt = np.empty(n_f, dtype=np.int32); me.polygons.foreach_get("loop_total", lt) ls = np.empty(n_f, dtype=np.int32); me.polygons.foreach_get("loop_start", ls) lv = np.empty(len(me.loops), dtype=np.int32); me.loops.foreach_get("vertex_index", lv) acc = np.zeros((n_v,3)); acc2 = np.zeros(n_v); cnt = np.zeros(n_v) for fi in range(n_f): for k in range(ls[fi], ls[fi]+lt[fi]): vi = lv[k] acc[vi] += fn[fi]; cnt[vi] += 1 mean = acc / np.maximum(cnt,1)[:,None] ml = np.linalg.norm(mean, axis=1) # 1 = all normals aligned; low = crease/facet window = (co[:,1] < 0) & (co[:,2] > 0.58) & (co[:,2] < 0.82) & (np.abs(co[:,0]) < 0.12) bad = window & (ml < 0.90) & (cnt > 0) print(f"creased verts in front-chest window: {bad.sum()}") if bad.sum(): b = co[bad] print(f"bbox: x [{b[:,0].min():+.3f},{b[:,0].max():+.3f}] " f"y [{b[:,1].min():+.3f},{b[:,1].max():+.3f}] " f"z [{b[:,2].min():+.3f},{b[:,2].max():+.3f}]") # cluster by z-decile to see structure for zlo in np.arange(0.58, 0.82, 0.02): m = bad & (co[:,2] >= zlo) & (co[:,2] < zlo+0.02) if m.sum() > 30: print(f" z {zlo:.2f}-{zlo+0.02:.2f}: n={m.sum():5d} " f"x[{co[m,0].min():+.3f},{co[m,0].max():+.3f}]") print("LOCATE_DONE")