Правильный способ добавления шума в сигнал

во многих областях я обнаружил, что при добавлении шума мы упоминаем некоторые спецификации, такие как нулевое среднее и дисперсия. Мне нужно добавить AWGN, цветной шум, равномерный шум различной SNR в Db. Следующий код показывает, как я создал и добавил шум. Я знаю о функции 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

4 ответов


я добавляю еще один ответ, поскольку мне кажется, что Стивен не совсем корректно и Хорхлер предложение заглянуть внутрь функции awgn - это хорошо.

либо MATLAB, либо Octave (в панели инструментов communications) имеют функцию awgn это добавляет (белый гауссовский) шум для достижения желаемого уровня мощности "сигнал-шум"; следующая соответствующая часть кода (из октавной функции):

  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 (the мощность входных данных) вычисляется, ответ от Стивена кажется не совсем правильным.

вы можете попросить функцию вычислить общую мощность вашего массива данных и объединить ее с желаемым значением s/n, которое вы предоставляете, чтобы вычислить соответствующий уровень мощности добавленного шума. Вы делаете это, передавая строку "measured" среди дополнительных входов, например (см. здесь для документации октавы или здесь для MATLAB документация):

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

это приводит в конечном счете к meas=1 и meas==1 быть истинным в коде выше. Функция awgn затем использует сигнал, переданный ему, чтобы вычислить мощность сигнала, и из этого и желаемого s/n он затем вычисляет соответствующий уровень мощности для добавленного шума.

как поясняется в документации

по умолчанию предполагается, что snr и pwr находятся в dB и dBW соответственно. Это поведение по умолчанию можно выбрать тип набора, чтобы "децибел." В случае, когда тип установлен в "линейный", pwr предполагается как в Ваттах и SNR-это соотношение.

это означает, что вы можете передать отрицательное или 0 dB snr значение. Результат также будет зависеть от других параметров, которые вы передаете, таких как строка "measured".

для случая 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) - это население дисперсия шума y.


большинство ответов здесь забывают, что SNR указан в децибелах. Поэтому вы не должны столкнуться с ошибкой "деление на 0", потому что вы действительно должны разделить на 10^(targetSNR/10) который никогда не отрицателен и не равен нулю для реального targetSNR.


вы можете использовать randn () для генерации вектора шума "awgnNoise" нужной длины. Затем, учитывая заданное значение SNR, вычислите мощность исходного сигнала и мощность вектора шума "awgnoise". Получите правильный коэффициент масштабирования амплитуды для вектора шума и просто масштабируйте его.

следующий код является примером поврежденного сигнала с белым шумом, предполагая, что входной сигнал 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

будьте осторожны с коэффициентом sqrt(2), когда вы имеете дело со сложным сигналом, если вы хотите создать реальной и мнимой частей отдельно.


эта проблема "не должна делиться на 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