# Critique round 2: the clean SIDE's key shapes (sheet pixels) over the clean SIDE (left) and the v04 model render (right). import os SHEET_IMG=os.environ.get('SHEET','critique/sheet_clean.png') from PIL import Image, ImageDraw b=(30,530,970,1065); K=2 O=(255,120,0); B=(0,150,255); P=(120,0,180); G=(0,140,0); R=(200,30,0); KK=(0,0,0) items=[ ('line',[(178,702),(200,697),(250,684),(275,678),(300,672)],O), # brow top = silhouette ('line',[(178,703),(200,700),(240,700),(262,706),(280,720),(290,740),(297,760),(300,780),(293,800),(300,812)],O), # brow underside flowing into the collar's front edge ('line',[(305,688),(333,720),(338,740),(339,760),(334,780),(325,800),(305,815)],O), # collar back edge ('line',[(422,712),(447,712),(446,735),(423,758),(392,756),(422,712)],KK), # black slot (only this is black) ('rect',(340,705,420,790),P), # recess: mid grey ~(113,124,134), not black ('line',[(280,820),(342,800),(392,780),(431,760),(470,742)],G), # cheek panel top edge: light grey from here down, like the fin ('rect',(205,738,245,812),B), # seat back + headrest seen through the glass (dark navy) ('line',[(282,948),(300,968)],R), # prong slit starts here, ~6 px wide ('line',[(368,840),(300,840)],R), # C upper arm tapers to a point at x 368 ('line',[(405,953),(425,940),(440,909),(455,890)],P), # lower front body's rear-bottom corner ('line',[(645,828),(660,795),(700,770),(800,770),(800,832),(645,832)],B), # rear glass bay (ends at x 800, dark tint) ('rect',(912,740,918,785),KK),('line',[(900,800),(950,800)],KK),('rect',(875,815,930,852),KK), # stern: post, upper tool arm, lower unit ('ellipse',(863,797,880,820),O), # orange lens ('line',[(835,858),(868,948)],G), # ventral fin leading edge ] w,h=b[2]-b[0],b[3]-b[1] sheet=Image.open(SHEET_IMG).convert('RGB').crop(b).resize((w*K,h*K),Image.LANCZOS) m=Image.open('previews/compare/lk_side.png').convert('RGBA').resize((w*K,h*K),Image.LANCZOS) bg=Image.new('RGBA',m.size,(255,255,255,255)); bg.alpha_composite(m); m=bg.convert('RGB') P_=lambda p:((p[0]-b[0])*K,(p[1]-b[1])*K) for im in (sheet,m): d=ImageDraw.Draw(im) for kind,geo,col in items: if kind=='ellipse': d.ellipse([*P_(geo[:2]),*P_(geo[2:])],outline=col,width=3) elif kind=='rect': d.rectangle([*P_(geo[:2]),*P_(geo[2:])],outline=col,width=3) else: d.line([P_(p) for p in geo],fill=col,width=3) c=Image.new('RGB',(w*K,h*K*2+20),'white'); c.paste(sheet,(0,0)); c.paste(m,(0,h*K+20)); c.save('critique/r2_targets_side.png') print('ok')