我正在尝试通过频谱减法来增强超声信号。该信号在时域中并且包含噪声。我将信号划分为2 µs的汉明窗,并计算了这些帧的傅立叶变换。然后,我选择了3个连续的帧,我将其解释为噪声。我将这3帧的幅度谱取平均值,然后从每个单帧的幅度谱中减去该平均值。然后,我将所有负振幅谱定义为零,并通过将新的振幅谱与相位谱组合来重建增强的傅立叶变换。这给了我每帧一系列的复数。现在,我想通过使用傅立叶逆变换将这个序列变换回时域。但是,此操作为我提供了不知道如何使用的复数。
我读过几篇文章,从傅里叶逆变换获得复杂的输出是正常的。但是,复数的使用是分开的。有人说忽略了虚部,因为它应该很小(e-15),但在我的情况下却不能忽略(0.01-0.5)。老实说,我只是现在不知道该如何处理数字,因为我期望傅里叶逆变换只会给我实数。并希望有非常小的假想部分,但不幸的是。
# General parameters
#
total_samples = length(time_or) # Total numbers of samples in the current series
max_time = max(time_or) # Length of the measurement in microseconds
sampling_freq = 1/(max_time/1000000)*total_samples # Sampling frequency
frame_length_t = 2 # In microseconds (time)
frame_length_s = round(frame_length_t/1000000*sampling_freq) # In samples per frame
overlap = frame_length_s/2 # Overlap in number of frames, set to 50% overlap
#
# Transform the frame to frequency domain
#
fft_frames = specgram(amp, n=frame_length_s, Fs=125, window=hamming(frame_length_s), overlap=overlap)
mag_spec=abs(fft_frames[["S"]])
phase_spec=atan(Im(fft_frames[["S"]])/Re(fft_frames[["S"]]))
#
# Determine the arrival time of noise
#
cutoff= 10 #determine the percentage of the signal that has to be cut off
dnr=us_data[(length(us_data[,1])*(cutoff/100)):length(us_data[,1]), ]
noise_arr=(length(us_data[,1])-length(dnr[,1])+min(which(dnr[,2]>0.01)))*0.008
#
# Select the frames for noise spectrum estimation
#
noise_spec=0
noise_spec=mag_spec[,noise_arr]
noise_spec=noise_spec+mag_spec[, (noise_arr+1)]
noise_spec=noise_spec+mag_spec[, (noise_arr+2)]
noise_spec_check=noise_spec/3
#
# Subtract the estimated noise spectrum from every frame
#
est_mag_spec=mag_spec-noise_spec_check
est_mag_spec[est_mag_spec < 0] = 0
#
# Transform back to frequency spectrum
#
j=complex(real=0, imaginary=1)
enh_spec = est_mag_spec*exp(j*phase_spec)
#
# Transform back to time domain
#
install.packages("pracma")
library("pracma")
enh_time=fft(enh_spec[,2], inverse=TRUE)
我希望有人对如何处理这些复数有所了解。也许我之前在处理方法上犯了一个错误,但是我已经多次检查了它,对我来说似乎很可靠。这是该过程的最后一步,但实际上是希望在傅里叶逆变换之后获得一个不错的时域信号。
答案 0 :(得分:0)
使用傅立叶变换进行数据转换时,基本的故障排除辅助是您可以先进行fft然后取数据并进行逆fft并取回原始数据的想法。我建议您可以轻松地通过玩具输入来完成此操作时域数据...可以说是一个1 Khz音频波,它是您的时域数据...将其发送到fft调用中,它将返回其频域表示形式的数组...对该数据不执行任何操作转换为逆fft(ifft)...返回的数据将使您原来的1 Khz音频波...现在进行操作以增强其威力,并在您的项目中使用此技巧来确认您在球场上。 ..或者,如果您从频域数据开始,也可以这样做...
freq domain data -> ifft -> time domain data -> fft -> same freq domain data
或
time domain -> fft -> freq domain -> ifft -> same time domain data
查看更多详细信息
答案 1 :(得分:0)
这是您的问题:
phase_spec=atan(Im(fft_frames[["S"]])/Re(fft_frames[["S"]]))
您在这里计算一个半圆的角度,将另一半映射到第一个。也就是说,您正在丢失信息。
许多语言都具有获取复杂值相位的功能,例如在MATLAB中为angle
,而在Python numpy.angle
中。
或者,使用atan2
函数,该函数存在于我曾经使用过的每种语言中,但在NumPy中,他们决定将其命名为arctan2
。它通过将两个分量作为单独的值来计算四象限反正切。也就是说,如果结果在前两个象限中,则atan(y/x)
与atan2(y,x)
相同。
我想你可以
phase_spec=atan2(Im(fft_frames[["S"]]), Re(fft_frames[["S"]]))