我有一个信号,我正在尝试确定其 SNR,但我对该信号的了解有限。对于我收到的信号,我不知道频率是多少,但我确实知道频率不会改变。我知道我的信号被分成块(符号),并且任何两个块之间的相位差将为 0 或 180 度。我还知道信号将具有相似的幅度,因此任何两个信号块之间唯一的不同应该是相位以及影响它们的任何噪声。
至于添加到信号中的噪声,我预计大部分是 awgn,但也可能存在符号间干扰,即与信号本身频率相同的噪声。
有没有办法只用这些信息来确定 SNR?这是一个例子。我可以生成两个信号块,称为 prevSig 和 currSig,这就是可能传输的内容。
然后在接收信号时,会添加一些随机噪声,这些相同的信号可以看作:
因此,如果我只有嘈杂的接收信号,我该怎么做才能从中获得信噪比。我相信我可以通过对样本进行逐点加法或减法来确定任意两个信号块之间的相对相位。如果将样本相加小于样本相减,则意味着这些块的相对相位差为 180,如果不是,则这些块具有相同的相位,因此从那里我可以轻松获得两个信号块应该是相同的初始信号,只是有不同的随机噪声影响它们(我假设噪声方差是相似的)
感谢您帮助我思考这个问题。下面是我用来生成这些信号的代码
from plotly.subplots import make_subplots
import plotly.graph_objs as go
import numpy as np
fs = 12000
t = 505/fs
f = 500
samples = np.arange(t * fs) / fs
signal = np.sin(2 * np.pi * f * samples)
prevSig = signal
currSig = signal*-1 # 180 degree phase shift
fig = make_subplots(rows=2, cols=1)
fig.add_trace(go.Scatter(y=list(prevSig), mode='lines+markers', name='prevSig'), row=1, col=1)
fig.add_trace(go.Scatter(y=list(currSig), mode='lines+markers', name='currSig'), row=2, col=1)
fig.update_layout(dict(title=dict(text='Signals before noise')))
fig.show()
#calculate power of signal before noise
sigPower = np.mean(signal**2)
targetSNR = 5
#Calculate noise
prevNoise = np.random.normal(0, sigPower/targetSNR, len(signal))
currNoise = np.random.normal(0, sigPower/targetSNR, len(signal))
fig = make_subplots(rows=2, cols=1)
fig.add_trace(go.Scatter(y=list(prevSig+prevNoise), mode='lines+markers', name='prevSigNoisy'), row=1, col=1)
fig.add_trace(go.Scatter(y=list(currSig+currNoise), mode='lines+markers', name='currSigNoisy'), row=2, col=1)
fig.update_layout(dict(title=dict(text='Signals with noise')))
fig.show()
让我们接受您的信号:
import numpy as np
from scipy import fft
fs = 12000
t = 505/fs
f = 500
samples = np.arange(t * fs) / fs
signal = np.sin(2 * np.pi * f * samples)
并在其上添加一些可重现的噪音:
np.random.seed(12345)
noise = 0.25*np.random.normal(size=signal.size)
然后我们可以通过估计每个分量的RMS来估计SNR:
def rms(x):
return np.sqrt(np.sum(x**2)/x.size)
SNR = (rms(signal)/rms(noise))**2 # 7.76816527364244
现在让我们确认可以使用 FFT 通过对信号进行去噪来估计它。
我们对噪声信号进行 FFT(并且还计算频率以进行绘图):
dt = np.diff(samples)[0] # 1/f
G = fft.fft(signal + noise)
freq = fft.fftfreq(G.size, dt)
现在我们创建一个数字滤波器(帽子滤波器),它只会拾取或拒绝基频:
q = np.abs(np.abs(freq) - f) <= 20.
F = np.zeros(G.size)
F[q] = 1.
我们过滤信号:
Gf = G*F
Nf = G*(1-F)
并估计功率,然后估计信噪比:
def power(X):
return np.sum(np.real(X*np.conj(X)))
SNR2 = power(Gf)/power(Nf) # 7.600875978410159
这符合我们的参考。
我们可以通过逆 FFT 来确认滤波后的信号已正确去噪:
signalf = np.real(fft.ifft(Gf))