- Python 94.9%
- Shell 4%
- Dockerfile 1.1%
| .devcontainer | ||
| .scripts | ||
| .vscode | ||
| docs | ||
| src/relief | ||
| tests | ||
| .gitignore | ||
| .python-version | ||
| LICENSE | ||
| pyproject.toml | ||
| README.md | ||
| uv.lock | ||
Relief
Image-to-bas-relief pipeline for relief masters. The project accepts an input image, removes the background, crops to the foreground, estimates depth, converts that depth into a height field, and exports a watertight STL plaque that can be CNC machined, 3D printed, or used as the master for later mold/cast workflows.
The long-lived implementation notes are in docs/implementation-plan.md.
What This Repo Builds
- custom file input support
- background removal with
rembg - monocular depth estimation with
depth-anything/DA3-LARGE-1.1 - tunable relief height, smoothing, and detail emphasis
- watertight mesh export for CNC, printing, or downstream mold/casting workflows
Why These Defaults
rembgis used because it is simple to automate and stable.- The depth backend is
depth-anything/DA3-LARGE-1.1. - The code path is intentionally simple: masking stage, depth stage, height-map stage, mesh stage.
Devcontainer Setup
- Open the repository in VS Code.
- Run
Dev Containers: Reopen in Container. - Wait for the bootstrap to finish. It will:
- install Python with
uv - sync project dependencies
- install the pinned external
depth-anything-3package into the venv
- install Python with
The devcontainer requests GPU access with --gpus=all. On a WSL host this still depends on Docker Desktop plus NVIDIA container runtime support being available on the machine.
If you are not using the devcontainer, run:
./.scripts/bootstrap.sh
Verify The Environment
uv run relief doctor
If CUDA is available, the doctor command will report it and the depth model will use the GPU when --device auto or --device cuda is selected.
Run The Pipeline
uv run relief build IMG_2949.jpeg --output-dir outputs/demo
Useful tuning options:
uv run relief build IMG_2949.jpeg \
--output-dir outputs/demo \
--height-mm 7 \
--base-mm 3 \
--size-mm 140 \
--detail-strength 0.35 \
--smooth-radius 1.0 \
--gamma 0.9 \
--mesh-resolution 448
If a particular image comes out inside-out, flip the relief orientation:
uv run relief build IMG_2949.jpeg \
--output-dir outputs/demo-inverted \
--invert-depth
Outputs
Each run writes:
masked.pngmask.pngcropped.pngcropped-mask.pngdepth.npydepth-preview.pngheightmap.npyheightmap.pngrelief.stlmanifest.json
Key Parameters
--height-mm: maximum added relief above the base--base-mm: flat backing thickness--size-mm: physical size of the longest side of the plaque--detail-strength: how much local high-frequency depth detail to reintroduce--smooth-radius: Gaussian smoothing radius in pixels on the working depth map--gamma: tonal shaping for the normalized relief--mesh-resolution: downsample target for STL generation to control mesh weight--device:auto,cuda, orcpu--invert-depth: optional polarity flip if a particular image reads inside-out
Notes On Manufacturing
- The exported STL is a rectangular plaque with a flat back and continuous side walls.
- Background areas remain at base thickness so the mesh stays watertight.
- The primary output is the relief itself, suitable as a direct manufacturing target or as a master pattern for mold-making.
- Monocular depth is relative rather than physically measured, so the post-processing controls are where most of the final “relief look” is tuned.