Skip to main content

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 (+ its WeightKind), 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), and PatchPair/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 patchcraft package, what gets installed by pip 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's for loop, or torch.vmap, or a DataLoader.
  • The track is tests/, lab/, tests/_datasets.py and 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, with weight="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(...) and paired_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.py has mnist_subset(...) for dev fixtures, and torchvision is in the [dev] extra (never a runtime dep of the car).
  • Not a multi-image API. Every primitive takes one image. Use vmap or 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

patchcraft-0.2.1.tar.gz (152.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

patchcraft-0.2.1-py3-none-any.whl (27.3 kB view details)

Uploaded Python 3

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

Hashes for patchcraft-0.2.1.tar.gz
Algorithm Hash digest
SHA256 07725fff0f341a2ed80cbb20d416c802e31c6c228aa362ae58ca1a6e6087e157
MD5 84db07be0e5d4eba21e1bc6fcbf6a69b
BLAKE2b-256 9d83ca2d5fcc12c87bd23a051a4badd24bf8dd3686f5037b796821f088bed063

See more details on using hashes here.

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

Hashes for patchcraft-0.2.1-py3-none-any.whl
Algorithm Hash digest
SHA256 016f60b654ebbfb151cf15de05ea818a0ced551a3fa8854d5572404be2f1f178
MD5 07ec80d629ea05d89a768f75174e1ba3
BLAKE2b-256 56baa4f23fdd6faa33f3dc064c5150aa410559f5dd55cd50ff6686cd0946bf9e

See more details on using hashes here.

Release history Release notifications | RSS feed

0.5.4

7 files

0.5.3

7 files

0.5.2

7 files

0.5.1

7 files

0.5.0

2 files

0.2.2

2 files

This release

0.2.1 This release

2 files

0.2.0

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page