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