Instructions to use mlx-community/DRUNet-color-fp32 with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- MLX
How to use mlx-community/DRUNet-color-fp32 with MLX:
# Download the model from the Hub pip install huggingface_hub[hf_xet] huggingface-cli download --local-dir DRUNet-color-fp32 mlx-community/DRUNet-color-fp32
- Notebooks
- Google Colab
- Kaggle
- Local Apps Settings
- LM Studio
mlx-community/DRUNet-color-fp32
DRUNet colour denoising, converted to Apple MLX for
Apple-Silicon inference via mlx-drunet-swift.
Zhang et al., Plug-and-Play Image Restoration with Deep Denoiser Prior, IEEE TPAMI 2021. 32,640,960 parameters (130.6 MB).
π The point of this model: the noise level is an INPUT
DRUNet takes Ο as a constant 4th channel of Ο/255, so one set of weights spans a continuous
range β a denoise-strength dial rather than a fixed level baked into the checkpoint. Verified on
these weights:
| Ο | 0 | 15 | 25 | 50 |
|---|---|---|---|---|
| mean |out β in| | 0.0055 | 0.018 | 0.036 | 0.130 |
Monotonic β the conditioning is real. A port that silently dropped the 4th channel would still produce plausible-looking denoised output, which is why it is worth checking rather than assuming.
import DRUNetMLXCore
let model = DRUNet()
try model.loadWeights(from: weightsURL)
let clean = model.denoise(imageNHWC, sigma: 25) // NHWC RGB in [0,1]; sigma on the 0β¦255 scale
Or as an MLXEngine imageRestore ModelPackage (MLXDRUNet.DRUNetRestorePackage), which honours
ImageRestoreRequest.strength β the optional parameter contract 1.30.0 added for exactly this case.
β οΈ Honest positioning: a UX play, not a quality play
DRUNet is Gaussian-only in its paper and does not report SIDD. It is not a NAFNet or Restormer replacement on denoise quality. Its value is the continuous dial, which those models architecturally cannot offer.
Note also that Ο nominally means "the AWGN standard deviation of the input". Treating it as a user-facing strength slider is a product decision; picking Ο automatically for a real photograph needs a measured per-ISO noise characterisation, not a guess.
Conversion
MLX NHWC. Two different 4-D transposes, and they cannot be told apart by shape:
| PyTorch | MLX | transpose | |
|---|---|---|---|
Conv2d |
(O, I, kH, kW) |
(O, kH, kW, I) |
(0,2,3,1) |
ConvTranspose2d |
(I, O, kH, kW) |
(O, kH, kW, I) |
(1,2,3,0) |
m_down3.4.weight (strideconv 256β512) and m_up3.0.weight (transposed 512β256) are both
(512, 256, 2, 2) with opposite meanings. The wrong transpose loads clean and is silently wrong.
Only the key discriminates: exactly m_up{1,2,3}.0.weight are transposed.
Parity
Gated against the PyTorch oracle on the CPU stream, fp32, relative error:
- key contract β 64 tensors / 32,640,960 params / 0 missing / 0 unused, strict load
- primitives β 5/5; the transposed conv is bit-identical (0.00e+00)
- Ο sweep β 4/4 at cosine 1.00000000, with the monotonic response asserted
Weights: MIT, published first-party by the author in the
cszn/KAIR v1.0 release. Port code: MIT.
(Third-party mirrors tagged bsd-3-clause carry the DeepInverse library's licence, not this
model's β this build does not use them.)
Quantized