Ускорить дельта-фильтр в Python / Numpy - PullRequest
2 голосов
/ 08 февраля 2012

Я пишу декомпрессор, который (помимо прочего) должен применить дельта-фильтр к изображениям RGB.То есть читать изображения, где только первый пиксель является абсолютным (R1, G1, B1), а все остальные находятся в форме (R [n] -R [n-1], G [n] -G [n-1]], B [n] -B [n-1]) и преобразовать их в стандартный RGB.

Сейчас я использую numpy следующим образом:

rgb = numpy.fromstring(data, 'uint8')
components = rgb.reshape(3, -1, order='F')
filtered = numpy.cumsum(components, dtype='uint8', axis=1)
frame = numpy.reshape(filtered, -1, order='F')

Где

  • строка 1 создает одномерный массив исходного изображения;
  • строка 2 преобразует его в форму

    [[R1, R2, ..., Rn], [G1, G2, ..., Gn], [B1, B2, ..., Bn]]
    
  • строка 3выполняет фактическую фильтрацию

  • , строка 4 снова преобразует в 1D массив

Проблема в том, что он слишком медленный для моих нужд.Я профилировал его и обнаружил, что на изменение формы массива уходит достаточно времени.

Поэтому я задаюсь вопросом: есть ли способ избежать изменения формы или ускорить ее?

Примечания:

  • Я бы предпочел не писать для этого расширение C.
  • Я уже использую многопоточность

Ответы [ 2 ]

2 голосов
/ 08 февраля 2012

По какой-то причине я еще не понял, окончательное изменение вашего кода копирует данные.Этого можно избежать, используя C-порядок вместо Fortran-порядка:

rgb = numpy.fromstring(data, 'uint8')
components = rgb.reshape(-1, 3)
filtered = numpy.cumsum(components, dtype='uint8', axis=0)
frame = filtered.reshape(-1)
1 голос
/ 09 февраля 2012

Во-первых, когда вы читаете его, вы можете рассказать немного больше о типе, попробуйте:

rgb = numpy.fromstring(data, '3uint8')

Нет необходимости в изменении.

Далее, для больших операций, где выможет сойти с рук (и cumsum квалифицируется), использовать параметр out=, чтобы не перемещать данные ... все происходит на месте.Используйте:

rgb.cumsum(axis=0,out=rgb)

, если вы все еще хотите, чтобы он был сплющен:

rgb = rgb.ravel()
...