Nodes/Krea 2 and MiniMax H3 Pixel Art Refiners/MiniMax H3 Pixel Art Autorefiner
ComfyUI Node

MiniMax H3 Pixel Art Autorefiner

It finds the pixel grid so you don't have to

By envy-ai·Created 3 days ago·Updated about 18 hours ago· 9
MiniMax H3 Pixel Art Autorefiner
  • image
  • palette_image
  • IMAGE
width64
height64
colors24
scale_to_originaltrue
shared_palettetrue
manual_resolutionfalse

The other two refiners in this pack need you to say how big the logical grid is. That's fine when you generated the image and know you upscaled 16×. It's tedious when you inherited a sprite, pulled a frame out of a video model, or have a folder of art at inconsistent scales.

This node measures the grid for you. You give it a frame, it finds the pixel mesh, collapses every cell to one real pixel, and hands back a frame that's actually on a grid.

How the detection works

It is not guessing from the width/height inputs - those are fallbacks. The actual pipeline, per frame:

  1. Reduce the frame to the perceptual palette first (same weighted OKLab clustering as the sibling nodes).
  2. Upscale 2× and run Canny edge detection, then a morphological close with an 8×8 kernel, which turns sprite edges into connected line evidence.
  3. Find horizontal and vertical lines with a probabilistic Hough transform, cluster nearby hits, and estimate the pixel pitch from the median filtered gap.
  4. Throw out weak landmarks: a line sitting close to stronger neighbours, with visibly less edge support, is noise.
  5. Subdivide the remaining gaps locally so small variations in pixel pitch are kept rather than forced into one global block size.
  6. Collapse each mesh cell by modal colour with the same centre-pixel tie-break as the other nodes, then treat the upper-left colour as transparent, optionally scale and pad to the original dimensions, and composite on white.

The mesh detector is adapted from Kenneth Allen's Proper Pixel Art (MIT, credited in the repo's third-party notices); the palette quantizer is the pack author's own. If detection fails or produces something unusable, the node falls back to a regular grid of width × height, retrying at 1× if the 2× pass found nothing. Worth knowing: a soft, gradient-heavy image can quietly come back uniformly gridded rather than truly detected, so eyeball your first result.

Inputs that matter

  • image - single image, image batch, or a decoded video-frame batch.
  • manual_resolution - the honest off-switch. With it on, the frame is divided evenly into width × height cells and no detection runs at all. The README's worked case is the one to remember: a 2048 × 512 four-view character sheet built from 16×16 source pixels wants width=128, height=32.
  • width / height - full-frame logical size in manual mode; the fallback grid otherwise, defaulting to 64×64.
  • colors - palette cap, default 24, and the same advice applies: 16ish for game art.
  • shared_palette - on by default here, unlike the plain refiner. Good default for batches; one palette across all frames.
  • palette_image - lock the palette to reference colours for the whole batch. Overrides shared_palette.
  • scale_to_original - on by default, fits the collapsed frame inside the original and pads it. Turn it off and you get the detected true pixel resolution, which is the honest output and the one you want if you're handing the sprite to an engine.

One IMAGE output, batch preserved. For batches, the mesh is detected from the first frame only and then applied to every later frame - deliberately, because re-detecting per frame would let sprite size and position wobble as edge evidence changed, and you'd get flicker no palette setting could fix.

Installing

Same pack as the other three nodes. Manager: search ComfyUI-Krea2-Pixel-Art-Refiner. Manually:

cd ComfyUI/custom_nodes
git clone https://github.com/envy-ai/ComfyUI-Krea2-Pixel-Art-Refiner.git krea2_pixel_art_refiner

Restart; it's under image/minimax. No weights or keys - the pack's one dependency, opencv-python-headless>=4.8, exists for this node's Canny and Hough passes.

Where people get burned

The upper-left pixel is the transparency key. The node reads the top-left colour to decide what counts as background; everything matching it becomes alpha and is then flattened onto white. If your sprite touches the top-left corner - a full-bleed character, a tile that fills the frame - you've just declared part of your art transparent. Pad or crop so the corner is background first.

Output is opaque. There's no alpha output; the frame comes back composited on white. Fine for viewing, wrong for a game engine that wants transparency - take the logical-resolution output and re-key in your tooling.

Detection needs something to detect. Small or very soft inputs are the failure mode - the node errors on images at or below 4×4, and low-contrast, painterly, anti-aliased art gives the Hough stage almost nothing to work with, so you silently get the width/height fallback. If a detected result looks identical to manual_resolution with the right grid, detection gave up.

Mixed content in one frame. A sprite on a detailed background, or two sprites at different scales, produces a grid that fits neither. This node deliberately treats the frame as one mesh without splitting subjects - if the frame genuinely contains two scales, crop first.

Wire the output into Save Image, or into Pixel Art Animation Pose Compositor if you're working with a video batch and want repeated cycles merged into distinct poses.

Categoryimage/minimax

Inputs (8)

NameTypeDefaultDescription
imageIMAGE
widthINT641–16384Full-frame logical width for manual mode or automatic detection fallback.
heightINT641–16384Full-frame logical height for manual mode or automatic detection fallback.
colorsINT242–256Maximum generated or supplied palette size.
scale_to_originalBOOLEANtrueScale and pad the collapsed frame to the input dimensions.
shared_paletteBOOLEANtrueGenerate one palette from the entire image batch instead of a separate palette for each frame.
manual_resolutionBOOLEANfalseDivide the full frame evenly into width × height cells instead of detecting a mesh.
palette_imageoptIMAGEUse this image's colors as the palette for the entire batch. Overrides shared_palette.

Outputs (1)

NameTypeDescription
IMAGEIMAGE