Nodes/ComfyUI CV/CV DNN Forward
ComfyUI Node

CV DNN Forward

Load an ONNX model and run it, in one node

By bmad4ever·Created 4 months ago·Updated 14 days ago· 1
CV DNN Forward
  • blob
  • output
◄model▾►
◄output_layer►
◄backendauto (default backend)►
◄targetauto (default target)►
◄engineauto (default engine)►

CV DNN Forward loads an ONNX model with cv2.dnn.readNetFromONNX and runs a forward pass on the blob you feed it. It's the inference step of the generic three-node ONNX pipeline: CV DNN Blob From Image → this → CV DNN Images From Blob.

Reach for it when you have an .onnx file and want to run it inside ComfyUI without writing a node: a super-resolution or denoise network, a style transfer model, a custom head you exported yourself. It's the box the pack's whole DNN section is built around.

One honest framing first, from the pack's own README: ComfyUI often already does this better. Everything here goes through cv2.dnn on principle - that's the point of the pack - and the cost is that it runs on the CPU, without the fp16, offloading and batch handling a native PyTorch node gets. If core ships a node for your job, use core. This is for reaching models core doesn't support, or for seeing how the pieces fit.

How it works

The net is loaded, the blob is set as input, one forward pass runs. The forward pass happens in the pack's interruptible DNN worker, so a long inference can be cancelled from the UI instead of wedging the queue - a small thing that turns into a large one the first time you run a big model by accident.

output_layer picks which layer's output you get back. Blank means the model's default output, which is right for most single-head models. Name a layer and you get that layer's tensor instead. Note that some models have several unconnected outputs - a detection tensor plus a mask prototype, for instance - and this node fetches one. CV DNN Forward All is the multi-output variant.

Inputs and outputs

Required: blob - an (N, C, H, W) NCHW array from CV DNN Blob From Image, or any correctly-shaped float array you built yourself - and model, an ONNX file from ComfyUI/models/onnx.

Optional: output_layer (blank = default), plus the three "advanced" widgets - backend, target and engine. Read the tooltips before you get excited, because on this build they mostly do nothing:

  • backend / target are honoured only on the classic DNN engine. OpenCV 5.1 removed that engine, this wheel is built without CUDA and without OpenVINO, and it reports haveOpenCL() == False. The graph engine ignores the setting entirely and says so in a log line.
  • engine picks the engine at load time: OpenCV 5.0 offered classic and new graph, 5.1 merged them into one. ONNX Runtime needs a build compiled with WITH_ONNXRUNTIME=ON and otherwise falls back with a warning. A workflow saved with an engine your build lacks gets remapped and logs it - it doesn't silently become auto.

The historical note in the tooltip is the most interesting thing in the node: on the 5.0 classic engine, OpenCL was a per-model lottery and usually a loss. SqueezeNet got 3.6x faster, but YuNet came out 14x slower - partly because that build's OpenCL kernel for dnn/activations failed to compile and those layers fell back per-layer with a device round trip each way. If you remember people saying "try OpenCL, it's faster", that's the context for why it often wasn't.

Output: output, the raw network tensor, NCHW for image models. Feed it to CV DNN Images From Blob to get a picture, or Inspect CV Data to just look at the shape - which is the fastest way to debug a model you've never run before.

Install

From comfyui_cv (bmad4ever/comfyui_cv). ComfyUI Manager → "ComfyUI CV", or:

cd ComfyUI/custom_nodes
git clone https://github.com/bmad4ever/comfyui_cv
pip install "opencv-contrib-python-headless~=5.0.0.93"

Restart ComfyUI. Python ≥ 3.12, V3-API ComfyUI.

Models don't ship. Put .onnx files in ComfyUI/models/onnx - the dropdown only lists what's there - and get URLs, licences and target folders from the pack's model_sources.txt. The pack's models come from the OpenCV Zoo collection among others; check licences before redistributing anything, since a couple are stricter than the pack's own GPL-3.0.

Common issues

  • The model file isn't in the dropdown. Wrong folder, or ComfyUI wasn't restarted. It's ComfyUI/models/onnx, not models/diffusion_models.
  • readNetFromONNX fails on a perfectly valid export. Documented and expected: OpenCV's DNN implementation supports a limited slice of modern architectures, and conversion to ONNX is sometimes not sufficient. The pinned OpenCV version limits this further. If it won't load, it won't load - that's not a bug you can configure away.
  • The output is garbage. Almost always preprocessing upstream (scale, means, channel order). See CV DNN Blob From Image.
  • The output isn't an image at all. Detection and segmentation heads return tensors, not pictures. CV DNN Forward All plus CV DNN Pick Output and a decoder is the workflow.
  • You have a multi-output model and only get one tensor. Use CV DNN Forward All.
  • You're running a model ComfyUI has a native node for. Stop, and use the native node. Same conclusion the pack's own README reaches about its frame-interpolation example.
Categoryimage/CV/dnn

Inputs (6)

NameTypeDefaultDescription
blobNPARRAY(N, C, H, W) NCHW input blob from 'CV DNN Blob From Image' (or any NCHW float array).
modelCOMBOONNX model file from ComfyUI/models/onnx to run.
output_layeroptSTRINGName of the output layer to fetch. Blank = the model's single / default output (right for most models).
backendoptCOMBOauto (default backend)Compute backend (cv2.dnn.setPreferableBackend). 'auto' leaves the net on its default and is right for almost every model. Only backends present in the loaded build are listed, but PRESENT IS NOT USABLE: this wheel is built without CUDA and without OpenVINO, so 'CUDA' and 'Inference Engine' raise on the classic engine. The GRAPH engine ignores this setting entirely (it warns 'Back-ends are not supported by the new graph engine for now'), and only the CLASSIC engine honoured it - OpenCV 5.1 removed that engine, so on this build the widget has NO effect on any model.
targetoptCOMBOauto (default target)Compute target / device (cv2.dnn.setPreferableTarget). 'auto' leaves the net on its default (CPU). Honoured on the CLASSIC engine only - OpenCV 5.1 removed that engine, and this build also reports haveOpenCL() == False, so the widget currently does NOTHING (squeezenet times identically across every target). HISTORICAL, on the 5.0 classic engine: OpenCL was a per-model lottery and usually a LOSS - squeezenet 3.6x faster, but yolo26n-seg 0.73x, EAST 0.68x, RAFT 0.26x and YuNet 0.07x (14x SLOWER), partly because that build's OpenCL kernel for 'dnn/activations' failed to compile and those layers fell back per-layer with a device round trip each way.
engineoptCOMBOauto (default engine)DNN engine passed to cv2.dnn.readNetFromONNX, chosen once at model load time. WHICH OPTIONS EXIST DEPENDS ON THE BUILD: OpenCV 5.0 offered 'classic' (the 4.x per-layer engine) and 'new graph'; 5.1 merged them into a single 'OpenCV (built-in graph)' - the graph engine - so there 'auto' is the only meaningful choice. 'ONNX Runtime' needs a build with WITH_ONNXRUNTIME=ON and otherwise falls back to the built-in engine with a warning. A workflow saved with an engine this build lacks is remapped and logs a warning - it does not silently become 'auto'.

Outputs (1)

NameTypeDescription
outputNPARRAYThe raw output blob from the network (NCHW for image models). Feed 'CV DNN Images From Blob' to turn an image output back into a picture, or 'Inspect CV Data' to see its shape.