我有一组(x,y)坐标点。我想要生成一个距离每个点的图像,因此我的简单函数如下:
from scipy.spatial.distance import cdist
from numpy import *
def findDistances(imageSize, points):
image = zeros(imageSize)
for x in range(0,imageSize[1]):
for y in range(0,imageSize[0]):
image[y,x] = np.min(cdist(array([[x,y]]), points))
return image
这个函数很好,它提供了我想要的结果(见下图)。对于一个大约1MP的图像,处理时间需要大约100秒,对于只需要一次处理的任务来说已经足够好了,但我认为还有改进的空间。我也尝试过:
image[y,x] = min(linalg.norm(array([[x,y]])- points, axis=1))
我认为这两者的运行时间相当 - 这很有道理,它们可能在内部执行类似的操作,尽管我没有检查源代码以确保。
我研究了Scipy的cKDTree:
from scipy.spatial import cKDTree
def findDistancesTree(imageSize, points):
tree = cKDTree(points)
image = zeros(imageSize)
for x in range(0,imageSize[1]):
for y in range(0,imageSize[0]):
image[y,x] = tree.query([x,y])[0]
return image
调用tree.query
大约需要50微秒(来自%timeit
),但实际上生成一张100万像素的距离图需要70-80秒。比起受到踢腿的打击,20秒的改进是好的,但我不知道是否可以进一步改进。
%timeit np.min(linalg.norm(array([[random.random()*1000,random.random()*1000]]) - points, axis=1))
%timeit np.min(cdist(array([[random.random()*1000,random.random()*1000]]), points))
%timeit tree.query(array([[random.random()*1000,random.random()*1000]]))
10000 loops, best of 3: 82.8 µs per loop
10000 loops, best of 3: 67.9 µs per loop
10000 loops, best of 3: 52.3 µs per loop
就复杂度而言,暴力搜索应该是类似于
O(NM)
的,其中 N
是图像中的像素数量,M
是要检查的点的数量。我原本期望速度会更快,因为对于每个像素来说,搜索时间应该是类似于 O(N log(M))
的,每次查找需要 log(M)
的时间 - 我有什么遗漏了吗?