【问题标题】:Finding minimal jump zero crossings in numpy在numpy中找到最小的跳跃零交叉
【发布时间】:2019-10-09 17:44:36
【问题描述】:

对于数据分析任务,我想在一个 numpy 数组中找到零交叉点,该数组来自一个卷积,首先是一个类似 sobel 的内核,然后是一个墨西哥帽子内核。零交叉让我能够检测数据中的边缘。

不幸的是,数据有些嘈杂,我只想找到具有最小跳跃大小的零交叉点,20 在以下示例中:

import numpy as np
arr = np.array([12, 15, 9, 8, -1, 1, -12, -10, 10])

应该会导致

>>>array([1, 3, 7])

>>>array([3, 7])

其中3-1 的索引,就在第一次跳转中间之前,7-10 的索引

我尝试过修改以下代码(来源:Efficiently detect sign-changes in python

zero_crossings = np.where(np.diff(np.sign(np.trunc(arr/10))))[0]

正确地忽略了小跳跃,但将零交叉点放在[1,5,7]

这样做的有效方法是什么?

最小跳跃的定义并不严格,但结果应该与我的问题相符。

编辑:澄清

arr = np.array([12, 15, 9, 8, -1, 1, -12, -10, 10])
arr_floored = np.trunc(arr/10)
>>>>np.array([10, 10, 0, 0, 0, 0, -10, -10, 10])
sgn = np.sign(arr_floored)
>>>>array([ 1,  1,  0,  0,  0,  0, -1, -1,  1])
dsgn = np.diff(sgn)
>>>>array([ 0, -1,  0,  0,  0, -1,  0,  2])
np.where(dsgn)
>>>>(array([1, 5, 7], dtype=int64),)

进一步的边缘情况:

arr = [10,9,8,7,6,5,4,3,2,1,0,-1,-2,-3,-4,-5,-6,-7,-8,-9,-10]

应该会导致

>>> np.array([10])

还刚刚注意到:问题可能是不适定的(在数学意义上)。今天晚些时候我会澄清的。

【问题讨论】:

  • 你好,你说结果应该是array([3, 6]),但是3位置的跳转是从-1到1,所以相差不是20,这正常吗?也许更新您的问题来解释这一点?干杯
  • 最后一个索引不应该是7吗?
  • 是的,将编辑此内容

标签: python numpy signal-processing


【解决方案1】:

这是一个解决方案,它给出了涉及噪声阈值的交叉点的中点,以过滤跨多个数据点应用的可能在零附近的多个波动。它为您提供的两个示例提供了正确答案。 不过,我做了几个假设:

  • 您没有准确定义要考虑哪些数据点范围来确定交叉点的中点,但我使用了您的示例代码作为基础 - 它正在检测 ABS(start | end) >= 10 的交叉点,因此我使用了最小这个条件成立的范围。
    注意:这不会检测到从 +15 到 -6 的过渡。
    编辑:实际上它并不总是最小范围,但代码应该足以让您开始并根据需要进行调整.
  • 我假设也可以使用 pandas(跟踪感兴趣的数据点的索引)。如有必要,您可以避免使用熊猫。

import numpy as np import pandas as pd arr = np.array([12, 15, 9, 8, -1, 1, -12, -10, 10]) sgn = pd.Series(np.sign(np.trunc(arr/10))) trailingEdge = sgn[sgn!=0].diff() edgeIndex = np.array(trailingEdge[trailingEdge!=0].index) edgeIndex[:-1] + np.diff(edgeIndex) / 2

给予:

array([3., 7.])

arr = [10,9,8,7,6,5,4,3,2,1,0,-1,-2,-3,-4,-5,-6,-7,-8,-9,-10]

给予:

array([10.])

【讨论】:

  • 谢谢。熊猫很好。
【解决方案2】:

基本情况

我猜你想要

import numpy as np
x = np.array([10, -50, -30, 50, 10, 3, -200, -12, 123])
indices = np.where(np.logical_and(np.abs(np.diff(x)) >= 20, np.diff(np.sign(x)) != 0))[0]

读作:索引,其中 ((x 的绝对差) 大于或等于 20) 和 (符号翻转)

返回

array([0, 2, 5, 7])

周期性信号

通常的 numpy 函数不包括这种情况。我建议通过 pad 函数在最后添加第一个元素:

import numpy as np
x = np.array([10, 5, 0, -5, -10])
x = np.pad(x, (0, 1), 'wrap')
indices = np.where(np.logical_and(np.abs(np.diff(x)) >= 20, np.diff(np.sign(x)) != 0))[0]

【讨论】:

  • 明天早上测试:)
  • [10,9,8,7,6,5,4,3,2,1,0,-1,-2,-3,-4,-5,-6,-7,-8,-9,-10]的情况如何?在 0 处应该正好有 1 个过零,因为这个向量的总差是 20。但是您的代码没有检测到任何。
  • 嗯...我认为可能不可能找到一种适用于您可能想到的所有情况的方法。为了使这种情况起作用,您需要进行某种下采样或等效操作,这必然会导致忽略此分辨率下的实际零跳
  • 我明白了,你的信号是周期性的。可悲的是,通常的 numpy 函数并没有真正涵盖这种情况。我想你需要一个额外的oneliner那里。原则上,有多种选择,具体取决于您需要的性能。此外,过零不应该在 0,因为跳转 10->9 在这里不是过零。而是在 20 点。
  • 我用填充编辑了答案,这应该是最易读的方法
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-12-13
  • 2014-06-10
相关资源
最近更新 更多