Style Transfer Pipeline
Companion document to README-DEBLUR.md. This file covers the host-level
style-transfer feature that follows the same fork/race/fold shape as the
deblur ensemble APIs.
Overview
styleTransferAnyImage(content, style, options) applies deterministic style
transfer for 1-channel and RGB images:
- matches channel mean/std from style image onto content image
- blends stylized signal with the original content signal (
strength) - preserves structure via edge-aware reinjection (
structurePreservation) - passes style through an alpha wave field, then transposes the waved style onto target
- optional post sharpen for textures
forkRaceFoldStyleTransfer(...) runs multiple style-transfer configs in
parallel and folds survivors with Buleyean weighting.
Quick start
import {
styleTransferAnyImage,
forkRaceFoldStyleTransfer,
encodeStyledAsPNG,
} from '@a0n/distributed-inference-host/style';
const single = await styleTransferAnyImage(content, style, {
method: 'classical',
strength: 0.75,
structurePreservation: 0.55,
alphaWave: { edgeThreshold: 0.22, edgeBoost: 0.7, frequency: 2.2, phase: 0.0 },
});
const ensemble = await forkRaceFoldStyleTransfer({
content,
style,
configs: [
{ label: 'balanced', options: { method: 'classical', strength: 0.7 } },
{ label: 'bold', options: { method: 'classical', strength: 0.9 } },
],
});
await writeFile('styled.png', await encodeStyledAsPNG(single));Golden PNG regression snapshots
Byte-stable PNGs under __tests__/golden/style-transfer/ guard the classical
pipeline (plain, mesh stub, mesh + depth) and the FRF style fold (frf-mesh-fold-16.png)
on a fixed 16×16 LCG plane pair. The
encoder is rgbFloat01InterleavedToPngBuffer (zlib filter-0, same round(clamp01(v)*255) quantization as encodeStyledAsPNG).
Update goldens after an intentional algorithm change:
UPDATE_STYLE_TRANSFER_GOLDEN_SNAPSHOTS=1 pnpm run a0 -- run @a0n/distributed-inference-host:test -- --testPathPattern=style-transfer-goldenSee __tests__/golden/style-transfer/README.md. A maintainer script that mirrors the same fixtures lives at scripts/write-style-transfer-golden-pngs.ts (run via gnode when the TS bridge is available, or bundle with esbuild and a footer that calls main() from the package root).
Wasm imaging surface (StyleTransferImagingWasmSurface)
Pass the wasm-bindgen namespace from distributed_inference (same object a Worker
loads after init) as the last argument to styleTransferAnyImage, or set
imagingWasm on forkRaceFoldStyleTransfer ensemble args for all forks:
wasmTopologyMaskBuildRgbF32— used whenmeshGate.enabledis true and no explicittopologyAlphaBackendis passed (topology provenance stays JSON-serializable).wasmMeshDepthConfidenceRgbF32— optional; whenmeshGate.autoWasmDepthis true and the caller did not supplymeshGate.depthConfidence, the host fills the depth channel from wasm (build_mesh_depth_fieldin the Rust crate).meshGate.wasmMonocularCueBlendforwards monocular cue blend into that wasm entry.
Host-only Gibson proxies (meshGate.hostMonocularAdmissionWeight) multiply into
the photometric veto path without wasm.
AdaIN adapter contract
The AdaIN path is exposed as an adapter surface:
method: 'adain-adapter'switches to adapter mode- if no backend is supplied, output falls back to classical transfer while preserving the method label
- if a backend is supplied, it must return
width*height*channelsvalues
Mesh gate and AdaIN ordering
- Classical reference always runs first (with mesh gate when enabled) so
meshProvenance,meshFoldMetrics, and fallbackstylizedstay defined. - The AdaIN backend replaces
stylizedwith its own plane (same contract as before). - Optional
meshGate.applyScalarMeshAdmissionToAdaIN: after AdaIN, each channel is pulled toward content with scalarmean_effective_gatefrom the classical mesh path:out = content + mean_effective_gate * (adain - content)(per-channel, clamped). Per-pixel gating of AdaIN output is not implemented yet; the scalar is an explicit, replayable compromise.
This keeps the API stable while neural backend wiring is still evolving.