高效插值热力图的方法

5
我正在编写一个程序,用于创建温度的可视化表示。有200个数据点布置在网格中,我使用插值方法填充这些点之间的像素。
我编写了一个程序,使用反距离加权法(在本例中是修改后的Shepards方法)输出所需的数据,生成如下图所示的图像:

heatmap

剔除所有不相关的内容(如图像库内容),以下是创建此内容的代码:

首先计算每个点到每个管道的距离和总距离(因为这些是不变的)。在这一部分,我并不特别担心所花费的时间,因为它只需要执行一次,但我包含了代码,以便您可以看到值是如何存储的。

#set_tubes creates an array of tubes (which is the data I'm working on)
#each tube has an x position in pixels, a y position in pixels and a temperature

self.set_tubes()
self.dists = []
for x in range(1,BASE_WIDTH-1):
    self.summed_dists.append([])
    self.dists.append([])
    for y in range(1,BASE_HEIGHT-1):
        self.summed_dists[x-1].append([])
        self.dists[x-1].append([])
        self.summed_dists[x-1][y-1]=0
        for row in range(10):
            self.dists[x-1][y-1].append([])
            for tube in range(20):
                dist = np.sqrt((x-self.tubes[row][tube].xPos)**2+(y-self.tubes[row][tube].yPos)**2)+0.1
                #The -3 in the next two lines is simply a weighting factor
                self.dists[x-1][y-1][row].append(dist**(-3))
                self.summed_dists[x-1][y-1] = self.summed_dists[x-1][y-1] + dist**(-3)

然后进行插值(随着温度的变化,这将重复进行)。这是时间成为关键因素的部分。
def other_proc_calc_temp(ret_queue, dists, tubes,summed_dists):
    heat_values = list()
    for x in range (BASE_WIDTH):
        heat_values.append([])
        for y in range(BASE_HEIGHT):
            summed = 0
            for row in range(10):
                for tube in range(20):
                    dist = dists[x][y][row][tube]
                    temp = tubes[row][tube].temp
                    summed = summed + temp* dist/summed_dists[x-1][y-1]
            heat_values[x].append(summed)

我的问题在于速度,对于一个200*200像素的图像,在我的电脑上运行第二部分代码大约需要30秒。有没有更快的方法来实现相同或类似的效果,或者我的代码存在明显的低效率?
我尝试了双线性和双三次插值,但对得到的图像并不满意。
我还限制了影响单个像素的数据点邻域,以试图加快速度,这确实有所帮助,但我认为我已经推到了极限,否则图像会出现明显的线条。
感谢您能提供的任何帮助。

1
最好看看是否可以使用numpy来完成这个任务。否则,可以考虑使用cython。 - John La Rooy
1个回答

1

有一个改变可能会更好:

尝试将dists[x][y]tubes[row]移动到最内层的循环之外。 这样做可以减少每个内部迭代的数组索引查找次数(这取决于Python解释器的聪明程度):

def other_proc_calc_temp(ret_queue, dists, tubes,summed_dists):
    heat_values = list()
    for x in range (BASE_WIDTH):
        heat_values.append([])
        for y in range(BASE_HEIGHT):
            outer_dist = dists[x][y]
            summed = 0
            for row in range(10):
                inner_dist = outer_dist[row]
                inner_tube = tubes[row]
                for tube in range(20):
                    dist = inner_dist[tube]
                    temp = inner_tubes[tube].temp
                    summed = summed + temp* dist/summed_dists[x-1][y-1]
            heat_values[x].append(summed)

如果Python解释器足够聪明,知道这些值没有改变,那么这只是更难阅读而已。但是,如果Python解释器一遍又一遍地重新计算所有这些数组索引,它可能会累加。

我曾经在这里写过一段关于预先设置数组大小而不是使用.append()来增长它们的段落。gnibbler说.append()是一个O(1)摊销操作 这意味着这里可能没有太多的优化可用。如果您想知道我写了什么,请查看编辑历史记录。


list.append() 是一种平摊时间复杂度为 O(1) 的操作。 - John La Rooy
@gnibbler:谢谢。我希望API文档能够更容易地提供更多语言的信息。长而明显毫无意义的段落已被删除。 :) - sarnold

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接