【问题标题】:PyQt5 QImage from Numpy Array来自 Numpy 数组的 PyQt5 QImage
【发布时间】:2018-07-16 06:57:31
【问题描述】:

考虑以下代码

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

我收到以下错误

TypeError:参数不匹配任何重载调用:QImage(): 参数太多 QImage(QSize, QImage.Format):参数 1 有 意外类型'numpy.ndarray' QImage(int,int,QImage.Format): 参数 1 具有意外类型 'numpy.ndarray' QImage(bytes, int, int, QImage.Format):参数 1 具有意外类型“numpy.ndarray”
QImage(sip.voidptr, int, int, QImage.Format):参数 1 有 意外类型'numpy.ndarray' QImage(字节,int,int,int, QImage.Format):参数 1 具有意外类型“numpy.ndarray”
QImage(sip.voidptr, int, int, int, QImage.Format):参数 1 有 意外类型'numpy.ndarray' QImage(List [str]):参数1有 意外类型'numpy.ndarray' QImage(str,格式:str = None): 参数 1 具有意外类型 'numpy.ndarray' QImage(QImage): 参数 1 具有意外类型 'numpy.ndarray' QImage(Any): too many 论据

根据this post,这可能是由 numpy 创建视图引起的。 修改线条

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

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

产生同样的错误。为了测试我没有通过视图,我打印了测试结果

im_np_cpy.base is im_np

这是错误的。 使用 cv2 可以正确显示图像。 我显然错过了一些东西,知道什么吗?

干杯!

【问题讨论】:

    标签: python python-3.x numpy pyqt pyqt5


    【解决方案1】:

    轴转置、重新排序(BGR 到 RGB)或任何不需要复制的转换,将创建一个新的图像容器,代表相同的图像缓冲区。问题开始出现在另一个模块的接口点。通常,图像缓冲区表示为沿定义的轴顺序的连续字节流。可以通过以下方式解决:

    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)
    

    或者(更快)通过:

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

    【讨论】:

      【解决方案2】:

      这样做:

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

      【讨论】:

        【解决方案3】:

        Ivan 的回答简短而优雅,但是 numpy 使用 (H, W) 顺序,而 Qt 使用 (W, H) 顺序。因此,要使其工作,我必须在第二行交换 w 和 h:

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

        (我更愿意对上述答案发表评论,但我没有足够的声誉。)

        【讨论】:

          【解决方案4】:

          检查模块 qimage2ndarray 是否满足您的需求,只需一行代码 https://pypi.org/project/qimage2ndarray/

          yourQImage=qimage2ndarray.array2qimage(yournumpyarray)
          

          【讨论】:

            【解决方案5】:

            我在转置后添加了一个副本,如下所示:

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

            这对我有用。

            【讨论】:

            • 好的...这似乎解决了它...但是为什么呢?做 im_np_cpy = np.copy(im_np) 有什么问题?首先进行转置有什么问题?内存视图?
            • 我不知道 a = np.copy(matrix) 是什么。我知道 a = matrix.copy() 有效,例如从 data[row:stride,column:stride].copy() 中的数据中获取一部分
            • 根据numpy.copynumpy.ndarray.copy 的文档,唯一的区别在于控制内存布局的order。在您的解决方案中,默认值为 C-order。虽然在我的是 K,这意味着它试图匹配原始矩阵的布局。现在我不知道这意味着什么,但显然是在搞砸 Qt。
            • 谢谢,这对我有用。不幸的是,制作副本会大大减慢我的进程。
            • 我认为根本原因是"view" 的某个关键attr 实际上返回base object attrs。就像view.strides 实际上给出了view.base.strides,但是view.shape 很好(与view.copy().strides 相比)。我认为img for QImage(img.data, ...) constr 必须有.base..base.base.flags['OWNDATA']True,不幸的是,除非你copy¯\_(ツ)_/¯ 否则不会发生。我花了一段时间才弄清楚这一点。使用 bytesPerLineQimage constructor 对应 @eyllanesc...
            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2014-12-05
            • 2019-06-13
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多