OnyxModels β Real-ESRGAN x4 upscaler (Onyx MLX build)
The learned AI image upscaler for Onyx (the "Enhance (AI)" tier). A Γ4 single-pass super-resolution GAN (RRDBNet) that synthesizes real detail β unlike the Lanczos "Quick" tier, which only interpolates.
Layout
mlx/
model.safetensors Onyx MLX build β fp16, 33.4 MB (what the app downloads from HF)
onyx_mlx.json arch config (rrdbnet, scale 4, num_feat 64, num_block 23, num_grow_ch 32)
pth-src/
RealESRGAN_x4plus.pth original fp32 PyTorch weights (~64 MB, provenance / rebuild source)
convert.py reproducible converter (.pth β Onyx MLX safetensors)
verify/
input_768x512.png test input
onyx_esrgan_4x.png Onyx MLX output (3072Γ2048)
pytorch_ref_4x.png PyTorch reference output β Onyx matches it (99.8% of pixels within Β±3, mean diff 0.09)
Provenance
Source: RealESRGAN_x4plus.pth from xinntao/Real-ESRGAN v0.1.0 (Apache-2.0 β commercially shippable).
The Onyx MLX build is a straight format conversion (convert.py): keys kept 1:1 with the PyTorch names,
conv weights transposed to MLXNN's (C_out, kH, kW, C_in) layout (with np.ascontiguousarray so the buffer
order matches the shape β a view-vs-copy bug here scrambles the weights), fp16 storage. No retraining.
Architecture (RRDBNet): conv_first β 23Γ RRDB (each = 3 ResidualDenseBlocks, dense 5-conv, growth 32) β
conv_body + global residual β nearest-upsample Γ2, conv_up1 β nearest-upsample Γ2, conv_up2 β conv_hr β
conv_last. LeakyReLU(0.2). Runs in fp32 compute (the fp16 export is upcast at load; 23 dense blocks
overflow fp16 to NaN otherwise). Swift model: OnyxDiffusion/Families/Upscale/RRDBNet.swift +
ImageUpscaleModel.swift (tiled, overlap-blended forward for memory-safe large images).
Verified
Device-parity: the Onyx MLX build matches the PyTorch reference within fp16 rounding (max abs diff 0.09 mean, 99.8% of pixels β€3). Runs on Mac in ~4.5 s for 768Γ512 β 3072Γ2048 (single-shot; tiled for larger).
Publishing to Hugging Face
App downloads from wabibito/Onyx-Real-ESRGAN (mirror convention, like the other onyx-* image models).
Upload needs a transient HF token you provide and revoke after. The pth-src/ original stays local-only.