exponenta event banner

Поиск сигнала в данных

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

Например, при наличии синусоиды:

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)

Figure contains 2 axes. Axes 1 with title signal contains an object of type line. Axes 2 with title signal matches found: 1 contains 2 objects of type line. These objects represent data, signal.

Поиск ближайших совпадений под порогом

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

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

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

Figure contains 2 axes. Axes 1 with title signal contains an object of type line. Axes 2 with title signal matches found: 6 contains 2 objects of type line. These objects represent data, signals.

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])
  53    63     0
  69    79     0
  85    95     0
   5    15     1.776357e-15
  21    31     1.776357e-15
  37    47     1.776357e-15

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

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

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

Figure contains an axes. The axes contains an object of type line.

Тот же писатель отследил букву «p» как шаблонный сигнал.

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

Figure contains an axes. The axes with title signal contains an object of type line.

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

findsignal(data,signal)

Figure contains 2 axes. Axes 1 with title signal contains an object of type line. Axes 2 with title signal matches found: 1 contains 2 objects of type line.

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

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

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

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

Figure contains 2 axes. Axes 1 with title signal contains an object of type line. Axes 2 with title signal matches found: 2 contains 2 objects of type line.

Поиск растянутых по времени сигналов мощности

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

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

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

Один и тот же оратор обычно варьирует произношение отдельных произносимых слов в предложении или фразе. Говорящий в этом примере произносил «инженерный» двумя разными способами: Говорящему потребовалось примерно 0,5 секунды, чтобы произнести слово во фразе, подчеркнув второй слог («en-GIN-eer-ing»); этому же говорящему потребовалось 0,75 секунды, чтобы произнести слово изолированно, подчёркивая третий слог («en-gin-EER-ing»).

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

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

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

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

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

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

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

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

Figure contains 2 axes. Axes 1 with title signal contains an object of type image. Axes 2 with title signal matches found: 1 contains 3 objects of type image, patch.

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

См. также