augrs
Fast, GIL-free image augmentation with a Rust core and an Albumentations-compatible Python API.
augrs transforms images, masks, bounding boxes and keypoints together with a single random draw, releases the GIL while it works, and can augment a whole batch on its own thread pool. Its Python API follows Albumentations 2.0.8, so most pipelines port by changing the import, and it reads and writes Albumentations config files. It is dual-licensed under MIT or Apache-2.0.
import augrs as A # instead of: import albumentations as A
t = A.Compose([A.RandomResizedCrop(size=(512, 512)), A.HorizontalFlip(), A.ColorJitter(0.2, 0.2, 0.2, 0.05)],
bbox_params=A.BboxParams(format="coco", label_fields=["labels"]), seed=0)
out = t(image=img, mask=mask, bboxes=boxes, labels=labels)
Status: early (0.1.0, alpha).
pip install augrs-py, thenimport augrs(see Install).
Why
- Albumentations is archived. The MIT-licensed library most vision projects use was archived in June 2025; its last release is 2.0.8.
- Its successor is AGPL. AlbumentationsX is AGPL-3.0 or commercial, which many companies cannot ship. augrs is MIT OR Apache-2.0 and contains no AlbumentationsX code.
- Python augmentation is GIL-bound. Using more than one core with Albumentations means worker
processes, which cost memory and the pickling of every output. augrs runs in Rust with the GIL
released, so Python threads or
augment_batch(num_threads=...)scale without extra processes.
More background, including the survey of alternatives, is in docs/MOTIVATION.md.
Features
- 26 transforms plus 4 composition types (
Compose,OneOf,SomeOf,Sequential) with Albumentations names, arguments, defaults and per-transform probabilityp. - Joint targets. Every geometric transform is a single point map (affine, homography or
displacement field) applied consistently to images, masks, bounding boxes (
pascal_voc,coco,yolo,albumentations) and keypoints (xy,yx,xya,xys,xyas,xysa), with Albumentations' filtering options (min_area,min_visibility,min_width,min_height,max_accept_ratio,remove_invisible) and label fields. additional_targets: extra images, masks, box sets and keypoint sets get the same geometry and the same sampled colour parameters.- Seeded determinism. The same seed gives the same output, independent of the thread count and of the CPU's SIMD support. Single draws can be replayed, and applied parameters returned.
- GIL-free batches.
augment_batch(images, ..., num_threads=4)runs on a rayon thread pool; single calls release the GIL too. - Fast kernels. Hand-written AVX2/FMA kernels with runtime detection and a portable scalar fallback (bit-identical results) for warps, resizes, 8-bit HSV, saturation and normalisation; mimalloc in the Python extension.
- Albumentations configs.
augrs.loadreads JSON/YAML files written by Albumentations'A.save/A.to_dict;augrs.savewrites files that Albumentations can load. - Tested parity. A pytest suite compares augrs against Albumentations 2.0.8 and OpenCV transform by transform, and Rust property tests check that targets stay consistent.
Supported transforms
Parity is measured against Albumentations 2.0.8 (with OpenCV) given the same sampled parameters, since augrs uses its own random number generator: random transforms produce the same distribution of results, not the same individual samples.
- Bit-exact: identical output for the same parameters.
- Close: small numeric differences (bounds below, all pinned by tests).
- Differs: a deliberate, documented difference (see Differences from Albumentations).
Geometric
| Transform | Parity | Notes |
|---|---|---|
HorizontalFlip, VerticalFlip |
Bit-exact | Image, mask, boxes in all 4 formats, labels, keypoints |
Transpose |
Bit-exact | Same targets as flips |
RandomRotate90 |
Bit-exact | Every factor, vs np.rot90 and Albumentations' box/keypoint functions |
CenterCrop |
Bit-exact | Including pad_if_needed3 |
RandomCrop |
Bit-exact | Given the same window (image, mask, boxes in all 4 formats, keypoints), including pad_if_needed3 |
PadIfNeeded |
Bit-exact | min_height/min_width and pad_*_divisor, every position and border mode3 |
Resize |
Close | Linear: max diff 1 level, on < 1% of pixels2 (tested sizes of 16 px and up). Nearest: INTER_NEAREST_EXACT, identical except where an output pixel centre lies exactly halfway between two input pixels (OpenCV breaks such ties either way). Cubic/area/lanczos: antialiased fast_image_resize kernels |
RandomResizedCrop |
Close | Crop + Resize given the window; window distribution (area, aspect) tested against Albumentations' sampler |
LongestMaxSize, SmallestMaxSize |
Close | As Resize, same output size (Python rounding); a list of sizes picks one at random |
Rotate |
Close | vs cv2.warpAffine with the same matrix: mean diff < 0.6 (OpenCV quantises to 1/32 px); crop_border, fit_output |
Affine |
Close | As Rotate, with fixed parameters vs Albumentations (scale, rotate, shear, whole-pixel translation); fit_output canvas within 1 px; balanced_scale |
ShiftScaleRotate |
Close | As Affine, with fixed parameters vs Albumentations |
Perspective |
Differs | Warp matches cv2.warpPerspective; no extra zoom with keep_size=True |
ElasticTransform |
Differs | Coarse-grid noise for sigma > 8; exact keypoint inverse |
Photometric and other
| Transform | Parity | Notes |
|---|---|---|
HueSaturationValue |
Bit-exact | All 16.7M RGB colours through OpenCV's 8-bit HSV round trip1 |
ColorJitter |
Close | Hue bit-exact1; brightness/contrast/saturation within 1 level |
RandomBrightnessContrast |
Bit-exact | uint8; float32 within 1e-6. brightness_by_max, ensure_safe_range |
RandomGamma |
Bit-exact | uint8 |
ToGray |
Bit-exact | weighted_average, average, max, desaturation; 1 or 3 output channels |
CLAHE |
Close | Gray images bit-exact2; RGB mean diff < 1 level (float Lab conversion) |
GaussianBlur |
Close | Within 1 level of OpenCV |
Normalize |
Close | Within 2e-4; standard, image, image_per_channel, min_max, min_max_per_channel |
GaussNoise |
Differs | Same distribution parameters; different sampler (see below) |
CoarseDropout |
Bit-exact | Given the same holes: image/mask fill, box (shrink) and keypoint handling |
1 Bit-exact against OpenCV builds that fuse multiply-adds (the Linux x86-64 wheels). OpenCV's Windows (MSVC) wheels do not, and a few values (< 0.1%, the tested bound) differ by one level there.
2 Against OpenCV's x86-64 builds. OpenCV's arm64 builds (macOS on Apple silicon, Linux aarch64) use different kernels for some 8-bit ops, so the reference itself moves: linear resize differs by one level on up to ~22% of pixels for some sizes (two levels on some single-channel upscales), gray CLAHE on < 0.5% of pixels, and the HSV round trip1 on < 0.3% of values (0.02-0.07% measured on Linux aarch64). augrs produces the same output on x86 and arm; the tests allow these differences only on arm builds of OpenCV.
3 With reflecting border modes (reflect, reflect101), Albumentations 2.0.8 also adds
mirrored copies of boxes and keypoints that fall in the padded area; augrs keeps one box per
object. Images and masks are identical.
Compositions
Compose (nestable), OneOf, SomeOf (Albumentations 2.x semantics: uniform choice of n,
original order, each child keeps its p) and Sequential, all with p.
Transforms not listed here, and a few options (CoarseDropout(fill="inpaint_*"),
ToGray(method="from_lab" | "pca"), area_for_downscale, max_size_hw), are not supported yet;
loading a config that uses them raises NotImplementedError naming the transform or argument.
Install
pip install augrs-py # the import name is `augrs`
The PyPI name is augrs-py because augrs was already taken by an unrelated package. Prebuilt
abi3 wheels (CPython 3.9+) cover Linux x86_64 / aarch64, macOS x86_64 / arm64 and Windows x86_64.
To build from source you need a Rust toolchain (1.85 or newer, via rustup) and Python 3.9 or newer. pip builds the extension with maturin in release mode (a few minutes the first time).
git clone https://github.com/Dat-cool-repo/augrs
cd augrs
python -m venv .venv && source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install . # or, without cloning: pip install git+https://github.com/Dat-cool-repo/augrs
# for development: an editable install, or an abi3 wheel (one wheel for every Python >= 3.9)
pip install maturin
maturin develop --release
maturin build --release --out dist && pip install dist/augrs_py-*.whl
pyyaml is needed only for YAML configs (pip install pyyaml). The Rust core is the
augrs-core crate in this workspace (also not on crates.io yet):
[dependencies]
augrs-core = { git = "https://github.com/Dat-cool-repo/augrs" }
ndarray = "0.17"
Python quick start
Detection and segmentation
import numpy as np
import augrs as A
t = A.Compose(
[
A.RandomResizedCrop(size=(512, 512), scale=(0.25, 1.0)),
A.HorizontalFlip(p=0.5),
A.Affine(rotate=(-15, 15), scale=(0.9, 1.1), p=0.5),
A.OneOf([A.HueSaturationValue(), A.RandomBrightnessContrast()], p=0.8),
A.CoarseDropout(fill_mask=0, p=0.3),
A.Normalize(),
],
bbox_params=A.BboxParams(format="coco", label_fields=["labels"], min_visibility=0.1),
seed=0,
)
image = np.random.randint(0, 256, (480, 640, 3), dtype=np.uint8) # HWC, uint8 or float32
mask = np.zeros((480, 640), dtype=np.uint8)
mask[100:200, 150:300] = 1
boxes = [(150, 100, 150, 100), (20, 30, 60, 80)] # coco: x, y, w, h
labels = ["car", "person"]
out = t(image=image, mask=mask, bboxes=boxes, labels=labels)
out["image"] # (512, 512, 3) float32, normalised
out["mask"] # (512, 512) uint8, same geometry as the image
out["bboxes"], out["labels"] # transformed boxes; labels of dropped boxes are dropped too
Extra images, masks, box sets and keypoint sets go through additional_targets
(e.g. additional_targets={"depth": "image", "mask2": "mask"}), and keypoints through
keypoint_params=A.KeypointParams(format="xy", label_fields=["kp_labels"]).
Batches without the GIL
images = [np.random.randint(0, 256, (480, 640, 3), dtype=np.uint8) for _ in range(32)]
outs = t.augment_batch(
images,
bboxes=[boxes] * 32, # every other argument: one entry per image
labels=[labels] * 32,
seed=1,
num_threads=4,
)
batch = np.stack([o["image"] for o in outs]) # (32, 512, 512, 3)
Sample i uses a seed derived from (seed, i), so the result does not depend on num_threads.
Calling t(...) from several Python threads also scales, since each call releases the GIL.
Albumentations configs
import augrs
t = augrs.load("albumentations_pipeline.yaml") # written by albumentations' A.save (JSON or YAML)
augrs.save(t, "pipeline.json") # loadable by augrs and by albumentations' A.load
# or convert an in-memory Albumentations pipeline
import albumentations
t = augrs.from_dict(albumentations.to_dict(albu_pipeline))
PyTorch DataLoader
examples/torch_dataloader.py augments whole batches in
collate_fn, so no worker processes are needed:
class AugrsCollate:
def __init__(self, transform, num_threads=4):
self.t, self.num_threads = transform, num_threads
def __call__(self, batch):
imgs, boxes, labels = zip(*batch)
outs = self.t.augment_batch(list(imgs), bboxes=list(boxes), labels=list(labels),
num_threads=self.num_threads)
x = torch.from_numpy(np.stack([o["image"] for o in outs])).permute(0, 3, 1, 2)
return x, [{"boxes": torch.as_tensor(np.asarray(o["bboxes"]).reshape(-1, 4)),
"labels": torch.as_tensor(o["labels"])} for o in outs]
loader = DataLoader(dataset, batch_size=32, num_workers=0, collate_fn=AugrsCollate(t))
Run it with python examples/torch_dataloader.py (synthetic images) or with --data data after
downloading the COCO subset; it prints a throughput comparison with Albumentations.
Rust quick start
use augrs_core::{BboxFormat, BboxParams, Buf, Input, Pipeline, PipelineSpec, Transform};
use ndarray::Array3;
fn main() -> augrs_core::Result<()> {
let spec = PipelineSpec::new(vec![
Transform::random_resized_crop(512, 512, (0.25, 1.0)),
Transform::hflip(0.5),
Transform::some_of(
vec![
Transform::rotate((-15.0, 15.0), 1.0),
Transform::perspective((0.05, 0.1), 1.0),
],
1,
0.5,
),
Transform::color_jitter(0.2, 0.2, 0.2, 0.05, 0.8),
Transform::normalize_imagenet(),
])
.with_bboxes(BboxParams::new(BboxFormat::Coco));
let pipe = Pipeline::new(spec, Some(42))?;
let img = Array3::<u8>::zeros((480, 640, 3)); // HWC
let mut inp = Input::image(Buf::U8(img));
inp.bboxes = vec![[10.0, 20.0, 50.0, 40.0]];
let out = pipe.apply(inp)?; // out.image, out.masks, out.bboxes, out.bbox_ids, out.keypoints, ...
println!("{} boxes kept", out.bboxes.len());
// batches run on rayon; sample i uses a seed derived from (7, i)
let batch = vec![Input::image(Buf::U8(Array3::zeros((480, 640, 3))))];
let _outs = pipe.apply_batch(batch, Some(7), false);
Ok(())
}
Transforms are a serde-serialisable Transform enum, so a PipelineSpec can also be built from
JSON (Pipeline::from_json).
Benchmarks
augrs vs Albumentations 2.0.8 on 300 COCO val2017 images (mean 482x577, 2145 boxes), decoded once
up front; only augmentation is timed. Pipeline: RandomResizedCrop(512x512, scale=(0.25, 1)),
HorizontalFlip(0.5), Affine(rotate ±15, scale 0.9-1.1, translate ±6.25%, p=0.5),
ColorJitter(0.2, 0.2, 0.2, 0.05, p=0.8), GaussianBlur((3, 5), p=0.2), Normalize().
"Detection" adds COCO boxes and labels, "segmentation" a uint8 mask. OpenCV was limited to one
thread per worker.
Machine: Intel i9-13900H laptop (P- and E-cores) under WSL2. Each number is the median of 3 runs (each run the best of 2), with the individual runs in brackets.
| images/s (higher is better) | detection | segmentation |
|---|---|---|
| Albumentations, 1 thread | 230 [259, 230, 221] | 221 [303, 221, 213] |
| Albumentations, 4 Python threads | 251 [271, 251, 227] | 669 [735, 571, 669] |
| Albumentations, 4 processes (fork pool, no result transfer) | 757 [796, 757, 685] | 794 [891, 705, 794] |
augrs, 1 thread, per-image t(...) calls |
417 [417, 397, 418] | 389 [389, 374, 396] |
augrs, augment_batch(num_threads=1) |
461 [474, 457, 461] | 407 [407, 396, 409] |
augrs, 4 Python threads calling t(...) |
1504 [1613, 1504, 1463] | 1310 [1293, 1310, 1325] |
augrs, augment_batch(num_threads=2) |
833 [871, 833, 799] | 767 [767, 758, 767] |
augrs, augment_batch(num_threads=4) |
1393 [1493, 1332, 1393] | 1348 [1382, 1348, 1254] |
Noise caveat: the machine was shared with other jobs, and single runs vary by up to ±25% (mostly P-core vs E-core scheduling). Read the ratios rather than the absolute numbers, and run the benchmark on your own hardware.
- Single thread: augrs is about 1.8-2x Albumentations.
- Four threads: about 1.7-2x Albumentations' 4 worker processes, without extra processes, and
5-6x Albumentations with 4 Python threads on detection (its box bookkeeping holds the GIL). The
process-pool row also excludes shipping the float outputs back to the parent, which a real
DataLoaderpays. - PyTorch DataLoader (
examples/torch_dataloader.py, 256 COCO images to 384x384 with boxes, batch 32): Albumentations in__getitem__312 img/s (0 workers) / 635 img/s (4 workers); augrs in__getitem__483 img/s (0 workers); augrsaugment_batchincollate_fn498 img/s (1 thread) / 1251 img/s (4 threads, no worker processes). - Per kernel (512x512 RGB, one thread, AVX2 vs scalar fallback): hue shift 0.52 vs 2.1 ms, warp 0.6 vs 1.3 ms, resize 0.5 vs 0.56 ms, saturation 0.12 vs 0.32 ms.
Raw numbers are in benches/results/coco300.json. To reproduce:
bash scripts/fetch_coco_subset.sh # COCO val2017 annotations + 300 images into ./data
RUNS=3 bash scripts/bench_median.sh --repeats 2
bash scripts/torch_example.sh # DataLoader comparison (needs torch)
bash scripts/profile_ops.sh # per-kernel timings
Differences from Albumentations
- Keypoint coordinates are continuous: pixel
ispans[i, i+1)and its centre is ati + 0.5. PassKeypointParams(pixel_index_coords=True)for the pixel-index convention; flips, transposes and 90-degree rotations then match Albumentations exactly. BboxParams(clip=True)is the default (Albumentations:False).- Reflect padding does not duplicate targets: Albumentations 2.0.8 mirrors boxes and keypoints
into reflect-padded borders (
PadIfNeeded,pad_if_needed, and warps with reflecting borders); augrs keeps exactly one box / keypoint per input. - Box filtering happens once, at the end of the pipeline:
min_visibilityis the fraction of the input box still visible after all transforms.check_each_transformis accepted for config compatibility. - Random draws differ: augrs uses its own RNG (xoshiro256++), so the same seed does not give the same samples as Albumentations.
Perspective: the jittered quadrilateral is mapped exactly onto the output. Albumentations 2.0.8 additionally zooms in bysize / quad_sizewhenkeep_size=True.fit_output(Rotate,Affine,Perspective) uses whole-pixel floor/ceil bounds; Albumentations' canvas is one pixel larger.GaussNoise: normal samples come from a 65536-entry inverse-CDF table (tails cut at about ±4.2 sigma) and are rounded rather than truncated.ElasticTransform: forsigma > 8the noise is generated on a gridsigma / 4times coarser and upsampled (same standard deviation) instead of a very large blur at full resolution. Boxes are the union of the output pixels that sample inside them and of their mapped boundary; keypoints use the exact inverse of the displacement field.CLAHEon RGB converts to Lab in floating point; OpenCV uses fixed-point tables.- Masks default to nearest-pixel-centre sampling (OpenCV
INTER_NEAREST_EXACT); every geometric transform acceptsmask_interpolation(also settable onCompose). - Cubic, area and lanczos resizes use
fast_image_resizekernels (antialiased, Catmull-Rom for cubic), so they differ from OpenCV's. CoarseDropoutaddsbbox_handling("shrink", the Albumentations behaviour,"visibility"or"keep") andkeypoint_handlingoptions.
Determinism
- A
Compose(..., seed=s)produces the same sequence of outputs every time it is created with that seed.t.set_seed(s)resets it. t(..., seed=s)replays one specific draw; withCompose(save_applied_params=True)the output also containsapplied_transforms(the sampled parameters) and theseedthat produced it.augment_batch(..., seed=s)gives sampleia seed derived from(s, i): the results are the same for anynum_threads(1 vs 4 is tested).- The AVX2 kernels and the portable scalar kernels produce identical results (every kernel is
tested against its scalar version; the whole Rust suite also runs with
AUGRS_FORCE_SCALAR=1). - The RNG is implemented in augrs (no dependency on platform or library RNGs). Outputs for a given seed may still change between augrs releases while the project is pre-1.0.
- Worker processes. A process forked after the pipeline was created (PyTorch
DataLoaderworkers on Linux) re-seeds the pipeline on its first call: from(seed, worker seed)inside a PyTorch worker (reproducible for a seededDataLoader), from fresh entropy whenseed=None. Without this every worker would replay the same augmentation stream (Albumentations 2.0.8 has that problem). Pipelines pickle, so spawned workers (Windows, macOS) work too; an unpickled pipeline restarts its stream from its seed. A seeded pipeline used in other kinds of forked processes keeps its stream: callt.set_seed(...)in each process if needed.
Input validation and limits
- Parameters are checked when a transform is created. Non-finite values (NaN, infinity),
poutside[0, 1], zero or negative sizes, inverted ranges and values beyond the limits below raiseValueErrornaming the transform (andNotImplementedErrorfor Albumentations options augrs does not support), so a bad config fails where it is built, not in aDataLoaderworker. - Images must be non-empty
(H, W)or(H, W, C)arrays of uint8 or float32 (ValueError/TypeErrorotherwise); masks and additional images must have the image's height and width. - Boxes with NaN or infinite values, or with
x_max < x_min/y_max < y_min, raiseValueError. Boxes partly or fully outside the image are clipped (clip=True, the default) or raise (clip=False). Boxes that are empty after clipping or after the pipeline (zero area, outside the output) or that fail theBboxParamsthresholds are dropped together with their labels. An empty box list is fine. - Keypoints with a non-finite coordinate, angle or scale raise
ValueError. Withremove_invisible=True(the default) keypoints outside the output image are dropped, including ones that were already outside on input; withFalsethey are kept with their coordinates. - Limits (far beyond normal use; they bound memory and time for malformed configs): images up
to 1,048,576 px per side and 2^31 - 1 elements;
GaussianBlurkernels up to 1023 (sosigmaup to 146 when the kernel size is derived from it);CoarseDropoutup to 4096 holes;SomeOf(replace=True)up ton = 1024;CLAHEup to 256 tiles per axis; compositions nested up to 32 levels. A parameter beyond a limit raises at construction; a transform whose output would exceed the size limit for a given image (for exampleAffine(fit_output=True)with a huge scale) raisesValueErrorwhen it is called.
Development
# one-time: a virtualenv with the test dependencies
python -m venv .venv && source .venv/bin/activate
pip install maturin numpy pytest pyyaml "albumentations==2.0.8" opencv-python-headless
bash scripts/test_rust.sh # Rust unit + property tests (release)
AUGRS_FORCE_SCALAR=1 bash scripts/test_rust.sh # same, on the portable scalar kernels
bash scripts/build_py.sh # maturin develop --release into the venv
bash scripts/test_py.sh # pytest: parity with Albumentations/OpenCV, API, serialisation
cargo fmt --all --check && cargo clippy --workspace --all-targets --release -- -D warnings
The scripts source scripts/env.sh, which activates $AUGRS_VENV (default
./.venv) and sets AUGRS_DATA (default ./data, git-ignored). Set CARGO_TARGET_DIR to keep
build output elsewhere (on WSL, a Linux path is much faster than a Windows drive).
Windows wheel from WSL/Linux. scripts/build_wheel_windows.sh cross-builds the abi3 Windows
wheel with mingw-w64 (rustup target add x86_64-pc-windows-gnu, apt install gcc-mingw-w64-x86-64)
into dist/. On the Windows host, scripts/test_wheel_windows.ps1 installs it into a fresh venv
and runs the smoke test and the test suite:
powershell -File scripts\test_wheel_windows.ps1 -Python python -VenvDir $env:TEMP\augrs-venv
CI (.github/workflows/ci.yml) runs rustfmt, clippy and the Rust tests on Linux, Windows and
macOS, plus pytest on Python 3.9, 3.12 and 3.13. .github/workflows/wheels.yml (manual or on a
v* tag) builds abi3 wheels for Linux (x86_64, aarch64), Windows and macOS (x86_64, arm64) plus
an sdist, runs the smoke test and the full pytest suite on each build machine, then checks the
distributions (twine check, license files, metadata) and installs the sdist in a fresh venv. On a
v* tag it then publishes everything to PyPI (trusted publishing).
Tested by hand as well: the Windows wheel in a fresh native Python 3.10 venv (412 tests pass), and on Apple Silicon (macOS, M5 Pro) both a source build and the CI wheel (412 tests pass, Rust tests pass, and a pipeline runs in spawned worker processes).
Fuzzing (nightly Rust and cargo install cargo-fuzz; see fuzz/):
cargo +nightly fuzz run pipeline -- -jobs=2 -rss_limit_mb=2048 -timeout=10 -max_total_time=1200
cargo +nightly fuzz run single_transform -- -jobs=2 -rss_limit_mb=2048 -timeout=10 -max_total_time=1200
cargo +nightly fuzz run from_json -- -dict=fuzz/dict/augrs_json.dict -jobs=2 -max_total_time=1200
python fuzz/python/fuzz_from_dict.py --loop --seconds 1200 # Albumentations config loader
Project layout
Cargo.toml workspace (rustfmt max_width 120)
pyproject.toml Python package metadata (maturin build backend)
crates/augrs-core/ Rust core: ndarray HWC buffers, fast_image_resize, rayon
src/geometry.rs Affine2 and Homography in continuous pixel coordinates
src/geo.rs one sampled geometric op -> images, masks, boxes, keypoints
src/targets.rs box/keypoint formats, clipping, visibility filtering
src/transforms.rs the Transform enum (serde) and parameter sampling
src/pipeline.rs Pipeline: seeded RNG, apply / apply_batch (rayon)
src/rng.rs xoshiro256++ / splitmix64
src/ops/ kernels: flip/crop/pad, resize, warp, remap, color, hsv, clahe,
noise, blur, normalize, simd.rs (AVX2, runtime-detected)
tests/props.rs proptest property tests (joint-target consistency)
tests/robustness.rs invalid parameters / targets, degenerate inputs, limits (fuzz regressions)
examples/profile_ops.rs per-kernel timings
crates/augrs-py/ PyO3 (abi3-py39) extension and the `augrs` Python package (maturin)
python/augrs/ _transforms.py, _compose.py, serialization.py
compat-tests/ pytest: parity with Albumentations 2.0.8 / OpenCV, API, serialisation
fixtures/ configs exported by Albumentations 2.0.8 (JSON and YAML)
examples/torch_dataloader.py augment_batch in a PyTorch collate_fn
examples/train_parity.py train the same classifier with augrs and Albumentations (Imagenette)
fuzz/ cargo-fuzz targets (random pipelines, JSON specs) and a config-loader fuzzer
benches/ benchmark script and results
scripts/ build, test, benchmark and wheel scripts
docs/MOTIVATION.md background and original scope
Roadmap
- AVX2 kernels for Gaussian blur and nearest-neighbour mask warps; NEON kernels for aarch64 and Apple silicon (which currently run the correct, deterministic scalar fallback).
- More transforms (
MotionBlur,Downscale,GridDistortion,RandomScale, ...),max_size_hwand inpainting fills. - The core crate on crates.io.
- A Burn integration crate for Rust-native training.
License
Licensed under either of
- Apache License, Version 2.0 (LICENSE-APACHE)
- MIT license (LICENSE-MIT)
at your option.
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in this project by you, as defined in the Apache-2.0 license, shall be dual-licensed as above, without any additional terms or conditions.
Acknowledgements
- Albumentations (MIT), whose API and behaviour augrs follows, and whose 2.0.8 release the test suite compares against.
- OpenCV (Apache-2.0), whose arithmetic several kernels reproduce.
- PyO3, maturin, rust-numpy, ndarray, rayon, fast_image_resize and mimalloc.
- The COCO dataset, used (downloaded on demand) for benchmarks.
See THIRD_PARTY_NOTICES.md for details and license notices. augrs contains no code from AlbumentationsX.
Metadata
Release files for augrs-py 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| augrs_py-0.1.0.tar.gz | 149.4 kB | Details |
Built distributions (wheels)
| File | Reset | |||
|---|---|---|---|---|
| augrs_py-0.1.0-cp39-abi3-win_amd64.whl | CPython 3.9 | abi3 | Windows x86-64 | Details |
| augrs_py-0.1.0-cp39-abi3-manylinux_2_28_x86_64.whl | CPython 3.9 | abi3 | Linux glibc 2.28+ x86-64 | Details |
| augrs_py-0.1.0-cp39-abi3-manylinux_2_28_aarch64.whl | CPython 3.9 | abi3 | Linux glibc 2.28+ ARM64 | Details |
| augrs_py-0.1.0-cp39-abi3-macosx_11_0_arm64.whl | CPython 3.9 | abi3 | macOS 11.0+ ARM64 | Details |
| augrs_py-0.1.0-cp39-abi3-macosx_10_12_x86_64.whl | CPython 3.9 | abi3 | macOS 10.12+ x86-64 | Details |
Total release size: 8.2 MB
Release files / augrs_py-0.1.0.tar.gz
| Download URL | augrs_py-0.1.0.tar.gz |
|---|---|
| Size | 149.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
db1ae0648f6534bd9d3aa92d429eda474ee446b4f3c932ff6c70dc677e79d687
|
|
BLAKE2b-256 checksum How to use checksums |
5e87771d3dd5977a9397d0ec35db2a55cb64811af6b50ab9d1cdd07f391124dd
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
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.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 8, 2026.
Transparency logRelease files / augrs_py-0.1.0-cp39-abi3-win_amd64.whl
| Download URL | augrs_py-0.1.0-cp39-abi3-win_amd64.whl |
|---|---|
| Size | 1.6 MB |
| Tags | CPython 3.9 Windows x86-64 abi3 |
|
SHA-256 checksum How to use checksums |
3c88b0a9e34f4e696f59a8b0c6513c66b0867a8606947fae480c7266f0c4f4f7
|
|
BLAKE2b-256 checksum How to use checksums |
22e457bfe37b6afdacc4f0375d3237432994be8c53d4c63d1069b3e53c7d931f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
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.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 8, 2026.
Transparency logRelease files / augrs_py-0.1.0-cp39-abi3-manylinux_2_28_x86_64.whl
| Download URL | augrs_py-0.1.0-cp39-abi3-manylinux_2_28_x86_64.whl |
|---|---|
| Size | 1.8 MB |
| Tags | CPython 3.9 Linux glibc 2.28+ x86-64 abi3 |
|
SHA-256 checksum How to use checksums |
641a5207f102106f13eb2da9f1b0f69305d02cf488d68af38538e337e4db16e8
|
|
BLAKE2b-256 checksum How to use checksums |
6eda874fa839d43accb517275fdcd2e67f808f3d56c1c5214ce3b194bfb0bf28
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
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.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 8, 2026.
Transparency logRelease files / augrs_py-0.1.0-cp39-abi3-manylinux_2_28_aarch64.whl
| Download URL | augrs_py-0.1.0-cp39-abi3-manylinux_2_28_aarch64.whl |
|---|---|
| Size | 1.5 MB |
| Tags | CPython 3.9 Linux glibc 2.28+ ARM64 abi3 |
|
SHA-256 checksum How to use checksums |
8e16306b425caee36432b0bf440e25bc4df6e1e85b11b9523441df2587252953
|
|
BLAKE2b-256 checksum How to use checksums |
d9ca98f1ca6fae2545bf484aa7bf49ed1a1c9323c6f242a38bd2539bbeffb307
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
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.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 8, 2026.
Transparency logRelease files / augrs_py-0.1.0-cp39-abi3-macosx_11_0_arm64.whl
| Download URL | augrs_py-0.1.0-cp39-abi3-macosx_11_0_arm64.whl |
|---|---|
| Size | 1.4 MB |
| Tags | CPython 3.9 abi3 macOS 11.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
5126c82f589802b3fecb12be4da0c82ab6ec8bb8cfcc832921828f61a224f578
|
|
BLAKE2b-256 checksum How to use checksums |
7dde20a00324cbad087dcbb19c12bebd5dd1a192ed7e6c73604b84a14910259f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
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.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 8, 2026.
Transparency logRelease files / augrs_py-0.1.0-cp39-abi3-macosx_10_12_x86_64.whl
| Download URL | augrs_py-0.1.0-cp39-abi3-macosx_10_12_x86_64.whl |
|---|---|
| Size | 1.7 MB |
| Tags | CPython 3.9 abi3 macOS 10.12+ x86-64 |
|
SHA-256 checksum How to use checksums |
71466e70621b193ad06b8271be3b126af2c03865792083f09ae24987f2748777
|
|
BLAKE2b-256 checksum How to use checksums |
73e6ee5f745d3d058aff35b6d48c50cc39aef32f57313ea729bc2f275a4c5bfa
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
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.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 8, 2026.
Transparency log