Выделение «активных» частей в сигнале - PullRequest
0 голосов
/ 07 ноября 2019

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

Я хочу выделить части, где нажата кнопка. Поэтому я сначала подумал использовать определенный порог для шума. Шум никогда не бывает выше 0.4, поэтому это будет хорошим порогом. Поэтому я планирую создать новые векторы, каждый из которых будет содержать данные из временного периода, когда нажата одна кнопка, но я не могу понять, как это сделать.

Я считаю, что мне нужен код, который проходит по вектору, который проверяет, преодолен ли порог 0.4, и затем сохраняет данные в новом векторе, пока, по крайней мере, x многие записи снова не окажутся ниже порогового значения.

Будет ли эта идея работать? И я понятия не имею, как начать эту проверку, любая помощь приветствуется.

Просто для информации: в конце я хочу извлечь синусоидальные функции, используя fft, но без использования signal processing toolbox.

РЕДАКТИРОВАТЬ

Теперь я создал (частично) рабочий код:

z= [0 0.1 0.4 0.2 0.8 0.3 0.6 0.3 0.3 0.2 0.1 0.2 0.0 0.3 0.4 0.5 0.6 0.3 0.3 0.2 0.1 0.0];
zN = length(z);
y=[;];
m=0;
j=0;
i=1;
while i < zN
    if z(i) >= 0.4
        m=m+1;
        k=0;
        for j = i:zN
            k=k+1;
            y(m,k) = z(j);
            if z(j) <0.4 && z(j+1)<0.4 && z(j+2)<0.4
                i=i+j+3;
                break
            end
        end
    end
i=i+1;    
end

Это, как мы надеемся, возвращаетматрица y=[0.4 0.2 0.8 0.3 0.6 0.3; 0.4 0.5 0.6 0.3 0 0]. Но для меня это выглядит очень некрасиво и не очень читабельно. Кроме того, я теперь вручную назначил, что следующие три записи должны быть ниже 0.4, но я хотел бы управлять этим с помощью переменной, чтобы я мог так же легко назначить логику для следующих тридцати записей вместо трех. Кроме того, это создало правильный вектор, но он не продолжает работать над кодом и создавать новые векторы.

1 Ответ

1 голос
/ 08 ноября 2019

Исходя из моего понимания требований, которые вы указали, код вашего цикла дает неправильные результаты даже для заданного z. Запустив ваш код для данного z, мы получим:

y =
   0.40000   0.20000   0.80000   0.30000   0.60000   0.30000
   0.40000   0.50000   0.60000   0.30000   0.00000   0.00000

Но, по крайней мере, насколько я понимаю, первый «активный интервал» должен быть:

   0.40000   0.20000   0.80000   0.30000   0.60000   0.30000   0.30000   0.20000

Здесь выполняется требование, чтобы три последовательных значения были ниже порогового значения, что не относится к вашему результату y.

Я не хотел исправлять ваш цикл for, и так как вы попросили некоторыедругой подход, ниже будет моим решением. Если он «читаемый» или «некрасивый», зависит от читателя. Я пытался прокомментировать каждую строку. Кроме того, вы можете проверить все промежуточные результаты, чтобы лучше понять идею и функционирование.

z = [0.0 0.1 0.4 0.2 0.8 0.3 0.6 0.3 0.3 0.2 0.1 ...
     0.2 0.0 0.3 0.4 0.5 0.6 0.3 0.3 0.2 0.1 0.0]; 

% Threshold
thr = 0.4;

% Successor threshold
nSucc = 3;

% Find indices, where z >= threshold ("overshoot")
idxOver = find(z >= thr);

% Calculate distances between these overshoots
distOver = diff(idxOver);

% Distances below successor threshold are considered to belong 
% to the same active interval; split active intervals where
% successor threshold is exceeded
idxSplitItv = find(distOver > nSucc);

% Determine starts and ends of the active intervals
idxActiveS = idxOver([1, idxSplitItv+1]);
idxActiveE = idxOver([idxSplitItv, numel(idxOver)]) + nSucc;
nActive = numel(idxActiveS);

% If end of last interval would exceed length of z, ignore
if (idxActiveE(end) > numel(z))
  x = 1:nActive-1;
else
  x = 1:nActive;
end

% Get all active intervals
yy = arrayfun(@(x) z(idxActiveS(x):idxActiveE(x)), x.', 'UniformOutput', false)

Для заданного z мы получаем:

yy =
{
  [1,1] =
     0.40000   0.20000   0.80000   0.30000   0.60000   0.30000   0.30000   0.20000

  [2,1] =
     0.40000   0.50000   0.60000   0.30000   0.30000   0.20000
}

, поскольку «активные интервалы» могутменяя длины, я решил использовать массивы ячеек для вывода. Обратите внимание: arrayfun - это просто какой-то замаскированный цикл, так что цикл для последнего шага тоже будет в порядке.

Если мы сократим три последних элемента из z, так что не будет действительного второго "«активный интервал» (меньше трех последовательных значений ниже порога), мы правильно получим:

yy =
{
  [1,1] =
     0.40000   0.20000   0.80000   0.30000   0.60000   0.30000   0.30000   0.20000
}

С другой стороны, если мы установим nSucc = 10, то есть нам нужно как минимум десять последовательных значений ниже порога, мы получаем:

yy = {}(0x1)

То есть, потому что в данном z.

нет такого интервала, надеюсь, это поможет!

Отказ от ответственности: Я тестировал кодс Octave 5.1.0, но я совершенно уверен, что он должен быть полностью MATLAB-совместимым. Если нет, пожалуйста, оставьте комментарий, и я постараюсь исправить возможные проблемы.

...