Inkvec Upscale x4 (MambaIRv2)
Making a too-small logo big enough to trace properly
- image
- mask
- image
- mask
Every tracing problem eventually turns into a resolution problem. A 96-pixel logo pulled off a website has maybe three pixels of curve in a letter, and no tracer on earth is going to reconstruct a clean bezier from three pixels - you get faceted arcs and lumpy edges. The usual advice is "get a bigger source", which is unhelpful when the bigger source doesn't exist. Inkvec Upscale invents a bigger one, trained on exactly this kind of image.
What it is
A MambaIRv2-Small fine-tune (Logolabs/inkvec-sr-001, Apache-2.0), 9.77M parameters, trained on logo and icon art - i.e. flat colour, hard edges, geometric curves. It's the upscaler behind inkvec --sr. The base architecture is MambaIRv2 (Hang Guo et al., CVPR 2025, Attentive State Space Restoration), a state-space restoration model rather than a GAN - which is why you don't get the crunchy, over-textured "ESRGAN hallucinating a whole leaf" look on line art.
The important framing: this is the "more pixels" job in upscaling terms, not the generative-restoration job. There is no photograph path here - feed it a portrait and it will do something technically valid and visually upsetting. If your source is a photo, this is the wrong node; the general upscaling decision tree looks nothing like this one.
How it works
scale has two settings and they're genuinely different recipes:
4xis the network's raw output.2xis the same x4, box-averaged back down to x2, then the flat colours are refitted to the source's with one affine map per channel. That last step isn't cosmetic: on clean input the network alone drifts about 0.6 dE00 in flat interiors, and the refit takes the colour back from the source, so your brand blue stays your brand blue.
Transparency is handled rather than hoped for. The network sees RGB only, so colour is zeroed wherever alpha is 0 - otherwise transparent logos pick up a dark halo from the black behind them - and alpha itself is resized separately with Lanczos. The mask output is at the new size.
Tiling is on by default (tile 256 input pixels, 32 px overlap, feathered blend). The feathering is deliberate: a hard seam is an edge, and an edge is precisely the thing the tracer downstream will latch onto.
The bit worth knowing about: MambaIRv2 samples noise on every forward pass through its Gumbel-softmax routing, even in eval mode, so out of the box the same image gives you a slightly different result each run - up to 12.45 levels apart, in the author's measurement. The node pins the random generator to a reference seed around every forward pass and restores ComfyUI's generator state afterwards. Same input, same output. Your logo doesn't flicker between runs for no reason.
Inputs and outputs
Required: image, scale (4x or 2x), device (auto/cpu/cuda - auto means CUDA when available), tile (64–2048). Optional: mask for transparency (LoadImage's convention, 1 = transparent) and weights_path if you'd rather point at a local logo_sr_x4.pt than download it.
Outputs are image and mask. Both go into Inkvec Trace, mask included - otherwise you've upscaled the artwork and thrown away its transparency.
Install
ComfyUI Manager: search "Inkvec" (publisher logolabs-org) and restart. Manually:
cd ComfyUI/custom_nodes
git clone https://github.com/logolabs/inkvec-comfyui.git
pip install -r inkvec-comfyui/requirements.txt
This node needs einops from that list, plus torch. The MambaIRV2 weights (about 20 MB) download to ComfyUI/models/inkvec/ on first use, pinned to a revision and SHA-256 checked. If mamba-ssm happens to be installed and imports cleanly, the selective scan uses its CUDA kernel; otherwise a pure-PyTorch parallel scan runs instead, on CPU or any GPU. On CUDA the forward pass runs in bfloat16.
Realistic expectations
Use the GPU. On CPU through the node, a 64 px input took 36 seconds and 128 px took 62 seconds on a Ryzen 7 5800X. On an RTX 4060 that was also busy, the same node did 64 px in 1.3 s. So device auto without a working CUDA/torch setup is a "why is this stuck" experience.
Out of memory? Lower tile. That's the whole fix - 256 with 32 px overlap is comfortable on most cards, and small tiles cost you time, not quality.
Upscaling doesn't rescue a bad source. If the original is a blurry 200 px JPEG, x4 gives you a blurry 800 px image, which the tracer will happily fit with matching levels of mush. For that, run Inkvec Denoise first (or after; the pack's own example workflow does Denoise → Upscale → Trace with the masks chained through) and set the trace node's lossy to on.
Inputs (6)
| Name | Type | Default | Description |
|---|---|---|---|
| image | IMAGE | — | |
| scale | COMBO | 4x | 4x = the network's output. 2x = the recipe `inkvec --sr on` traces: x4, box-averaged back to x2, flat colours refitted to the source's. |
| device | COMBO | auto | auto = CUDA when available, else CPU. |
| tile | INT | 25664–2048 | Tile size in input pixels (32 px overlap, feathered blend). Lower it if the GPU runs out of memory. |
| maskopt | MASK | Transparency, 1 = transparent (LoadImage's MASK). | |
| weights_pathopt | STRING | Local logo_sr_x4.pt (or its folder) instead of the download. Empty = download from Hugging Face into models/inkvec/. |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| image | IMAGE | — |
| mask | MASK | — |