Spaces:
Sleeping
Sleeping
| from landmarks import get_landmarks | |
| from geometry import extract_features | |
| from classifier import classify_face_shape | |
| import logging | |
| logger = logging.getLogger(__name__) | |
| RECOMMENDATIONS = { | |
| # Keys must match frame-metadata.ts: | |
| # Wayfarer, Aviator, Round, Square, Rectangle, Cat-eye, Clubmaster, Geometric, Oversized | |
| "Oval": { | |
| "glasses": ["Square", "Rectangle", "Wayfarer", "Aviator"], | |
| "hair": ["Quiff", "Side Part", "Buzz Fade", "Pompadour"], | |
| "beard": ["Light Stubble", "Short Boxed", "Verdi"], | |
| "description": "Balanced proportions. Most frame styles work well." | |
| }, | |
| "Round": { | |
| "glasses": ["Rectangle", "Square", "Wayfarer", "Geometric"], | |
| "hair": ["Pompadour", "High Fade", "Faux Hawk", "Side Part"], | |
| "beard": ["Goatee", "Van Dyke", "Extended Chin Curtain"], | |
| "description": "Soft angles with similar width and height. Angular frames add definition." | |
| }, | |
| "Square": { | |
| "glasses": ["Round", "Aviator", "Cat-eye", "Clubmaster"], | |
| "hair": ["Textured Crop", "Side Fade", "Buzz Cut", "Crew Cut"], | |
| "beard": ["Light Stubble", "Circle Beard", "Royale"], | |
| "description": "Strong jawline and broad forehead. Round frames soften features." | |
| }, | |
| "Oblong": { | |
| "glasses": ["Oversized", "Aviator", "Square", "Wayfarer"], | |
| "hair": ["Side Part", "Buzz Cut", "Fringe", "Caesar Cut"], | |
| "beard": ["Mutton Chops", "Chin Strap", "Short Stubble"], | |
| "description": "Face is longer than it is wide. Oversized frames balance length." | |
| }, | |
| "Heart": { | |
| "glasses": ["Round", "Wayfarer", "Cat-eye", "Geometric"], | |
| "hair": ["Long Fringe", "Side Part", "Textured Quiff", "Swept Back"], | |
| "beard": ["Full Beard", "Garibaldi", "Extended Goatee"], | |
| "description": "Wider forehead and narrower chin. Bottom-heavy frames help balance." | |
| }, | |
| "Diamond": { | |
| "glasses": ["Round", "Cat-eye", "Clubmaster", "Oval"], # Oval frame type not in metadata, but maybe acceptable as fallback or mapped later. Kept for logic. | |
| "hair": ["Faux Hawk", "Textured Crop", "Quiff", "Fringe"], | |
| "beard": ["Full Beard", "Goatee", "Balbo"], | |
| "description": "Cheekbones are the widest part. Curves soften the cheekbones." | |
| } | |
| } | |
| def get_recommendations(face_shape): | |
| """Returns style recommendations based on face shape.""" | |
| return RECOMMENDATIONS.get(face_shape, RECOMMENDATIONS["Oval"]) | |