Image curation tool
Project description
qrate
Image curator. Index, analyze, score, and export your best shots.
Install
pip install -e ".[cv]"
Quick Start
# Index a directory (extracts previews, computes quality scores)
qrate index /path/to/photos
# See what you've got
qrate status /path/to/photos
# Score images for exhibition quality
qrate score /path/to/photos --top 20 --verbose
# Detect bursts and select best shots
qrate cull /path/to/photos
# Export top images as gallery (JPGs + scores)
qrate export /path/to/photos --out picks --format gallery --top 10
Commands
qrate index <directory>
Index RAW files: extract EXIF, generate previews, compute quality metrics.
qrate index /Volumes/NIKON/DCIM
Creates:
.qrate.db— SQLite database with metadata and scores.qrate_previews/— JPEG previews (auto-rotated via EXIF)
qrate status <directory>
Show index statistics.
qrate status /Volumes/NIKON/DCIM
qrate score <directory>
Rank images by exhibition-worthiness using multi-pass scoring.
# Top 10 with scores
qrate score /path/to/photos
# Top 50 with detailed breakdown
qrate score /path/to/photos --top 50 --verbose
Scoring passes:
| Category | Metrics |
|---|---|
| Technical | sharpness, subject_sharpness, exposure, noise, dynamic_range |
| Composition | thirds, balance, simplicity, obstruction, subject_clarity |
| Color | harmony, saturation_balance, contrast |
| Collection | uniqueness |
qrate cull <directory>
Detect burst sequences and mark best-of-burst.
qrate cull /path/to/photos --burst-threshold 2.0
qrate export <directory>
Export selected images in various formats.
# Export paths to text file
qrate export /path/to/photos --out picks.txt --top 100
# Copy files to directory
qrate export /path/to/photos --out /dest/folder --format copy --top 50
# Generate XMP sidecars (for Lightroom/Capture One)
qrate export /path/to/photos --out . --format xmp --top 100 --rating 5 --label red
# Create gallery with JPGs and scores (great for sharing/review)
qrate export /path/to/photos --out best/ --format gallery --top 20
Options:
--format list|copy|xmp|gallery— output format--top N— export top N images--min-sharpness N— filter by sharpness--include-dupes— include duplicates--all-burst— include all burst members (not just best)
qrate select <input_dir> (legacy)
Simple selection by modification time.
qrate select /Volumes/NIKON/DCIM --out export.txt --n 100 --ext .NEF
Workflow Example
# 1. Index your card
qrate index /Volumes/NIKON/DCIM
# 2. See the scores
qrate score /Volumes/NIKON/DCIM --top 20 -v
# 3. Detect and cull bursts
qrate cull /Volumes/NIKON/DCIM
# 4. Export best shots with Lightroom ratings
qrate export /Volumes/NIKON/DCIM --out . --format xmp --top 50 --rating 5
# 5. Or just get a list to copy
qrate export /Volumes/NIKON/DCIM --out keepers.txt --top 100
cat keepers.txt | xargs -I {} cp {} /destination/
Output Formats
Text list (--format list)
/path/to/DSC_0001.NEF
/path/to/DSC_0002.NEF
XMP sidecar (--format xmp)
Creates DSC_0001.xmp next to each selected RAW with star rating and color label.
Gallery (--format gallery)
Creates a shareable folder with RAW files, JPG previews, and detailed scores:
best/
├── raw/
│ ├── 001_DSC_0001.NEF
│ ├── 002_DSC_0002.NEF
│ └── ...
├── jpg/
│ ├── 001_DSC_0001.jpg
│ ├── 002_DSC_0002.jpg
│ └── ...
└── scores.txt
scores.txt contains rankings with score breakdowns:
Rank Score File
------------------------------------------------------------
1 71.7 _DSC0720.NEF
Technical: sharp=1859 subj=1.00 exp=0.75
Composition: thirds=0.62 obstruct=1.00 clarity=1.00
Color: harmony=0.50 sat=1.00 contrast=0.77
Supported RAW Formats
NEF, CR2, CR3, ARW, DNG, RAF, ORF, RW2, PEF
Dependencies
rawpy— RAW file processingPillow— image handlingimagehash— perceptual hashingnumpy,scipy— numerical analysisopencv-python-headless(optional) — advanced CV features
Development
Install development dependencies:
pip install -e ".[dev]"
Run checks before committing:
# Run all checks manually (lint, format, type, test)
./scripts/check.sh
# Or install pre-commit hook (runs automatically on commit)
cp scripts/pre-commit.template .git/hooks/pre-commit
chmod +x .git/hooks/pre-commit
The pre-commit hook runs:
ruff check— lintingruff format --check— format checkmypy— type checkingpytest --cov— tests with 80% coverage requirement
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file qrate-0.1.1.tar.gz.
File metadata
- Download URL: qrate-0.1.1.tar.gz
- Upload date:
- Size: 41.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
67aed681387a2260323c5fceadb23863b5885726b56afd531cf5ff6dec7587a5
|
|
| MD5 |
48c02ff0fa8f9cd1d337c1a32a3a3d69
|
|
| BLAKE2b-256 |
0bd96d0265a8edb74c22fc37a9d543c2f7f9f29a735610450a16d3599653f38d
|
Provenance
The following attestation bundles were made for qrate-0.1.1.tar.gz:
Publisher:
publish.yml on swap357/qrate
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
qrate-0.1.1.tar.gz -
Subject digest:
67aed681387a2260323c5fceadb23863b5885726b56afd531cf5ff6dec7587a5 - Sigstore transparency entry: 776276375
- Sigstore integration time:
-
Permalink:
swap357/qrate@bb434293e5cdbe4dce92359b8b9765723083ea92 -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/swap357
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@bb434293e5cdbe4dce92359b8b9765723083ea92 -
Trigger Event:
release
-
Statement type:
File details
Details for the file qrate-0.1.1-py3-none-any.whl.
File metadata
- Download URL: qrate-0.1.1-py3-none-any.whl
- Upload date:
- Size: 31.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1b2fbd56e940f4b4a1f562806c82dfef68c2a15b6c53d46c6eb3ac3c0598b33e
|
|
| MD5 |
f693556f62b95d01b1b92f5257cb0386
|
|
| BLAKE2b-256 |
dbd98cf01f8aa9c054c4396f8a3fe78f82a4b29c178570ad4067af4e71444fa0
|
Provenance
The following attestation bundles were made for qrate-0.1.1-py3-none-any.whl:
Publisher:
publish.yml on swap357/qrate
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
qrate-0.1.1-py3-none-any.whl -
Subject digest:
1b2fbd56e940f4b4a1f562806c82dfef68c2a15b6c53d46c6eb3ac3c0598b33e - Sigstore transparency entry: 776276377
- Sigstore integration time:
-
Permalink:
swap357/qrate@bb434293e5cdbe4dce92359b8b9765723083ea92 -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/swap357
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@bb434293e5cdbe4dce92359b8b9765723083ea92 -
Trigger Event:
release
-
Statement type: