seamless_blend(foreground_path, background_path, center_x, center_y, output_path, mode="normal"): Poisson image compositing viacv2.seamlessClone. Reads an RGBA foreground, reuses its alpha as the clone mask, auto-scales the foreground to fit the destination, and supports"normal"/"mixed"/"monochrome"clone modes. Exported from the top-level package. Opt-in —CapAugcontinues to default to plain alpha compositing.BEV.from_image_shape(shape, ...): construct a BEV transform without a calibration YAML. Synthesizes intrinsics from image dimensions (fx = fy = max(W, H), principal point at center). Paired with the new public helperintrinsics_from_image_shape(height, width).BEV()with no arguments still loads the packaged AXIS default — unchanged.BEV(calib_matrices=...): pass a pre-built{"camera_matrix": K}dict to bypass YAML loading.
dataset_tools/cityscapes/download_dataset.py: stdlib-only Cityscapes downloader usingCITYSCAPES_USERNAME/CITYSCAPES_PASSWORDenv vars.run.shgains a--downloadstep and auto-sources a gitignored repo-root.env;.env.exampleships as a template. Repo-only tooling, not part of the installed wheel.
- README:
seamless_blendlisted in the Public API; new "Without your own calibration" section coveringBEV.from_image_shapeand the no-perspectivebev_transform=Nonefallback.
max_overlapparameter onCapAug: skip pastes whose tight bbox exceeds the given IoU with any already-accepted bbox. Useful for dense placement where overlapping pastes would corrupt detection ground truth. DefaultNonekeeps the prior unrestricted behavior.
- Promoted Albumentations and Torchvision
DeprecationWarningandPendingDeprecationWarningto errors inpyproject.tomlfilterwarnings. Future upstream deprecations will fail the suite immediately rather than slipping through.
- Corrected the 0.4.0
CapAlbumentations.always_applynote: the field was removed by Albumentations 2.0.0, not a hypothetical 3.x. We had already required>=2.0.8, so the wrapper carried the alias longer than the underlying library supported it.
CapAlbumentations.always_applywas removed. The kwarg had been a deprecated alias forp=1.0since 0.2.x; Albumentations itself removed the field in 2.0.0 (we already require>=2.0.8), so the wrapper was kept around longer than the underlying library supported it. Passingalways_apply=...now raises aTypeErrorwith a migration hint pointing atp=1.0.
object_transformscallables that return a 4-channel image now raise a clearValueErrorinstead of silently broadcasting a (H, W) alpha against a (H, W, 4) source in the composite. The contract (alpha travels via the separatemaskargument, not the image one) is now explicit in the error message.
probability_mapis now normalised once and cached on theCapAuginstance instead of being re-summed and re-divided on every call. For a 1000×1000 map that's ~1 MB of per-call busywork avoided in tight training loops. The cached value is invalidated only by constructing a newCapAug— replace the array, don't mutate it in place.
probability_mapinputs withndim != 2now raise a clearValueErrorinstead of failing downstream innp.random.choicewith an opaque shape mismatch.
- Added end-to-end coverage for
image_format='rgb', thes_rangescale path (whenh_rangeis None), andCapAugMulticlasscomposed withbev_transform— three paths the audit flagged as untested. - Added
tests/test_notebooks.py: parses eachexamples/notebooks/*.ipynb, compiles every code cell (catches API-rename drift), and asserts cell outputs are stripped per repo convention. - CI now runs on macOS-latest and Windows-latest (Python 3.12) in addition to the Linux 3.10 / 3.11 / 3.12 / 3.13 matrix.
- Coverage reporting via
pytest-covon the Linux/3.12 job, with thecoverage.xmlartifact uploaded for inspection.
- Split
[all]into runtime extras and a new[dev]extra. Previouslypip install "cap-augmentation[all]"leaked black/ruff/build into user environments;[all]is now runtime-only, and contributors installpip install -e ".[test,dev]"to get the CI toolchain. [test]no longer carries black/ruff (moved to[dev]).
- Documented the default BEV calibration YAML (source camera + FOV + "placeholder, replace for production") inline in the YAML and in the README's BEV section.
- CONTRIBUTING.md gained a Releasing section and a coverage-reporting
command; pinned the CHANGELOG header format so
publish.yml's release-notes extractor doesn't silently produce empty notes.
- Dropped Python 3.9 support; minimum is now Python 3.10 (3.9 reached EOL in October 2025). CI matrix is now 3.10 / 3.11 / 3.12 / 3.13.
- The default soft-alpha composite now honors intermediate alpha values
on source PNGs. For sources with anti-aliased edges (most real
cutouts), pasted objects blend smoothly into the destination instead
of being hard-thresholded by the previous bitwise composite. Outputs
are bit-identical for sources with binary alpha (alpha ∈ {0, 255}),
which is what
dataset_tools/cityscapesproduces.
CapAug(..., rng=42)accepts an int seed ornumpy.random.Generatorfor local, reproducible randomness — no more seeding bothrandom.seedandnp.random.seedglobally.rng=None(default) preserves the legacy global-state behavior.CapAug(..., cache_size=...)caches decoded source PNGs. Default is unbounded; set0to disable, orNfor an LRU cap. Eliminates the per-pastecv2.imreadcost that dominated training-loop wall time.- Public type annotations on
CapAug,CapAugMulticlass,resize_keep_ar,ImageMaskTransform, and__version__. Shipspy.typedso mypy/pyright honor them. - New
OpaqueSourceWarning(exported) fires once per source path when CapAug detects a grayscale, 3-channel, or fully-opaque source — these silently paste the full rectangle as an "object", which is almost always a user error.
_align_columnspreserved float padding even when both inputs were integer, silently upcasting box arrays. Padding now usesnp.result_type(*inputs)so homogeneous integer inputs stay integer.- Pixel-mode now rejects non-integer ranges with an explicit error
pointing at
normalized_range=Trueorbev_transform=BEV(...). Previouslynp.random.randintsilently truncated floats — passing(0.0, 1.0)produced all-zero placements with no feedback. _match_histogramno longer routes through a misleadingcv2.COLOR_BGR2BGRAconstant + redundantbitwise_and; the RGBA array is reassembled directly from numpy slices.
- README gained sections on reproducibility (
rng=), the source-image cache,blending_coeffsemantics (now a "ghost factor" over soft alpha), and theOpaqueSourceWarningrationale. CapTorchvisiondocstring now spells out the target merge rules (when boxes / labels / masks / semantic_mask are appended vs. dropped vs. created from scratch). Locked with a regression test.
Documentation-only release.
- Reformatted all Python code blocks in
README.mdto PEP 8 / black-compatible style (kwargs on their own lines under multi-line calls, consistent list spacing[a, b], double-quoted strings, stdlib imports before third-party). - Fixed wrapper-install instructions: now show
pip install "cap-augmentation[albumentations]"instead of the editablepip install -e ".[albumentations]", matching the canonical install section. - BEV usage section explicitly states that
x_range/y_range/z_range/h_rangeare interpreted in metres whenbev_transformis set (was implicit before). - Marked
albu_transformsparameter as a deprecated alias ofobject_transformsin the README to match the code's docstring. - Removed a duplicate
### Usage with multiple classesheading; fixed typos ("cold be found", "cutted"). .gitignore: addedresults/for ad-hoc augmentation outputs.
CapAug.paste_objectno longer crashes when anobject_transformscallable crops or resizes the input. Previously the source dimensions were captured before the transform ran, so the post-transform mask was sliced with stale ROI bounds and OpenCV failed with a size-mismatch assertion. The transform is now applied first, and shape-changing transforms that return mismatched image and mask sizes raise a clearValueError.- Returned bounding boxes are now tight against the visible (alpha > 0) region of the pasted object rather than the source canvas. PNGs with transparent padding (e.g. a 20×20 file containing a 10×10 visible object) used to yield a box covering the full canvas; the box now matches the pixels that actually changed in the destination. Behaviour is unchanged for fully opaque sources.
- Returned mask is sliced to the same tight region as the new bbox, so multiclass aggregation and instance-mask blits stay aligned.
CONTRIBUTING.mdnow tells contributors to also upgradesetuptoolsandwheelwhen bootstrapping the dev venv.python -m venvseeds a pinned old setuptools thatpip-auditflags for known CVEs; the project build itself usessetuptools>=68(seepyproject.toml [build-system]) so this only affects the dev environment, but it removes the noise.- Added
rufflint to the project and CI (tool.ruffconfig inpyproject.toml,ruff checkstep in.github/workflows/test.yml,ruff>=0.6in the[test]and[all]extras). Auto-fixed 21 findings: removed 2 genuinely unused imports (dataset_tools/cityscapes/filter_dataset.py:Path,dataset_tools/vinbig/generate_dataset.py:os), modernisedsuper(Cls, self).__init__andclass Foo(object), sorted imports, and dropped redundant# coding: utf-8declarations.
- Expose
cap_augmentation.__version__(read from installed package metadata viaimportlib.metadata). - Make
.github/workflows/publish.ymlidempotent by passingskip-existing: trueto the PyPI publish action; re-tagging an already-published version no longer fails the workflow.
- Renamed public classes to PEP 8:
CAP_AUG→CapAug,CAP_AUG_Multiclass→CapAugMulticlass,CAP_Albu/CAP_Albumentations→CapAlbumentations,CAP_TorchVision→CapTorchvision. No backward-compatible aliases. - Renamed
dataset/→dataset_tools/to disambiguate from the runtimedata/directory. - Renamed
dataset/vb/→dataset_tools/vinbig/(long form matches the upstream VinBigData dataset name). - Renamed wrapper modules:
wrappers/albumentations.py→wrappers/albu.py,wrappers/torchvision.py→wrappers/tv.py,wrappers/generic.py→wrappers/image_mask_transform.py. Public imports fromcap_augmentationare unchanged. - Renamed packaged calibration:
bev/camera_intrinsic_params.yaml→bev/default_calibration.yaml. - Moved demo assets: top-level
example_images/→examples/images/. - Renamed demo notebooks:
test_generation.ipynb→bev_and_pedestrians_demo.ipynb,test_generation_vbd.ipynb→vinbig_demo.ipynb. - Renamed Cityscapes runner:
generate_and_filter_dataset.sh→run.sh.
- Renamed GitHub repository
CAP_augmentation→cap-augmentationto align with the PyPI distribution name. The old URL redirects.
- Removed dead
src/cap_augmentation/bev/config.py; inlined the default camera intrinsics/extrinsics intobev/bev_transform.py. - Split
tests/test_dataset_scripts.pyintotests/test_dataset_cityscapes.pyandtests/test_dataset_vinbig.py. - Replaced the original author's hardcoded VinBig paths in
dataset_tools/vinbig/config.pywithNoneplus startup assertions. - Added
.topytest.pythonpathsodataset_tools.*imports resolve in tests. - Updated README, CONTRIBUTING, and the CI workflow to reflect every rename.
- Restructured the project into an installable
src/cap_augmentationpackage. - Added tests for the augmentation core, BEV helpers, dataset scripts, and wrappers.
- Added optional Albumentations and Torchvision integrations.
- Moved example notebooks under
examples/notebooks/. - Reduced repository size by stripping notebook outputs and replacing large example PNGs.