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

Этот пример показывает, как использовать 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)