数字化模拟信号

10 投票
4 回答
8255 浏览
提问于 2025-04-17 17:18

我有一组CSV格式的值,这些值代表一个数字信号。它是通过模拟示波器收集的,所以信号并不是完美的数字信号。我想对这些数据进行过滤,以得到一个完美的数字信号,这样我就可以计算周期(周期可能会有所不同)。我还想定义一下在这个过滤过程中可能出现的最大误差。

大概是这样的:

这里输入图片描述

想法

对数据应用一个阈值。这里有一段伪代码:

for data_point_raw in data_array:
    if data_point_raw < 0.8: data_point_perfect = LOW
    if data_point_raw > 2  : data_point_perfect = HIGH

else:
    #area between thresholds
    if previous_data_point_perfect == Low : data_point_perfect = LOW
    if previous_data_point_perfect == HIGH: data_point_perfect = HIGH

我有两个问题困扰着我。

  1. 这似乎是数字信号处理中的一个常见问题,但我没有找到一个预定义的标准函数来处理它。这种过滤方法可以吗?
  2. 我该如何计算出最大误差呢?

4 个回答

1

你的过滤方法没问题,基本上和施密特触发器是一样的,但你可能会遇到速度方面的问题。使用Numpy的好处是,它的速度可以和C语言一样快,而你需要逐个处理每个元素。

你可以使用SciPy中的中值滤波器来实现类似的效果。下面的代码应该能达到相似的结果(而且不受任何大小的影响):

filtered = scipy.signal.medfilt(raw)
filtered = numpy.where(filtered > numpy.mean(filtered), 1, 0)

你可以通过medfilt(raw, n_samples)来调整中值滤波的强度,n_samples的默认值是3。

至于误差,这个会很主观。一个方法是先对信号进行离散化,不进行过滤,然后比较差异。例如:

discrete = numpy.where(raw > numpy.mean(raw), 1, 0)
errors = np.count_nonzero(filtered != discrete)
error_rate = errors / len(discrete)
2

这不是对你问题的回答,只是一个可能有帮助的建议。我在这里写这个是因为我不能在评论里放图片。

我觉得你应该先对数据进行归一化处理,才能进行后续的处理。

在把数据归一化到0到1的范围后,你再应用你的过滤器。

在这里输入图片描述

7

这里有一段代码,可能对你有帮助。

from __future__ import division

import numpy as np


def find_transition_times(t, y, threshold):
    """
    Given the input signal `y` with samples at times `t`,
    find the times where `y` increases through the value `threshold`.

    `t` and `y` must be 1-D numpy arrays.

    Linear interpolation is used to estimate the time `t` between
    samples at which the transitions occur.
    """
    # Find where y crosses the threshold (increasing).
    lower = y < threshold
    higher = y >= threshold
    transition_indices = np.where(lower[:-1] & higher[1:])[0]

    # Linearly interpolate the time values where the transition occurs.
    t0 = t[transition_indices]
    t1 = t[transition_indices + 1]
    y0 = y[transition_indices]
    y1 = y[transition_indices + 1]
    slope = (y1 - y0) / (t1 - t0)
    transition_times = t0 + (threshold - y0) / slope

    return transition_times


def periods(t, y, threshold):
    """
    Given the input signal `y` with samples at times `t`,
    find the time periods between the times at which the
    signal `y` increases through the value `threshold`.

    `t` and `y` must be 1-D numpy arrays.
    """
    transition_times = find_transition_times(t, y, threshold)
    deltas = np.diff(transition_times)
    return deltas


if __name__ == "__main__":
    import matplotlib.pyplot as plt

    # Time samples
    t = np.linspace(0, 50, 501)
    # Use a noisy time to generate a noisy y.
    tn = t + 0.05 * np.random.rand(t.size)
    y = 0.6 * ( 1 + np.sin(tn) + (1./3) * np.sin(3*tn) + (1./5) * np.sin(5*tn) +
               (1./7) * np.sin(7*tn) + (1./9) * np.sin(9*tn))

    threshold = 0.5
    deltas = periods(t, y, threshold)
    print("Measured periods at threshold %g:" % threshold)
    print(deltas)
    print("Min:  %.5g" % deltas.min())
    print("Max:  %.5g" % deltas.max())
    print("Mean: %.5g" % deltas.mean())
    print("Std dev: %.5g" % deltas.std())

    trans_times = find_transition_times(t, y, threshold)

    plt.plot(t, y)
    plt.plot(trans_times, threshold * np.ones_like(trans_times), 'ro-')
    plt.show()

运行后的结果是:

Measured periods at threshold 0.5:
[ 6.29283207  6.29118893  6.27425846  6.29580066  6.28310224  6.30335003]
Min:  6.2743
Max:  6.3034
Mean: 6.2901
Std dev: 0.0092793

图表

你可以使用 numpy.histogram 和/或 matplotlib.pyplot.hist 来进一步分析 periods(t, y, threshold) 返回的数组。

撰写回答