pictures-valentina

Automated pipeline for generating a 16-year school portrait poster from an Apple Photos library.

https://github.com/davidbmar/pictures-valentina  ·  private  ·  shipped

What it is

A Python-based automation tool that scans an Apple Photos library for yearly portraits of a specific subject, allows manual selection via a local web interface, and composites the chosen images into a print-ready 18x24 inch poster. It handles face detection, consistent cropping, background replacement with a studio-blue gradient, and final layout generation.

Features

Quickstart

pip install pillow rembg opencv-python-headless numpy osxphotos
python src/find_candidates.py
python src/pick_server.py
# Open http://127.0.0.1:8770 in browser, select photos, and click Generate Board

Architecture

flowchart TD
    A[Apple Photos Library] -->|osxphotos| B(find_candidates.py)
    B -->|manifest.json| C(pick_server.py)
    C -->|selections.json| D(build_poster.py)
    E[models/face_detection_yunet.onnx] -->|OpenCV| F(face_crop.py)
    G[rembg u2net_human_seg] -->|PIL/Numpy| H(bg_replace.py)
    F --> D
    H --> D
    D --> I[output/poster.png]
    D --> J[output/poster.pdf]

How it's built

The system is built as a multi-stage pipeline: 1) `find_candidates.py` uses `osxphotos` to query the local Apple Photos database and ranks images by face size and quality. 2) `pick_server.py` serves a lightweight HTTP interface for manual year-by-year selection. 3) `build_poster.py` orchestrates the final composition, using `face_crop.py` (OpenCV YuNet) for consistent framing and `bg_replace.py` (rembg) for background removal on selected images before laying them out on a grid with PIL.

How it runs

sequenceDiagram
    participant User
    participant Finder as find_candidates.py
    participant Picker as pick_server.py
    participant Builder as build_poster.py
    participant FaceCrop as face_crop.py
    participant BGReplace as bg_replace.py
    
    User->>Finder: Run candidate search
    Finder->>Finder: Query Apple Photos DB
    Finder->>Finder: Rank & export thumbnails
    Finder-->>User: manifest.json created
    
    User->>Picker: Start web server
    Picker->>User: Serve candidate grid
    User->>Picker: Select photos per year
    Picker->>Picker: Save selections.json
    User->>Picker: Click Generate Board
    
    Picker->>Builder: Trigger build_poster.py
    Builder->>Builder: Load selections & manifest
    loop For each selected photo
        Builder->>FaceCrop: Detect face & crop
        FaceCrop-->>Builder: Cropped image
        Builder->>BGReplace: Remove background
        BGReplace-->>Builder: Subject on blue gradient
    end
    Builder->>Builder: Composite grid & add text
    Builder-->>User: Save poster.png/pdf

How to apply & reuse

This project is highly specific to macOS users with an Apple Photos library containing tagged faces. It can be adapted for other subjects by changing the `PERSON` constant in `find_candidates.py` or for different layouts by modifying `slots.py`. The background replacement and face cropping modules are reusable components for any batch photo processing task requiring consistent headshots.

At a glance

CapabilitiesBatch photo rankingFace detectionBackground removalImage compositingWeb-based UIPDF generation
Componentsfind_candidates.pypick_server.pybuild_poster.pyface_crop.pybg_replace.pyslots.py
TechPythonPillowOpenCVrembgosxphotosNumPy
Depends onmacOSApple Photos LibraryPython 3.8+
Integrates withApple PhotosiCloud Photos (optional hires download)
PatternsPipeline ProcessingHuman-in-the-loop SelectionLazy Model LoadingStatic Site Generation (local)
Reuse tagsphoto-automationface-croppingbackground-replacementapple-photosposter-generation

Repo hygiene

✓ all on main — nothing unmerged.