2012-03-20 54 views
16

Tôi muốn chuyển đổi hình ảnh thành mảng NumPy thành PySide QPixmap, vì vậy tôi có thể hiển thị nó (EDIT: trong giao diện người dùng PySide của tôi). Tôi đã tìm thấy công cụ này: qimage2ndarray, nhưng nó chỉ hoạt động cho PyQt4. Tôi đã cố gắng thay đổi nó để làm cho nó hoạt động với PySide, nhưng tôi sẽ phải thay đổi phần C của công cụ và tôi không có kinh nghiệm với C. Làm thế nào tôi có thể làm điều này hoặc có bất kỳ lựa chọn thay thế?Chuyển mảng numpy sang PySide QPixmap

Trả lời

12

Một cách khác là chỉ sử dụng thư viện PIL.

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

Bạn có thể xem hàm tạo QPixmap tại http://www.pyside.org/docs/pyside/PySide/QtGui/QImage.html.

Dường như bạn sẽ có thể sử dụng một mảng NumPy trực tiếp trong các nhà xây dựng:

lớp PySide.QtGui.QImage (dữ liệu, chiều rộng, chiều cao, định dạng)

nơi đối số định dạng là một trong các đối số sau: http://www.pyside.org/docs/pyside/PySide/QtGui/QImage.html#PySide.QtGui.PySide.QtGui.QImage.Format.

Vì vậy, ví dụ bạn có thể làm một cái gì đó như:

>>> 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) 

Tôi không có PySide cài đặt vì vậy tôi đã không kiểm tra này. Rất có thể nó sẽ không hoạt động như vậy, nhưng nó có thể hướng dẫn bạn đi đúng hướng.

+0

Xin lỗi, tôi quên đề cập đến điều đó. Tôi muốn hiển thị hình ảnh trong giao diện người dùng PySide của tôi, vì vậy tiếc là tôi không thể làm điều đó theo cách đó. – AntonS

+0

Tôi đã thay đổi dòng thứ 2 thành 'b = (255 << 24 | a [:,:, 0] << 16 | a [:,:, 1] << 8 | a [:,:, 2])' va no đa hoạt động. Cảm ơn nhiều! – AntonS

+0

Giải pháp tuyệt vời! Để làm cho nó làm việc cho tôi, tôi cần phải thực hiện một thay đổi nhỏ và sử dụng PySide.QtGui.QImage.Format_ARGB32. Phần còn lại là như nhau. –

4

Ngoài @ user545424 câu trả lời về việc sử dụng PIL, nếu bạn không muốn phụ thuộc vào PIL, bạn có thể xây dựng hình ảnh của bạn trực tiếp từ mảng np của bạn:

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) 

Tôi chắc chắn, sử dụng PIL, có một cách để đọc dữ liệu hình ảnh thực tế vào một QImage, nhưng tôi sẽ để @ user545424 giải quyết một phần kể từ khi nó trả lời. PIL đi kèm với mô-đun ImageQt thuận tiện cho việc chuyển đổi trực tiếp hình ảnh -> QPixmap, nhưng không may là một PyQt4 QPixmap không hỗ trợ bạn.

+1

Cảm ơn, công trình này. Nhưng nó mất khoảng 3 giây, đó là cách quá chậm cho ứng dụng của tôi. – AntonS

+2

@AntonS Cũng có thể sử dụng 'ImageQt' với' PySide'. Bạn có thể viết 'sys.modules ['PyQt4'] = PySide' trước khi' import ImageQt'. Mã ví dụ: http://pastebin.com/DX2pbdpV. Nhưng tôi không biết cái gì nhanh hơn. – reclosedev

+0

Cảm ơn bạn rất nhiều! Điều này làm việc, nhưng mã user545425s là một chút nhanh hơn và không phụ thuộc vào PIL – AntonS

10

Nếu bạn tự tạo dữ liệu, sử dụng ví dụ, tôi nghĩ phương pháp nhanh nhất là truy cập trực tiếp vào QImage. Bạn có thể tạo một ndarray từ đối tượng buffer QImage.bits(), thực hiện một số công việc bằng cách sử dụng các phương thức numpy và tạo một QPixmap từ QImage khi bạn hoàn thành. Bạn cũng có thể đọc hoặc sửa đổi QImages hiện có theo cách đó.

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) 

Đảm bảo rằng mảng không vượt ra ngoài đối tượng hình ảnh. Nếu bạn muốn, bạn có thể sử dụng một dtype tinh vi hơn, giống như một mảng bản ghi để truy cập cá nhân vào các bit alpha, đỏ, xanh lá cây và xanh dương (hãy cẩn thận với endianess).

Trong trường hợp không có cách hiệu quả để tính toán giá trị pixel bằng cách sử dụng gọn gàng, bạn cũng có thể sử dụng scipy.weave để nội dòng một số mã C/C++ hoạt động trên mảng img.bits() trỏ tới.

Nếu bạn đã có hình ảnh ở định dạng ARGB, việc tạo QImage từ dữ liệu như được đề xuất trước đây có thể dễ dàng hơn.

Các vấn đề liên quan