Superside Normalize Product
Same product, same frame, every SKU — local product normalization with no AI
- image
- image
- info
If you've ever set up detail crops on one product photo and watched them land on the wrong spot on the next SKU, this is the node that fixes your week. Superside Normalize Product takes a catalogue product shot and places the product into a consistent frame - same relative size, same margin, same position - so that a fixed set of crop boxes, drawn once, stays aligned across an entire catalogue. It detects the product against the light background locally, with no AI and no API key.
The trick that makes it work for catalogues: everything is relative. The product always ends up spanning the same fraction of the frame, so fractional crop coordinates (the kind a Manual Detail Sheet stores) mean the same thing on every image. Normalize first, draw your boxes once per profile (front, side, three-quarter), and the same callouts come out correctly on every SKU that goes through the same normalizer.
The inputs that matter
mode-keep resolution (pad)(default) orfixed canvas (scale). The default is the quality choice: it crops to the product and pads with the margin at native resolution, never downscaling. Output size varies per photo, but you lose nothing.fixed canvasscales into a set output_width × output_height - choose it when you need byte-identical canvas sizes across SKUs, and accept the possible downscale.margin_percent(default 8, 0–45) - empty margin around the product as a percent of the frame. This is what makes "always spans the same relative area" true.threshold(default 12, 1–128) - how different a pixel must be from the background (0–255) to count as product. Lower catches faint detail like thin metal; higher ignores soft shadows. This is the main dial if detection is grabbing too much or too little.background_hex- fill color for the output canvas. Leave empty to auto-sample the source photo's corner background (usually the right call for white-backdrop shots).output_width/output_height/fit- only used infixed canvasmode.fitiscontain(whole product),width, orheight.detect_pad_percent(default 2) - extra padding around the detected product before placing, as a percent of its size.
Two outputs: image (the normalized frame) and info (JSON - the detected bounding box, sizes, and settings used). That info string is genuinely useful for auditing why a weird shot normalized the way it did.
How it works
It samples the photo's corners as the background color, thresholds against it to find the product's bounding box (using your threshold), then centers and scales the box into the frame with your margin. Pure PIL/numpy work - no model, no network, no key.
Installing it
cd ComfyUI/custom_nodes
git clone https://github.com/Superside/comfyui-superside-nodes
pip install -r requirements.txt
Restart ComfyUI, find it under Superside.
Where it fits and what can bite
The intended chain is Normalize Product → Manual Detail Sheet (boxes set once per profile) → detail-sheet output, and it's the closest thing this pack has to a "catalogue pipeline" node. Two gotchas: it assumes a light, fairly uniform background - a busy scene or a dark backdrop will confuse the corner-sampling, and no amount of threshold tuning fixes a photo that violates the assumption. And if you switch between keep resolution and fixed canvas, redraw your crop boxes - the relative geometry changes with the mode.
Inputs (9)
| Name | Type | Default | Description |
|---|---|---|---|
| image | IMAGE | — | |
| modeopt | COMBO | keep resolution (pad) | keep resolution (pad): crop to the product and pad with the margin at NATIVE resolution - no downscaling, no quality loss (output size varies per photo). fixed canvas (scale): scale the product into a fixed output_width x output_height canvas (may downscale). |
| margin_percentopt | FLOAT | 8.00–45 | Empty margin kept around the product, as a percent of the frame. The product always ends up spanning the same centered region, so crops stay aligned across SKUs. |
| output_widthopt | INT | 102464–8192 | Only used in 'fixed canvas' mode - width of the output canvas. |
| output_heightopt | INT | 102464–8192 | Only used in 'fixed canvas' mode - height of the output canvas. |
| fitopt | COMBO | contain | Only used in 'fixed canvas' mode. contain: fit the whole product. width: scale so the product's width fills the frame. height: scale to fill height. |
| background_hexopt | STRING | Fill color for the output canvas. Leave empty to auto-sample the source photo's corner background. | |
| thresholdopt | FLOAT | 121–128 | How different from the background a pixel must be (0-255) to count as part of the product. Lower catches fainter details (thin metal), higher ignores soft shadows. |
| detect_pad_percentopt | FLOAT | 2.00–25 | Extra padding added around the detected product before placing it, as a percent of the detected size. |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| image | IMAGE | — |
| info | STRING | — |