Instagram image selection pipeline package.
python3 -m venv .venv
source .venv/bin/activate
make install-dev
python -m pip install -e ".[clip,claude,yolo]"
pickinsta ./input --output ./selected --top 10 --scorer clipProject docs are in /Users/renatobo/development/pickinsta/docs:
docs/README.md(documentation index)docs/composition-rules.md(composition/scoring/cropping reference)docs/troubleshooting.md(setup and runtime troubleshooting)
Detailed flow:
flowchart TD
A["Input folder (raw event photos)"] --> B["Stage 0: Resize<br/>Longest edge <= 1920px, EXIF-safe"]
B --> C["Stage 1: Deduplicate<br/>Perceptual hash grouping"]
C --> D["Stage 2: Technical scoring<br/>Sharpness, lighting, composition, color, clutter"]
D --> E["Select vision candidates<br/>Top N or --vision-pct or --all"]
E --> F{"Stage 3 scorer"}
F -->|clip| G["CLIP scoring (local)"]
F -->|claude| H["Resolve ANTHROPIC_API_KEY + model"]
H --> I["Check per-image cache<br/>*.pickinsta.json"]
I --> J{"Cache hit?"}
J -->|yes| K["Use cached Claude score"]
J -->|no| L["Claude vision scoring<br/>Optional YOLO context for subject info"]
L --> M["Save cache entry"]
G --> N["Final score<br/>0.3 * technical + 0.7 * vision"]
K --> N
M --> N
N --> O["Stage 4: Smart crop<br/>YOLO-guided crop to 1080x1440<br/>Fallback: saliency/center"]
O --> P["Output top N images + reports<br/>selection_report.json and selection_report.md<br/>Optional *_full_* fallback only for uncertain crops"]
cd /path/to/pickinsta
python3 -m venv .venv
source .venv/bin/activate
python -m pip install --upgrade pip setuptools
python -m pip install -e ".[clip,claude,yolo]"
python -c "import transformers, torch, anthropic, ultralytics; print(transformers.__version__, torch.__version__, anthropic.__version__, ultralytics.__version__)"If you only need one scorer:
# CLIP only
python -m pip install -e ".[clip]"
# Claude only
python -m pip install -e ".[claude]"
# YOLO support (smart crop + Claude context enrichment)
python -m pip install -e ".[yolo]"If ultralytics is not installed, YOLO is disabled and smart crop falls back to saliency/center heuristics.
pip install Pillow opencv-python numpy imagehash
pip install transformers torch
pip install anthropic tqdm
pip install ultralyticsCreate a .env file with your key:
cp .env.example .env
# then edit .env and set your real keyRequired content:
ANTHROPIC_API_KEY=your_key_hereOptional content:
HF_TOKEN=hf_xxx_your_token
# optional Claude model override:
ANTHROPIC_MODEL=claude-sonnet-4-6
# optional account context used in Claude prompt:
PICKINSTA_ACCOUNT_CONTEXT="motorcycle enthusiast account"When --scorer claude is used, pickinsta checks:
ANTHROPIC_API_KEYfrom the current environment.envin the current working directory.envin the input photos folder
When --scorer clip is used, HF_TOKEN is optional. If present, pickinsta
loads it from environment or .env (same search order) to reduce HF warnings
and improve download/rate limits. If missing, CLIP still runs.
YOLO model weights are downloaded at runtime on first YOLO use to:
~/.cache/pickinsta/models/yolov8n.pt
Override model path with:
PICKINSTA_YOLO_MODEL=/absolute/path/to/model.pt
From the project folder (with venv active):
mkdir -p ./input ./selected
pickinsta ./input --output ./selected --top 10 --scorer clipOr as a module:
python -m pickinsta ./input --output ./selected --top 10 --scorer claudeShow full CLI options:
pickinsta -hTo score all Stage 2 images (CLIP or Claude), use --all instead of the --vision-pct cutoff:
pickinsta ./input --output ./selected --scorer claude --all
# or
pickinsta ./input --output ./selected --scorer clip --allFor Claude, you can score on pre-cropped 4:5 candidates to better align ranking with final portrait output quality:
pickinsta ./input --output ./selected --scorer claude --all --claude-crop-firstReports are written to ./selected:
selection_report.json(top selected outputs)selection_report.md(top outputs + full vision/Claude scores for all analyzed images)
Output files:
NN_<image-stem>.jpg(always, ranked crop output)NN_full_<image-stem>.jpg(optional, only when crop uncertainty is detected: subject too large/clipped/too close to borders)
Claude caching:
- Claude responses are cached per original input image file.
- Cache file format:
<original_filename>.pickinsta.jsonin the same input folder. Example:IMG_1234.jpg.pickinsta.json - Cache validity includes image content hash + Claude model + prompt hash.
Run the full automated test suite:
make testRun a specific test file:
.venv/bin/pytest -q tests/test_scoring_and_reports.pyLint code:
make lintRun both lint + tests:
make checkSee detailed test coverage notes in tests/README.md.
See CONTRIBUTING.md for development workflow, PR expectations, and project layout.