2

我需要能够根据数据的特征检测 (x, y) 数据列表的区域。一些示例数据显示在第一张图片中。现在,我需要能够找到黑色标记之间的区域(对不起质量差,imgur 的编辑器不是很准确)。不幸的是,每次收集这些数据时,由于长度和形状不同,问题变得复杂,如第二张图所示。从~98 到~85 的急剧下降是一致的,~1e-9 和~1.5e-9 之间的两个下降/两个峰值特征应该是相当一致的。

我的问题是,根据信号的特征检测信号中的事件的最佳方法是什么?如果我能把它分成三个标记的区域(开始到第一个标记,第一个到第二个标记,第二个标记到结束),那么我相信我可以扩展该方法来处理我更复杂的情况。

我以前解决过类似的问题,但是这个问题在从一组数据到另一组数据发生的变化量方面是独一无二的。上次我只是简单地写了一个手工算法来找到一个局部极值并用它来定位边缘,但我觉得这是一个相当丑陋和低效的解决方案,不能轻易重用。

我使用的是 Python 2.7.5,但理想情况下,这应该是一个与语言无关的解决方案,以便我可以在 VB.NET 等其他环境中实现它。

图像1

img2

4

2 回答 2

3

仅基于您发布的两个示例,我有几个不同的建议:阈值或模板匹配。

门槛

因为您提到信号中的垂直下降是相对恒定的,特别是对于您检测到的第一个事件,似乎您可以使用阈值方法,您可以将事件放置在第一次出现超过某个阈值的信号时兴趣。例如,放置第一个事件(在 Python 中,并假设您的测量数据存在于包含 xy 对的元组序列中):

def detect_onset_event(measurements):
    armed = False
    for offset, (timestamp, value) in enumerate(measurements):
        if value > 90:
            armed = True
        if armed and value < 85:
            return offset
    return -1  # failure condition, might want to raise ValueError()

因此,我们在信号高于 90 后降至低于 85 的第一个样本偏移处触发。

您可以为第二个事件做类似的事情,但看起来对那个事件很重要的信号电平可能不太明确。取决于您的应用和测量数据。这是一个很好的例子,说明阈值方法不太好——它们可能很脆弱并且依赖于硬编码的值。但是,如果您的测量非常有规律,那么这可以很好地工作,只需很少的编码工作。

模板

在这种方法中,您可以为每个感兴趣的信号事​​件创建一个模板,然后将模板与您的信号进行卷积以识别信号的相似区域。

import numpy

def detect_twopeak_event(measurements, template):
    data = numpy.asarray(measurements) # convert to numpy array
    activations = numpy.convolve(
        data[:, 1],  # convolve over all "value" elements
        template)
    return activations.argmax()

在这里,您需要创建构成您要检测的事件的样本测量值列表 - 例如,您可以从示例信号的两个峰值区域中提取测量值以用作模板。然后,通过将此模板与测量数据进行卷积,您将获得测量与模板的相似程度的指标。您可以只返回最佳匹配的索引(如上面的代码中所示)或将这些相似性估计传递给其他进程以选择“最佳”。

有很多方法可以创建模板,但我认为最有前途的方法之一是使用来自标记训练事件的一组邻域的平均值。也就是说,假设您有一个与给定事件发生的样本偏移配对的信号数据库。您可以通过平均围绕这些标记事件的窗口区域来创建模板:

def create_mean_template(signals, offsets, radius=20):
    w = numpy.hanning(2 * radius)
    return numpy.mean(
        [s[o-radius:o+radius] * w for s, o in zip(signals, offsets)],
        axis=0)

这已成功用于许多信号处理领域,如面部识别(例如,您可以通过对一组标记的眼睛周围的像素进行平均来为眼睛创建模板)。

模板方法开始失败的一个地方是,如果您的信号有很多看起来像模板的区域,但这些区域与您想要检测的事件不对应。处理这个问题很棘手,因此如果您的事件附近发生了独特的信号模式,则模板方法效果最好。

模板方法失败的另一种方式是,如果您的测量数据包含,例如,一个有趣的双峰区域,但出现的频率与您用作模板的样本不同。在这种情况下,您可以通过在时频域而不是时幅域中工作,使您的模板对轻微的频率变化更加稳健。在那里,无需制作与您感兴趣的幅度变化的时间模式相对应的 1D 模板,您可以对测量结果运行窗口 FFT,然后提出与 k 维频率变化相对应的 kD 模板。您感兴趣的事件周围的区域。

希望这些建议中的一些有用!

于 2013-08-12T20:30:12.523 回答
1

您可能可以使用具有 6 个以上状态的隐马尔可夫模型,我不是数学天才,所以我会使用具有离散状态的模型并将您的数据四舍五入到最接近的整数,我的模型看起来很相似:

状态 1:开始 blob(排放量在 97 左右) 状态 2:“下降”(排放量在 83 到 100 之间) 状态 3:有趣的东西(排放量在 82-86 之间) 状态 4:峰值(80-88) 状态 5:最后一个峰值( 80-94) 状态 6:基线 (87-85)

HMM 不是完美的工具,因为它们主要捕获每个州的排放范围,但它们擅长容忍更早或更晚出现的东西,因为它们只关心州之间的 p 值,因此

我希望这会有所帮助并且有意义

如果您超级懒惰,您可能只需手动标记 6 个光谱,然后相应地切割数据并计算每个状态的每个发射的 p 值。

#pseudo code
emissions = defaultdict(int) # with relevant labels initialized to 0
for state_lable, value in data:
    emissions[state_lable][value] += 1
# then normalize all states to 1 and voila you have a HMM

以上是超级简化的,但应该比你通常做的 if 语句更好,更健壮:)... HMM 通常也有一个转换矩阵,但是因为你的数据信号太强了,你可以“跳过” ' 那就是我的务实解决方案 :)

然后随后使用维特比路径标记您未来的所有实验

于 2013-08-12T20:00:17.313 回答