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