В этом примере показано, как использовать 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)
По умолчанию 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])
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')
То же средство записи отследило букву «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 секунды, чтобы произнести слово во фразе, подчеркивая второй слог («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')
soundsc(phrase(Nstride*istart-Nwindow/2 : Nstride*istop+Nwindow/2),fs)