Уведомления

Группа в Telegram: @pythonsu

#1 Фев. 1, 2017 18:46:45

AlexL
Зарегистрирован: 2017-02-01
Сообщения: 6
Репутация: +  0  -
Профиль   Отправить e-mail  

Ускорение работы, оптимизация

Доброго времени суток!
Я часто пишу на питоне экстракторы розничных графический форматов игр. Но вот скорость выполнения зачастую очень низкая. В результате выполнения мне нужно получать объект 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, но точного предназначения её так и не понял. Может быть, с помощью неё можно как-то ускорить процесс?
В общем, как можно максимально ускорить работу стандартными методами?

Отредактировано AlexL (Фев. 1, 2017 22:19:47)

Офлайн

#2 Фев. 1, 2017 20:32:46

doza_and
От:
Зарегистрирован: 2010-08-15
Сообщения: 4138
Репутация: +  253  -
Профиль   Отправить e-mail  

Ускорение работы, оптимизация

AlexL
Я пробовал использовать вместо списка rgb стандартную библиотеку array, а также numpy, но скорости это не прибавило
Так вы покажите как вы это делали. Если так как у вас написано без numpy то конечно не будет ускорения.
AlexL
В общем, как можно максимально ускорить работу стандартными методами?
Отредактировано AlexL (сегодня 18:46:58)

Про максимально не скажу. Это тема бесконечная. Суть в том что не надо использовать циклы, вместо них в numpy используйте векторные операции и будет вам счастье.



Офлайн

#3 Фев. 1, 2017 21:07:12

Shaman
Зарегистрирован: 2013-03-15
Сообщения: 1369
Репутация: +  88  -
Профиль   Отправить e-mail  

Ускорение работы, оптимизация

AlexL
Сейчас для ускорения я использую Cython, он существенно увеличивает скорость обработки данных. Слышал про библиотеку ctypes, но точного предназначения её так и не понял
Попробуйте также Намбу.

Офлайн

#4 Фев. 2, 2017 05:07:04

scidam
Зарегистрирован: 2016-06-15
Сообщения: 288
Репутация: +  35  -
Профиль   Отправить e-mail  

Ускорение работы, оптимизация

Думаю, рабочий процесс должен быть приблизительно таким:
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 объект ..

В этом случае удается избежать циклов и все должно быть гораздо быстрее.

Офлайн

#5 Фев. 3, 2017 15:48:12

AlexL
Зарегистрирован: 2017-02-01
Сообщения: 6
Репутация: +  0  -
Профиль   Отправить e-mail  

Ускорение работы, оптимизация

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? И может ли она помочь ускорить работу?

Офлайн

#6 Фев. 3, 2017 18:11:20

vic57
Зарегистрирован: 2015-07-07
Сообщения: 913
Репутация: +  127  -
Профиль  

Ускорение работы, оптимизация

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

Отредактировано vic57 (Фев. 3, 2017 18:13:21)

Офлайн

#7 Фев. 3, 2017 18:48:36

AlexL
Зарегистрирован: 2017-02-01
Сообщения: 6
Репутация: +  0  -
Профиль   Отправить e-mail  

Ускорение работы, оптимизация

vic57
Спасибо!
Увы, в программе все изображения представлены в объектах PIL.Image. Переписывать всё нет желания.

Офлайн

#8 Фев. 3, 2017 19:05:44

vic57
Зарегистрирован: 2015-07-07
Сообщения: 913
Репутация: +  127  -
Профиль  

Ускорение работы, оптимизация

AlexL
Переписывать всё нет желания.
я знаю bmp, png, jpeg чем от них PIL отличается?
обработать можно любым методом и сохранить как PIL.Image()

Офлайн

#9 Фев. 3, 2017 22:58:29

AlexL
Зарегистрирован: 2017-02-01
Сообщения: 6
Репутация: +  0  -
Профиль   Отправить e-mail  

Ускорение работы, оптимизация

vic57
Вы перечислили стандартные форматы изображений. PIL (Pillow) - библиотека. Я изображения храню в памяти как объекты PIL.Image для последующей работы с ними.
PyQt - библиотека для создания графического интерфейса, которая немало весит. И использовать её только для работы с изображениями, мне кажется, нерационально. В качестве GUI я использую Tkinter.

Офлайн

#10 Фев. 3, 2017 23:53:44

vic57
Зарегистрирован: 2015-07-07
Сообщения: 913
Репутация: +  127  -
Профиль  

Ускорение работы, оптимизация

ну дело хозяйское…

Офлайн

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version