forgo.cloud
Sign in
Repo workspace

forkjoin-ai/gnosis

Topology imaging kernel (`distributed-inference`)

distributed-inference/TOPOLOGY_IMAGING.md
forkjoin-ai/gnosis

Topology imaging kernel (distributed-inference)

Rust-first primitives for topology-guided masking, minimal compositing, Lambert relighting, and a mesh-governed depth field plus extrusion. TypeScript hosts should treat these as FFI/WASM callers, not duplicate the pipeline.

Parity scope (editor vertical)

Priority vertical: photo retouch and compositing (local pixel edits, layered blends, matte-driven adjustments). Typography, vector-heavy design tools, PSD I/O, and full color-management are explicitly out of scope for this crate; they belong in separate editor stacks.

Native modules

Module Role
topology_mask Interest planes → multi-scale super-level sieve → soft alpha [0,1] + TopologyMaskProvenance (JSON via serde).
imaging_composite Source-over and multiply blending with per-pixel alpha; mask_multiply_rgb for mask-linked tonal adjustments.
imaging_relight Finite-difference normals from a scalar plane × Lambert-ish shading; topology_alpha gates where relight replaces source RGB.
mesh_depth_field Mesh-governed depth: fuses classical proxy depth + topology alpha (+ optional ONNX prior) with per-pixel confidence and MeshDepthProvenance (schema_version: mesh_depth_provenance/v1).
depth_monocular_cues Five-level dyadic luma bands + cheap Gibsonian proxies (texture gradient, aerial perspective, horizontal-dominant structure, luminance edges). Optional blend via MeshDepthConfig::monocular_cue_blend. Not transformer standing_wave_pinning (attention Q/K/V); same “multi-scale admission” pattern, different signal.
depth_metric_anchor SI / metric anchors after a ratio-scale field: known mask + extent (scale_meters_per_relative_unit_from_known_extent), CameraIntrinsics → m/px at Z, stereo Z=f·B/d, Sim3-style scale from world vs unit translation (depth_metric_anchor.rs). MeshDepthMetricAnchor + MetricAnchorFire integrate into build_mesh_depth_field (optional 6th arg); provenance metric_anchor + parallel values_meters.
depth_extrusion Classical proxy estimate_depth_classical_normalized; optional native ONNX via depth-onnx feature + depth_onnx; extrude_depth_heightfield_rgb and extrude_depth_heightfield_rgb_weighted (Z × confidence).
text_topology Not-quite-OCR: domain-neutral ink topology extraction for handwriting and line art. Emits stroke components, graph-ish shape facts, text-likeness priors, Rosetta bridge entries, and optional cleared-image previews. Language decoding belongs to aeon-communication / rosetta-datacore; training belongs to open-source/buleyean-rl.

Text topology: not quite OCR

The _why handwriting work is intentionally not OCR first. OCR starts with a language target and asks which pixels spell it. This crate starts one layer lower: text as topology.

The mesh extractor sees arbitrary ink shapes and reports:

  • connected stroke components;
  • bounding boxes and normalized page positions;
  • density, endpoints, junctions, coarse loop estimates, and aspect;
  • a text-likeness prior that only says "this shape participates in a language-like stroke topology";
  • render-layer hints (text, unknown, art) for removal/rewrite previews.

It does not decide that a component is an a, fox, or Chunky bacon!!. Those are language-domain claims. The handoff is:

image ink
  -> distributed-inference/text_topology: arbitrary stroke mesh
  -> rosetta-datacore: symbols, candidates, anchors, collisions, mesh display
  -> aeon-communication: language-specific decoding and Rosetta pressure
  -> buleyean-rl: rejection ledgers for "not this glyph / not safe to erase"
  -> image mesh projection: clear and rewrite the recovered text manifold

The first art-project side effect is a cleared preview: high-confidence text-like ink components can be filled into a new PNG while the full topology JSONL remains available for Rosetta/Buleyean training. Clearing is background aware at the component level: each erased stroke is replaced with a local non-ink fill sampled around its bounding box, preserving transparent or off-white page backgrounds better than a hard white stamp. Admission is intentionally more conservative than raw ink detection: candidate strokes are grouped into baseline-like bands, and clearing only happens when a band has enough glyph-sized repetition to look language-shaped. This protects small drawing marks such as eyes and mouths, which can share the same local topology as punctuation. The clearer then runs a second, bounded artifact cleanup pass inside admitted text bands to remove anti-aliased residue. When --clear-iterations N is greater than one, the topology pass reruns on the current preview until it reaches a fixed point or the cap is hit. Primary black ink that survives stabilization is treated as an unresolved semantic artifact rather than erased blindly unless an explicit --clear-residual-threshold admits it. The same admitted text bands can also be emitted as source-resolution alpha assets: a grayscale text-region mask and a transparent text-region cutout. Those alpha assets use a Teddy-style stroke envelope: admitted component pixels are dilated and lightly closed so the layer hugs the written marks instead of filling the whole baseline rectangle. These layers share the original image coordinate frame, so the cleared base and cutout can recompose exactly or be transformed independently for mesh/image mashups. The preview is not the final inpainted page; it is the visual falsification surface for whether the mesh chose the right text layer.

Native CLI:

cargo run -p distributed-inference --bin why-text-topology -- \
  --input /path/to/__why \
  --out /tmp/why-text-topology \
  --candidate-limit 500 \
  --emit-cleared \
  --emit-region-masks \
  --emit-text-cutouts \
  --emit-depth-probes \
  --emit-pixel-moa-probes \
  --emit-surface-probes \
  --clear-threshold 0.55 \
  --clear-radius 1 \
  --clear-iterations 3 \
  --clear-region-radius 6 \
  --monocular-cue-blend 0.6

Operational _why run used during development:

cargo run -p distributed-inference --bin why-text-topology -- \
  --input ./tmp/why-text-project/__why \
  --out ./tmp/why-text-project/rust-full-filament-set \
  --candidate-limit 500 \
  --emit-cleared \
  --emit-region-masks \
  --emit-text-cutouts \
  --emit-depth-probes \
  --emit-pixel-moa-probes \
  --emit-surface-probes \
  --clear-threshold 0.55 \
  --clear-radius 1 \
  --clear-iterations 3 \
  --clear-residual-threshold 0.5 \
  --clear-region-radius 6 \
  --clear-pixel-moa-recovery \
  --monocular-cue-blend 0.6

Outputs:

  • text-topology-corpus.jsonl — full stroke topology corpus;
  • rosetta-import-payload.json — compact datacore import payload, including stroke candidates, textLineCandidates for language-shaped band admission, and residualTextArtifacts for primary ink fragments that need semantic review before cleanup. residualReviewQueue groups those fragments by line and ranks the lines that most need semantic admission/protection. meshTextAdmissionLedger records each component as a subject/object/verb FRFVI operation, distinguishing admitted text, measured non-text, unresolved unknowns, and active demotions;
  • cleared/*.cleared.png — optional erased-text previews;
  • cleared/*.text-region-mask.png — optional reusable alpha masks for admitted text regions;
  • cleared/*.text-region-cutout.png — optional transparent source cutouts for recomposition or independent text-layer transforms;
  • cleared/*.depth-probe.png and cleared/*.depth-confidence.png — optional mesh-governed monocular probe layers for testing whether surface/depth cues can separate speech-bubble text from drawing contours before they influence admission;
  • cleared/*.pixel-moa-probe.png — optional pixelwise mixture-of-attention probe. It forks local darkness, stroke-density, horizontal-cadence, and surface ownership heads, then folds them into a per-pixel admission prior for visual debugging before the result is allowed to erase anything;
  • cleared/*.surface-mask-probe.png — optional mesh/surface ownership probe. Bright pixels are eroded background/speech-surface interiors; dim pixels are protected near-boundary interiors. This is the current “where may text live?” contract for recovery experiments;
  • cleared/*.surface-fragment-probe.png — optional clipped-fragment probe. It paints ink fragments with nearby eroded surface support, then marks fragments that the opt-in recovery classifier would admit. Punctuation is treated as a small-fragment outlier class: it may lack letter rhythm but still belongs to a nearby admitted language band or speech surface. Use this probe to distinguish missing surface support from rejected semantics before changing thresholds.

--clear-pixel-moa-recovery is deliberately opt-in. It clips candidate ink to surface-supported fragments before erasure, but the current failure mode is still semantic attachment: bubble contours can have nearby surface support, while connected letters such as descenders may need word-level attachment evidence.

Text recomposition CLI

why-text-recompose writes new text back into cleared images. It is a local, programmatic compositor: no OCR, no external font dependency, no AI call. It expects a cleared PNG plus the matching *.text-region-mask.png emitted by why-text-topology.

Single image:

cargo run -p distributed-inference --bin why-text-recompose -- \
  --image /tmp/why-text-topology/cleared/the.foxes-4c.cleared.png \
  --mask /tmp/why-text-topology/cleared/the.foxes-4c.text-region-mask.png \
  --out /tmp/why-recomposed \
  --layout surface \
  --text "MESH SEES WORDS|TEXT AS TOPOLOGY"

Full directory:

cargo run -p distributed-inference --bin why-text-recompose -- \
  --image /tmp/why-text-topology/cleared \
  --mask /tmp/why-text-topology/cleared \
  --out /tmp/why-recomposed/full-set \
  --layout surface \
  --text "MESH SEES WORDS|TEXT AS TOPOLOGY"

Useful output locations from the _why working set:

./tmp/why-text-project/recomposed-first-pass/full-set
./tmp/why-text-project/recomposed-contained-pass/full-set
./tmp/why-text-project/recomposed-compact-pass/full-set

--layout mask draws inside the old text footprint. It is conservative and useful as a falsification control: if text appears in the wrong place, the mask admission is wrong.

--layout surface derives speech-bubble-like surfaces from white enclosed regions, intersects them with text-mask anchors, rejects broad panel whitespace, erodes each candidate slot to a clean mostly-white interior, and then fits text inside the remaining rectangle. This is the preferred art-project mode.

--text accepts either plain sentences or explicit slot separators:

one sentence only
first bubble|second bubble|third bubble
The mesh sees the words. The bubble keeps the shape.

Explicit | separators are preserved as semantic units. Without |, sentence punctuation (., !, ?) is used for ranked placement.

Random ranked recomposition

For a fun exploration loop, --random-ranked chooses one image from a directory instead of recomposing every file. It ranks candidate images by physical fit and then randomly selects among the top tier.

cargo run -p distributed-inference --bin why-text-recompose -- \
  --image ./tmp/why-text-project/rust-full-filament-set/cleared \
  --mask ./tmp/why-text-project/rust-full-filament-set/cleared \
  --out ./tmp/why-text-project/recomposed-random-eroded \
  --layout surface \
  --random-ranked \
  --text "The mesh sees the words. The bubble keeps the shape."

The command prints:

ranked_random_choice=<image id>
ranked_random_score=<0..1 physical fit>
ranked_random_slots=<usable slot count>
recomposed=<output png>

Ranking is topology-aware, not semantic OCR:

  • sentence/unit count is compared to usable slot count;
  • slot capacity is estimated from the clean interior rectangle and compact font metrics;
  • slot balance rewards images where multiple bubbles have comparable capacity;
  • one sentence is penalized when the image has multiple separate bubbles;
  • two sentences are rewarded when the image has two usable bubbles.

Recomposition renderer

The renderer has two built-in bitmap fonts:

  • normal: 5x7 glyphs with 1-pixel tracking, scaled by integer factors;
  • compact: 3x5 glyphs, used when the normal font cannot fit a narrow slot.

The fitter chooses the largest complete rendering that fits the slot. It wraps words, breaks long words only when needed, and falls back to compact glyphs for small or vertical bubbles. --scale N can force a maximum scale, but operational use usually leaves scale unset so the fitter can choose.

Containment rules are intentionally biased toward false negatives:

  • broad white panel interiors are rejected as surfaces;
  • slots whose background contains too much dark artwork are skipped;
  • dirty borders are eroded away before text is placed;
  • if no clean slot remains in --layout surface, the image is emitted unchanged rather than drawing into uncertain space.

This means some valid bubbles will be skipped. That is preferable to writing replacement text over characters, trees, antlers, panel art, or open contours.

  1. Unpack or stage source images into a directory such as /tmp/why-text-project/__why.
  2. Run why-text-topology with --emit-cleared --emit-region-masks --emit-text-cutouts --emit-surface-probes.
  3. Inspect a few *.cleared.png, *.text-region-mask.png, and *.surface-fragment-probe.png files.
  4. Run why-text-recompose --layout surface on a focused image.
  5. Run why-text-recompose --layout surface --random-ranked for exploration.
  6. Run the full directory only after the focused sample looks sane.

Focused sample command:

cargo run -p distributed-inference --bin why-text-recompose -- \
  --image ./tmp/why-text-project/rust-full-filament-set/cleared/the.foxes-4c.cleared.png \
  --mask ./tmp/why-text-project/rust-full-filament-set/cleared/the.foxes-4c.text-region-mask.png \
  --out ./tmp/why-text-project/recomposed-sample \
  --layout surface \
  --text "MESH SEES WORDS|TEXT AS TOPOLOGY"

Full recomposition command:

cargo run -p distributed-inference --bin why-text-recompose -- \
  --image ./tmp/why-text-project/rust-full-filament-set/cleared \
  --mask ./tmp/why-text-project/rust-full-filament-set/cleared \
  --out ./tmp/why-text-project/recomposed-compact-pass/full-set \
  --layout surface \
  --text "MESH SEES WORDS|TEXT AS TOPOLOGY"

Tuning guide

Symptom First knob / check
letters remain after clearing inspect *.text-region-mask.png; if the mask contains them, tune clearing/envelope; if not, tune admission/recovery
a connected glyph is glued to a bubble line use --clear-pixel-moa-recovery and inspect *.surface-fragment-probe.png
text is too large or vertical leave --scale unset so compact font fallback can engage; shorten the semantic unit or split with `
text draws over art inside a bubble inspect surface mode; dirty-slot erosion should skip or shrink it; if it still draws, the clean-background threshold is too permissive
random picker chooses a one-bubble image for two sentences check ranked_random_slots; if slots are low, surface detection rejected candidate bubbles as unsafe
good image is skipped run --layout mask as a control to determine whether the mask exists; surface mode may be rejecting open contours

Verification

For source changes in this area:

cargo fmt
cargo check --bin why-text-topology
cargo check --bin why-text-recompose
cargo test text_topology --lib

For Markdown-only edits, no code check is required; read the touched docs and verify command examples still match the current CLI usage strings.

Mesh-governed depth field (Monster Mesh operator pattern)

Monster Mesh in this repo maps to the Pleromatic / transport layer (PleromaticFrame, SovereignSieve, …) used for logic and fingerprint reassembly—not literal Monster-group depth inversion. For imaging, we reuse the same engineering roles: multiple views (priors), sieve admission (agreement + topology gate), and JSON provenance.

  • Priors (views): Classical (deterministic luma/contrast proxy in depth_extrusion.rs), TopologyAlpha from build_topology_alpha, optional Onnx when compiled with --features depth-onnx and a weights path is supplied at runtime, optional MonocularCues when MeshDepthConfig::monocular_cue_blend > 0 (depth_monocular_cues.rs).
  • Cue stack (human-style heuristics): Gibsonian texture gradient, aerial perspective (cool / desat + coarse luma), linear-perspective proxy (horizontal-vs-vertical gradient dominance), and occlusion / boundary support (Sobel on luma—complements topology T-junctions). Metric depth is not automatic: MonocularCueProvenance::scale_ambiguity records ratio-scale honesty; apply depth_metric_anchor when the host has known extent + mask, intrinsics + reference Z, stereo (f_px, B, d), or world translation vs Sim units.
  • Output: MeshDepthField: values and confidence in [0,1], plus MeshDepthProvenance (fragments, nested topology, degraded_mode, schema_version).
  • Sieve: Per pixel, classical and ONNX (if present) are blended when they agree within MeshDepthConfig::agreement_threshold; disagreement scales confidence down. Topology alpha gates toward neutral_depth where contours are unstable so edges do not solo-drive extrusion.
  • Tile summaries (optional): build_mesh_depth_tile_summaries packs tile means into PleromaticDepthTileSummary (level, phase = level % 3, media: "Image") for Forge/logging—not full 4K×4K×Z voxels through SovereignSieve (out of scope until an explicit sizing policy exists).

Non-goals

  • Full-resolution holographic voxel sieve for every RGB frame.
  • Any claim that Lean Monster representation theory is monocular depth; alignment is vocabulary and provenance structure only.
  • Paid or worker-bound external inference: ONNX stays native-only, behind depth-onnx; wasm builds omit ort.

Cross-cutting spec (contracts and gates)

Topic Contract
Uncertainty grammar Use confidence / admission consistently: topology alpha, mesh depth sieve, and weighted extrusion read the same “why trust this pixel” shape.
Color Buffers are linear RGB in [0,1], row-major RGBRGB…. Classical and topology paths assume this; ONNX models must match training (often sRGB in the wild—document and convert at the host if needed).
Degraded mode MeshDepthProvenance::degraded_mode: full, onnx_disabled, onnx_shape_mismatch, or onnx_err_* when the third prior fails; fusion continues on classical + topology where possible.
ONNX I/O (pinned) See depth_onnx.rs: NCHW float [1,3,H,W] input; env DEPTH_ONNX_INPUT_NAME / DEPTH_ONNX_OUTPUT_NAME (defaults input / output); float output [1,1,H,W] or [1,H,W]; min–max normalize to [0,1].
Provenance schema mesh_depth_provenance/v1 in JSON; additive optional monocular_cues and metric_anchor (MetricAnchorFire). Bump schema_version if fragment semantics change incompatibly.
Ship gates (suggested) Default cargo test: finite depth, [0,1], two-fragment bootstrap, extrusion index counts, weighted Z strictly below full extrusion when confidence < 1. Optional: MAE vs raw ONNX on smooth synthetics (#[ignore] until DEPTH_ONNX_MODEL is set).
Safety (untrusted images) Enforce max megapixels / timeouts at the host; this crate does not allocate beyond width*height; callers must cap dimensions.
CI Default features do not enable ort. ONNX regression: DEPTH_ONNX_MODEL=/path/to/model.onnx cargo test -p distributed-inference --features depth-onnx mesh_depth_onnx -- --ignored.

Wasm contract (wasm32 build)

Exported from wasm_topology_mask.rs:

  • wasmTopologyMaskBuildRgbF32(rgb: Float32Array, width, height) -> WasmTopologyMaskResult

    • alpha: Float32Array length width*height
    • provenanceJson: JSON string matching TopologyMaskProvenance
  • wasmMeshDepthConfidenceRgbF32(rgb, width, height, monocular_cue_blend) -> WasmMeshDepthStyleResult

  • wasmCompositeMaskedRgb(bg, fg, alpha, width, height, blendMode)Float32Array length width*height*3

    • blendMode: 0 = source-over, 1 = multiply
  • wasmMaskMultiplyRgb(src, alpha, width, height)Float32Array

  • wasmRelightLambertMasked(rgb, plane, topologyAlpha, width, height, lightX, lightY, lightZ, diffuseStrength, ambient)Float32Array

Mesh depth on wasm: follow-on wasm_bindgen entry mirroring the above (buffers + JSON provenance) once the native API is frozen; native consumers use build_mesh_depth_field / mesh_depth_to_heightfield today.

All RGB buffers are row-major linear light in [0,1], sequential RGBRGB….

Tests

Synthetic coverage: topology_mask/tests_internal.rs, imaging_composite unit tests, mesh_depth_field unit tests, tests/mesh_depth_pipeline.rs, and optional tests/mesh_depth_onnx_validate.rs.

cargo test -p distributed-inference --lib mesh_depth
cargo test -p distributed-inference --test mesh_depth_pipeline
# Release timing (native)
cargo run -p distributed-inference --release --bin bench-mesh-depth -- --w 512 --h 512 --iters 24
# With vendored weights (native only):
DEPTH_ONNX_MODEL=/path/to/model.onnx cargo test -p distributed-inference --features depth-onnx mesh_depth_onnx -- --ignored