如何在 Python 中将 scipy.spatial.distance 替换为 np.linalg.norm



我正在按照本教程为我的项目实现对象跟踪 - https://www.pyimagesearch.com/2018/07/23/simple-object-tracking-with-opencv/

方法是在初始帧中查找检测到的对象的质心,然后计算到下一帧中显示的检测到的对象的其他质心的最短距离。假设最接近的质心将是同一个对象。

在教程中 -

from scipy.spatial import distance as dist
...
D = dist.cdist(np.array(objectCentroids), newCentroids)

用于计算距离(欧氏距离)。不幸的是,我无法使用 scipy 模块,因为我正在尝试将其部署到 AWS Lambda(大小限制)。在这种情况下,建议使用此 - https://docs.scipy.org/doc/numpy/reference/generated/numpy.linalg.norm.html

D = np.linalg.norm(objectCentroids – newCentroids)

这样做的问题是,与dist.cdist不同, 计算所有和任何矩阵,np.linalg.norm只输出 1 个值,这是在从 objectCentroids 矩阵中减去 newCentroids 后计算的。我即将循环 n 次(无论矩阵有多大)并附加到另一个矩阵以构建我需要的结果。但是,我不确定我对这个概念的理解是否正确,所以我想寻求一些帮助。如果有人知道更好的方法,我将不胜感激任何指示。

更新

根据我得到的反馈/答案,我稍微更新了代码,嗯......它似乎正在工作 -

n = arrayObjectCentroids.shape[0]
m = inputCentroids.shape[0]
T = []
for i in range(0,n):
for z in range(0,m):
Tv = np.linalg.norm(arrayObjectCentroids[i] - inputCentroids[z])
# print(f'Tv is n {Tv}')
T = np.append(T, Tv)
# print(f'T is n {T}')
print(f'new T is n {T}')   
D = np.reshape(T, (n, m))
print(f'D is n {D}')

在这种情况下,如果有一个物体并且移动了一点——

新质心是[[224 86]],它的形状是(1,2)... 对象质心是[[224 86]],形状对象质心是(1,2)

D 为[[0.]]

如果我有 3 个对象,-

新质心是

[[228  79]
[ 45 127]
[103 123]]

输入质心的形状为 (3, 2)

对象质心是

[[228  79]
[ 45 127]
[103 123]]

形状对象质心是 (3, 2)

D 是

[[  0.         189.19038031 132.51792332]
[189.19038031   0.          58.13776741]
[132.51792332  58.13776741   0.        ]]

太好了,它有效,但我觉得这可能不是最好的解决方案,如果您有任何指示,我将不胜感激! 谢谢!

编辑:编辑代码以解决下面的注释

如果在您的情况下,您在欧几里得空间中有向量,那么np.linalg.norm将返回该向量的长度。

因此objectCentroid – newCentroid将为您提供objectCentroid点和newCentroid点之间的向量。请注意,它介于 2 点之间,而不是包含所有点的数组。

为了获得我使用的所有点组合itertools然后重新塑造数组以提供与dist相同的输出

import numpy as np
from scipy.spatial import distance as dist
import itertools
# Example data
objectCentroids = np.array([[0,0,0],[1,1,1],[2,2,2], [3,3,3]])
newCentroids    = np.array([[4,4,4],[5,5,5],[6,6,6],[7,7,7]])
comb            = list(itertools.product(objectCentroids, newCentroids))
all_dist        = [] 
for pair in comb:
dis = np.linalg.norm((pair[0] - pair[1]))
all_dist.append(dis)
all_dist = np.reshape(all_dist, (len(objectCentroids), len(objectCentroids)))
D        = dist.cdist(objectCentroids, newCentroids)   
print(D)
print(" ")
print(all_dist)

您可以使用 Numpy 广播来创建距离矩阵。

在这里和这里阅读它。

基本思想是:

将质心堆叠(重塑)为(1, n, 3),并(n, 1, 3)形状为 3 的最后一个维度(x,y,z)。然后减去数组并使用np.linalg.norm计算沿轴的距离......嗯......可能是最后一个。这应该产生一个方形(n,n)距离矩阵。

最新更新