用于scipy.spatial.distance.cdist
计算来自 2 个输入集合的每对点之间的距离。
import numpy as np
import scipy.spatial.distance as SSD
h, w = 40, 60
A = np.random.random((h, w))
B = np.random.random((h, w))
C = np.random.random((h, w))
M = np.array([A.mean(), B.mean(), C.mean()]) # means vector
covariance = np.cov([A.ravel(), B.ravel(), C.ravel()])
inv_cov = np.linalg.inv(covariance) # inv. covariance matrix
def orig(A, B, C, M, inv_cov):
h, w = A.shape
result = np.zeros_like(A, dtype='float64')
for i in range(h):
for j in range(w):
# array with particular pixels from each image
v = np.array([A[i, j], B[i, j], C[i, j]])
# calculate mahalanobis distance and insert value as a pixel
result[i, j] = SSD.mahalanobis(v, M, inv_cov)
return result
def using_cdist(A, B, C, M, inv_cov):
D = np.dstack([A, B, C]).reshape(-1, 3)
result = SSD.cdist(D, M[None, :], metric='mahalanobis', VI=inv_cov)
result = result.reshape(A.shape)
return result
expected = orig(A, B, C, M, inv_cov)
result = using_cdist(A, B, C, M, inv_cov)
assert np.allclose(result, expected)
即使对于三个小 (40x60) 图像,速度也快了using_cdist
约 285 倍:
In [49]: expected = orig(A, B, C, M, inv_cov)
In [76]: result = using_cdist(A, B, C, M, inv_cov)
In [78]: np.allclose(result, expected)
Out[78]: True
In [79]: %timeit orig(A, B, C, M, inv_cov)
10 loops, best of 3: 36.3 ms per loop
In [80]: %timeit using_cdist(A, B, C, M, inv_cov)
10000 loops, best of 3: 127 µs per loop