2D Image Smoothing#

We use the smooth module to smooth a 2D grayscale image, with strong visible noise.

Imports#

import numpy as np
import matplotlib.pyplot as plt
from splineops.smoothing_splines.smoothing_spline import smoothing_spline_nd

2D Image Smoothing#

from urllib.request import urlopen
from PIL import Image

def create_image():
    """
    Loads a real image and converts it to grayscale.
    """
    url = 'https://r0k.us/graphics/kodak/kodak/kodim06.png'
    with urlopen(url, timeout=10) as resp:
        # Force grayscale (L = luminance)
        img = Image.open(resp).convert('L')

    data = np.array(img, dtype=np.float64)
    data /= 255.0  # Normalize to [0, 1] grayscale

    return data

def add_noise(img, snr_db):
    """
    Adds Gaussian noise to the image based on the desired SNR in dB.
    """
    signal_power = np.mean(img ** 2)
    sigma = np.sqrt(signal_power / (10 ** (snr_db / 10)))
    noise = np.random.randn(*img.shape) * sigma
    noisy_img = img + noise

    # Keep within [0, 1] for nicer display
    noisy_img = np.clip(noisy_img, 0.0, 1.0)

    return noisy_img

def compute_snr(clean_signal, noisy_signal):
    """
    Compute the Signal-to-Noise Ratio (SNR).

    Parameters:
    clean_signal (np.ndarray): Original clean signal.
    noisy_signal (np.ndarray): Noisy signal.

    Returns:
    float: SNR value in decibels (dB).
    """
    signal_power = np.mean(clean_signal ** 2)
    noise_power = np.mean((noisy_signal - clean_signal) ** 2)
    snr = 10 * np.log10(signal_power / noise_power)
    return snr

def demo_image():
    # Parameters
    lambda_ = 0.1   # Regularization parameter
    gamma = 2.0     # Order of the spline operator

    # Noise
    snr_db = 8.0

    # Load grayscale image
    img = create_image()

    # Add noise
    noisy_img = add_noise(img, snr_db)

    # Smooth the noisy image
    smoothed_img = smoothing_spline_nd(noisy_img, lambda_, gamma)

    # Clip for display and SNR computation
    smoothed_img = np.clip(smoothed_img, 0.0, 1.0)

    # Compute SNRs
    snr_noisy = compute_snr(img, noisy_img)
    snr_smooth = compute_snr(img, smoothed_img)
    snr_improvement = snr_smooth - snr_noisy

    print("Image:")
    print(f"SNR of noisy image: {snr_noisy:.2f} dB")
    print(f"SNR after smoothing: {snr_smooth:.2f} dB")
    print(f"SNR improvement: {snr_improvement:.2f} dB\n")

    # Visualization for image
    plt.figure(figsize=(12, 4))

    # Original grayscale image
    plt.subplot(1, 3, 1)
    plt.imshow(img, cmap='gray', vmin=0, vmax=1)
    plt.title('Original Grayscale Image')
    plt.axis('off')

    # Noisy image
    plt.subplot(1, 3, 2)
    plt.imshow(noisy_img, cmap='gray', vmin=0, vmax=1)
    plt.title(f'Noisy Image (SNR={snr_noisy:.2f} dB)')
    plt.axis('off')

    # Smoothed grayscale image
    plt.subplot(1, 3, 3)
    plt.imshow(smoothed_img, cmap='gray', vmin=0, vmax=1)
    plt.title(f'Smoothed Image (SNR={snr_smooth:.2f} dB)')
    plt.axis('off')

    plt.tight_layout()
    plt.show()

# Run the image demo
demo_image()
Original Grayscale Image, Noisy Image (SNR=8.90 dB), Smoothed Image (SNR=15.17 dB)
Image:
SNR of noisy image: 8.90 dB
SNR after smoothing: 15.17 dB
SNR improvement: 6.27 dB

Total running time of the script: (0 minutes 1.929 seconds)

Gallery generated by Sphinx-Gallery