TinyFaceNet-1M / code /live_ab.py
sraivante's picture
Add LFW benchmark (62.6%), stranger test, eval_lfw.py; open-set THR 0.45 -> 0.55
e0c1479 verified
Raw History Blame Contribute Delete
4.24 kB
"""Side-by-side webcam: same frame & detection, LEFT = INT8 (ONNX Runtime static), RIGHT = INT4 (simulated weight-only).
usage: python live_ab.py [tag=v2] q=quit s=snapshot n=toggle norm"""
import sys, time, collections, copy, numpy as np, cv2, torch, torch.nn.functional as F, onnxruntime as ort
from insightface.app import FaceAnalysis
from insightface.utils.face_align import norm_crop
from model import TinyFaceNet
TAG=sys.argv[1] if len(sys.argv)>1 else "v2"; THR=0.55; VOTE=7; NORM=True
ck=torch.load(f"dataset/model_{TAG}.pt",weights_only=False); names=list(map(str,ck["names"])); C=ck["centroids"].numpy()
# INT8: real ORT
s8=ort.InferenceSession(f"dataset/{TAG}_int8.onnx",providers=["CPUExecutionProvider"]); in8=s8.get_inputs()[0].name
# INT4: fake-quant weights, torch fp32 compute
m=TinyFaceNet(n_cls=len(names)); m.load_state_dict(ck["model"]); m.eval(); torch.set_num_threads(4)
for n_,p in m.named_parameters():
if p.dim()<2 or n_.startswith(("distill","cls")): continue
w=p.data; wf=w.reshape(w.shape[0],-1); sc=wf.abs().amax(1,keepdim=True).clamp_min(1e-8)/7; p.data=((wf/sc).round().clamp(-7,7)*sc).reshape(w.shape)
def emb8(x): e=s8.run(None,{in8:x})[0][0]; return e/np.linalg.norm(e)
def emb4(x):
with torch.no_grad(): return F.normalize(m(torch.from_numpy(x)),dim=1)[0].numpy()
app=FaceAnalysis(name="buffalo_l",allowed_modules=["detection"],providers=["CPUExecutionProvider"]); app.prepare(ctx_id=-1,det_size=(320,320))
clahe=cv2.createCLAHE(clipLimit=2.0,tileGridSize=(8,8))
def normalize(img):
mean=img.mean()
if mean<110:
gamma=np.log(110/255)/np.log(max(mean,1)/255); lut=(np.linspace(0,1,256)**gamma*255).astype(np.uint8); img=cv2.LUT(img,lut)
lab=cv2.cvtColor(img,cv2.COLOR_BGR2LAB); lab[...,0]=clahe.apply(lab[...,0]); return cv2.cvtColor(lab,cv2.COLOR_LAB2BGR),mean
def iou(a,b):
ix=max(0,min(a[2],b[2])-max(a[0],b[0])); iy=max(0,min(a[3],b[3])-max(a[1],b[1])); i=ix*iy
return i/((a[2]-a[0])*(a[3]-a[1])+(b[2]-b[0])*(b[3]-b[1])-i+1e-6)
tracks={"INT8":[],"INT4":[]}
def annotate(img,bb,sim,side,fr):
j=int(sim.argmax()); s=float(sim[j]); inst=names[j] if s>=THR else "unknown"; T=tracks[side]
tr=max(T,key=lambda t:iou(t[0],bb),default=None)
if tr is None or iou(tr[0],bb)<0.3: tr=[bb,collections.deque(maxlen=VOTE),collections.deque(maxlen=VOTE),fr]; T.append(tr)
tr[0]=bb; tr[1].append(inst); tr[2].append(s); tr[3]=fr
lab,cnt=collections.Counter(tr[1]).most_common(1)[0]; conf=np.mean(tr[2]); col=(0,255,0) if lab!="unknown" else (0,0,255)
x1,y1,x2,y2=bb; cv2.rectangle(img,(x1,y1),(x2,y2),col,2)
cv2.putText(img,f"{lab} {conf:.2f} ({cnt}/{len(tr[1])})",(x1,y1-8),0,0.65,col,2)
cv2.putText(img," ".join(f"{names[k]}:{sim[k]:.2f}" for k in np.argsort(-sim)[:3]),(x1,y2+18),0,0.42,(255,255,0),1)
cap=cv2.VideoCapture(0,cv2.CAP_DSHOW); cap.set(3,640); cap.set(4,480)
if not cap.isOpened(): sys.exit("webcam open nahi hua")
n=0; t0=time.time(); fr=0; t8=t4=0.
while True:
ok,raw=cap.read()
if not ok: continue
img,mean=normalize(raw) if NORM else (raw,raw.mean()); L=img.copy(); R=img.copy()
for f in app.get(img):
crop=norm_crop(img,f.kps,112); x=((crop.transpose(2,0,1)[None].astype(np.float32)/255.)-0.5)/0.5; bb=tuple(map(int,f.bbox))
a=time.perf_counter(); e8=emb8(x); b=time.perf_counter(); e4=emb4(x); c=time.perf_counter(); t8=0.9*t8+0.1*(b-a)*1000; t4=0.9*t4+0.1*(c-b)*1000
annotate(L,bb,C@e8,"INT8",fr); annotate(R,bb,C@e4,"INT4",fr)
for k in tracks: tracks[k]=[t for t in tracks[k] if fr-t[3]<15]
cv2.putText(L,f"INT8 ORT {t8:.1f}ms/face",(8,20),0,0.6,(255,255,255),2); cv2.putText(R,f"INT4 sim {t4:.1f}ms/face",(8,20),0,0.6,(255,255,255),2)
out=np.concatenate([L,np.full((img.shape[0],4,3),255,np.uint8),R],1)
fr+=1; cv2.putText(out,f"{TAG} {fr/(time.time()-t0):.1f}fps norm={'ON' if NORM else 'off'} light={mean:.0f} q=quit s=save n=norm",(8,out.shape[0]-10),0,0.5,(255,255,255),1)
cv2.imshow("INT8 | INT4",out); k=cv2.waitKey(1)&0xFF
if k==ord("q"): break
if k==ord("n"): NORM=not NORM; tracks={"INT8":[],"INT4":[]}
if k==ord("s"): n+=1; cv2.imwrite(f"analysis/ab_{n}.jpg",out); print("saved",n,flush=True)
cap.release(); cv2.destroyAllWindows()