简体   繁体   English

如何确定“振荡”轨迹的幅度和频率

[英]How to determine the amplitude and the frequency of an “oscillating” trajectory

This is the trajectory of a pedestrian moving in jam 这是行人在果酱中移动的轨迹 在此输入图像描述

As you can see, his/her head perform an oscillation-like movement. 如你所见,他/她的头部表现出类似振荡的运动。 So not a perfect sinus curve but neither a line. 所以不是一个完美的正弦曲线,但不是一条线。

Is it possible to define for this irregular curve an "amplitude" and a "frequency"? 是否有可能为这条不规则曲线定义“幅度”和“频率”?

UPDATE : 更新

So far I tried two different approaches: 到目前为止我尝试了两种不同的方法

  1. The first one is based on calculating the turning points and then make a spline with them. 第一个是基于计算转折点,然后用它们制作样条曲线。
  2. The second approach is based on the suggestion of unutbu and uses the Ramer-Douglas-Peucker algorithm. 第二种方法基于unutbu的建议,并使用Ramer-Douglas-Peucker算法。

The results are as follows: 结果如下:

在此输入图像描述

The problem that I see with the RDP is the free parameter dist . 我在RDP中看到的问题是自由参数dist low values (means more details) imply oscillations in the resulting trajectories. 低值(意味着更多细节)意味着产生的轨迹中的振荡。 So I'm forced to be careful with this parameter. 所以我不得不小心这个参数。 Besides, the splin ed curve is much more smoother. 此外, splin ed曲线更加平滑。

What do you think? 你怎么看?

There is no absolute correct way to do this. 没有绝对正确的方法来做到这一点。 Below is just one way. 以下只是一种方式。

Let's start with the assumption/claim that people generally intend to walk in straight lines. 让我们从人们通常打算直线行走的假设/主张开始。 So you could use the Ramer-Douglas-Peucker algorithm to estimate the intended path of the person with a small set of line segments. 因此,您可以使用Ramer-Douglas-Peucker算法来估计具有一小组线段的人的预期路径。 (There is a Python implementation of the algorithm here .) (这里有算法Python实现 。)

Then generate the distances of the true data points from the line segments . 然后从线段生成真实数据点的距离

timeseries = []
for point in  points: 
    timeseries.append(
        min((distance between point and segment) 
             for segment in segments))

This array of distances is a timeseries. 这一系列距离是一个时间序列。 You could then take the root-mean-squared of the timeseries as a measure of amplitude, and take a Fourier transform to find its dominant frequency (or frequencies). 然后,您可以将时间序列的均方根作为幅度的度量,并进行傅立叶变换以找到其主要频率(或频率)。

Here is an update to RDP module you were linked to that should work with Python 3.x using Vectors: 以下是您链接到的RDP模块的更新,它应该使用向量与Python 3.x一起使用:

import functools

def autocast(function):
    @functools.wraps(function)
    def wrapper(self, other):
        if isinstance(other, self.__class__):
            if len(other) != len(self):
                raise ValueError('Object dimensions are not equivalent!')
            return function(self, other)
        return function(self, self.__class__(size=len(self), init=other))
    return wrapper

class Vector:

    __slots__ = '__data'

    def __init__(self, *args, size=0, init=0):
        self.__data = list(map(float, args if args else [init] * size))

    def __repr__(self):
        return self.__class__.__name__ + repr(tuple(self))

    @autocast
    def __cmp__(self, other):
        return (self.__data > other.__data) - (self.__data < other.__data)

    def __lt__(self, other):
        return self.__cmp__(other) < 0

    def __le__(self, other):
        return self.__cmp__(other) <= 0

    def __eq__(self, other):
        return self.__cmp__(other) == 0

    def __ne__(self, other):
        return self.__cmp__(other) != 0

    def __gt__(self, other):
        return self.__cmp__(other) > 0

    def __ge__(self, other):
        return self.__cmp__(other) >= 0

    def __bool__(self):
        return any(self)

    def __len__(self):
        return len(self.__data)

    def __getitem__(self, key):
        return self.__data[key]

    def __setitem__(self, key, value):
        self.__data[key] = float(value)

    def __delitem__(self, key):
        self[key] = 0

    def __iter__(self):
        return iter(self.__data)

    def __reversed__(self):
        return reversed(self.__data)

    def __contains__(self, item):
        return item in self.__data

    @autocast
    def __add__(self, other):
        return Vector(*(a + b for a, b in zip(self, other)))

    @autocast
    def __sub__(self, other):
        return Vector(*(a - b for a, b in zip(self, other)))

    @autocast
    def __mul__(self, other):
        return Vector(*(a * b for a, b in zip(self, other)))

    @autocast
    def __truediv__(self, other):
        return Vector(*(a / b for a, b in zip(self, other)))

    @autocast
    def __floordiv__(self, other):
        return Vector(*(a // b for a, b in zip(self, other)))

    @autocast
    def __mod__(self, other):
        return Vector(*(a % b for a, b in zip(self, other)))

    @autocast
    def __divmod__(self, other):
        result = tuple(divmod(a, b) for a, b in zip(self, other))
        return Vector(*(a for a, b in result)), Vector(*(b for a, b in result))

    @autocast
    def __pow__(self, other):
        return Vector(*(a ** b for a, b in zip(self, other)))

    @autocast
    def __radd__(self, other):
        return Vector(*(a + b for a, b in zip(other, self)))

    @autocast
    def __rsub__(self, other):
        return Vector(*(a - b for a, b in zip(other, self)))

    @autocast
    def __rmul__(self, other):
        return Vector(*(a * b for a, b in zip(other, self)))

    @autocast
    def __rtruediv__(self, other):
        return Vector(*(a / b for a, b in zip(other, self)))

    @autocast
    def __rfloordiv__(self, other):
        return Vector(*(a // b for a, b in zip(other, self)))

    @autocast
    def __rmod__(self, other):
        return Vector(*(a % b for a, b in zip(other, self)))

    @autocast
    def __rdivmod__(self, other):
        result = tuple(divmod(a, b) for a, b in zip(other, self))
        return Vector(*(a for a, b in result)), Vector(*(b for a, b in result))

    @autocast
    def __rpow__(self, other):
        return Vector(*(a ** b for a, b in zip(other, self)))

    @autocast
    def __iadd__(self, other):
        for key in range(len(self)):
            self[key] += other[key]
        return self

    @autocast
    def __isub__(self, other):
        for key in range(len(self)):
            self[key] -= other[key]
        return self

    @autocast
    def __imul__(self, other):
        for key in range(len(self)):
            self[key] *= other[key]
        return self

    @autocast
    def __itruediv__(self, other):
        for key in range(len(self)):
            self[key] /= other[key]
        return self

    @autocast
    def __ifloordiv__(self, other):
        for key in range(len(self)):
            self[key] //= other[key]
        return self

    @autocast
    def __imod__(self, other):
        for key in range(len(self)):
            self[key] %= other[key]
        return self

    @autocast
    def __ipow__(self, other):
        for key in range(len(self)):
            self[key] **= other[key]
        return self

    def __neg__(self):
        return Vector(*(-value for value in self))

    def __pos__(self):
        return Vector(*(+value for value in self))

    def __abs__(self):
        return Vector(*(abs(value) for value in self))

    def __get_magnitude(self):
        return sum(value ** 2 for value in self) ** 0.5

    def __set_magnitude(self, value):
        self *= value / self.magnitude

    magnitude = property(__get_magnitude, __set_magnitude)

###############################################################################

def point_line_distance(point, start, end):
    if start == end:
        return (point - start).magnitude
    es, sp = end - start, start - point
    return abs(es[0] * sp[1] - es[1] * sp[0]) / es.magnitude

def rdp(points, epsilon):
    dmax = index = 0
    start, *middle, end = points
    for i in range(1, len(points) - 1):
        d = point_line_distance(points[i], start, end)
        if d > dmax:
            index, dmax = i, d
    if dmax >= epsilon:
        return rdp(points[:index+1], epsilon)[:-1] + \
               rdp(points[index:], epsilon)
    return start, end

Similar to the demonstration given by the original module, the following is an example usage scenario: 与原始模块给出的演示类似,以下是一个示例使用场景:

>>> from pprint import pprint
>>> line = [Vector(0.0, 0.0),
            Vector(1.0, 0.0),
            Vector(2.0, 0.0),
            Vector(2.0, 1.0),
            Vector(2.0, 2.0),
            Vector(1.0, 2.0),
            Vector(0.0, 2.0),
            Vector(0.0, 1.0),
            Vector(0.0, 0.0)]
>>> pprint(rdp(line, 1.0))
(Vector(0.0, 0.0),
 Vector(2.0, 0.0),
 Vector(2.0, 2.0),
 Vector(0.0, 2.0),
 Vector(0.0, 0.0))
>>> 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何将正弦曲线图拟合到音频信号以确定 Python 中的频率和幅度? - How to fit a sinusoidal graph to an audio signal in order to determine frequency and amplitude in Python? PyAudio,如何在录制时分辨频率和幅度? - PyAudio, how to tell frequency and amplitude while recording? 如何在python中修改幅度、频率和带宽值 - How to modify amplitude, frequency and bandwidth values in python 如何从WAV文件获取振幅和频率列表 - How to get amplitude and frequency list from a wav file 如何从声音文件中获取幅度和频率? - How do I get the amplitude and frequency from a sound file? 如何获取在Python 3.x中记录的音频的频率和幅度? - How do I get the frequency and amplitude of audio that's being recorded in Python 3.x? 如何使用python绘制频谱或频率与整个音频文件的幅度的关系? - How to plot spectrum or frequency vs amplitude of entire audio file using python? 使用scipy.interpolate进行样条曲线表示:低振幅,快速振荡函数的插值不良 - Spline representation with scipy.interpolate: Poor interpolation for low-amplitude, rapidly oscillating functions 通过fft查找WAV文件的频率幅度和相位 - find the frequency amplitude and phase of a wav file by fft 从 FFT 获取幅度最高的频率 - Get frequency with highest amplitude from FFT
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM