Найти - Пользователи
Полная версия: Ускорение работы, оптимизация
Начало » Python для новичков » Ускорение работы, оптимизация
1 2
AlexL
Доброго времени суток!
Я часто пишу на питоне экстракторы розничных графический форматов игр. Но вот скорость выполнения зачастую очень низкая. В результате выполнения мне нужно получать объект PIL.Image.
Вот пример.
 def decode_image(f):
    
    def color(p):
        r = ((p >> 11) & 31) << 3
        g = ((p >> 5) & 63) << 2
        b = (p & 31) << 3
        return (r,g,b)
    
    rgb = []
    w,h = struct.unpack("HH", f.read(4))
    for i in range(w*h):
        p = color(struct.unpack("H", f.read(2))[0])
        rgb.extend(p)
    rgb = np.array(rgb, np.uint8).reshape(h, w, 3)
    image = Image.fromarray(rgb, "RGB") # Готовое изображение
Структура достаточно простая: сначала идут 8 байт на ширину и высоту, затем идут данные RGB, в которых цвет одного пикселя записан в двух байтах. Приходятся использовать библиотеку numpy, чтобы создать объект PIL.Image.
Я пробовал использовать вместо списка rgb стандартную библиотеку array, а также numpy, но скорости это не прибавило. Более того, стандартный список работает быстрее этих библиотек.
Сейчас для ускорения я использую Cython, он существенно увеличивает скорость обработки данных. Слышал про библиотеку ctypes, но точного предназначения её так и не понял. Может быть, с помощью неё можно как-то ускорить процесс?
В общем, как можно максимально ускорить работу стандартными методами?
doza_and
AlexL
Я пробовал использовать вместо списка rgb стандартную библиотеку array, а также numpy, но скорости это не прибавило
Так вы покажите как вы это делали. Если так как у вас написано без numpy то конечно не будет ускорения.
AlexL
В общем, как можно максимально ускорить работу стандартными методами?
Отредактировано AlexL (сегодня 18:46:58)

Про максимально не скажу. Это тема бесконечная. Суть в том что не надо использовать циклы, вместо них в numpy используйте векторные операции и будет вам счастье.
Shaman
AlexL
Сейчас для ускорения я использую Cython, он существенно увеличивает скорость обработки данных. Слышал про библиотеку ctypes, но точного предназначения её так и не понял
Попробуйте также Намбу.
scidam
Думаю, рабочий процесс должен быть приблизительно таким:
1) считываем w,h из файла
2) далее, читаем все что осталось и подаем это на вход функции numpy.frombuffer указывая, что тип получаемого массива должен быть unsign int: dtype = numpy.uint16
3) делаем reshape массива в соответствии с w,h
4) теперь выделям массивы R, G, B применяя ваши операции в функции color, т.е. если X – это созданных при помощи numpy.frombuffer массив, то: R = (X >> 11 &31) <<3 (в общем, как у вас), только теперь эти операции будут применять поэлементно ко всей матрице X
5) Получаем массивы R,G,B
6) используем функцию numpy.dstack чтобы из 3-х 2D массивов сделать 1 3D массив
7) создаем Image объект ..

В этом случае удается избежать циклов и все должно быть гораздо быстрее.
AlexL
scidam
Огромное спасибо за описание алгоритма, всё работает. Проверил на изображении 640x480:
Мой код: 0.450 sec
C использованием NumPy: 0.028
В 16 раз быстрее.
А как быть с RLE?
 def decode_image(f):
    rgb = []
    w,h = struct.unpack("HH", f.read(4))
    num = struct.unpack("I", f.read(4))[0] # Количество блоков
    
    for i in range(num):
        n = struct.unpack("I", f.read(4))[0]
        r,g,b = struct.unpack("3B", f.read(3))
        for j in range(n):
            rgb.extend((r,g,b))
    rgb = np.array(rgb, np.uint8).reshape(h, w, 3)
    image = Image.fromarray(rgb, "RGB") # Готовое изображение
Буду очень благодарен, если поможете ещё и с этим алгоритмом, т.к. большинство форматов основываются именно на RLE.
P.S. Кто-нибудь объясните, пожалуйста, вкратце, для чего библиотека ctypes? И может ли она помочь ускорить работу?
vic57
ctypes - подключение С-кода к python
https://habrahabr.ru/post/157537//
пишешь на С как shared и вызываешь где надо
PIL вообще-то заточен под работу с изображениями, а не с пикселями, типа осветлить, размыть
посмотри из PyQt QImage, QPixmap, QPainter, имхо может быть быстрее на уровне пикселов
http://doc.crossplatform.ru/qt/4.8.x/html-qt/examples-graphicsview.html
http://doc.crossplatform.ru/qt/4.8.x/html-qt/examples-painting.html
AlexL
vic57
Спасибо!
Увы, в программе все изображения представлены в объектах PIL.Image. Переписывать всё нет желания.
vic57
AlexL
Переписывать всё нет желания.
я знаю bmp, png, jpeg чем от них PIL отличается?
обработать можно любым методом и сохранить как PIL.Image()

AlexL
vic57
Вы перечислили стандартные форматы изображений. PIL (Pillow) - библиотека. Я изображения храню в памяти как объекты PIL.Image для последующей работы с ними.
PyQt - библиотека для создания графического интерфейса, которая немало весит. И использовать её только для работы с изображениями, мне кажется, нерационально. В качестве GUI я использую Tkinter.
vic57
ну дело хозяйское…
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB