Слишком медленная обработка изображений на Python с PIL + NumPy

Пытаюсь реализовать простейший blur-фильтр на питоне:

import os, sys, time
import Image, ImageEnhance
import numpy as np

if (len(sys.argv) > 1):
    im = Image.open(sys.argv[1])
    data = np.array(im.resize((128,128)))
    out_data = np.array(data)
    chs = len(data[0][0])
    im_size = (data.shape[0], data.shape[1])

    #defining filter kernel (mask)
    #let's believe it's square anytime
    kernel = np.array([[1.,2,1],
                       [2,3,2],
                       [1,2,1]])
    ctr = 1
    ker_size = kernel.shape[0]
    kernel = kernel/np.sum(kernel)

    #let's go looping!
    start_time = time.time()
    #loop over image dimensions
    for x in xrange(im_size[0]):
        for y in xrange(im_size[1]):
            #loop over channels
            for c in xrange(chs):
                acc = 0
                #loop over kernel
                for i in xrange(ker_size):
                    for j in xrange(ker_size):
                        m = x + i - ctr
                        n = y + j - ctr
                        if (m >= 0 and n >= 0 and m < im_size[0] and n < im_size[1]):
                            acc += data[m][n][c]*kernel[i][j]
                out_data[x][y][c] = acc
    elapsed = time.time() - start_time

    #it's over, let's do the rest
    out = Image.new(im.mode, (im_size[0], im_size[1]))
    out = Image.fromarray(out_data)
    out.show()
    print elapsed, "sec."
else:
    print "no file was passed"


4 секунды на 128х128 RGB изображении. Так не должно быть! =)
Я знаю, что мне поможет многопоточность и параллелизация, но это не решение проблемы.
Где моя ошибка? Прошу о помощи.
  • Вопрос задан
  • 4013 просмотров
Пригласить эксперта
Ответы на вопрос 8
vit1251
@vit1251
Software Engineer
А вы пробывали отпрофилиировать ваше приложение где возникает проблема посмотреть?
Ответ написан
noonv
@noonv
гм… а может использовать функции C++, которые уже дёргать из питона?
Ответ написан
Amper
@Amper
Попробуйте так (сам не пробовал):
    r = range(ker_size)
    R = map(lambda i: map(lambda j: (i,j), r), r)
    for x, y in map(lambda x: map(lambda y: (x,y), im_size[1]), range(im_size[0])):
        #loop over channels
        for c in range(chs):
            acc = 0
            #loop over kernel
            a, b = y - ctr, x - ctr
            for i,j in R:
                n, m = a + j, b + i
                if 0 <= m < im_size[0] and 0 <= n < im_size[1]:
                    acc += data[m][n][c] * kernel[i][j]
            out_data[x][y][c] = acc
Ответ написан
Lerg
@Lerg
Defold, Corona, Lua, GameDev
Попробуйте воспользоваться psyco.
Ответ написан
vit1251
@vit1251
Software Engineer
а я все подумываю может GD собрать на выходных для Python. А то действительно PIL какой-то уж очень ИМХО тормозной.
Ответ написан
@tkirill128 Автор вопроса
отказался от numpy-массивов внутри циклов. 4 секунды превратились в 0.6 для 128х128 изображения.
но на 512х512 10.6 секунды. неприемлимо =/
Ответ написан
@radioxoma
А зачем? Кстати, в opencv они побыстрее будут.

P.S. И многопоточность вам не поможет.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы