web-dev-qa-db-ja.com

信号にノイズを追加する適切な方法

多くの分野で、ノイズを追加しながら、平均値や分散などの仕様について言及しました。 DbでSWが変化するAWGN、カラーノイズ、均一ノイズを追加する必要があります。次のコードは、ノイズを生成して追加する方法を示しています。私は関数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
10
SKM

Stevenの答えが正確ではなく、関数awgnの内部を調べるというHorchlerの提案は良いものだと思うので、別の答えを追加します。

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からの答えは完全に正しいようには見えません。

データ配列の合計電力を計算するように関数に要求し、追加したノイズの適切な電力レベルを計算するために提供する目的のs/n値とそれを組み合わせることができます。これを行うには、次のように、オプションの入力の間に文字列 "measured"を渡します(Octaveドキュメンテーションについては here を、MATLABドキュメンテーションについては here を参照してください)。

_     y = awgn (x, snr, 'measured')
_

これは最終的に_meas=1_につながるため、上記のコードでは_meas==1_がtrueになります。関数awgnは、渡された信号を使用して信号電力を計算し、これと目的のs/nから、追加されたノイズの適切な電力レベルを計算します。

ドキュメントがさらに説明するように

デフォルトでは、snrとpwrはそれぞれdBとdBWであると見なされます。このデフォルトの動作は、タイプを「dB」に設定して選択できます。タイプが「線形」に設定されている場合、pwrはワットであると想定され、snrは比率です。

つまり、負または0 dBのsnr値を渡すことができます。結果は、「measured」という文字列など、渡す他のオプションにも依存します。

documentation を読むことをお勧めするMATLABのケースでは、さまざまなシナリオで関数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)は、ノイズypopulation分散です。

8
Buck Thorn

ここでのほとんどの回答は、SNRがデシベルで指定されていることを忘れています。したがって、実際にtargetSNRに対して負でもゼロでもない10^(targetSNR/10)で実際に除算する必要があるため、「0による除算」エラーは発生しません。

3
programagor

Randn()を使用して、必要な長さのノイズベクトル「awgnNoise」を生成できます。次に、指定されたSNR値を指定して、元の信号のパワーとノイズベクトル 'awgnNoise'のパワーを計算します。ノイズベクトルの適切な振幅スケーリング係数を取得し、スケーリングします。

次のコードは、入力信号が1Dで実数値であると想定して、信号をホワイトノイズで破損させる例です。

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

実数部分とimag部分を別々に生成する場合は、複雑な信号を処理するときにsqrt(2)係数に注意してください。

1
Steven

この「0で除算すべきではない」問題は、targetSNRが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
1
Steven