Nodes/Portrait Dataset Tools/Upscale If Smaller (model upscale only when needed)
ComfyUI Node

Upscale If Smaller (model upscale only when needed)

Don't spend GPU time on photos that were already big enough

By BillyBGit·Created 23 days ago·Updated 22 days ago· 1
Upscale If Smaller (model upscale only when needed)
  • image
  • upscale_model
  • image
  • was_upscaled
◄min_short_edge1024►

What it is

A one-line concept with real consequences: if the image's short edge is at least min_short_edge, pass it through untouched. If it's smaller, run an upscale model on it. Two outputs, one of which is a boolean telling you which happened.

The reason you want this in a dataset pipeline is that datasets aren't uniform. Yours has a 3000px raw and a 600px scan of a print. Without a gate you either run both through a 4x ESRGAN model - which is a genuine waste of time and VRAM on the big one, and worse, does nothing you wanted - or you split the set into two workflows and hold the whole thing in your head. This node is what lets one crop chain serve both.

How it works

It's about as plain as a node gets. Read h, w from the tensor, compare min(h, w) to min_short_edge, and if it passes the test, return the input tensor plus False. Otherwise call the core ImageUpscaleWithModel implementation with your model and return the result plus True. There's no tiling, no ratio calculation, no post-pass resize.

Note what that means: it's the cheap rung of the upscaling ladder. A model upscale is a fixed, well-behaved transform - it multiplies pixels, it doesn't invent identity. That's exactly what you want for making a small crop usable, and exactly the wrong tool for repairing damage; that job belongs to restoration models, which rewrite faces. For a training set, size is a mechanical problem and this node treats it as one.

Inputs, outputs, wiring

image, upscale_model (a UPSCALE_MODEL, so it comes from the core UpscaleModelLoader - nothing in this pack ships a model), and min_short_edge (default 1024).

Outputs: image and was_upscaled. That boolean is genuinely useful - log it, count it, or use it downstream as a "this one is synthetic detail" marker. A crop that came from a 4x model on a 300px source is not the same evidence as a native 2400px one, and knowing which is which while you're curating is half the battle.

Typical wiring in this pack's example workflow: FaceAlignCrop (target_size: native) → UpscaleIfSmaller gated at 1024 → a plain resize node to take everything to 1024×1024 lanczos → the tone and texture stages. The 4x model in that workflow is 4xFaceUpSharpDAT, i.e. a face-trained ESRGAN-family model, which is the sensible choice when you already know the subject is a head.

Install

ComfyUI Manager: search Portrait Dataset Tools. Manual:

cd ComfyUI/custom_nodes
git clone https://github.com/BillyBGit/ComfyUI-PortraitDatasetTools
pip install -r ComfyUI-PortraitDatasetTools/requirements.txt

The pack's stated dependencies are insightface, opencv-python, numpy, Pillow and onnxruntime - this node itself only needs the core ComfyUI upscale path, which is why the pack's README is short on model downloads. It doesn't ship an upscale model; you load your own.

Where people get burned

It never downscales. Big images pass through at full size, which is correct - but it means a 6000px portrait hits the next node in the chain at 6000px. If you're feeding that into a diffusion pass rather than a resize, you'll find out about it as an OOM. Follow it with the resize you already planned.

Near-threshold inputs are the expensive ones. A 4x model on a 1000px crop produces 4000px, and the peak cost scales with output pixels, not input. Reading pixel counts: a 4x upscale is 16× the pixels of its input, so the worst case is always the image that just failed the gate. If your card is tight, raise min_short_edge or use a 2x model.

The model loader isn't lazy. upscale_model is wired from an UpscaleModelLoader, and that loader node will run regardless - it loads weights into VRAM before anything decides whether they're needed. This node saves the upscale pass, not the model load. Pair it with LazyImageSelect if the loader feeding it is also plugged into other branches.

"Upscaling before fixing defects bakes artifacts", in the words of the standard upscaling checklist. Order matters: fix the face and the damage at native resolution, and let this node make small-but-clean crops bigger, not crooked-but-huge crops huge.

Categoryimage/upscaling

Inputs (3)

NameTypeDefaultDescription
imageIMAGE—
upscale_modelUPSCALE_MODEL—
min_short_edgeINT102464–8192—

Outputs (2)

NameTypeDescription
imageIMAGE—
was_upscaledBOOLEAN—