从数字输入中滤除二进制数组中的短波动

问题描述 投票:0回答:1

我有一个 ttl 信号,表示为 0/1 值的数组。我想平滑任何值在很短的时间内变化的短峰值(例如,少于 4 个样本),我知道这是噪声。

例如,如果 4 是最小合法脉冲长度:

[0,0,0,0,0,0,1,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0,0,0,1,1,0,1,1,1,1,1,1] 

应该成为

[0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1] 

虽然大多数情况在主观上是显而易见的,但想出一个精确的替换规则似乎有点困难。一般来说,这并不是特别重要,只要不保留任何短期波动即可。

python signal-processing
1个回答
0
投票

您可以简单地遍历输入数组,形成另一个仅包含您想要的模式的数组。这将是一个相当简单的状态机,它只是“缓冲”它所经过的数组项,并清除任何遇到的短于四个项的运行,并将它们替换为零。

甚至可以使用正则表达式来完成,该正则表达式将输入数组视为字符串并用零替换短的一串。不过,这种方法可能效率较低。

这里的 PHP 代码演示了实现上述状态机的一种方法,其形式并未严格优化,但编写得易于理解:

define('SPIKE_LEN', 4);

$input  = [0,0,0,0,0,0,1,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0,0,0,1,1,0,1,1,1,1,1,1];
$output = [];

$count     = count($input);
$run_start = null;

for ($i = 0; $i < $count; ++$i) {
    $is_one = ($input[$i] == 1);
    $is_end = ($i == $count - 1);

    if ($is_one && is_null($run_start))
        $run_start = $i;

    elseif ($is_one && !is_null($run_start) && !$is_end)
        continue;

    elseif ((!$is_one && !is_null($run_start))
        || ($is_one && $is_end)) {

        if ($i - $run_start > SPIKE_LEN)
            for ($j = $run_start; $j <= $i; ++$j)
                $output[$j] = $input[$j];
        else    // spike
            for ($j = $run_start; $j <= $i; ++$j)
                $output[$j] = 0;

        $run_start = null;
    }

    elseif (!$is_one && is_null($run_start))
        $output[$i] = $input[$i];

    else    // shouldn't be reached
        die("Internal error at position {$i} out of {$count}, value is {$input[$i]}\n");
}

echo('Input:  ');
for ($i = 0; $i < $count; ++$i)
    echo("{$input[$i]} ");
echo("\n");

echo('Output: ');
for ($i = 0; $i < $count; ++$i)
    echo("{$output[$i]} ");
echo("\n");

这也是此代码生成的示例输出:

Input:  0 0 0 0 0 0 1 0 0 0 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 0 1 1 1 1 1 1 
Output: 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1
© www.soinside.com 2019 - 2024. All rights reserved.