隔离信号中的 'active' 个部分
Isolating 'active' parts in signal
我有一个数据集,其中包含来自按下按钮的信号。现在在数据涵盖的整个时间段内,也有噪音。数据本身只是一个向量,其中包含对应于正弦函数线性组合的数字。
我想隔离按下按钮的部分。所以我首先想到对噪音使用一定的阈值。噪音永远不会高于 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
以下,但我想通过一个变量来管理它,这样我就可以轻松地将逻辑分配给接下来的三十个条目,而不仅仅是三。此外,这创建了正确的向量,但它不会继续 运行 遍历代码并创建新的向量。
根据我对您陈述的要求的理解,您的循环代码给出了错误的结果,即使对于给定的 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
但是,至少根据我的理解,第一个 "active interval" 应该是:
0.40000 0.20000 0.80000 0.30000 0.60000 0.30000 0.30000 0.20000
此处满足三个连续值低于阈值的要求,但您的结果并非如此 y
。
我不想更正您的 for 循环,并且由于您也要求了一些不同的方法,下面是我的解决方案。如果是 "readable" 或 "ugly",取决于 reader。我试着评论每一行。此外,您可以检查所有中间结果以进一步了解想法和功能。
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
}
由于 "active intervals" 可以有不同的长度,我决定使用元胞数组作为输出。注意:arrayfun
只是一些伪装的循环,所以最后一步的循环在这里也可以。
如果我们从 z
中删除最后三个元素,这样就没有有效的第二个 "active interval"(低于阈值的连续值少于三个),我们正确地得到:
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 兼容。如果没有,请发表评论,我会尽力解决可能出现的问题。
我有一个数据集,其中包含来自按下按钮的信号。现在在数据涵盖的整个时间段内,也有噪音。数据本身只是一个向量,其中包含对应于正弦函数线性组合的数字。
我想隔离按下按钮的部分。所以我首先想到对噪音使用一定的阈值。噪音永远不会高于 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
以下,但我想通过一个变量来管理它,这样我就可以轻松地将逻辑分配给接下来的三十个条目,而不仅仅是三。此外,这创建了正确的向量,但它不会继续 运行 遍历代码并创建新的向量。
根据我对您陈述的要求的理解,您的循环代码给出了错误的结果,即使对于给定的 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
但是,至少根据我的理解,第一个 "active interval" 应该是:
0.40000 0.20000 0.80000 0.30000 0.60000 0.30000 0.30000 0.20000
此处满足三个连续值低于阈值的要求,但您的结果并非如此 y
。
我不想更正您的 for 循环,并且由于您也要求了一些不同的方法,下面是我的解决方案。如果是 "readable" 或 "ugly",取决于 reader。我试着评论每一行。此外,您可以检查所有中间结果以进一步了解想法和功能。
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
}
由于 "active intervals" 可以有不同的长度,我决定使用元胞数组作为输出。注意:arrayfun
只是一些伪装的循环,所以最后一步的循环在这里也可以。
如果我们从 z
中删除最后三个元素,这样就没有有效的第二个 "active interval"(低于阈值的连续值少于三个),我们正确地得到:
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 兼容。如果没有,请发表评论,我会尽力解决可能出现的问题。