AI-powered image upscaler accelerated on Apple Metal (MPS).
Project description
metalgrow
AI-powered image upscaler accelerated on Apple Metal (MPS).
metalgrow runs super-resolution on Apple Silicon GPUs through PyTorch's MPS
backend, with graceful fallbacks to CUDA and CPU. It ships with a bicubic
baseline so the pipeline is runnable end-to-end, and exposes a clean seam for
plugging in a learned backbone (Real-ESRGAN, SwinIR, etc.).
Table of contents
Features
- 🍎 Apple Metal first — PyTorch MPS backend, zero config on Apple Silicon
- 🔁 Portable — automatic fallback to CUDA / CPU when MPS isn't available
- 🧩 Pluggable backbones — bicubic, Real-ESRGAN (x2/x4), SwinIR (x2/x4)
- 🧱 Tiled inference — process arbitrarily large images with feathered overlap blending
- 📂 Batch mode — upscale whole directories or globs with a progress bar
- 📦 Model registry —
metalgrow modelsmanages cached weights with sha256 verification - 🧪 Tested — pytest suite covering the CPU baseline, tiling, batch mode, and registry
Requirements
- Python 3.11+
- macOS with Apple Silicon for MPS acceleration (optional — CPU/CUDA also work)
Install
git clone https://github.com/joaodotwork/metalgrow.git
cd metalgrow
uv venv && source .venv/bin/activate
uv pip install -e .
Or with plain pip:
python -m venv .venv && source .venv/bin/activate
pip install -e .
Usage
CLI
Single file:
metalgrow info
metalgrow upscale input.jpg out.png --scale 2
metalgrow upscale input.jpg out.png --scale 4 --device mps --backbone realesrgan-x4
Whole directory or glob (writes to a target directory, mirroring filenames):
metalgrow upscale ./photos ./photos-upscaled --scale 2 --backbone realesrgan-x2
metalgrow upscale "./photos/*.png" ./out --scale 2 --skip-existing
| Flag | Default | Description |
|---|---|---|
--scale, -s |
2.0 |
Upscale factor (1.01–8.0) |
--device, -d |
auto |
auto | mps | cuda | cpu |
--backbone, -b |
bicubic |
bicubic | realesrgan-x{2,4} | swinir-x{2,4} |
--dtype |
fp32 |
fp32 | fp16 (fp16 is MPS-only and noisier) |
--tile |
backbone hint | Tile size in input px for tiled inference (0 disables) |
--tile-pad |
backbone hint | Context padding per tile edge (covers backbone receptive field) |
--skip-existing |
off | Batch mode: skip outputs that already exist |
--workers, -j |
4 |
Batch mode: parallel I/O workers (inference stays serial) |
Manage cached model weights
metalgrow models list
metalgrow models download realesrgan-x4
metalgrow models rm realesrgan-x4
Weights cache to ~/.cache/metalgrow/ by default; override with the
METALGROW_CACHE_DIR env var. Every download is sha256-verified.
See docs/models.md for a quality / speed / memory
comparison (with benchmark numbers) and guidance on which backbone to pick,
or docs/usage.md for the full CLI / library reference.
Library
from PIL import Image
from metalgrow import Upscaler
upscaler = Upscaler(backbone="realesrgan-x2", device="auto") # auto | mps | cuda | cpu
result = upscaler.upscale(
Image.open("input.jpg").convert("RGB"),
scale=2.0,
tile=256, # optional — backbone has sensible defaults
tile_pad=16,
)
result.save("out.png")
Project layout
src/metalgrow/
device.py # device auto-selection (MPS → CUDA → CPU)
upscaler.py # Upscaler class + tiled inference with overlap blending
batch.py # directory / glob batch mode
weights.py # weight registry, sha256 verification, cache management
cli.py # typer CLI (upscale, info, models)
backbones/ # bicubic, realesrgan, swinir; plugin registry
tests/
docs/
usage.md # CLI recipes, library API, env vars, pitfalls
models.md # backbone comparison, benchmark snapshot, tiling
benchmarks.md # full (device × backbone × scale) tables
architecture.md # module layout, data flow, extension points
Roadmap
- Integrate a learned SR backbone (Real-ESRGAN default)
- Tiled inference for large images
- Batch / directory mode
- Model registry + weight download
- Second backbone family (SwinIR)
- GitHub Actions CI (lint + test on macOS + Linux)
- Benchmarks: MPS vs CPU (CUDA pending GPU runner)
- v0.1.0 release
Contributing
Issues and PRs are welcome. Please run ruff and pytest before opening a PR.
License
MIT — see LICENSE.
Made with 🔩 on Apple Silicon.
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 metalgrow-0.1.1.tar.gz.
File metadata
- Download URL: metalgrow-0.1.1.tar.gz
- Upload date:
- Size: 90.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d7fc3a7b0ce84259db3c9dda4ba0d29da1122b01075b4ecd42c9a7331f89b641
|
|
| MD5 |
3d9e70566719e3ce75ee66ae22c3cfc1
|
|
| BLAKE2b-256 |
d917355145d15dac921cd02ba339aa51d8f302d562d87101e5504aeef9a93156
|
Provenance
The following attestation bundles were made for metalgrow-0.1.1.tar.gz:
Publisher:
release.yml on joaodotwork/metalgrow
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
metalgrow-0.1.1.tar.gz -
Subject digest:
d7fc3a7b0ce84259db3c9dda4ba0d29da1122b01075b4ecd42c9a7331f89b641 - Sigstore transparency entry: 1287575851
- Sigstore integration time:
-
Permalink:
joaodotwork/metalgrow@445462bd11cfbbe0950d61583821fe449e03deaa -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/joaodotwork
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@445462bd11cfbbe0950d61583821fe449e03deaa -
Trigger Event:
push
-
Statement type:
File details
Details for the file metalgrow-0.1.1-py3-none-any.whl.
File metadata
- Download URL: metalgrow-0.1.1-py3-none-any.whl
- Upload date:
- Size: 18.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
bc30ab4e69401c791b636d33a89c2d594ee48dda02faca0cd49d97ba949f0cf2
|
|
| MD5 |
b5574ab957b920ecfd2aa432eeba0e18
|
|
| BLAKE2b-256 |
5be2be0f2f46954ca8ed2ba4fb89025401138a13d6c0887146cc02078925098c
|
Provenance
The following attestation bundles were made for metalgrow-0.1.1-py3-none-any.whl:
Publisher:
release.yml on joaodotwork/metalgrow
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
metalgrow-0.1.1-py3-none-any.whl -
Subject digest:
bc30ab4e69401c791b636d33a89c2d594ee48dda02faca0cd49d97ba949f0cf2 - Sigstore transparency entry: 1287575942
- Sigstore integration time:
-
Permalink:
joaodotwork/metalgrow@445462bd11cfbbe0950d61583821fe449e03deaa -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/joaodotwork
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@445462bd11cfbbe0950d61583821fe449e03deaa -
Trigger Event:
push
-
Statement type: