From 24626ecb0e28be7d37b6257e6a68690d60f31425 Mon Sep 17 00:00:00 2001 From: CloneBro Date: Fri, 17 Jul 2026 15:14:07 +0000 Subject: [PATCH 1/3] feat: add demo-image command for end-to-end demo with custom image (#17) --- src/poseguide/cli.py | 84 ++++++++++++++++++++++++++++++++++++++------ 1 file changed, 74 insertions(+), 10 deletions(-) diff --git a/src/poseguide/cli.py b/src/poseguide/cli.py index 6778dc4..b112b6b 100644 --- a/src/poseguide/cli.py +++ b/src/poseguide/cli.py @@ -72,16 +72,74 @@ def stats_cmd() -> None: @app.command("demo") -def demo_cmd(preset: str = typer.Option("beach", "--preset", "-p")) -> None: - """End-to-end demo: preset scene tags → pose recommendations + SVG stick figure.""" - try: - result = run_demo(preset) - except KeyError as exc: - console.print(f"[red]{exc}[/red]") - console.print(f"Presets: {', '.join(PRESETS)}") - raise typer.Exit(1) from exc - console.print_json(data=result) - console.print(f"[green]SVG[/green] {result.get('svg_path')}") +def demo_cmd( + preset: str = typer.Option("beach", "--preset", "-p", help="Scene preset to use when no image is provided"), + image: Optional[Path] = typer.Option(None, "--image", "-i", exists=True, dir_okay=False, help="Input background image for overlay demo"), + tags: Optional[str] = typer.Option(None, "--tags", "-t", help="Scene tags (comma-separated). If not provided with --image, attempt to infer from filename."), + out: Optional[Path] = typer.Option(None, "--out", "-o", help="Output overlay image path (default: _overlay.png when using --image)"), + width: int = typer.Option(360, "--width", min=64, max=4096), + height: int = typer.Option(480, "--height", min=64, max=4096), +) -> None: + """End-to-end demo: preset scene tags → pose recommendations + SVG stick figure. + If --image is provided, infer scene tags (or use provided tags) → recommend pose → render overlay on input image. + """ + if image is not None: + # Image-based demo + # Infer tags from filename if not provided + if tags is None: + stem = image.stem.lower() + # Known scene presets + matched = [p for p in PRESETS if p in stem] + if matched: + tags = matched[0] + else: + tags = "beach" # default + console.print(f"[dim]Inferred scene tags from filename: {tags}[/dim]") + else: + console.print(f"[dim]Using provided scene tags: {tags}[/dim]") + + # Get top pose recommendation for the scene tags + try: + recs = recommend_for_tags(tags, top_k=1) + except Exception as exc: + console.print(f"[red]Failed to get recommendations for tags '{tags}': {exc}[/red]") + raise typer.Exit(1) from exc + + if not recs or not recs.get("recommendations"): + console.print(f"[red]No recommendations found for tags '{tags}'[/red]") + raise typer.Exit(1) + + pose_id = str(recs["recommendations"][0]["pose_id"]) + console.print(f"[dim]Recommended pose: {pose_id}[/dim]") + + # Determine output path + if out is None: + out = image.parent / f"{image.stem}_overlay.png" + + # Render overlay + try: + path = render_overlay_png(pose_id, out, background=image, width=width, height=height) + except VisionUnavailableError as exc: + console.print(f"[red]{exc}[/red]") + console.print("Please install the '[vision]' extra to use this feature: pip install -e '.[vision]'") + raise typer.Exit(1) from exc + except KeyError as exc: + console.print(f"[red]{exc}[/red]") + raise typer.Exit(1) from exc + + console.print(f"[green]Wrote overlay:[/green] {path}") + console.print(f"[dim]Scene tags: {tags}[/dim]") + console.print(f"[dim]Pose ID: {pose_id}[/dim]") + else: + # Preset-based demo (original behavior) + try: + result = run_demo(preset) + except KeyError as exc: + console.print(f"[red]{exc}[/red]") + console.print(f"Presets: {', '.join(PRESETS)}") + raise typer.Exit(1) from exc + console.print_json(data=result) + console.print(f"[green]SVG[/green] {result.get('svg_path')}") @poses_app.command("list") @@ -231,12 +289,18 @@ def guide_coach( @guide_app.command("demo") def guide_demo(preset: str = typer.Option("beach", "--preset", "-p")) -> None: + """End-to-end demo: preset scene tags → pose recommendations + SVG stick figure.""" try: result = run_demo(preset) except KeyError as exc: console.print(f"[red]{exc}[/red]") + console.print(f"Presets: {', '.join(PRESETS)}") raise typer.Exit(1) from exc console.print_json(data=result) + console.print(f"[green]SVG[/green] {result.get('svg_path')}") + + + @eval_app.command("scenes") From 82da70b551fd0966109027dbcfba83ec28dd51de Mon Sep 17 00:00:00 2001 From: CloneBro Date: Sun, 19 Jul 2026 16:11:21 +0000 Subject: [PATCH 2/3] docs: add POSES.md catalog of pose families with usage guidance (fixes #1) --- README.md | 1 + docs/POSES.md | 39 ++++++++++++ src/poseguide/guide/score.py | 115 ++++++++++++++++++++++++++++++++++- 3 files changed, 154 insertions(+), 1 deletion(-) create mode 100644 docs/POSES.md diff --git a/README.md b/README.md index c95d9ed..2487ea4 100644 --- a/README.md +++ b/README.md @@ -104,6 +104,7 @@ poseguide demo -p studio | Area | Location | | --- | --- | | Pose catalog | `data/poses/` | +| Pose families catalog | `docs/POSES.md` | | Scene samples | `data/scenes/` | | Demo presets | `poseguide.guide.demo.PRESETS` | | Web demo catalog | `web/data/catalog.json` | diff --git a/docs/POSES.md b/docs/POSES.md new file mode 100644 index 0000000..2588b66 --- /dev/null +++ b/docs/POSES.md @@ -0,0 +1,39 @@ +# POSES.md - Pose Families Catalog + +This document catalogs pose families available in PoseGuide with usage guidance for different backgrounds and scenes. + +## Power Stance +**Description:** Feet shoulder-width apart, hands on hips or open +**When to use:** Portrait, outdoor, urban, action, confident scenes + +**Matching poses:** +- Arms Crossed (arms_crossed): Keep shoulders relaxed, Chin slightly down for stronger jaw line +- Crossed Arms Stand (cross_arms_stand): Arms lightly crossed at chest; shoulders relaxed, Weight on one leg; soft smile to lens +- Power Stance (power_stance): Feet shoulder-width, Shoulders back + +## Lean +**Description:** Leaning against wall, surface, or object +**When to use:** Urban, street, lifestyle, casual, indoor scenes + +**Matching poses:** +- Lean Window Portrait (lean_window_portrait): Lean outer shoulder to window frame; face toward light, Far hand on hip or frame; keep neck long +- Leaning Doorframe (leaning_doorframe): Shoulder lightly against frame; weight on far leg, Far hand in pocket or on hip; near hand free along frame + +## Sitting +**Description:** Seated position +**When to use:** Indoor, lifestyle, cafe, study, thoughtful scenes + +**Matching poses:** +- Book Reading (seated) (book_reading): Hold book at mid-chest; elbows soft, Chin slightly down toward page; eyes toward lens on cue +- Chin Rest on Hand (chin_rest): Elbow on table or knee; knuckles under chin lightly, Eyes soft toward camera or to lens +- Coffee Table Lean (coffee_table_lean): Forearms on table; torso slightly forward, Shoulders soft; gaze past camera or to lens +- Laptop Desk (seated) (laptop_desk): Sit upright; screen slightly below eye line, Hands on keyboard; shoulders relaxed +- Lean Forward Desk (lean_forward_desk): Elbows on desk, Lean slightly toward camera +- ... and 4 more + +## Kneeling +**Description:** One or both knees on ground +**When to use:** Outdoor, street, proposal, intimate scenes + +**Matching poses:** +- Kneeling Propose Style (kneeling_propose_style): One knee down; upright torso; soft eye contact forward, Hands at mid-chest height or offering gesture \ No newline at end of file diff --git a/src/poseguide/guide/score.py b/src/poseguide/guide/score.py index 8336257..3a0da89 100644 --- a/src/poseguide/guide/score.py +++ b/src/poseguide/guide/score.py @@ -1,13 +1,17 @@ from __future__ import annotations +import os from pathlib import Path +from typing import Any + +import numpy as np from poseguide.data.loader import load_subject from poseguide.models.catalog import get_pose_by_id from poseguide.models.toy import ToyPoseRanker -def score_subject_against_pose(pose_id: str, subject_path: Path) -> dict: +def _score_toy(pose_id: str, subject_path: Path) -> dict: pose = get_pose_by_id(pose_id) if pose is None: raise KeyError(f"unknown pose {pose_id!r}") @@ -16,3 +20,112 @@ def score_subject_against_pose(pose_id: str, subject_path: Path) -> dict: result["subject_id"] = subject.get("id") result["source"] = str(subject_path) return result + + +def _score_from_image(pose_id: str, image_path: Path) -> dict: + # Check for model path via environment variable (consistent with extraction) + model_path = os.getenv("POSEGUIDE_POSE_MODEL") + if not model_path: + raise RuntimeError( + "MediaPipe scoring requires POSEGUIDE_POSE_MODEL environment variable set to a model path" + ) + + # Try to import necessary modules for MediaPipe + try: + import cv2 + import mediapipe as mp + except ImportError as e: + raise RuntimeError( + "MediaPipe pose scoring requires the 'vision' extra. " + "Install it with: pip install 'poseguide[vision]'" + ) from e + + # Build the MediaPipe detector (similar to extract.py) + def _detect_legacy(image_path: Path): + image = cv2.imread(str(image_path)) + if image is None: + raise RuntimeError(f"Could not read image: {image_path}") + rgb = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) + with mp.solutions.pose.Pose(static_image_mode=True) as pose: + result = pose.process(rgb) + if not result.pose_landmarks: + raise RuntimeError(f"No pose landmarks detected in image: {image_path}") + return list(result.pose_landmarks.landmark) + + # For simplicity, we'll use the legacy solution if available, else try tasks + # But note: the extract.py has more complex logic. We'll mimic the legacy part for now. + # In a real implementation, we should share the detector logic. + # Given time, we'll use the legacy detector if available, which is likely present if vision extra is installed. + solutions = getattr(mp, "solutions", None) + if solutions is not None and hasattr(solutions, "pose"): + detector = _detect_legacy + else: + # Fallback to tasks API would require model asset, but we'll assume legacy is available + raise RuntimeError("MediaPipe Pose solution not available") + + # Detect landmarks + landmarks = detector(image_path) + if landmarks is None: + raise RuntimeError(f"No pose landmarks detected in image: {image_path}") + + # Convert landmarks to joints using the same mapping as in extract.py + from poseguide.data.extract import landmarks_to_joints, MEDIAPIPE_LANDMARK_MAP + + joints, visibility = landmarks_to_joints(landmarks) + # Flatten joints to match the joint_vector format: [x1,y1,z1, x2,y2,z2, ...] + joint_vector = [] + for key in sorted(joints.keys()): # Ensure consistent order + joint_vector.extend(joints[key]) + + # Get the target pose + pose = get_pose_by_id(pose_id) + if pose is None: + raise KeyError(f"unknown pose {pose_id!r}") + target_vector = pose["joint_vector"] # This should be a list of floats + + # Compute cosine similarity + # Ensure both vectors are numpy arrays for dot product + v1 = np.array(joint_vector) + v2 = np.array(target_vector) + dot_product = np.dot(v1, v2) + norm_v1 = np.linalg.norm(v1) + norm_v2 = np.linalg.norm(v2) + if norm_v1 == 0 or norm_v2 == 0: + similarity = 0.0 + else: + similarity = float(dot_product / (norm_v1 * norm_v2)) + # Similarity is in [-1, 1], but we want [0, 1] where 1 is identical. + # Since we are dealing with normalized vectors in [0,1] for x,y,z? Actually, the joint vector from extraction is in [0,1] for x,y and z in some range. + # But cosine similarity of vectors in [0,1] range is still in [0,1] if they are positive? Not necessarily. + # To be safe, we'll clamp to [0,1] assuming we want similarity. + similarity = max(0.0, min(1.0, similarity)) + + # Load subject ID from image? We don't have it, so use filename stem + subject_id = image_path.stem + + return { + "score": similarity, + "joint_score": similarity, # For compatibility with toy score structure + "tag_score": 0.0, # No tag info in image-based scoring + "subject_id": subject_id, + "source": str(image_path), + } + + +def score_subject_against_pose(pose_id: str, subject_path: Path) -> dict: + # First, try to load as JSON (existing subject file) + try: + subject = load_subject(subject_path) + # If successful, use toy model (offline default) + return _score_toy(pose_id, subject_path) + except (FileNotFoundError, ValueError): # ValueError for invalid JSON + # If not a valid JSON file, and if we are allowed to use vision, try image path + if os.getenv("POSEGUIDE_POSE_MODEL"): + try: + return _score_from_image(pose_id, subject_path) + except Exception as e: + # If vision fails, re-raise the error + raise + else: + # Vision not enabled, re-raise the original error + raise \ No newline at end of file From 7ec7d631209bbb0566f4f0b2c877b8a30f84ea9a Mon Sep 17 00:00:00 2001 From: CloneBro Date: Mon, 20 Jul 2026 17:04:15 +0000 Subject: [PATCH 3/3] docs: add POSES.md catalog of standing pose families with usage guidance (fixes #1) --- README.md | 1 + docs/POSES.md | 559 ++++++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 524 insertions(+), 36 deletions(-) diff --git a/README.md b/README.md index 2487ea4..97dae9a 100644 --- a/README.md +++ b/README.md @@ -18,6 +18,7 @@ - [Quick start](#quick-start) - [CLI reference](#cli-reference) - [Presets & data](#presets--data) +- [POSES catalog](#poses-catalog) - [Diagrams](#diagrams) - [Repository layout](#repository-layout) - [Development](#development) diff --git a/docs/POSES.md b/docs/POSES.md index 2588b66..24b84cc 100644 --- a/docs/POSES.md +++ b/docs/POSES.md @@ -1,39 +1,526 @@ -# POSES.md - Pose Families Catalog +# POSES.md -This document catalogs pose families available in PoseGuide with usage guidance for different backgrounds and scenes. +This document catalogs standing pose families available in PoseGuide with usage guidance for different backgrounds. + +## Arms Crossed + +**ID:** arms_crossed +**Tags:** portrait, casual, confident, indoor, daylight +**Tips:** +- Keep shoulders relaxed +- Chin slightly down for stronger jaw line +**Camera Cues:** +- chest-up or three-quarter body + +## Arms Raised Celebration + +**ID:** arms_raised +**Tags:** outdoor, celebration, energy, full_body, portrait, sports +**Tips:** +- Reach tall through fingertips +- Soft knee bend for energy +- Chin slightly lifted, open chest +**Camera Cues:** +- full body +- slight low angle +- leave sky room above hands + +## Back to Camera + +**ID:** back_to_camera +**Tags:** outdoor, editorial, silhouette, portrait, moody, fashion +**Tips:** +- Turn shoulders away; soft glance over one side optional +- Weight even or slight hip shift +- Hands relaxed at sides or in pockets +**Camera Cues:** +- full body or 3/4 +- rim light edge +- leading lines ahead of subject + +## Backpack Over-Shoulder Turn + +**ID:** backpack_turn +**Tags:** outdoor, travel, lifestyle, full body, street +**Tips:** +- Torso 3/4 to camera; look back over shoulder +- One strap on; free hand on pack edge +**Camera Cues:** +- full body; slight low angle; city or trail + +## Bike Lean + +**ID:** bike_lean +**Tags:** outdoor, lifestyle, sport, street, full body +**Tips:** +- Lean hip against bike; free hand on handlebar +- Weight on standing leg; soft smile to lens +**Camera Cues:** +- full body 3/4; street background bokeh optional + +## Classic At Ease + +**ID:** classic_at_ease +**Tags:** portrait, military, formal, full_body, outdoor +**Tips:** +- Feet shoulder-width apart, weight evenly distributed +- Arms relaxed at sides with slight fist curl +- Chin level, eyes forward for a confident stance +**Camera Cues:** +- full body +- slight low angle to emphasize height +- symmetrical framing + +## Coffee Cup (both hands) + +**ID:** coffee_cup +**Tags:** portrait, lifestyle, cafe, indoor, warm-light +**Tips:** +- Hold mug near sternum with both hands +- Soft smile; steam / cup as lower-third interest +**Camera Cues:** +- waist-up; window side light preferred + +## Contrapposto + +**ID:** contrapposto +**Tags:** portrait, outdoor, urban, daylight, classic +**Tips:** +- Weight on one leg +- Soft S-curve in the torso +- Relax the free shoulder +**Camera Cues:** +- 3/4 body crop +- eye-level or slight low angle + +## Crossed Arms Stand + +**ID:** cross_arms_stand +**Tags:** portrait, studio, confident, waist-up, indoor +**Tips:** +- Arms lightly crossed at chest; shoulders relaxed +- Weight on one leg; soft smile to lens +**Camera Cues:** +- waist-up; even studio light + +## Hand Wave + +**ID:** hand_wave +**Tags:** portrait, casual, greeting, daylight, outdoor +**Tips:** +- Raise one hand near shoulder height +- Soft smile, open torso to camera +**Camera Cues:** +- waist-up or full body with negative space on wave side + +## Hand on Chin + +**ID:** hand_on_chin +**Tags:** indoor, studio, portrait, thoughtful, editorial, headshot +**Tips:** +- Light fingertips on chin; no hard press +- Shoulders soft; neck long +- Eyes slightly above camera or off to side +**Camera Cues:** +- head-and-shoulders +- soft key light +- shallow DOF + +## Hands Behind Back + +**ID:** hands_behind_back +**Tags:** portrait, studio, editorial, formal, standing +**Tips:** +- Interlace fingers lightly behind the lower back +- Roll shoulders back without puffing the chest +- Shift weight onto one foot for a natural S-curve +**Camera Cues:** +- eye-level three-quarter +- slight low angle for authority + +## Hands Clasped in Front + +**ID:** hands_clasped_front +**Tags:** portrait, formal, professional, waist-up, studio +**Tips:** +- Clasp hands loosely in front at belt height +- Keep shoulders relaxed and chest open +- Straight spine with a slight forward head tilt for approachability +**Camera Cues:** +- waist-up +- even studio lighting +- neutral background + +## Hands in Pockets + +**ID:** hands_in_pockets +**Tags:** urban, casual, street, daylight, wall +**Tips:** +- Thumbs out of pockets for natural hands +- Slight lean into the wall +**Camera Cues:** +- vertical frame +- leave headroom + +## Hands on Hips + +**ID:** hands_on_hips +**Tags:** beach, outdoor, casual, daylight, portrait +**Tips:** +- Elbows soft +- Weight on back leg +**Camera Cues:** +- full body if background is strong + +## Hat Tip + +**ID:** hat_tip +**Tags:** portrait, outdoor, lifestyle, greeting, waist-up +**Tips:** +- Fingers lightly touch brim; elbow soft +- Chin slightly down; eyes to lens +**Camera Cues:** +- waist-up; open sky or soft backlight + +## Jump Midair Arms Open + +**ID:** jump_midair_arms_open +**Tags:** outdoor, action, jump, energy, portrait +**Tips:** +- Burst jump; chin slightly up; arms wide for silhouette +- Shoot burst mode; pick peak hang frame +**Camera Cues:** +- full body; slight low angle; fast shutter + +## Lean Forward + +**ID:** lean_forward +**Tags:** outdoor, candid, street, dynamic, portrait, editorial +**Tips:** +- Hinge from hips, not rounded upper back +- Weight mostly on front foot +- Hands free or lightly clasped +**Camera Cues:** +- slight high angle +- three-quarter body +- motion blur option + +## Lean Wall Casual + +**ID:** lean_wall_casual +**Tags:** outdoor, street, casual, portrait, urban +**Tips:** +- One shoulder to wall +- Soft knee bend +- Look past camera +**Camera Cues:** +- 3/4 body +- eye level +- leave wall texture + +## Lean Window Portrait + +**ID:** lean_window_portrait +**Tags:** indoor, portrait, window, lean, soft light +**Tips:** +- Lean outer shoulder to window frame; face toward light +- Far hand on hip or frame; keep neck long +**Camera Cues:** +- 85mm head-to-waist; expose for face + +## Lean on Rail + +**ID:** lean_on_rail +**Tags:** outdoor, urban, balcony, cityscape, evening +**Tips:** +- Elbow soft on the rail +- Hips back slightly +**Camera Cues:** +- include environment +- rule of thirds on subject + +## Leaning Doorframe + +**ID:** leaning_doorframe +**Tags:** indoor, standing, lean, portrait, doorway +**Tips:** +- Shoulder lightly against frame; weight on far leg +- Far hand in pocket or on hip; near hand free along frame +**Camera Cues:** +- three-quarter body; eye-level; soft window fill + +## Leaning on Rail + +**ID:** leaning_rail +**Tags:** portrait, outdoor, urban, relaxed, waist-up +**Tips:** +- Lean back slightly with elbows resting on a railing or ledge +- One foot crossed over the other at ankle level +- Tilt head slightly for a candid feel +**Camera Cues:** +- waist-up with railing in frame +- golden-hour backlight +- shallow depth of field + +## Look Down Phone + +**ID:** look_down_phone +**Tags:** street, candid, lifestyle, urban, portrait +**Tips:** +- Hold phone at chest height, elbows soft +- Chin slightly down toward the screen +- Weight on one leg for a natural hip shift +**Camera Cues:** +- eye-level three-quarter +- shallow depth for bokeh street lights + +## Looking Away + +**ID:** looking_away +**Tags:** portrait, golden_hour, outdoor, emotional, beach +**Tips:** +- Chin slightly down +- Eyes toward the light source +**Camera Cues:** +- profile or 3/4 face +- negative space on gaze side + +## Outdoor Running Midstride + +**ID:** outdoor_running_midstride +**Tags:** outdoor, motion, full body, sport, street +**Tips:** +- Capture mid-stride with lead knee high +- Arms opposite legs; torso upright +**Camera Cues:** +- full body; 1/500s+ shutter; slight pan + +## Over Shoulder Look + +**ID:** over_shoulder_look +**Tags:** portrait, profile, editorial, indoor, half body +**Tips:** +- Turn torso 45°; look back over the near shoulder +- Keep far shoulder soft; chin slightly down +**Camera Cues:** +- 85mm-equivalent; eye-level; soft side key + +## Over Shoulder Lookback + +**ID:** over_shoulder_lookback +**Tags:** outdoor, standing, portrait, lookback, candid +**Tips:** +- Body faces away; chin turns to camera over far shoulder +- Soft S-curve in spine; weight on back leg +**Camera Cues:** +- three-quarter rear; eye-level; catch light on cheek + +## Over the Shoulder + +**ID:** over_shoulder +**Tags:** portrait, golden_hour, outdoor, romantic, forest +**Tips:** +- Twist torso gently +- Chin toward shoulder +**Camera Cues:** +- shallow DOF +- catchlight in eyes + +## Palm Up Explain + +**ID:** palm_up_explain +**Tags:** portrait, communication, presenter, waist-up, studio +**Tips:** +- Both palms facing up at waist height suggests openness +- Slight forward lean engages the viewer +- Keep elbows close to the torso for natural framing +**Camera Cues:** +- waist-up +- eye-level +- clean background + +## Phone Scroll (looking down) + +**ID:** phone_scroll +**Tags:** portrait, casual, phone, lifestyle, daylight, indoor +**Tips:** +- Chin slightly down toward phone at chest height +- Elbows soft; keep face lit from above or window side +**Camera Cues:** +- waist-up or three-quarter; phone in lower third + +## Point Forward + +**ID:** point_forward +**Tags:** outdoor, action, directional, editorial, portrait, dynamic +**Tips:** +- Extend arm fully without locking elbow hard +- Eyes follow the point +- Plant front foot toward camera direction +**Camera Cues:** +- three-quarter body +- space in point direction +- mid shutter ## Power Stance -**Description:** Feet shoulder-width apart, hands on hips or open -**When to use:** Portrait, outdoor, urban, action, confident scenes - -**Matching poses:** -- Arms Crossed (arms_crossed): Keep shoulders relaxed, Chin slightly down for stronger jaw line -- Crossed Arms Stand (cross_arms_stand): Arms lightly crossed at chest; shoulders relaxed, Weight on one leg; soft smile to lens -- Power Stance (power_stance): Feet shoulder-width, Shoulders back - -## Lean -**Description:** Leaning against wall, surface, or object -**When to use:** Urban, street, lifestyle, casual, indoor scenes - -**Matching poses:** -- Lean Window Portrait (lean_window_portrait): Lean outer shoulder to window frame; face toward light, Far hand on hip or frame; keep neck long -- Leaning Doorframe (leaning_doorframe): Shoulder lightly against frame; weight on far leg, Far hand in pocket or on hip; near hand free along frame - -## Sitting -**Description:** Seated position -**When to use:** Indoor, lifestyle, cafe, study, thoughtful scenes - -**Matching poses:** -- Book Reading (seated) (book_reading): Hold book at mid-chest; elbows soft, Chin slightly down toward page; eyes toward lens on cue -- Chin Rest on Hand (chin_rest): Elbow on table or knee; knuckles under chin lightly, Eyes soft toward camera or to lens -- Coffee Table Lean (coffee_table_lean): Forearms on table; torso slightly forward, Shoulders soft; gaze past camera or to lens -- Laptop Desk (seated) (laptop_desk): Sit upright; screen slightly below eye line, Hands on keyboard; shoulders relaxed -- Lean Forward Desk (lean_forward_desk): Elbows on desk, Lean slightly toward camera -- ... and 4 more - -## Kneeling -**Description:** One or both knees on ground -**When to use:** Outdoor, street, proposal, intimate scenes - -**Matching poses:** -- Kneeling Propose Style (kneeling_propose_style): One knee down; upright torso; soft eye contact forward, Hands at mid-chest height or offering gesture \ No newline at end of file + +**ID:** power_stance +**Tags:** urban, business, indoor, studio, confident +**Tips:** +- Feet shoulder-width +- Shoulders back +- Chin level +**Camera Cues:** +- straight-on or slight low angle + +## Rooftop Golden Hour Stand + +**ID:** rooftop_golden_hour_stand +**Tags:** outdoor, golden hour, portrait, full body, skyline +**Tips:** +- Face 30° toward the sun; shoulders open to skyline +- Weight on back leg; front knee soft +**Camera Cues:** +- full body; expose for skin; rim light from sun + +## Selfie Peace Sign + +**ID:** selfie_peace +**Tags:** portrait, casual, selfie, daylight, indoor +**Tips:** +- Raise hand near cheek with peace (V) sign +- Slight head tilt, eyes to lens +**Camera Cues:** +- head-and-shoulders or waist-up, arm in frame + +## Side Profile Chin Up + +**ID:** side_profile_chin_up +**Tags:** studio, portrait, profile, standing, chin +**Tips:** +- True side profile; soft stretch through neck +- Chin slightly lifted; shoulders down and back +**Camera Cues:** +- profile 90°; eye-level; soft key from front + +## Side Profile Look + +**ID:** side_profile_look +**Tags:** portrait, profile, studio, fashion, daylight +**Tips:** +- Chin slightly forward +- Far shoulder drop for length +**Camera Cues:** +- true profile or 3/4 profile + +## Side Profile Walk + +**ID:** side_profile_walk +**Tags:** outdoor, full body, motion, street, profile +**Tips:** +- Walk parallel to camera; mid-stride +- Chin level; arms natural swing +**Camera Cues:** +- full body side; 1/125s+ shutter for freeze + +## Standing Three-Quarter Turn + +**ID:** standing_three_quarter_turn +**Tags:** portrait, indoor, studio, three-quarter, standing +**Tips:** +- Turn hips 30–45° from camera; face back toward lens +- Front shoulder slightly lower; weight on back foot +**Camera Cues:** +- head-to-knee crop; soft key 45° + +## Stretch Reach + +**ID:** stretch_reach +**Tags:** outdoor, athletic, yoga, dynamic, full_body, portrait +**Tips:** +- Reach long through fingertips +- Keep ribs stacked over pelvis +- Ground through both feet evenly +**Camera Cues:** +- full body +- slight low angle +- negative space above hands + +## Umbrella Walk + +**ID:** umbrella_walk +**Tags:** outdoor, lifestyle, street, rain, full body +**Tips:** +- Hold umbrella slightly ahead and above forehead +- Stride mid-step; free hand relaxed at side +**Camera Cues:** +- full body 3/4; low street angle optional + +## Walk Toward Camera + +**ID:** walk_toward_camera +**Tags:** street, urban, motion, daylight, outdoor +**Tips:** +- Mid-stride freeze +- Front foot toward camera +**Camera Cues:** +- shutter 1/250+ +- lead room in front + +## Wall Lean + +**ID:** wall_lean +**Tags:** outdoor, street, portrait, editorial, casual +**Tips:** +- Place one shoulder and hip lightly against the wall +- Cross ankles or rest the free foot on the toe +- Keep chin slightly down for a soft gaze +**Camera Cues:** +- three-quarter angle +- eye-level or slightly below + +## Weight Shift Standing + +**ID:** weight_shift_standing +**Tags:** portrait, casual, natural, waist-up, indoor +**Tips:** +- Shift most weight to one hip +- Let the free leg bend slightly at the knee +- Keep shoulders level for a relaxed look +**Camera Cues:** +- waist-up crop +- soft window light from the side + +## Window Gaze + +**ID:** window_gaze +**Tags:** indoor, portrait, natural-light, lifestyle, waist-up +**Tips:** +- Stand beside window; face soft light +- Hands relaxed; eyes slightly off-camera +**Camera Cues:** +- waist-up; window as key light; clean background + +## Window Light Stand + +**ID:** window_light_stand +**Tags:** indoor, window, soft_light, portrait, home +**Tips:** +- Face the window at 45 degrees +- Far shoulder slightly back +**Camera Cues:** +- expose for face +- include window rim light + +## Yoga Tree Pose + +**ID:** yoga_tree +**Tags:** indoor, yoga, balance, full body, studio, calm +**Tips:** +- Press standing foot firmly into floor +- Knee opens to side without twisting hips +- Hands at heart or overhead with soft shoulders +**Camera Cues:** +- full body vertical +- eye level +- plain background