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

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

См. также