Images,
and the systems
that make them.

artist-led imaging systems by Dominic Hawgood

Creative technologist, bridging creative and engineering. I design, build and consult on AI workflows and systems for studios, agencies, production companies and image‑led brands.

Study 02 — liquid chrome folding into a seam
Typewriter Scans — land shell

01 / typewriter scans

Neandertal — the cave mouth, light dropping through the opening

03 / neandertal

02 / comfy bridge

Restoration Engine — a portrait restored from a low-resolution source

05 / restoration engine

Portrait Performance System — a head in profile, the fitted head's normal map on the left meeting the finished render on the right

06 / portrait performance

Casting Out the Self — the scanned Buddha head, in profile

casting out the self

Chasing Demons in the Night

chasing demons in the night

The Anointing Water

the anointing water

Under the Influence

under the influence

Archive, 2012–2020→

[fig. 1]restored · 4640 × 5760

Portrait 1 restored — a pale face, straight black hair, three moles on the cheek, a leather jacket

[fig. 2]restored · 4610 × 5760

Portrait 2 restored — a darker-skinned face, curly black hair, freckles, a herringbone coat

05 / system · restoration

Restoration Engine

contents
2 portraits · 22 renders · 1 canvas · 4 maps · 3 reports
models
SeedVR2 7B
made with
ComfyUI · Python / PyTorch · Claude Code · Comfy Bridge

A set of custom ComfyUI nodes built around the SeedVR2 upscaler. They run SeedVR2 as a pipeline in which every stage can be set and inspected. Noise is added to the whole frame, the image is split into tiles for upscaling, and the tiles are stitched back. The result is then mixed with the original band by band: broad colour and light from the original, fine detail from SeedVR2. An alignment check measures whether the upscale still lines up with the source, and the mixer can reduce or refuse the mix when it does not.

The nodes are controls and instruments, not a fixed recipe. They make it possible to test how SeedVR2 responds to its input. One such test, of a single control, is shown below.

eight nodes · five modules · one tile per call · exact crop back

SeedVR2 and the Restoration Engine

The same source through SeedVR2 on its own and through the suite, at the same output size. On flat skin, SeedVR2 on its own leaves the surface smooth; with the noise node at the tested setting it rebuilds pore-level texture. On detail that is already sharp — eyes, brows, hair — the two are close.

[pl. i]the same regions at actual pixels

anose · portrait 1

SeedVR2 on its ownRestoration Engine

Portrait 1, the bridge of the nose, SeedVR2 on its own — the skin smooth Portrait 1, the bridge of the nose, through the suite — pores across the skin

bbrow · portrait 2

SeedVR2 on its ownRestoration Engine

Portrait 2, between the brows, SeedVR2 on its own — the skin smooth Portrait 2, between the brows, through the suite — pores across the skin

Grain scale

One control of one node, tested on its own. The noise node adds fine grain to the image before SeedVR2 sees it, and one control sets how coarse that grain is. Too fine and skin comes out plastic, smoother than with no noise at all. Too coarse and it turns blotchy. Between the two, SeedVR2 rebuilds pore-level texture.

928 × 1152 in · 4640 × 5760 out · one pass · grain scale 1.0 – 4.5, nothing else changed

[pl. ii]grain scale · portrait 1

ainput · 928 × 1152

Portrait 1 — the low-resolution input, with the region shown beside it marked

boutput · detail at actual pixels

Cheek, SeedVR2 on its own, without the suite — smooth Cheek, grain scale 1.0 — plastic, with a woven imprint Cheek, grain scale 1.5 — plastic Cheek, grain scale 2.0 Cheek, grain scale 2.5 — pores Cheek, grain scale 3.0 — pores, the peak Cheek, grain scale 3.5 — pores Cheek, grain scale 4.0 — blotchy Cheek, grain scale 4.5 — blotchy
SeedVR2plasticporesblotchy

[pl. iii]grain scale · portrait 2

ainput · 922 × 1152

Portrait 2 — the low-resolution input, with the region shown beside it marked

boutput · detail at actual pixels

Bridge of the nose, SeedVR2 on its own, without the suite — smooth Bridge of the nose, grain scale 1.0 — plastic Bridge of the nose, grain scale 1.5 — plastic Bridge of the nose, grain scale 2.0 Bridge of the nose, grain scale 2.5 — pores Bridge of the nose, grain scale 3.0 — pores, the peak Bridge of the nose, grain scale 3.5 — pores Bridge of the nose, grain scale 4.0 — blotchy Bridge of the nose, grain scale 4.5 — blotchy
SeedVR2plasticporesblotchy

[fig. 3]comfyui canvas · prepare · degrade · split · restore · combine · measure · mix

The full ComfyUI restoration pipeline on one canvas, with portrait 1 loaded — its noise residual, tiles, frequency differences, mask and final output in the preview nodes

What each node makes visible

Middle grey is no change. None of the maps is a picture of the portrait — they are what the pipeline puts on the canvas while it works.

  1. Prepare

    Which of three sizing routes it took. Padding is flagged, because padded black is restored at full price.

  2. Tiling

    The grid actually in use after clamping, rather than the numbers you typed. Each tile carries context past its own edge.

    [doc. 1]tile plan

    4640×5760 → working 4656×5760
    grid 3×4
    core 1552×1440
    context 64×64 each side
    model tile 1680×1568
    pad L0/R16/T0/B0
    alignment 16
    order row_major
    tile 2.63 MP vs full frame 26.73 MP
    12 tiles processing 1.18× the source pixel area
  3. Noise

    Exactly what was withdrawn before the model saw it. Defects look like signal, so the model preserves them; weakened first, they get rebuilt.

    [fig. 4]noise residual

    Noise residual for portrait 1 — the grain injected across the whole frame before tiling, lighter over the face where edges are protected
  4. Combine

    How far neighbouring tiles disagreed where they overlap, measured before any preview gain. It refuses the run if a tile comes back the wrong size.

    [doc. 2]combine summary

    Combined 12 tiles by normalized cosine overlap-add
    context 64×64 each side
    blend 32×32 each side
    working 4656×5760 → exact crop 4640×5760
    weight range 1.0000–1.0000
    seam disagreement max 0.37089, mean 0.00901
  5. Alignment

    Whether the upscale still lines up with the source, and what the gate did about it. It never corrects the image.

    The alignment check executes whether or not anything is wired to its outputs. A check that only ran when connected would fail silently, and silence looks like success.

    [doc. 3]alignment, measured

    ALIGNED.
    Offset dy -0.180 px, dx -0.209 px (magnitude 0.276 px).
    Severity 0.033 against a threshold of 0.25, measured at detail scale 1.5 px. Severity is the high-band error recoverable by a single global shift, so it reads low when no global shift would help.
    Correlation confidence 157.9 (peak-to-sidelobe; below 12 is untrustworthy, unrelated images score about 8).
    Local 3x3 offset spread 0.317 px across 9 patches (threshold 0.75).
    Any residual offset is too small to meaningfully damage the high band. Safe to mix.
    Local offsets scatter by 0.317 px, above the 0.25 px seen on rigid pairs but below the threshold. Minor sub-pixel variation of this size is normal for a generative restoration and is not evidence of warping.
  6. Frequency mixer

    What the model proposed in each band and how much was accepted. Low 0.10, mid 1.00, high 1.00 — colour from the source, detail from SeedVR2.

    [pl. iv]frequency differences

    Low-frequency difference for portrait 1 — what the model changed in broad colour and light Mid-frequency difference for portrait 1 — what the model changed in outline and soft structure High-frequency difference for portrait 1 — the fine detail the model added