Image Router (liked/disliked)
The end of the judge pipeline that splits liked from disliked
- image
- liked
- disliked
- info
Every scoring pipeline ends the same way: you've got a batch of images and a list of booleans, and you need the good ones separated from the bad ones. Image Router is the final stage of the CCIP Judge pack - the node that takes your batch plus a pass_mask and hands you two clean outputs: liked and disliked.
It's deliberately more than a filter. The author's stated design goal is that the liked output feeds straight into downstream nodes like IPAdapter - no saving to disk and reloading in between. Both outputs are always IMAGE tensors, and here's a detail people love once they notice it: when a branch is empty, the router doesn't emit a fake black image. It emits ComfyUI's ExecutionBlocker, which stops that branch from executing at all. No garbage black frames polluting your pipeline, no wasted inference.
What it does when you ask it to save
save_liked_dir/save_disliked_dir- where each branch gets written. Leave empty and it skips saving that side entirely. Use dedicated directories, not the same folder as your reference images - the README says so, and it means the "clear" button won't nuke anything precious.liked_prefix/disliked_prefix- filename stems, defaulting toliked/disliked. They're sanitized so a widget value can never contain a path or traversal sequence - the node forces prefixes to be plain filename stems. Saved files embed the original batch index ({prefix}_idx00042_...png), which is how you trace a specific generation back to its verdict.clear_dirs_before_save- a careful reset: it deletes only the files this node wrote before ({prefix}_idx*.pngandscores_*.csv), never your other files in the same folder.csv_dir- writes ascores_*.csvreport when you connect the optional score inputs. This is your batch's audit trail.- It never overwrites - on a filename collision it appends a numeric suffix. Run the same batch twice and both result sets survive.
The inputs that matter
Required: image (the batch), pass_mask (from Three-Stage Filter, or a scorer's mask if you're doing a single-metric run), the save settings above, and the three thresholds (ccip_threshold, oks_threshold, angle_threshold) - those thresholds are what the CSV report uses to mark each row pass/fail.
Optional: ccip_distance, oks, angle_distance, plus pose_reasons and angle_reasons from the OKS/Angle scorers. Wire them up and the CSV becomes genuinely useful - it records per-image scores, the failure reasons, and empty cells plus a detect_failed flag for NaN images. That CSV is the backbone of the pack's optional Optuna threshold-search script, but you don't need any of that for normal use.
Outputs: liked, disliked (IMAGE), and info (a summary string). Wire liked into a Save Image node, a preview, or straight into whatever eats images next.
Installing
cd ComfyUI/custom_nodes
git clone https://github.com/o-ankomochi-o/comfyui-ccip-judge.git
cd comfyui-ccip-judge
python -m pip install -r requirements.txt
Or search "CCIP Judge" in ComfyUI Manager. Python 3.10–3.12, don't double-install onnxruntime and onnxruntime-gpu, and the DWPose model fetches from Hugging Face on the first scorer run.
Where people get burned
- Length mismatch. The router compares image count to
pass_masklength and errors loudly if they differ - usually a stale cache or a scorer you re-ran with different settings mid-pipeline. Rerun the whole graph. - Security hygiene. Save directories and
reference_folderare arbitrary local paths your ComfyUI process can read and write. Before running a workflow you didn't build, check the path fields - the README treats this as a real concern, not theater. - Group shots still get routed by whoever has the biggest bounding box upstream, and the router won't save you from that - fix it at the scorer stage.
Inputs (19)
| Name | Type | Default | Description |
|---|---|---|---|
| image | IMAGE | — | |
| pass_mask | BOOLEAN | — | |
| save_liked_dir | STRING | — | |
| save_disliked_dir | STRING | — | |
| liked_prefix | STRING | liked | — |
| disliked_prefix | STRING | disliked | — |
| clear_dirs_before_save | BOOLEAN | false | — |
| csv_dir | STRING | — | |
| ccip_threshold | FLOAT | 0.2130–2 | — |
| oks_threshold | FLOAT | 0.500–1 | — |
| angle_threshold | FLOAT | 0.500–5 | — |
| ccip_distanceopt | FLOAT | — | |
| oksopt | FLOAT | — | |
| angle_distanceopt | FLOAT | — | |
| pose_reasonsopt | STRING | — | |
| angle_reasonsopt | STRING | — | |
| reach_dopt | FLOAT | — | |
| gate_statusopt | STRING | — | |
| gate_reasonopt | STRING | — |
Outputs (3)
| Name | Type | Description |
|---|---|---|
| liked | IMAGE | — |
| disliked | IMAGE | — |
| info | STRING | — |