为信号添加噪声的正确方法
Posted
技术标签:
【中文标题】为信号添加噪声的正确方法【英文标题】:Proper way to add noise to signal 【发布时间】:2014-07-04 15:21:54 【问题描述】:在许多领域,我发现在添加噪声时,我们会提到一些规范,例如零均值和方差。我需要在 Db 中添加 AWGN、有色噪声、不同 SNR 的均匀噪声。以下代码显示了我如何生成和添加噪声的方式。我知道函数awgn()
,但它是一种黑盒子,不知道噪声是如何添加的。那么,有人可以解释产生和添加噪音的正确方法吗?谢谢
SNR = [-10:5:30]; %in Db
snr = 10 .^ (0.1 .* SNR);
for I = 1:length(snr)
noise = 1 / sqrt(2) * (randn(1, N) + 1i * randn(1, N));
u = y + noise .* snr(I);
end
【问题讨论】:
您可以查看在后台使用的awgn
和wgn
的所有代码:在命令窗口中输入edit awgn
或edit wgn
。
Steven,信号功率计算是否正确?如果您检查定义:gaussianwaves.com/2013/12/power-and-energy-of-a-signal 您将不会在那里找到 sqrt ...此外,如果没有 sqrt,您的公式和使用方差计算的信号功率是相同的(它们应该是)。
我有点困惑,因为有许多不同版本的向信号添加噪声。我不想使用awgn()
函数,仅基于理论想知道如何添加特定方差和特定信噪比值的复杂噪声。
【参考方案1】:
您可以使用 randn() 生成所需长度的噪声向量“awgnNoise”。然后,给定一个指定的 SNR 值,计算原始信号的功率和噪声矢量 'awgnNoise' 的功率。 为噪声矢量获取正确的幅度比例因子并对其进行缩放。
以下代码是一个用白噪声破坏信号的示例,假设输入信号是一维实数值。
function out_signal = addAWGN(signal, targetSNR)
sigLength = length(signal); % length
awgnNoise = randn(size(signal)); % orignal noise
pwrSig = sqrt(sum(signal.^2))/sigLength; % signal power
pwrNoise = sqrt(sum(awgnNoise.^2))/sigLength; % noise power
scaleFactor = (pwrSig/pwrNoise)/targetSNR; %find scale factor
awgnNoise = scaleFactor*awgnNoise;
out_signal = signal + awgnNoise; % add noise
如果您想分别生成实部和虚部,请在处理复数信号时注意 sqrt(2) 因子。
【讨论】:
忘记问了,如果您可以回复它-对于复杂的信号,您提到了 sqrt(2)。我应该如何处理我在问题中发布的方式?或者是其他东西?您能否也显示复杂信号?其次,我如何知道信号何时复杂? 是否复杂取决于您模拟中信号的物理含义,例如如果它是正交调制信号,它会很复杂。如果你的意思是在 matlab 中,你可以使用 isreal() 函数。 抱歉这么久又打扰你了。我早些时候运行了你的代码,当目标信噪比不为零 dB 时没有遇到问题。在变量 scaleFactor 中,你正在划分比率(powersignal 和 pwrNoise )由targetSNR。如果targetSNR=0,则scaleFactor将变为infty。通常,信号功率是固定的,我们希望生成具有targetSNR的输出。为什么我们要除以targetSNR?请你解释一下【参考方案2】:如果您添加一个条件来检查 targetSNR 是否为 0,并且仅当它不为 0 时才执行这些操作,则可以轻松解决“不应除以 0”的问题。当您的目标 SNR 为 0 时,这意味着它是纯噪声。
function out_signal = addAWGN(signal, targetSNR)
sigLength = length(signal); % length
awgnNoise = randn(size(signal)); % orignal noise
pwrSig = sqrt(sum(signal.^2))/sigLength; % signal power
pwrNoise = sqrt(sum(awgnNoise.^2))/sigLength; % noise power
if targetSNR ~= 0
scaleFactor = (pwrSig/pwrNoise)/targetSNR; %find scale factor
awgnNoise = scaleFactor*awgnNoise;
out_signal = signal + awgnNoise; % add noise
else
out_signal = awgnNoise; % noise only
end
【讨论】:
【参考方案3】:我正在添加另一个答案,因为我觉得 Steven 的答案并不完全正确,而 Horchler 建议查看函数 awgn
是一个很好的答案。
MATLAB 或 Octave(在通信工具箱中)都有一个函数 awgn
,它添加(高斯白)噪声以达到所需的信噪比功率水平;以下是代码的相关部分(来自 Octave 函数):
if (meas == 1) % <-- if using signal power to determine appropriate noise power
p = sum( abs( x(:)) .^ 2) / length(x(:));
if (strcmp(type,"dB"))
p = 10 * log10(p);
endif
endif
if (strcmp(type,"linear"))
np = p / snr;
else % <-- in dB
np = p - snr;
endif
y = x + wgn (m, n, np, 1, seed, type, out);
正如您在计算p
(输入数据的幂)的方式中看到的那样,Steven 的答案似乎并不完全正确。
您可以要求该函数计算数据阵列的总功率,并将其与您提供的所需信噪比值相结合,以计算添加噪声的适当功率水平。为此,您可以在可选输入中传递字符串“measured”,如下所示(请参阅 here 获取 Octave 文档或 here 获取 MATLAB 文档):
y = awgn (x, snr, 'measured')
这最终导致meas=1
和meas==1
在上面的代码中为真。函数awgn
然后使用传递给它的信号来计算信号功率,然后根据这个和所需的信噪比计算增加的噪声的适当功率电平。
正如文档进一步解释的那样
默认情况下,假定 snr 和 pwr 以 dB 和 dBW 为单位 分别。可以选择此默认行为,类型设置为 “D b”。在 type 设置为“linear”的情况下,假定 pwr 为 瓦特和信噪比是一个比率。
这意味着您可以传递负值或 0 dB 信噪比值。结果还取决于您传递的其他选项,例如字符串“measured”。
对于 MATLAB 案例,我建议阅读 documentation,它解释了如何在不同场景中使用函数 awgn
。请注意,Octave 和 MATLAB 中的实现并不相同,噪声功率的计算应该相同,但可能有不同的选项。
这是来自wgn
的相关部分(上面由awgn
调用):
if (strcmp(type,"dBW"))
np = 10 ^ (p/10);
elseif (strcmp(type,"dBm"))
np = 10 ^((p - 30)/10);
elseif (strcmp(type,"linear"))
np = p;
endif
if(!isempty(seed))
randn("state",seed);
endif
if (strcmp(out,"complex"))
y = (sqrt(imp*np/2))*(randn(m,n)+1i*randn(m,n)); % imp=1 assuming impedance is 1 Ohm
else
y = (sqrt(imp*np))*randn(m,n);
endif
如果您想检查噪声的功率 (np
),awgn
和 awg
函数假定以下关系成立:
np = var(y,1); % linear scale
np = 10*log10(np); % in dB
其中var(...,1)
是噪声y
的总体 方差。
【讨论】:
感谢您再次查看此问题。我不太了解如何应用变量 meas(它在哪里使用)。此外,这如何处理负和零 SNR?比如说,如果 SNR = -10 作为数字或 SNR = 0 ? @SKM 请查看补充说明 @SKM 还添加了关于功率和真实/复杂数据关系的更正。【参考方案4】:这里的大多数答案都忘记了 SNR 以分贝为单位。因此,您不应该遇到“除以 0”错误,因为您实际上应该除以 10^(targetSNR/10)
,对于真正的 targetSNR
,它永远不会是负数也不为零。
【讨论】:
以上是关于为信号添加噪声的正确方法的主要内容,如果未能解决你的问题,请参考以下文章