web-dev-qa-db-fra.com

Moyen approprié d'ajouter du bruit au signal

Dans de nombreux domaines, j'ai constaté qu'en ajoutant du bruit, nous mentionnons certaines spécifications comme la moyenne zéro et la variance. J'ai besoin d'ajouter AWGN, un bruit coloré, un bruit uniforme de SNR variable en Db. Le code suivant montre comment j'ai généré et ajouté du bruit. Je connais la fonction awgn() mais c'est une sorte de boîte noire sans savoir comment le bruit est ajouté. Alors, quelqu'un peut-il expliquer la bonne façon de générer et d'ajouter du bruit. Je vous remercie

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

J'ajoute une autre réponse car il me semble que Steven n'est pas tout à fait correct et la suggestion de Horchler de regarder à l'intérieur de la fonction awgn est une bonne.

MATLAB ou Octave (dans la boîte à outils de communication) ont une fonction awgn qui ajoute du bruit (blanc gaussien) pour atteindre le niveau de puissance signal/bruit souhaité; ce qui suit est la partie pertinente du code (de la fonction 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);

Comme vous pouvez le voir par la façon dont p (la puissance des données d'entrée) est calculée, la réponse de Steven ne semble pas être tout à fait juste.

Vous pouvez demander à la fonction de calculer la puissance totale de votre réseau de données et de la combiner avec la valeur s/n souhaitée que vous fournissez pour calculer le niveau de puissance approprié du bruit ajouté. Pour ce faire, passez la chaîne "mesurée" parmi les entrées optionnelles, comme ceci (voir ici pour la documentation Octave ou ici pour la documentation MATLAB):

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

Cela conduit finalement à meas=1 Et donc meas==1 À vrai dans le code ci-dessus. La fonction awgn utilise ensuite le signal qui lui est transmis pour calculer la puissance du signal, et à partir de cela et du s/n souhaité, elle calcule ensuite le niveau de puissance approprié pour le bruit ajouté.

Comme l'explique la documentation

Par défaut, le snr et le pwr sont supposés être respectivement en dB et dBW. Ce comportement par défaut peut être choisi avec un type défini sur "dB". Dans le cas où le type est défini sur "linéaire", pwr est supposé être en watts et snr est un rapport.

Cela signifie que vous pouvez passer une valeur snr négative ou 0 dB. Le résultat dépendra alors également des autres options que vous passerez, comme la chaîne "mesurée".

Pour le cas MATLAB, je suggère de lire le documentation , il explique comment utiliser la fonction awgn dans différents scénarios. Notez que les implémentations dans Octave et MATLAB ne sont pas identiques, le calcul de la puissance de bruit doit être le même mais il peut y avoir différentes options.

Et voici la partie pertinente de wgn (appelée ci-dessus par 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

Si vous souhaitez vérifier la puissance de votre bruit (np), les fonctions awgn et awg supposent les relations suivantes:

  np = var(y,1);        % linear scale
  np = 10*log10(np);    % in dB 

var(...,1) est la variance population pour le bruit y.

8
Buck Thorn

La plupart des réponses ici oublient que le SNR est spécifié en décibels. Par conséquent, vous ne devriez pas rencontrer d'erreur "division par 0", car vous devez vraiment diviser par 10^(targetSNR/10) qui n'est jamais négatif ni nul pour le vrai targetSNR.

3
programagor

Vous pouvez utiliser randn () pour générer un vecteur de bruit "awgnNoise" de la longueur souhaitée. Puis, étant donné une valeur SNR spécifiée, calculez la puissance du signal d'origine et la puissance du vecteur de bruit "awgnNoise". Obtenez le bon facteur d'échelle d'amplitude pour le vecteur de bruit et mettez-le à l'échelle.

Le code suivant est un exemple de corruption de signal avec du bruit blanc, en supposant que le signal d'entrée est 1D et réel.

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

Faites attention au facteur sqrt (2) lorsque vous traitez un signal complexe, si vous voulez générer séparément la partie réelle et imagée.

1
Steven

Ce problème "ne devrait pas diviser par 0" pourrait être facilement résolu si vous ajoutez une condition pour vérifier si targetSNR est 0 et ne le faites que s'il n'est pas 0. Lorsque votre SNR cible est 0, cela signifie que c'est du bruit pur.

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