Perfect interpolation (sinc) of Fourier spectrum equivalent to zero-padding time domain

  Kiến thức lập trình

I have a need to up-sample a 2D Fourier spectrum, this can be done by zero padding the image before the FFT. But in my particular case I cannot perform an FFT or IFFT, the interpolation must be performed in the Fourier domain.

Here, to make visualization easier, I will present only the 1D case.
I use Python and the PyTorch library to perform the computation, but almost everything can be converted name for name to numpy.

Imports

import torch
from matplotlib import pyplot as plt
from torch.nn import functional as F

Parameters

Ts: float = 2.0  # Sampling period
NUM_POINTS: int = 10
FACTOR: int = 16  # Factor by which to up-sample (new signal will have NUM_POINTS*FACTOR samples)

Generate a 1D signal and its spectrum

def func(time: torch.Tensor) -> torch.Tensor:
    # A func to generate a signal
    return 5*torch.sin(time) + 3*torch.cos(time*2) + time * 0.5

# Sampling times
original_t = torch.arange(start=0, end=NUM_POINTS*Ts, step=Ts, dtype=torch.float)
# Time domain signal
original_signal = func(original_t)
# Fourier spectrum of said signal
original_spectrum = torch.fft.fftshift(torch.fft.fft(original_signal))

# Plotting
plt.plot(original_t, original_spectrum.abs(), marker="o", label="Original")
plt.legend()
plt.title("Original Spectrum of 1D signal")
plt.show()

Sampled signal

FFT based interpolation

padding: int = (NUM_POINTS*FACTOR - NUM_POINTS) // 2
old_signal_padded = F.pad(original_signal, (padding,padding), mode="constant", value=0)

interpolated_spectrum = torch.fft.fftshift(torch.fft.fft(old_signal_padded))

# Generate interpolation times
interpolated_t = torch.arange(start=0, end=NUM_POINTS*Ts, step=Ts/FACTOR, dtype=torch.float)

# Plotting
plt.plot(interpolated_t, interpolated_spectrum.abs(), marker="x", label="Up-sampled")
plt.plot(original_t, original_spectrum.abs(), marker="o", label="Original")
plt.legend()
plt.title("Magnitude of original and interpolated spectrum (using zero-padding + FFT)")
plt.show()

FFT+zero-padding based interpolation

The zero-padding theorem states that zero-padding the spatial domain is equivalent to a convolution of the Fourier spectrum with an infinite sinc (sinus cardinal) kernel. But I cannot obtain the same result, what is the correct way to do it ?

Here is a visualization of the sinc interpolation process

I tried:

Sinc interpolation

# Generate interpolation times
interpolated_t = torch.arange(start=0, end=NUM_POINTS*Ts, step=Ts/FACTOR, dtype=torch.float)

# Compute the differences for sinc interpolation
sinc_matrix = interpolated_t.unsqueeze(1) - original_t.unsqueeze(0)
sinc_matrix /= Ts
sinc_matrix.sinc_()

# Perform the interpolation
interpolated_spectrum = torch.matmul(sinc_matrix.to(original_spectrum.dtype), original_spectrum)

# Plotting
plt.plot(interpolated_t, interpolated_spectrum.abs(), marker="x", label="Up-sampled")
plt.plot(original_t, original_spectrum.abs(), marker="o", label="Original")
plt.legend()
plt.title("Magnitude of original and interpolated spectrum (sinc interpolation)")
plt.show()

Sinc base interpolation
This code, despite providing an up-sampling of the signal does not fit my needs because it does not provide the same result as zero-padding in the time domain before the FFT (which I cannot do).

How do I obtain de same result ?

New contributor

ElecThor is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.

Theme wordpress giá rẻ Theme wordpress giá rẻ Thiết kế website

LEAVE A COMMENT