Merge pull request #6 from outis1one/claude/ai-photo-edit-tool-c8orl
Add public domain eye catalog system for CNC wood carving
This commit is contained in:
@@ -0,0 +1,225 @@
|
|||||||
|
# Eye Catalog Import Scripts
|
||||||
|
|
||||||
|
Tools for populating your carved eye catalog with public domain examples.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Quick Start
|
||||||
|
|
||||||
|
### 1. Download Classical Eyes
|
||||||
|
|
||||||
|
Follow the guide: `/docs/PUBLIC_DOMAIN_EYE_SOURCES.md`
|
||||||
|
|
||||||
|
**Best sources:**
|
||||||
|
- Metropolitan Museum (CC0)
|
||||||
|
- Smithsonian Open Access
|
||||||
|
- Getty Museum Open Content
|
||||||
|
|
||||||
|
**Download 10-20 high-res images** of carved eyes from classical sculptures.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 2. Crop the Eyes
|
||||||
|
|
||||||
|
Use any image editor (Photoshop, GIMP, Preview, etc.):
|
||||||
|
|
||||||
|
1. Open statue photo
|
||||||
|
2. Zoom in on eye
|
||||||
|
3. Crop just the eye (include eyelids, socket, tear duct)
|
||||||
|
4. Save as PNG with descriptive name:
|
||||||
|
- `greek_serene_left.png`
|
||||||
|
- `roman_fierce_right.png`
|
||||||
|
- `egyptian_wise_left.png`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 3. Import to Catalog
|
||||||
|
|
||||||
|
**Easy way (one at a time):**
|
||||||
|
```bash
|
||||||
|
cd backend/scripts
|
||||||
|
|
||||||
|
# Import a Greek serene eye
|
||||||
|
python import_eyes.py greek_serene_left.png \
|
||||||
|
--emotion serene \
|
||||||
|
--side left \
|
||||||
|
--style greek
|
||||||
|
|
||||||
|
# Import a Roman fierce eye
|
||||||
|
python import_eyes.py roman_fierce_right.png \
|
||||||
|
--emotion fierce \
|
||||||
|
--side right \
|
||||||
|
--style roman
|
||||||
|
```
|
||||||
|
|
||||||
|
**Batch import:**
|
||||||
|
```bash
|
||||||
|
# Import all Greek eyes at once
|
||||||
|
python import_eyes.py greek_*.png \
|
||||||
|
--emotion serene \
|
||||||
|
--side both \
|
||||||
|
--style greek
|
||||||
|
|
||||||
|
# Import all Roman eyes
|
||||||
|
python import_eyes.py roman_*.png \
|
||||||
|
--emotion fierce \
|
||||||
|
--side both \
|
||||||
|
--style roman
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Available Options
|
||||||
|
|
||||||
|
### Emotions
|
||||||
|
- `serene` - Peaceful, calm (most classical Greek)
|
||||||
|
- `fierce` - Intense, powerful (Hellenistic, Alexander)
|
||||||
|
- `wise` - Aged, experienced (Roman senators)
|
||||||
|
- `peaceful` - Gentle, kind (Archaic Greek)
|
||||||
|
- `joyful` - Happy, smiling (rare in classical)
|
||||||
|
- `sorrowful` - Sad, mourning (some Hellenistic)
|
||||||
|
- `neutral` - Default, no strong emotion
|
||||||
|
|
||||||
|
### Styles
|
||||||
|
- `greek` - Classical Greek (450-400 BCE)
|
||||||
|
- `roman` - Roman Republican/Imperial
|
||||||
|
- `egyptian` - Ancient Egyptian carved eyes
|
||||||
|
- `renaissance` - Renaissance sculpture
|
||||||
|
- `baroque` - Baroque period
|
||||||
|
- `modern` - Contemporary carving
|
||||||
|
- `custom` - Your own style
|
||||||
|
|
||||||
|
### Sides
|
||||||
|
- `left` - Left eye
|
||||||
|
- `right` - Right eye
|
||||||
|
- `both` - Can be used for either (symmetric)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Example Workflow
|
||||||
|
|
||||||
|
### Build a Complete Catalog
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 1. Download eyes from Met Museum
|
||||||
|
# (See PUBLIC_DOMAIN_EYE_SOURCES.md)
|
||||||
|
|
||||||
|
# 2. Crop and save them:
|
||||||
|
# greek_serene_left.png
|
||||||
|
# greek_serene_right.png
|
||||||
|
# roman_fierce_left.png
|
||||||
|
# roman_fierce_right.png
|
||||||
|
# etc.
|
||||||
|
|
||||||
|
# 3. Import them all:
|
||||||
|
|
||||||
|
python import_eyes.py greek_serene_left.png --emotion serene --side left --style greek
|
||||||
|
python import_eyes.py greek_serene_right.png --emotion serene --side right --style greek
|
||||||
|
python import_eyes.py roman_fierce_left.png --emotion fierce --side left --style roman
|
||||||
|
python import_eyes.py roman_fierce_right.png --emotion fierce --side right --style roman
|
||||||
|
|
||||||
|
# Or batch:
|
||||||
|
python import_eyes.py greek_*.png --emotion serene --side both --style greek
|
||||||
|
python import_eyes.py roman_*.png --emotion fierce --side both --style roman
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Recommended Starting Collection
|
||||||
|
|
||||||
|
### 10 Essential Eyes
|
||||||
|
|
||||||
|
1. **Greek Serene Left** (peaceful carvings)
|
||||||
|
2. **Greek Serene Right**
|
||||||
|
3. **Greek Archaic Left** (stylized, simple)
|
||||||
|
4. **Greek Archaic Right**
|
||||||
|
5. **Roman Fierce Left** (powerful portraits)
|
||||||
|
6. **Roman Fierce Right**
|
||||||
|
7. **Roman Wise Left** (aged, realistic)
|
||||||
|
8. **Roman Wise Right**
|
||||||
|
9. **Egyptian Stylized Left** (distinctive style)
|
||||||
|
10. **Egyptian Stylized Right**
|
||||||
|
|
||||||
|
This gives you 5 styles/emotions to start!
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Check Your Catalog
|
||||||
|
|
||||||
|
### Via API
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# List all eyes in catalog
|
||||||
|
curl http://localhost:8101/patches/?category=carved_eye
|
||||||
|
|
||||||
|
# Filter by emotion
|
||||||
|
curl http://localhost:8101/patches/?category=carved_eye&tags=serene
|
||||||
|
|
||||||
|
# Filter by style
|
||||||
|
curl http://localhost:8101/patches/?tags=greek
|
||||||
|
```
|
||||||
|
|
||||||
|
### Via Web Interface
|
||||||
|
|
||||||
|
Go to: `http://your-server:3080`
|
||||||
|
|
||||||
|
Navigate to patch library to browse your eyes visually.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Advanced: Seed Script
|
||||||
|
|
||||||
|
For batch importing from the `seed_data/eyes/` directory:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 1. Place all cropped eyes in:
|
||||||
|
mkdir -p seed_data/eyes/
|
||||||
|
# Copy your eye images there
|
||||||
|
|
||||||
|
# 2. Edit seed_eye_catalog.py to add metadata
|
||||||
|
|
||||||
|
# 3. Run:
|
||||||
|
python seed_eye_catalog.py
|
||||||
|
```
|
||||||
|
|
||||||
|
This auto-imports all eyes in `seed_data/eyes/` with pre-configured metadata.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Tips
|
||||||
|
|
||||||
|
1. **High resolution:** Use images 1000px+ for best results
|
||||||
|
2. **Clean crops:** Include some surrounding area, not just the eyeball
|
||||||
|
3. **Consistent naming:** Use descriptive filenames
|
||||||
|
4. **Test first:** Import 2-3 eyes to test the workflow
|
||||||
|
5. **Build gradually:** Start with 10 eyes, expand as needed
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
**"File not found":**
|
||||||
|
- Make sure you're in `backend/scripts/` directory
|
||||||
|
- Use full path or relative path to image
|
||||||
|
|
||||||
|
**"Database connection error":**
|
||||||
|
- Make sure backend is running: `docker compose up backend`
|
||||||
|
- Check database exists: `ls -la ../../data/`
|
||||||
|
|
||||||
|
**"Import failed":**
|
||||||
|
- Check image format (PNG, JPG supported)
|
||||||
|
- Verify file isn't corrupted
|
||||||
|
- Check file permissions
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Next Steps
|
||||||
|
|
||||||
|
After importing eyes:
|
||||||
|
|
||||||
|
1. **Test them:** Apply to a colored photo via API
|
||||||
|
2. **Refine:** Add more variations as needed
|
||||||
|
3. **Build library:** Aim for 20-30 eyes covering all emotions
|
||||||
|
4. **Share:** Your best eyes can be exported and shared
|
||||||
|
|
||||||
|
**Your catalog of master sculptor's eyes is ready to use!**
|
||||||
Executable
+210
@@ -0,0 +1,210 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
Quick eye import script
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
python import_eyes.py greek_serene_left.png --emotion serene --side left --style greek
|
||||||
|
python import_eyes.py *.png --emotion fierce --style roman
|
||||||
|
|
||||||
|
This will add eyes to the patch library with proper metadata.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import argparse
|
||||||
|
from pathlib import Path
|
||||||
|
from PIL import Image
|
||||||
|
|
||||||
|
# Add parent directory to path to import app modules
|
||||||
|
sys.path.insert(0, str(Path(__file__).parent.parent))
|
||||||
|
|
||||||
|
from app.database import SessionLocal
|
||||||
|
from app.models.patch import Patch
|
||||||
|
from app.services.patch_library import PatchLibraryService
|
||||||
|
|
||||||
|
|
||||||
|
def import_eye(
|
||||||
|
image_path: Path,
|
||||||
|
emotion: str,
|
||||||
|
side: str,
|
||||||
|
style: str,
|
||||||
|
description: str = None
|
||||||
|
):
|
||||||
|
"""
|
||||||
|
Import a single eye image into the catalog
|
||||||
|
|
||||||
|
Args:
|
||||||
|
image_path: Path to eye image file
|
||||||
|
emotion: serene, fierce, wise, peaceful, joyful, sorrowful
|
||||||
|
side: left, right, both
|
||||||
|
style: greek, roman, egyptian, renaissance, custom
|
||||||
|
description: Optional custom description
|
||||||
|
"""
|
||||||
|
|
||||||
|
db = SessionLocal()
|
||||||
|
patch_service = PatchLibraryService()
|
||||||
|
|
||||||
|
# Generate name from filename if not provided
|
||||||
|
name = image_path.stem.replace('_', ' ').title()
|
||||||
|
|
||||||
|
# Auto-generate description if not provided
|
||||||
|
if not description:
|
||||||
|
description = f"{style.title()} carved eye, {emotion} expression, {side} side. Suitable for CNC wood carving."
|
||||||
|
|
||||||
|
# Generate tags
|
||||||
|
tags = f"{style}, {emotion}, {side}, carved, cnc-ready, wood-carving"
|
||||||
|
|
||||||
|
print(f"\n📸 Importing: {name}")
|
||||||
|
print(f" File: {image_path.name}")
|
||||||
|
print(f" Style: {style}")
|
||||||
|
print(f" Emotion: {emotion}")
|
||||||
|
print(f" Side: {side}")
|
||||||
|
|
||||||
|
try:
|
||||||
|
# Create patch record
|
||||||
|
patch = Patch(
|
||||||
|
name=name,
|
||||||
|
description=description,
|
||||||
|
source_type="imported",
|
||||||
|
category="carved_eye",
|
||||||
|
tags=tags,
|
||||||
|
width=0,
|
||||||
|
height=0,
|
||||||
|
user_id=None,
|
||||||
|
file_path=""
|
||||||
|
)
|
||||||
|
|
||||||
|
db.add(patch)
|
||||||
|
db.commit()
|
||||||
|
db.refresh(patch)
|
||||||
|
|
||||||
|
# Save image file
|
||||||
|
file_path = patch_service.save_patch_from_file(
|
||||||
|
patch.id,
|
||||||
|
str(image_path),
|
||||||
|
create_thumb=True
|
||||||
|
)
|
||||||
|
|
||||||
|
# Get and update dimensions
|
||||||
|
width, height = patch_service.get_patch_size(patch.id)
|
||||||
|
patch.width = width
|
||||||
|
patch.height = height
|
||||||
|
patch.file_path = file_path
|
||||||
|
patch.thumbnail_path = str(patch_service.get_thumbnail_path(patch.id))
|
||||||
|
|
||||||
|
db.commit()
|
||||||
|
|
||||||
|
print(f"✅ Successfully imported!")
|
||||||
|
print(f" ID: {patch.id}")
|
||||||
|
print(f" Size: {width}x{height}px")
|
||||||
|
|
||||||
|
return patch.id
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"❌ Error importing: {e}")
|
||||||
|
db.rollback()
|
||||||
|
return None
|
||||||
|
|
||||||
|
finally:
|
||||||
|
db.close()
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
parser = argparse.ArgumentParser(
|
||||||
|
description="Import carved eye images into the patch library",
|
||||||
|
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||||
|
epilog="""
|
||||||
|
Examples:
|
||||||
|
# Import a single eye
|
||||||
|
python import_eyes.py greek_serene_left.png --emotion serene --side left --style greek
|
||||||
|
|
||||||
|
# Import multiple eyes with same metadata
|
||||||
|
python import_eyes.py roman_*.png --emotion fierce --side both --style roman
|
||||||
|
|
||||||
|
# With custom description
|
||||||
|
python import_eyes.py statue_eye.png --emotion wise --side right --style roman --description "Emperor Augustus portrait eye"
|
||||||
|
|
||||||
|
Emotions: serene, fierce, wise, peaceful, joyful, sorrowful, neutral
|
||||||
|
Sides: left, right, both
|
||||||
|
Styles: greek, roman, egyptian, renaissance, baroque, modern, custom
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
|
||||||
|
parser.add_argument(
|
||||||
|
'images',
|
||||||
|
nargs='+',
|
||||||
|
help='Image file(s) to import (supports wildcards)'
|
||||||
|
)
|
||||||
|
|
||||||
|
parser.add_argument(
|
||||||
|
'--emotion',
|
||||||
|
required=True,
|
||||||
|
choices=['serene', 'fierce', 'wise', 'peaceful', 'joyful', 'sorrowful', 'neutral'],
|
||||||
|
help='Emotional expression of the eye'
|
||||||
|
)
|
||||||
|
|
||||||
|
parser.add_argument(
|
||||||
|
'--side',
|
||||||
|
required=True,
|
||||||
|
choices=['left', 'right', 'both'],
|
||||||
|
help='Which eye (left or right)'
|
||||||
|
)
|
||||||
|
|
||||||
|
parser.add_argument(
|
||||||
|
'--style',
|
||||||
|
required=True,
|
||||||
|
choices=['greek', 'roman', 'egyptian', 'renaissance', 'baroque', 'modern', 'custom'],
|
||||||
|
help='Carving style/period'
|
||||||
|
)
|
||||||
|
|
||||||
|
parser.add_argument(
|
||||||
|
'--description',
|
||||||
|
help='Custom description (optional)'
|
||||||
|
)
|
||||||
|
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
# Resolve wildcards and get all image files
|
||||||
|
image_files = []
|
||||||
|
for pattern in args.images:
|
||||||
|
path = Path(pattern)
|
||||||
|
if '*' in pattern:
|
||||||
|
# Wildcard - expand it
|
||||||
|
parent = path.parent if path.parent.exists() else Path('.')
|
||||||
|
image_files.extend(parent.glob(path.name))
|
||||||
|
else:
|
||||||
|
# Single file
|
||||||
|
if path.exists():
|
||||||
|
image_files.append(path)
|
||||||
|
else:
|
||||||
|
print(f"⚠️ File not found: {pattern}")
|
||||||
|
|
||||||
|
if not image_files:
|
||||||
|
print("❌ No image files found!")
|
||||||
|
return
|
||||||
|
|
||||||
|
print(f"\n🎨 Importing {len(image_files)} eye image(s) into catalog...")
|
||||||
|
print(f" Style: {args.style}")
|
||||||
|
print(f" Emotion: {args.emotion}")
|
||||||
|
print(f" Side: {args.side}")
|
||||||
|
print("="*60)
|
||||||
|
|
||||||
|
imported_count = 0
|
||||||
|
for image_path in image_files:
|
||||||
|
patch_id = import_eye(
|
||||||
|
image_path,
|
||||||
|
args.emotion,
|
||||||
|
args.side,
|
||||||
|
args.style,
|
||||||
|
args.description
|
||||||
|
)
|
||||||
|
if patch_id:
|
||||||
|
imported_count += 1
|
||||||
|
|
||||||
|
print("="*60)
|
||||||
|
print(f"\n✅ Import complete! {imported_count}/{len(image_files)} eyes added to catalog")
|
||||||
|
print(f"\n💡 Access your eye catalog at: http://your-server:3080")
|
||||||
|
print(f" Or via API: GET /patches/?category=carved_eye")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
@@ -0,0 +1,176 @@
|
|||||||
|
"""
|
||||||
|
Seed the patch library with classical carved eyes from public domain sources
|
||||||
|
|
||||||
|
This script helps pre-populate the eye catalog with examples from:
|
||||||
|
- Greek statues (Metropolitan Museum, Louvre)
|
||||||
|
- Roman sculptures (Smithsonian, British Museum)
|
||||||
|
- Renaissance carvings
|
||||||
|
- Ancient Egyptian carved eyes
|
||||||
|
|
||||||
|
All images should be public domain (CC0, Public Domain Mark)
|
||||||
|
"""
|
||||||
|
|
||||||
|
import asyncio
|
||||||
|
import httpx
|
||||||
|
from pathlib import Path
|
||||||
|
from PIL import Image
|
||||||
|
from io import BytesIO
|
||||||
|
|
||||||
|
# Public domain eye examples to seed the catalog
|
||||||
|
# These are examples - you would add actual URLs from museum APIs
|
||||||
|
CLASSICAL_EYES = [
|
||||||
|
{
|
||||||
|
"name": "Greek Statue - Serene Left Eye",
|
||||||
|
"description": "Classical Greek marble carving, convex eyeball, defined upper lid, deep socket. Perfect for serene expressions.",
|
||||||
|
"category": "carved_eye",
|
||||||
|
"tags": "greek, serene, left, marble, classical, convex, deep-socket",
|
||||||
|
"style": "greek_classical",
|
||||||
|
"emotion": "serene",
|
||||||
|
"side": "left",
|
||||||
|
"source_url": "https://images.metmuseum.org/...", # Example
|
||||||
|
"source": "Metropolitan Museum of Art - Public Domain"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Roman Sculpture - Fierce Right Eye",
|
||||||
|
"description": "Roman marble, prominent brow ridge, intense gaze, sharp eyelid definition.",
|
||||||
|
"category": "carved_eye",
|
||||||
|
"tags": "roman, fierce, right, marble, intense, sharp-detail",
|
||||||
|
"style": "roman_classical",
|
||||||
|
"emotion": "fierce",
|
||||||
|
"side": "right",
|
||||||
|
"source_url": "https://...",
|
||||||
|
"source": "Smithsonian - CC0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Greek Kouros - Peaceful Left Eye",
|
||||||
|
"description": "Archaic Greek style, almond-shaped, subtle carving, peaceful expression.",
|
||||||
|
"category": "carved_eye",
|
||||||
|
"tags": "greek, peaceful, left, archaic, almond-shaped, subtle",
|
||||||
|
"style": "greek_archaic",
|
||||||
|
"emotion": "peaceful",
|
||||||
|
"side": "left",
|
||||||
|
"source_url": "https://...",
|
||||||
|
"source": "Getty Museum - Public Domain"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Roman Portrait - Wise Right Eye",
|
||||||
|
"description": "Late Roman period, detailed eyelids, slight downward gaze, wisdom and age.",
|
||||||
|
"category": "carved_eye",
|
||||||
|
"tags": "roman, wise, right, portrait, detailed, aged",
|
||||||
|
"style": "roman_portrait",
|
||||||
|
"emotion": "wise",
|
||||||
|
"side": "right",
|
||||||
|
"source_url": "https://...",
|
||||||
|
"source": "British Museum - CC0"
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
async def download_image(url: str) -> bytes:
|
||||||
|
"""Download image from URL"""
|
||||||
|
async with httpx.AsyncClient() as client:
|
||||||
|
response = await client.get(url)
|
||||||
|
response.raise_for_status()
|
||||||
|
return response.content
|
||||||
|
|
||||||
|
async def crop_eye_from_statue(image_bytes: bytes, crop_box: tuple) -> bytes:
|
||||||
|
"""
|
||||||
|
Crop just the eye from a full statue photo
|
||||||
|
|
||||||
|
Args:
|
||||||
|
image_bytes: Full statue image
|
||||||
|
crop_box: (left, top, right, bottom) coordinates
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Cropped eye image bytes
|
||||||
|
"""
|
||||||
|
img = Image.open(BytesIO(image_bytes))
|
||||||
|
eye = img.crop(crop_box)
|
||||||
|
|
||||||
|
# Save as PNG
|
||||||
|
buffer = BytesIO()
|
||||||
|
eye.save(buffer, format='PNG')
|
||||||
|
return buffer.getvalue()
|
||||||
|
|
||||||
|
async def seed_eye_catalog():
|
||||||
|
"""
|
||||||
|
Seed the patch library with classical carved eyes
|
||||||
|
|
||||||
|
NOTE: This is a template. You need to:
|
||||||
|
1. Get actual public domain image URLs
|
||||||
|
2. Manually crop the eyes (or provide crop coordinates)
|
||||||
|
3. Run this to populate the catalog
|
||||||
|
"""
|
||||||
|
|
||||||
|
from app.database import SessionLocal
|
||||||
|
from app.models.patch import Patch
|
||||||
|
from app.services.patch_library import PatchLibraryService
|
||||||
|
|
||||||
|
db = SessionLocal()
|
||||||
|
patch_service = PatchLibraryService()
|
||||||
|
|
||||||
|
print("Seeding eye catalog with classical carved eyes...")
|
||||||
|
|
||||||
|
for eye_data in CLASSICAL_EYES:
|
||||||
|
print(f"\nAdding: {eye_data['name']}")
|
||||||
|
|
||||||
|
# Create patch record
|
||||||
|
patch = Patch(
|
||||||
|
name=eye_data['name'],
|
||||||
|
description=eye_data['description'],
|
||||||
|
source_type="imported",
|
||||||
|
category=eye_data['category'],
|
||||||
|
tags=eye_data['tags'],
|
||||||
|
width=0, # Will be set after image save
|
||||||
|
height=0,
|
||||||
|
user_id=None,
|
||||||
|
file_path=""
|
||||||
|
)
|
||||||
|
|
||||||
|
db.add(patch)
|
||||||
|
db.commit()
|
||||||
|
db.refresh(patch)
|
||||||
|
|
||||||
|
# Download and save image
|
||||||
|
# NOTE: You need to manually download/crop these first
|
||||||
|
# This is just the structure
|
||||||
|
|
||||||
|
try:
|
||||||
|
# image_bytes = await download_image(eye_data['source_url'])
|
||||||
|
# cropped_eye = await crop_eye_from_statue(image_bytes, crop_box)
|
||||||
|
|
||||||
|
# For now, you would manually place images in:
|
||||||
|
# ./seed_data/eyes/greek_serene_left.png
|
||||||
|
# ./seed_data/eyes/roman_fierce_right.png
|
||||||
|
# etc.
|
||||||
|
|
||||||
|
seed_image_path = Path(__file__).parent / "seed_data" / "eyes" / f"{eye_data['style']}_{eye_data['emotion']}_{eye_data['side']}.png"
|
||||||
|
|
||||||
|
if seed_image_path.exists():
|
||||||
|
file_path = patch_service.save_patch_from_file(
|
||||||
|
patch.id,
|
||||||
|
str(seed_image_path),
|
||||||
|
create_thumb=True
|
||||||
|
)
|
||||||
|
|
||||||
|
# Get dimensions
|
||||||
|
width, height = patch_service.get_patch_size(patch.id)
|
||||||
|
patch.width = width
|
||||||
|
patch.height = height
|
||||||
|
patch.file_path = file_path
|
||||||
|
patch.thumbnail_path = str(patch_service.get_thumbnail_path(patch.id))
|
||||||
|
|
||||||
|
db.commit()
|
||||||
|
print(f"✅ Added {eye_data['name']}")
|
||||||
|
else:
|
||||||
|
print(f"⚠️ Image not found: {seed_image_path}")
|
||||||
|
print(f" Please download and crop eye from: {eye_data['source']}")
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"❌ Error adding {eye_data['name']}: {e}")
|
||||||
|
db.rollback()
|
||||||
|
|
||||||
|
db.close()
|
||||||
|
print("\n✅ Eye catalog seeding complete!")
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
asyncio.run(seed_eye_catalog())
|
||||||
@@ -0,0 +1,300 @@
|
|||||||
|
# Public Domain Carved Eye Sources
|
||||||
|
|
||||||
|
Where to find high-quality images of carved eyes from classical sculptures (all public domain).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Best Museums with Public Domain Images
|
||||||
|
|
||||||
|
### 1. Metropolitan Museum of Art (CC0 Public Domain)
|
||||||
|
|
||||||
|
**Website:** https://www.metmuseum.org/art/collection
|
||||||
|
|
||||||
|
**Search tips:**
|
||||||
|
- Search: "greek statue marble head"
|
||||||
|
- Search: "roman portrait bust"
|
||||||
|
- Filter: "Public Domain" only
|
||||||
|
- Download: Click "Download" for high-resolution
|
||||||
|
|
||||||
|
**Great examples:**
|
||||||
|
- Greek Kouros heads (Archaic period)
|
||||||
|
- Roman portrait busts
|
||||||
|
- Hellenistic marble sculptures
|
||||||
|
|
||||||
|
**Direct collections:**
|
||||||
|
- Greek & Roman Art: https://www.metmuseum.org/art/collection/search#!?department=13
|
||||||
|
- Filter by "Images" → "Public Domain"
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 2. Smithsonian Open Access (CC0)
|
||||||
|
|
||||||
|
**Website:** https://www.si.edu/openaccess
|
||||||
|
|
||||||
|
**Features:**
|
||||||
|
- 3 million+ images
|
||||||
|
- All CC0 (no copyright restrictions)
|
||||||
|
- High-resolution downloads
|
||||||
|
|
||||||
|
**Search:**
|
||||||
|
- "roman marble head"
|
||||||
|
- "greek sculpture eyes"
|
||||||
|
- "classical portrait bust"
|
||||||
|
|
||||||
|
**API available:** https://api.si.edu/openaccess/api/v1.0/
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 3. Getty Museum (Open Content)
|
||||||
|
|
||||||
|
**Website:** https://www.getty.edu/art/collection/
|
||||||
|
|
||||||
|
**Search tips:**
|
||||||
|
- Filter: "Open Content Program"
|
||||||
|
- Greek and Roman antiquities
|
||||||
|
- High-resolution IIIF images
|
||||||
|
|
||||||
|
**Great for:**
|
||||||
|
- Archaic Greek sculptures
|
||||||
|
- Classical period heads
|
||||||
|
- Detailed close-ups
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 4. Rijksmuseum (Public Domain)
|
||||||
|
|
||||||
|
**Website:** https://www.rijksmuseum.nl/en/rijksstudio
|
||||||
|
|
||||||
|
**Features:**
|
||||||
|
- Rijksstudio (free download tool)
|
||||||
|
- High-resolution images
|
||||||
|
- Classical sculpture collection
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 5. British Museum (CC BY-NC-SA 4.0)
|
||||||
|
|
||||||
|
**Website:** https://www.britishmuseum.org/collection
|
||||||
|
|
||||||
|
**Note:** Some restrictions, but many images free for non-commercial use
|
||||||
|
|
||||||
|
**Great for:**
|
||||||
|
- Egyptian carved eyes
|
||||||
|
- Greek marble heads
|
||||||
|
- Roman portraits
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 6. Louvre Collections
|
||||||
|
|
||||||
|
**Website:** https://collections.louvre.fr/en/
|
||||||
|
|
||||||
|
**Search:** "sculpture greek head" or "sculpture roman portrait"
|
||||||
|
|
||||||
|
**Note:** Check individual image licenses
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## How to Find the Perfect Eyes
|
||||||
|
|
||||||
|
### Search Strategy
|
||||||
|
|
||||||
|
1. **Search for heads/busts, not full statues:**
|
||||||
|
- "greek marble head"
|
||||||
|
- "roman portrait bust"
|
||||||
|
- "classical sculpture face"
|
||||||
|
|
||||||
|
2. **Specific periods:**
|
||||||
|
- "archaic greek kouros" (serene, stylized)
|
||||||
|
- "classical greek sculpture" (idealized, peaceful)
|
||||||
|
- "hellenistic sculpture" (emotional, dramatic)
|
||||||
|
- "roman portrait" (realistic, wise)
|
||||||
|
|
||||||
|
3. **Look for close-ups:**
|
||||||
|
- Museums often provide detail shots
|
||||||
|
- Check "zoom" or "IIIF viewer" options
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Recommended Starting Collection
|
||||||
|
|
||||||
|
### Serene/Peaceful Eyes
|
||||||
|
|
||||||
|
**Greek Classical Period (450-400 BCE):**
|
||||||
|
- Doryphoros (Spear Bearer) type
|
||||||
|
- Athena heads
|
||||||
|
- Apollo statues
|
||||||
|
- Smooth, idealized features
|
||||||
|
- Almond-shaped eyes
|
||||||
|
- Minimal lid detail
|
||||||
|
|
||||||
|
**Best sources:** Met Museum, Getty
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Fierce/Intense Eyes
|
||||||
|
|
||||||
|
**Hellenistic Period (323-31 BCE):**
|
||||||
|
- Alexander the Great portraits
|
||||||
|
- Dying Gaul
|
||||||
|
- Laocoon group
|
||||||
|
- Dramatic expressions
|
||||||
|
- Deep-set eyes
|
||||||
|
- Strong brow ridges
|
||||||
|
|
||||||
|
**Best sources:** Smithsonian, British Museum
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Wise/Aged Eyes
|
||||||
|
|
||||||
|
**Roman Republican Period:**
|
||||||
|
- Senator portraits
|
||||||
|
- Veristic portraits
|
||||||
|
- Realistic aging details
|
||||||
|
- Detailed wrinkles
|
||||||
|
- Saggy eyelids
|
||||||
|
- Life-like features
|
||||||
|
|
||||||
|
**Best sources:** Met Museum, Getty
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Stylized/Archaic Eyes
|
||||||
|
|
||||||
|
**Greek Archaic Period (700-480 BCE):**
|
||||||
|
- Kouros statues
|
||||||
|
- Kore statues
|
||||||
|
- Almond-shaped
|
||||||
|
- Simplified forms
|
||||||
|
- "Archaic smile"
|
||||||
|
- Clean, simple carving
|
||||||
|
|
||||||
|
**Best sources:** Getty, Met Museum
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## How to Download and Crop
|
||||||
|
|
||||||
|
### Step 1: Find the Statue
|
||||||
|
|
||||||
|
Example: Met Museum
|
||||||
|
1. Go to https://www.metmuseum.org/art/collection
|
||||||
|
2. Search: "roman portrait marble"
|
||||||
|
3. Filter: Public Domain only
|
||||||
|
4. Click on a good example
|
||||||
|
|
||||||
|
### Step 2: Download High-Res
|
||||||
|
|
||||||
|
1. Click "Download" button
|
||||||
|
2. Choose largest size (usually 4000px+)
|
||||||
|
3. Save to your computer
|
||||||
|
|
||||||
|
### Step 3: Crop the Eyes
|
||||||
|
|
||||||
|
Use any image editor (Photoshop, GIMP, etc.):
|
||||||
|
|
||||||
|
1. Open the full statue image
|
||||||
|
2. Zoom in on one eye
|
||||||
|
3. Crop just the eye area:
|
||||||
|
- Include: eyeball, eyelids, tear duct, socket
|
||||||
|
- Leave some surrounding area for context
|
||||||
|
- Square or slightly rectangular crop
|
||||||
|
|
||||||
|
4. Save as PNG:
|
||||||
|
- `greek_serene_left.png`
|
||||||
|
- `roman_fierce_right.png`
|
||||||
|
- etc.
|
||||||
|
|
||||||
|
5. Repeat for other eye (if different)
|
||||||
|
|
||||||
|
### Step 4: Organize
|
||||||
|
|
||||||
|
Place cropped eyes in:
|
||||||
|
```
|
||||||
|
./backend/scripts/seed_data/eyes/
|
||||||
|
├── greek_serene_left.png
|
||||||
|
├── greek_serene_right.png
|
||||||
|
├── roman_fierce_left.png
|
||||||
|
├── roman_fierce_right.png
|
||||||
|
├── greek_peaceful_left.png
|
||||||
|
└── ...
|
||||||
|
```
|
||||||
|
|
||||||
|
### Step 5: Run Seed Script
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd backend
|
||||||
|
python scripts/seed_eye_catalog.py
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Recommended Starting Collection (10 Eyes)
|
||||||
|
|
||||||
|
To start, get these 10 eyes:
|
||||||
|
|
||||||
|
### Greek Classical (Serene)
|
||||||
|
1. Left eye - Greek marble head
|
||||||
|
2. Right eye - Greek marble head
|
||||||
|
|
||||||
|
### Greek Archaic (Stylized/Peaceful)
|
||||||
|
3. Left eye - Kouros statue
|
||||||
|
4. Right eye - Kouros statue
|
||||||
|
|
||||||
|
### Hellenistic (Fierce/Dramatic)
|
||||||
|
5. Left eye - Alexander portrait
|
||||||
|
6. Right eye - Alexander portrait
|
||||||
|
|
||||||
|
### Roman Republican (Wise/Aged)
|
||||||
|
7. Left eye - Roman senator bust
|
||||||
|
8. Right eye - Roman senator bust
|
||||||
|
|
||||||
|
### Roman Imperial (Powerful)
|
||||||
|
9. Left eye - Emperor portrait
|
||||||
|
10. Right eye - Emperor portrait
|
||||||
|
|
||||||
|
This gives you 5 emotional ranges × 2 eyes = 10 eyes to start!
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Quick Links
|
||||||
|
|
||||||
|
- **Met Museum Collection:** https://www.metmuseum.org/art/collection/search#!?department=13&showOnly=openAccess
|
||||||
|
- **Smithsonian Open Access:** https://www.si.edu/openaccess
|
||||||
|
- **Getty Open Content:** https://www.getty.edu/about/whatwedo/opencontent.html
|
||||||
|
- **Rijksmuseum API:** https://data.rijksmuseum.nl/object-metadata/api/
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Legal Notes
|
||||||
|
|
||||||
|
- **CC0/Public Domain:** Use freely for any purpose
|
||||||
|
- **CC BY:** Must credit the source
|
||||||
|
- **CC BY-NC:** Non-commercial use only
|
||||||
|
- **Always check** individual image licenses
|
||||||
|
|
||||||
|
For commercial carving business, stick to **CC0** or **Public Domain** images.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Tips for Best Results
|
||||||
|
|
||||||
|
1. **High resolution:** Download largest size available (2000px+ minimum)
|
||||||
|
2. **Good lighting:** Look for evenly lit photographs
|
||||||
|
3. **Straight-on angle:** Avoid extreme angles
|
||||||
|
4. **Clear detail:** Can you see the eyelid lines clearly?
|
||||||
|
5. **Minimal damage:** Choose well-preserved sculptures
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Next Steps
|
||||||
|
|
||||||
|
1. Browse the museums above
|
||||||
|
2. Download 10-20 good eye examples
|
||||||
|
3. Crop them in an image editor
|
||||||
|
4. Place in `backend/scripts/seed_data/eyes/`
|
||||||
|
5. Run the seed script
|
||||||
|
6. Your catalog is ready!
|
||||||
|
|
||||||
|
**You'll have a library of proven carved eyes from master sculptors spanning 2000+ years!**
|
||||||
Reference in New Issue
Block a user