为信号添加噪声的正确方法

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

【问题讨论】:

您可以查看在后台使用的awgnwgn 的所有代码:在命令窗口中输入edit awgnedit 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=1meas==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),awgnawg 函数假定以下关系成立:

  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,它永远不会是负数也不为零。

【讨论】:

以上是关于为信号添加噪声的正确方法的主要内容,如果未能解决你的问题,请参考以下文章

Python-给图像添加椒盐噪声和高斯噪声

OpenCV给图像添加噪声

如何正确地给图像添加高斯噪声

基于MATLAB给数据点添加高斯噪声

基于MATLAB给数据点添加高斯噪声

怎么用matlab给声音加入噪音?