[英]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: 到目前为止我尝试了两种不同的方法
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.