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