Нахождение сигнала в данных

В этом примере показано, как использовать findsignal найти изменяющийся во времени сигнал в ваших данных. Это включает примеры того, как найти точные и тесно соответствующие сигналы при помощи метрики расстояния, как компенсировать медленно смещение варьирования и использование динамической трансформации временной шкалы, чтобы допускать изменения выборки.

Нахождение точных совпадений

Когда вы хотите найти численно точные совпадения сигнала, можно использовать strfind выполнять соответствие.

Например, если у нас есть вектор данных:

data = [1 4 3 2 55 2 3 1 5 2 55 2 3 1 6 4 2 55 2 3 1 6 4 2];

и мы хотим найти местоположение сигнала:

signal = [55 2 3 1];

мы можем использовать strfind найти начальные значения индекса того, где сигнал существует в данных, пока сигнал и данные численно точны.

iStart = strfind(data,signal)
iStart = 1×3

     5    11    18

Нахождение самого близкого соответствия с сигналом

strfind работает хорошо на численно точные совпадения. Однако этот подход перестал работать, когда могут быть ошибки из-за шума квантования или других артефактов в вашем сигнале.

Например, если у вас есть sinewave:

data = sin(2*pi*(0:25)/16);

и вы хотите найти местоположение сигнала:

signal = cos(2*pi*(0:10)/16);

strfind не может определить местоположение синусоиды в данных, которые запускаются на пятой выборке:

iStart = strfind(data,signal)
iStart =

     []

strfind не может найти сигнал в данных, потому что, из-за ошибки округления, не все значения численно равны. Чтобы видеть это, вычтите данные из сигнала в соответствующей области.

data(5:15) - signal
ans = 1×11
10-15 ×

         0         0         0    0.0555    0.0612    0.0555         0    0.2220         0    0.2220         0

Существуют числовые различия на порядке 1e-15.

Чтобы исправить это, можно использовать findsignal, который значением по умолчанию развертывает сигнал через данные и вычисляет сумму различий в квадрате между сигналом и данными локально в каждом местоположении, ища самую низкую сумму.

Чтобы произвести график сигнала и данных, где лучшее местоположение соответствия подсвечено, можно вызвать findsignal можно следующим образом:

findsignal(data,signal)

Нахождение самых близких соответствий под порогом

findsignal по умолчанию всегда возвращает самое близкое соответствие сигнала с данными. Чтобы возвратить несколько соответствий, можно задать привязанный, максимальная сумма придала различию квадратную форму.

data = sin(2*pi*(0:100)/16);
signal = cos(2*pi*(0:10)/16);

findsignal(data,signal,'MaxDistance',1e-14)

findsignal возвращает соответствия в отсортированном порядке близости

[iStart, iStop, distance] = findsignal(data,signal,'MaxDistance',1e-14);
fprintf('iStart iStop  total squared distance\n')
iStart iStop  total squared distance
fprintf('%4i %5i     %.7g\n',[iStart; iStop; distance])
  37    47     0
  69    79     0
  85    95     0
   5    15     1.776357e-15
  21    31     1.776357e-15
  53    63     1.776357e-15

Поиск комплексной траектории сигнала со смещением варьирования

Этот следующий пример показывает, как использовать findsignal найти сигнал, который прослеживает известную траекторию. Файл "cursiveex.mat" содержит запись x-и y-положение совета пера, когда это проследило слово "фосфоресценция" на листке бумаги. X, y данные закодирован как действительные и мнимые компоненты комплексного сигнала, соответственно.

load cursiveex
plot(data)
xlabel('real')
ylabel('imag')

То же средство записи, прослеженное буква "p" как сигнал шаблона.

plot(signal)
title('signal')
xlabel('real')
ylabel('imag')

Можно найти первый "p" в данных довольно легко с помощью findsignal. Это вызвано тем, что значения сигнальной линии довольно хорошо в начале данных.

findsignal(data,signal)

Однако второй "p" имеет две характеристики, которые мешают findsignal идентифицировать: Это имеет значительное, но постоянное смещение из первой буквы, и части буквы чертились на различном уровне скорости, чем сигнал шаблона.

Если вы интересуетесь только соответствием с полной формой буквы, можно вычесть от оконного локального среднего значения и из и из элемента данных сигнала. Это позволяет вам смягчать последствие постоянных сдвигов.

Чтобы смягчить последствие различных скоростей, на которых чертятся буквы, можно использовать динамическую трансформацию временной шкалы, которая расширит или сигнал или данные к общей основе времени, когда это выполняет поиск:

findsignal(data,signal,'TimeAlignment','dtw', ...
               'Normalization','center', ...
               'NormalizationLength',600, ...
               'MaxNumSegments',2)

Нахождение растянутых во времени сигналов степени

Этот следующий пример показывает, как использовать findsignal найти местоположение произносимого слова во фразе.

Следующий файл содержит аудиозапись фразы: "Ускоряя темп разработки и науки" и отдельной аудиозаписи "разработки", на которой говорит тот же динамик.

load slogan
soundsc(phrase,fs)
soundsc(hotword,fs)

Тому же динамику свойственно варьироваться произношение отдельных произносимых слов в предложении или фразе. Докладчик в этом примере объявил "разработку" двумя различными способами: динамик занял примерно 0,5 секунды, чтобы произнести слово во фразе, подчеркивая второй слог ("разработка"); тот же динамик занял 0,75 секунды, чтобы произнести слово в изоляции, подчеркивая третий слог ("разработка").

Чтобы компенсировать эти локальные изменения и во время и в объем, можно использовать спектрограмму, чтобы сообщить о спектральном распределении электроэнергии, когда это развивается через время.

Чтобы начать, используйте спектрограмму с довольно крупным разрешением частоты. Это сделано, чтобы сознательно размыть узкополосные глоттальные импульсы речевого тракта, оставив только резонансы более широкой полосы устных и носовых полостей без помех. Это позволяет вам блокировать на разговорные гласные слова. Согласные (особенно plosives и фрикативные звуки) значительно больше затрудняют, чтобы идентифицировать спектрограммы использования. Код ниже вычисляет спектрограмму

Nwindow = 64;
Nstride = 8;
Beta = 64;

Noverlap = Nwindow - Nstride;
[~,~,~,PxxPhrase] = spectrogram(phrase, kaiser(Nwindow,Beta), Noverlap);
[~,~,~,PxxHotWord] = spectrogram(hotword, kaiser(Nwindow,Beta), Noverlap);

Теперь, когда у вас есть спектрограмма фразы и поискового слова, можно использовать динамическую трансформацию временной шкалы, чтобы составлять локальные изменения размера слова. Точно так же можно объяснить изменения степени при помощи нормализации степени в сочетании с симметричным расстоянием Kullback-Liebler.

[istart,istop] = findsignal(PxxPhrase, PxxHotWord, ...
    'Normalization','power','TimeAlignment','dtw','Metric','symmkl')
istart = 1144
istop = 1575

Постройте и проигрывайте идентифицированное слово.

findsignal(PxxPhrase, PxxHotWord, 'Normalization','power', ...
    'TimeAlignment','dtw','Metric','symmkl')

soundsc(phrase(Nstride*istart-Nwindow/2 : Nstride*istop+Nwindow/2),fs)