PlumbKing 👑 — Classical CV Image Leveling & Thumbnails
PlumbKing is a lightweight, classical-CV horizon leveling and thumbnail generator. It processes photo batches using a purely deterministic pipeline:
- Multi-scale K-Means segmentation
- Canny edge extraction
- Probabilistic Hough transform
- Weighted roll voting
- Optional RANSAC horizon correction
No ML models, no cloud calls — just fast, transparent image geometry.
✨ Features
- 📐 Automatic roll leveling (multi-scale classical CV)
- 🔍 Preview mode with confirmation before replacing originals
- 🧭 EXIF-aware rotation correction
- 🖼️ Structured thumbnail generation
- 🛠️ Debug output for each stage (
--debug-dir) - 🐧 Works on Linux, macOS, WSL
🚀 Installation
pip install plumbking
📦 Basic Usage
Level and thumbnail all images in a directory:
plumbking --directory /path/to/images
Dry-run (no writes):
plumbking --directory /path/to/images --dry-run
Enable full CV debug logging:
plumbking --directory /photos --debug-dir /tmp/pk-debug
This creates per-image folders containing:
- segmentation maps
- Canny edge maps
- Hough overlays
- RANSAC boundary maps
- intermediate resized crops
🔧 Workflow Summary
-
Scan the directory
-
Detect leveling candidates
-
Generate preview leveled images under
_leveled_preview/ -
Prompt for approval
- Yes → originals replaced by leveled versions
- No → preview removed, originals kept
-
Generate missing thumbnails
⚙️ Environment Variables
| Variable | Default | Meaning |
|---|---|---|
THUMB_MAX_SIZE |
720 |
Max width/height of thumbnails |
LEVELED_PREVIEW_DIR |
_leveled_preview |
Directory used for preview leveling |
LEVEL_ANALYSIS_SIZE |
720 |
Downscale used during leveling analysis |
LEVEL_DEBUG_DIR |
(unset) | Optional global debug directory (overridden by --debug-dir) |
📝 Notes
- Works best for horizon-bearing photos, architecture, landscapes
- Deterministic classical CV — great for reproducible pipelines
- Safe to rerun; naming conventions prevent double-processing
- Designed for large photo collections and batch workflows
One hand for the ship, one hand for the soul. Built aboard Moonshot.
:=.:***. . .* ==: .*. .... ...
.=. : = .+ =-: .*. .. .
.=. - .= :. ==:.... .*.
.+: .. * .:.= -=:. .*.
.*+:+: + --:=+:=***-.:+-: .*................ . .. . ...
++=+:..+.==*+*+-#*++**=****. .*.
-::..:-=++*********+*%%##%##:#**+ *:
::.......:.::.. .:-=+%@*. .+ =-:. .*- ..
-**=#*#*:::.... . . -.:+-+-:*****+*++=:=-
. .===##-::......... . .+ ......
.. .:+-. =-:..... :+#+ ......:-=+****#
.. .. . -:%:+..-+*****=*+##*=#%# ##%@@@@@@*@@@%%%#@@@@@@@%@@@
....:...... . . :. . .. . . .: ###*#*+**+-#: :-%% ::.- .=*: .*#= ..:=*
++**+++++*+**##**##@%%%##*. +%%%%%%%%%%%%%% :+#*=-+= =+-:++ :%*-=: - ==#.+:+=*#-=+:=**%@%@%#**%
==*+*##*+*+*+++++**#%%%#-+: =##%%%%%%%@%%**:++-==:-... ..... :+ -%##**:*#*#=:*#+++++++*%%
##+%%%@#@@*@@@@. @@%#+@=%*+@%-##%@%-=*@@#+*%--++*# *##***= +%* #%%%@%-@@%%+*+%+*+=+#+%@%
%%#@@%@%*@*@@@@+-%@%#*@%* @%-%%#@%%:+@@%*#%##### +*#####+ %* #%@@@#:@@@%##*#.:-:::..-%
#*+#@@@@:@-@@@@@ #@%#-@%+ @@+*- @@%+*@@%-#- - =- *%%%#:%%+=***-*******##%
%+-@@%@@+@+%@%@@#+@.#+@@* =@*#..@@+=*@%@##@%@%%%%%#%%%#*##*##**+*++ - -+*#%#=%%--.+-*+++***++=+
. +@@@@%@@#%%@@@=%..=@@+. .@++#=@@***@@@#*%%%%**#%%%%%###%#####+*+= . **#**-*#.+==**********=*
. .@@@@@@@@%%@@@+@-.+@@#*::@*##:+-%%%@@@+#%%##*%%%%%%*=#*+-:+#*=-. -*#++*.####*-############
. %@@@@@@@@%@@#-@*-%@@#+:.@+-+-=#***+. * ...... .=*=############
+:.-%@@@@+@#@*@@+:%*-%@@++.-@*-#-=@ =**+++++++++. -. = .#*############
-...+@@@@+@##:@@#.#%-%*@=#: @+:-. =*****+=--. - #=......... =++***********
:. :@@@@@@##-@@+:#%+#+@=%**@. ==.... .-:::::::----=
*: .@@@@@@@#+%@#:*%++%%+:+* .=-++ :*............ ..::..........
#= @@@@@@@#+#@@%%#-:%%%= . . .: ... .... .:::::::::..:
@= #%%@@@@@%%@@%*=+: - **=. . ::............ .-------:::::
%+=. *%%%%%%%%%%%%%@%## .--. .. +*-..................===----::--
%**: *%%%%%%%%#%%%%%= # : :-: -==##...... ............=====------
%#+--+%%%%%%%%#%%%%@%% =. -: .-==--: -=+-:*................. ..:=====-----
@%=.-*%%%%%%%%%%%@@@@* . ..-=====---:. .**+=- ....................=----::::-
%%***#%%%%%%%%%@@@@# :: **++==-=====- +%##+. - ............... .--::-:::::
%%###*%%%%%%%@@@@@* =*%%@@#+++=-. .=#%%#- : = .................... . :.
%%###*#%%%%%@@@@@@@##** .:@@%@@@@+. .:.:*%%#. .++= ................... .. :...
####**#%%%%%@@@@@@@@@%%@@@@@%@@@@@@- -*#*- -+-. .................... ... ..=.
####**#%%@@@@@@@@@@@@%@@@@@##@@@@@%%#*- -+= : +. : ....................: -=- .:++
####*##%%%%@@@@@@@@@@@@@@%%%%%%%%+. =****: . =-= -: ..................... ... .=++
##%##*##%%@@@@@@@%%%%%%%%%%%#: =*#*#. -+: .= .*%##**:............ . :... ...
Metadata
Release files for plumbking 0.1.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| plumbking-0.1.1.tar.gz | 37.6 kB | Without provenance | Details for plumbking-0.1.1.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| plumbking-0.1.1-py3-none-any.whl | Python 3 | none | any | Details for plumbking-0.1.1-py3-none-any.whl |
Total release size: 71.6 kB
Release files / plumbking-0.1.1.tar.gz
| Download URL | plumbking-0.1.1.tar.gz |
|---|---|
| Size | 37.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
085cebb5551eab4937bdc650b213c091a50bbfddbefeeff7102ee7c9ca88fb89
|
|
BLAKE2b-256 checksum How to use checksums |
2682f0ecaede154421c8bbde4e8d9d7a290ecb659dc8a1787d066063bf6e2f6c
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.14.1
|
Release files / plumbking-0.1.1-py3-none-any.whl
| Download URL | plumbking-0.1.1-py3-none-any.whl |
|---|---|
| Size | 33.9 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
35a22dd378fbfde57478776ef76bb0e11715a82133cdc3dcf337016777ca2313
|
|
BLAKE2b-256 checksum How to use checksums |
fa5fd257aee95564a121ac0fb1137b13173b4b9163699695a69ee5bfbe6e6e52
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.14.1
|
Security for plumbking 0.1.1
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.