Low-light denoising + 4x super-resolution

Trained for Kaggle competition dlp-26t2-nppe3. Public leaderboard 39.85 dB PSNR.

The task is posed as super-resolution but is mostly denoising. Bicubic upsampling of the noisy input scores 33.36 dB; bicubic upsampling of a clean low-resolution image scores 41.19 dB. About 7.8 of the 8 dB available is therefore denoising, so all 24 residual blocks run at low resolution and the upsampling is a thin pixel-shuffle branch on top of a bicubic base.

The grader scores PIL.Image.convert('L') only. Because the noise is independent across channels (measured cross-channel correlation +0.001), that projection removes about 55% of its variance for free, so the network predicts luma directly with a single output channel and writes mode-L PNGs.

The degradation was identified exactly as LR = box_downsample(HR, 4) - 0.70 + n, with n white, per-channel independent, sigma 10.32/255, excess kurtosis +0.42. Real noise fields are therefore lifted off one training image and added to another, giving a fresh noise realisation every step instead of one fixed realisation per image.

Usage

import torch
from huggingface_hub import hf_hub_download
from train_ddp import DenoiseSR                # train_ddp.py is in this repo

ck = torch.load(hf_hub_download("ChemYukti/denoise-sr4x-dlp26t2nppe3", "model.pt"), map_location="cpu")
model = DenoiseSR(ck["nf"], ck["nb"])
model.load_state_dict(ck["sd"]); model.eval()

Input is float RGB in [0,1], shape (B,3,H,W). Returns (hr_luma, denoised_lr_luma); the first is the prediction, at 4x the input size. Averaging the 8 rotation/flip variants at inference is worth about +0.03 dB.

Training

160 channels, 24 residual blocks with channel attention on every 4th, 11.73 M parameters. Charbonnier for the first 60% then MSE, AdamW, cosine to 1e-6, EMA 0.999, fp16 with channels_last, 2x Tesla T4 via DistributedDataParallel, 80,000 iterations at effective batch 32.

Results

PSNR
bicubic from noisy LR 33.36 dB
bicubic from clean LR (denoising-only ceiling) 41.19 dB
this model, 40 held-out images 39.00 dB
public leaderboard 39.85 dB

Held-out means 40 validation images excluded from training entirely. Scores over all 267 validation images come out about 0.5 dB higher and are not comparable, since 227 of them were in the training set.

The 39.92 dB leaderboard entry came from a sibling run of this same pipeline (128 channels, 32 blocks, 126,779 iterations). Its checkpoint was lost to a failed Kaggle commit, so the weights published here are the 160-channel, 24-block variant, 0.08 dB behind on held-out data.

Downloads last month

-

Downloads are not tracked for this model. How to track
Inference Providers NEW
This model isn't deployed by any Inference Provider. 🙋 Ask for provider support