Normalize Depth
Every depth map is a mess of arbitrary ranges — this is the node that fixes it
- depth_map
- normalized_depth
- range_report_json
If you've ever plugged a fresh depth map into a ControlNet and gotten mush, the problem usually isn't the model - it's the range. MiDaS gives you one scale, Depth Anything another, Marigold something in between, and a raw estimator can spit out values from -3 to 47. Depth Normalize exists because almost everything downstream in this pack assumes depth lives in [0, 1], and most of the time yours doesn't. It's the gateway node of the whole toolkit: wire it right after your depth estimator and every other node here behaves.
How it works
The node reads your depth as a single grayscale channel (Rec. 709 luma weighting) and rescales it per image, so a batch of frames each get their own sane range instead of sharing one global stretch. Pick a method:
- Percentile (default) - clips the histogram at your
lowandhighpercentiles, then stretches what's between to 0–1. Robust to one hot pixel or one black hole in the image. - Min-max - stretches the full min/max. Fast and obvious, but a single outlier owns the whole range.
- Fixed range - treats
lowandhighas literal depth values and maps that band to 0–1. For when you know your estimator's absolute scale (ZoeDepth-style metric depth) and want to pin it.
invert flips white/black - some estimators output far-as-white, and downstream nodes in this pack assume near-as-white unless you tell them otherwise. gamma applies a curve via pow(x, 1/gamma); a gamma under 1 brightens the midtones, which is your fine-tune for "my foreground washes out."
Inputs and outputs that matter
Realistically you set three things: method, low/high, and invert. The defaults (Percentile, 1/99, no invert) are a genuinely good starting point - don't touch them until you have a reason.
Outputs:
normalized_depth(IMAGE) - wire this into every other depth node: Depth Range Masks, Depth Cleanup, Depth Colormap, Depth to Surface Normal, and the 3D exporters.range_report_json(STRING) - per-imagelow/highactually used, plus method/invert/gamma. Throw it into a ShowText node if you want to audit what happened.
Install
From ComfyUI-Depth-Visualization by gokayfem (the author behind Decartunizer and ComfyUI-Texture-Simple). Easiest route is ComfyUI Manager: search for ComfyUI-Depth-Visualization and hit install. Or do it by hand:
cd ComfyUI/custom_nodes
git clone https://github.com/gokayfem/ComfyUI-Depth-Visualization.git
python -m pip install -r ComfyUI-Depth-Visualization/requirements.txt
Restart ComfyUI and the node lives under the depth/toolkit menu. The bright side of this pack: requirements are just numpy and Pillow, there are no model downloads, and it runs on CPU tensors. No new weights, no network calls.
Where people get burned
highmust be greater thanlow. The node raises aValueErrorif you swap them. It's the single most common head-scratcher.- Percentile is per image, not per batch. If you normalize a video as one batch, each frame gets its own stretch, which means brightness can breathe across frames. For per-clip consistency you want a
Fixed rangeafter eyeballing the min/max from one frame. - Don't skip it before mesh export. DepthToMesh and the parallax node both read raw values and assume
[0,1]; feeding them an un-normalized map gives you geometry that's all wrong scale or nothing at all. Normalize first, export second.
Inputs (6)
| Name | Type | Default | Description |
|---|---|---|---|
| depth_map | IMAGE | — | |
| method | COMBO | 3 options: Percentile, Min-max, Fixed range | |
| low | FLOAT | 1.00–100 | — |
| high | FLOAT | 99.00–100 | — |
| invert | BOOLEAN | false | — |
| gamma | FLOAT | 1.000.05–8 | — |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| normalized_depth | IMAGE | — |
| range_report_json | STRING | — |