Форум сайта python.su
0
Доброго времени суток!
Я часто пишу на питоне экстракторы розничных графический форматов игр. Но вот скорость выполнения зачастую очень низкая. В результате выполнения мне нужно получать объект 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") # Готовое изображение
Отредактировано AlexL (Фев. 1, 2017 22:19:47)
Офлайн
253
AlexLТак вы покажите как вы это делали. Если так как у вас написано без numpy то конечно не будет ускорения.
Я пробовал использовать вместо списка rgb стандартную библиотеку array, а также numpy, но скорости это не прибавило
AlexL
В общем, как можно максимально ускорить работу стандартными методами?
Отредактировано AlexL (сегодня 18:46:58)
Офлайн
88
AlexLПопробуйте также Намбу.
Сейчас для ускорения я использую Cython, он существенно увеличивает скорость обработки данных. Слышал про библиотеку ctypes, но точного предназначения её так и не понял
Офлайн
35
Думаю, рабочий процесс должен быть приблизительно таким:
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 объект ..
В этом случае удается избежать циклов и все должно быть гораздо быстрее.
Офлайн
0
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") # Готовое изображение
Офлайн
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)
Офлайн
0
vic57
Спасибо!
Увы, в программе все изображения представлены в объектах PIL.Image. Переписывать всё нет желания.
Офлайн
AlexLя знаю bmp, png, jpeg чем от них PIL отличается?
Переписывать всё нет желания.
Офлайн
0
vic57
Вы перечислили стандартные форматы изображений. PIL (Pillow) - библиотека. Я изображения храню в памяти как объекты PIL.Image для последующей работы с ними.
PyQt - библиотека для создания графического интерфейса, которая немало весит. И использовать её только для работы с изображениями, мне кажется, нерационально. В качестве GUI я использую Tkinter.
Офлайн