Эффективный метод интерполяции тепловой карты - PullRequest
3 голосов
/ 19 января 2012

Я пишу программу, которая создает визуальное представление температуры.В сетке размещено 200 точек данных, и я использую интерполяцию для заполнения пикселей между этими точками.

Я написал программу, которая выводит данные, которые я хочу, используя обратное взвешивание расстояния (в данном случае модифицированный метод Шепардса), давая изображение, как показано ниже:

heatmaphttp://img688.imageshack.us/img688/1069/stackoverflowimage.png

Со всеми несущественными элементами (такими как элементы библиотеки изображений) код для их создания показан ниже:

Во-первых, все расстояния и суммарные расстояния от каждой точки до каждой трубкирассчитываются (потому что они инвариантны).В этом бите меня не особо беспокоит время, затрачиваемое только потому, что оно выполняется только один раз, но я включаю код, чтобы вы могли видеть, как хранятся значения.

#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 Ответ

1 голос
/ 19 января 2012

Есть одно изменение, которое может быть улучшением:

Попробуйте переместить 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) , что означает, что здесь, вероятно, мало что оптимизировано Посмотрите историю изменений, если вам интересно, что я написал.

...