Nodes/ComfyUI-Image-Filters/Normal Map (Simple)
ComfyUI Node

Normal Map (Simple)

A normal map from a flat image, no depth model needed

By spacepxl·Created 3 years ago·Updated 8 months ago· 293
Normal Map (Simple)
  • images
  • IMAGE
scale_XY1.000

Most normal maps in a ComfyUI graph come from a model - Depth Anything, a ControlNet preprocessor, something that actually understands 3D. Normal Map (Simple) doesn't do any of that. It runs a Scharr operator (a classic edge-detection kernel, the sharper cousin of Sobel) over the image to estimate how the surface tilts in x and y at every pixel, then packs those gradients into the usual normal-map colors - no model, no depth pass, just math on the pixels you already have.

That's both the appeal and the limit. It's instant and it needs nothing downloaded, but it only sees local contrast - the fine texture on a surface, not the surface's actual shape. Depth estimators like Depth Anything can also derive normals (a normal map is literally the spatial gradient of a depth map), but they know a face is a sphere-ish shape and a wall is flat. This node has no such idea. Feed it a photo of a face and you get normals that follow the skin texture and the shading already baked into the image, not the underlying geometry of a head. It's honest about that in the name: "Simple," high-frequency only.

What you feed it and what you get back

Two inputs, both required:

  • images (IMAGE) - whatever you want a pseudo-normal-map from. Works on generated output, photos, textures.
  • scale_XY (default 1, 0–100) - how strongly the x/y gradients push the normal away from pointing straight at the camera. Low values give you a nearly flat blue normal map (subtle bump); crank it up and you get exaggerated, almost embossed-looking surface detail.

One output: IMAGE - the normal map, in the standard tangent-space color convention (blue-ish where flat, red/green shifts where the surface tilts). Wire it into this same pack's Relight (Simple) node for a quick dot-product relight, or into Convert Normals if you need a different normal-map color-space convention downstream.

How to install it

Through ComfyUI Manager: search "ComfyUI-Image-Filters", install, restart. Or by hand:

cd ComfyUI/custom_nodes
git clone https://github.com/spacepxl/ComfyUI-Image-Filters

then restart ComfyUI. The pack's only real dependency is OpenCV - specifically opencv-contrib-python, which the author notes covers every variant the pack needs. If you install manually and see cv2 import errors on startup, that's almost always a version conflict from another node pack pulling in a different opencv variant, not this pack being broken; the author ships install.bat / import_error_install.bat on Windows to uninstall every opencv variant and reinstall the matching set, and on Linux the equivalent fix is uninstalling the stray opencv packages and installing opencv-contrib-python on its own. No model files, no VRAM cost - this node is pure numpy/opencv, so it's essentially free to run.

Common issues & troubleshooting

The normal map looks almost flat / does nothing when relit. scale_XY at the default of 1 is conservative on a low-contrast image. Push it up - there's real headroom to 100 - until you see the surface detail you expect.

Relighting off this looks like the texture is being shaded, not the object. That's expected, not a bug. This node has no concept of macro-scale shape - it's reading local pixel gradients, so a relight built on it will shade fine detail (fabric weave, skin pores, brush strokes) convincingly while getting the big picture wrong (it won't know the object curves away from the light). If you need a relight that respects actual scene geometry, you want a real depth-to-normal pass first, or a diffusion-based relighter that understands the whole image, not this node's math-only shortcut.

Output looks noisy on a busy/high-frequency image. The Scharr operator amplifies whatever local contrast exists, including compression artifacts and generation noise. A light blur pass (this pack's own Blur Image (Fast) node) before feeding into NormalMapSimple can clean that up if the noise is dominating over the detail you actually want.

CategoryImage-Filters/image

Inputs (2)

NameTypeDefaultDescription
imagesIMAGE
scale_XYFLOAT1.0000–100

Outputs (1)

NameTypeDescription
IMAGEIMAGE