🎨 psdfy
Convert any image into an editable Adobe Photoshop file with AI-powered layer segmentation.
Upload a photo, and psdfy automatically detects objects, creates separate layers for each one, and exports a ready-to-edit .psd file. Perfect for designers, photographers, and anyone who needs to work with layered images.
✨ Features
- 🤖 AI-Powered Segmentation - Uses SAM 2 to automatically detect and separate objects
- 📦 Multi-Layer PSD Export - Each detected object becomes an editable layer
- 🎯 Text-Prompted Detection - Optional GroundingDINO integration for specific object detection
- 🌐 Web UI - Simple browser interface for uploading and downloading
- 💻 CLI Tool - Command-line interface for automation and scripting
- ☁️ Cloud Ready - S3 storage backend support for cloud deployments
- 🐳 Docker Support - CPU and GPU Docker images included
- ⚡ Fast Processing - Optimized for 1080p images (< 5 seconds on GPU)
🚀 Quick Start
Option 1: Web UI (Easiest)
# Install psdfy
pip install psdfy
# Run installation wizard
psdfy install
# Start the service
psdfy start
# Open browser and go to http://localhost:3457
Then:
- Login with password (default:
123456) - Upload an image
- Click "Convert to PSD"
- Download your layered PSD file
Option 1b: Lightweight Install (GroundingDINO Only)
If you want to set up psdfy without downloading the large SAM2 model weights (2GB+), use:
# Install psdfy
pip install psdfy
# Run installation wizard without SAM2 weights
psdfy install --no-weights
# Start the service
psdfy start
What you get with --no-weights:
- ✅ GroundingDINO model (text-prompt based detection)
- ✅ Web UI with "Text Prompt" mode only
- ❌ SAM2 automatic segmentation (requires full install)
- ❌ "Auto" mode in the UI (hidden)
When to use this:
- Setting up on servers with limited bandwidth or disk space
- Testing the UI before committing to full installation
- Running text-prompt-only workflows
- Downloading SAM2 weights later on a separate machine
Upgrading to full install:
# Download SAM2 weights later
psdfy install
This will add SAM2 support and enable the "Auto" mode in the UI.
Note: The combined "GroundingDINO + SAM2" refinement mode is coming soon.
Option 2: Docker (Recommended)
# CPU version
docker build -f docker/Dockerfile -t psdfy:latest .
docker run -p 3456:3456 -p 3457:3457 psdfy:latest
# GPU version (CUDA 12.1)
docker build -f docker/Dockerfile.gpu -t psdfy:gpu .
docker run --gpus all -p 3456:3456 -p 3457:3457 psdfy:gpu
Option 3: Python API
from app.utils.io import load_image
from app.services.segmenter import get_segmenter
from app.services.psd_writer import get_psd_writer
# Load image
image_array, (width, height), fmt = load_image(image_bytes)
# Segment objects
segmenter = get_segmenter()
masks = segmenter.segment_auto(image_array)
# Write PSD
psd_writer = get_psd_writer()
psd_bytes = psd_writer.write_psd(layers, width, height)
📖 Usage
Web UI
- Login - Enter password (default:
123456) - Upload - Drag & drop or click to select image
- Configure - Choose segmentation mode:
Automatic- Detects all objectsText Prompt- Specify objects (e.g., "person . table . book")
- Convert - Click "Convert to PSD"
- Download - Get your layered PSD file
CLI Commands
# Show version and system info
psdfy version
# Install/configure psdfy
psdfy install --password mypassword
# Start API and UI servers
psdfy start
# Stop servers
psdfy stop
# Diagnose and repair installation
psdfy fix --dry-run
# Update to latest version
psdfy update
# Check for issues
psdfy fix --redownload-weights
🏗️ Architecture
┌─────────────────────────────────────────────────────────┐
│ Browser (Web UI) │
└────────────────────────┬────────────────────────────────┘
│ (Cookie Auth)
▼
┌─────────────────────────────────────────────────────────┐
│ GUI Web Server (Port 3457) │
│ - Login page │
│ - Upload interface │
│ - Server-side proxy to API │
└────────────────────────┬────────────────────────────────┘
│ (X-Session-Id, X-Client-Signature)
▼
┌─────────────────────────────────────────────────────────┐
│ Proxy API Server (Port 3456) │
│ - /convert - Image to PSD conversion │
│ - /files - Download results │
│ - /auth - Session management │
└────────────────────────┬────────────────────────────────┘
│
┌────────────────┼────────────────┐
▼ ▼ ▼
┌────────┐ ┌────────┐ ┌────────┐
│ SAM 2 │ │ Mask │ │ PSD │
│ Loader │ │ Post- │ │ Writer │
│ │ │ process│ │ │
└────────┘ └────────┘ └────────┘
🛠️ Development
Setup
# Clone repository
git clone https://github.com/Mattel-Limbo/psdfy.git
cd psdfy
# Create virtual environment
python -m venv venv
source venv/bin/activate # On Windows: venv\Scripts\activate
# Install in development mode
pip install -e ".[dev]"
Code Quality
# Run linter
ruff check app psdfy tests
# Format code
black app psdfy tests
# Type checking
mypy --strict app psdfy
# Run tests
pytest tests/ -v
Project Structure
psdfy/
├── app/ # FastAPI application
│ ├── api_app/ # Proxy API server (port 3456)
│ ├── ui_app/ # Web UI server (port 3457)
│ ├── services/ # Business logic (segmentation, PSD writing, etc.)
│ ├── models/ # AI model loaders (SAM 2, GroundingDINO)
│ ├── storage/ # Storage backends (local, S3)
│ └── utils/ # Helper utilities
├── psdfy/ # CLI tool
│ ├── commands/ # CLI commands (install, start, stop, etc.)
│ ├── config.py # Configuration management
│ └── weights.py # Model weights downloader
├── web/ # Web UI assets
│ └── templates/ # HTML templates
├── tests/ # Test suite
├── docker/ # Docker configurations
└── scripts/ # Utility scripts (benchmarking, etc.)
📋 Requirements
- Python: 3.11 or higher
- RAM: 8GB minimum (16GB recommended)
- GPU (optional): NVIDIA GPU with CUDA 12.1+ for faster processing
- Disk: 5GB for model weights
🔧 Configuration
Configuration is stored in ~/.psdfy/config.toml:
[app]
host = "localhost"
api_port = 3456
ui_port = 3457
device = "cpu" # or "cuda", "mps"
[auth]
ui_password_hash = "..."
client_secret = "..."
[models]
sam2_weights_path = "~/.psdfy/weights/sam2_hiera_large.pt"
enable_sam2 = true # Set to false with --no-weights
dino_weights_path = "~/.psdfy/weights/groundingdino_swint_ogc.pth"
enable_grounding_dino = true # Always true after install
Model Availability:
The UI automatically detects which models are available and shows only the corresponding segmentation modes:
| Install Command | enable_sam2 |
enable_grounding_dino |
UI Modes Available |
|---|---|---|---|
psdfy install |
true |
true |
Auto (SAM 2), Text Prompt |
psdfy install --no-weights |
false |
true |
Text Prompt only |
To check available modes programmatically, call GET /capabilities:
curl http://localhost:3456/api/capabilities
Response:
{
"modes": ["auto", "prompt"],
"default_mode": "auto",
"sam2_available": true,
"dino_available": true
}
🐛 Troubleshooting
Port Already in Use
# Change ports
psdfy start --api-port 3500 --ui-port 3501
Model Weights Not Found
# Re-download weights
psdfy fix --redownload-weights
Reset Password
# Reset to default (123456)
psdfy fix --reset-password
Check System Health
# Run diagnostics
psdfy fix --dry-run
📊 Performance
| Resolution | GPU (RTX 3080) | CPU (i7-12700) |
|---|---|---|
| 512x512 | ~0.5s | ~3s |
| 1080x1080 | ~1.5s | ~8s |
| 2160x2160 | ~4s | ~20s |
📝 API Examples
Convert Image (cURL)
# Get session
SESSION=$(curl -X POST http://localhost:3456/auth/client-signature \
-H "Content-Type: application/json" \
-d '{"clientSecret":"your-secret"}' | jq -r '.sessionId')
# Convert image
curl -X POST http://localhost:3456/convert \
-H "X-Session-Id: $SESSION" \
-H "X-Client-Signature: your-signature" \
-F "file=@image.jpg" \
-F "mode=auto" \
-o output.psd
Convert Image (Python)
import requests
# Get session
response = requests.post(
"http://localhost:3456/auth/client-signature",
json={"clientSecret": "your-secret"}
)
session_id = response.json()["sessionId"]
# Convert image
with open("image.jpg", "rb") as f:
response = requests.post(
"http://localhost:3456/convert",
headers={
"X-Session-Id": session_id,
"X-Client-Signature": "your-signature"
},
files={"file": f},
data={"mode": "auto"}
)
# Save PSD
with open("output.psd", "wb") as f:
f.write(response.content)
📄 License
MIT License - see LICENSE file for details
🤝 Contributing
Contributions are welcome! Please:
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit changes (
git commit -m 'Add amazing feature') - Push to branch (
git push origin feature/amazing-feature) - Open a Pull Request
📞 Support
- Issues: GitHub Issues
- Discussions: GitHub Discussions
- Documentation: See
plan.mdfor detailed technical documentation
🎯 Roadmap
- Batch processing support
- Advanced layer ordering heuristics
- Real-time preview in browser
- Multi-user support with API keys
- Webhook notifications
- Custom model fine-tuning
Made with ❤️ for designers and developers
Metadata
Release files for psdfy 0.3.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| psdfy-0.3.2.tar.gz | 74.9 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| psdfy-0.3.2-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 151.3 kB
Release files / psdfy-0.3.2.tar.gz
| Download URL | psdfy-0.3.2.tar.gz |
|---|---|
| Size | 74.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
b13569bad99ab11bbf0f0071b5c14c686f796ef7c4ca9d6c53bf37fd176d0bd5
|
|
BLAKE2b-256 checksum How to use checksums |
d945cbb8c8ecf3f8012ebf2dd87b60404ea55dbc75d9d502904eddfd8de37f0c
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.13.2
|
Release files / psdfy-0.3.2-py3-none-any.whl
| Download URL | psdfy-0.3.2-py3-none-any.whl |
|---|---|
| Size | 76.4 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
4d48a0bad871ac81525fa4ba6fcda07760219628bf2e8e69471c0d694e46fa3e
|
|
BLAKE2b-256 checksum How to use checksums |
7ab87d9eba964f6557df2d7e835a21a9e0db5039f207f75394a16250db463d4b
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.13.2
|