master
John Lauer Add Fusion 24-net crossover routing, shared vias, and captioned demo b3f148d 1mo ago
"""Find visible copper changes in the Fusion board, excluding surrounding UI."""
import argparse,json,subprocess
from pathlib import Path
import numpy as np
p=argparse.ArgumentParser();p.add_argument('source',type=Path);a=p.parse_args()
probe=json.loads(subprocess.check_output(['ffprobe','-v','error','-show_format','-show_streams','-of','json',str(a.source)]))
duration=float(probe['format']['duration'])
# Work at half the native width. This crop contains the board, not the DRC panel.
w,h=600,620
proc=subprocess.Popen(['ffmpeg','-v','error','-i',str(a.source),'-vf',f'fps=10,scale=1280:-2,crop={w}:{h}:220:130','-f','rawvideo','-pix_fmt','rgb24','-'],stdout=subprocess.PIPE)
prev=None;scores=[];events=[];i=0
while True:
    buf=proc.stdout.read(w*h*3)
    if not buf:break
    assert len(buf)==w*h*3
    frame=np.frombuffer(buf,np.uint8).reshape(h,w,3).astype(np.int16)
    colored=(frame.max(2)-frame.min(2)>60)&(frame.max(2)>70)
    if prev is not None:
        changed=(np.abs(frame-prev).max(2)>40)&(colored|oldcolored)
        score=int(changed.sum());scores.append([round(i/10,3),score])
        if score>=3 and i/10>.5:events.append(i/10)
    prev=frame;oldcolored=colored;i+=1
assert proc.wait()==0
ranges=[]
for t in events:
    lo=max(0,t-.25);hi=min(duration,t+.4)
    if ranges and lo<=ranges[-1][1]:ranges[-1][1]=hi
    else:ranges.append([lo,hi])
assert ranges
# Show a brief unrouted setup and retain the final clean DRC result for the hold.
ranges[0][0]=max(0,ranges[0][0]-.4)
ranges.append([max(ranges[-1][1],duration-.5),duration])
ranges=[r for r in ranges if r[1]>r[0]]
(a.source.parent/'motion-scores.json').write_text(json.dumps(scores)+'\n')
(a.source.parent/'action-ranges.json').write_text(json.dumps(ranges,indent=2)+'\n')
print({'sourceSeconds':duration,'events':len(events),'intervals':len(ranges),'keptSeconds':sum(b-a for a,b in ranges)})