imagehide

A-tolerant / MWIP · 896 b in pixels · invertible NN carrier git 0db753e · snapshot 2026-05-18

Lightweight invertible-NN image watermarking: an on-camera carrier that embeds an Ed25519 content-bound signature in pixels (896 b headline payload, ECC-wrapped to 1024 b), recoverable after JPEG / resize / platform pipelines, without a C2PA-style manifest. Companion to the public imagehide-demo; this page is the internal work-surface (open risks, decision log, in-flight design line). See Spec (overview + vs SOTA) / Model (full reference) / Design (rationale) / Plan. Paper draft: Overleaf.

Highlight any text → 💬 comment. Publishes to GitHub Issues; optional 🤖 Ask Claude to fix tag for action items.
HANDOFF.md bulk is from 2026-04-28; stale-section markers added 2026-05-19

Active research has moved on to the idea084/d001 → idea112/d003 design line (subband-weighted permutation adapter, multi-aux losses; see results/exp0_inn_idea*/). The "pending reds" list in HANDOFF predates this. The deployed carrier on imagehide-demo is idea097_design001 (lives in the sibling autohide project, 2026-05-17). Headline numbers below are from its eval. Treat the deployed-carrier section as ground truth for what verifies today; in-flight jobs are tracked locally via squeue -u $USER. A STATUS as of 2026-05-19 callout at the top of HANDOFF.md spells out which earlier facts (chain_wechat removal, multi-res light, v2 mobile carrier) are superseded by the deployed model.

Deployed carrier idea097/d001

checkpoint autohide/experiments/1024bit_noamp_keepckpt/idea097_design001/ckpt_latest.pt
demo yanghangai.github.io/imagehide/demo · in-browser embed + verify (WASM)
backbone INN v3 · 8 / light · 0.167 M params · 0.7 MB fp32 · no-AMP train
data payload [ H(128) | sig(512) | pk(256) ] · 896 b
ECC codeword in pixels BCH(127,99) + RS(128,100) · 1024 b
acceptable bit_acc (verify floor) ≥ ~0.986 iid · RS(128,100) tolerates 14 / 128 byte errors; p8 ≥ 1 − 14/128 ⇒ p ≥ 0.9856. Patch-tile errors are clustered (multi-bit per failed patch) so the realised floor is somewhat lower — empirical per-image RS-success sweep still pending.
trained 2026-05-17 · step 30,000

Headline eval (idea097/d001)

avg (7 sizes) @ 1024² only bit_acc avg 0.995 0.999 min over 14 attacks 0.955 0.992
PSNR clean37.4 dB
SSIM clean0.940
12 MP fp16~25 ms (est)
100 DIV2K val · 7 sizes (256² → 2048×1536 + random) · 14 in-scope attacks (JPEG + chains + resize + platform pipelines). Worst attack overall: chain_wechat at 0.955 (avg) / 0.992 (1024²). At 1024² alone every in-scope attack ≥ 0.99; the 0.955 floor is dominated by 256² where the patch grid is tightest. Gaussian-noise and noise-augmented platform chains excluded per threat model.
Spec
One-page overview: deployed demo model, headline numbers, comparison vs TrustMark / MetaSeal / StegaStamp / HiDDeN.
Model details
Full reference for the demo carrier: architecture, components, ECC layout, adapter math, training, eval, API, diagnostics.
Design rationale
Why patch-tile adapter, α=1, ramp curriculum; what was tried and rejected. TrustMark CNN baseline as a side panel.
Plan & milestones
Research plan v4 timeline — problem, threat model, experiments, kill criteria, decision log, change log.
Operations
SLURM policy, filterable sbatch inventory, datasets catalog, site deploy runbook.
blind_watermark analysis
Classical DWT-DCT-SVD baseline (12.9k★) benchmarked on the compression suite. Mechanism walk-through + ideas to bring back to MWIP.

Recent decisions (from HANDOFF + git)

Top open risks

idea097/d001 — bit_acc by attack 100 DIV2K val · 14 in-scope attacks

categoryattackavg@ 1024²note
clean—1.0001.000no attack baseline
single jpegq90 / q70 / q50 / q301.000 / 0.999 / 0.999 / 0.9961.000 / 1.000 / 1.000 / 1.000platform re-encode
jpeg chain85→60 · 70×30.999 / 0.9991.000 / 1.000cross-platform re-uploads
resize only0.9 / 0.7 / 0.51.000 / 1.000 / 1.0001.000 / 1.000 / 1.000down-then-up resample
platformchain_insta0.9981.000Instagram feed (resize 0.5 + Q85)
platformchain_x0.9861.000X / Twitter (resize 0.4 + Q75)
platformchain_whatsapp_std0.9961.000WhatsApp Std / FB feed (resize 0.5 + Q70)
platformchain_wechat0.9550.992WeChat (resize 0.3 + Q50) — worst overall; 1024² holds 0.99
Source: autohide/experiments/1024bit_noamp_keepckpt/idea097_design001/eval.json · 14 attacks across 7 sizes (256² → 2048×1536 + random). avg row = mean across 7 sizes (avg bit_acc 0.995, min 0.955). @ 1024² = single-size slice (avg 0.999, min 0.992 — every in-scope attack ≥ 0.99). PSNR clean 37.4 dB at 1024². Gaussian-noise and noise-augmented (_full) chains excluded — noise is out of the canonical-delivery threat model.

Useful commands

# activate env (don't use `source activate`)
module load conda/latest
eval "$(conda shell.bash hook)"
conda activate hang

# check 2080Ti availability
sinfo -p gpu-preempt -o "%t %D %G" | grep 2080_ti

# running jobs
squeue -u $USER -o "%.18i %.20j %.8t %.10M %R"

# interactive debug session
srun --partition=gpu-preempt --gres=gpu:2080_ti:1 \
     --mem=16G --time=1:00:00 --pty bash

# re-eval the deployed carrier (~30 min)
sbatch scripts/exp0_inn_eval_v2.sbatch
# → results/exp0_inn_p896_light_v2/eval.json