ComfyUI Node

Compute Defocus Map

Turning depth into a per-pixel blur recipe

By EricRollei·Created 8 months ago·Updated 4 months ago· 19
Compute Defocus Map
  • disparity_map
  • focus_point
  • defocus_preview
  • defocus_map
  • defocus_raw
blur_strength20.0
max_coc100
use_raw_disparityfalse
normalize_for_genfocusfalse

ComputeDefocusMap is where the refocus pipeline stops being about depth and starts being about blur. It takes a disparity/depth map and a focus point and computes, for every pixel, exactly how much it should be blurred based on its distance from the focal plane. The formula is gloriously simple:

blur = K × |depth − depth_at_focus|

where K is blur_strength, depth is the (normalized) depth at each pixel, and depth_at_focus is the depth value at your selected focus point. Everything at the focus depth gets blur 0 - perfectly sharp. Everything else gets blur proportional to how far it is in depth, capped at max_coc (the maximum circle of confusion, the blur-radius ceiling in real-photography terms). That one formula is the entire artistic control surface of the pack.

The three outputs, and why you should care which is which

  • defocus_preview - contrast-stretched to full 0–1 for visualization. This is what you look at.
  • defocus_map - the real normalized map, clamped at max_coc. This is what you feed to bokeh generation.
  • defocus_raw - the raw blur values before normalization. For debugging.

Mixing them up is the classic wiring error - the bokeh nodes want defocus_map, not the pretty preview.

The knobs that make the photograph

  • blur_strength (20) - K, how fast blur grows with depth difference. Subtle portrait: 10–20. Standard bokeh: 20–30. Dramatic tilt-shift: 40–60. Extreme shallow-DOF: 60–100.
  • max_coc (100) - the blur cap. 64 = gentle softening; 100+ = obvious separation; 200+ = very shallow DOF look.
  • use_raw_disparity (false) - if your input is unnormalized raw depth values instead of normalized 0–1, flip this. Default expects normalized.
  • normalize_for_genfocus (false) - the one that surprises people. The original Genfocus does not stretch its defocus map to full 0–1 - dark maps are the trained convention, and subtle bokeh is normal. If your map looks nearly black, that's often correct. Turn this on only if you want a stronger/different effect; it's explicitly experimental.

Where the inputs come from

disparity_map is typically the disparity_map or depth_map output from DepthPro Estimate (in relative mode), and focus_point comes from Select Focus Point or Focus Point From Mask. The output defocus_map feeds either Genfocus Bokeh (Native) directly or Genfocus Defocus Map Condition if you're driving Genfocus Generate yourself.

A reality check on "no change"

Even if your focus point matches the original photo's focus, bokeh generation will still slightly soften already-sharp areas - FLUX re-renders, and tiny depth differences still produce small blur values. If you want truly zero change in sharp regions, your defocus map has to be genuinely zero there; the preview output is how you verify.

Install

Part of the Refocus pack (ComfyUI Manager → "Refocus - Generative Refocusing", or clone into custom_nodes/). No models, no pip extras - pure numpy math. It works even before you commit to the FLUX download, which makes it the cheapest node in the pack to learn on.

CategoryRefocus/Defocus

Inputs (6)

NameTypeDefaultDescription
disparity_mapIMAGE
focus_pointFOCUS_POINT
blur_strengthoptFLOAT20.00–100K value - controls bokeh intensity (0 = no blur)
max_cocoptFLOAT1001–500Maximum circle of confusion (blur radius)
use_raw_disparityoptBOOLEANfalseIf True, expects raw disparity values. If False, expects normalized 0-1 depth.
normalize_for_genfocusoptBOOLEANfalseIf True, stretch defocus map to full 0-1 range for stronger bokeh. Original Genfocus uses False.

Outputs (3)

NameTypeDescription
defocus_previewIMAGE
defocus_mapIMAGE
defocus_rawIMAGE