3

これは、ジャムで移動する歩行者の軌跡です。 ここに画像の説明を入力してください

ご覧のとおり、彼/彼女の頭は振動のような動きをします。したがって、完全な正弦曲線ではなく、線でもありません。

この不規則な曲線に対して「振幅」と「周波数」を定義することは可能ですか?

更新

これまでのところ、2つの異なるアプローチを試しました。

  1. 1つ目は、ターニングポイントを計算し、それらを使用してスプラインを作成することに基づいています。
  2. 2番目のアプローチは、unutbuの提案に基づいており、Ramer-Douglas-Peuckerアルゴリズムを使用します。

結果は次のとおりです。

ここに画像の説明を入力してください

RDPで見られる問題は、自由パラメーターdistです。低い値(より詳細を意味する)は、結果として生じる軌道の振動を意味します。したがって、このパラメータには注意する必要があります。その上、splined曲線ははるかに滑らかです。

どう思いますか?

4

2 に答える 2

6

これを行うための絶対的な正しい方法はありません。以下は一方向です。

人々は一般的に直線で歩くことを意図しているという仮定/主張から始めましょう。したがって、Ramer-Douglas-Peuckerアルゴリズムを使用して、線分の小さなセットで人の意図したパスを推定できます。(ここにアルゴリズムのPython実装があります。)

次に、線分から真のデータポイントの距離を生成します。

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

この距離の配列は時系列です。次に、振幅の尺度として時系列の二乗平均平方根を取り、フーリエ変換を行ってその支配的な周波数を見つけることができます。

于 2012-12-03T21:19:38.210 に答える
1

これは、ベクターを使用してPython3.xで動作するはずのリンク先のRDPモジュールの更新です。

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

元のモジュールによって提供されたデモンストレーションと同様に、以下は使用シナリオの例です。

>>> 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))
>>> 
于 2012-12-04T20:37:12.283 に答える