PatchCraft
A small library for encoding an image into patches and decoding it back. Built to slot into other people's torch pipelines as one transform among many, like a GaussianBlur step in a Compose([...]).
Status: v0.2.1 on PyPI, installable with
pip install patchcraft. Public API (19 symbols):extract,Patchify,reconstruct,stitch(+ itsWeightKind),pair,resize,Cache, plus geometry helpers (num_patches,tilings,TilingSpec,scale_factor,paired_tilings,PairedTilingSpec), pixel metrics (patch_metrics,per_patch_mse,per_patch_psnr), andPatchPair/PatchMeta.
The lib vs. this repo
Think of the lib as a car and this repo as the car plus its test track.
- The car is the
patchcraftpackage, what gets installed bypip install patchcraft. It is a single library with one job: take one image (Tensor[C, H, W]), encode it into patches, decode patches back into the image, optionally pair LR/HR, resize, cache. One image at a time, every time. No datasets, no training, no orchestration, no batching across images. Multi-image is the caller'sforloop, ortorch.vmap, or aDataLoader. - The track is
tests/,lab/,tests/_datasets.pyand the dev extras (torchvision, etc.) in the repo. It is the pit crew, telemetry, driver and stopwatch that prove the car works on real images. It downloads datasets, drives the lib through varied geometries, measures correctness. It never ships in the wheel. See CONTRIBUTING.md if you're contributing.
The car is also acoplável, designed to drop into someone else's pipeline:
from patchcraft import Patchify
from torchvision import transforms
transform = transforms.Compose([
transforms.ToTensor(),
transforms.GaussianBlur(kernel_size=3),
Patchify(patch_size=4, stride=2), # ← PatchCraft as one step
])
Patchify is a callable; chain it inside a Compose, let DataLoader parallelize over workers. PatchCraft gives you the primitive; the surrounding pipeline stays your code.
Visual cheat sheet
The five core operations, one diagram each. Letters mark which patch each cell came from / goes to.
extract: image → patch stack
patch_size=4, stride=4 (no overlap) on an 8×8 image:
image (1, 8, 8) patches (4, 1, 4, 4)
+-----------------+ +-----+ +-----+
| . . . . | . . . . | | A | | B |
| . A . . | . B . . | extract +-----+ +-----+
| . . . . | . . . . | --------> patch0 patch1
| . . . . | . . . . |
|---------+---------| +-----+ +-----+
| . . . . | . . . . | | C | | D |
| . C . . | . D . . | +-----+ +-----+
| . . . . | . . . . | patch2 patch3
| . . . . | . . . . | (row-major order)
+-----------------+
reconstruct: patch stack → image (bit-exact when stride == patch_size)
Each output pixel = sum of patch contributions / count map (= how many patches covered it). When stride == patch_size, count is all-ones and the divide is a no-op.
stride == patch --> count map all 1 --> trivial copy
stride < patch --> count map > 1 --> weighted average
patch=4, stride=2, image cols 0..7:
col: 0 1 2 3 4 5 6 7
patch0: x x x x
patch1: x x x x
patch2: x x x x
count: 1 1 2 2 2 2 1 1 <- divide sum by this
pair: LR <-> HR, same image region, different resolution
scale_factor=2: every k-th LR patch corresponds to the k-th HR patch; HR coords are LR coords times the integer scale.
LR (1, 4, 4) HR (1, 8, 8)
+---------+ +-------------+
| . . . . | | . . . . . . . . |
| .[A]. . | k = 1 --> | . .[A A]. . . . |
| . . . . | | . .[A A]. . . . |
| . . . . | | . . . . . . . . |
+---------+ | . . . . . . . . |
| . . . . . . . . |
| . . . . . . . . |
| . . . . . . . . |
+-------------+
LR patch at (row=1, col=1) <--> HR patch at (row=2, col=2)
stitch: same fold geometry as reconstruct, with each patch weighted by a window kernel
Use when patches were modified by a model and uniform averaging shows boundary seams. Window kernels for patch_size=4:
weight="uniform" weight="hann" weight="gaussian"
(== reconstruct) centers > edges centers >> edges
(never 0) (never 0)
+ + + + . X X . . o o .
+ + + + X X X X o X X o
+ + + + X X X X o X X o
+ + + + . X X . . o o .
no seam attenuation strong attenuation, smooth attenuation,
corners preserved corners preserved
Everything stays one-image-at-a-time
for image in images:
patches = extract(image, ...) # PatchCraft primitive
result = model(patches) # caller's work
out = stitch(result, ...) # PatchCraft primitive
Multi-image parallelism is the caller's pipeline (torch.vmap, DataLoader workers, etc.). See SCOPE.md §2.
Scope (what the car does)
- Extract patches from a single image with configurable size, stride and dilation (
extract,Patchify). - Reconstruct an image from its patches, exact and weighted-overlap (
reconstruct). - Stitch modified patches (model output, denoised, super-resolved) back into one image with a window kernel that attenuates boundary seams (
stitch, withweight="uniform"|"hann"|"gaussian"). - Plan the geometry ahead of time:
num_patches((H, W), ...)for the count,tilings((H, W), allow_overlap=...)for every full-coverage(patch_size, stride)combo (no image, no allocation, just arithmetic). For LR↔HR setups:scale_factor(...)andpaired_tilings(...). - Pair LR and HR patches with metadata sufficient to reconstruct either (
pair,PatchPair,PatchMeta). - Measure pixel-level error between two patch stacks:
patch_metrics,per_patch_mse,per_patch_psnr. - Resize with pluggable backends, either PIL or torch (
resize). - Cache results on disk with content-addressed keys, OneDrive-race retry, optional zstd (
Cache).
Scope (what the car does NOT do)
- Not a dataset manager. PatchCraft does not load, download, batch, shuffle, or stream datasets. That's the track's job:
tests/_datasets.pyhasmnist_subset(...)for dev fixtures, andtorchvisionis in the[dev]extra (never a runtime dep of the car). - Not a multi-image API. Every primitive takes one image. Use
vmapor a Python loop if you need to apply it to many. - No SVMs, no kernels, no quantum circuits: those belong to other projects.
- No neural network training. PatchCraft is infrastructure, not a model.
Install
From PyPI
pip install patchcraft # core only
pip install patchcraft[cache] # adds zstandard for compressed Cache entries
From source (development)
git clone https://github.com/LeoPR/PatchCraft.git
cd patchcraft
pip install -e ".[dev,cache]"
For GPU support, install a matching torch wheel before PatchCraft
(e.g. pip install torch --index-url https://download.pytorch.org/whl/cu124).
Where to read next
| If you want… | Open |
|---|---|
| A hands-on tour with real REPL outputs for every public API | USAGE.md |
| The line between "PatchCraft's job" and "your pipeline's job", plus the parallelization story | SCOPE.md |
| Design decisions, math, the per-API contract | THEORY.md |
| Architecture Decision Records | ADR/ |
| Per-release changes | CHANGELOG.md |
| Cloning and contributing (run tests, layout, validation conventions) | CONTRIBUTING.md |
Author
Leonardo Marques de Souza
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 patchcraft-0.2.1.tar.gz.
File metadata
- Download URL: patchcraft-0.2.1.tar.gz
- Upload date:
- Size: 152.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via:
uv/0.11.11 {"installer":{"name":"uv","version":"0.11.11","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":null,"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
07725fff0f341a2ed80cbb20d416c802e31c6c228aa362ae58ca1a6e6087e157
|
|
| MD5 |
84db07be0e5d4eba21e1bc6fcbf6a69b
|
|
| BLAKE2b-256 |
9d83ca2d5fcc12c87bd23a051a4badd24bf8dd3686f5037b796821f088bed063
|
File details
Details for the file patchcraft-0.2.1-py3-none-any.whl.
File metadata
- Download URL: patchcraft-0.2.1-py3-none-any.whl
- Upload date:
- Size: 27.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via:
uv/0.11.11 {"installer":{"name":"uv","version":"0.11.11","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":null,"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
016f60b654ebbfb151cf15de05ea818a0ced551a3fa8854d5572404be2f1f178
|
|
| MD5 |
07ec80d629ea05d89a768f75174e1ba3
|
|
| BLAKE2b-256 |
56baa4f23fdd6faa33f3dc064c5150aa410559f5dd55cd50ff6686cd0946bf9e
|