Spaces:
Running
Running
import cv2 | |
import numpy as np | |
from scipy.fft import fft2, ifft2, fftshift, ifftshift | |
from PIL import Image | |
def fourier_upscale(image, scale_factor=4): | |
upscaled_channels = [] | |
for c in range(3): # For R, G, B channels | |
# Get single channel | |
channel = image[:, :, c] | |
# Forward FFT | |
F = fft2(channel) | |
F_shifted = fftshift(F) | |
# Zero-padding in frequency domain | |
h, w = channel.shape | |
new_h, new_w = h * scale_factor, w * scale_factor | |
F_padded = np.zeros((new_h, new_w), dtype=complex) | |
# Place the original spectrum in the center of the padded one | |
h_center, w_center = new_h // 2, new_w // 2 | |
h_half, w_half = h // 2, w // 2 | |
F_padded[h_center - h_half:h_center + h_half, w_center - w_half:w_center + w_half] = F_shifted | |
# Inverse FFT | |
F_unshifted = ifftshift(F_padded) | |
upscaled = np.real(ifft2(F_unshifted)) | |
# ✅ Rescale intensities | |
upscaled *= scale_factor ** 2 # Rescale to preserve brightness | |
# Normalize to [0, 255] | |
upscaled = np.clip(upscaled, 0, 255) | |
upscaled_channels.append(upscaled.astype(np.uint8)) | |
# Stack the 3 upscaled channels | |
upscaled_img = np.stack(upscaled_channels, axis=2) | |
return upscaled_img |