您提出的解决方案 - 根据 FFT 中的峰值计算时域中的正弦曲线,然后减去它 - 应该可以工作,但有一种更简单的方法可以做本质上相同的事情:修改 FFT 中的峰值,然后取反转变。
因此,对于您的光栅化视频,M[nframes, npixels]
您会找到包含伪影的频率箱,然后系统地将其展平(例如,将其幅度设置为其相邻像素的平均值):
import numpy as np
nframes, npixels = np.shape(M)
# Identify the bin containing the sinusoidal artifact
# Use the average intensity for each image
m = np.mean(M, axis=1)
# Calculate the FFT
Fm = np.fft.rfft(m)
# Find the largest bin away from the low-frequency region
lowfreq = 100 # or something
badbin = lowfreq + np.argmax(Fm[lowfreq:]**2)
# Now adjust the amplitude of that bin in the FFT of each pixel
for pixel in range(npixels):
Fpix = np.fft.rfft(M[:, pixel])
# Scale magnitude of artifact bin to be the mean of its neighbors
Fpix[badbin] *= np.mean(np.absolute(Fpix[[badbin-1, badbin+1]]))/np.absolute(Fpix[badbin])
# Rewrite the time sequence of that pixel
M[:,pixel] = np.fft.irfft(Fpix)
如果伪影是完全恒定的幅度和频率,并且它的频率正好落在序列长度的约数上(即,由 FFT 表示的正弦曲线),这应该可以工作。通常,您可能希望将两侧的一个或两个 bin 展平,badbin
以处理一组稍宽的窄带损坏,例如
# ...
# Scale magnitude of artifact binS to be the mean of neighbors
spread = 3 # flatten bins from (badbin - (spread-1)) to (badbin + (spread-1))
# target value for new bins
targetmag = np.mean(np.absolute(Fpix[[badbin-spread, badbin+spread]]))
bins = range(badbin - (spread-1), badbin + spread)
Fpix[bins] *= targetmag/np.abs(Fpix[bins])
# ...
如果您想约束从每个像素中移除的分量,使其具有在平均强度中检测到的伪影的相同频率和相位,您可以仅移除badbin
幅度在该相位上的投影,例如
badbinphase = np.angle(Fm[badbin])
# ...
Ncomponent = np.abs(Fpix[badbin])*np.cos(np.angle(Fpix[badbin]) - badbinphase)
Fpix[badbin] -= Ncomponent * np.exp(0+1j * badbinphase)
# ...
请注意,生成的分量badbin
现在总是与badbinphase
每个像素中的全局相移 90°(正交) - 任何恰好处于该频率和相位的信号分量都无法与伪影分离。