窗口上的距离矩阵(通过访问周围的帧)

时间:2013-03-30 19:20:30

标签: numpy scipy distance

我是scipy的新手,最近了解了cdist我们可以传递自己的自定义函数来计算距离。但是,cdist仅计算各个点的距离(因此,自定义函数必须计算两点之间的距离)。这适用于大多数情况,但在我的情况下,距离是在一组点之间计算的。 (您可以将其视为滑动窗口,例如大小为3)。一个例子可以说明这一点:

def f(*a, **kw):
    print(a, kw)
    return 0

# Consider it a set of points: [p0, p1, p2, ...]
a = numpy.array([[1,2,3],[10,11,12],[20,21,22],[30,31,32]]) 

# Consider it a set of points: [q0, q1, q2, ...]
b = numpy.array([[4,5,6],[14,15,16],[24,25,26],[34,35,36],[44,45,46]])

现在,如果我只是scipy.spatial.distance.cdist(a, b, f),则每次调用f时,每个数组中只有1个条目传递给f。所以函数调用(和传递的值)看起来像:

1st call: p0, q0
2nd call: p0, q1
3rd call: p0, q2
4th call: p0, q3
5th call: p0, q4 <-- 
6th call: p1, q0
7th call: p1, q1
...and so on...

但我想要的是(对于3号窗口):

1st call: [p0,p1,p2], [q0,q1,q2]
2nd call: [p0,p1,p2], [q1,q2,q3]
3rd call: [p0,p1,p2], [q2,q3,q4] <-- only till boundary
4th call: [p1,p2,p3], [q0,q1,q2]
5th call: [p1,p2,p3], [q1,q2,q3]
...and so on...

我搜索了很多,并且还尝试了scipy的generic filtercorrelation functions,但他们没有提供这种功能(据我所知)。是否有任何方式来计算距离,如上所述?

欢迎任何想法/建议。 感谢

1 个答案:

答案 0 :(得分:1)

由于您想要计算所有距离,并且您正在使用自定义函数,因此使用cdist时除了方便之外可能没有多大优势。

首先,您需要隐藏您的积分,我建议您使用as_strided

import numpy as np
from numpy.lib.stride_tricks import as_strided

p = np.random.rand(4, 3)
q = np.random.rand(6, 3)
win = 3
win_p = as_strided(p, shape=(p.shape[0]-win+1, win)+p.shape[1:],
                   strides=p.strides[:1]*2+p.strides[1:])
win_q = as_strided(q, shape=(q.shape[0]-win+1, win)+q.shape[1:],
                   strides=q.strides[:1]*2+q.strides[1:])

现在:

>>> p
array([[ 0.8962062 ,  0.62471689,  0.1754708 ],
       [ 0.69104294,  0.66960955,  0.97012228],
       [ 0.32023353,  0.08146304,  0.7663883 ],
       [ 0.06276952,  0.1679428 ,  0.9419452 ]])
>>> win_p
array([[[ 0.8962062 ,  0.62471689,  0.1754708 ],
        [ 0.69104294,  0.66960955,  0.97012228],
        [ 0.32023353,  0.08146304,  0.7663883 ]],

       [[ 0.69104294,  0.66960955,  0.97012228],
        [ 0.32023353,  0.08146304,  0.7663883 ],
        [ 0.06276952,  0.1679428 ,  0.9419452 ]]])

从这里你可以做到显而易见:

ps, qs = len(win_p), len(win_q)
dist = np.empty((ps, qs))
for j, pp in enumerate(win_p) :
    for k, qq in enumerate(win_q) :
        dist[j, k] = f(pp, qq)

正如我所说,如果你定义自己的距离函数,我认为这不会比cdist慢。

根据您的距离函数的样子,您可以尝试对事物进行矢量化。这可能涉及创建一个形状(ps, win, 3, qs, win, 3)的中间数组,因此很可能需要大量的内存。但是随意发布您测量距离的内容,我很乐意看看。