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.
:=.:***. . .* ==: .*. .... ...
.=. : = .+ =-: .*. .. .
.=. - .= :. ==:.... .*.
.+: .. * .:.= -=:. .*.
.*+:+: + --:=+:=***-.:+-: .*................ . .. . ...
++=+:..+.==*+*+-#*++**=****. .*.
-::..:-=++*********+*%%##%##:#**+ *:
::.......:.::.. .:-=+%@*. .+ =-:. .*- ..
-**=#*#*:::.... . . -.:+-+-:*****+*++=:=-
. .===##-::......... . .+ ......
.. .:+-. =-:..... :+#+ ......:-=+****#
.. .. . -:%:+..-+*****=*+##*=#%# ##%@@@@@@*@@@%%%#@@@@@@@%@@@
....:...... . . :. . .. . . .: ###*#*+**+-#: :-%% ::.- .=*: .*#= ..:=*
++**+++++*+**##**##@%%%##*. +%%%%%%%%%%%%%% :+#*=-+= =+-:++ :%*-=: - ==#.+:+=*#-=+:=**%@%@%#**%
==*+*##*+*+*+++++**#%%%#-+: =##%%%%%%%@%%**:++-==:-... ..... :+ -%##**:*#*#=:*#+++++++*%%
##+%%%@#@@*@@@@. @@%#+@=%*+@%-##%@%-=*@@#+*%--++*# *##***= +%* #%%%@%-@@%%+*+%+*+=+#+%@%
%%#@@%@%*@*@@@@+-%@%#*@%* @%-%%#@%%:+@@%*#%##### +*#####+ %* #%@@@#:@@@%##*#.:-:::..-%
#*+#@@@@:@-@@@@@ #@%#-@%+ @@+*- @@%+*@@%-#- - =- *%%%#:%%+=***-*******##%
%+-@@%@@+@+%@%@@#+@.#+@@* =@*#..@@+=*@%@##@%@%%%%%#%%%#*##*##**+*++ - -+*#%#=%%--.+-*+++***++=+
. +@@@@%@@#%%@@@=%..=@@+. .@++#=@@***@@@#*%%%%**#%%%%%###%#####+*+= . **#**-*#.+==**********=*
. .@@@@@@@@%%@@@+@-.+@@#*::@*##:+-%%%@@@+#%%##*%%%%%%*=#*+-:+#*=-. -*#++*.####*-############
. %@@@@@@@@%@@#-@*-%@@#+:.@+-+-=#***+. * ...... .=*=############
+:.-%@@@@+@#@*@@+:%*-%@@++.-@*-#-=@ =**+++++++++. -. = .#*############
-...+@@@@+@##:@@#.#%-%*@=#: @+:-. =*****+=--. - #=......... =++***********
:. :@@@@@@##-@@+:#%+#+@=%**@. ==.... .-:::::::----=
*: .@@@@@@@#+%@#:*%++%%+:+* .=-++ :*............ ..::..........
#= @@@@@@@#+#@@%%#-:%%%= . . .: ... .... .:::::::::..:
@= #%%@@@@@%%@@%*=+: - **=. . ::............ .-------:::::
%+=. *%%%%%%%%%%%%%@%## .--. .. +*-..................===----::--
%**: *%%%%%%%%#%%%%%= # : :-: -==##...... ............=====------
%#+--+%%%%%%%%#%%%%@%% =. -: .-==--: -=+-:*................. ..:=====-----
@%=.-*%%%%%%%%%%%@@@@* . ..-=====---:. .**+=- ....................=----::::-
%%***#%%%%%%%%%@@@@# :: **++==-=====- +%##+. - ............... .--::-:::::
%%###*%%%%%%%@@@@@* =*%%@@#+++=-. .=#%%#- : = .................... . :.
%%###*#%%%%%@@@@@@@##** .:@@%@@@@+. .:.:*%%#. .++= ................... .. :...
####**#%%%%%@@@@@@@@@%%@@@@@%@@@@@@- -*#*- -+-. .................... ... ..=.
####**#%%@@@@@@@@@@@@%@@@@@##@@@@@%%#*- -+= : +. : ....................: -=- .:++
####*##%%%%@@@@@@@@@@@@@@%%%%%%%%+. =****: . =-= -: ..................... ... .=++
##%##*##%%@@@@@@@%%%%%%%%%%%#: =*#*#. -+: .= .*%##**:............ . :... ...
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 | |
|---|---|---|---|
| plumbking-0.1.1.tar.gz | 37.6 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| plumbking-0.1.1-py3-none-any.whl | Python 3 | none | any | Details |
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
|