<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: for IT the</title>
    <description>The latest articles on DEV Community by for IT the (@for_itthe_9cb5ee8d4b91f2).</description>
    <link>https://dev.to/for_itthe_9cb5ee8d4b91f2</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3968028%2F8009423d-4a80-413a-a4c2-2e5df60128ba.png</url>
      <title>DEV Community: for IT the</title>
      <link>https://dev.to/for_itthe_9cb5ee8d4b91f2</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/for_itthe_9cb5ee8d4b91f2"/>
    <language>en</language>
    <item>
      <title>Image Reconstruction Using Deep Learning: A Complete Guide</title>
      <dc:creator>for IT the</dc:creator>
      <pubDate>Fri, 12 Jun 2026 11:31:09 +0000</pubDate>
      <link>https://dev.to/for_itthe_9cb5ee8d4b91f2/image-reconstruction-using-deep-learning-a-complete-guide-1fp2</link>
      <guid>https://dev.to/for_itthe_9cb5ee8d4b91f2/image-reconstruction-using-deep-learning-a-complete-guide-1fp2</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;A comprehensive guide covering history, techniques, datasets, algorithms, tools, real-world applications, and final year project ideas for image reconstruction using deep learning.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Introduction&lt;/li&gt;
&lt;li&gt;History and Evolution of Image Reconstruction&lt;/li&gt;
&lt;li&gt;Types of Image Reconstruction&lt;/li&gt;
&lt;li&gt;How Deep Learning Transformed Image Reconstruction&lt;/li&gt;
&lt;li&gt;Top Datasets for Image Reconstruction&lt;/li&gt;
&lt;li&gt;Popular Algorithms and Architectures&lt;/li&gt;
&lt;li&gt;Evaluation Metrics Explained&lt;/li&gt;
&lt;li&gt;Tools and Frameworks for Image Reconstruction&lt;/li&gt;
&lt;li&gt;Real-World Applications&lt;/li&gt;
&lt;li&gt;Image Reconstruction as a Final Year Project&lt;/li&gt;
&lt;li&gt;Step-by-Step Implementation Guide&lt;/li&gt;
&lt;li&gt;Challenges in Image Reconstruction&lt;/li&gt;
&lt;li&gt;Future Trends and Research Directions&lt;/li&gt;
&lt;li&gt;Conclusion&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  1. Introduction
&lt;/h2&gt;

&lt;p&gt;Image reconstruction is one of the most fundamental and impactful challenges in computer vision and digital imaging. At its core, image reconstruction refers to the process of recovering a high-quality, complete, or enhanced image from a degraded, incomplete, or low-quality input. Whether the input image suffers from low resolution, noise, missing pixels, blur, or compression artifacts, image reconstruction techniques aim to restore the image to its original — or even better — quality.&lt;/p&gt;

&lt;p&gt;In today's world, image reconstruction has moved far beyond academic research labs. It is actively used in medical diagnostics, satellite imaging, film restoration, surveillance systems, and even smartphone photography. Every time your phone camera takes a sharp photo in dim light, or a radiologist reads an MRI scan with enhanced contrast, image reconstruction algorithms are working silently in the background.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why Image Reconstruction Matters
&lt;/h3&gt;

&lt;p&gt;The need for image reconstruction arises from a fundamental reality: images captured in the real world are rarely perfect. Cameras have physical limitations. Sensors introduce noise. Bandwidth constraints force compression. Distance reduces detail. Environmental factors like fog, rain, or motion blur degrade quality. In many critical fields — medicine, security, space exploration — the cost of a poor-quality image can be enormous. A blurry X-ray might miss a tumor. A low-resolution satellite image might miss a building structure. A degraded surveillance frame might fail to identify a suspect.&lt;/p&gt;

&lt;p&gt;This is why image reconstruction has become such a critical area of research and development. The ability to recover clean, high-resolution, and accurate images from imperfect inputs is not just a technical achievement — it is a capability with profound real-world consequences.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Deep Learning Revolution
&lt;/h3&gt;

&lt;p&gt;For decades, image reconstruction relied on mathematical models, hand-crafted filters, and signal processing techniques. While these classical methods made significant contributions, they had inherent limitations. They struggled with complex real-world degradations, required domain-specific expertise to tune, and often produced overly smooth or artifact-prone outputs.&lt;/p&gt;

&lt;p&gt;The arrival of deep learning changed everything. Convolutional Neural Networks (CNNs), Generative Adversarial Networks (GANs), Vision Transformers, and most recently, Diffusion Models, have pushed the boundaries of what is possible in image reconstruction. These models can learn complex mappings from degraded to clean images directly from data, without requiring explicit mathematical formulations of the degradation process.&lt;/p&gt;

&lt;h3&gt;
  
  
  Scope of This Article
&lt;/h3&gt;

&lt;p&gt;This article provides a complete, in-depth guide to image reconstruction using deep learning. We cover the history, the types of reconstruction tasks, the most important datasets, the leading algorithms and architectures, evaluation metrics, tools and frameworks, real-world applications, and a practical guide for students looking to build their own image reconstruction projects. Whether you are a researcher, a developer, or a final year engineering student, this guide will give you everything you need to understand and work with modern image reconstruction systems.&lt;/p&gt;




&lt;h2&gt;
  
  
  2. History and Evolution of Image Reconstruction
&lt;/h2&gt;

&lt;p&gt;Understanding where image reconstruction came from helps us appreciate how far it has come and where it is going. The field has evolved through several distinct phases, each defined by the dominant methodologies of the era.&lt;/p&gt;

&lt;h3&gt;
  
  
  2.1 The Classical Era: Signal Processing and Mathematical Models (1960s–1990s)
&lt;/h3&gt;

&lt;p&gt;The earliest work in image reconstruction was rooted in signal processing and linear algebra. Researchers approached image degradation as a mathematical problem: if a clean image is convolved with a degradation kernel (such as a blur) and corrupted by noise, can we invert this process to recover the original?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Wiener Filtering&lt;/strong&gt;, developed in the 1940s and applied to images in the 1960s, was one of the first systematic approaches. It minimized the mean squared error between the estimated and true image using statistical properties of the signal and noise. While mathematically elegant, Wiener filtering required knowledge of the noise power spectrum and the image's power spectrum, which are rarely available in practice.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Total Variation (TV) Regularization&lt;/strong&gt;, introduced by Rudin, Osher, and Fatemi in 1992, became another cornerstone technique. It preserved edges while removing noise by minimizing the total variation of the image — essentially penalizing rapid changes in pixel intensity except at true edges. TV-based methods became widely used in medical imaging and remain relevant today in certain applications.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Compressed Sensing&lt;/strong&gt;, developed in the mid-2000s by Candès, Romberg, Tao, and Donoho, introduced a revolutionary idea: if a signal is sparse in some domain, it can be perfectly reconstructed from far fewer measurements than the Nyquist theorem traditionally required. This theoretical breakthrough had enormous implications for MRI imaging, where reducing scan time could translate directly to better patient care.&lt;/p&gt;

&lt;p&gt;The limitation of all these classical methods was their reliance on explicit mathematical models of both the image and the degradation. Real-world images and degradation processes are far too complex to be captured by simple mathematical models. This motivated the shift toward learning-based approaches.&lt;/p&gt;

&lt;h3&gt;
  
  
  2.2 The Machine Learning Era (2000s–2012)
&lt;/h3&gt;

&lt;p&gt;As machine learning became mainstream in the 2000s, researchers began applying it to image reconstruction problems. Sparse coding and dictionary learning approaches — such as the K-SVD algorithm — treated image patches as sparse combinations of atoms from a learned dictionary. These methods showed significant improvements over classical techniques, especially for denoising and super-resolution.&lt;/p&gt;

&lt;p&gt;Gaussian Mixture Models (GMMs) and other probabilistic models were used to learn the distribution of natural image patches. The Expected Patch Log Likelihood (EPLL) framework by Zoran and Weiss (2011) showed that modeling the prior distribution of natural image patches could lead to excellent reconstruction results.&lt;/p&gt;

&lt;p&gt;However, these methods were still limited. They required careful feature engineering, slow iterative optimization at test time, and did not scale well to large images or complex degradation patterns.&lt;/p&gt;

&lt;h3&gt;
  
  
  2.3 The Deep Learning Revolution (2012–Present)
&lt;/h3&gt;

&lt;p&gt;The publication of AlexNet in 2012 marked a turning point for all of computer vision, and image reconstruction was no exception. Researchers quickly realized that deep convolutional neural networks could learn far more powerful representations of image structure than any hand-crafted method.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;SRCNN (Super-Resolution Convolutional Neural Network)&lt;/strong&gt;, published by Dong et al. in 2014, was the first deep learning method applied to image super-resolution. It demonstrated that even a shallow three-layer CNN could outperform all previous methods on standard benchmarks. This opened the floodgates for deep learning research in image reconstruction.&lt;/p&gt;

&lt;p&gt;Over the next decade, the field witnessed a rapid succession of innovations: residual learning, dense connections, attention mechanisms, adversarial training, and ultimately transformer-based and diffusion-based models. Each advancement pushed the state of the art further, enabling reconstructions that were increasingly indistinguishable from real high-quality images.&lt;/p&gt;

&lt;p&gt;Today, deep learning dominates image reconstruction across all sub-tasks, and the field continues to advance at a remarkable pace.&lt;/p&gt;

&lt;h3&gt;
  
  
  2.4 Key Milestones Timeline
&lt;/h3&gt;

&lt;p&gt;Understanding the progression of the field through key milestones helps contextualize where current research fits:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;1992&lt;/strong&gt; — Total Variation Regularization (Rudin, Osher, Fatemi) establishes the mathematical foundation for edge-preserving reconstruction&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;2006&lt;/strong&gt; — Compressed Sensing theory published (Candès, Romberg, Tao; Donoho) — enables reconstruction from far fewer measurements than traditionally required&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;2007&lt;/strong&gt; — BM3D denoising algorithm published — remains the gold standard classical denoising baseline&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;2010&lt;/strong&gt; — Sparse coding and dictionary learning reach maturity for SR tasks&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;2014&lt;/strong&gt; — SRCNN published — the first deep learning super-resolution method&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;2016&lt;/strong&gt; — VDSR introduces residual learning for SR — enables very deep networks&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;2017&lt;/strong&gt; — SRGAN introduces adversarial training and perceptual loss for photo-realistic SR&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;2017&lt;/strong&gt; — DnCNN demonstrates deep learning superiority for image denoising&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;2018&lt;/strong&gt; — ESRGAN wins PIRM 2018 challenge — sets new standard for perceptual SR quality&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;2018&lt;/strong&gt; — RCAN introduces channel attention for SR&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;2020&lt;/strong&gt; — NeRF revolutionizes 3D scene reconstruction from 2D images&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;2021&lt;/strong&gt; — SwinIR demonstrates transformer superiority for image restoration&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;2022&lt;/strong&gt; — Diffusion models achieve state-of-the-art perceptual quality for image restoration&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;2023–2026&lt;/strong&gt; — Foundation models and real-time diffusion bring universal restoration closer to production deployment&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This timeline illustrates the accelerating pace of innovation in the field. What took decades to achieve in the classical era now happens in months.&lt;/p&gt;




&lt;h2&gt;
  
  
  3. Types of Image Reconstruction
&lt;/h2&gt;

&lt;p&gt;Image reconstruction is not a single task but a family of related problems. Each type of reconstruction addresses a different kind of image degradation or incompleteness. Understanding these categories is essential for selecting the right approach for a given application.&lt;/p&gt;

&lt;h3&gt;
  
  
  3.1 Image Super-Resolution
&lt;/h3&gt;

&lt;p&gt;Super-resolution (SR) is perhaps the most widely studied form of image reconstruction. The goal is to recover a high-resolution (HR) image from one or more low-resolution (LR) inputs. The LR image typically contains less detail due to downsampling, which may have been performed with bicubic interpolation or by a more complex camera degradation process.&lt;/p&gt;

&lt;p&gt;Super-resolution has applications in surveillance (enhancing camera footage), medical imaging (improving scan quality), satellite imaging (increasing spatial resolution), and consumer photography (computational zoom). The challenge lies in recovering fine details that are fundamentally lost during downsampling — a problem that is inherently ill-posed since many HR images can correspond to the same LR input.&lt;/p&gt;

&lt;h3&gt;
  
  
  3.2 Image Inpainting
&lt;/h3&gt;

&lt;p&gt;Inpainting refers to the task of filling in missing or corrupted regions of an image. The missing regions might be caused by scratches on old photographs, watermarks, occlusions, or deliberately removed objects. A good inpainting algorithm must not only fill the missing region with plausible content but also ensure that the filled region is seamlessly consistent with the surrounding image in terms of texture, color, and structure.&lt;/p&gt;

&lt;p&gt;Modern deep learning approaches, particularly those based on GANs and diffusion models, have achieved remarkable results in image inpainting, often generating completions that are visually indistinguishable from real image content.&lt;/p&gt;

&lt;h3&gt;
  
  
  3.3 Image Denoising
&lt;/h3&gt;

&lt;p&gt;Noise is a pervasive problem in digital images, arising from sensor limitations, low-light conditions, transmission errors, and compression artifacts. Image denoising aims to remove this noise while preserving the true signal — the underlying image content.&lt;/p&gt;

&lt;p&gt;Classical denoising methods like Gaussian filtering and median filtering are fast but produce overly smooth results. The BM3D (Block-Matching and 3D Filtering) algorithm was long considered the gold standard for denoising. Deep learning methods, starting with DnCNN (Denoising CNN) by Zhang et al. in 2017, have since surpassed BM3D by significant margins while being much faster at test time.&lt;/p&gt;

&lt;h3&gt;
  
  
  3.4 Compressed Sensing Reconstruction
&lt;/h3&gt;

&lt;p&gt;In compressed sensing, a signal is acquired through a small number of random linear measurements — far fewer than the signal's dimensionality. The reconstruction problem is to recover the original signal from these measurements. This is particularly important in MRI imaging, where the number of measurements directly determines the scan time. Reducing scan time from 30 minutes to 5 minutes can make MRI accessible to many more patients.&lt;/p&gt;

&lt;p&gt;Deep learning has revolutionized compressed sensing reconstruction, enabling high-quality recovery from extremely undersampled measurements that classical methods could not handle.&lt;/p&gt;

&lt;h3&gt;
  
  
  3.5 Medical Image Reconstruction (MRI and CT)
&lt;/h3&gt;

&lt;p&gt;Medical imaging presents unique reconstruction challenges. MRI scanners acquire data in the frequency domain (k-space) and must reconstruct the spatial image from this data. CT scanners reconstruct cross-sectional images from projection data (sinograms). Both tasks are inverse problems with significant noise and potential undersampling.&lt;/p&gt;

&lt;p&gt;Deep learning methods for medical image reconstruction must satisfy extremely high accuracy requirements, since errors can have life-or-death consequences. This makes this subfield particularly demanding and actively researched.&lt;/p&gt;

&lt;h3&gt;
  
  
  3.6 3D Image Reconstruction
&lt;/h3&gt;

&lt;p&gt;3D reconstruction refers to the recovery of three-dimensional structure from 2D observations — such as reconstructing a 3D scene from multiple 2D photographs. This is a core problem in robotics, augmented reality, autonomous driving, and cultural heritage preservation.&lt;/p&gt;

&lt;p&gt;Neural Radiance Fields (NeRF), introduced in 2020, represented a breakthrough in neural 3D reconstruction, enabling photorealistic novel view synthesis from a sparse set of input images.&lt;/p&gt;




&lt;h2&gt;
  
  
  4. How Deep Learning Transformed Image Reconstruction
&lt;/h2&gt;

&lt;p&gt;Deep learning has fundamentally changed the approach to image reconstruction. Instead of designing algorithms based on mathematical models of image formation and degradation, deep learning allows us to directly learn the mapping from degraded to clean images from data. This section explores the major deep learning paradigms that have shaped modern image reconstruction.&lt;/p&gt;

&lt;h3&gt;
  
  
  4.1 CNN-Based Methods
&lt;/h3&gt;

&lt;p&gt;Convolutional Neural Networks were the first deep learning architecture to be successfully applied to image reconstruction. Their ability to learn hierarchical feature representations through convolutional layers makes them naturally suited to image-to-image mapping tasks.&lt;/p&gt;

&lt;p&gt;The key insight is that image reconstruction can be formulated as a regression problem: given a degraded input image, predict the clean output image. CNNs are trained on pairs of degraded and clean images using a pixel-wise loss function, typically mean squared error (MSE) or mean absolute error (MAE).&lt;/p&gt;

&lt;p&gt;Residual learning, introduced for image reconstruction by VDSR (Very Deep Super-Resolution, Kim et al., 2016), proved to be a critical innovation. Instead of directly predicting the clean image, the network learns to predict the residual — the difference between the degraded and clean image. This simplifies the learning problem significantly and enables the training of much deeper networks.&lt;/p&gt;

&lt;p&gt;Dense connections, as used in RDN (Residual Dense Network, Zhang et al., 2018), allow each layer to access feature maps from all preceding layers, enabling maximum information flow and feature reuse. This leads to more expressive networks and better reconstruction quality.&lt;/p&gt;

&lt;h3&gt;
  
  
  4.2 GAN-Based Methods
&lt;/h3&gt;

&lt;p&gt;Generative Adversarial Networks (GANs), introduced by Goodfellow et al. in 2014, brought a new perspective to image reconstruction. Instead of training a network to minimize pixel-wise loss — which tends to produce blurry, over-smoothed outputs — GANs introduce a discriminator network that learns to distinguish between real and reconstructed images.&lt;/p&gt;

&lt;p&gt;The generator (the reconstruction network) is trained to fool the discriminator, while the discriminator is trained to correctly classify images as real or generated. This adversarial training process pushes the generator to produce outputs that are perceptually realistic, with fine textures and sharp edges that pixel-wise loss functions cannot capture.&lt;/p&gt;

&lt;p&gt;SRGAN (Super-Resolution GAN, Ledig et al., 2017) was the first method to demonstrate photorealistic 4× super-resolution. Its successor ESRGAN (Enhanced SRGAN, Wang et al., 2018) further improved quality and won the PIRM 2018 Super-Resolution Challenge.&lt;/p&gt;

&lt;p&gt;GAN-based methods have also been highly successful for image inpainting, face hallucination, and blind image restoration.&lt;/p&gt;

&lt;h3&gt;
  
  
  4.3 Transformer-Based Methods
&lt;/h3&gt;

&lt;p&gt;The Vision Transformer (ViT), introduced by Dosovitskiy et al. in 2020, demonstrated that transformer architectures originally designed for natural language processing could be highly effective for image understanding tasks. This sparked a wave of transformer-based methods for image reconstruction.&lt;/p&gt;

&lt;p&gt;SwinIR (Swin Transformer for Image Restoration, Liang et al., 2021) became the dominant transformer-based reconstruction model. It uses the Swin Transformer's shifted window attention mechanism, which computes self-attention within local windows while allowing cross-window connections. This design achieves an excellent balance between local and global context, which is critical for image reconstruction tasks that require both local texture recovery and global structure coherence.&lt;/p&gt;

&lt;p&gt;Transformers have demonstrated superior performance over CNNs on multiple reconstruction benchmarks, particularly for tasks that require modeling long-range dependencies — such as recovering large missing regions in inpainting or reconstructing consistent global structure in super-resolution.&lt;/p&gt;

&lt;h3&gt;
  
  
  4.4 Diffusion Model-Based Methods
&lt;/h3&gt;

&lt;p&gt;Diffusion models, which emerged as the leading generative modeling paradigm around 2020–2022, have recently been applied with great success to image reconstruction. Diffusion models learn to generate images by reversing a gradual noising process: they are trained to iteratively denoise images starting from pure Gaussian noise.&lt;/p&gt;

&lt;p&gt;For image reconstruction, diffusion models can be conditioned on the degraded input image to guide the generation process toward a reconstruction consistent with the observed input. This conditioning can be achieved through various mechanisms, including classifier guidance, classifier-free guidance, and direct conditioning in the network architecture.&lt;/p&gt;

&lt;p&gt;Diffusion-based reconstruction methods achieve state-of-the-art perceptual quality, often surpassing GANs in terms of output diversity and fidelity. However, they are significantly slower than feed-forward CNN or GAN methods due to the iterative denoising process required at test time.&lt;/p&gt;




&lt;h2&gt;
  
  
  5. Top Datasets for Image Reconstruction
&lt;/h2&gt;

&lt;p&gt;The quality and diversity of training and evaluation data are critical determinants of reconstruction model performance. Over the years, the research community has developed a rich ecosystem of benchmark datasets for image reconstruction. Here are the three most important datasets, along with notable honorable mentions.&lt;/p&gt;

&lt;h3&gt;
  
  
  5.1 DIV2K — The Gold Standard for Training
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;DIV2K (Diverse 2K Resolution Images)&lt;/strong&gt; is by far the most widely used dataset for training and evaluating image reconstruction models, particularly in the super-resolution domain. Originally introduced for the NTIRE (New Trends in Image Restoration and Enhancement) Challenge, DIV2K has become the de facto standard training set for learning-based reconstruction methods.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Dataset Composition:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;800 high-resolution training images&lt;/li&gt;
&lt;li&gt;100 high-resolution validation images&lt;/li&gt;
&lt;li&gt;100 high-resolution test images&lt;/li&gt;
&lt;li&gt;Images available at multiple degradation scales: ×2, ×3, ×4, ×8&lt;/li&gt;
&lt;li&gt;Degradation types: bicubic downsampling, realistic degradation tracks&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Why DIV2K Stands Out:&lt;/strong&gt;&lt;br&gt;
DIV2K was carefully curated to include a wide diversity of image content — people, nature, architecture, food, animals, text, and more. The images are of genuine 2K resolution, meaning they contain fine details that are truly challenging to recover. This diversity makes models trained on DIV2K highly generalizable across different types of images and scenes.&lt;/p&gt;

&lt;p&gt;The dataset also provides paired LR-HR image pairs under multiple degradation settings, making it immediately useful for supervised training without additional preprocessing. The NTIRE community has continued to extend the dataset with additional degradation tracks, keeping it relevant for the latest research trends.&lt;/p&gt;

&lt;p&gt;For final year projects and research papers involving image reconstruction, DIV2K is the recommended primary training dataset. It is publicly available, widely cited, and results on DIV2K benchmarks are directly comparable to state-of-the-art published methods. Students exploring &lt;a href="https://projectcentersinchennai.co.in/ieee-domains/image-generation-projects-for-final-year/" rel="noopener noreferrer"&gt;Image Generation Projects&lt;/a&gt; will find DIV2K to be the most straightforward starting point for training any reconstruction model.&lt;/p&gt;
&lt;h3&gt;
  
  
  5.2 CelebA-HQ — The Face Reconstruction Benchmark
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;CelebA-HQ (Large-scale CelebFaces Attributes High Quality)&lt;/strong&gt; is the premium face image dataset for image reconstruction research. It is an extended version of the original CelebA dataset, providing dramatically higher image quality.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Dataset Composition:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;30,000 high-resolution face images at 1024×1024 resolution&lt;/li&gt;
&lt;li&gt;Derived from the original CelebA dataset of 202,599 celebrity face images&lt;/li&gt;
&lt;li&gt;Clean, well-aligned face images with consistent composition&lt;/li&gt;
&lt;li&gt;Used alongside FFHQ (Flickr-Faces-HQ) for face-specific reconstruction tasks&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Why CelebA-HQ Matters:&lt;/strong&gt;&lt;br&gt;
Face images present unique reconstruction challenges and opportunities. Human faces have strong structural priors — we know that faces have eyes, noses, mouths, and specific spatial relationships between these features. This prior knowledge can be leveraged by reconstruction models to achieve remarkable results even from severely degraded inputs.&lt;/p&gt;

&lt;p&gt;CelebA-HQ is the standard benchmark for evaluating face super-resolution, face inpainting, and blind face restoration methods. Notable models like GFPGAN, CodeFormer, and RestoreFormer were all evaluated on CelebA-HQ.&lt;/p&gt;

&lt;p&gt;The high resolution and clean composition of CelebA-HQ also make it excellent for training generative models, since the model can learn fine facial details that are critical for photorealistic face reconstruction. The consistent face alignment simplifies the learning problem while still providing substantial diversity in age, ethnicity, expression, and lighting.&lt;/p&gt;

&lt;p&gt;For students working on face-specific image reconstruction projects, CelebA-HQ is the essential dataset. Paired with FFHQ for training and CelebA-HQ for evaluation, this combination represents the standard experimental setup in the face restoration literature.&lt;/p&gt;
&lt;h3&gt;
  
  
  5.3 Urban100 — The Structural Reconstruction Challenge
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Urban100&lt;/strong&gt; is a benchmark dataset specifically designed to challenge image reconstruction models on high-frequency structural content — particularly architectural and urban scenes with repetitive patterns, sharp edges, and fine geometric detail.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Dataset Composition:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;100 high-resolution images of urban scenes&lt;/li&gt;
&lt;li&gt;Focused exclusively on man-made structures: buildings, bridges, fences, windows, roads&lt;/li&gt;
&lt;li&gt;Rich in regular patterns and sharp edges — content that tests structural reconstruction fidelity&lt;/li&gt;
&lt;li&gt;Used exclusively as a test set (not for training)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Why Urban100 Is Uniquely Challenging:&lt;/strong&gt;&lt;br&gt;
Urban scenes with regular patterns and sharp geometric structures are notoriously difficult for super-resolution and reconstruction models. These structures require the model to correctly reconstruct regular, repeated patterns like window grids and brick walls — errors that would be less noticeable in natural scenes become highly visible in urban images.&lt;/p&gt;

&lt;p&gt;Urban100 consistently reveals the differences between reconstruction methods that struggle with aliasing artifacts and those that can correctly recover structural patterns. It has become the standard test for evaluating a model's ability to reconstruct high-frequency details and avoid grid artifacts.&lt;/p&gt;

&lt;p&gt;For research papers, reporting performance on Urban100 alongside other benchmarks (Set5, Set14, BSD100) provides a comprehensive picture of a model's capabilities across different types of image content.&lt;/p&gt;
&lt;h3&gt;
  
  
  5.4 Honorable Mentions
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Set5 and Set14&lt;/strong&gt; are classical small-scale benchmark datasets with 5 and 14 test images respectively. Despite their small size, they remain widely used for quick evaluation and comparison due to their long history in the literature.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;BSD100 (Berkeley Segmentation Dataset 100)&lt;/strong&gt; contains 100 natural images covering a wide range of scenes, from people to animals to food. It provides a good general-purpose benchmark for natural image reconstruction.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;FFHQ (Flickr-Faces-HQ)&lt;/strong&gt; contains 70,000 high-quality face images at 1024×1024 resolution and is widely used for training face reconstruction models.&lt;/p&gt;


&lt;h2&gt;
  
  
  6. Popular Algorithms and Architectures
&lt;/h2&gt;

&lt;p&gt;The image reconstruction field has produced a rich lineage of algorithms, each building on the insights of its predecessors. This section covers the most important architectures from the early CNN era to the current state of the art.&lt;/p&gt;
&lt;h3&gt;
  
  
  6.1 SRCNN — The Pioneer (2014)
&lt;/h3&gt;

&lt;p&gt;SRCNN (Super-Resolution Convolutional Neural Network) by Dong et al. was the first deep learning method for image super-resolution. It consists of just three convolutional layers: one for patch extraction and representation, one for nonlinear mapping, and one for reconstruction. Despite its simplicity, SRCNN outperformed all previous methods on standard benchmarks and established the framework for all subsequent deep SR methods.&lt;/p&gt;

&lt;p&gt;SRCNN operates on the bicubic-upsampled LR image, meaning the LR image is first upsampled to the target HR size before being processed by the network. This approach, while computationally inefficient (since the CNN operates at the full HR resolution), was standard practice until more efficient subpixel convolution and deconvolution approaches were developed.&lt;/p&gt;
&lt;h3&gt;
  
  
  6.2 VDSR — Going Deep with Residuals (2016)
&lt;/h3&gt;

&lt;p&gt;VDSR (Very Deep Super-Resolution) by Kim et al. was the first to demonstrate the benefit of very deep networks (up to 20 layers) for super-resolution, made possible by residual learning. Instead of learning the full mapping from LR to HR, VDSR learns the high-frequency residual that, when added to the bicubic-upsampled LR image, yields the HR output.&lt;/p&gt;

&lt;p&gt;Residual learning dramatically simplified the optimization problem and enabled the training of networks too deep for direct mapping to converge. VDSR also introduced the use of a large learning rate with gradient clipping, a training trick that accelerated convergence significantly.&lt;/p&gt;
&lt;h3&gt;
  
  
  6.3 EDSR — Enhanced Deep Residual Networks (2017)
&lt;/h3&gt;

&lt;p&gt;EDSR (Enhanced Deep Residual Networks for Single Image Super-Resolution) by Lim et al. won the NTIRE 2017 Super-Resolution Challenge and became a landmark architecture. EDSR made two key modifications to the standard residual network architecture: it removed the batch normalization layers (which were found to reduce performance for SR) and scaled the residual features.&lt;/p&gt;

&lt;p&gt;By removing batch normalization, EDSR could use larger mini-batches and train deeper networks without instability. The resulting model achieved state-of-the-art performance on all standard benchmarks (Set5, Set14, BSD100, Urban100) at the time of publication and remains a strong baseline today.&lt;/p&gt;
&lt;h3&gt;
  
  
  6.4 SRGAN and ESRGAN — Perceptual Super-Resolution (2017–2018)
&lt;/h3&gt;

&lt;p&gt;SRGAN by Ledig et al. introduced the use of GANs for photo-realistic super-resolution. The key innovation was the use of a perceptual loss function, which measures similarity in a feature space learned by a pre-trained VGG network rather than in pixel space. This perceptual loss, combined with adversarial training, enabled SRGAN to produce visually sharp and textured outputs that were more realistic than the smooth outputs of pixel-loss methods.&lt;/p&gt;

&lt;p&gt;ESRGAN (Enhanced SRGAN) by Wang et al. improved upon SRGAN by using a Residual-in-Residual Dense Block (RRDB) architecture for the generator and a relativistic discriminator that evaluates whether real images are more realistic than generated images (rather than just classifying real vs. fake). ESRGAN set a new standard for perceptual super-resolution quality and won the PIRM 2018 challenge.&lt;/p&gt;
&lt;h3&gt;
  
  
  6.5 U-Net — The Swiss Army Knife of Reconstruction (2015)
&lt;/h3&gt;

&lt;p&gt;U-Net, originally designed for biomedical image segmentation by Ronneberger et al., has become one of the most widely used architectures in image reconstruction. Its encoder-decoder structure with skip connections allows the network to combine low-level spatial details (from the encoder) with high-level semantic information (from the decoder) — a property that is highly beneficial for reconstruction tasks.&lt;/p&gt;

&lt;p&gt;U-Net is the backbone architecture for many state-of-the-art reconstruction methods, including medical image reconstruction, image denoising, and inpainting. Diffusion models for image reconstruction also commonly use U-Net as the core denoising network.&lt;/p&gt;
&lt;h3&gt;
  
  
  6.6 RCAN — Attention-Enhanced Reconstruction (2018)
&lt;/h3&gt;

&lt;p&gt;RCAN (Residual Channel Attention Networks) by Zhang et al. introduced channel attention into deep SR networks. Channel attention allows the network to selectively emphasize informative features and suppress less useful ones, improving the network's ability to focus on the most informative channels for reconstruction.&lt;/p&gt;

&lt;p&gt;RCAN demonstrated state-of-the-art performance on multiple benchmarks and showed that attention mechanisms, which were revolutionizing NLP at the time, were equally powerful for image reconstruction.&lt;/p&gt;
&lt;h3&gt;
  
  
  6.7 SwinIR — Transformer-Based Restoration (2021)
&lt;/h3&gt;

&lt;p&gt;SwinIR (Swin Transformer for Image Restoration) by Liang et al. brought the Swin Transformer's powerful self-attention mechanism to image restoration. Its key advantage is the ability to model long-range dependencies across the entire image, which is crucial for tasks like inpainting (where context from far away must inform the completion) and super-resolution (where global structure must be consistent).&lt;/p&gt;

&lt;p&gt;SwinIR achieves state-of-the-art performance on image super-resolution, JPEG artifact removal, and image denoising, and has become the standard transformer baseline in the field.&lt;/p&gt;
&lt;h3&gt;
  
  
  6.8 Stable Diffusion for Reconstruction
&lt;/h3&gt;

&lt;p&gt;Stable Diffusion and other large-scale diffusion models have recently been adapted for image reconstruction tasks. Methods like StableSR and DiffBIR leverage the powerful generative prior of diffusion models trained on billions of images to guide the reconstruction process. The key idea is that a model that has learned the distribution of natural images can serve as a powerful prior for reconstruction, hallucinating realistic details that are consistent with the degraded input.&lt;/p&gt;

&lt;p&gt;These methods achieve remarkable perceptual quality, particularly for blind image restoration (where the degradation type and magnitude are unknown), but at the cost of slower inference due to the iterative denoising process.&lt;/p&gt;


&lt;h2&gt;
  
  
  7. Evaluation Metrics Explained
&lt;/h2&gt;

&lt;p&gt;Evaluating image reconstruction quality is more nuanced than it might appear. Different metrics capture different aspects of image quality — and they do not always agree. Understanding these metrics is essential for interpreting research results and designing evaluation protocols for your own projects.&lt;/p&gt;
&lt;h3&gt;
  
  
  7.1 PSNR (Peak Signal-to-Noise Ratio)
&lt;/h3&gt;

&lt;p&gt;PSNR is the most widely used metric for image quality assessment. It is defined as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;PSNR = 10 · log₁₀(MAX² / MSE)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;where MAX is the maximum possible pixel value (255 for 8-bit images) and MSE is the mean squared error between the reconstructed and reference images. PSNR is measured in decibels (dB), with higher values indicating better quality. A PSNR above 40 dB is generally considered excellent; below 30 dB is poor.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Limitation:&lt;/strong&gt; PSNR measures pixel-wise fidelity but does not correlate well with human perceptual quality. Images with the same PSNR can look very different to humans. Methods that maximize PSNR tend to produce over-smoothed, blurry outputs that lack the fine texture details that make images look natural.&lt;/p&gt;

&lt;h3&gt;
  
  
  7.2 SSIM (Structural Similarity Index)
&lt;/h3&gt;

&lt;p&gt;SSIM by Wang et al. (2004) was developed to address PSNR's poor correlation with perceptual quality. It measures similarity in terms of luminance, contrast, and structure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SSIM(x, y) = [l(x,y)]^α · [c(x,y)]^β · [s(x,y)]^γ
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;SSIM values range from 0 to 1, where 1 indicates perfect similarity. SSIM is computed locally using a sliding window and provides better correlation with human judgments than PSNR for many types of distortion.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Limitation:&lt;/strong&gt; SSIM still does not fully capture perceptual quality, particularly for super-resolution where visually realistic textures may differ structurally from the reference.&lt;/p&gt;

&lt;h3&gt;
  
  
  7.3 LPIPS (Learned Perceptual Image Patch Similarity)
&lt;/h3&gt;

&lt;p&gt;LPIPS by Zhang et al. (2018) is a learned metric that measures perceptual similarity using deep features from pre-trained networks (VGG, AlexNet, or SqueezeNet). It computes the distance between deep feature representations of two images.&lt;/p&gt;

&lt;p&gt;LPIPS correlates much better with human perceptual judgments than PSNR or SSIM, particularly for evaluating GAN-based methods that produce perceptually realistic but not pixel-accurate outputs. Lower LPIPS values indicate greater perceptual similarity.&lt;/p&gt;

&lt;p&gt;LPIPS has become the standard metric for evaluating perceptual image reconstruction quality and is now widely reported alongside PSNR and SSIM.&lt;/p&gt;

&lt;h3&gt;
  
  
  7.4 FID (Fréchet Inception Distance)
&lt;/h3&gt;

&lt;p&gt;FID measures the distance between the distribution of generated images and the distribution of real images, using statistics (mean and covariance) of Inception network features. It captures both the quality and diversity of generated images.&lt;/p&gt;

&lt;p&gt;FID is primarily used for evaluating generative models (GANs, diffusion models) rather than deterministic reconstruction networks. Lower FID indicates that the generated distribution is closer to the real distribution.&lt;/p&gt;

&lt;h3&gt;
  
  
  7.5 MOS (Mean Opinion Score)
&lt;/h3&gt;

&lt;p&gt;MOS is a human evaluation metric obtained by asking human raters to score image quality on a scale (typically 1–5). MOS is the most reliable measure of perceptual quality but is expensive and time-consuming to collect. It is typically used for final evaluation in high-stakes comparisons and challenge leaderboards.&lt;/p&gt;




&lt;h2&gt;
  
  
  8. Tools and Frameworks for Image Reconstruction
&lt;/h2&gt;

&lt;p&gt;Building image reconstruction systems requires the right combination of deep learning frameworks, specialized toolboxes, and computing infrastructure. Here is a practical guide to the tools you will need.&lt;/p&gt;

&lt;h3&gt;
  
  
  8.1 PyTorch
&lt;/h3&gt;

&lt;p&gt;PyTorch is the dominant framework for image reconstruction research. Its dynamic computation graph, intuitive API, and strong community support make it the preferred choice for implementing and training reconstruction models. Most state-of-the-art methods (SwinIR, ESRGAN, DiffBIR) release their code in PyTorch.&lt;/p&gt;

&lt;p&gt;Key PyTorch components for image reconstruction:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;torch.nn.Conv2d&lt;/code&gt; for convolutional layers&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;torch.nn.functional&lt;/code&gt; for loss functions and upsampling&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;torchvision.transforms&lt;/code&gt; for data augmentation&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;torch.utils.data.DataLoader&lt;/code&gt; for efficient data loading&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  8.2 TensorFlow / Keras
&lt;/h3&gt;

&lt;p&gt;TensorFlow with Keras is a solid alternative to PyTorch, particularly for deployment on edge devices and mobile platforms via TensorFlow Lite. Some classic models (SRCNN, DnCNN) have well-maintained TensorFlow implementations.&lt;/p&gt;

&lt;h3&gt;
  
  
  8.3 OpenCV
&lt;/h3&gt;

&lt;p&gt;OpenCV is an essential library for image preprocessing, loading, and post-processing. It provides efficient implementations of classical image processing operations that are frequently used in reconstruction pipelines — resizing, color space conversion, noise generation, and evaluation metric computation.&lt;/p&gt;

&lt;h3&gt;
  
  
  8.4 BasicSR
&lt;/h3&gt;

&lt;p&gt;BasicSR (Basic Super-Resolution) is a dedicated PyTorch toolbox for image and video restoration tasks. It provides clean, modular implementations of classic and state-of-the-art SR models (EDSR, RCAN, ESRGAN, SwinIR), along with standardized training and evaluation pipelines. For anyone working on image reconstruction, BasicSR dramatically reduces the time needed to set up experiments and reproduce published results.&lt;/p&gt;

&lt;p&gt;Key features:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Pre-implemented SR models ready for training and inference&lt;/li&gt;
&lt;li&gt;Standard data loaders for DIV2K, Set5, Set14, Urban100&lt;/li&gt;
&lt;li&gt;Integrated evaluation with PSNR, SSIM, and LPIPS&lt;/li&gt;
&lt;li&gt;Modular design for easy customization&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  8.5 Hugging Face Diffusers
&lt;/h3&gt;

&lt;p&gt;For diffusion-based reconstruction methods, the Hugging Face Diffusers library provides pre-trained models (Stable Diffusion, DDPM) and flexible pipelines that can be adapted for image reconstruction conditioning. Methods like StableSR can be implemented using Diffusers as the backbone.&lt;/p&gt;

&lt;h3&gt;
  
  
  8.6 Google Colab Setup
&lt;/h3&gt;

&lt;p&gt;For students without access to powerful GPUs, Google Colab provides free access to NVIDIA T4 GPUs (16GB VRAM). Here is a basic setup for an image reconstruction experiment:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Install dependencies
&lt;/span&gt;&lt;span class="err"&gt;!&lt;/span&gt;&lt;span class="n"&gt;pip&lt;/span&gt; &lt;span class="n"&gt;install&lt;/span&gt; &lt;span class="n"&gt;torch&lt;/span&gt; &lt;span class="n"&gt;torchvision&lt;/span&gt; &lt;span class="n"&gt;basicsr&lt;/span&gt;

&lt;span class="c1"&gt;# Mount Google Drive for dataset storage
&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;google.colab&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;drive&lt;/span&gt;
&lt;span class="n"&gt;drive&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;mount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;/content/drive&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Load a pre-trained ESRGAN model
&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;basicsr.archs.rrdbnet_arch&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;RRDBNet&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;torch&lt;/span&gt;

&lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;RRDBNet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;num_in_ch&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;num_out_ch&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;num_feat&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
                &lt;span class="n"&gt;num_block&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;23&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;num_grow_ch&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;scale&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;load_state_dict&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;torch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;ESRGAN_x4.pth&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;params_ema&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;eval&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For more demanding experiments, Kaggle's free GPU quota (30 hours per week of T4/P100 access) or Paperspace Gradient are good alternatives.&lt;/p&gt;




&lt;h2&gt;
  
  
  9. Real-World Applications
&lt;/h2&gt;

&lt;p&gt;Image reconstruction has moved well beyond academic benchmarks into production systems that affect millions of people every day. Here are the most impactful real-world application domains.&lt;/p&gt;

&lt;h3&gt;
  
  
  9.1 Medical Imaging
&lt;/h3&gt;

&lt;p&gt;Medical imaging is arguably the most critical application of image reconstruction. The quality of medical images directly affects diagnostic accuracy, and consequently, patient outcomes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;MRI Reconstruction:&lt;/strong&gt; Modern MRI scanners can acquire data much faster if they collect fewer measurements (k-space samples). Deep learning-based compressed sensing reconstruction allows radiologists to achieve diagnostic-quality images from 4× to 8× undersampled acquisitions, reducing scan times from 20–30 minutes to 5–7 minutes. This improves patient comfort, reduces motion artifacts, and increases scanner throughput. The fastMRI dataset and challenge, organized by Facebook AI and NYU, has driven significant progress in this area.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;CT Reconstruction:&lt;/strong&gt; Low-dose CT imaging is critical for reducing radiation exposure, particularly in screening applications. However, reducing the X-ray dose increases image noise. Deep learning denoising and reconstruction methods can produce high-quality images from low-dose acquisitions that would previously have been diagnostically unusable.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pathology Image Enhancement:&lt;/strong&gt; Digital pathology involves scanning tissue samples at very high magnification, producing enormous image files. Super-resolution and denoising methods allow pathologists to work with smaller files while maintaining diagnostic quality at full resolution when needed.&lt;/p&gt;

&lt;h3&gt;
  
  
  9.2 Satellite and Remote Sensing
&lt;/h3&gt;

&lt;p&gt;Satellite imagery suffers from resolution limitations imposed by the physics of the imaging system and the altitude of the satellite. Higher resolution requires larger optics or lower orbits — both expensive constraints. Super-resolution of satellite imagery can effectively increase the resolution of existing satellite systems at a fraction of the cost of hardware upgrades.&lt;/p&gt;

&lt;p&gt;Applications include: monitoring agricultural fields (detecting crop health from vegetation indices that require high resolution), tracking deforestation and urban development, disaster response (assessing damage after earthquakes or floods), and military intelligence.&lt;/p&gt;

&lt;p&gt;The challenge in satellite SR is that the degradation process is more complex than simple bicubic downsampling — it includes atmospheric distortion, sensor noise, and aliasing effects that vary depending on the satellite, orbit, and atmospheric conditions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Super-Resolution for Climate Science:&lt;/strong&gt; Satellite-based climate monitoring depends on consistent, high-resolution observations over decades. As older satellite systems are replaced by newer ones with different resolutions and sensor characteristics, image reconstruction methods play a critical role in creating consistent long-term records. Downscaling climate model outputs using deep SR also helps regional planners access high-resolution climate projections that global models cannot provide directly.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Ocean and Ice Monitoring:&lt;/strong&gt; Reconstruction of ocean surface temperature maps and polar ice extent from satellite data is critical for climate change monitoring. SR methods applied to MODIS and Sentinel satellite imagery allow researchers to track fine-scale oceanographic features and ice margin dynamics that were previously below the resolution threshold of available sensors.&lt;/p&gt;

&lt;h3&gt;
  
  
  9.3 Surveillance and Forensics
&lt;/h3&gt;

&lt;p&gt;Surveillance cameras capture enormous amounts of footage, often at low resolution to minimize storage requirements. When an incident occurs, investigators frequently need to enhance footage to identify individuals, read license plates, or recover other forensically important details.&lt;/p&gt;

&lt;p&gt;Super-resolution and face hallucination methods can significantly enhance surveillance footage, though results must be interpreted with caution in forensic contexts — perceptually realistic reconstructions may not be factually accurate. Blind face restoration methods (GFPGAN, CodeFormer) have shown remarkable results in recovering readable faces from heavily degraded surveillance images.&lt;/p&gt;

&lt;h3&gt;
  
  
  9.4 Entertainment and Film Restoration
&lt;/h3&gt;

&lt;p&gt;The film and entertainment industry uses image reconstruction extensively for restoring archival footage, upscaling older content for modern high-definition displays, and real-time enhancement of streaming video.&lt;/p&gt;

&lt;p&gt;Netflix, Disney, and other streaming platforms use AI-based upscaling to deliver higher quality video to users with high-bandwidth connections without increasing storage costs. Film archives use deep learning restoration to remove noise, scratches, and degradation from historical footage that would be impossible to restore manually at scale.&lt;/p&gt;

&lt;p&gt;Video game developers use super-resolution techniques (NVIDIA DLSS, AMD FSR, Intel XeSS) to render games at lower resolution and upscale them in real time, achieving high image quality with significantly reduced computational cost.&lt;/p&gt;

&lt;h3&gt;
  
  
  9.5 Autonomous Vehicles
&lt;/h3&gt;

&lt;p&gt;Autonomous vehicles rely on high-quality camera images for object detection, lane detection, and scene understanding. In adverse weather conditions — fog, rain, snow, glare — image degradation can severely compromise the performance of perception systems.&lt;/p&gt;

&lt;p&gt;Image reconstruction and enhancement methods can derain, defog, and denoise camera images in real time, improving the reliability of autonomous perception in challenging conditions. This is an active area of research with direct safety implications.&lt;/p&gt;

&lt;p&gt;Recent work from Waymo, Cruise, and academic groups has demonstrated that preprocessing camera frames with lightweight denoising and dehazing networks can improve downstream object detection accuracy by 10–20% in adverse weather conditions — a significant improvement for safety-critical systems.&lt;/p&gt;

&lt;h3&gt;
  
  
  9.6 Smartphone Computational Photography
&lt;/h3&gt;

&lt;p&gt;Modern smartphone cameras are engineering marvels, but their small sensors fundamentally limit image quality compared to larger camera systems. Computational photography — using software to compensate for hardware limitations — relies heavily on image reconstruction techniques.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Night Photography:&lt;/strong&gt; Google Night Sight, Apple Deep Fusion, and Samsung AI-powered night modes use variants of image reconstruction to combine multiple short exposures with learned denoising and super-resolution to produce bright, sharp images in very low light conditions that would be impossible with a single exposure.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Zoom Enhancement:&lt;/strong&gt; Optical zoom requires physically larger lenses. Most smartphones instead use digital zoom supplemented by AI super-resolution. Apple ProRAW, Google's Super Res Zoom, and Samsung's Space Zoom all use deep learning super-resolution models to produce usable images at zoom levels far beyond what the optics alone could support.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;HDR and Tone Mapping:&lt;/strong&gt; Reconstructing the full dynamic range of a scene from a camera with limited sensor dynamic range involves image reconstruction principles — combining exposures and applying tone mapping that preserves the natural appearance of a scene.&lt;/p&gt;

&lt;p&gt;The smartphone market has become one of the largest commercial drivers of image reconstruction research, with major companies investing heavily in on-device neural processing units (NPUs) specifically designed to run these reconstruction models in real time at full resolution.&lt;/p&gt;




&lt;h2&gt;
  
  
  10. Image Reconstruction as a Final Year Project
&lt;/h2&gt;

&lt;p&gt;Image reconstruction offers excellent opportunities for final year engineering projects. The field is rich with open problems, well-established benchmarks, and publicly available code and datasets. Here is a practical guide for students planning their project.&lt;/p&gt;

&lt;h3&gt;
  
  
  10.1 Project Ideas
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Beginner Level:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Implement SRCNN from scratch and evaluate on Set5/Set14 benchmarks&lt;/li&gt;
&lt;li&gt;Train a denoising CNN (DnCNN) and compare against classical methods (Gaussian filter, BM3D)&lt;/li&gt;
&lt;li&gt;Build a face restoration pipeline using pre-trained GFPGAN or CodeFormer&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Intermediate Level:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Implement a GAN-based super-resolution method and compare PSNR/SSIM/LPIPS with non-adversarial baselines&lt;/li&gt;
&lt;li&gt;Develop a real-world degradation simulator and evaluate robustness of SR models to unknown degradations&lt;/li&gt;
&lt;li&gt;Build an image inpainting system using partial convolutions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Advanced Level:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Adapt a diffusion model for blind image restoration (unknown degradation type)&lt;/li&gt;
&lt;li&gt;Implement a lightweight transformer for efficient mobile super-resolution&lt;/li&gt;
&lt;li&gt;Develop a domain-specific SR model for medical images (CT or MRI) with clinical evaluation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For well-structured project guidance, students in Chennai and across India can explore &lt;a href="https://projectcentersinchennai.co.in/ieee-domains/image-generation-projects-for-final-year/" rel="noopener noreferrer"&gt;Image Generation Projects for Final Year&lt;/a&gt; that cover IEEE-standard implementations with proper documentation and mentorship.&lt;/p&gt;

&lt;h3&gt;
  
  
  10.2 Recommended Dataset Selection
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Project Type&lt;/th&gt;
&lt;th&gt;Primary Dataset&lt;/th&gt;
&lt;th&gt;Evaluation Dataset&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;General SR&lt;/td&gt;
&lt;td&gt;DIV2K (train)&lt;/td&gt;
&lt;td&gt;Set5, Set14, Urban100&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Face Restoration&lt;/td&gt;
&lt;td&gt;FFHQ (train)&lt;/td&gt;
&lt;td&gt;CelebA-HQ (test)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Medical Imaging&lt;/td&gt;
&lt;td&gt;fastMRI / LoDoPaB-CT&lt;/td&gt;
&lt;td&gt;Task-specific splits&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Denoising&lt;/td&gt;
&lt;td&gt;DIV2K + CBSD68&lt;/td&gt;
&lt;td&gt;Set12, CBSD68&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Inpainting&lt;/td&gt;
&lt;td&gt;Paris StreetView / CelebA-HQ&lt;/td&gt;
&lt;td&gt;Held-out test split&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  10.3 Model Selection Guide
&lt;/h3&gt;

&lt;p&gt;Choosing the right model depends on your constraints and goals:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Limited GPU (&amp;lt; 8GB):&lt;/strong&gt; SRCNN, VDSR, lightweight CNNs&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Standard GPU (8–16GB):&lt;/strong&gt; EDSR, ESRGAN, SwinIR-small&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;High-end GPU (24GB+):&lt;/strong&gt; Full SwinIR, RealESRGAN, DiffBIR&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Edge deployment:&lt;/strong&gt; IMDN (Information Multi-Distillation Network), RFDN&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  10.4 Implementation Roadmap
&lt;/h3&gt;

&lt;p&gt;A typical 3-month project timeline for a final year image reconstruction project:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Month 1 — Foundation&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Literature review (SRCNN → EDSR → ESRGAN → SwinIR)&lt;/li&gt;
&lt;li&gt;Environment setup (PyTorch, BasicSR, CUDA)&lt;/li&gt;
&lt;li&gt;Dataset download and preprocessing (DIV2K, Set5, Set14)&lt;/li&gt;
&lt;li&gt;Baseline implementation (SRCNN or EDSR)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Month 2 — Core Development&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Implement or adapt target architecture&lt;/li&gt;
&lt;li&gt;Train on DIV2K with standard data augmentation&lt;/li&gt;
&lt;li&gt;Evaluate with PSNR, SSIM, LPIPS on test sets&lt;/li&gt;
&lt;li&gt;Ablation studies (loss functions, architecture components)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Month 3 — Polish and Documentation&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Comparative evaluation against published baselines&lt;/li&gt;
&lt;li&gt;Visualization of results (input vs. output comparisons)&lt;/li&gt;
&lt;li&gt;Report writing and presentation preparation&lt;/li&gt;
&lt;li&gt;Optional: deployment demo (web app or mobile app)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  10.5 Evaluation Tips
&lt;/h3&gt;

&lt;p&gt;Always report PSNR and SSIM together. PSNR alone is insufficient for evaluating perceptual quality. For GAN-based methods, add LPIPS. Use the Y channel (luminance) of the YCbCr color space for metric computation, as this is the standard in the SR literature and results are not comparable across different evaluation protocols.&lt;/p&gt;




&lt;h2&gt;
  
  
  11. Step-by-Step Implementation Guide
&lt;/h2&gt;

&lt;p&gt;This section provides a practical walkthrough for implementing a basic image super-resolution system using PyTorch and the BasicSR framework. The code is designed to run on Google Colab with a free T4 GPU.&lt;/p&gt;

&lt;h3&gt;
  
  
  11.1 Environment Setup
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Install required packages&lt;/span&gt;
pip &lt;span class="nb"&gt;install &lt;/span&gt;torch torchvision torchaudio &lt;span class="nt"&gt;--index-url&lt;/span&gt; https://download.pytorch.org/whl/cu118
pip &lt;span class="nb"&gt;install &lt;/span&gt;basicsr opencv-python matplotlib pillow
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;torch&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;torch.nn&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;nn&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;torch.optim&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;optim&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;torch.utils.data&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;DataLoader&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Dataset&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;torchvision.transforms&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;transforms&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;cv2&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;numpy&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;PIL&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Image&lt;/span&gt;

&lt;span class="c1"&gt;# Check GPU availability
&lt;/span&gt;&lt;span class="n"&gt;device&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;torch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;device&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;cuda&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;torch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cuda&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;is_available&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;cpu&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Using device: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;device&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  11.2 Dataset Preparation
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SRDataset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Dataset&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Dataset class for super-resolution training.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;hr_dir&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;scale&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;patch_size&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;128&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;hr_dir&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;hr_dir&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;scale&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;scale&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;patch_size&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;patch_size&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;image_files&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listdir&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;hr_dir&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
                           &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;endswith&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;.png&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;.jpg&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;.jpeg&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;))]&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__len__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;image_files&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__getitem__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;idx&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="c1"&gt;# Load HR image
&lt;/span&gt;        &lt;span class="n"&gt;hr_path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;hr_dir&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;image_files&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;idx&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
        &lt;span class="n"&gt;hr_img&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Image&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;hr_path&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;convert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;RGB&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="c1"&gt;# Random crop for training
&lt;/span&gt;        &lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;h&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;hr_img&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;
        &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;random&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;randint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;w&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;patch_size&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;random&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;randint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;h&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;patch_size&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;hr_patch&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;hr_img&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;crop&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;patch_size&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;patch_size&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

        &lt;span class="c1"&gt;# Generate LR image by bicubic downsampling
&lt;/span&gt;        &lt;span class="n"&gt;lr_size&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;patch_size&lt;/span&gt; &lt;span class="o"&gt;//&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;scale&lt;/span&gt;
        &lt;span class="n"&gt;lr_patch&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;hr_patch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;resize&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;lr_size&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;lr_size&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;Image&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;BICUBIC&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="c1"&gt;# Convert to tensors
&lt;/span&gt;        &lt;span class="n"&gt;to_tensor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;transforms&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;ToTensor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;hr_tensor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;to_tensor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;hr_patch&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;lr_tensor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;to_tensor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lr_patch&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;lr_tensor&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;hr_tensor&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  11.3 Model Architecture (SRCNN)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SRCNN&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;nn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Module&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
    Super-Resolution Convolutional Neural Network (SRCNN).
    Simple 3-layer CNN for image super-resolution.
    &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="nf"&gt;super&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;SRCNN&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

        &lt;span class="c1"&gt;# Feature extraction
&lt;/span&gt;        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;conv1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;nn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Conv2d&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;kernel_size&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;padding&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="c1"&gt;# Non-linear mapping
&lt;/span&gt;        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;conv2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;nn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Conv2d&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;kernel_size&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;padding&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="c1"&gt;# Reconstruction
&lt;/span&gt;        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;conv3&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;nn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Conv2d&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;kernel_size&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;padding&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;relu&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;nn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;ReLU&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;inplace&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;forward&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="c1"&gt;# Upsample input first (bicubic interpolation)
&lt;/span&gt;        &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;nn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;functional&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;interpolate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;scale_factor&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;mode&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;bicubic&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
                                       &lt;span class="n"&gt;align_corners&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;relu&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;conv1&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;relu&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;conv2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;conv3&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;torch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;clamp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="c1"&gt;# Initialize model
&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;SRCNN&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;to&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;device&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Model parameters: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;numel&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parameters&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  11.4 Training Loop
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;train_model&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;train_loader&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;num_epochs&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;lr&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;1e-4&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Train the SR model.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;

    &lt;span class="n"&gt;optimizer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;optim&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Adam&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parameters&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;lr&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;lr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;scheduler&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;optim&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;lr_scheduler&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;StepLR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;optimizer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;step_size&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;gamma&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;0.5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;criterion&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;nn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;L1Loss&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;  &lt;span class="c1"&gt;# L1 loss generally produces sharper results than MSE
&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;epoch&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;num_epochs&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;train&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;total_loss&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;

        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;batch_idx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lr_imgs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;hr_imgs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;enumerate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;train_loader&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="n"&gt;lr_imgs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;lr_imgs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;device&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;hr_imgs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;hr_imgs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;device&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

            &lt;span class="c1"&gt;# Forward pass
&lt;/span&gt;            &lt;span class="n"&gt;sr_imgs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;model&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lr_imgs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;loss&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;criterion&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sr_imgs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;hr_imgs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

            &lt;span class="c1"&gt;# Backward pass
&lt;/span&gt;            &lt;span class="n"&gt;optimizer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;zero_grad&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="n"&gt;loss&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;backward&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="n"&gt;optimizer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;step&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

            &lt;span class="n"&gt;total_loss&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;loss&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;item&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

        &lt;span class="n"&gt;scheduler&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;step&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;avg_loss&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;total_loss&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;train_loader&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="nf"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;epoch&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Epoch [&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;epoch&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;/&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;num_epochs&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;], Loss: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;avg_loss&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;, &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
                  &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;LR: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;scheduler&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_last_lr&lt;/span&gt;&lt;span class="p"&gt;()[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  11.5 Evaluation with PSNR and SSIM
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;calculate_psnr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;img1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;img2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;max_val&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Calculate PSNR between two images.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="n"&gt;mse&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;torch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;mean&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;img1&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;img2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;mse&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;float&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;inf&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;torch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log10&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;torch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;tensor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;max_val&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;torch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log10&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mse&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;evaluate_model&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;test_loader&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Evaluate model on test set.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;eval&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;total_psnr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
    &lt;span class="n"&gt;num_samples&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;

    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;torch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;no_grad&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;lr_imgs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;hr_imgs&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;test_loader&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;lr_imgs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;lr_imgs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;device&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;hr_imgs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;hr_imgs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;device&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

            &lt;span class="n"&gt;sr_imgs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;model&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lr_imgs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

            &lt;span class="c1"&gt;# Calculate PSNR for each image in batch
&lt;/span&gt;            &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sr_imgs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;size&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)):&lt;/span&gt;
                &lt;span class="n"&gt;psnr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;calculate_psnr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sr_imgs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;hr_imgs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
                &lt;span class="n"&gt;total_psnr&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;psnr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;item&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
                &lt;span class="n"&gt;num_samples&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;

    &lt;span class="n"&gt;avg_psnr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;total_psnr&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;num_samples&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Average PSNR: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;avg_psnr&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; dB&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;avg_psnr&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  11.6 Result Visualization
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;matplotlib.pyplot&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;plt&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;visualize_results&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;lr_img_path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;save_path&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Visualize super-resolution results.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;

    &lt;span class="c1"&gt;# Load and preprocess LR image
&lt;/span&gt;    &lt;span class="n"&gt;lr_img&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Image&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lr_img_path&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;convert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;RGB&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;lr_tensor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;transforms&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;ToTensor&lt;/span&gt;&lt;span class="p"&gt;()(&lt;/span&gt;&lt;span class="n"&gt;lr_img&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;unsqueeze&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;to&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;device&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Generate SR image
&lt;/span&gt;    &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;eval&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;torch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;no_grad&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
        &lt;span class="n"&gt;sr_tensor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;model&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lr_tensor&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;sr_img&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;transforms&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;ToPILImage&lt;/span&gt;&lt;span class="p"&gt;()(&lt;/span&gt;&lt;span class="n"&gt;sr_tensor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;squeeze&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;cpu&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;

    &lt;span class="c1"&gt;# Bicubic upsampling for comparison
&lt;/span&gt;    &lt;span class="n"&gt;bicubic_img&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;lr_img&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;resize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sr_img&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Image&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;BICUBIC&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Plot results
&lt;/span&gt;    &lt;span class="n"&gt;fig&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;axes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;plt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;subplots&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;figsize&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="n"&gt;axes&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;imshow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lr_img&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="n"&gt;axes&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;set_title&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;LR Input&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;fontsize&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;14&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;axes&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;imshow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bicubic_img&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="n"&gt;axes&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;set_title&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Bicubic Upsampling&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;fontsize&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;14&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;axes&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;imshow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sr_img&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="n"&gt;axes&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;set_title&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;SR Output (SRCNN)&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;fontsize&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;14&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;ax&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;axes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;ax&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;axis&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;off&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;plt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;tight_layout&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;save_path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;plt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;savefig&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;save_path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dpi&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;150&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;bbox_inches&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;tight&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;plt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;show&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  12. Challenges in Image Reconstruction
&lt;/h2&gt;

&lt;p&gt;Despite remarkable progress, image reconstruction remains an open research problem with significant challenges.&lt;/p&gt;

&lt;h3&gt;
  
  
  12.1 Hallucination and Faithfulness
&lt;/h3&gt;

&lt;p&gt;GAN-based and diffusion-based reconstruction methods produce perceptually realistic outputs, but these outputs may contain details that were not present in the original image. In medical imaging, this hallucination of non-existent features could lead to misdiagnosis. In forensic applications, hallucinated facial features could falsely incriminate innocent individuals.&lt;/p&gt;

&lt;p&gt;Balancing perceptual quality against faithfulness to the original content remains a fundamental tension in reconstruction research. Methods that score highest on perceptual metrics (LPIPS, FID) often have lower PSNR and SSIM scores, reflecting this trade-off.&lt;/p&gt;

&lt;h3&gt;
  
  
  12.2 Real-World Degradation Generalization
&lt;/h3&gt;

&lt;p&gt;Most reconstruction models are trained on specific, simulated degradations (e.g., bicubic downsampling with ×4 scale). Real-world images are often degraded by complex, unknown combinations of noise, blur, compression, and sensor effects. Models that perform well on clean benchmarks often fail dramatically on real-world degraded images.&lt;/p&gt;

&lt;p&gt;Blind image restoration — recovering images without knowing the degradation type — is an active research area aimed at addressing this challenge. Methods like Real-ESRGAN train on complex, realistic degradation pipelines to improve generalization to real-world images.&lt;/p&gt;

&lt;h3&gt;
  
  
  12.3 Computational Cost and Speed
&lt;/h3&gt;

&lt;p&gt;State-of-the-art reconstruction models require significant computational resources. SwinIR and diffusion-based methods are particularly demanding. This limits their use in real-time applications (surveillance, video streaming, autonomous driving) and on resource-constrained platforms (mobile devices, embedded systems).&lt;/p&gt;

&lt;p&gt;Knowledge distillation, neural architecture search, and quantization are active research directions for developing lightweight, efficient reconstruction models that maintain high quality while meeting real-time constraints.&lt;/p&gt;

&lt;h3&gt;
  
  
  12.4 Lack of Paired Training Data for Real-World Tasks
&lt;/h3&gt;

&lt;p&gt;Training supervised reconstruction models requires paired data — corresponding pairs of degraded and clean images. For simulated degradations, such pairs can be generated synthetically. For real-world degradations, collecting genuine paired data is extremely challenging, requiring specialized acquisition setups or expert annotation.&lt;/p&gt;

&lt;p&gt;This motivates research into unsupervised and self-supervised reconstruction methods that can train without paired data, and semi-supervised methods that can leverage abundant unpaired data alongside limited paired data.&lt;/p&gt;

&lt;h3&gt;
  
  
  12.5 Perceptual-Distortion Trade-off
&lt;/h3&gt;

&lt;p&gt;The Perception-Distortion trade-off, formalized by Blau and Michaeli (2018), established that there is a fundamental trade-off between perceptual quality and distortion (pixel-level accuracy). Improving perceptual quality (measured by FID or LPIPS) necessarily comes at the cost of increased distortion (worse PSNR/SSIM), and vice versa. This theoretical result has important practical implications — there is no single best reconstruction algorithm, and the appropriate trade-off depends on the application.&lt;/p&gt;

&lt;h3&gt;
  
  
  12.6 Domain Shift Between Training and Deployment
&lt;/h3&gt;

&lt;p&gt;Even when models are trained on large, diverse datasets, they can still fail in deployment when the distribution of real-world images differs significantly from the training distribution. This domain shift problem is particularly acute in medical imaging, where imaging protocols, equipment manufacturers, and patient demographics vary widely across different hospitals and clinical settings.&lt;/p&gt;

&lt;p&gt;A model trained on MRI data from one scanner type may perform poorly on data from a different manufacturer's scanner, even if the imaging task appears identical. This has motivated research into domain adaptation and domain generalization techniques for reconstruction models, as well as the development of large-scale multi-center training datasets.&lt;/p&gt;

&lt;h3&gt;
  
  
  12.7 Interpretability and Trust
&lt;/h3&gt;

&lt;p&gt;Deep learning reconstruction models are black boxes — they produce outputs without explanations of why those outputs were generated. In clinical settings, radiologists and clinicians need to be able to trust and interpret reconstruction results. A model that hallucinates anatomical structures without any way to flag its uncertainty is a safety risk.&lt;/p&gt;

&lt;p&gt;Research into uncertainty quantification for reconstruction models — methods that produce confidence maps alongside reconstructions — is an important step toward clinical trustworthiness. Bayesian deep learning approaches and ensemble methods can provide calibrated uncertainty estimates that help clinicians identify which regions of a reconstruction are reliable and which should be treated with caution.&lt;/p&gt;




&lt;h2&gt;
  
  
  13. Future Trends and Research Directions
&lt;/h2&gt;

&lt;p&gt;The image reconstruction field is evolving rapidly. Here are the most promising directions that are shaping its future.&lt;/p&gt;

&lt;h3&gt;
  
  
  13.1 Foundation Models for Universal Restoration
&lt;/h3&gt;

&lt;p&gt;Large-scale foundation models trained on diverse data and tasks are emerging as a new paradigm for image restoration. Instead of training specialized models for each degradation type, a single foundation model can handle denoising, super-resolution, inpainting, deblurring, and more within a unified architecture. Models like Painter and PromptIR represent early steps in this direction.&lt;/p&gt;

&lt;h3&gt;
  
  
  13.2 Neural Radiance Fields and 3D Reconstruction
&lt;/h3&gt;

&lt;p&gt;NeRF and its successors (Instant-NGP, 3D Gaussian Splatting) have revolutionized 3D scene reconstruction from 2D images. These methods enable photorealistic novel view synthesis — generating realistic views of a scene from new angles — using only a sparse set of input photographs. Applications in virtual reality, robotics, and cultural heritage preservation are enormous.&lt;/p&gt;

&lt;h3&gt;
  
  
  13.3 Real-Time Diffusion Reconstruction
&lt;/h3&gt;

&lt;p&gt;Diffusion models produce state-of-the-art reconstruction quality but are slow due to iterative denoising. Research into consistency models, latent diffusion, and accelerated sampling is rapidly reducing inference time, bringing diffusion-based reconstruction closer to real-time performance. NVIDIA's TensorRT-LLM and similar inference optimization frameworks are also making deployment more practical.&lt;/p&gt;

&lt;h3&gt;
  
  
  13.4 Multimodal Reconstruction
&lt;/h3&gt;

&lt;p&gt;Future reconstruction systems will leverage multiple modalities — text descriptions, depth maps, semantic segmentation maps, or reference images — to guide the reconstruction process. Text-guided inpainting (filling missing regions with content described by a text prompt) is already commercially available through tools built on Stable Diffusion. Richer multimodal conditioning will enable more controllable and semantically meaningful reconstructions.&lt;/p&gt;

&lt;h3&gt;
  
  
  13.5 Medical AI and Personalized Reconstruction
&lt;/h3&gt;

&lt;p&gt;Medical image reconstruction is moving toward patient-specific models that are fine-tuned on individual patient data to produce reconstructions optimized for each patient's anatomy and imaging characteristics. Federated learning frameworks are enabling training on sensitive medical data across multiple hospitals without centralizing patient data.&lt;/p&gt;

&lt;h3&gt;
  
  
  13.6 Self-Supervised and Unsupervised Learning
&lt;/h3&gt;

&lt;p&gt;A significant limitation of current deep learning reconstruction methods is their dependence on large amounts of paired training data. Collecting paired (degraded, clean) image pairs at scale is expensive or impossible for many real-world degradation scenarios.&lt;/p&gt;

&lt;p&gt;Self-supervised learning approaches — such as Noise2Noise (training to denoise using only noisy images without clean references), Blind2Unblind, and masked image modeling — are enabling high-quality reconstruction models to be trained without paired ground truth. This opens the door to training on raw internet images, unlocking vast amounts of training data that were previously unusable.&lt;/p&gt;

&lt;h3&gt;
  
  
  13.7 Video Reconstruction and Temporal Consistency
&lt;/h3&gt;

&lt;p&gt;Extending image reconstruction to video introduces new challenges around temporal consistency. Super-resolving video frame by frame with an image SR model produces flickering artifacts, since the model cannot leverage temporal information. Video SR methods must balance spatial quality with temporal coherence, ensuring that reconstructed frames are consistent over time.&lt;/p&gt;

&lt;p&gt;Recent methods like BasicVSR++ and RVRT use deformable convolutions and attention mechanisms to align and aggregate information across frames, achieving both high spatial quality and temporal consistency. With the explosion of streaming video content, video reconstruction is one of the most commercially important applications of the field.&lt;/p&gt;

&lt;h3&gt;
  
  
  13.8 Edge Computing and On-Device Inference
&lt;/h3&gt;

&lt;p&gt;As image reconstruction models become more capable, there is increasing demand for running them on edge devices — smartphones, cameras, medical devices, satellites — rather than in the cloud. This requires extremely efficient models that can run within tight power and memory budgets.&lt;/p&gt;

&lt;p&gt;Neural architecture search (NAS) for SR, knowledge distillation from large teacher models to small student models, and hardware-aware model design are active research directions. Apple's Neural Engine, Qualcomm's Hexagon DSP, and dedicated ISP chips in camera systems are hardware platforms that are being co-designed with reconstruction algorithms to maximize efficiency.&lt;/p&gt;




&lt;h2&gt;
  
  
  14. Conclusion
&lt;/h2&gt;

&lt;p&gt;Image reconstruction has undergone a transformation that few could have predicted a decade ago. From mathematical signal processing models to deep convolutional networks, and now to transformer-based and diffusion-based generative approaches, the field has advanced at a remarkable pace, enabling capabilities that were once thought impossible.&lt;/p&gt;

&lt;p&gt;The three pillars of modern image reconstruction research — diverse high-quality datasets like DIV2K and CelebA-HQ, powerful architectures like SwinIR and ESRGAN, and rich evaluation frameworks combining PSNR, SSIM, and LPIPS — provide a solid foundation for both academic research and practical applications.&lt;/p&gt;

&lt;p&gt;For students entering the field, image reconstruction offers an ideal combination of theoretical depth and practical impact. The problems are mathematically interesting, the results are visually compelling, and the applications — from medical imaging to satellite analysis to consumer photography — are genuinely impactful.&lt;/p&gt;

&lt;p&gt;Whether you are reconstructing low-resolution surveillance footage, enhancing MRI scans to reduce scan times, or restoring archival film footage, image reconstruction techniques give you the tools to recover the information that degradation took away.&lt;/p&gt;

&lt;p&gt;For final year students in India looking to explore this exciting field with structured project guidance and IEEE-standard implementations, &lt;a href="https://projectcentersinchennai.co.in/ieee-domains/image-generation-projects-for-final-year/" rel="noopener noreferrer"&gt;Image Generation Projects&lt;/a&gt; offer comprehensive resources to get started on the right track.&lt;/p&gt;

&lt;p&gt;The future of image reconstruction is brighter than ever — and the best contributions to this field are yet to come.&lt;/p&gt;




&lt;h2&gt;
  
  
  Frequently Asked Questions (FAQ)
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Q: What is the difference between image reconstruction and image generation?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Image reconstruction starts with a degraded or incomplete version of a real image and attempts to recover the original — or an enhanced version of it. Image generation, on the other hand, creates entirely new images that did not previously exist. The two tasks overlap when reconstruction methods (like diffusion models) use learned generative priors to hallucinate missing details, but the fundamental goal differs: reconstruction preserves fidelity to an original, while generation prioritizes novelty and realism.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q: Which deep learning framework should I use for image reconstruction projects?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;PyTorch is the strongly recommended choice for research and final year projects. The majority of state-of-the-art reconstruction methods release their official code in PyTorch, and the BasicSR toolbox — the most comprehensive SR/restoration framework — is PyTorch-based. TensorFlow is a viable alternative if you intend to deploy on mobile using TensorFlow Lite, but for training and experimentation, PyTorch offers significantly better flexibility and community support.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q: Can image reconstruction methods be applied to videos?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Yes, and this is an active research area. Image reconstruction methods can be applied frame-by-frame to video, but this tends to produce temporal inconsistencies (flickering) because frames are processed independently. Dedicated video reconstruction methods use temporal information — by aligning and fusing features across multiple frames — to produce temporally consistent results. Methods like BasicVSR, EDVR, and RVRT are the leading video reconstruction architectures.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q: How much GPU memory do I need to train an image reconstruction model?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;For training a basic SRCNN or DnCNN model from scratch on DIV2K with a small patch size (64×64), 6–8GB of GPU memory is sufficient. For training EDSR or SwinIR-small, 16GB is recommended. Full SwinIR-large or RealESRGAN require 24GB or more. For students with limited GPU resources, Google Colab Pro (with A100 access) or Kaggle's free GPU quota provide viable alternatives to personal hardware.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q: What is "blind" image restoration?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Blind restoration refers to reconstructing images when the type and parameters of the degradation are unknown. In a non-blind setting, you know exactly how the image was degraded (e.g., bicubic downsampling with ×4 scale) and can train a specialized model for that degradation. In a blind setting, the image might be degraded by any combination of noise, blur, compression, and downsampling — and you need a model general enough to handle any degradation. Methods like Real-ESRGAN, BSRGAN, and DiffBIR are designed for blind restoration.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q: How is image reconstruction evaluated beyond PSNR and SSIM?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Modern evaluation frameworks use multiple complementary metrics. PSNR and SSIM measure pixel-level fidelity. LPIPS measures perceptual similarity using deep features. FID measures distributional similarity (used for generative models). NIQE and BRISQUE are no-reference quality metrics that don't require a ground truth reference. Human evaluation (MOS studies) remains the gold standard but is expensive. For comprehensive evaluation, reporting at least PSNR, SSIM, and LPIPS together is now expected in any peer-reviewed paper.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q: Is image reconstruction used in real-time applications?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Yes, though with efficiency trade-offs. CNN-based methods like IMDN and RFDN are designed for real-time inference and run at 60+ FPS on modern hardware. GAN-based methods are slower but can still achieve near-real-time performance on dedicated hardware. Diffusion-based methods are currently too slow for real-time use in most applications, though consistency models and latent diffusion acceleration are rapidly reducing this gap. Consumer applications (smartphone cameras, streaming upscaling) use highly optimized, hardware-accelerated models specifically designed for real-time performance.&lt;/p&gt;




&lt;p&gt;Image reconstruction has become one of the most exciting applications of deep learning, spanning everything from medical MRI enhancement to satellite imaging and smartphone photography. If you're looking for a comprehensive breakdown of the field — covering datasets like DIV2K and CelebA-HQ, architectures like ESRGAN and SwinIR, evaluation metrics, and even a full PyTorch implementation guide — I put together a detailed writeup on Kaggle. Check it out here: &lt;a href="https://www.kaggle.com/writeups/marykabrown/image-reconstruction-using-deep-learning" rel="noopener noreferrer"&gt;Image Reconstruction Using Deep Learning: A Complete Guide&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Keywords: Image Reconstruction, Deep Learning, Super Resolution, Image Inpainting, Image Denoising, DIV2K Dataset, CelebA-HQ Dataset, Urban100 Dataset, SRCNN, ESRGAN, SwinIR, Diffusion Models, Final Year Projects, IEEE Projects&lt;/em&gt;&lt;/p&gt;

</description>
      <category>imagegeneration</category>
      <category>imagereconstruction</category>
      <category>computervision</category>
      <category>generativeai</category>
    </item>
    <item>
      <title>Top 5 Image Dehazing Datasets Every Computer Vision Researcher Must Know</title>
      <dc:creator>for IT the</dc:creator>
      <pubDate>Thu, 11 Jun 2026 17:45:26 +0000</pubDate>
      <link>https://dev.to/for_itthe_9cb5ee8d4b91f2/top-5-image-dehazing-datasets-every-computer-vision-researcher-must-know-plj</link>
      <guid>https://dev.to/for_itthe_9cb5ee8d4b91f2/top-5-image-dehazing-datasets-every-computer-vision-researcher-must-know-plj</guid>
      <description>&lt;p&gt;A Complete Guide to Hazy-Clean Paired Datasets, Haze Types, Metrics, Models, and Implementation — With Final Year Project Angles for Researchers, PhD, M.Tech, and Final Year Students&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Who is this for? Final year B.Tech/M.Tech students building a dehazing project, PhD researchers benchmarking new architectures, and CV practitioners who need to understand which dataset to trust and why. Every section is written to save you the 40+ hours of scattered paper-reading that most researchers go through before picking a dataset.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;&lt;strong&gt;Table of Contents&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Introduction&lt;/li&gt;
&lt;li&gt;What Makes a Great Image Dehazing Dataset?&lt;/li&gt;
&lt;li&gt;Dataset 1 — RESIDE&lt;/li&gt;
&lt;li&gt;Dataset 2 — O-Haze&lt;/li&gt;
&lt;li&gt;Dataset 3 — I-Haze&lt;/li&gt;
&lt;li&gt;Dataset 4 — NH-Haze&lt;/li&gt;
&lt;li&gt;Dataset 5 — Dense-Haze&lt;/li&gt;
&lt;li&gt;Image Dehazing Metrics Explained&lt;/li&gt;
&lt;li&gt;Comparison Table — All 5 Datasets Across 12+ Attributes&lt;/li&gt;
&lt;li&gt;How to Choose the Right Dataset&lt;/li&gt;
&lt;li&gt;Common Dehazing Models Benchmarked&lt;/li&gt;
&lt;li&gt;How to Prepare Hazy-Clean Pairs for Training&lt;/li&gt;
&lt;li&gt;Research Gap Radar — 5 Open Problems&lt;/li&gt;
&lt;li&gt;Implementation Roadmap — 8-Step Week-by-Week Guide&lt;/li&gt;
&lt;li&gt;Tools and Frameworks&lt;/li&gt;
&lt;li&gt;7 Common Mistakes Researchers Make&lt;/li&gt;
&lt;li&gt;Your Next Steps + Conclusion&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;h3&gt;
  
  
  What is Image Dehazing?
&lt;/h3&gt;

&lt;p&gt;Image dehazing is the process of recovering a clear, haze-free image J from a hazy observation I, where atmospheric scattering has degraded contrast, colour fidelity, and visibility. The classical physical model that governs this degradation is the &lt;strong&gt;Atmospheric Scattering Model (ASM)&lt;/strong&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Filn0wdj547fmrl053ekz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Filn0wdj547fmrl053ekz.png" alt="Atmospheric Scattering Model (ASM)" width="324" height="41"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;where:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;I(x)&lt;/strong&gt; is the observed hazy image at pixel x&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;J(x)&lt;/strong&gt; is the scene radiance (the clean image we want to recover)
-** t(x)** is the transmission map — the fraction of light that reaches the camera without being scattered&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A&lt;/strong&gt; is the global atmospheric light (the colour of the haze, typically a bright greyish-white)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The transmission map is related to scene depth &lt;strong&gt;d(x)&lt;/strong&gt; and the atmospheric scattering coefficient &lt;strong&gt;β&lt;/strong&gt; by:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fumg8v006lsj4ywci8e8u.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fumg8v006lsj4ywci8e8u.png" alt="atmospheric scattering coefficient" width="200" height="42"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This means that distant objects (large d) have very low transmission — they are almost completely obscured by haze — while nearby objects retain most of their original appearance. Dehazing algorithms work by estimating &lt;strong&gt;t(x)&lt;/strong&gt; and &lt;strong&gt;A&lt;/strong&gt; from &lt;strong&gt;I(x)&lt;/strong&gt; alone, then inverting the &lt;strong&gt;ASM **to recover **J(x)&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Three Eras of Dehazing Research
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Prior-based era (2000s–2014):&lt;/strong&gt; Methods like Dark Channel Prior (DCP) by He et al. (CVPR 2009, TPAMI 2011) exploited the statistical observation that in most haze-free image patches, at least one colour channel has very low intensity. DCP-based dehazing became the foundational baseline that all subsequent methods compare against.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Deep learning era (2016–2020):&lt;/strong&gt; CNNs such as DehazeNet, MSCNN, AOD-Net, and GFN learned end-to-end mappings from hazy to clean images, dramatically outperforming prior-based methods on benchmark datasets. These methods were trained and evaluated almost exclusively on synthetic haze.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Transformer and physics-guided era (2020–present):&lt;/strong&gt; Models like FFA-Net, MAXIM, DehazeFormer, and Dehamer use attention mechanisms, multi-scale feature fusion, and explicit physical priors simultaneously. The critical challenge of this era is the synthetic-to-real gap: models trained on synthetic haze often fail on real outdoor haze despite achieving high PSNR on benchmarks.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Why Datasets Matter in Dehazing
&lt;/h3&gt;

&lt;p&gt;Dehazing has a unique dataset challenge that other restoration tasks do not share: &lt;strong&gt;obtaining ground-truth clean images for real hazy scenes is extremely difficult.&lt;/strong&gt; You cannot photograph the same scene on a clear day and a hazy day and simply compare them — the lighting, time of day, and seasonal variation will have changed. This fundamental difficulty has driven the community to develop multiple creative dataset collection strategies, each with its own trade-offs.&lt;/p&gt;

&lt;p&gt;Understanding which dataset uses which strategy — and what limitations that introduces — is essential for correctly interpreting benchmark results and designing your own research.&lt;/p&gt;

&lt;h3&gt;
  
  
  How This Article is Structured
&lt;/h3&gt;

&lt;p&gt;Each of the five dataset sections follows the same 12-subsection template: overview, origin, haze characteristics, image statistics, download/access, metadata block, licence, how researchers use it, code to load it, reported state-of-the-art numbers, known limitations, research angles, and a quick-reference summary card. After the datasets, you get metrics, model benchmarks, data preparation recipes, a research gap radar, a week-by-week implementation roadmap, and the tooling ecosystem.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Makes a Great Image Dehazing Dataset?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. Haze Type Coverage&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Haze in the real world is not a single phenomenon. Homogeneous haze is uniform across the image — a simple fog where density does not vary much spatially. Heterogeneous (non-homogeneous) haze varies spatially — thick patches next to thin patches, common in morning mist and industrial smog. Dense haze almost completely obscures distant scene content with transmission values near zero. A great dataset should clearly document which type it contains, because models trained on homogeneous synthetic haze fail dramatically on non-homogeneous real haze.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Synthetic vs Real Haze&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Synthetic haze is generated by applying the ASM to clean images using depth maps, yielding perfectly aligned hazy-clean pairs with precisely known A and t(x). Synthetic data enables controlled training and full-reference evaluation but misses the spectral, spatial, and dynamic complexity of real outdoor haze.&lt;/p&gt;

&lt;p&gt;Real haze is captured in actual foggy or hazy weather conditions. Getting clean ground truth requires using a haze machine in a controlled indoor setting (I-Haze, O-Haze), capturing the scene before and after haze (challenging outdoors), or accepting that no ground truth is available (unpaired real haze datasets like RTTS).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Indoor vs Outdoor Scenes&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Indoor dehazing (I-Haze) and outdoor dehazing (O-Haze) involve fundamentally different illumination conditions, depth ranges, and haze density profiles. A model trained only on indoor data will fail outdoors because the depth range — and therefore the transmission variation across the image — is completely different.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Image Diversity and Scale&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A dataset with 10 images is suitable only for evaluation, not training. A dataset with 10,000 image pairs covers a range of textures, depths, and haze densities sufficient for training robust models. Diversity also means coverage across time of day, season, and weather type.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. Licence and Accessibility&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The dehazing community is smaller than the denoising community and some datasets are less formally licensed. Always check whether a dataset allows commercial use, requires citation, or is restricted to academic research before building a product or open-source tool.&lt;/p&gt;




&lt;h2&gt;
  
  
  Dataset 1 — RESIDE
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1.1 Overview
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;RESIDE (Real-world hazy Images for Single Image DEhazing)&lt;/strong&gt; is the largest and most comprehensive image dehazing dataset ever created and is the undisputed standard for dehazing benchmarking. Published by Li et al. at IEEE TIP 2019, RESIDE combines synthetic indoor and outdoor hazy images at large scale with a carefully curated real-world evaluation set. If you have read any deep learning dehazing paper since 2018, you have almost certainly seen PSNR and SSIM numbers on RESIDE's SOTS (Synthetic Objective Testing Set) subset.&lt;/p&gt;

&lt;h3&gt;
  
  
  1.2 Origin and History
&lt;/h3&gt;

&lt;p&gt;RESIDE was created by researchers at Hefei University of Technology and the University of Maryland. The authors recognised that existing dehazing datasets were either too small (a few dozen images) or evaluated only on synthetic data, creating a gap between benchmark performance and real-world results. RESIDE was designed to bridge this gap by providing multiple subsets covering different haze types, densities, and evaluation protocols.&lt;/p&gt;

&lt;p&gt;The dataset was introduced alongside the RESIDE benchmark challenge and has been updated in multiple versions. RESIDE-V0 (the original) and RESIDE-6K (a curated 6,000-pair training subset) are the most commonly used variants in recent papers.&lt;/p&gt;

&lt;h3&gt;
  
  
  1.3 Haze Characteristics
&lt;/h3&gt;

&lt;p&gt;RESIDE uses &lt;strong&gt;synthetic haze&lt;/strong&gt; generated by applying the ASM to depth maps:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;**Indoor subset (ITS — Indoor Training Set): **13,990 hazy images generated from 1,399 clean indoor images using synthetic depth maps and multiple A and β values per image.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Outdoor subset (OTS — Outdoor Training Set):&lt;/strong&gt; 313,950 hazy images from clean outdoor images with synthetic haze. The scale of OTS is unique in the dehazing field.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SOTS (Synthetic Objective Testing Set):&lt;/strong&gt; 500 indoor + 500 outdoor test images with ground truth. This is the standard evaluation split.&lt;/li&gt;
&lt;li&gt;**HSTS (Hybrid Subjective Testing Set): **10 synthetic + 10 real hazy images for perceptual evaluation without ground truth on the real subset.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;RTTS (Real-world Task-driven Testing Set):&lt;/strong&gt; 4,322 real hazy images without ground truth, for qualitative evaluation only.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Haze parameters: atmospheric light A ∈ &lt;a href="https://dev.touniform%20RGB"&gt;0.7, 1.0&lt;/a&gt;, scattering coefficient β ∈ [0.04, 0.20] for outdoor, β ∈ [0.6, 1.8] for indoor.&lt;/p&gt;

&lt;h3&gt;
  
  
  1.4 Image Statistics
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;Attribute&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Value&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Indoor training pairs (ITS)&lt;/td&gt;
&lt;td&gt;13,990 hazy + 1,399 clean&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Outdoor training pairs (OTS)&lt;/td&gt;
&lt;td&gt;313,950 hazy + 8,970 clean&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SOTS test pairs&lt;/td&gt;
&lt;td&gt;500 indoor + 500 outdoor&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;RTTS real images (no GT)&lt;/td&gt;
&lt;td&gt;4,322&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Resolution&lt;/td&gt;
&lt;td&gt;Varies: 460×620 (indoor), up to 1024×1024 (outdoor)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Haze type&lt;/td&gt;
&lt;td&gt;Synthetic homogeneous&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Depth maps&lt;/td&gt;
&lt;td&gt;Included for ITS&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Colour space&lt;/td&gt;
&lt;td&gt;RGB&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  1.5 Download and Access
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Official RESIDE page:&lt;/strong&gt; &lt;a href="https://sites.google.com/view/reside-dehaze-datasets/" rel="noopener noreferrer"&gt;https://sites.google.com/view/reside-dehaze-datasets/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;RESIDE-6K (compact training set):&lt;/strong&gt; &lt;a href="https://github.com/liuye123321/DMT-Net" rel="noopener noreferrer"&gt;https://github.com/liuye123321/DMT-Net&lt;/a&gt; — linked in the repository README&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Kaggle mirror:&lt;/strong&gt; Search "RESIDE dehazing dataset" on Kaggle for community-hosted versions of ITS and SOTS&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Direct Google Drive links&lt;/strong&gt; for each subset are available on the official page&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;1.6 Dataset Metadata&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  1.7 Licence
&lt;/h3&gt;

&lt;p&gt;RESIDE is released for &lt;strong&gt;non-commercial research and education&lt;/strong&gt; use only. All publications using RESIDE must cite the original IEEE TIP paper. Commercial use requires written permission from the dataset creators.&lt;/p&gt;

&lt;h3&gt;
  
  
  1.8 How Researchers Use RESIDE
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Standard training protocol:&lt;/strong&gt; Train on ITS (indoor) or OTS (outdoor) or both. Most recent papers use ITS for indoor evaluation and OTS for outdoor evaluation separately, since models trained on indoor data do not generalise well to outdoor haze due to different depth ranges.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Standard evaluation protocol:&lt;/strong&gt; Report PSNR and SSIM on SOTS-Indoor (500 pairs) and SOTS-Outdoor (500 pairs) separately. Always specify which SOTS subset you are using — "SOTS" alone is ambiguous.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Qualitative evaluation:&lt;/strong&gt; Run inference on RTTS images and include visual comparisons in your paper. Since RTTS has no ground truth, only qualitative assessment is possible.&lt;/p&gt;

&lt;h3&gt;
  
  
  1.9 Code to Load RESIDE
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;numpy&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;PIL&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Image&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;torch.utils.data&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Dataset&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;RESIDEDataset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Dataset&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
    Dataset loader for RESIDE ITS or SOTS.

    Directory structure expected:
      root/
        hazy/   &amp;lt;- hazy images (named e.g. 1_1.png, 1_2.png for ITS)
        clear/  &amp;lt;- clean images (named e.g. 1.png for ITS)

    For ITS, multiple hazy images correspond to one clean image.
    The naming convention is {clean_id}_{haze_param_id}.png
    &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;mode&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;its&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;transform&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;root&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;root&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;transform&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;transform&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;hazy_dir&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;hazy&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;clean_dir&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;clear&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;hazy_files&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;sorted&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listdir&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;hazy_dir&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;mode&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;its&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="c1"&gt;# For ITS: extract clean image ID from hazy filename
&lt;/span&gt;            &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;clean_map&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;_&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;.png&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
                &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;h&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;hazy_files&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="c1"&gt;# For SOTS: 1-to-1 correspondence
&lt;/span&gt;            &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;clean_map&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;h&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;h&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;hazy_files&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__len__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;hazy_files&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__getitem__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;idx&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;hazy_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;hazy_files&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;idx&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="n"&gt;clean_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;clean_map&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;hazy_name&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

        &lt;span class="n"&gt;hazy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;Image&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;hazy_dir&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;hazy_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;astype&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;float32&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mf"&gt;255.0&lt;/span&gt;

        &lt;span class="n"&gt;clean&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;Image&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;clean_dir&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;clean_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;astype&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;float32&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mf"&gt;255.0&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;transform&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;hazy&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;clean&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;transform&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;hazy&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;clean&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="c1"&gt;# Convert to (C, H, W) for PyTorch
&lt;/span&gt;        &lt;span class="n"&gt;hazy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;hazy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;transpose&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;clean&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;clean&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;transpose&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;hazy&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;clean&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;compute_psnr_ssim_reside&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;sots_root&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;split&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;indoor&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
    Evaluate a dehazing model on RESIDE SOTS.
    &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;

    &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;torch&lt;/span&gt;
    &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;skimage.metrics&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;peak_signal_noise_ratio&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;psnr&lt;/span&gt;
    &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;skimage.metrics&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;structural_similarity&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;ssim&lt;/span&gt;

    &lt;span class="n"&gt;dataset&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;RESIDEDataset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sots_root&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;split&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="n"&gt;mode&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;sots&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;psnr_list&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
    &lt;span class="n"&gt;ssim_list&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;hazy_t&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;clean_t&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;dataset&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;torch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;no_grad&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
            &lt;span class="n"&gt;output&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;model&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="n"&gt;hazy_t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;unsqueeze&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;squeeze&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="n"&gt;output_np&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;output&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;permute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;cpu&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;numpy&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;clip&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="n"&gt;clean_np&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;clean_t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;permute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;cpu&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;numpy&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="n"&gt;psnr_list&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="nf"&gt;psnr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="n"&gt;clean_np&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="n"&gt;output_np&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="n"&gt;data_range&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;1.0&lt;/span&gt;
            &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="n"&gt;ssim_list&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="nf"&gt;ssim&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="n"&gt;clean_np&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="n"&gt;output_np&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="n"&gt;data_range&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="n"&gt;multichannel&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="n"&gt;channel_axis&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;
            &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;RESIDE SOTS-&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;split&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; | &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;PSNR: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;mean&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;psnr_list&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; dB | &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;SSIM: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;mean&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ssim_list&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="nf"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;mean&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;psnr_list&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;mean&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ssim_list&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  1.10 State-of-the-Art Numbers on RESIDE SOTS
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;SOTS-Indoor:&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Model&lt;/th&gt;
&lt;th&gt;Year&lt;/th&gt;
&lt;th&gt;PSNR (dB)&lt;/th&gt;
&lt;th&gt;SSIM&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;DCP&lt;/td&gt;
&lt;td&gt;2011&lt;/td&gt;
&lt;td&gt;16.62&lt;/td&gt;
&lt;td&gt;0.818&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DehazeNet&lt;/td&gt;
&lt;td&gt;2016&lt;/td&gt;
&lt;td&gt;21.14&lt;/td&gt;
&lt;td&gt;0.847&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AOD-Net&lt;/td&gt;
&lt;td&gt;2017&lt;/td&gt;
&lt;td&gt;20.29&lt;/td&gt;
&lt;td&gt;0.877&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;MSBDN&lt;/td&gt;
&lt;td&gt;2020&lt;/td&gt;
&lt;td&gt;33.67&lt;/td&gt;
&lt;td&gt;0.985&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;FFA-Net&lt;/td&gt;
&lt;td&gt;2020&lt;/td&gt;
&lt;td&gt;36.39&lt;/td&gt;
&lt;td&gt;0.989&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;MAXIM&lt;/td&gt;
&lt;td&gt;2022&lt;/td&gt;
&lt;td&gt;38.11&lt;/td&gt;
&lt;td&gt;0.991&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DehazeFormer-B&lt;/td&gt;
&lt;td&gt;2023&lt;/td&gt;
&lt;td&gt;40.05&lt;/td&gt;
&lt;td&gt;0.994&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;SOTS-Outdoor:&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Model&lt;/th&gt;
&lt;th&gt;Year&lt;/th&gt;
&lt;th&gt;PSNR (dB)&lt;/th&gt;
&lt;th&gt;SSIM&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;DCP&lt;/td&gt;
&lt;td&gt;2011&lt;/td&gt;
&lt;td&gt;19.13&lt;/td&gt;
&lt;td&gt;0.815&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AOD-Net&lt;/td&gt;
&lt;td&gt;2017&lt;/td&gt;
&lt;td&gt;24.14&lt;/td&gt;
&lt;td&gt;0.920&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GDN&lt;/td&gt;
&lt;td&gt;2019&lt;/td&gt;
&lt;td&gt;30.86&lt;/td&gt;
&lt;td&gt;0.982&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;MSBDN&lt;/td&gt;
&lt;td&gt;2020&lt;/td&gt;
&lt;td&gt;33.48&lt;/td&gt;
&lt;td&gt;0.982&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;FFA-Net&lt;/td&gt;
&lt;td&gt;2020&lt;/td&gt;
&lt;td&gt;33.57&lt;/td&gt;
&lt;td&gt;0.984&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DehazeFormer-B&lt;/td&gt;
&lt;td&gt;2023&lt;/td&gt;
&lt;td&gt;34.81&lt;/td&gt;
&lt;td&gt;0.986&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  1.11 Known Limitations
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;**Synthetic haze only (ITS/OTS/SOTS). **The ASM-based synthetic haze is spatially homogeneous and does not capture real-world haze complexity. Models achieving 40+ dB on SOTS-Indoor can look visually poor on real outdoor photos.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Depth map quality for ITS.&lt;/strong&gt; Indoor depth maps from datasets like NYU Depth V2 used in RESIDE generation have noise and errors that introduce artefacts in synthetic haze.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scale imbalance.&lt;/strong&gt; OTS is 300K+ images; most research groups train on ITS only due to compute constraints, meaning OTS is underutilised.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No heterogeneous haze.&lt;/strong&gt; All RESIDE synthetic haze is generated with a single global A per image — real haze has spatially varying A, which this dataset does not capture.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  1.12 Research Angles for Final Year / PhD Students
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;**Synthetic-to-real domain adaptation: **Train on RESIDE-ITS and evaluate on O-Haze or NH-Haze. Quantify the domain gap and propose an adaptation method.&lt;/li&gt;
&lt;li&gt;**Depth-aware dehazing: **Use the depth maps included with RESIDE-ITS to design a depth-conditioned architecture that varies its processing by scene distance.&lt;/li&gt;
&lt;li&gt;**RTTS as an unsupervised training signal: **Apply Noise2Noise-style or contrastive learning using RTTS real hazy images without ground truth.&lt;/li&gt;
&lt;li&gt;**Lightweight dehazing on OTS: **Most papers train on ITS; use the full OTS scale to train a lightweight model and show that scale compensates for reduced model capacity.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  1.13 Quick Reference Card
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;*&lt;em&gt;RESIDE *&lt;/em&gt;| 13,990 indoor + 313,950 outdoor training pairs | SOTS: 1,000 test pairs | Synthetic homogeneous haze | Non-commercial research licence | Use as: training + standard benchmark | Primary metrics: PSNR, SSIM on SOTS | Download: &lt;a href="https://sites.google.com/view/reside-dehaze-datasets/" rel="noopener noreferrer"&gt;sites.google.com/view/reside-dehaze-datasets/&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Dataset 2 — O-Haze
&lt;/h2&gt;

&lt;h3&gt;
  
  
  2.1 Overview
&lt;/h3&gt;

&lt;p&gt;O-Haze (Outdoor Haze dataset) is the first dataset to provide real outdoor hazy-clean image pairs captured using a professional haze machine. Released by Ancuti et al. at CVPR Workshop 2018, O-Haze addresses the fundamental limitation of purely synthetic benchmarks by providing genuine optical haze — the same atmospheric scattering physics that occurs in real foggy weather, reproduced in a controlled outdoor setting. It is one of the NTIRE 2018 and NTIRE 2019 challenge datasets, giving it significant community visibility.&lt;/p&gt;

&lt;h3&gt;
  
  
  2.2 Origin and History
&lt;/h3&gt;

&lt;p&gt;O-Haze was created at the Multimedia Lab of Hasselt University, Belgium. The collection methodology was carefully designed: 45 outdoor scenes were photographed both with and without haze produced by a professional haze machine positioned to fill the scene. The haze machine produces water-droplet-based aerosol that mimics the optical properties of natural outdoor haze and fog. This approach yields &lt;strong&gt;perfectly aligned hazy-clean pairs&lt;/strong&gt; — the camera is fixed, only the haze presence changes between the two captures.&lt;/p&gt;

&lt;p&gt;O-Haze was one of the first datasets to allow researchers to quantitatively evaluate real-haze dehazing with full-reference metrics, filling a critical gap between synthetic benchmarks and purely qualitative real-world testing.&lt;/p&gt;

&lt;h3&gt;
  
  
  2.3 Haze Characteristics
&lt;/h3&gt;

&lt;p&gt;O-Haze haze is &lt;strong&gt;real, optically generated&lt;/strong&gt; using a professional haze/fog machine:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Haze type:&lt;/strong&gt; Dense, relatively homogeneous fog produced by atomised water particles.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Spatial variation:&lt;/strong&gt; Some spatial variation exists due to wind, outdoor air movement, and distance from the haze machine — making it more realistic than synthetic homogeneous haze.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Depth correlation:&lt;/strong&gt; Distant objects are more obscured than near objects, consistent with the ASM model.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Colour shift:&lt;/strong&gt; Real haze introduces a whitish colour cast that varies slightly from image to image depending on ambient lighting and haze density — unlike the constant A used in synthetic datasets.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Haze density:&lt;/strong&gt; Generally dense — visibility is significantly reduced in most image pairs.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2.4 Image Statistics
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Attribute&lt;/th&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Total image pairs&lt;/td&gt;
&lt;td&gt;45 (hazy + clean)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Training pairs&lt;/td&gt;
&lt;td&gt;40&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Validation pairs&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Test pairs (withheld for challenge)&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Resolution&lt;/td&gt;
&lt;td&gt;4964×3312 pixels (original, ~16 MP)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Standard evaluation resolution&lt;/td&gt;
&lt;td&gt;Resized to 512×512 or 1024×1024&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Haze type&lt;/td&gt;
&lt;td&gt;Real (haze machine), outdoor&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Scene content&lt;/td&gt;
&lt;td&gt;Gardens, streets, paths, vegetation&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Colour space&lt;/td&gt;
&lt;td&gt;RGB&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  2.5 Download and Access
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Official O-Haze page (NTIRE challenge):&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
&lt;a href="https://data.vision.ee.ethz.ch/cvl/ntire18/o-haze/" rel="noopener noreferrer"&gt;https://data.vision.ee.ethz.ch/cvl/ntire18/o-haze/&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Direct download:&lt;/strong&gt; Available from the official page — requires accepting a short terms-of-use agreement.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Papers with code listing:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
&lt;a href="https://paperswithcode.com/dataset/o-haze" rel="noopener noreferrer"&gt;https://paperswithcode.com/dataset/o-haze&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Google Drive mirror:&lt;/strong&gt; Linked from several GitHub repositories including the NTIRE 2018 challenge GitHub.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2.6 Dataset Metadata
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Field&lt;/th&gt;
&lt;th&gt;Detail&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Official Download&lt;/td&gt;
&lt;td&gt;&lt;a href="https://data.vision.ee.ethz.ch/cvl/ntire18/o-haze/" rel="noopener noreferrer"&gt;https://data.vision.ee.ethz.ch/cvl/ntire18/o-haze/&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Published&lt;/td&gt;
&lt;td&gt;April 2018 (CVPR Workshop)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;License&lt;/td&gt;
&lt;td&gt;Non-commercial research use&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Authors&lt;/td&gt;
&lt;td&gt;Codruta O. Ancuti, Cosmin Ancuti, Radu Timofte, Christophe De Vleeschouwer&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;File size&lt;/td&gt;
&lt;td&gt;~2.1 GB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Citation&lt;/td&gt;
&lt;td&gt;Ancuti et al., "O-HAZE: A Dehazing Benchmark with Real Hazy and Haze-Free Outdoor Images," CVPRW 2018&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  2.7 Licence
&lt;/h3&gt;

&lt;p&gt;O-Haze is available for &lt;strong&gt;non-commercial research and educational use&lt;/strong&gt;. Citation of the CVPR Workshop 2018 paper is required. The dataset was released as part of the NTIRE 2018 challenge and remains hosted by ETH Zurich's Computer Vision Laboratory.&lt;/p&gt;

&lt;h3&gt;
  
  
  2.8 How Researchers Use O-Haze
&lt;/h3&gt;

&lt;p&gt;O-Haze is used almost exclusively as a &lt;strong&gt;test dataset&lt;/strong&gt; due to its relatively small size (45 image pairs). The standard evaluation protocol is:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Train on RESIDE-ITS or OTS (synthetic datasets).&lt;/li&gt;
&lt;li&gt;Fine-tune or directly evaluate on O-Haze to assess real-haze generalisation.&lt;/li&gt;
&lt;li&gt;Report PSNR and SSIM on the 40-pair training set (in some papers) or the 5-pair validation set.&lt;/li&gt;
&lt;li&gt;Submit results to the NTIRE challenge evaluation server for official benchmark numbers.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Papers that achieve strong performance on RESIDE-SOTS but perform poorly on O-Haze typically reveal a &lt;strong&gt;synthetic-to-real gap&lt;/strong&gt;. This gap highlights the importance of real-world evaluation, making O-Haze a key benchmark for validating practical dehazing algorithms.&lt;/p&gt;

&lt;h3&gt;
  
  
  2.9 Code to Load O-Haze
&lt;/h3&gt;

&lt;p&gt;The following example demonstrates how to create a PyTorch dataset loader for O-Haze. Since O-Haze provides perfectly aligned hazy and haze-free image pairs, loading the dataset follows a straightforward paired-image approach.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;numpy&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;PIL&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Image&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;glob&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;glob&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;skimage.metrics&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;peak_signal_noise_ratio&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;psnr&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;skimage.metrics&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;structural_similarity&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;ssim&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;load_ohaze_pairs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ohaze_root&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;split&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;train&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;target_size&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;512&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;512&lt;/span&gt;&lt;span class="p"&gt;)):&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
    Load O-Haze hazy-clean pairs.

    Expected structure:
      ohaze_root/
        hazy/   &amp;lt;- hazy images (e.g. 01_outdoor_hazy.jpg)
        GT/     &amp;lt;- clean ground truth (e.g. 01_outdoor_GT.jpg)
    &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="n"&gt;hazy_files&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;sorted&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;glob&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ohaze_root&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;hazy&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;*.jpg&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
    &lt;span class="n"&gt;gt_files&lt;/span&gt;   &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;sorted&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;glob&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ohaze_root&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;GT&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;*.jpg&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;

    &lt;span class="n"&gt;pairs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;hf&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;gf&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;zip&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;hazy_files&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;gt_files&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;hazy&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Image&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;hf&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;convert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;RGB&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;clean&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Image&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gf&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;convert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;RGB&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;target_size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;hazy&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;hazy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;resize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;target_size&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Image&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;LANCZOS&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;clean&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;clean&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;resize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;target_size&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Image&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;LANCZOS&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="n"&gt;hazy_np&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;hazy&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;astype&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;float32&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mf"&gt;255.0&lt;/span&gt;
        &lt;span class="n"&gt;clean_np&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;clean&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;astype&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;float32&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mf"&gt;255.0&lt;/span&gt;
        &lt;span class="n"&gt;pairs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;hazy_np&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;clean_np&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Loaded &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pairs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; O-Haze pairs at &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;target_size&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;pairs&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;evaluate_ohaze&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;model_fn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pairs&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Evaluate a dehazing model on O-Haze pairs.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="n"&gt;psnr_list&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ssim_list&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;hazy&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;clean&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;pairs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;dehazed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;model_fn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;hazy&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;psnr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;clean&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dehazed&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;data_range&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;ssim&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;clean&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dehazed&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;data_range&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                 &lt;span class="n"&gt;multichannel&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;channel_axis&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;psnr_list&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;ssim_list&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;O-Haze | PSNR: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;mean&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;psnr_list&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; dB | &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
          &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;SSIM: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;mean&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ssim_list&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;mean&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;psnr_list&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;mean&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ssim_list&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2.10 State-of-the-Art Numbers on O-Haze
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Model&lt;/th&gt;
&lt;th&gt;Year&lt;/th&gt;
&lt;th&gt;PSNR (dB)&lt;/th&gt;
&lt;th&gt;SSIM&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;DCP&lt;/td&gt;
&lt;td&gt;2011&lt;/td&gt;
&lt;td&gt;15.78&lt;/td&gt;
&lt;td&gt;0.561&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;MSCNN&lt;/td&gt;
&lt;td&gt;2016&lt;/td&gt;
&lt;td&gt;17.56&lt;/td&gt;
&lt;td&gt;0.810&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AOD-Net&lt;/td&gt;
&lt;td&gt;2017&lt;/td&gt;
&lt;td&gt;15.03&lt;/td&gt;
&lt;td&gt;0.527&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GFN&lt;/td&gt;
&lt;td&gt;2018&lt;/td&gt;
&lt;td&gt;21.55&lt;/td&gt;
&lt;td&gt;0.844&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;FPDN&lt;/td&gt;
&lt;td&gt;2019&lt;/td&gt;
&lt;td&gt;22.57&lt;/td&gt;
&lt;td&gt;0.863&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;FFA-Net&lt;/td&gt;
&lt;td&gt;2020&lt;/td&gt;
&lt;td&gt;22.12&lt;/td&gt;
&lt;td&gt;0.858&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AECR-Net&lt;/td&gt;
&lt;td&gt;2021&lt;/td&gt;
&lt;td&gt;23.43&lt;/td&gt;
&lt;td&gt;0.879&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DehazeFormer-B&lt;/td&gt;
&lt;td&gt;2023&lt;/td&gt;
&lt;td&gt;24.16&lt;/td&gt;
&lt;td&gt;0.891&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; O-Haze PSNR values are substantially lower than RESIDE-SOTS values. This is expected because O-Haze contains real atmospheric haze rather than synthetic haze. Direct comparison of absolute PSNR and SSIM values across different datasets is not recommended.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  2.11 Known Limitations
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Only 45 pairs:&lt;/strong&gt; The dataset is extremely small and cannot be used for training deep models from scratch. It is primarily intended for evaluation and fine-tuning experiments.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Haze machine ≠ natural haze:&lt;/strong&gt; The water-droplet aerosol generated by a professional haze machine differs from natural atmospheric haze in particle-size distribution, humidity, and spectral characteristics. Models trained on O-Haze may not fully generalize to real-world weather conditions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Controlled outdoor setting:&lt;/strong&gt; All scenes were captured in a similar garden and outdoor environment. Scene diversity is limited compared to large-scale benchmarks.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No depth information:&lt;/strong&gt; Unlike RESIDE, O-Haze does not provide depth maps, transmission maps, or atmospheric-light annotations.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Resolution mismatch:&lt;/strong&gt; Original images are approximately 4964×3312 pixels (~16 MP), but most studies evaluate at resized resolutions such as 512×512 or 1024×1024, introducing potential scaling artifacts.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2.12 Research Angles for Final Year / PhD Students
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Domain-gap measurement:&lt;/strong&gt; Train a model on RESIDE-OTS and evaluate it directly on O-Haze. Measure the synthetic-to-real performance gap and identify scene categories (vegetation, sky, roads, shadows) that suffer the most degradation.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fine-tuning with limited real data:&lt;/strong&gt; Investigate how fine-tuning on only a small subset of O-Haze pairs affects generalization. Compare different adaptation strategies and determine the minimum number of real-haze samples required.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Perceptual quality optimization:&lt;/strong&gt; Analyze why PSNR-optimized dehazing methods sometimes produce halo artifacts or unnatural colors on O-Haze. Explore perceptual, adversarial, or human-visual-system-based losses to improve visual quality.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Multi-scale evaluation:&lt;/strong&gt; Compare model performance at original resolution (4964×3312) and resized resolutions. Quantify how downsampling influences haze-removal quality and fine-detail restoration.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Real-haze robustness benchmarking:&lt;/strong&gt; Evaluate recent transformer-based and diffusion-based dehazing models on O-Haze to determine whether improvements on synthetic datasets translate to real-world haze.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cross-dataset generalization:&lt;/strong&gt; Train on RESIDE, Dense-Haze, or NH-Haze and test on O-Haze. Analyze which datasets contribute most to real-world generalization.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Failure-case analysis:&lt;/strong&gt; Categorize common failure modes such as color shifts, over-enhancement, sky artifacts, and texture loss. Build a taxonomy of errors to guide future model development.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2.13 Quick Reference Card
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;O-Haze&lt;/strong&gt; | 45 real outdoor pairs | Real optical haze (haze machine) | Non-commercial research license | Released: 2018 (CVPR Workshop) | Primary metrics: PSNR, SSIM | Resolution: 4964×3312 (~16 MP) | Download: &lt;a href="https://data.vision.ee.ethz.ch/cvl/ntire18/o-haze/" rel="noopener noreferrer"&gt;https://data.vision.ee.ethz.ch/cvl/ntire18/o-haze/&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Dataset 3 — I-Haze
&lt;/h2&gt;

&lt;h3&gt;
  
  
  3.1 Overview
&lt;/h3&gt;

&lt;p&gt;I-Haze (&lt;strong&gt;Indoor Haze dataset&lt;/strong&gt;) is the indoor counterpart to O-Haze, released by the same Hasselt University team at CVPR Workshop 2018. The dataset contains real hazy-clean image pairs captured in a controlled indoor environment using a professional haze machine. It serves as one of the primary benchmarks for indoor image dehazing and was used in the NTIRE 2018 and NTIRE 2019 challenge tracks.&lt;/p&gt;

&lt;h3&gt;
  
  
  3.2 Origin and History
&lt;/h3&gt;

&lt;p&gt;I-Haze was motivated by the observation that indoor haze and smoke (originating from cooking fumes, industrial ventilation failures, fires, and cigarette smoke) present challenges distinct from outdoor haze. The dataset was created using the same methodology as O-Haze, where a professional haze machine filled a controlled indoor environment with dense haze while maintaining identical camera positions for the hazy and haze-free captures.&lt;/p&gt;

&lt;p&gt;The dataset was released with predefined training and validation splits and supported NTIRE challenge evaluations through a centralized evaluation server, enabling reproducible benchmarking and fair comparison of dehazing methods.&lt;/p&gt;

&lt;h3&gt;
  
  
  3.3 Haze Characteristics
&lt;/h3&gt;

&lt;p&gt;I-Haze uses &lt;strong&gt;real, optically generated indoor haze&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Haze distribution:&lt;/strong&gt; More spatially uniform than O-Haze because indoor environments have less air movement. This makes I-Haze closer to the assumptions of the Atmospheric Scattering Model (ASM).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Depth range:&lt;/strong&gt; Indoor scenes typically contain shorter depth ranges (3–8 meters) compared to outdoor scenes. Transmission values are therefore generally higher than in outdoor haze datasets.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Colour temperature:&lt;/strong&gt; Indoor scenes often contain mixed illumination sources (artificial lighting combined with natural window light), creating additional color-restoration challenges.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Haze density:&lt;/strong&gt; Dense enough to significantly reduce visibility and contrast while introducing a noticeable whitish haze layer across the scene.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3.4 Image Statistics
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Attribute&lt;/th&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Total image pairs&lt;/td&gt;
&lt;td&gt;35 (hazy + clean)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Training pairs&lt;/td&gt;
&lt;td&gt;25&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Validation pairs&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Test pairs (withheld)&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Resolution&lt;/td&gt;
&lt;td&gt;2833×4256 pixels (original, ~12 MP)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Standard evaluation resolution&lt;/td&gt;
&lt;td&gt;Resized to 512×512 or 1024×1024&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Haze type&lt;/td&gt;
&lt;td&gt;Real (haze machine), indoor&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Scene content&lt;/td&gt;
&lt;td&gt;Living rooms, offices, corridors, furniture, household objects&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Colour space&lt;/td&gt;
&lt;td&gt;RGB&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  3.5 Download and Access
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Official I-Haze page (NTIRE challenge):&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
&lt;a href="https://data.vision.ee.ethz.ch/cvl/ntire18/i-haze/" rel="noopener noreferrer"&gt;https://data.vision.ee.ethz.ch/cvl/ntire18/i-haze/&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Direct download:&lt;/strong&gt; Available from the official page after accepting the dataset terms of use.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Papers with Code listing:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
&lt;a href="https://paperswithcode.com/dataset/i-haze" rel="noopener noreferrer"&gt;https://paperswithcode.com/dataset/i-haze&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Combined I-Haze + O-Haze downloads:&lt;/strong&gt; Community mirrors and GitHub repositories occasionally host both datasets together. Search for "NTIRE 2018 dehazing dataset" to locate available mirrors.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3.6 Dataset Metadata
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Field&lt;/th&gt;
&lt;th&gt;Detail&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Official Download&lt;/td&gt;
&lt;td&gt;&lt;a href="https://data.vision.ee.ethz.ch/cvl/ntire18/i-haze/" rel="noopener noreferrer"&gt;https://data.vision.ee.ethz.ch/cvl/ntire18/i-haze/&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Published&lt;/td&gt;
&lt;td&gt;April 2018 (CVPR Workshop)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;License&lt;/td&gt;
&lt;td&gt;Non-commercial research use&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Authors&lt;/td&gt;
&lt;td&gt;Codruta O. Ancuti, Cosmin Ancuti, Radu Timofte, Christophe De Vleeschouwer&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;File Size&lt;/td&gt;
&lt;td&gt;~1.4 GB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Citation&lt;/td&gt;
&lt;td&gt;Ancuti et al., "I-HAZE: A Dehazing Benchmark with Real Hazy and Haze-Free Indoor Images," CVPRW 2018&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  3.7 Licence
&lt;/h3&gt;

&lt;p&gt;I-Haze is available for &lt;strong&gt;non-commercial research and educational use&lt;/strong&gt;. Citation of the CVPR Workshop 2018 paper is required when publishing results. The dataset continues to be hosted and maintained through ETH Zurich's Computer Vision Laboratory as part of the NTIRE benchmark collection.&lt;/p&gt;

&lt;h3&gt;
  
  
  3.8 How Researchers Use I-Haze
&lt;/h3&gt;

&lt;p&gt;I-Haze is primarily used as an &lt;strong&gt;indoor real-haze evaluation benchmark&lt;/strong&gt;. A typical evaluation workflow is:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Train a model on RESIDE-ITS or RESIDE-OTS synthetic indoor haze datasets.&lt;/li&gt;
&lt;li&gt;Evaluate the trained model directly on I-Haze without additional training.&lt;/li&gt;
&lt;li&gt;Measure the synthetic-to-real domain gap using PSNR and SSIM.&lt;/li&gt;
&lt;li&gt;Compare results with O-Haze to assess indoor versus outdoor generalization.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Many research papers report results on both I-Haze and O-Haze because the two datasets provide complementary real-world evaluation environments. A model that performs well on RESIDE-ITS but poorly on I-Haze often indicates overfitting to synthetic haze characteristics rather than learning physically meaningful haze removal.&lt;/p&gt;

&lt;h3&gt;
  
  
  3.9 Code to Load I-Haze
&lt;/h3&gt;

&lt;p&gt;The following PyTorch dataset loader can be used to load paired hazy and haze-free images from I-Haze.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;numpy&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;PIL&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Image&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;glob&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;glob&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;load_ihaze_pairs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ihaze_root&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;target_size&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;512&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;512&lt;/span&gt;&lt;span class="p"&gt;)):&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
    Load I-Haze hazy-clean pairs.

    Expected structure:
      ihaze_root/
        hazy/   &amp;lt;- hazy images (e.g. 01_indoor_hazy.jpg)
        GT/     &amp;lt;- clean ground truth (e.g. 01_indoor_GT.jpg)
    &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="n"&gt;hazy_files&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;sorted&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;glob&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ihaze_root&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;hazy&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;*.jpg&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
    &lt;span class="n"&gt;gt_files&lt;/span&gt;   &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;sorted&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;glob&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ihaze_root&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;GT&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;*.jpg&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;

    &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;hazy_files&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gt_files&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; \
        &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Mismatch: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;hazy_files&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; hazy vs &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gt_files&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; clean&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

    &lt;span class="n"&gt;pairs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;hf&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;gf&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;zip&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;hazy_files&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;gt_files&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;hazy&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;Image&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;hf&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;convert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;RGB&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;resize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="n"&gt;target_size&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Image&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;LANCZOS&lt;/span&gt;
            &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;astype&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;float32&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mf"&gt;255.0&lt;/span&gt;
        &lt;span class="n"&gt;clean&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;Image&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gf&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;convert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;RGB&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;resize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="n"&gt;target_size&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Image&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;LANCZOS&lt;/span&gt;
            &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;astype&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;float32&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mf"&gt;255.0&lt;/span&gt;
        &lt;span class="n"&gt;pairs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;hazy&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;clean&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Loaded &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pairs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; I-Haze pairs&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;pairs&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;patch_based_dehazing_eval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;model_fn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pairs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;patch_size&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;256&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;stride&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;256&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
    Evaluate model using patch-based inference (for memory-limited GPUs).
    Useful when evaluating at full resolution on I-Haze&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;s large originals.
    &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;skimage.metrics&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;peak_signal_noise_ratio&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;psnr&lt;/span&gt;
    &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;skimage.metrics&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;structural_similarity&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;ssim&lt;/span&gt;
    &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;numpy&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;

    &lt;span class="n"&gt;psnr_list&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ssim_list&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;hazy&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;clean&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;pairs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;H&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;W&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;hazy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;shape&lt;/span&gt;
        &lt;span class="n"&gt;output&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;zeros_like&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;hazy&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;count&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;zeros&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;H&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;W&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;H&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;patch_size&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;stride&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;W&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;patch_size&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;stride&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
                &lt;span class="n"&gt;patch&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;hazy&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;patch_size&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;patch_size&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
                &lt;span class="n"&gt;denoised_patch&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;model_fn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;patch&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="n"&gt;output&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;patch_size&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;patch_size&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;denoised_patch&lt;/span&gt;
                &lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;patch_size&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;patch_size&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;

        &lt;span class="n"&gt;output&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;output&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;clip&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;min&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;clip&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;psnr_list&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;psnr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;clean&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;output&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;data_range&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="n"&gt;ssim_list&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;ssim&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;clean&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;output&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;data_range&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                               &lt;span class="n"&gt;multichannel&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;channel_axis&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;I-Haze patch eval | PSNR: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;mean&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;psnr_list&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; dB | &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
          &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;SSIM: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;mean&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ssim_list&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;psnr_list&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ssim_list&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3.10 State-of-the-Art Numbers on I-Haze
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Model&lt;/th&gt;
&lt;th&gt;Year&lt;/th&gt;
&lt;th&gt;PSNR (dB)&lt;/th&gt;
&lt;th&gt;SSIM&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;DCP&lt;/td&gt;
&lt;td&gt;2011&lt;/td&gt;
&lt;td&gt;14.43&lt;/td&gt;
&lt;td&gt;0.754&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;MSCNN&lt;/td&gt;
&lt;td&gt;2016&lt;/td&gt;
&lt;td&gt;15.22&lt;/td&gt;
&lt;td&gt;0.785&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AOD-Net&lt;/td&gt;
&lt;td&gt;2017&lt;/td&gt;
&lt;td&gt;16.72&lt;/td&gt;
&lt;td&gt;0.820&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GFN&lt;/td&gt;
&lt;td&gt;2018&lt;/td&gt;
&lt;td&gt;22.30&lt;/td&gt;
&lt;td&gt;0.880&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;FPDN&lt;/td&gt;
&lt;td&gt;2019&lt;/td&gt;
&lt;td&gt;22.83&lt;/td&gt;
&lt;td&gt;0.888&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;FFA-Net&lt;/td&gt;
&lt;td&gt;2020&lt;/td&gt;
&lt;td&gt;23.75&lt;/td&gt;
&lt;td&gt;0.912&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AECR-Net&lt;/td&gt;
&lt;td&gt;2021&lt;/td&gt;
&lt;td&gt;24.02&lt;/td&gt;
&lt;td&gt;0.915&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DehazeFormer-B&lt;/td&gt;
&lt;td&gt;2023&lt;/td&gt;
&lt;td&gt;25.14&lt;/td&gt;
&lt;td&gt;0.927&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; I-Haze contains real indoor haze rather than synthetic haze. Consequently, PSNR and SSIM values are generally lower than those reported on synthetic benchmarks such as RESIDE-ITS. Cross-dataset comparison of absolute metric values should be avoided.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  3.11 Known Limitations
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Only 35 image pairs:&lt;/strong&gt; I-Haze is one of the smallest dehazing datasets available. Performance estimates can vary noticeably because evaluation is based on a very limited number of scenes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Single indoor environment:&lt;/strong&gt; All scenes were captured using a similar laboratory setup. Models fine-tuned on I-Haze may overfit to the specific scene characteristics and lighting conditions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Haze machine uniformity bias:&lt;/strong&gt; Indoor air movement is limited, producing haze that is more spatially uniform than naturally occurring indoor smoke or aerosol events.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No depth information:&lt;/strong&gt; The dataset does not include depth maps, transmission maps, atmospheric-light estimates, or haze-density annotations.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Limited scene diversity:&lt;/strong&gt; Most scenes contain furniture, household objects, office materials, and indoor decorations, reducing environmental variability.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3.12 Research Angles for Final Year / PhD Students
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Mixed indoor/outdoor dehazing:&lt;/strong&gt; Train jointly on RESIDE-ITS, I-Haze, and O-Haze to determine whether combining indoor and outdoor real-haze data improves generalization.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Haze density estimation from image cues:&lt;/strong&gt; Design a lightweight sub-network that estimates haze density before dehazing and adaptively controls restoration strength.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Colour correction post-dehazing:&lt;/strong&gt; Investigate colour-cast removal techniques for indoor haze and evaluate perceptual improvements beyond PSNR and SSIM.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Benchmark instability study:&lt;/strong&gt; Evaluate multiple models on I-Haze's small validation set and quantify confidence intervals for PSNR and SSIM measurements.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Domain adaptation from synthetic to real haze:&lt;/strong&gt; Compare adversarial, contrastive, and self-supervised adaptation techniques using I-Haze as the target domain.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Indoor scene understanding after dehazing:&lt;/strong&gt; Measure how object detection, segmentation, and depth-estimation performance changes before and after dehazing.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3.13 Quick Reference Card
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;I-Haze&lt;/strong&gt; | 35 real indoor pairs | Real optical haze (haze machine) | Non-commercial research licence | Released: 2018 (CVPR Workshop) | Use case: Indoor real-haze evaluation | Primary metrics: PSNR, SSIM | Resolution: 2833×4256 (~12 MP) | Download: &lt;a href="https://data.vision.ee.ethz.ch/cvl/ntire18/i-haze/" rel="noopener noreferrer"&gt;https://data.vision.ee.ethz.ch/cvl/ntire18/i-haze/&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Dataset 4 — NH-Haze
&lt;/h2&gt;

&lt;h3&gt;
  
  
  4.1 Overview
&lt;/h3&gt;

&lt;p&gt;NH-Haze (&lt;strong&gt;Non-Homogeneous Haze dataset&lt;/strong&gt;) is the first dehazing benchmark specifically designed to model &lt;strong&gt;spatially varying real-world haze&lt;/strong&gt;. Released by Ancuti et al. at the CVPR Workshop 2020, NH-Haze addresses a major limitation of earlier datasets such as O-Haze and I-Haze, which primarily contain relatively uniform haze distributions.&lt;/p&gt;

&lt;p&gt;The dataset introduces realistic haze-density variations across different regions of the image, creating a significantly more challenging benchmark for image dehazing algorithms. NH-Haze better reflects real atmospheric conditions where haze density changes due to terrain, wind, obstacles, vegetation, and localized aerosol concentrations.&lt;/p&gt;

&lt;h3&gt;
  
  
  4.2 Origin and History
&lt;/h3&gt;

&lt;p&gt;NH-Haze was developed by the Multimedia Lab at Hasselt University, Belgium, building directly on the experience gained from O-Haze and I-Haze.&lt;/p&gt;

&lt;p&gt;The key innovation in NH-Haze is the generation of &lt;strong&gt;non-uniform haze distributions&lt;/strong&gt;. Instead of producing a nearly homogeneous haze layer, the haze generation process deliberately varied haze concentration across different parts of the scene to mimic real atmospheric conditions.&lt;/p&gt;

&lt;p&gt;The first version, NH-Haze (2020), was released as part of the NTIRE 2020 Dehazing Challenge. An expanded version, NH-Haze 2, was later introduced for the NTIRE 2021 challenge, providing additional scenes and increasing dataset diversity.&lt;/p&gt;

&lt;p&gt;Today, both versions are widely used for evaluating the robustness of modern dehazing networks under realistic non-uniform haze conditions.&lt;/p&gt;

&lt;h3&gt;
  
  
  4.3 Haze Characteristics
&lt;/h3&gt;

&lt;p&gt;NH-Haze contains &lt;strong&gt;real, non-homogeneous optical haze&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Non-uniform density:&lt;/strong&gt; Haze concentration varies significantly across the image. Some regions may exhibit dense haze while other regions remain comparatively clear.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No global atmospheric-light assumption:&lt;/strong&gt; Spatial haze variation violates the assumptions made by many classical dehazing methods that rely on a single atmospheric-light estimate.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scene-depth correlation preserved:&lt;/strong&gt; Although haze density varies, distant objects generally remain more obscured than nearby objects.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Natural appearance:&lt;/strong&gt; The resulting haze resembles realistic morning mist, industrial haze, and environmental aerosol distributions more closely than previous benchmarks.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Increased restoration difficulty:&lt;/strong&gt; Models must adapt to local haze conditions instead of applying uniform enhancement across the entire image.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  4.4 Image Statistics
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Attribute&lt;/th&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;NH-Haze v1 pairs&lt;/td&gt;
&lt;td&gt;55 (hazy + clean)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Training pairs (v1)&lt;/td&gt;
&lt;td&gt;45&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Validation pairs (v1)&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Test pairs (v1, withheld)&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;NH-Haze v2 additional pairs&lt;/td&gt;
&lt;td&gt;25&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Resolution&lt;/td&gt;
&lt;td&gt;~5000×3000 pixels (original)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Standard evaluation resolution&lt;/td&gt;
&lt;td&gt;1600×1200 or 512×512&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Haze type&lt;/td&gt;
&lt;td&gt;Real, non-homogeneous outdoor haze&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Scene content&lt;/td&gt;
&lt;td&gt;Diverse outdoor environments including forests, streets, buildings, vegetation, and open fields&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Colour space&lt;/td&gt;
&lt;td&gt;RGB&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  4.5 Download and Access
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;NH-Haze v1 (NTIRE 2020):&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
&lt;a href="https://data.vision.ee.ethz.ch/cvl/ntire20/nh-haze/" rel="noopener noreferrer"&gt;https://data.vision.ee.ethz.ch/cvl/ntire20/nh-haze/&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;NH-Haze v2 (NTIRE 2021):&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
&lt;a href="https://data.vision.ee.ethz.ch/cvl/ntire21/nh-haze2/" rel="noopener noreferrer"&gt;https://data.vision.ee.ethz.ch/cvl/ntire21/nh-haze2/&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Papers with Code listing:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
&lt;a href="https://paperswithcode.com/dataset/nh-haze" rel="noopener noreferrer"&gt;https://paperswithcode.com/dataset/nh-haze&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;GitHub repositories:&lt;/strong&gt; Several repositories, including NHDehazing and NTIRE challenge implementations, provide download scripts, preprocessing tools, and benchmark code.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  4.6 Dataset Metadata
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Field&lt;/th&gt;
&lt;th&gt;Detail&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Official Download&lt;/td&gt;
&lt;td&gt;&lt;a href="https://data.vision.ee.ethz.ch/cvl/ntire20/nh-haze/" rel="noopener noreferrer"&gt;https://data.vision.ee.ethz.ch/cvl/ntire20/nh-haze/&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Published&lt;/td&gt;
&lt;td&gt;June 2020 (CVPR Workshop)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;License&lt;/td&gt;
&lt;td&gt;Non-commercial research use&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Authors&lt;/td&gt;
&lt;td&gt;Codruta O. Ancuti, Cosmin Ancuti, Radu Timofte&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;File Size&lt;/td&gt;
&lt;td&gt;~3.8 GB (v1)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Citation&lt;/td&gt;
&lt;td&gt;Ancuti et al., "NH-HAZE: An Image Dehazing Benchmark with Non-Homogeneous Hazy and Haze-Free Images," CVPRW 2020&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  4.7 Licence
&lt;/h3&gt;

&lt;p&gt;NH-Haze is available for &lt;strong&gt;non-commercial research and educational use&lt;/strong&gt;. Citation of the CVPR Workshop 2020 paper is required when publishing results. The dataset is hosted by ETH Zurich as part of the NTIRE benchmark collection.&lt;/p&gt;

&lt;h3&gt;
  
  
  4.8 How Researchers Use NH-Haze
&lt;/h3&gt;

&lt;p&gt;NH-Haze serves two major purposes in image dehazing research.&lt;/p&gt;

&lt;h4&gt;
  
  
  As a Hard Real-Haze Test Set
&lt;/h4&gt;

&lt;p&gt;A model trained on synthetic datasets such as RESIDE and evaluated only on O-Haze or I-Haze may still perform reasonably well because those datasets contain relatively uniform haze distributions. NH-Haze acts as a significantly more challenging benchmark by introducing strong spatial variation in haze density across the image.&lt;/p&gt;

&lt;p&gt;Researchers use NH-Haze to evaluate:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Robustness to spatially varying haze.&lt;/li&gt;
&lt;li&gt;Generalization beyond homogeneous haze assumptions.&lt;/li&gt;
&lt;li&gt;Local contrast restoration capability.&lt;/li&gt;
&lt;li&gt;Adaptive atmospheric-light estimation methods.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  As a Training Set for Non-Homogeneous Dehazing
&lt;/h4&gt;

&lt;p&gt;With 45 training pairs in Version 1 and additional scenes introduced in Version 2, NH-Haze can also be used for fine-tuning and limited supervised training.&lt;/p&gt;

&lt;p&gt;Common training strategies include:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Pre-train on RESIDE-OTS or RESIDE-ITS.&lt;/li&gt;
&lt;li&gt;Fine-tune using NH-Haze training pairs.&lt;/li&gt;
&lt;li&gt;Evaluate on NH-Haze validation or NTIRE challenge test sets.&lt;/li&gt;
&lt;li&gt;Compare performance against O-Haze and I-Haze to measure real-world robustness.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Many recent transformer-based and diffusion-based dehazing models include NH-Haze as part of multi-dataset training protocols to improve real-haze generalization.&lt;/p&gt;

&lt;h3&gt;
  
  
  4.8 Code to Load NH-Haze
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;numpy&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;PIL&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Image&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;glob&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;glob&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;load_nhhaze_pairs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;nhhaze_root&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;version&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;target_size&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
    Load NH-Haze hazy-clean pairs.

    Expected structure:
      nhhaze_root/
        hazy/   &amp;lt;- non-homogeneous hazy images
        GT/     &amp;lt;- clean ground truth
    &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="n"&gt;hazy_files&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;sorted&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;glob&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;nhhaze_root&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;hazy&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;*.png&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;hazy_files&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;hazy_files&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;sorted&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;glob&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;nhhaze_root&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;hazy&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;*.jpg&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;

    &lt;span class="n"&gt;gt_files&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;sorted&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;glob&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;nhhaze_root&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;GT&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;*.png&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;gt_files&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;gt_files&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;sorted&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;glob&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;nhhaze_root&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;GT&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;*.jpg&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;

    &lt;span class="n"&gt;pairs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;hf&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;gf&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;zip&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;hazy_files&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;gt_files&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;hazy_img&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Image&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;hf&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;convert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;RGB&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;clean_img&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Image&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gf&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;convert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;RGB&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;target_size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;hazy_img&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;hazy_img&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;resize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;target_size&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Image&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;LANCZOS&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;clean_img&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;clean_img&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;resize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;target_size&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Image&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;LANCZOS&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="n"&gt;pairs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;
            &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;hazy_img&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;astype&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;float32&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mf"&gt;255.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;clean_img&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;astype&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;float32&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mf"&gt;255.0&lt;/span&gt;
        &lt;span class="p"&gt;))&lt;/span&gt;

    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Loaded &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pairs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; NH-Haze v&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;version&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; pairs&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;pairs&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;visualise_transmission_map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;hazy&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;clean&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;save_path&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
    Estimate and visualise approximate transmission map for NH-Haze analysis.
    Uses simplified DCP-based estimation for visualisation only.
    &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;matplotlib.pyplot&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;plt&lt;/span&gt;

    &lt;span class="n"&gt;A&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;percentile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;hazy&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;99.9&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;axis&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="n"&gt;t_approx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;1.0&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;min&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;hazy&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;clip&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;min&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;1e-6&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;axis&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;t_approx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;t_approx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;clip&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;fig&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;axes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;plt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;subplots&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;figsize&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="n"&gt;axes&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;imshow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;hazy&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="n"&gt;axes&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;set_title&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Hazy input&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;axes&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;imshow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;clean&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="n"&gt;axes&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;set_title&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Clean GT&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;axes&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;imshow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t_approx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cmap&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;jet&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="n"&gt;axes&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;set_title&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Approx. haze density&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;ax&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;axes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ax&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;axis&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;off&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;save_path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;plt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;savefig&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;save_path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dpi&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;150&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;bbox_inches&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;tight&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;plt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;show&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  4.10 State-of-the-Art Numbers on NH-Haze
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Model&lt;/th&gt;
&lt;th&gt;Year&lt;/th&gt;
&lt;th&gt;PSNR (dB)&lt;/th&gt;
&lt;th&gt;SSIM&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;DCP&lt;/td&gt;
&lt;td&gt;2011&lt;/td&gt;
&lt;td&gt;10.57&lt;/td&gt;
&lt;td&gt;0.521&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AOD-Net&lt;/td&gt;
&lt;td&gt;2017&lt;/td&gt;
&lt;td&gt;15.40&lt;/td&gt;
&lt;td&gt;0.651&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GDN&lt;/td&gt;
&lt;td&gt;2019&lt;/td&gt;
&lt;td&gt;13.80&lt;/td&gt;
&lt;td&gt;0.520&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;FFA-Net&lt;/td&gt;
&lt;td&gt;2020&lt;/td&gt;
&lt;td&gt;19.87&lt;/td&gt;
&lt;td&gt;0.692&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AECR-Net&lt;/td&gt;
&lt;td&gt;2021&lt;/td&gt;
&lt;td&gt;19.88&lt;/td&gt;
&lt;td&gt;0.720&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DehazeFormer-B&lt;/td&gt;
&lt;td&gt;2023&lt;/td&gt;
&lt;td&gt;20.66&lt;/td&gt;
&lt;td&gt;0.748&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;MB-TaylorFormer&lt;/td&gt;
&lt;td&gt;2023&lt;/td&gt;
&lt;td&gt;21.08&lt;/td&gt;
&lt;td&gt;0.762&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; NH-Haze is significantly more challenging than O-Haze and I-Haze because haze density varies spatially across each image. Consequently, PSNR and SSIM values are noticeably lower even for state-of-the-art methods.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  4.11 Known Limitations
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Only 55 image pairs (v1):&lt;/strong&gt; NH-Haze remains a relatively small dataset, resulting in higher statistical variance compared to large-scale synthetic benchmarks.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Controlled non-homogeneity:&lt;/strong&gt; Although haze density varies spatially, the haze is still generated using a professional haze machine. Real atmospheric haze may exhibit more complex dynamics and environmental interactions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No depth maps or auxiliary metadata:&lt;/strong&gt; The dataset does not provide transmission maps, depth maps, atmospheric-light estimates, or haze-density annotations.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Evaluation split inconsistency:&lt;/strong&gt; Some publications evaluate using the 45-image training split while others report results on the 5-image validation split. Researchers should verify the exact evaluation protocol before comparing results across papers.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Limited environmental diversity:&lt;/strong&gt; Although more diverse than O-Haze and I-Haze, the dataset still contains a restricted number of outdoor environments compared to real-world deployment scenarios.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  4.12 Research Angles for Final Year / PhD Students
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Non-homogeneous haze modeling:&lt;/strong&gt; Extend the Atmospheric Scattering Model (ASM) by estimating a spatially varying atmospheric-light map A(x) rather than assuming a single global value.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Haze-region segmentation:&lt;/strong&gt; Develop an attention module that explicitly identifies dense-haze and light-haze regions and applies adaptive restoration strategies.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Joint training with RESIDE:&lt;/strong&gt; Investigate whether combining NH-Haze with RESIDE-OTS improves synthetic-to-real transfer performance and robustness.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Transformer attention analysis:&lt;/strong&gt; Visualize attention maps in transformer-based dehazing networks to understand how different heads respond to varying haze densities.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Local atmospheric-light estimation:&lt;/strong&gt; Compare global and patch-wise atmospheric-light estimation methods on NH-Haze.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Multi-scale non-homogeneous restoration:&lt;/strong&gt; Study whether feature pyramids or hierarchical transformers better handle localized haze distributions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cross-dataset robustness evaluation:&lt;/strong&gt; Train on O-Haze, I-Haze, and RESIDE, then test on NH-Haze to quantify robustness against spatial haze variation.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  4.13 Quick Reference Card
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;NH-Haze&lt;/strong&gt; | 55 real outdoor pairs (v1) | Real non-homogeneous optical haze | Non-commercial research licence | Released: 2020 (CVPR Workshop) | Use case: Hard real-haze benchmark | Primary metrics: PSNR, SSIM | Resolution: ~5000×3000 | Download: &lt;a href="https://data.vision.ee.ethz.ch/cvl/ntire20/nh-haze/" rel="noopener noreferrer"&gt;https://data.vision.ee.ethz.ch/cvl/ntire20/nh-haze/&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Dataset 5 — Dense-Haze
&lt;/h2&gt;

&lt;h3&gt;
  
  
  5.1 Overview
&lt;/h3&gt;

&lt;p&gt;Dense-Haze is a real-image dehazing dataset specifically designed to represent &lt;strong&gt;extremely dense atmospheric haze conditions&lt;/strong&gt;. Released by Ancuti et al. at ICIP 2019, Dense-Haze was created to evaluate dehazing algorithms under scenarios where visibility is severely degraded and many conventional restoration methods fail.&lt;/p&gt;

&lt;p&gt;The dataset served as the official benchmark for the NTIRE 2019 Image Dehazing Challenge and is widely regarded as one of the most difficult real-haze datasets available. Dense-Haze represents the upper extreme of haze severity in commonly used dehazing benchmarks.&lt;/p&gt;

&lt;h3&gt;
  
  
  5.2 Origin and History
&lt;/h3&gt;

&lt;p&gt;Dense-Haze was developed by the Multimedia Lab at Hasselt University, Belgium, following the success of O-Haze and I-Haze. Researchers observed that previous datasets primarily contained moderate haze levels and did not adequately evaluate algorithm performance under severe visibility degradation.&lt;/p&gt;

&lt;p&gt;To address this limitation, the haze generation process was modified to produce substantially denser haze concentrations while maintaining paired haze-free reference images. The resulting benchmark provides realistic examples of scenes affected by heavy fog, industrial haze, dense smoke-like conditions, and severe atmospheric scattering.&lt;/p&gt;

&lt;p&gt;Dense-Haze became the primary evaluation dataset for the NTIRE 2019 Challenge on Image Dehazing and remains a standard benchmark for assessing algorithm robustness under challenging real-world haze conditions.&lt;/p&gt;

&lt;h3&gt;
  
  
  5.3 Haze Characteristics
&lt;/h3&gt;

&lt;p&gt;Dense-Haze contains &lt;strong&gt;real, extremely dense optical haze&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Very low transmission values:&lt;/strong&gt; Large portions of the image exhibit extremely low visibility, causing significant information loss.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Severe colour degradation:&lt;/strong&gt; Dense haze introduces strong colour distortion and contrast reduction, particularly in distant and mid-range regions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Difficult scene reconstruction:&lt;/strong&gt; Recovering fine textures and realistic colours is substantially more challenging than in O-Haze, I-Haze, or NH-Haze.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Heavy atmospheric scattering:&lt;/strong&gt; Multiple scattering effects become more pronounced, violating assumptions used by many classical dehazing methods.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Spatial variation remains:&lt;/strong&gt; Although haze is generally dense across the image, some local variations remain due to scene geometry and environmental conditions.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  5.4 Image Statistics
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Attribute&lt;/th&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Total image pairs&lt;/td&gt;
&lt;td&gt;55 (hazy + clean)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Training pairs&lt;/td&gt;
&lt;td&gt;45&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Validation pairs&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Test pairs (withheld)&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Resolution&lt;/td&gt;
&lt;td&gt;~1600×1200 pixels&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Haze type&lt;/td&gt;
&lt;td&gt;Real, extremely dense outdoor haze&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Scene content&lt;/td&gt;
&lt;td&gt;Outdoor scenes including vegetation, buildings, roads, and structures&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Colour space&lt;/td&gt;
&lt;td&gt;RGB&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  5.5 Download and Access
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Official Dense-Haze page (NTIRE 2019):&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
&lt;a href="https://data.vision.ee.ethz.ch/cvl/ntire19/dense-haze/" rel="noopener noreferrer"&gt;https://data.vision.ee.ethz.ch/cvl/ntire19/dense-haze/&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Direct download:&lt;/strong&gt; Available from the official page after accepting the dataset terms of use.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Papers with Code listing:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
&lt;a href="https://paperswithcode.com/dataset/dense-haze" rel="noopener noreferrer"&gt;https://paperswithcode.com/dataset/dense-haze&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;GitHub repositories:&lt;/strong&gt; Several open-source dehazing repositories provide preprocessing scripts, evaluation code, and dataset-loading utilities for Dense-Haze.&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Example download workflow&lt;/span&gt;
&lt;span class="c"&gt;# Download link becomes available after accepting the dataset licence&lt;/span&gt;

wget &lt;span class="nt"&gt;-O&lt;/span&gt; dense_haze.zip &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="s2"&gt;"https://data.vision.ee.ethz.ch/cvl/ntire19/dense-haze/"&lt;/span&gt;

unzip dense_haze.zip &lt;span class="nt"&gt;-d&lt;/span&gt; ./Dense-Haze/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  5.6 Dataset Metadata
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Field&lt;/th&gt;
&lt;th&gt;Detail&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Official Download&lt;/td&gt;
&lt;td&gt;&lt;a href="https://data.vision.ee.ethz.ch/cvl/ntire19/dense-haze/" rel="noopener noreferrer"&gt;https://data.vision.ee.ethz.ch/cvl/ntire19/dense-haze/&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Published&lt;/td&gt;
&lt;td&gt;September 2019 (ICIP 2019)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;License&lt;/td&gt;
&lt;td&gt;Non-commercial research use&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Authors&lt;/td&gt;
&lt;td&gt;Codruta O. Ancuti, Cosmin Ancuti, Radu Timofte, Luc Van Gool&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;File Size&lt;/td&gt;
&lt;td&gt;~600 MB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Citation&lt;/td&gt;
&lt;td&gt;Ancuti et al., "Dense-Haze: A Benchmark for Image Dehazing with Dense-Haze and Haze-Free Images," ICIP 2019&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  5.7 Licence
&lt;/h3&gt;

&lt;p&gt;Dense-Haze is available for &lt;strong&gt;non-commercial research and educational use&lt;/strong&gt;. Citation of the ICIP 2019 paper is required when publishing experimental results. The dataset is hosted by ETH Zurich's Computer Vision Laboratory alongside O-Haze, I-Haze, and NH-Haze.&lt;/p&gt;

&lt;h3&gt;
  
  
  5.8 How Researchers Use Dense-Haze
&lt;/h3&gt;

&lt;p&gt;Dense-Haze is primarily used as an &lt;strong&gt;extreme-conditions real-haze benchmark&lt;/strong&gt; because it represents the most challenging haze density among standard paired real-haze datasets.&lt;/p&gt;

&lt;p&gt;Researchers commonly use Dense-Haze to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Evaluate robustness under severe visibility degradation.&lt;/li&gt;
&lt;li&gt;Measure performance when scene information is heavily obscured.&lt;/li&gt;
&lt;li&gt;Compare classical prior-based methods against modern CNN and transformer architectures.&lt;/li&gt;
&lt;li&gt;Analyze failure cases involving colour restoration, texture recovery, and structural reconstruction.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Typical observations include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Models achieving &lt;strong&gt;≥20 dB PSNR&lt;/strong&gt; on Dense-Haze are generally considered strong performers.&lt;/li&gt;
&lt;li&gt;Methods that perform well on O-Haze and I-Haze often experience noticeable degradation on Dense-Haze.&lt;/li&gt;
&lt;li&gt;Classical methods such as DCP frequently struggle because dense haze violates many of their underlying assumptions.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A common evaluation protocol is:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Train on RESIDE-OTS or RESIDE-ITS.&lt;/li&gt;
&lt;li&gt;Fine-tune using O-Haze, I-Haze, NH-Haze, and Dense-Haze training pairs.&lt;/li&gt;
&lt;li&gt;Evaluate separately on each benchmark.&lt;/li&gt;
&lt;li&gt;Report cross-dataset robustness and generalization metrics.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  5.9 Code to Load Dense-Haze
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;numpy&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;PIL&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Image&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;glob&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;glob&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;skimage.metrics&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;peak_signal_noise_ratio&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;psnr&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;skimage.metrics&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;structural_similarity&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;ssim&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;load_densehaze_pairs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;densehaze_root&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;target_size&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;512&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;512&lt;/span&gt;&lt;span class="p"&gt;)):&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
    Load Dense-Haze hazy-clean pairs.

    Expected structure:
      densehaze_root/
        hazy/   &amp;lt;- densely hazy images
        GT/     &amp;lt;- clean ground truth
    &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="n"&gt;hazy_files&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;sorted&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;glob&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;densehaze_root&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;hazy&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;*.png&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;hazy_files&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;hazy_files&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;sorted&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;glob&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;densehaze_root&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;hazy&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;*.jpg&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
    &lt;span class="n"&gt;gt_files&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;sorted&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;glob&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;densehaze_root&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;GT&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;*.png&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;gt_files&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;gt_files&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;sorted&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;glob&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;densehaze_root&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;GT&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;*.jpg&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;

    &lt;span class="n"&gt;pairs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;hf&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;gf&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;zip&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;hazy_files&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;gt_files&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;hazy&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Image&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;hf&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;convert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;RGB&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;clean&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Image&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gf&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;convert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;RGB&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;target_size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;hazy&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;hazy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;resize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;target_size&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Image&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;LANCZOS&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;clean&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;clean&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;resize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;target_size&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Image&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;LANCZOS&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;pairs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;
            &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;hazy&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;astype&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;float32&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mf"&gt;255.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;clean&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;astype&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;float32&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mf"&gt;255.0&lt;/span&gt;
        &lt;span class="p"&gt;))&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;pairs&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;evaluate_densehaze_with_input_baseline&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;model_fn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pairs&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
    Evaluate dehazing model AND compute hazy-input PSNR for Dense-Haze.
    On very dense haze, some models perform WORSE than just passing
    the hazy image through — this comparison is informative.
    &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="n"&gt;model_psnr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;input_psnr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ssim_list&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;hazy&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;clean&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;pairs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;dehazed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;model_fn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;hazy&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;model_psnr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;psnr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;clean&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dehazed&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;data_range&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="n"&gt;input_psnr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;psnr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;clean&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;hazy&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;data_range&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="n"&gt;ssim_list&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;ssim&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;clean&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dehazed&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;data_range&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                               &lt;span class="n"&gt;multichannel&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;channel_axis&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Dense-Haze | Model PSNR: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;mean&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;model_psnr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; dB | &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
          &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Input PSNR: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;mean&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input_psnr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; dB | &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
          &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Gain: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;mean&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;model_psnr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;mean&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input_psnr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; dB | &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
          &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;SSIM: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;mean&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ssim_list&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;model_psnr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;input_psnr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ssim_list&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  5.10 State-of-the-Art Numbers on Dense-Haze
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Model&lt;/th&gt;
&lt;th&gt;Year&lt;/th&gt;
&lt;th&gt;PSNR (dB)&lt;/th&gt;
&lt;th&gt;SSIM&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;DCP&lt;/td&gt;
&lt;td&gt;2011&lt;/td&gt;
&lt;td&gt;10.06&lt;/td&gt;
&lt;td&gt;0.382&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AOD-Net&lt;/td&gt;
&lt;td&gt;2017&lt;/td&gt;
&lt;td&gt;13.14&lt;/td&gt;
&lt;td&gt;0.414&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DCPDN&lt;/td&gt;
&lt;td&gt;2018&lt;/td&gt;
&lt;td&gt;13.66&lt;/td&gt;
&lt;td&gt;0.432&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;EPDN&lt;/td&gt;
&lt;td&gt;2019&lt;/td&gt;
&lt;td&gt;16.15&lt;/td&gt;
&lt;td&gt;0.519&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;FFA-Net&lt;/td&gt;
&lt;td&gt;2020&lt;/td&gt;
&lt;td&gt;14.39&lt;/td&gt;
&lt;td&gt;0.452&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;MSBDN&lt;/td&gt;
&lt;td&gt;2020&lt;/td&gt;
&lt;td&gt;15.37&lt;/td&gt;
&lt;td&gt;0.491&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AECR-Net&lt;/td&gt;
&lt;td&gt;2021&lt;/td&gt;
&lt;td&gt;15.80&lt;/td&gt;
&lt;td&gt;0.466&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DehazeFormer-B&lt;/td&gt;
&lt;td&gt;2023&lt;/td&gt;
&lt;td&gt;16.62&lt;/td&gt;
&lt;td&gt;0.560&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Dense-Haze is one of the most challenging real-haze benchmarks available. Rankings often differ substantially from RESIDE, O-Haze, and I-Haze because severe haze causes significant information loss. Always report results across multiple datasets rather than relying on a single benchmark.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  5.11 Known Limitations
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Ground-truth recoverability ceiling:&lt;/strong&gt; Under extremely dense haze, portions of scene information may be physically lost due to severe attenuation and scattering. No algorithm can perfectly recover details that were never captured by the camera.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Only 55 image pairs:&lt;/strong&gt; Like other Hasselt University real-haze datasets, Dense-Haze remains relatively small and therefore exhibits higher statistical variance than large synthetic datasets.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Limited density diversity:&lt;/strong&gt; Although haze is extremely dense, most images contain similar haze severity levels. The dataset does not provide the broad density variation seen in NH-Haze.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No auxiliary annotations:&lt;/strong&gt; Depth maps, transmission maps, atmospheric-light estimates, and haze-density labels are not provided.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Evaluation instability:&lt;/strong&gt; Because benchmark results are often computed on only a few validation images, small PSNR differences may not be statistically significant.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  5.12 Research Angles for Final Year / PhD Students
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Information-theoretic limits of dehazing:&lt;/strong&gt; Estimate the maximum recoverable information under severe haze conditions and compare theoretical limits against current state-of-the-art performance.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Diffusion models for dense dehazing:&lt;/strong&gt; Investigate whether diffusion-based restoration methods outperform CNN and transformer architectures under extreme visibility degradation.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Multi-image dense-haze restoration:&lt;/strong&gt; Explore temporal aggregation, burst photography, or multi-view dehazing approaches to recover information unavailable in a single image.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dense-haze pre-processing for downstream tasks:&lt;/strong&gt; Evaluate whether dehazing improves object detection, semantic segmentation, or scene understanding performance under severe haze.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Perceptual quality versus PSNR:&lt;/strong&gt; Analyze whether models with similar PSNR values produce noticeably different perceptual quality, colour fidelity, and texture restoration.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Adaptive atmospheric-light estimation:&lt;/strong&gt; Develop local atmospheric-light estimation techniques that remain stable under very dense scattering conditions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cross-benchmark robustness study:&lt;/strong&gt; Train on RESIDE, O-Haze, I-Haze, and NH-Haze, then evaluate on Dense-Haze to identify which training strategies best generalize to extreme haze.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  5.13 Quick Reference Card
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Dense-Haze&lt;/strong&gt; | 55 real outdoor pairs | Real extremely dense optical haze | Non-commercial research licence | Released: 2019 (ICIP) | Use case: Extreme-haze benchmark | Primary metrics: PSNR, SSIM | Resolution: ~1600×1200 | Download: &lt;a href="https://data.vision.ee.ethz.ch/cvl/ntire19/dense-haze/" rel="noopener noreferrer"&gt;https://data.vision.ee.ethz.ch/cvl/ntire19/dense-haze/&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Image Dehazing Metrics Explained
&lt;/h2&gt;

&lt;h3&gt;
  
  
  PSNR — Peak Signal-to-Noise Ratio
&lt;/h3&gt;

&lt;p&gt;PSNR measures the ratio of maximum signal power to distortion power in decibels. In dehazing, it compares the dehazed image against the clean ground truth:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;PSNR = 10 × log₁₀(MAX² / MSE)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Higher PSNR = better dehazing. Typical ranges: 30-40+ dB on RESIDE-SOTS (synthetic), 20-25 dB on O-Haze/I-Haze (real mild), 19-21 dB on NH-Haze (real non-homogeneous), 14-17 dB on Dense-Haze (extreme). &lt;strong&gt;Never compare absolute PSNR across datasets&lt;/strong&gt; — the haze difficulty fundamentally changes the achievable score.&lt;/p&gt;

&lt;h3&gt;
  
  
  SSIM — Structural Similarity Index
&lt;/h3&gt;

&lt;p&gt;SSIM evaluates luminance, contrast, and structural similarity simultaneously, producing a score between 0 and 1 (higher = better). In dehazing, SSIM is particularly informative because it detects halo artefacts and contrast errors that PSNR tolerates. A model with high PSNR but low SSIM is typically over-brightening the image globally without restoring structural detail.&lt;/p&gt;

&lt;h3&gt;
  
  
  LPIPS — Learned Perceptual Image Patch Similarity
&lt;/h3&gt;

&lt;p&gt;LPIPS uses deep network feature distances to measure perceptual similarity (lower = better). Increasingly reported in dehazing papers to detect the over-saturation and plastic-looking texture artefacts common in GAN-based methods. A dehazing model that scores 1 dB lower PSNR but has significantly better LPIPS is usually producing more visually pleasing results.&lt;/p&gt;

&lt;h3&gt;
  
  
  CIEDE2000 — Colour Difference Metric
&lt;/h3&gt;

&lt;p&gt;CIEDE2000 measures perceptual colour difference between the dehazed and ground truth images, accounting for human colour perception nonlinearities. Particularly relevant for dehazing because haze introduces a strong colour cast (whitish or yellowish) that PSNR and SSIM may not penalise correctly. Lower CIEDE2000 = better colour fidelity.&lt;/p&gt;

&lt;h3&gt;
  
  
  FADE — Fog Aware Density Evaluator
&lt;/h3&gt;

&lt;p&gt;FADE is a &lt;strong&gt;no-reference&lt;/strong&gt; metric designed specifically for fog and haze assessment. It estimates haze density from the image without a clean reference, producing a score where lower = clearer image. FADE is useful for evaluating on unpaired real hazy images like RTTS, where no ground truth exists. Its limitations include poor calibration for non-natural images and sensitivity to over-brightening (which artificially reduces estimated haze density).&lt;/p&gt;

&lt;h3&gt;
  
  
  NIQE — Naturalness Image Quality Evaluator
&lt;/h3&gt;

&lt;p&gt;NIQE measures deviation from natural image statistics without requiring a reference. In dehazing, NIQE helps detect when a model produces an unnaturally sharp or unnaturally smooth result — both common failure modes. Lower NIQE = more natural appearance.&lt;/p&gt;

&lt;h3&gt;
  
  
  Which Metric for Which Task?
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Scenario&lt;/th&gt;
&lt;th&gt;Recommended Metrics&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Synthetic haze (RESIDE SOTS)&lt;/td&gt;
&lt;td&gt;PSNR + SSIM&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Real mild haze (O-Haze, I-Haze)&lt;/td&gt;
&lt;td&gt;PSNR + SSIM + LPIPS&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Non-homogeneous haze (NH-Haze)&lt;/td&gt;
&lt;td&gt;PSNR + SSIM + CIEDE2000&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Dense haze (Dense-Haze)&lt;/td&gt;
&lt;td&gt;PSNR + SSIM + visual comparison&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Unpaired real haze (RTTS)&lt;/td&gt;
&lt;td&gt;FADE + NIQE (no-reference)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Full research paper&lt;/td&gt;
&lt;td&gt;PSNR + SSIM + LPIPS + FADE&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Comparison Table — All 5 Datasets Across 12+ Attributes
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Attribute&lt;/th&gt;
&lt;th&gt;RESIDE&lt;/th&gt;
&lt;th&gt;O-Haze&lt;/th&gt;
&lt;th&gt;I-Haze&lt;/th&gt;
&lt;th&gt;NH-Haze&lt;/th&gt;
&lt;th&gt;Dense-Haze&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Year&lt;/td&gt;
&lt;td&gt;2018/2019&lt;/td&gt;
&lt;td&gt;2018&lt;/td&gt;
&lt;td&gt;2018&lt;/td&gt;
&lt;td&gt;2020&lt;/td&gt;
&lt;td&gt;2019&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;# Pairs&lt;/td&gt;
&lt;td&gt;313K+ (OTS) / 14K (ITS)&lt;/td&gt;
&lt;td&gt;45&lt;/td&gt;
&lt;td&gt;35&lt;/td&gt;
&lt;td&gt;55&lt;/td&gt;
&lt;td&gt;55&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Haze Type&lt;/td&gt;
&lt;td&gt;Synthetic&lt;/td&gt;
&lt;td&gt;Real (machine)&lt;/td&gt;
&lt;td&gt;Real (machine)&lt;/td&gt;
&lt;td&gt;Real, non-homogeneous&lt;/td&gt;
&lt;td&gt;Real, dense&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Setting&lt;/td&gt;
&lt;td&gt;Indoor + Outdoor&lt;/td&gt;
&lt;td&gt;Outdoor&lt;/td&gt;
&lt;td&gt;Indoor&lt;/td&gt;
&lt;td&gt;Outdoor&lt;/td&gt;
&lt;td&gt;Outdoor&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Ground Truth&lt;/td&gt;
&lt;td&gt;Synthetic (exact)&lt;/td&gt;
&lt;td&gt;Yes (captured)&lt;/td&gt;
&lt;td&gt;Yes (captured)&lt;/td&gt;
&lt;td&gt;Yes (captured)&lt;/td&gt;
&lt;td&gt;Yes (captured)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Haze Density&lt;/td&gt;
&lt;td&gt;Configurable&lt;/td&gt;
&lt;td&gt;Medium-dense&lt;/td&gt;
&lt;td&gt;Medium&lt;/td&gt;
&lt;td&gt;Non-uniform&lt;/td&gt;
&lt;td&gt;Extreme&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Resolution&lt;/td&gt;
&lt;td&gt;460×620 to 1024+&lt;/td&gt;
&lt;td&gt;4964×3312&lt;/td&gt;
&lt;td&gt;2833×4256&lt;/td&gt;
&lt;td&gt;~5000×3000&lt;/td&gt;
&lt;td&gt;~1600×1200&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Depth Maps&lt;/td&gt;
&lt;td&gt;Yes (ITS)&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Use as Train&lt;/td&gt;
&lt;td&gt;Yes (primary)&lt;/td&gt;
&lt;td&gt;No (too small)&lt;/td&gt;
&lt;td&gt;No (too small)&lt;/td&gt;
&lt;td&gt;No (borderline)&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Use as Test&lt;/td&gt;
&lt;td&gt;Yes (SOTS)&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Licence&lt;/td&gt;
&lt;td&gt;Non-commercial&lt;/td&gt;
&lt;td&gt;Non-commercial&lt;/td&gt;
&lt;td&gt;Non-commercial&lt;/td&gt;
&lt;td&gt;Non-commercial&lt;/td&gt;
&lt;td&gt;Non-commercial&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Typical PSNR&lt;/td&gt;
&lt;td&gt;35–40 dB&lt;/td&gt;
&lt;td&gt;22–24 dB&lt;/td&gt;
&lt;td&gt;23–25 dB&lt;/td&gt;
&lt;td&gt;19–21 dB&lt;/td&gt;
&lt;td&gt;14–17 dB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Challenge&lt;/td&gt;
&lt;td&gt;NTIRE 2018/2019&lt;/td&gt;
&lt;td&gt;NTIRE 2018/2019&lt;/td&gt;
&lt;td&gt;NTIRE 2018/2019&lt;/td&gt;
&lt;td&gt;NTIRE 2020/2021&lt;/td&gt;
&lt;td&gt;NTIRE 2019&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  How to Choose the Right Dataset
&lt;/h2&gt;

&lt;h3&gt;
  
  
  By Haze Type
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;You are studying haze physics and want controlled conditions:&lt;/strong&gt; Use RESIDE with synthetic ASM haze. You control A and β precisely and can isolate their effects.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;You need to demonstrate real-world applicability at moderate haze:&lt;/strong&gt; Use O-Haze (outdoor) or I-Haze (indoor) for evaluation. Train on RESIDE, evaluate on both.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;You are targeting UAV, road scene, or satellite imagery in real hazy conditions:&lt;/strong&gt; Use NH-Haze — its non-homogeneous structure best matches real atmospheric conditions over varied terrain.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;You are working on extreme conditions&lt;/strong&gt; (wildfire smoke, thick industrial fog, dense coastal mist): Use Dense-Haze as your primary benchmark.&lt;/p&gt;

&lt;h3&gt;
  
  
  By Domain
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Autonomous driving:&lt;/strong&gt; RESIDE-OTS (outdoor synthetic) + NH-Haze (non-homogeneous) + RTTS (real road scenes, unpaired). Road scenes need both far-field dehazing (for navigation) and near-field accuracy (for pedestrian detection).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Indoor CCTV/surveillance:&lt;/strong&gt; RESIDE-ITS + I-Haze. Indoor depth ranges and artificial lighting conditions are specific to this domain.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Medical imaging / endoscopy:&lt;/strong&gt; None of the five datasets are directly applicable. Turbid medium scattering in tissue is governed by different physics. Use these datasets for pre-training only.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Satellite/aerial remote sensing:&lt;/strong&gt; RESIDE-OTS provides the largest training set. NH-Haze best approximates heterogeneous cloud/haze cover patterns.&lt;/p&gt;

&lt;h3&gt;
  
  
  By Compute Budget
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;GPU-constrained (&amp;lt;8 GB VRAM):&lt;/strong&gt; Train on RESIDE-ITS only (14K pairs, easily fits). Evaluate on SOTS-Indoor + I-Haze + O-Haze.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Standard research (24 GB VRAM):&lt;/strong&gt; Train on RESIDE-ITS + OTS subset (100K pairs). Evaluate on full five-dataset suite.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Large-scale (multi-GPU):&lt;/strong&gt; Use full RESIDE-OTS (313K pairs) + data augmentation + multi-scale training. Evaluate on all five datasets plus RTTS qualitative.&lt;/p&gt;




&lt;h2&gt;
  
  
  Common Dehazing Models Benchmarked
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;DCP — Dark Channel Prior (He et al., CVPR 2009 / TPAMI 2011):&lt;/strong&gt; The foundational prior-based method. Exploits the observation that at least one colour channel has near-zero intensity in most haze-free patches. Computationally efficient and requires no training data. Still the mandatory baseline. Fails on sky regions and white objects where the dark channel prior breaks.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;DehazeNet (Cai et al., IEEE TIP 2016):&lt;/strong&gt; The first CNN-based dehazing method. Learns the transmission map from hazy image patches using a shallow convolutional network. Pioneered the end-to-end learning paradigm for dehazing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;AOD-Net (Li et al., ICCV 2017):&lt;/strong&gt; Reformulates the ASM to directly estimate a unified parameter K that captures both A and t in a single network pass. Extremely lightweight and fast — good for embedded deployment despite lower PSNR than modern methods.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GFN — Gated Fusion Network (Ren et al., CVPR 2018):&lt;/strong&gt; Multi-scale feature fusion with learned gating. Strong performance on O-Haze and I-Haze at the time of publication.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;FFA-Net (Qin et al., AAAI 2020):&lt;/strong&gt; Feature Fusion Attention Network — channel and pixel attention mechanisms allow the network to adaptively weight features by their importance for haze removal. Significant jump over prior methods on RESIDE-SOTS.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;MSBDN (Dong et al., CVPR 2020):&lt;/strong&gt; Multi-Scale Boosted Dehazing Network with dense feature fusion. Strong on RESIDE outdoor scenes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;AECR-Net (Wu et al., CVPR 2021):&lt;/strong&gt; Adaptive Enhancement and Contrastive Regularisation. Uses a contrastive loss between hazy and clean features to improve perceptual quality alongside PSNR.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;DehazeFormer (Song et al., IEEE TIP 2023):&lt;/strong&gt; Transformer-based architecture with K-space normalisation and a modified window attention mechanism. Currently achieves the best published results on RESIDE-SOTS-Indoor (40+ dB) and strong results across all real-haze benchmarks.&lt;/p&gt;




&lt;h2&gt;
  
  
  How to Prepare Hazy-Clean Pairs for Training
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Synthetic Haze Generation
&lt;/h3&gt;

&lt;p&gt;If you want to create your own training data or augment existing datasets with synthetic haze:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;numpy&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;PIL&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Image&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;cv2&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;synthesise_haze_asm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;clean_img&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;depth_map&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;beta_range&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.05&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;0.20&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; 
                         &lt;span class="n"&gt;A_range&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="p"&gt;)):&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
    Generate a hazy image using the Atmospheric Scattering Model.

    Args:
        clean_img: float32 numpy array [H, W, 3] in [0, 1]
        depth_map: float32 numpy array [H, W] — scene depth, normalised to [0, 1]
        beta_range: scattering coefficient range
        A_range: atmospheric light range (per channel)

    Returns:
        hazy: synthesised hazy image
        t_map: transmission map
        A: atmospheric light vector
    &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="n"&gt;beta&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;random&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;uniform&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;beta_range&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;A&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;random&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;uniform&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;A_range&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;A_range&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;astype&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;float32&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Normalise depth to a reasonable physical range (e.g., 0–10m)
&lt;/span&gt;    &lt;span class="n"&gt;depth&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;depth_map&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mf"&gt;10.0&lt;/span&gt;

    &lt;span class="c1"&gt;# Compute transmission map
&lt;/span&gt;    &lt;span class="n"&gt;t_map&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;beta&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;depth&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;astype&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;float32&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;t_map&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;clip&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t_map&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;0.1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# prevent t=0 (complete obstruction)
&lt;/span&gt;    &lt;span class="n"&gt;t_map&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;t_map&lt;/span&gt;&lt;span class="p"&gt;[:,&lt;/span&gt; &lt;span class="p"&gt;:,&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;newaxis&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;   &lt;span class="c1"&gt;# shape [H, W, 1]
&lt;/span&gt;
    &lt;span class="c1"&gt;# Apply ASM: I = J*t + A*(1-t)
&lt;/span&gt;    &lt;span class="n"&gt;hazy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;clean_img&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;t_map&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;A&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;1.0&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;t_map&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;hazy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;clip&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;hazy&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;astype&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;float32&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;hazy&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;t_map&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;squeeze&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;squeeze&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;generate_hazy_dataset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;clean_images&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;depth_maps&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;num_per_image&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
    Generate multiple hazy versions of each clean image using different A, β.
    Mimics RESIDE ITS generation where 10 hazy variants exist per clean image.
    &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="n"&gt;pairs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;clean&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;depth&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;zip&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;clean_images&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;depth_maps&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;num_per_image&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="n"&gt;hazy&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;t_map&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;A&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;synthesise_haze_asm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;clean&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;depth&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;pairs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
                &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;hazy&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;hazy&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
                &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;clean&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;clean&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
                &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;t_map&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;t_map&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
                &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;A&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;A&lt;/span&gt;
            &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;pairs&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Real Haze Dataset Preprocessing
&lt;/h3&gt;

&lt;p&gt;For O-Haze, I-Haze, NH-Haze, and Dense-Haze:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;preprocess_real_haze_pairs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pairs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;patch_size&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;256&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;stride&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;128&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
                                 &lt;span class="n"&gt;min_haze_score&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;0.01&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
    Extract patches from real haze pairs with quality filtering.
    Filters out near-sky patches where haze dominates without scene content.
    &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="n"&gt;filtered_patches&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;hazy&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;clean&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;pairs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="c1"&gt;# Skip patches where clean image is nearly uniform (sky, wall)
&lt;/span&gt;        &lt;span class="c1"&gt;# and hazy image adds almost no structure
&lt;/span&gt;        &lt;span class="n"&gt;H&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;W&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;hazy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;shape&lt;/span&gt;

        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;H&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;patch_size&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;stride&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;W&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;patch_size&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;stride&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
                &lt;span class="n"&gt;hazy_p&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;hazy&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;patch_size&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;patch_size&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
                &lt;span class="n"&gt;clean_p&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;clean&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;patch_size&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;patch_size&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

                &lt;span class="c1"&gt;# Quality filter: discard near-uniform patches
&lt;/span&gt;                &lt;span class="n"&gt;clean_std&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;std&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;clean_p&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;clean_std&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mf"&gt;0.03&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  &lt;span class="c1"&gt;# uniform patch (sky/wall)
&lt;/span&gt;                    &lt;span class="k"&gt;continue&lt;/span&gt;

                &lt;span class="c1"&gt;# Haze filter: discard patches where haze is minimal
&lt;/span&gt;                &lt;span class="n"&gt;haze_diff&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;mean&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;hazy_p&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;mean&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;clean_p&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;haze_diff&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;min_haze_score&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                    &lt;span class="k"&gt;continue&lt;/span&gt;

                &lt;span class="n"&gt;filtered_patches&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;hazy_p&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;clean_p&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Extracted &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;filtered_patches&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; quality patches&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;filtered_patches&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Augmentation for Dehazing
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;random&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;augment_hazy_pair&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;hazy&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;clean&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
    Apply identical augmentation to hazy-clean pair.
    Dehazing-specific: avoid colour jitter on clean (distorts ground truth).
    &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="c1"&gt;# Geometric augmentation (applied identically)
&lt;/span&gt;    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;random&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;random&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mf"&gt;0.5&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;hazy&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;hazy&lt;/span&gt;&lt;span class="p"&gt;[:,&lt;/span&gt; &lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;:].&lt;/span&gt;&lt;span class="nf"&gt;copy&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;clean&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;clean&lt;/span&gt;&lt;span class="p"&gt;[:,&lt;/span&gt; &lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;:].&lt;/span&gt;&lt;span class="nf"&gt;copy&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;random&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;random&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mf"&gt;0.5&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;hazy&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;hazy&lt;/span&gt;&lt;span class="p"&gt;[::&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;:,&lt;/span&gt; &lt;span class="p"&gt;:].&lt;/span&gt;&lt;span class="nf"&gt;copy&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;clean&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;clean&lt;/span&gt;&lt;span class="p"&gt;[::&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;:,&lt;/span&gt; &lt;span class="p"&gt;:].&lt;/span&gt;&lt;span class="nf"&gt;copy&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;k&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;random&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;randint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;hazy&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;rot90&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;hazy&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;copy&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;clean&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;rot90&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;clean&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;copy&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="c1"&gt;# Haze intensity augmentation (only applied to hazy, not clean)
&lt;/span&gt;    &lt;span class="c1"&gt;# Randomly scale the haze density to augment training distribution
&lt;/span&gt;    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;random&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;random&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mf"&gt;0.7&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;alpha&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;random&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;uniform&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;1.2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# scale haze intensity
&lt;/span&gt;        &lt;span class="c1"&gt;# Move toward or away from the clean image
&lt;/span&gt;        &lt;span class="n"&gt;hazy_aug&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;clean&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;alpha&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;hazy&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;clean&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;hazy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;clip&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;hazy_aug&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;astype&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;float32&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;hazy&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;clean&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Research Gap Radar — 5 Open Problems
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Gap 1 — Synthetic-to-Real Domain Transfer
&lt;/h3&gt;

&lt;p&gt;The community's best models achieve &lt;strong&gt;40+ dB on RESIDE-SOTS-Indoor&lt;/strong&gt; but only &lt;strong&gt;~25 dB on I-Haze&lt;/strong&gt;. This 15 dB gap represents a fundamental failure of synthetic-trained models on real data.&lt;/p&gt;

&lt;p&gt;No paper has yet demonstrated a principled solution that closes this gap without fine-tuning on real image pairs. Domain adaptation, physics-informed augmentation, and self-supervised approaches are active but unresolved research directions.&lt;/p&gt;

&lt;h3&gt;
  
  
  Gap 2 — Non-Homogeneous Haze Modelling
&lt;/h3&gt;

&lt;p&gt;The Atmospheric Scattering Model (ASM) assumes a single global atmospheric light &lt;strong&gt;A&lt;/strong&gt; — an assumption that breaks down in many real-world environments.&lt;/p&gt;

&lt;p&gt;NH-Haze highlighted this limitation by introducing spatially varying haze distributions. Current SOTA performance on NH-Haze remains substantially below performance on homogeneous-haze benchmarks.&lt;/p&gt;

&lt;p&gt;Designing architectures that explicitly model spatially varying &lt;strong&gt;A(x)&lt;/strong&gt; and &lt;strong&gt;β(x)&lt;/strong&gt; remains an open research problem.&lt;/p&gt;

&lt;h3&gt;
  
  
  Gap 3 — Video Dehazing with Temporal Consistency
&lt;/h3&gt;

&lt;p&gt;Most dehazing models operate on individual images.&lt;/p&gt;

&lt;p&gt;When applied frame-by-frame to video, temporal artifacts such as flickering, colour instability, and inconsistent restoration often appear.&lt;/p&gt;

&lt;p&gt;Adjacent video frames contain highly correlated haze information. Exploiting temporal consistency for stable video dehazing remains significantly underexplored compared to single-image dehazing.&lt;/p&gt;

&lt;p&gt;Applications include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Autonomous driving&lt;/li&gt;
&lt;li&gt;UAV surveillance&lt;/li&gt;
&lt;li&gt;Traffic monitoring&lt;/li&gt;
&lt;li&gt;Video enhancement systems&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Gap 4 — Dehazing for Downstream Tasks
&lt;/h3&gt;

&lt;p&gt;Most image dehazing research optimizes PSNR and SSIM.&lt;/p&gt;

&lt;p&gt;However, many real-world applications care more about downstream performance than reconstruction quality.&lt;/p&gt;

&lt;p&gt;Examples include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Object detection&lt;/li&gt;
&lt;li&gt;License plate recognition&lt;/li&gt;
&lt;li&gt;Semantic segmentation&lt;/li&gt;
&lt;li&gt;Pedestrian detection&lt;/li&gt;
&lt;li&gt;Autonomous navigation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The relationship between improved PSNR and improved task performance remains inconsistent. Task-aware dehazing loss functions and joint optimization frameworks remain active research areas.&lt;/p&gt;

&lt;h3&gt;
  
  
  Gap 5 — Nighttime and Coloured Haze
&lt;/h3&gt;

&lt;p&gt;Nearly all standard dehazing datasets contain daytime scenes.&lt;/p&gt;

&lt;p&gt;Nighttime haze introduces additional challenges:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Multiple light sources&lt;/li&gt;
&lt;li&gt;Spatially varying illumination&lt;/li&gt;
&lt;li&gt;Headlight scattering&lt;/li&gt;
&lt;li&gt;Streetlight glow&lt;/li&gt;
&lt;li&gt;Colour-dependent atmospheric effects&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The standard ASM does not adequately model these phenomena.&lt;/p&gt;

&lt;p&gt;Developing benchmark datasets, physical models, and deep learning architectures specifically for nighttime dehazing remains a major open problem.&lt;/p&gt;




&lt;h2&gt;
  
  
  Implementation Roadmap — 8-Step Week-by-Week Guide
&lt;/h2&gt;

&lt;p&gt;This roadmap targets a Final Year / M.Tech student with 2–3 months before submission and a single GPU (8–24 GB VRAM).&lt;/p&gt;

&lt;h3&gt;
  
  
  Week 1 — Environment and Baseline
&lt;/h3&gt;

&lt;p&gt;Install PyTorch 2.x, clone BasicIR or the FFA-Net repository, and reproduce DCP results on RESIDE-SOTS-Indoor.&lt;/p&gt;

&lt;p&gt;Target baseline:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;~16 dB (DCP)&lt;/li&gt;
&lt;li&gt;If you can get AOD-Net working: ~20 dB&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These numbers confirm your evaluation pipeline is functioning correctly.&lt;/p&gt;

&lt;h3&gt;
  
  
  Week 2 — Dataset Setup
&lt;/h3&gt;

&lt;p&gt;Download:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;RESIDE-ITS (training)&lt;/li&gt;
&lt;li&gt;SOTS (testing)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Tasks:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Implement the data loader from Section 12.&lt;/li&gt;
&lt;li&gt;Compute average hazy-image statistics (mean brightness, contrast, estimated β distribution).&lt;/li&gt;
&lt;li&gt;Visualise 10 hazy-clean image pairs.&lt;/li&gt;
&lt;li&gt;Download O-Haze and I-Haze for later evaluation.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Week 3 — Train a Baseline CNN
&lt;/h3&gt;

&lt;p&gt;Train:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;FFA-Net, or&lt;/li&gt;
&lt;li&gt;A simplified MSBDN model on RESIDE-ITS.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Target:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;~30 dB on SOTS-Indoor after approximately 100 epochs.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If your model does not reach 30 dB, review:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Patch extraction&lt;/li&gt;
&lt;li&gt;Data augmentation&lt;/li&gt;
&lt;li&gt;Input normalization&lt;/li&gt;
&lt;li&gt;Learning-rate scheduling&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Week 4 — Implement Your Contribution
&lt;/h3&gt;

&lt;p&gt;Possible contributions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A new attention mechanism (channel + spatial jointly)&lt;/li&gt;
&lt;li&gt;A transmission-map estimation branch&lt;/li&gt;
&lt;li&gt;A contrastive-learning component inspired by AECR-Net&lt;/li&gt;
&lt;li&gt;A Swin Transformer replacement block&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Implement the proposed component and validate it independently.&lt;/p&gt;

&lt;h3&gt;
  
  
  Week 5 — Integrate and Train Full Model
&lt;/h3&gt;

&lt;p&gt;Train the complete architecture from scratch.&lt;/p&gt;

&lt;p&gt;Tasks:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Save checkpoints periodically.&lt;/li&gt;
&lt;li&gt;Evaluate on SOTS-Indoor and SOTS-Outdoor every 50 epochs.&lt;/li&gt;
&lt;li&gt;Track both PSNR and SSIM.&lt;/li&gt;
&lt;li&gt;Monitor training stability and convergence.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Week 6 — Cross-Dataset Evaluation
&lt;/h3&gt;

&lt;p&gt;Run the trained model directly (zero-shot, no fine-tuning) on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;O-Haze&lt;/li&gt;
&lt;li&gt;I-Haze&lt;/li&gt;
&lt;li&gt;NH-Haze&lt;/li&gt;
&lt;li&gt;Dense-Haze&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Record all metrics and observations.&lt;/p&gt;

&lt;p&gt;This is usually where model weaknesses become visible and where the research narrative begins to emerge.&lt;/p&gt;

&lt;h3&gt;
  
  
  Week 7 — Ablation Studies
&lt;/h3&gt;

&lt;p&gt;Remove or disable one component at a time and retrain.&lt;/p&gt;

&lt;p&gt;Examples:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Remove attention module.&lt;/li&gt;
&lt;li&gt;Remove transmission branch.&lt;/li&gt;
&lt;li&gt;Remove contrastive loss.&lt;/li&gt;
&lt;li&gt;Replace custom block with baseline block.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For each ablation:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Measure ΔPSNR.&lt;/li&gt;
&lt;li&gt;Measure ΔSSIM.&lt;/li&gt;
&lt;li&gt;Compare computational cost.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This section is often the most important part of the paper for reviewers.&lt;/p&gt;

&lt;h3&gt;
  
  
  Week 8 — Paper and Submission
&lt;/h3&gt;

&lt;p&gt;Suggested paper structure:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Introduction&lt;/li&gt;
&lt;li&gt;Related Work&lt;/li&gt;
&lt;li&gt;Proposed Method&lt;/li&gt;
&lt;li&gt;Experimental Setup&lt;/li&gt;
&lt;li&gt;Results and Discussion&lt;/li&gt;
&lt;li&gt;Ablation Studies&lt;/li&gt;
&lt;li&gt;Conclusion&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Guidelines:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Include tables covering all five datasets.&lt;/li&gt;
&lt;li&gt;Provide visual comparisons on at least three challenging images from each real-haze dataset.&lt;/li&gt;
&lt;li&gt;Report both quantitative and qualitative results.&lt;/li&gt;
&lt;li&gt;Clearly justify every architectural design choice.&lt;/li&gt;
&lt;li&gt;Discuss failure cases honestly.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Tools and Frameworks
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;BasicIR:&lt;/strong&gt; The image restoration framework from XiPixelGroup, the same team behind BasicSR. Specifically includes dehazing models (FFA-Net, AECR-Net) alongside other restoration tasks. Clean codebase, well-documented training configs.&lt;/p&gt;

&lt;p&gt;Repository:&lt;br&gt;&lt;br&gt;
&lt;a href="https://github.com/XPixelGroup/BasicIR" rel="noopener noreferrer"&gt;https://github.com/XPixelGroup/BasicIR&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;BasicSR:&lt;/strong&gt; The broader image restoration framework covering denoising, super-resolution, and dehazing. Includes training scripts, loss functions, and metric evaluation utilities.&lt;/p&gt;

&lt;p&gt;Repository:&lt;br&gt;&lt;br&gt;
&lt;a href="https://github.com/XPixelGroup/BasicSR" rel="noopener noreferrer"&gt;https://github.com/XPixelGroup/BasicSR&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;DehazeFormer official code:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
&lt;a href="https://github.com/IDKiro/DehazeFormer" rel="noopener noreferrer"&gt;https://github.com/IDKiro/DehazeFormer&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Includes training scripts for RESIDE and all five evaluation datasets. Best starting point for transformer-based dehazing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;OpenCV:&lt;/strong&gt; For image I/O, colour space conversion, and the DCP baseline implementation.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;opencv-python
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;OpenCV includes a built-in dehazing module (&lt;code&gt;cv2.createCLAHE&lt;/code&gt;) that can serve as a simple baseline.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;scikit-image:&lt;/strong&gt; PSNR, SSIM, and image quality metrics.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;scikit-image
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;IQA-PyTorch:&lt;/strong&gt; Unified metric library for PSNR, SSIM, LPIPS, NIQE, FADE, and CIEDE2000. Essential for comprehensive evaluation.&lt;/p&gt;

&lt;p&gt;Repository:&lt;br&gt;&lt;br&gt;
&lt;a href="https://github.com/chaofengc/IQA-PyTorch" rel="noopener noreferrer"&gt;https://github.com/chaofengc/IQA-PyTorch&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;pyiqa
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;FADE metric implementation:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
&lt;a href="https://github.com/Utkarsh-Deshmukh/Fog-Aware-Density-Evaluator" rel="noopener noreferrer"&gt;https://github.com/Utkarsh-Deshmukh/Fog-Aware-Density-Evaluator&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Python implementation of the FADE no-reference fog density metric.&lt;/p&gt;




&lt;h2&gt;
  
  
  7 Common Mistakes Researchers Make
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Mistake 1 — Reporting Only RESIDE-SOTS Numbers
&lt;/h3&gt;

&lt;p&gt;A paper that reports 40 dB on SOTS-Indoor but does not evaluate on any real-haze dataset will face justified reviewer pushback. The community has largely moved to requiring at least one real-haze benchmark alongside RESIDE.&lt;/p&gt;

&lt;p&gt;Always include O-Haze or I-Haze results.&lt;/p&gt;

&lt;h3&gt;
  
  
  Mistake 2 — Confusing SOTS-Indoor and SOTS-Outdoor
&lt;/h3&gt;

&lt;p&gt;Outdoor dehazing appears easier because test sets contain different visibility levels. SOTS-Outdoor typically yields 3–5 dB higher PSNR than SOTS-Indoor for the same model.&lt;/p&gt;

&lt;p&gt;Reporting "SOTS PSNR: 36 dB" without specifying indoor or outdoor is ambiguous and should be avoided.&lt;/p&gt;

&lt;h3&gt;
  
  
  Mistake 3 — Evaluating at Wrong Resolution
&lt;/h3&gt;

&lt;p&gt;O-Haze, I-Haze, NH-Haze, and Dense-Haze are captured at high resolutions (approximately 2K–16 MP), but almost all studies evaluate at 512×512 or 1024×1024.&lt;/p&gt;

&lt;p&gt;Some papers resize differently, leading to non-comparable numbers.&lt;/p&gt;

&lt;p&gt;Always report the evaluation resolution.&lt;/p&gt;

&lt;h3&gt;
  
  
  Mistake 4 — Training and Testing on the Same Real-Haze Dataset
&lt;/h3&gt;

&lt;p&gt;With only 45 pairs in O-Haze, some researchers mistakenly use all 45 pairs for both training and evaluation.&lt;/p&gt;

&lt;p&gt;This inflates benchmark numbers.&lt;/p&gt;

&lt;p&gt;The official training/validation/test split and evaluation protocol should always be respected.&lt;/p&gt;

&lt;h3&gt;
  
  
  Mistake 5 — Ignoring the Sky Region Problem
&lt;/h3&gt;

&lt;p&gt;DCP and many CNN methods produce visible artefacts in sky regions (over-darkening in DCP, bright halos in CNNs).&lt;/p&gt;

&lt;p&gt;If qualitative examples only show vegetation or textured regions, reviewers may notice the omission.&lt;/p&gt;

&lt;p&gt;Include at least one challenging sky-containing image in qualitative evaluations.&lt;/p&gt;

&lt;h3&gt;
  
  
  Mistake 6 — Claiming SOTA Without Real-Haze Evaluation
&lt;/h3&gt;

&lt;p&gt;Achieving 40+ dB on RESIDE-SOTS-Indoor is impressive but no longer sufficient to claim state-of-the-art performance.&lt;/p&gt;

&lt;p&gt;Recent research places substantial emphasis on real-haze robustness.&lt;/p&gt;

&lt;p&gt;Ensure your proposed method is evaluated on at least NH-Haze or Dense-Haze.&lt;/p&gt;

&lt;h3&gt;
  
  
  Mistake 7 — Using PSNR Alone to Compare Methods on Dense-Haze
&lt;/h3&gt;

&lt;p&gt;On Dense-Haze, PSNR ranges are often narrow (approximately 10–17 dB), making small differences difficult to interpret.&lt;/p&gt;

&lt;p&gt;Always supplement PSNR with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;SSIM&lt;/li&gt;
&lt;li&gt;LPIPS&lt;/li&gt;
&lt;li&gt;Visual side-by-side comparisons&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A model achieving 15.5 dB with SSIM = 0.55 and visually strong texture restoration may be preferable to a model achieving 16.0 dB with SSIM = 0.45 and blurry outputs.&lt;/p&gt;




&lt;h2&gt;
  
  
  Your Next Steps + Conclusion
&lt;/h2&gt;

&lt;h3&gt;
  
  
  A Practical Action Plan
&lt;/h3&gt;

&lt;p&gt;You now have a complete blueprint for image dehazing research. Here is how to convert it into output.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;If you are a Final Year B.Tech student:&lt;/strong&gt; Start with RESIDE-ITS and FFA-Net. Get a PSNR of approximately 30 dB on SOTS-Indoor. Then add O-Haze evaluation — that cross-dataset result is what makes a thesis examiner approve the work confidently.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;If you are an M.Tech student with 6 months:&lt;/strong&gt; Follow the 8-week roadmap. The key differentiator at this level is the cross-dataset evaluation table. Showing results on all five datasets — synthetic, real mild, real non-homogeneous, and real dense — demonstrates thoroughness that distinguishes publication-ready work from average academic projects.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;If you are a PhD student:&lt;/strong&gt; Engage directly with the Research Gap Radar. The synthetic-to-real gap (Gap 1) and non-homogeneous haze modelling (Gap 2) remain the two largest unresolved challenges in image dehazing research. Gap 4 (dehazing for downstream tasks) is particularly underexplored and has natural conference relevance for venues such as TIP, CVPR, ICCV, ECCV, and AAAI.&lt;/p&gt;

&lt;h3&gt;
  
  
  What the Community Has Learned
&lt;/h3&gt;

&lt;p&gt;The history of image dehazing benchmarks is essentially a progression toward increasingly realistic models.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;RESIDE established the first large-scale benchmark and revealed that deep learning could outperform traditional prior-based methods on synthetic data.&lt;/li&gt;
&lt;li&gt;O-Haze and I-Haze exposed the synthetic-to-real gap.&lt;/li&gt;
&lt;li&gt;NH-Haze demonstrated that spatially varying haze significantly increases difficulty and challenges assumptions used by many traditional models.&lt;/li&gt;
&lt;li&gt;Dense-Haze highlighted the fundamental limitations of existing approaches under severe visibility degradation.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each benchmark contributed a specific piece to the overall research story. Researchers who understand the progression from RESIDE → O-Haze/I-Haze → NH-Haze → Dense-Haze are better equipped to position their work, anticipate reviewer concerns, and identify meaningful research contributions.&lt;/p&gt;

&lt;p&gt;The datasets discussed in this guide remain highly relevant. Future improvements are unlikely to come solely from achieving marginal gains such as 0.2 dB PSNR improvements on SOTS. More impactful contributions will come from understanding &lt;strong&gt;why&lt;/strong&gt; current methods fail under real haze and developing architectures that explicitly address those limitations.&lt;/p&gt;




&lt;h2&gt;
  
  
  Further Reading and Resources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;DCP Paper:&lt;/strong&gt; He et al., &lt;em&gt;"Single Image Haze Removal Using Dark Channel Prior,"&lt;/em&gt; TPAMI 2011.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;RESIDE Paper:&lt;/strong&gt; Li et al., &lt;em&gt;"Benchmarking Single-Image Dehazing and Beyond,"&lt;/em&gt; IEEE TIP 2019.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;FFA-Net Paper:&lt;/strong&gt; Qin et al., &lt;em&gt;"FFA-Net: Feature Fusion Attention Network for Single Image Dehazing,"&lt;/em&gt; AAAI 2020.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AECR-Net Paper:&lt;/strong&gt; Wu et al., &lt;em&gt;"Contrastive Learning for Compact Single Image Dehazing,"&lt;/em&gt; CVPR 2021.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;DehazeFormer Paper:&lt;/strong&gt; Song et al., &lt;em&gt;"Vision Transformers for Single Image Dehazing,"&lt;/em&gt; IEEE TIP 2023.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;NTIRE 2020 Challenge Report:&lt;/strong&gt; Ancuti et al., &lt;em&gt;"NTIRE 2020 Challenge on NonHomogeneous Dehazing,"&lt;/em&gt; CVPRW 2020.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;IQA-PyTorch Documentation:&lt;/strong&gt; &lt;a href="https://iqa-pytorch.readthedocs.io" rel="noopener noreferrer"&gt;https://iqa-pytorch.readthedocs.io&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;BasicIR Documentation:&lt;/strong&gt; &lt;a href="https://github.com/XPixelGroup/BasicIR" rel="noopener noreferrer"&gt;https://github.com/XPixelGroup/BasicIR&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;strong&gt;This article was originally published on Kaggle:&lt;/strong&gt; &lt;a href="https://www.kaggle.com/writeups/marykabrown/top-5-image-dehazing-datasets-for-researchers" rel="noopener noreferrer"&gt;Read the original here&lt;/a&gt;&lt;/p&gt;

</description>
      <category>computervision</category>
      <category>dehaze</category>
      <category>imageprocessing</category>
      <category>deeplearning</category>
    </item>
    <item>
      <title>Python 3.15: 3 More Features Python Developers Need to Know (2026)</title>
      <dc:creator>for IT the</dc:creator>
      <pubDate>Thu, 04 Jun 2026 17:00:58 +0000</pubDate>
      <link>https://dev.to/for_itthe_9cb5ee8d4b91f2/python-315-3-more-features-python-developers-need-to-know-2026-4hni</link>
      <guid>https://dev.to/for_itthe_9cb5ee8d4b91f2/python-315-3-more-features-python-developers-need-to-know-2026-4hni</guid>
      <description>&lt;p&gt;&lt;em&gt;Free Threading, Unpacking in Comprehensions, and Improved Error Messages — the second half of what actually matters in Python 3.15&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;On This Page&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Introduction&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Feature 5 — Free Threading Stable ABI&lt;/li&gt;
&lt;li&gt;Feature 6 — Unpacking in Comprehensions&lt;/li&gt;
&lt;li&gt;Feature 7 — Improved AttributeError Messages&lt;/li&gt;
&lt;li&gt;Quick Reference — All 7 Features&lt;/li&gt;
&lt;li&gt;Conclusion&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;This is Part 2 of the Python 3.15 developer guide.&lt;/p&gt;

&lt;p&gt;Part 1 on Hashnode covered Lazy Imports, UTF-8 Default, Zero-Overhead Profiler, and Faster JIT. If you haven't read it, start there — it covers the four features with the broadest day-to-day impact.&lt;/p&gt;

&lt;p&gt;This part covers the remaining three: Free Threading, Unpacking in Comprehensions, and Improved Error Messages.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Final release: October 1, 2026.&lt;/strong&gt; Beta 1 shipped May 7 — the feature set is locked.&lt;/p&gt;

&lt;p&gt;If you use Python for AI or ML engineering, &lt;a href="https://scientias.in/ai-coding/python-3-15-ai-engineers/" rel="noopener noreferrer"&gt;the full AI engineering breakdown of all seven features is on Scientias AI Labs&lt;/a&gt; — it covers the production AI systems implications in depth.&lt;/p&gt;

&lt;p&gt;Now let's get into Part 2.&lt;/p&gt;

&lt;h2&gt;
  
  
  Feature 5 — Free Threading Stable ABI
&lt;/h2&gt;

&lt;h3&gt;
  
  
  What It Is
&lt;/h3&gt;

&lt;p&gt;Python has had a Global Interpreter Lock (GIL) for decades. The GIL ensures thread safety by allowing only one thread to execute Python bytecode at a time. This makes Python threads safe — but useless for CPU-bound parallelism, because threads take turns rather than running simultaneously.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Python 3.14 introduced experimental free-threading. Python 3.15 makes the free-threading ABI stable.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Stable ABI means C extension libraries — NumPy, Pillow, lxml, cryptography — can now be reliably compiled for free-threaded Python builds. True CPU parallelism in Python threads is now practical.&lt;/p&gt;

&lt;p&gt;Full specification: &lt;a href="https://peps.python.org/pep-0703/" rel="noopener noreferrer"&gt;PEP 703 — Making the Global Interpreter Lock Optional&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  The GIL Problem in Plain Terms
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;threading&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;

&lt;span class="c1"&gt;# CPU-bound task
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;count_to_million&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;total&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1_000_000&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;total&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;total&lt;/span&gt;

&lt;span class="c1"&gt;# Sequential
&lt;/span&gt;&lt;span class="n"&gt;start&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;perf_counter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="nf"&gt;count_to_million&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="nf"&gt;count_to_million&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;sequential_time&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;perf_counter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;start&lt;/span&gt;

&lt;span class="c1"&gt;# Threaded — you expect this to be faster
# It is NOT faster in Python 3.14 because of the GIL
&lt;/span&gt;&lt;span class="n"&gt;thread1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;threading&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Thread&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;count_to_million&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;thread2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;threading&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Thread&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;count_to_million&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;start&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;perf_counter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;thread1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;start&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;thread2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;start&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;thread1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;thread2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;threaded_time&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;perf_counter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;start&lt;/span&gt;

&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Python 3.14 (with GIL):&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;  Sequential: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;sequential_time&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;s&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;  Threaded:   &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;threaded_time&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;s&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;  Speedup:    &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;sequential_time&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;threaded_time&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;x&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;  → ~1x. GIL serialises CPU-bound threads.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Python 3.15 (free threading, stable ABI):&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;  Threaded on 2 cores: ~&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;sequential_time&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;s&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;  Speedup: ~2x (true parallel execution)&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Free Threading in Practice
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;concurrent.futures&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;ThreadPoolExecutor&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;random&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;process_chunk&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data_chunk&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;CPU-bound processing&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;data_chunk&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;processed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
            &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;processed&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;split_into_chunks&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;n_chunks&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;chunk_size&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;//&lt;/span&gt; &lt;span class="n"&gt;n_chunks&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;chunk_size&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;chunk_size&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="n"&gt;random&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;seed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;dataset&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;random&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;random&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10_000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="n"&gt;n_workers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;
&lt;span class="n"&gt;chunks&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;split_into_chunks&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dataset&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;n_workers&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Sequential
&lt;/span&gt;&lt;span class="n"&gt;start&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;perf_counter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;sequential_results&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;process_chunk&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;chunks&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;sequential_time&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;perf_counter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;start&lt;/span&gt;

&lt;span class="c1"&gt;# Threaded — Python 3.15 free threading
# runs these truly in parallel on multiple cores
&lt;/span&gt;&lt;span class="n"&gt;start&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;perf_counter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nc"&gt;ThreadPoolExecutor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;max_workers&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;n_workers&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;executor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;threaded_results&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;executor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;process_chunk&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;chunks&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;threaded_time&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;perf_counter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;start&lt;/span&gt;

&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Sequential: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;sequential_time&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;s&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Threaded:   &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;threaded_time&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;s&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Speedup:    &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;sequential_time&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;threaded_time&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;x&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Python 3.14: ~1x (GIL prevents parallelism)&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Python 3.15: ~3-4x (true parallel execution)&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Threads vs Multiprocessing — The Shift
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# When to use each after Python 3.15
&lt;/span&gt;
&lt;span class="n"&gt;guidelines&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;I/O bound work (network, files, DB)&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;before_315&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;threading or asyncio&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;after_315&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;threading or asyncio (unchanged)&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;CPU bound work (computation, parsing)&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;before_315&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;multiprocessing (GIL workaround)&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;after_315&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;threading (simpler, less memory)&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Shared large data structures&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;before_315&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;multiprocessing with shared memory&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;after_315&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;threading (direct shared memory)&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Process isolation needed&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;before_315&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;multiprocessing&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;after_315&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;multiprocessing (still appropriate)&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;scenario&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;details&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;guidelines&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;items&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;scenario&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;:&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;  Before 3.15: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;details&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;before_315&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;  After 3.15:  &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;details&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;after_315&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Thread Safety — What to Watch
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;threading&lt;/span&gt;

&lt;span class="c1"&gt;# Without GIL, race conditions are more likely
&lt;/span&gt;&lt;span class="n"&gt;counter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;increment_unsafe&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;global&lt;/span&gt; &lt;span class="n"&gt;counter&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100_000&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;counter&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;  &lt;span class="c1"&gt;# Not atomic — race condition!
&lt;/span&gt;
&lt;span class="c1"&gt;# Safe version — always use locks for shared state
&lt;/span&gt;&lt;span class="n"&gt;counter_safe&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;span class="n"&gt;lock&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;threading&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Lock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;increment_safe&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;global&lt;/span&gt; &lt;span class="n"&gt;counter_safe&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100_000&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;lock&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;counter_safe&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;

&lt;span class="c1"&gt;# Best practices for Python 3.15 free threading:
# - Use threading.Lock() for shared mutable state
# - Prefer immutable data where possible
# - Use queue.Queue for thread communication
# - Check library support: https://py-free-threading.github.io/
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Where You Will Notice This Most
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Data processing pipelines&lt;/strong&gt; — split large datasets across CPU cores using threads instead of processes. Simpler code, lower memory cost, true parallelism.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Web server request handling&lt;/strong&gt; — true CPU parallelism for compute-heavy endpoints without the memory overhead of multiprocessing.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Batch file processing&lt;/strong&gt; — images, documents, logs across multiple CPU cores using a thread pool.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Feature 6 — Unpacking in Comprehensions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  What It Is
&lt;/h3&gt;

&lt;p&gt;PEP 798 extends Python's &lt;code&gt;*&lt;/code&gt; and &lt;code&gt;**&lt;/code&gt; unpacking operators to work inside list, set, and dict comprehensions.&lt;/p&gt;

&lt;p&gt;Before Python 3.15, flattening nested structures inside a comprehension required nested loops or intermediate variables.&lt;/p&gt;

&lt;p&gt;Full specification: &lt;a href="https://peps.python.org/pep-0798/" rel="noopener noreferrer"&gt;PEP 798 — Unpack Operator in Comprehensions&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  The Problem It Solves
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;nested&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt;

&lt;span class="c1"&gt;# Before Python 3.15 — nested loop required
&lt;/span&gt;&lt;span class="n"&gt;flat_old&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;item&lt;/span&gt;
            &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;sublist&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;nested&lt;/span&gt;
            &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;sublist&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="c1"&gt;# Python 3.15 — clean unpacking
&lt;/span&gt;&lt;span class="n"&gt;flat&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;sublist&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;sublist&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;nested&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="c1"&gt;# [1, 2, 3, 4, 5, 6, 7, 8, 9]
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Real-World Examples
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# 1. Flattening grouped data
&lt;/span&gt;
&lt;span class="n"&gt;tag_groups&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;python&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;python3&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;python-3.15&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;cpython&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;web&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;django&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;fastapi&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;flask&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;data&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;   &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;pandas&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;numpy&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;polars&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# Python 3.15
&lt;/span&gt;&lt;span class="n"&gt;all_tags&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;tags&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;tags&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;tag_groups&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;values&lt;/span&gt;&lt;span class="p"&gt;()]&lt;/span&gt;
&lt;span class="c1"&gt;# ['python3', 'python-3.15', 'cpython',
#  'django', 'fastapi', 'flask',
#  'pandas', 'numpy', 'polars']
&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;All tags: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;all_tags&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="c1"&gt;# 2. Merging dicts with defaults
&lt;/span&gt;
&lt;span class="n"&gt;user_profiles&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Alice&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;admin&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Bob&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;   &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="n"&gt;user_defaults&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;active&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;notifications&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;theme&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;dark&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# Python 3.15 — clean dict comprehension
&lt;/span&gt;&lt;span class="n"&gt;enriched&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;user_defaults&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;profile&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;profile&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;user_profiles&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;profile&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;enriched&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;profile&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="c1"&gt;# 3. Unique items from nested lists
&lt;/span&gt;
&lt;span class="n"&gt;post_tags&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;python&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;tutorial&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;beginner&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;python&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;advanced&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;performance&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;tutorial&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;web&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;django&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="c1"&gt;# Python 3.15 — set comprehension with unpacking
&lt;/span&gt;&lt;span class="n"&gt;unique_tags&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;tags&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;tags&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;post_tags&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Unique tags: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;unique_tags&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="c1"&gt;# 4. Combining config sources
&lt;/span&gt;
&lt;span class="n"&gt;default_config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;debug&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;log_level&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;INFO&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;timeout&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;env_overrides&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;debug&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;timeout&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;log_level&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;WARNING&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;debug&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;log_level&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;ERROR&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="n"&gt;env_names&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;development&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;staging&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;production&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="n"&gt;configs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;default_config&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;override&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;override&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;zip&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;env_names&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;env_overrides&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;config&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;configs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;items&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;: debug=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;debug&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;, &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
          &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;log=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;log_level&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Before vs After — Quick Summary
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# FLATTEN nested list:
# Before: [item for sub in nested for item in sub]
# After:  [*sub for sub in nested]
&lt;/span&gt;
&lt;span class="c1"&gt;# MERGE dicts in comprehension:
# Before: loop + .update()
# After:  {**defaults, **override for ...}
&lt;/span&gt;
&lt;span class="c1"&gt;# UNIQUE items from nested:
# Before: set(item for sub in nested for item in sub)
# After:  {*sub for sub in nested}
&lt;/span&gt;
&lt;span class="c1"&gt;# Best for:
# ✓ Flattening one level of nesting
# ✓ Merging dicts with a base default
# ✓ Building sets from nested iterables
# ✗ Deep nesting (still needs explicit loops)
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Where You Will Notice This Most
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Data transformation code&lt;/strong&gt; — flattening grouped or categorised data into flat lists. One of the most common Python patterns.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Config merging&lt;/strong&gt; — combining base configs with environment-specific overrides inside a dict comprehension.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;API response building&lt;/strong&gt; — flattening paginated results, combining data from multiple sources.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Feature 7 — Improved AttributeError Messages
&lt;/h2&gt;

&lt;h3&gt;
  
  
  What It Is
&lt;/h3&gt;

&lt;p&gt;Python 3.10 improved &lt;code&gt;NameError&lt;/code&gt; messages — mistype a variable name, Python suggests what you meant. Python 3.15 extends this significantly to &lt;strong&gt;nested attribute access&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Reference: &lt;a href="https://docs.python.org/3.15/whatsnew/3.15.html" rel="noopener noreferrer"&gt;Python 3.15 What's New&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  The Problem It Solves
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Config&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;database_host&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;localhost&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;database_port&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;5432&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;database_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;myapp&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;debug_mode&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;log_level&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;INFO&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;timeout_seconds&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;

&lt;span class="n"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Config&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;host&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;databse_host&lt;/span&gt;  &lt;span class="c1"&gt;# typo: databse
&lt;/span&gt;&lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;AttributeError&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;pass&lt;/span&gt;

&lt;span class="c1"&gt;# Python 3.14:
# AttributeError: 'Config' object has no attribute 'databse_host'
# → Open REPL, dir(config), find it manually
&lt;/span&gt;
&lt;span class="c1"&gt;# Python 3.15:
# AttributeError: 'Config' object has no attribute 'databse_host'.
# Did you mean: 'database_host'?
# → Fix it in 5 seconds. Move on.
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Where It Really Helps — Nested Access
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;DatabaseConfig&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;host&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;localhost&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;port&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;5432&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;max_connections&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;connection_timeout&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AppConfig&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;database&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;DatabaseConfig&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;debug&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Settings&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;AppConfig&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;version&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;1.0.0&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;

&lt;span class="n"&gt;settings&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Settings&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="c1"&gt;# Typo three levels deep
&lt;/span&gt;    &lt;span class="n"&gt;limit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;settings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;database&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;max_connection&lt;/span&gt;
&lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;AttributeError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;pass&lt;/span&gt;

&lt;span class="c1"&gt;# Python 3.14:
# AttributeError: 'DatabaseConfig' object
# has no attribute 'max_connection'
# → Which level caused it? Manual inspection needed.
&lt;/span&gt;
&lt;span class="c1"&gt;# Python 3.15:
# AttributeError: 'DatabaseConfig' object
# has no attribute 'max_connection'.
# Did you mean: 'max_connections'?
# → Correct it immediately.
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Common Scenarios — Before and After
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;scenarios&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;context&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Django model&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;typo&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;user.profil.avatar&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;py315&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;   &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Did you mean: &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;profile&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;?&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;context&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;SQLAlchemy session&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;typo&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;session.querry(User)&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;py315&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;   &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Did you mean: &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;query&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;?&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;context&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Requests response&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;typo&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;response.status_cod&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;py315&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;   &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Did you mean: &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;status_code&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;?&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;context&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;datetime object&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;typo&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;dt.strftim(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;%Y-%m-%d&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;)&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;py315&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;   &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Did you mean: &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;strftime&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;?&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;context&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;FastAPI app&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;typo&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;app.inclue_router(router)&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;py315&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;   &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Did you mean: &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;include_router&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;?&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;scenarios&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;context&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;typo&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;  → Python 3.15: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;py315&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  The Daily Time Saving
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Step&lt;/th&gt;
&lt;th&gt;Python 3.14&lt;/th&gt;
&lt;th&gt;Python 3.15&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Read error message&lt;/td&gt;
&lt;td&gt;5s&lt;/td&gt;
&lt;td&gt;5s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Open REPL / docs&lt;/td&gt;
&lt;td&gt;15s&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Inspect object&lt;/td&gt;
&lt;td&gt;30s&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Identify correct name&lt;/td&gt;
&lt;td&gt;15s&lt;/td&gt;
&lt;td&gt;3s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Fix and continue&lt;/td&gt;
&lt;td&gt;10s&lt;/td&gt;
&lt;td&gt;2s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Total&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;~75s&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;~10s&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;3–5 AttributeErrors per developer per day = &lt;strong&gt;4–5 minutes saved daily&lt;/strong&gt;. Small feature, real impact.&lt;/p&gt;

&lt;h3&gt;
  
  
  Where You Will Notice This Most
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Third-party libraries&lt;/strong&gt; — frameworks and ORMs have dozens of attributes. Typos are inevitable. Python 3.15 makes them instantly correctable.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Refactoring&lt;/strong&gt; — rename an attribute, Python 3.15 guides every typo fix across the codebase.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;New codebases&lt;/strong&gt; — exploring unfamiliar objects becomes faster when Python suggests the correct attribute name.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Deep object hierarchies&lt;/strong&gt; — Django models, Pydantic schemas, config objects. Typos at any nesting level now come with a suggestion.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Quick Reference — All 7 Python 3.15 Features
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;What It Does&lt;/th&gt;
&lt;th&gt;Who Benefits Most&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Lazy Imports&lt;/td&gt;
&lt;td&gt;Defers imports until first use&lt;/td&gt;
&lt;td&gt;CLI tools, scripts, serverless&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;UTF-8 Default&lt;/td&gt;
&lt;td&gt;UTF-8 everywhere by default&lt;/td&gt;
&lt;td&gt;Cross-platform teams&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Zero-Overhead Profiler&lt;/td&gt;
&lt;td&gt;Profile without slowing code&lt;/td&gt;
&lt;td&gt;All Python developers&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Faster JIT&lt;/td&gt;
&lt;td&gt;Pure Python loops faster&lt;/td&gt;
&lt;td&gt;Data processing, business logic&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Free Threading&lt;/td&gt;
&lt;td&gt;True CPU parallelism in threads&lt;/td&gt;
&lt;td&gt;CPU-bound parallel workloads&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Unpacking in Comprehensions&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;*&lt;/code&gt; and &lt;code&gt;**&lt;/code&gt; inside comprehensions&lt;/td&gt;
&lt;td&gt;Data transformation code&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Improved AttributeError&lt;/td&gt;
&lt;td&gt;Suggests correct attribute names&lt;/td&gt;
&lt;td&gt;Every Python developer, daily&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Part 1 (Hashnode):&lt;/strong&gt; Features 1–4&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Part 2 (this article):&lt;/strong&gt; Features 5–7&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Python 3.15's final three features round out a strong release.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Free threading with stable ABI&lt;/strong&gt; is the most architecturally significant — true CPU parallelism in Python threads without the GIL. The shift from multiprocessing to threading for CPU-bound work starts here.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Unpacking in comprehensions&lt;/strong&gt; is a small syntax change with a real readability payoff. Flattening nested structures and merging dicts inside comprehensions becomes cleaner and more Pythonic.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Improved AttributeError messages&lt;/strong&gt; is the feature you will notice most frequently. Typos in attribute names happen every day. Python 3.15 makes fixing them nearly instant.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Final release: October 1, 2026.&lt;/strong&gt; Test against Beta 1 now. Free threading is opt-in, unpacking syntax is additive, and better error messages require no code changes.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Part 1 covering Lazy Imports, UTF-8 Default, Zero-Overhead Profiler, and Faster JIT is on Hashnode.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>python</category>
      <category>pythonversion315</category>
      <category>pythondevelopers</category>
      <category>pythonfeatures</category>
    </item>
  </channel>
</rss>
