Imgutils JSON Filter
Re-Threshold a Tagger's JSON Without Re-Running the Model
- json
- tags
- count
Every tagger in the imgutils pack bakes its threshold in at the node - and then hands you the full scored distribution in its json output anyway. Imgutils JSON Filter is for when you want a different cutoff than the one the node used, without paying to run the model again: feed it that scored JSON dict, set a threshold, and get back a filtered JSON, a prompt-ready tag string, and a count.
Why you'd reach for it
The taggers give you two outputs: tags (already thresholded, comma-separated) and json (the full score map). The tags output is the default view; JSON Filter is the "reconsider" view. Maybe the node's threshold was too loose and your prompt is drowning in junk tags. Maybe you want a stricter list for a LoRA caption than for a fun prompt. Maybe you want the top N tags by score. All of that is a filter away instead of a re-inference. The KB's captioning material (lora-training, llm-in-comfyui) keeps hammering that tag quality is dataset quality - a stricter secondary threshold is a legitimate cheap upgrade to your captions.
How it works
The node accepts a JSON dict of {key: score}. It's smart about one structural wrinkle: the sectioned taggers (WD14, Camie, DeepDanbooru, DeepGelbooru) emit {"rating": {...}, "general": {...}, "character": {...}} - nested dicts. JSON Filter flattens those into one flat map, keeps only entries whose score is >= your threshold, sorts by score descending, and builds the outputs.
The interface
json(STRING) - the scored dict, e.g. a tagger'sjsonor a classifier'sjsonoutput.threshold(FLOAT, default 0.5, 0–1, step 0.01) - minimum score to keep.- Outputs:
json(the filtered dict, sorted),tags(keys joined with commas - this is your prompt-ready string),count(INT, how many passed).
Honest take
Two things to know. First, the flattening loses your rating/general/character sectioning - fine for building a prompt, wrong if you specifically needed the sections separated (use the tagger's own tags output for that). Second, count is quietly the most useful output here: it turns "how many tags survived" into a signal you can gate on. "Fewer than three tags at 0.6 → this is probably a blank or degenerate frame → skip it." That's a real dataset-cleaning move.
Install
cd ComfyUI/custom_nodes
git clone https://github.com/xiaden/comfyui-imgutils.git
cd comfyui-imgutils
pip install -r requirements.txt
Or via ComfyUI Manager (search "imgutils"). Needs ComfyUI >= 0.25.0 and Python >= 3.10; dependency is dghs-imgutils[gpu]. No model, no downloads - it's pure dict filtering.
Troubleshooting
If the node returns an empty map on input you know is scored, check whether the scores are actually numeric - a serialized dict of strings (or a detections-style output) yields nothing after filtering. And if your tags output looks thin at the default 0.5, that's the threshold working as intended; drop it toward 0.3 and you'll watch the tag list fatten with noise, which is the tradeoff made visible.
Inputs (2)
| Name | Type | Default | Description |
|---|---|---|---|
| json | STRING | JSON string dict of {key: score} to filter. | |
| threshold | FLOAT | 0.500–1 | Minimum score to keep. |
Outputs (3)
| Name | Type | Description |
|---|---|---|
| json | STRING | — |
| tags | STRING | — |
| count | INT | — |