Skip to main content

RadVeil

Fast, verified face and ear anonymization for volumetric head imaging.
MRI and CT · NIfTI / DICOM / raw arrays · Rust core, Python API, C bindings, CLI

CI Release PyPI crates.io DOI License: Apache-2.0

Website · Documentation · Browser demo · Quickstart · Examples · Legal notes

MRHead sample, input after adaptive anonymization side view after face+ears with the ears cut voxels: region outlined brain (blue) and anonymization region (amber)
3D Slicer's public "MRHead" sample: input · adaptive · face + ears (ears cut) · the voxels that changed · the region (amber) vs the extracted brain (blue), 5 mm apart.

RadVeil finds the face the way an attacker would — by rendering the volume as a 3D portrait and running a face detector on it — removes it, and accepts the result only when the detector fails on the output. Ears are removed on request and located by measuring the surface, not by assuming an offset. Every voxel outside the anonymized region is preserved bit-exact: same datatype, same scaling, same header.

Quick start

pip install radveil                        # prebuilt wheels, no model download, no compiler
cargo install radveil-cli                  # or: the single-binary CLI
import radveil

report = radveil.deface_auto("t1.nii.gz", "t1_defaced.nii.gz", mode="adaptive")
# {'views_detected': 3, 'residual_detections': 0, 'eye_dist_mm': 63.1, ...}

# the pinna is biometric too — opt in (face-only remains the default)
report = radveil.deface_auto("t1.nii.gz", "t1_defaced.nii.gz",
                             region="face+ears", mode="adaptive", ear_mode="cut")
# rois: [{'label': 'ear_left', 'detected': True, 'protrusion_mm': 14.0}, ...]
radveil auto t1.nii.gz t1_defaced.nii.gz --report report.json

The face detector is built in: the MediaPipe BlazeFace and Face Mesh models (Apache-2.0) are embedded in the library and run by RadVeil's own small pure-Rust SIMD inference engine. There is no ML framework, Bazel or TensorFlow in the build, and no Python is needed for the CLI or C API. dlib is available in Python as an optional second detector or fallback (fallback_detector="dlib"); either way, the output is verified against the built-in detector too.

Why RadVeil

  • Attacker-model localization — no atlas, no registration. A 2D face detector on CPU-rendered surface views pinpoints the face, and per-pixel position maps lift the 2D landmarks into scanner space. Detections must agree in 3D across views (shape consensus) before anything is modified.
  • Closed-loop verification — the output is re-rendered and re-attacked from the detection views and a grid around them (verify_effort: fast, balanced, thorough). Blur escalates, and an opaque fill guarantees termination. If no plausible face exists (non-head data, already-defaced scans, a "face" on a field-of-view cut) it refuses loudly instead of modifying anything.
  • Skin-deep and auditable — the face region follows the measured skin (~4.5 mm deep, skin_depth_mm, chosen to stay above the skull). Only voxels inside the exported binary mask change.
  • Brain-aware — on the public SynthStrip evaluation set (201 scans processed, the rest refused) the face region touched the expert brain mask on none; median clearance 6.6 mm. The opt-in brain guard (brain_guard=True, --brain-guard) never modifies the brain or anything within 3 mm of it.
  • Zero tuning — geometric parameters auto-scale from the detected inter-eye distance; works across sequences, resolutions, storage orientations (LPS/RAS/oblique/wrong affines), head sizes, MRI and CT.
  • Fast, CPU-only — ~0.3 s per volume in a warm process, ~11 volumes/s batched on a laptop CPU (deployment, performance). SIMD kernels with runtime dispatch and a portable fallback.

Modes and regions

mode effect
adaptive (recommended) gradient-weighted averaging — the stronger a facial feature, the heavier the local kernel
blur Gaussian blur of the region
cut remove (fill with background: 0 on MRI, air on CT)
block opaque slab (also the guaranteed final escalation step)
region effect
face (default) face-aligned ROI, depth-anchored to the measured eye-skin surface
ears both pinnae, located by surface-protrusion detection
face+ears both; ear_mode can pick a different mode for the ears (e.g. adaptive face, cut ears)

The ear is a stable biometric identifier that survives most defacers, but no landmark model emits ear points. RadVeil ray-marches the volume into a surface height map, derives the scalp baseline by morphological opening, and detects each pinna as a protrusion blob of the right shape and position. Every ear ROI reports detected and protrusion_mm; an ear outside the field of view is flagged, never silently missed.

Opt-in refinements (all off by default):

option what it does
level_face measures the face skin along the level head axes, removing much more of the lower lip and chin
spare_air leaves background air bit-exact, roughly halving the changed volume
auto_threshold retries noisy, dim scans (e.g. infant T1s) at higher surface thresholds
partial_face handles axial slabs that cut through the face (no mouth in the field of view)

Details, measurements and every knob: parameters & tuning.

Interfaces

  • Python — deface_auto (file → file), deface_volume (in memory: DICOM series via any reader, raw arrays via Volume.from_array, uploads via Volume.from_bytes / to_bytes), deface_batch (multi-threaded cohorts), plus a step-by-step API (render / detect_landmarks / lift_landmarks / Volume.deface). anonymization_mask returns the region without modifying anything, for callers who process it themselves.
  • CLI — radveil auto (one step, --report JSON), radveil deskull (brain extraction), radveil conform, plus info | render | deface.
  • C — libradveil + radveil.h: radveil_deface_auto, radveil_anonymization_mask, radveil_deskull, and the low-level load / render / deface / save calls.
  • Bring your own detector — any callable returning 68 landmarks (detector=f(rgb, try_rotations)).

Brain extraction

radveil deskull / radveil.deskull() / radveil_deskull() write a binary brain mask, the skull-stripped volume, or both:

radveil deskull t1.nii.gz -o t1_brain.nii.gz --mask-out brain_mask.nii.gz
  • synthstrip (default) — the SynthStrip network (Hoopes et al., NeuroImage 2022) reimplemented in pure Rust with embedded weights (MIT). Works on any MRI contrast, CT and PET. Masks match the reference mri_synthstrip at Dice 0.992–1.000, in ~3.5 s on a 1 mm 256³ MPRAGE on a laptop CPU.
  • classical — model-free; a BET-style deformable surface for MRI (optionally anchored by the detected face), bone-enclosed soft tissue for CT.
  • rvbrain — experimental; loads your own smaller .rvb network (format in rvbrain.rs). No trained weights ship yet.
Method (SynthStrip eval set, mean Dice) All Worst contrast
synthstrip 0.969 0.955 (QIN T2)
classical --face (466 held-out) 0.798 0.298 (qT1)
classical (466 held-out) 0.682 0.298 (qT1)

radveil auto --brain-check reports how many brain voxels the anonymization touched and how close it came; the CLI exits with status 3 if any were modified, so a batch can stop on it.

If you publish results from the synthstrip method, please cite Hoopes et al., NeuroImage 260 (2022) 119474.

Guarantees and limits

  • Voxels outside the mask are bit-identical to the input (tested in CI on synthetic phantoms).
  • Output keeps the input datatype, scl_slope / scl_inter, affine and header. Header metadata is deliberately not scrubbed — that is your de-identification pipeline's job (legal notes).
  • Verification demonstrates resistance to the embedded detector class, not to every conceivable attack; the exported mask supports independent audit.
  • 3D volumes only (split 4D series first). CT is validated on synthetic Hounsfield phantoms; multi-subject CT evaluation is pending.

Building from source

cargo build --release                                   # core + CLI (+ C lib: -p radveil-capi)
pip install maturin && maturin develop --release        # Python module
cargo test --workspace --release && pytest tests/       # phantoms only, no data needed

Releases are automated from version tags: wheels, the CLI and the C library for Linux, macOS and Windows, with SBOMs and checksums (release.yml, RELEASING.md, SBOM). Contributions are welcome — see CONTRIBUTING.md; report vulnerabilities via SECURITY.md.

Citing

If RadVeil is part of your anonymization pipeline, please cite it — it makes your de-identification reproducible.

@software{radveil,
  author  = {Gródek, Piotr},
  title   = {{RadVeil: CPU-only face and ear anonymization for volumetric head imaging}},
  url     = {https://github.com/rAum/radveil},
  version = {0.1.1},
  year    = {2026}
}

A methods sentence you can adapt: "Facial and auricular surfaces were removed with RadVeil v0.1.1 (region="face+ears", mode="adaptive"), which verifies each output by re-rendering the volume and re-running the face detector; all voxels outside the anonymization mask are unchanged." Machine-readable metadata: CITATION.cff.

License

Copyright 2026 Piotr Gródek and the RadVeil contributors. Licensed under the Apache License, Version 2.0; see also NOTICE.

Bundled third-party components keep their own licenses (THIRD_PARTY_LICENSES.txt):

  • MediaPipe BlazeFace and Face Mesh model weights — © Google LLC, Apache-2.0, embedded in a converted format (provenance).
  • SynthStrip weights — Hoopes et al., MIT.
  • dlib (optional, Boost license) — defaults to dlib's CC0 5-point model; its research-only 68-point models are used only if you pass one explicitly.

A default install contains only permissively licensed components; see the commercial-use summary. No imaging data is contained in this repository: tests use synthetic phantoms, and the only rendered face (site/img/) is 3D Slicer's public "MRHead" sample, regenerated by tools/make_site_images.py.

Disclaimer

RadVeil is a personal, open-source project developed in the author's spare time, on personal equipment. It is not affiliated with, sponsored or endorsed by, and does not represent any current or former employer of the author; the views and code here are the author's own. Names of third-party projects (MediaPipe, SynthStrip, dlib, 3D Slicer) are used only to identify the components and data RadVeil uses and do not imply endorsement by their owners.

Generative AI tools were used in developing this project, including code, documentation and the website. All of it was reviewed by the author, who remains responsible for it.

RadVeil is provided "as is", without warranty of any kind (see the license). It is not a medical device, is not intended for diagnosis or treatment, and does not by itself make data compliant with any privacy regulation. You are responsible for validating it for your use case.

Metadata

Release files for radveil 0.1.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for radveil 0.1.1
File Size Uploaded Provenance
radveil-0.1.1.tar.gz 7.4 MB With provenance Details

Built distributions (wheels)

Table of built distributions (wheels) for radveil 0.1.1
File
radveil-0.1.1-cp39-abi3-win_amd64.whl CPython 3.9 abi3 Windows x86-64 Details
radveil-0.1.1-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl CPython 3.9 abi3 Linux glibc 2.17+ x86-64 Details
radveil-0.1.1-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl CPython 3.9 abi3 Linux glibc 2.17+ ARM64 Details
radveil-0.1.1-cp39-abi3-macosx_11_0_arm64.whl CPython 3.9 abi3 macOS 11.0+ ARM64 Details
radveil-0.1.1-cp39-abi3-macosx_10_12_x86_64.whl CPython 3.9 abi3 macOS 10.12+ x86-64 Details

Total release size: 47.8 MB

Release files / radveil-0.1.1.tar.gz

Download URL radveil-0.1.1.tar.gz
Size 7.4 MB
Tags Source
SHA-256 checksum
How to use checksums
2c009e6ecf60842cee8051fe229bfbbe62f55d488ce5c71a42fb9965446bb9a7
BLAKE2b-256 checksum
How to use checksums
27dc44976b1a0912639d3ea88910cae087b5bd2ac33e8ef059feebe359506625
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 25, 2026.

Transparency log

Release files / radveil-0.1.1-cp39-abi3-win_amd64.whl

Download URL radveil-0.1.1-cp39-abi3-win_amd64.whl
Size 8.1 MB
Tags CPython 3.9 Windows x86-64 abi3
SHA-256 checksum
How to use checksums
c125ca8f77ebbe00c94c813ea1084365dbc92bd2a30dcf65f2aca841e5015bc4
BLAKE2b-256 checksum
How to use checksums
8d69a871951d91942231bf467fd88e2c9bffb226700091bdd91b01dfd0c49f33
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 25, 2026.

Transparency log

Release files / radveil-0.1.1-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl

Download URL radveil-0.1.1-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Size 8.1 MB
Tags CPython 3.9 Linux glibc 2.17+ x86-64 abi3
SHA-256 checksum
How to use checksums
62c6050be9292c1805568c481525a8f2ff908f350404e242cd77195dce55e972
BLAKE2b-256 checksum
How to use checksums
58afb4df1e39467c8c6d9d8bb84f6dc514caa9cda48203e1c6694ea3edf5c6b4
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 25, 2026.

Transparency log

Release files / radveil-0.1.1-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl

Download URL radveil-0.1.1-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Size 8.0 MB
Tags CPython 3.9 Linux glibc 2.17+ ARM64 abi3
SHA-256 checksum
How to use checksums
dda7a775f5dc77779c91ab2f5358824698e23caad71e1437f4998d2e3efbd821
BLAKE2b-256 checksum
How to use checksums
f5140872c055e7b3c8dcceac19f093a6411a5994932f9fc439408b9a607a0aa5
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 25, 2026.

Transparency log

Release files / radveil-0.1.1-cp39-abi3-macosx_11_0_arm64.whl

Download URL radveil-0.1.1-cp39-abi3-macosx_11_0_arm64.whl
Size 8.1 MB
Tags CPython 3.9 abi3 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
f1fa2712911c04b108dcc6b6cf37472c646fa8be763d8b3e6caa24ad12c8514a
BLAKE2b-256 checksum
How to use checksums
beef2e12aba717b850be6ecf31d7e46a5f0ae835a6bace9ef0bb2facc546a16a
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 25, 2026.

Transparency log

Release files / radveil-0.1.1-cp39-abi3-macosx_10_12_x86_64.whl

Download URL radveil-0.1.1-cp39-abi3-macosx_10_12_x86_64.whl
Size 8.1 MB
Tags CPython 3.9 abi3 macOS 10.12+ x86-64
SHA-256 checksum
How to use checksums
72d0588d40728bbcd9c3c5dcb67a37e66ad3647f8fb1afdb5b42a3112ea65783
BLAKE2b-256 checksum
How to use checksums
99e782d78600376cc3e14c5b2946e725ee41fbc9e35fed51de3ac6182075748e
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 25, 2026.

Transparency log

Security for radveil 0.1.1

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.

Full provenance

All 6 files in this release have been uploaded with provenance metadata.

Select from 6 files

Attestation for radveil-0.1.1.tar.gz

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 25, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

0.1.1 This release

6 release files Full provenance

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