Python, вложенный в цикл for для объемных данных с тензорным значением

Используя упаковку ITK python, я читаю объем с тензорным значением. На каждом тензоре я выполняю такую ​​операцию:

image      = reader.Execute()
dimensions = image.GetSize()

for z in range ( 0, dimensions[2] ):
  for y in range ( 0, dimensions[1] ):
    for x in range ( 0, dimensions[0] ):      
      image[x,y,z] = function( image[x,y,z] )

Очевидно, что вложенные циклы for работают медленно при использовании Python. Однако я не могу решить эту проблему с помощью карт или понимания списка. Обратите внимание, что функция выполняется для списка из 9 значений, который представляет тензор 3x3.

У кого-нибудь есть предложение, как увеличить производительность? Возможно, операция сглаживания и ручная индексация результирующего списка?

Спасибо!


person Roy van Pelt    schedule 09.04.2013    source источник


Ответы (2)


Вы можете использовать itertools.product, но я бы профилировал, прежде чем предположить, что это на самом деле быстрее:

import itertools

xs = range(0, dimensions[0])
ys = range(0, dimensions[1])
zs = range(0, dimensions[2])

coords = itertools.product(xs, ys, zs)

for v in coords:
    image[v[0], v[1], v[2]] = function(image[v[0], v[1], v[2]])

Я предполагаю, что, к сожалению, любой цикл по пикселям изображения в Python будет невероятно медленным, и вам нужно будет каким-то образом выразить свою операцию без циклов, используя библиотеку изображений.

person japreiss    schedule 09.04.2013
comment
Спасибо за быстрый ответ. Быстрый грубый тест с настенными часами показывает, что он примерно в два раза быстрее. Это хорошее улучшение, но я надеялся на больший прирост производительности, так как имею дело с достаточно большим объемом (скажем, 128 в кубе). Все еще интересно, есть ли надежный подход в Python, или нам следует прибегнуть к C для этих вопросов. - person Roy van Pelt; 09.04.2013

После некоторых экспериментов я теперь использую компромисс между читабельностью и скоростью. Функция карты предлагает изящное решение, хотя и довольно медленное. Частично мой вопрос был рассмотрен в: Numpy: Beginner nditer

Вот моя текущая версия:

reader     = sitk.ImageFileReader()
reader.SetFileName ( tensorVolumePath )  

image      = reader.Execute()
dimes      = image.GetSize()
origin     = image.GetOrigin()    

values     = sitk.GetArrayFromImage( image )
valuesFlat = values.reshape(dims[0]*dims[1]*dims[2], 3, 3)  

arrayInv   = np.array(map(np.linalg.inv, valuesFlat))  

imageInv = sitk.GetImageFromArray( valuesFlat.reshape(dims[0], dims[1], dims[2], -1) )
imageInv.SetOrigin(origin)

writer = sitk.ImageFileWriter()
writer.SetFileName ( tensorVolumeInversePath )
writer.Execute ( imageInv );
person Roy van Pelt    schedule 06.05.2013