Add public domain eye catalog system for CNC wood carving

Added complete system for populating eye catalog with classical carved eyes:

Features:
- Eye import script (import_eyes.py) for batch/single eye imports
- Public domain source guide (museums: Met, Smithsonian, Getty, etc.)
- Seed catalog system for pre-populating database
- Organized by emotion (serene, fierce, wise, peaceful, etc.)
- Organized by style (Greek, Roman, Egyptian, Renaissance)
- Organized by side (left, right, both)
- Auto-generates thumbnails and metadata
- CNC-ready tagging system

Workflow:
1. Download classical sculpture photos from public domain museums
2. Crop eyes in any image editor
3. Run import script with metadata
4. Eyes saved to catalog with proper tags
5. Apply to colored photos (pure image compositing, no AI regeneration)
6. Convert result to grayscale for CNC carving

Documentation:
- PUBLIC_DOMAIN_EYE_SOURCES.md: Where to find carved eyes
- scripts/README.md: How to import eyes
- Includes recommended starting collection (10 essential eyes)

Benefits for wood carving:
- Build library from master sculptors (2000+ years of proven designs)
- Reusable across all projects
- Consistent emotional weight in carvings
- No AI regeneration - just intelligent copy/paste/blend
- Perfect for CNC workflow (colored preview → grayscale → carve)

The patch library system uses PIL/OpenCV for image compositing,
NOT AI regeneration, so it preserves exact carved geometry.
This commit is contained in:
Claude
2026-01-25 02:06:40 +00:00
parent cfbb9b691f
commit 3fe70fa663
4 changed files with 911 additions and 0 deletions
+225
View File
@@ -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!**
+210
View File
@@ -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()
+176
View File
@@ -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())
+300
View File
@@ -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!**