- Realistic facial analysis overlays - High resolution - Portrait orientation (4:5 or A4) - Suitable for printing Generate the complete facial aesthetic report as a single polished image, not as text. give rating out of 10
facial aesthetic assessment photographic standardization frontal portrait lighting guidelines
for both individual
standardized facial photography frontal portrait neutral expression lighting
~/
A portrait-format printable facial-analysis report background for two individual profiles, clean professional non-clinical aesthetic infographic, with subtle facial proportionality grid motifs and space for two portrait panels. Do not include people, branding, scores, or text.
mkdir -p "/tmp/workspace/facial-aesthetic-report/assets" "/tmp/workspace/facial-aesthetic-report/output" "/tmp/workspace/facial-aesthetic-report/src" && python - <<'PY' from PIL import Image im=Image.open('/tmp/workspace/attachments/74d85297-d86b-4422-aae2-353e090e22c6/IMG_0500.jpg') print(im.size, im.getexif().get(274)) for angle,name in [(0,'orig'),(90,'ccw'),(270,'cw')]: x=im.rotate(angle,expand=True) x.thumbnail((500,700)) x.save('/tmp/workspace/facial-aesthetic-report/assets/'+name+'.jpg') PY
python - <<'PY' from PIL import Image, ImageDraw, ImageFont, ImageFilter, ImageOps from pathlib import Path src=Path('/tmp/workspace/attachments/74d85297-d86b-4422-aae2-353e090e22c6/IMG_0500.jpg') out=Path('/tmp/workspace/facial-aesthetic-report/output/facial_aesthetic_report_dual.png') im=Image.open(src).convert('RGB') W,H=2400,3000 canvas=Image.new('RGB',(W,H),(16,18,22)); d=ImageDraw.Draw(canvas) # subtle vertical gradient for y in range(H): t=y/H col=(int(18+16*t),int(20+14*t),int(24+16*t)) d.line((0,y,W,y),fill=col) # fonts reg='/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf'; bold='/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf' def font(path,size): return ImageFont.truetype(path,size) F=lambda s:font(reg,s); B=lambda s:font(bold,s) cream=(238,230,214); muted=(174,178,178); gold=(200,157,91); line=(105,87,62); white=(249,246,240) # header for x in [120,2280]: d.line((x,85,x,250),fill=gold,width=3) d.text((180,92),'FACIAL AESTHETIC REPORT',font=B(67),fill=cream) d.text((183,170),'PHOTO-BASED VISUAL PRESENTATION | DUAL PORTRAIT REVIEW',font=F(27),fill=muted) d.line((180,244,2220,244),fill=line,width=2) # crop handling people=[ ('PERSON 01','8.3','Balanced, warm, expressive', (70,300,555,910), [(0.36,0.39),(0.64,0.39),(0.50,0.54),(0.39,0.68),(0.61,0.68)], ['EXPRESSION','FEATURE BALANCE','PHOTO PRESENCE']), ('PERSON 02','8.0','Defined, composed, confident', (365,750,900,1410), [(0.35,0.37),(0.64,0.37),(0.50,0.52),(0.39,0.67),(0.61,0.67)], ['STRUCTURE','FEATURE BALANCE','PHOTO PRESENCE'])] panel_x=[180,1230]; panel_y=390; pw,ph=990,1550 for idx,(name,score,desc,box,pts,cats) in enumerate(people): x=panel_x[idx]; y=panel_y # panel border d.rounded_rectangle((x,y,x+pw,y+ph),radius=28,outline=line,width=3,fill=(24,27,32)) # portrait region crop=im.crop(box) # resize cover to inside 890x920 target=(870,925) scale=max(target[0]/crop.width,target[1]/crop.height) crop=crop.resize((round(crop.width*scale),round(crop.height*scale)),Image.Resampling.LANCZOS) left=(crop.width-target[0])//2; top=(crop.height-target[1])//2 crop=crop.crop((left,top,left+target[0],top+target[1])) # overlay slight contrast crop=ImageOps.autocontrast(crop,cutoff=1) canvas.paste(crop,(x+60,y+110)) dd=ImageDraw.Draw(canvas,'RGBA') # portrait edge dd.rectangle((x+60,y+110,x+930,y+1035),outline=(223,185,118,210),width=3) # grid overlay for j in range(1,5): xx=x+60+j*870//5; dd.line((xx,y+110,xx,y+1035),fill=(255,245,215,58),width=2) for j in range(1,5): yy=y+110+j*925//5; dd.line((x+60,yy,x+930,yy),fill=(255,245,215,58),width=2) # non-identifying facial analysis motif fixed at middle, clearly illustrative cx=x+495; cy=y+535; rx=205; ry=295 dd.ellipse((cx-rx,cy-ry,cx+rx,cy+ry),outline=(218,171,98,210),width=4) dd.line((cx,cy-ry-60,cx,cy+ry+80),fill=(218,171,98,190),width=3) dd.line((cx-rx-55,cy,cx+rx+55,cy),fill=(218,171,98,190),width=3) points=[] for px,py in pts: points.append((x+60+px*870,y+110+py*925)) for px,py in points: dd.ellipse((px-8,py-8,px+8,py+8),fill=(255,230,166,235)) for a,b in [(0,1),(0,2),(1,2),(2,3),(2,4),(3,4)]: dd.line((points[a],points[b]),fill=(255,224,155,155),width=3) # name / score area d=ImageDraw.Draw(canvas) d.text((x+60,y+58),name,font=B(29),fill=cream) d.text((x+930,y+53),'PHOTO SCORE',font=F(20),fill=muted,anchor='ra') # lower content yy=y+1095 d.text((x+60,yy),'VISUAL IMPRESSION',font=B(25),fill=gold) d.text((x+60,yy+45),desc,font=F(35),fill=white) d.text((x+60,yy+125),score,font=B(126),fill=cream) d.text((x+245,yy+172),'/ 10',font=F(35),fill=muted) d.line((x+60,yy+260,x+930,yy+260),fill=line,width=2) for k,c in enumerate(cats): row=yy+305+k*83 d.text((x+60,row),c,font=F(22),fill=muted) # 5 pips subjective for q in range(5): fill=gold if q<4 else (66,68,71) d.ellipse((x+420+q*70,row+4,x+445+q*70,row+29),fill=fill) d.text((x+60,y+1462),'Overlay lines are illustrative guides, not measurements.',font=F(18),fill=muted) # footer footer_y=2140 d.line((180,footer_y,2220,footer_y),fill=line,width=2) d.text((180,2190),'READING THE REPORT',font=B(31),fill=gold) notes=[ ('RATING','A subjective photo-based presentation score, not a statement of personal worth.'), ('OVERLAYS','Illustrative symmetry and proportion guides. Camera angle, smile, lighting and glasses affect appearance.'), ('PHOTO LIMIT','This is a casual two-person image, not a standardized clinical portrait or diagnostic assessment.')] for i,(head,body) in enumerate(notes): yy=2260+i*150 d.text((180,yy),head,font=B(23),fill=cream) # wrap manually import textwrap lines=textwrap.wrap(body,width=105) for ii,l in enumerate(lines):d.text((445,yy+ii*34),l,font=F(25),fill=muted) d.line((180,2810,2220,2810),fill=line,width=2) d.text((180,2855),'Prepared from supplied image | Portrait analysis: visual presentation only',font=F(22),fill=muted) d.text((2220,2855),'PRINT EDITION • 4:5',font=B(22),fill=gold,anchor='ra') canvas.save(out,quality=95,dpi=(300,300)) print(out,canvas.size) PY
fc-match -f '%{file}\n' 'DejaVu Sans' && fc-match -f '%{file}\n' 'DejaVu Sans:style=Bold'
python - <<'PY' from PIL import Image, ImageDraw, ImageFont, ImageOps from pathlib import Path import textwrap src=Path('/tmp/workspace/attachments/74d85297-d86b-4422-aae2-353e090e22c6/IMG_0500.jpg'); out=Path('/tmp/workspace/facial-aesthetic-report/output/facial_aesthetic_report_dual.png') im=Image.open(src).convert('RGB'); W,H=2400,3000 canvas=Image.new('RGB',(W,H),(16,18,22)); d=ImageDraw.Draw(canvas) for y in range(H): t=y/H; d.line((0,y,W,y),fill=(int(18+16*t),int(20+14*t),int(24+16*t))) fontpath='/usr/share/fonts/google-noto-vf/NotoSans[wght].ttf' def F(s): return ImageFont.truetype(fontpath,s) def B(s): return ImageFont.truetype(fontpath,s) cream=(238,230,214); muted=(174,178,178); gold=(200,157,91); line=(105,87,62); white=(249,246,240) for x in [120,2280]:d.line((x,85,x,250),fill=gold,width=3) d.text((180,92),'FACIAL AESTHETIC REPORT',font=B(67),fill=cream);d.text((183,170),'PHOTO-BASED VISUAL PRESENTATION | DUAL PORTRAIT REVIEW',font=F(27),fill=muted);d.line((180,244,2220,244),fill=line,width=2) people=[('PERSON 01','8.3','Balanced, warm, expressive',(70,300,555,910),[(.36,.39),(.64,.39),(.5,.54),(.39,.68),(.61,.68)],['EXPRESSION','FEATURE BALANCE','PHOTO PRESENCE']),('PERSON 02','8.0','Defined, composed, confident',(365,750,900,1410),[(.35,.37),(.64,.37),(.5,.52),(.39,.67),(.61,.67)],['STRUCTURE','FEATURE BALANCE','PHOTO PRESENCE'])] for idx,(name,score,desc,box,pts,cats) in enumerate(people): x=[180,1230][idx];y=390;pw,ph=990,1550 d.rounded_rectangle((x,y,x+pw,y+ph),radius=28,outline=line,width=3,fill=(24,27,32)) crop=im.crop(box); target=(870,925); scale=max(target[0]/crop.width,target[1]/crop.height); crop=crop.resize((round(crop.width*scale),round(crop.height*scale)),Image.Resampling.LANCZOS);left=(crop.width-target[0])//2;top=(crop.height-target[1])//2;crop=ImageOps.autocontrast(crop.crop((left,top,left+target[0],top+target[1])),cutoff=1);canvas.paste(crop,(x+60,y+110)) dd=ImageDraw.Draw(canvas,'RGBA');dd.rectangle((x+60,y+110,x+930,y+1035),outline=(223,185,118,210),width=3) for j in range(1,5):dd.line((x+60+j*174,y+110,x+60+j*174,y+1035),fill=(255,245,215,58),width=2);dd.line((x+60,y+110+j*185,x+930,y+110+j*185),fill=(255,245,215,58),width=2) cx=x+495;cy=y+535;rx=205;ry=295;dd.ellipse((cx-rx,cy-ry,cx+rx,cy+ry),outline=(218,171,98,210),width=4);dd.line((cx,cy-ry-60,cx,cy+ry+80),fill=(218,171,98,190),width=3);dd.line((cx-rx-55,cy,cx+rx+55,cy),fill=(218,171,98,190),width=3) points=[(x+60+px*870,y+110+py*925) for px,py in pts] for px,py in points:dd.ellipse((px-8,py-8,px+8,py+8),fill=(255,230,166,235)) for a,b in [(0,1),(0,2),(1,2),(2,3),(2,4),(3,4)]:dd.line((points[a],points[b]),fill=(255,224,155,155),width=3) d=ImageDraw.Draw(canvas);d.text((x+60,y+58),name,font=B(29),fill=cream);d.text((x+930,y+53),'PHOTO SCORE',font=F(20),fill=muted,anchor='ra');yy=y+1095;d.text((x+60,yy),'VISUAL IMPRESSION',font=B(25),fill=gold);d.text((x+60,yy+45),desc,font=F(35),fill=white);d.text((x+60,yy+125),score,font=B(126),fill=cream);d.text((x+245,yy+172),'/ 10',font=F(35),fill=muted);d.line((x+60,yy+260,x+930,yy+260),fill=line,width=2) for k,c in enumerate(cats): row=yy+305+k*83;d.text((x+60,row),c,font=F(22),fill=muted) for q in range(5):d.ellipse((x+420+q*70,row+4,x+445+q*70,row+29),fill=gold if q<4 else (66,68,71)) d.text((x+60,y+1462),'Overlay lines are illustrative guides, not measurements.',font=F(18),fill=muted) footer_y=2140;d.line((180,footer_y,2220,footer_y),fill=line,width=2);d.text((180,2190),'READING THE REPORT',font=B(31),fill=gold) notes=[('RATING','A subjective photo-based presentation score, not a statement of personal worth.'),('OVERLAYS','Illustrative symmetry and proportion guides. Camera angle, smile, lighting and glasses affect appearance.'),('PHOTO LIMIT','This is a casual two-person image, not a standardized clinical portrait or diagnostic assessment.')] for i,(head,body) in enumerate(notes): yy=2260+i*150;d.text((180,yy),head,font=B(23),fill=cream) for ii,l in enumerate(textwrap.wrap(body,width=105)):d.text((445,yy+ii*34),l,font=F(25),fill=muted) d.line((180,2810,2220,2810),fill=line,width=2);d.text((180,2855),'Prepared from supplied image | Portrait analysis: visual presentation only',font=F(22),fill=muted);d.text((2220,2855),'PRINT EDITION • 4:5',font=B(22),fill=gold,anchor='ra');canvas.save(out,quality=95,dpi=(300,300));print(out,canvas.size) PY
python - <<'PY' from PIL import Image p='/tmp/workspace/facial-aesthetic-report/output/facial_aesthetic_report_dual.png' im=Image.open(p) print('format=',im.format,'size=',im.size,'dpi=',im.info.get('dpi'),'bytes=',__import__('os').path.getsize(p)) im.thumbnail((400,500)); im.save('/tmp/workspace/facial-aesthetic-report/output/preview.jpg',quality=80) PY
facial aesthetic report dual
Image · PNG