See in the dark, without the artifacts.

resenh restores low-light photos with an adaptive hybrid: classical Retinex, CLAHE and edge-preserving denoising, plus a fine-tuned Retinexformer. A quality controller checks every candidate for blown highlights, colour shift, lost detail and amplified noise before fusing them.

🔒 Runs on your device: the photo is never uploaded 🐍 the real resenh Python package, in your browser ⚙️ engine: loading…
Your result appears herePick a photo or a sample. Drag the slider to compare before and after.

How it works

01

Analyse

Brightness, dark-pixel share, noise σ (Immerkaer), colour cast, uneven lighting and highlights are measured, and every downstream parameter is set from them.

02

Classical branch

Max-RGB illumination refined by a guided filter, then Retinex/LIME gain, CLAHE on luminance, noise-adaptive guided denoising, gray-world white balance and highlight protection.

03

Hybrid network

Retinexformer (ICCV'23), fine-tuned with the GT-mean loss, with the classical illumination map and outputs fed in as extra prior channels.

04

Quality controller

Each candidate is scored for new clipping, chroma shift, edge loss, noise amplification and exposure error, then softmax-fused. Its decision is shown above.

Use it in Python

pip install "resenh[dl]"

import resenh
res = resenh.enhance("night.jpg")          # adaptive hybrid
resenh.save_image(res.image, "out.png")
res.decision                                # what the controller chose, and why

This page runs that same package through Pyodide (WebAssembly), with the network in ONNX Runtime Web. At the same resolution, the WebAssembly engine matches the native package to within 1/255. The faster WebGPU engine agrees with it to about 39 dB PSNR, which is visually identical. The page runs the network at up to 640 or 960 px; for full-resolution photos, use the Python package. Results with plain PSNR, SSIM, LPIPS, NIQE, latency and noise/edge metrics, the ablation and the failure analysis are in the repository.