【问题标题】:Isolating 'active' parts in signal隔离信号中的“活动”部分
【发布时间】:2019-11-07 09:46:07
【问题描述】:

我有一个数据集,其中包含来自按下按钮的信号。现在,在数据涵盖的整个时间段内,也存在噪音。数据本身只是一个向量,其中包含对应于正弦函数线性组合的数字。

我想隔离按下按钮的部分。所以我首先想到对噪声使用一定的阈值。噪声永远不会高于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,但我想通过一个变量来管理它,这样我就可以轻松地将逻辑分配为接下来的三十个条目,而不是三个。此外,这创建了正确的向量,但它不会继续运行代码并创建新向量。

【问题讨论】:

    标签: matlab signals signal-processing fft


    【解决方案1】:

    根据我对您所说的要求的理解,您的循环代码给出了错误的结果,即使对于给定的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 完全兼容。如果没有,请发表评论,我会尽力解决可能的问题。

    【讨论】:

    • 谢谢!对我来说非常好的和有用的代码。非常感谢。
    猜你喜欢
    • 1970-01-01
    • 2016-05-06
    • 1970-01-01
    • 1970-01-01
    • 2014-12-12
    • 1970-01-01
    • 2020-05-23
    • 2015-12-14
    • 2016-11-27
    相关资源
    最近更新 更多