Low-Light Denoising + 4x Super-Resolution

RRDBNet (Real-ESRGAN generator architecture), fine-tuned from Real-ESRGAN's pretrained RealESRGAN_x4plus weights on paired low-light noisy/clean image data. Trained with Charbonnier + SSIM pixel loss only β€” no adversarial or perceptual loss β€” since the goal is pixel-accurate reconstruction (PSNR), not hallucinated texture.

Validation PSNR: 39.51 dB

Files

  • best.pt β€” trained model checkpoint (contains model_state, the epoch, best validation PSNR, and the training config it was produced under)
  • model.py β€” architecture definition needed to load the checkpoint
  • config.json β€” architecture configuration (layer sizes, block count, scale factor, training settings) used to build the model before loading the weights

Usage

import json
import torch
import numpy as np
from PIL import Image
from model import RRDBNet

# Load the architecture configuration
with open("config.json") as f:
    cfg = json.load(f)

# Build the model using the saved configuration
model = RRDBNet(
    num_in_ch=cfg["num_in_ch"],
    num_out_ch=cfg["num_out_ch"],
    scale=cfg["scale"],
    num_feat=cfg["num_feat"],
    num_block=cfg["num_block"],
    num_grow_ch=cfg["num_grow_ch"],
)

# Load trained weights
ckpt = torch.load("best.pt", map_location="cpu")
model.load_state_dict(ckpt["model_state"])
model.eval()

print("Validation PSNR at save time:", ckpt["best_psnr"])

# Run inference on a low-light noisy image
img = Image.open("your_low_light_image.png").convert("RGB")
x = torch.from_numpy(np.asarray(img, dtype=np.float32) / 255.0).permute(2, 0, 1).unsqueeze(0)

with torch.no_grad():
    out = model(x).clamp(0, 1)

out_img = (out[0].permute(1, 2, 0).numpy() * 255).astype(np.uint8)
Image.fromarray(out_img).save("denoised_4x_output.png")

Architecture

  • RRDB (Residual-in-Residual Dense Block) trunk, 23 blocks, 64 features, 32 growth channels per block β€” identical structure to Real-ESRGAN's generator
  • No batch normalization (preserves per-image noise/illumination statistics needed for denoising)
  • Nearest-neighbor upsample + conv (2x β†’ 2x) for the 4x total upsampling
  • Input: low-light, noisy, low-resolution RGB image, values in [0, 1], shape (B, 3, H, W)
  • Output: denoised, super-resolved RGB image, shape (B, 3, 4H, 4W)

Full configuration values are in config.json.

Training

  • Initialized from Real-ESRGAN's public RealESRGAN_x4plus.pth pretrained weights (strict key-for-key match, all 702 tensors loaded)
  • Fine-tuned on paired low-light noisy (LR) / clean (HR) images
  • Loss: Charbonnier (smooth L1) + 0.1 Γ— (1 βˆ’ SSIM)
  • Optimizer: AdamW, cosine learning-rate schedule, mixed precision (loss computed in fp32 to avoid NaN gradients from the SSIM term)
  • 60 epochs, learning rate 5e-5, best validation PSNR 39.51 dB
Downloads last month
12
Inference Providers NEW
This model isn't deployed by any Inference Provider. πŸ™‹ Ask for provider support