2012-03-20 2 views
16

Я хочу преобразовать изображение в массив NumPy в PySide QPixmap, поэтому я могу его отобразить (EDIT: в моем пользовательском интерфейсе PySide). Я уже нашел этот инструмент: qimage2ndarray, но он работает только для PyQt4. Я попытался изменить его, чтобы заставить его работать с PySide, но мне пришлось бы изменить часть C инструмента, и у меня нет опыта работы с C. Как я могу это сделать или есть какие-то альтернативы?Преобразование массива numpy в PySide QPixmap

ответ

12

Один из вариантов - просто использовать библиотеку PIL.

>>> import numpy as np 
>>> import Image 
>>> im = Image.fromarray(np.random.randint(0,256,size=(100,100,3)).astype(np.uint8)) 
>>> im.show() 

Вы можете посмотреть на конструктор QPixmap на http://www.pyside.org/docs/pyside/PySide/QtGui/QImage.html.

Похоже, что вы должны быть в состоянии использовать Numpy массив непосредственно в конструкторе:

класс PySide.QtGui.QImage (данные, ширина, высота, форма)

где аргумент формата является одним из следующих: http://www.pyside.org/docs/pyside/PySide/QtGui/QImage.html#PySide.QtGui.PySide.QtGui.QImage.Format.

Так, например, вы могли бы сделать что-то вроде:

>>> a = np.random.randint(0,256,size=(100,100,3)).astype(np.uint32) 
>>> b = (255 << 24 | a[:,:,0] << 16 | a[:,:,1] << 8 | a[:,:,2]).flatten() # pack RGB values 
>>> im = PySide.QtGui.QImage(b, 100, 100, PySide.QtGui.QImage.Format_RGB32) 

я не имею PySide установлен таким образом, я не проверял это. Скорее всего, он не будет работать так, как есть, но он может помочь вам в правильном направлении.

+0

Извините, я забыл упомянуть об этом. Я хочу отобразить изображение в моем пользовательском интерфейсе PySide, так что, к сожалению, я не могу это сделать. – AntonS

+0

Я изменил вторую строку на 'b = (255 << 24 | a [:,:, 0] << 16 | a [:,:, 1] << 8 | a [:,:, 2])' и это сработало. Большое спасибо! – AntonS

+0

Отличное решение! Чтобы он работал для меня, мне нужно было внести небольшие изменения и использовать PySide.QtGui.QImage.Format_ARGB32. Остальное - то же самое. –

4

В дополнение к @ user545424 ответа об использовании PIL, если вы не хотите, чтобы зависеть от PIL, вы можете вручную построить свой образ прямо с вашего массива нп:

width = 100 
height = 100 
data = np.random.randint(0,256,size=(width,height,3)).astype(np.uint8) 

img = QtGui.QImage(width, height, QtGui.QImage.Format_RGB32) 
for x in xrange(width): 
    for y in xrange(height): 
     img.setPixel(x, y, QtGui.QColor(*data[x][y]).rgb()) 

pix = QtGui.QPixmap.fromImage(img) 

Я уверен, используя PIL, есть способ прочитать фактические данные изображения в QImage, но я позволю @ user545424 адресовать эту часть с момента его ответа. PIL поставляется с модулем ImageQt, который удобен для прямого преобразования изображения -> QPixmap, но, к сожалению, это PyQt4 QPixmap, который вам не поможет.

+1

Спасибо, это работает. Но это занимает около 3 секунд, что слишком медленно для моего приложения. – AntonS

+2

@AntonS Также можно использовать 'ImageQt' с' PySide'. Вы можете написать 'sys.modules ['PyQt4'] = PySide' перед' import ImageQt'. Пример кода: http://pastebin.com/DX2pbdpV. Но я не знаю, что быстрее. – reclosedev

+0

Большое спасибо! Это сработало, но код user545425s немного быстрее и не зависит от PIL – AntonS

10

Если вы создаете данные самостоятельно, используя, например, numpy, самый быстрый способ - получить прямой доступ к QImage. Вы можете создать ndarray из объекта-буфера QImage.bits(), выполнить некоторую работу с использованием методов numpy и создать QPixmap из QImage, когда вы закончите. Вы также можете прочитать или изменить существующие QImages таким образом.

import numpy as np 
from PySide.QtGui import QImage 

img = QImage(30, 30, QImage.Format_RGB32) 
imgarr = np.ndarray(shape=(30,30), dtype=np.uint32, buffer=img.bits()) 

# qt write, numpy read 
img.setPixel(0, 0, 5) 
print "%x" % imgarr[0,0] 

# numpy write, qt read 
imgarr[0,1] = 0xff000006 
print "%x" % img.pixel(1,0) 

Убедитесь, что массив не пережил объект изображения. Если вы хотите, вы можете использовать более сложный тип dtype, например массив записей для индивидуального доступа к альфа-, красным, зеленым и синим битам (остерегайтесь endianess, хотя).

В случае, если нет эффективного способа вычисления значений пикселей с помощью numpy, вы также можете использовать scipy.weave для встраивания некоторого кода на C/C++, который работает с массивом img.bits().

Если у вас уже есть изображение в формате ARGB, создание QImage из данных, как было предложено ранее, возможно, проще.

Смежные вопросы