Automated pipeline for generating a 16-year school portrait poster from an Apple Photos library.
https://github.com/davidbmar/pictures-valentina · private · shipped
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.
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
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]
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.
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
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.
✓ all on main — nothing unmerged.