Можно ли оптимизировать этот код обработки изображений, чтобы использовать меньше памяти? - PullRequest
1 голос
/ 27 июля 2010

У меня есть функция python, которая принимает строковое s-выражение типа «(add (sub 10 5) 5)», где «add» и «sub» на самом деле являются функциями обработки изображения, а также оценивает и создает изображение, представленное встрока.Функции обработки изображений принимают константы, переменные или другие изображения (представленные в виде списков векторов) и возвращают изображения, представленные таким же образом.PIL используется для преобразования изображения, представленного в виде списка векторов, в файл изображения.

Чтобы оценить s-выражения префиксной нотации, я преобразовываю s-expr в список, обращаюсь к нему и перебираю токеныпока функция не найдена, в этот момент выполняется функция обработки изображения, и результирующее изображение заменяет функцию и ее аргументы в списке.Это делается до тех пор, пока в списке не останется только один элемент, который является окончательным изображением.

Функции обработки изображения просты - большинство выполняет некоторую математическую операцию с каждым из значений (r, g, b) вthe image (s).

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

def createImage(self, sexpr, filename, (picWidth, picHeight)):
    """Use the image processing functions in ImgProcessing
       to create an image from the procedural information
       contained in the s-expression."""

    img = Image.new("RGB",(picWidth,picHeight),(255,255,255))
    ip = ImgProcessing(picWidth,picHeight)

    # Split s-expression into list of tokens and reverse
    sList = sexpr.replace("(","").replace(")","").split()
    sList.reverse()

    while len(sList) > 1:

        for index,token in enumerate(sList):
            # If token is an image processing function
            if type(token) == str and self.FuncSet.has_key(token):
                # If this function takes one argument
                if self.FuncSet[token] == 1:
                    rawImage = eval("ip." + token + "(" + "\"" + str(sList[index-1]) +
                                    "\"" + ")")
                    sList = sList[:index-1] + [rawImage] + sList[index+1:]
                    break
                # If this function takes two arguments
                elif self.FuncSet[token] == 2:
                    rawImage = eval("ip." + token + "(" + "\"" + str(sList[index-1]) +
                                    "\"" + "," + "\"" + str(sList[index-2]) + "\"" +
                                    ")")
                    sList = sList[:index-2] + [rawImage] + sList[index+1:]
                    break

    img.putdata(sList[0])
    img.save(filename)

Ответы [ 2 ]

2 голосов
/ 27 июля 2010

Профилирование может сказать вам, где программа проводит большую часть своего времени.

Во-вторых, str(sList[index-1]) преобразует Image в строку? ip.token(...) возвращает изображение? Если это так, вы конвертируете строку и изображение несколько раз. Это может быть очень медленно.

Это может помочь изменить

rawImage = eval("ip." + token + "(" + "\"" + str(sList[index-1]) +
                                    "\"" + ")")

к чему-то вроде

getattr(ip,token)(sList[index-1])

но, конечно, это зависит от того, какой тип аргумента ip.token ожидает. Я не смог найти информацию о ImgProcessing от Google. Это пользовательский класс? Если так, это может помочь объяснить больше о том, как это работает. Если ip.token можно изменить с получения строк на получение изображений, это может быть большим улучшением.

0 голосов
/ 27 июля 2010

По моему опыту, все, что вы делаете в чистом Python или PIL попиксельно на большом изображении, будет медленным, как патока в январе.Подумайте о переносе низкоуровневого материала в расширение Python, написанное на C. Я использовал OpenCV, но это требует некоторого изучения.

...