MagoNick
MagoNick

Reputation: 361

PyQt5 QImage from Numpy Array

Considering the following code

from PyQt5.QtWidgets import QMainWindow, QLabel, QSizePolicy, QApplication 
from PyQt5.QtGui import QPixmap, QImage                                
from PyQt5.QtCore import Qt                                                                                              
import numpy as np                                                     
import sys



class Test(QMainWindow):                                                                                                                                                                                       

 def __init__(self):                                                                                                                                                                                        
     super().__init__()                                                                                                                                                                                     
     self.initUI()                                                                                                                                                                                          

 def initUI(self):                                                                                                                                                                                          
     self.setGeometry(10,10,640, 400)                                                                                                                                                                       

     pixmap_label = QLabel()                                                                                                                                                                                
     pixmap_label.setSizePolicy(QSizePolicy.Ignored, QSizePolicy.Ignored)                                                                                                                                   
     pixmap_label.resize(640,400)                                                                                                                                                                           
     pixmap_label.setAlignment(Qt.AlignCenter)                                                                                                                                                              

     im_np = np.ones((1800,2880,3),dtype=uint8)                                                                                                                                                                                  
     im_np = np.transpose(im_np, (1,0,2))                                                                                                                                                                              
     qimage = QImage(im_np, im_np.shape[1], im_np.shape[0],                                                                                                                                                 
                     QImage.Format_RGB888)                                                                                                                                                                 
     pixmap = QPixmap(qimage)                                                                                                                                                                               
     pixmap = pixmap.scaled(640,400, Qt.KeepAspectRatio)                                                                                                                                                    
     pixmap_label.setPixmap(pixmap)                                                                                                                                                                         

     self.setCentralWidget(pixmap_label)                                                                                                                                                                    
     self.show()                                                                                                                                                                                            



def main():                                                                                                                                                                                                    
  app = QApplication(sys.argv)                                                                                                                                                                               
  win = Test()                                                                                                                                                                                               
  sys.exit(app.exec_())                                                                                                                                                                                      



if __name__=="__main__":                                                                                                                                                                                       
  main()  

I get the following error

TypeError: arguments did not match any overloaded call: QImage(): too many arguments QImage(QSize, QImage.Format): argument 1 has unexpected type 'numpy.ndarray' QImage(int, int, QImage.Format): argument 1 has unexpected type 'numpy.ndarray' QImage(bytes, int, int, QImage.Format): argument 1 has unexpected type 'numpy.ndarray'
QImage(sip.voidptr, int, int, QImage.Format): argument 1 has unexpected type 'numpy.ndarray' QImage(bytes, int, int, int, QImage.Format): argument 1 has unexpected type 'numpy.ndarray'
QImage(sip.voidptr, int, int, int, QImage.Format): argument 1 has unexpected type 'numpy.ndarray' QImage(List[str]): argument 1 has unexpected type 'numpy.ndarray' QImage(str, format: str = None): argument 1 has unexpected type 'numpy.ndarray' QImage(QImage): argument 1 has unexpected type 'numpy.ndarray' QImage(Any): too many arguments

According to this post this can be caused by numpy creating a view. Modifying the lines

 im_np = np.array(img)                                                                                                                                                                                  
 im_np = np.transpose(im_np, (1,0,2))                                                                                                                                                                              

To

im_np = np.array(img)                                                                                                                                                                                  
im_np = np.transpose(im_np, (1,0,2))                                                                                                                                                                              
im_np_cpy = np.copy(im_np)     

Produces the same error. To test that I am not passing a view I print the result of the test

im_np_cpy.base is im_np

and it's False. The image is visualised correctly with cv2. I am clearly missing something, any idea what?

Cheers!

Upvotes: 15

Views: 31171

Answers (7)

If we use opencv module in pyqt Qimage, use the below command for image.

 qimage = QImage(img, img.shape[1], img.shape[0], QImage.Format_BGR888)

And if we use images, then directly use this:

 qimage = QImage(img, img.shape[1], img.shape[0], QImage.Format_RGB888)

Upvotes: 1

import copy

im_np = np.array(img)                                                                                                                                                                                  
im_np = np.transpose(im_np, (1,0,2))                                                                                                                                                                              
im_np_cpy = copy.deepcopy(im_np) 

Use above command for getting the im_np data to im_np_cpy

Upvotes: 1

Assaf Genosar
Assaf Genosar

Reputation: 508

Axis transposing, reordering (BGR to RGB) or any transition that doesn't require a copy, a new image container, representing the same image buffer will be created. the problems starts to appear at the interface point to another module. usually an image buffer is represented as a continues stream of bytes along a defined order of axis. it could be solved using:

im_np = np.array(img)                                                                                                                                                                               
im_np = np.transpose(im_np, (1,0,2))
im_np = np.ascontiguousarray(im_np)
qimage = QImage(im_np.data, im_np.shape[1], im_np.shape[0],                                                                                                                                                 
                 QImage.Format_RGB888)

or alternatively (faster) by:

im_np = np.array(img)    
qimage = QImage(im_np.data, im_np.shape[1], im_np.shape[0],                                                                                                                                                 
                 QImage.Format_BGR888)

Upvotes: 5

Ivan
Ivan

Reputation: 359

Just do this:

h,w = img.shape
qimage = QImage(img.data, w, h, 3*w, QImage.Format_RGB888)

Upvotes: 5

Woffl
Woffl

Reputation: 116

Ivan's answer is short and elegant, however while numpy uses (H, W) order, Qt uses (W, H) order. Therefore, to make it work, I have to exchange w and h in the second line:

h, w, _ = img.shape
qimage = QImage(img.data, w, h, 3 * w, QImage.Format_RGB888)

(I would have preferred to comment on the above answer but I don't have enough reputation.)

Upvotes: 9

Dio Nik
Dio Nik

Reputation: 81

Check if the module qimage2ndarray suits your needs, with just one line of code https://pypi.org/project/qimage2ndarray/

yourQImage=qimage2ndarray.array2qimage(yournumpyarray)

Upvotes: 8

Johan van Breda
Johan van Breda

Reputation: 593

I added a copy after the transpose like this:

im_np = np.transpose(im_np,(1,0,2)).copy()

and that worked for me.

Upvotes: 15

Related Questions