Skip to content
ncoevoetPublic

About

Local AI photo scoring, culling, and gallery — score, organise, and explore your library with face recognition and semantic search. No cloud, no subscriptions.

Topics

Resources

Contributing

Stars

374 stars

Watchers

3 watching

Forks

Latest commit

 

History

3,317 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Facet

🌐 English · Français · Deutsch · Italiano · Español · Português · 简体中文

Facet is a local photo-analysis and culling engine. It scores each image across 9 dimensions — from aesthetic quality to face sharpness — then lets you browse, cull, and organize through a web gallery. Everything runs on your machine; no cloud, accounts, or API keys.

Python Angular FastAPI Platform License

Facet in action — gallery, per-photo scoring, culling, capsules, timeline, map, and stats

How It Works

  1. Scan — Point Facet at a folder of photos. Each image is analyzed for quality, composition, and faces. Supports JPEG, HEIF/HEIC, 10 RAW formats, JPEG XL, AVIF, PNG, WebP, TIFF and more — see supported file types.
  2. Browse — Open the web gallery to explore your library with filters, search, and multiple view modes.
  3. Cull — Facet detects bursts, flags blinks, groups similar photos, and surfaces top picks. Exposure brackets and panorama/HDR sets are recognized and kept whole rather than culled apart.

GPU is auto-detected and optional. Facet runs CPU-only or with up to 24 GB VRAM.

Features

Score

Each photo is scored across 9 dimensions: aesthetic quality, composition, face quality, eye sharpness, technical sharpness, color, exposure, subject saliency, and dynamic range. Photos are categorized by content (portrait, landscape, macro, street, etc. — 30+ categories) and scored with category-specific weights. A Top Picks filter ranks the library by a combined score.

Hover over any photo to see its score breakdown and EXIF data in the gallery's side panel, or switch to a hover bubble that gives a glance at the key scores.

Hover tooltip with score breakdown

Cull

  • Burst detection — groups rapid-fire shots and auto-selects the best one based on sharpness, quality, and blink detection
  • Sequence protection — exposure brackets, panoramas and HDR panoramas (--detect-sequences / --detect-panoramas) are recognized as sets; the culling darkroom starts every frame of a set as kept
  • Similarity groups — finds visually similar photos across the library, regardless of when they were taken
  • Scenes — groups a shoot into chronological "scenes" by capture-time gaps, so you cull in story order; tap to mark and confirm to reject
  • Auto-cull — one button culls a whole scope (all groups, or bursts / similars / scenes only, optionally narrowed to an album or date window) with a dry-run preview, a keeper budget, and an optional Highlights album
  • Auto-cull from the terminal — python facet.py --auto-cull [PATH] previews the cull as a dry run, --apply writes it and --copy-keepers DIR copies the survivors (see docs/COMMANDS.md)
  • Genre profiles — sports / wedding / concert / wildlife presets bundle strictness, keeper budget, similarity threshold and face gates in a single pick
  • Edited-look preview [Edition] — render a photo through a named darktable style inside the culling darkroom, so you cull on the developed look instead of the flat RAW preview
  • Subject close-ups — no-face groups (wildlife, macro, product) compare by an auto-cropped subject strip with group-normalized sharpness badges
  • Junk sweep — zero-shot detection of non-photo clutter (screenshots, documents, receipts, memes, slides) with a fast review queue: keep or reject each candidate, or reject all at once
  • Per-face culling badges — the culling lightbox shows per-face eyes open/closed, expression, and detection-confidence badges, not just a single photo-level blink flag; optional MediaPipe blendshapes sharpen the eyes/smile reads
  • Blink detection — flags closed-eye shots to hide or reject in one click
  • Duplicate detection — identifies near-identical images via perceptual hashing
Burst culling Similarity groups for culling

Browse

  • Gallery modes — mosaic (justified rows preserving aspect ratios) and grid (uniform cards with metadata overlay)
  • Filters — date range, content tag, composition pattern, camera, lens, person, folder, quality level, star rating, and custom metric ranges
  • Semantic search — type a natural-language query like "sunset on the beach" and find matching photos via embedding and text search
  • Timeline — chronological browser with year/month navigation and infinite scroll
  • Map — geotagged photos on an interactive map with marker clustering
  • Capsules — themed slideshows: journeys with place names, golden collection, seasonal palettes, photos of a person, and more
  • Folders — browse by directory structure with breadcrumb navigation and cover photos
  • Narrative moments — zero-shot scene/activity labels (beach, celebration, concert, …) name your scenes, filter and sort the gallery, and feed capsule selection
  • Memories — "On This Day": photos from the same date in previous years
  • Slideshow — full-screen mode with themed transitions, auto-chaining between capsules, and keyboard controls
Filter sidebar Semantic search results
Full filter sidebar — every section expanded (click to view)

The gallery filter sidebar, with its filters grouped under tabs

Workflow tips:

  • /timeline drills down years → months → days; click a day to open the gallery on that date.
  • /capsules builds themed slideshows (journeys, "Faces of", seasonal, golden) you can save as albums — the better choice for picking a trip's best shots.
  • The gallery hides blinks, non-lead bursts, and duplicates by default. When the "N photos hidden by current filters" banner appears, click "Show all" to expand the view.

Organize

  • Face recognition — automatic face detection, grouping into persons, and blink detection. Search, rename, merge, and organize person clusters from the management UI. Merge suggestions find similar-looking clusters that may be the same person.
  • Albums — manual collections with drag-and-drop, or smart albums that auto-populate from saved filter combinations
  • Ratings & favorites — star ratings (1–5), favorites, and reject flags. Cycle through ratings with a single click.
  • Tags — AI-generated content tags with configurable vocabulary. Click any tag to filter the gallery.
  • Batch operations — multi-select with Shift+click, Ctrl+click, or Ctrl+A (select all). Set ratings, toggle favorites, mark rejects, or add to albums in bulk — with a 7-second undo for every batch action.
  • Keyboard-first — arrow keys navigate the gallery, Enter opens, Space selects; press ? anywhere for the shortcut reference.

Albums — manual and smart collections

Manage Persons page Person gallery

Understand

  • Statistics — dashboards for equipment usage, category breakdown, shooting timeline, and metric correlations
  • AI critique — score breakdown showing each metric's contribution; VLM natural-language assessment [GPU] [12gb/16gb/24gb]
  • Weight tuning — per-category weight editor with live score preview. A/B photo comparison learns from your choices and suggests optimized weights.
  • Scoring contexts — choose which category a photo is scored as: reorder category priority, apply a named context (Action/Stage, Portrait Session, Wildlife, …) per album, or pin a category on one photo.
  • My Taste sort — sort the gallery by the personal ranker's learned score, with a confidence badge showing learned coverage and held-out accuracy
  • Learning from labels — culling decisions, star ratings, favorites, and rejections feed the weight optimizer (--sync-label-comparisons, --mine-insights)
  • Snapshots — save, restore, and compare weight configurations
  • Histogram — RGB/luminance histogram with clipping indicators, in the gallery side panel and detail view
  • AI captions [GPU] [12gb/16gb/24gb] — text descriptions, editable [Edition] and translatable to 5 languages (viewing is open; generation and editing need edition)
Equipment statistics Category analytics
Shooting timeline Metric correlations
AI Critique dialog Snapshots
Category weight sliders A/B photo comparison

Share

  • Album sharing — generate shareable links for any album, no login required for recipients. Revoke access at any time.
  • Client proofing — a shared album can run in proofing mode: clients heart photos and leave comments with just the link (plus an optional PIN), fully isolated from your own ratings
  • Phone auto-upload — point PhotoSync or any WebDAV app at the built-in /dav inbox; --watch scores new shots as they arrive
  • Photo frames & kiosks — a token-guarded endpoint feeds your curated best shots to smart photo frames and Home Assistant dashboards
  • AI agents (MCP) — a Model Context Protocol endpoint (on by default, viewer.mcp.enabled) lets assistants search the library with revocable personal tokens. Higher token levels can rate, tag, organise and cull; destructive actions preview first and need confirmation
  • Portfolio export [Edition] — render an album into a self-contained static HTML gallery (no CDN references, works offline) you can drop on any web host
  • Social crops [Edition] — full-resolution exports framed on the detected subject for square, portrait and story aspect presets
  • Photo download — download individual photos or selections from the gallery
  • Export — export all scores to CSV or JSON for external analysis

More

  • Dark & light mode with 10 accent color themes; respects system preference
  • Responsive — adapts from mobile to desktop, with a touch-friendly bulk-actions sheet on small screens
  • Installable PWA — web app manifest + service worker: install to home screen, offline app shell
  • Virtualized gallery — renders a handful of DOM nodes regardless of library size, so scrolling stays fast at 100k+ photos
  • Resumable scans — interrupted scans resume (--resume), failed files are tracked and retryable (--retry-failed), progress streams to the web UI
  • 7 UI languages — the viewer ships in English, French, German, Spanish, Italian, Brazilian Portuguese, and Simplified Chinese (简体中文); documentation is available in all seven
  • Multi-user — per-user directories, ratings, and role-based access
  • Plugins & webhooks — custom actions triggered on scoring events
  • Scan from web UI — trigger scans from the browser (superadmin in multi-user mode; edition access on a single-user install with an edition password)
Mobile gallery Tablet gallery Desktop mosaic

What you need

  • Any machine (CPU) runs most of Facet: scoring, faces, culling, the gallery, search, albums and metadata export.
  • Apple Silicon uses the Metal (mps) backend automatically. The auto profile follows unified memory: 32 GB reaches 16gb, 48 GB reaches 24gb.
  • An NVIDIA GPU on the 12gb/16gb/24gb profiles unlocks the strongest models: TOPIQ, SigLIP 2, VLM tagging, AI captions and critique, subject saliency.
  • No GPU? Point VLM tagging, captions and critique at a remote Ollama or OpenAI-compatible server with vlm_backend in scoring_config.json.
  • Editing in the viewer (ratings, faces, culling) needs the edition password. The Scan button needs viewer.features.show_scan_button: true and edition access (the superadmin role in multi-user mode).

→ Full per-feature requirements (GPU, VRAM profile, optional packages, auth): Installation › Feature requirements.

Is Facet for you?

Facet scores, ranks, and culls a local photo library and serves a gallery to browse it. It runs on your own hardware and keeps photos off the cloud.

A good fit if you:

  • have a large local library and want to find your best shots and cull bursts and near-duplicates;
  • want quality, composition, and face scoring you can tune to your own taste (it learns from your A/B comparisons);
  • prefer self-hosted and private — no cloud upload, no account, no subscription;
  • already edit in Lightroom, darktable, digiKam or Immich — Facet writes ratings, labels, keywords, captions and face regions to .xmp sidecars (originals stay untouched unless you ask for embedding: the gallery's "Write metadata to file" action or --export-sidecars --embed-originals) and reads edits back with --import-sidecars. A facet.lrplugin Lightroom plug-in adds a two-way flow. See Interop.

Probably not for you if you want:

  • a turnkey, mobile, cloud-backed Google Photos replacement — though phone auto-upload into a watched inbox is built in over WebDAV (PhotoSync recipe in the docs);
  • RAW editing or develop — Facet scores and organizes, it does not edit;
  • a zero-setup desktop app — it needs Python, and the best models need a GPU.

How it relates to other tools

  • Self-hosted libraries (Immich, PhotoPrism) focus on organizing, search, and backup. Facet adds quality scoring, ranking, and a culling workflow they don't, but it has no mobile app or cloud backup (phone auto-upload over WebDAV is built in, and ratings can sync to Immich).
  • AI culling apps (Aftershoot, Narrative, FilterPixel) are polished commercial cullers, often with editing built in. Facet is free, local, broader (gallery, search, faces), and its scoring is tunable — but it is a single-developer project without their support or RAW editing.
  • Editors and catalogs (Lightroom, darktable, digiKam) develop and manage photos. Facet complements them through the XMP metadata interop above rather than replacing them.

The aesthetic score is model-based and approximate; expect to tune the weights to match your taste.

Quick Start

Docker (recommended)

git clone https://github.com/ncoevoet/facet.git && cd facet
cp .env.example .env      # open .env and set PHOTOS_DIR to your photo folder
docker compose up -d      # then open http://localhost:5000

Have an NVIDIA card? Use the block for its size in Installation — one line each for 8 GB, 16 GB and 24 GB cards.

Without Docker (Linux, macOS)

git clone https://github.com/ncoevoet/facet.git && cd facet
bash install.sh                        # detects your hardware, installs everything
source venv/bin/activate
python facet.py /path/to/your/photos   # score photos
python viewer.py                       # gallery → http://localhost:5000

macOS: ControlCenter's AirPlay Receiver binds port 5000 by default. If you see "Address already in use", run python viewer.py --port 5001.

Full guide: Installation — per-hardware setup, first-run downloads, and dependency troubleshooting. Run python facet.py --doctor to diagnose GPU issues.

First time here? Follow the Getting Started walkthrough: scan, review, teach, discard, tag and export.

Documentation

Document Description
Installation Requirements, GPU setup, VRAM profiles, dependencies
Getting Started First-run walkthrough: install to scan, review, teach, discard, tag and export
Commands All CLI commands reference
Configuration Full scoring_config.json reference
Scoring Categories, weights, tuning guide
Face Recognition Face workflow, clustering, person management
Viewer Web gallery features and usage
API Viewer HTTP API reference
Interop Round-tripping ratings/tags with Lightroom, Capture One, digiKam, darktable
Immich Syncing ratings and favorites with Immich, plus the inbound webhook
Relink Relink moved photos
AI Agents Letting an MCP-capable assistant search the library with a personal token
Deployment Production deployment (Synology NAS, Linux, Docker)
Contributing Development setup, architecture, code style

License

MIT

Licensing

Facet's own code is MIT. Some default models are non-commercial: pyiqa (TOPIQ, LIQE, …) and the InsightFace weights. Set licensing.mode: commercial to use only permissively licensed replacements (Licensing, Third-party models).

About

Local AI photo scoring, culling, and gallery — score, organise, and explore your library with face recognition and semantic search. No cloud, no subscriptions.

Topics

Resources

Contributing

Stars

374 stars

Watchers

3 watching

Forks

Releases

Packages

Used by

Contributors

Languages