将matplotlib图复制到QClipboard,分辨率提高

时间:2017-11-23 07:37:56

标签: python matplotlib pyqt clipboard dpi

在pyQt应用程序中,我正在使用

将matplotlib数字(self.canvas)复制到QClipboard实例
cb = QClipboard(self)
img = QImage(self.canvas.grab())
cb.setImage(img)

img = QPixmap(self.canvas.grab())
self.cb.setPixmap(img)

两者都运行良好,但是,我还没有设法控制导出图像的分辨率。这可以通过创建和导出临时文件来实现,但是,这很慢并且由于文件系统限制而存在潜在问题:

self.canvas.figure.savefig(self.temp_file, dpi = 300, type = 'png')
temp_img = QImage(self.temp_file)
cb.setImage(temp_img)

那么,有没有办法在不绕过文件系统的情况下设置复制图像的分辨率?

-------------------------------

编辑:我刚刚发现上述内容在pyqt4下无效。相反,您可以使用

img = QPixmap.grabWidget(self.canvas)
self.cb.setPixmap(img)

-------------------------------

编辑:几乎可以使用的另一个解决方案是以下代码,遗憾的是它会改变颜色(返回到matplotlib默认值?):

# construct image from raw rgba data, this changes the colormap:
size = self.canvas.size()
width, height = size.width(), size.height()
im = QImage(self.canvas.buffer_rgba(), width, height, QImage.Format_ARGB32)
self.cb.setImage(im)

1 个答案:

答案 0 :(得分:0)

以下是一个不完整的答案。如此进一步的答案,仍然欢迎提供完整或替代解决方案。

您可以将图像保存到文件缓冲区并从那里读取,而不是将图像保存到磁盘。但是,直接将缓冲区读入QImage可能很困难。这被问到here,但答案使用了一种解决方法,首先将文件保存到磁盘。这在这里是不希望的。

相反,您可以根据numpy数组将该数字读入QImage。 这可能涉及

的步骤
  1. 将具有所需分辨率的图形保存到缓冲区,然后读取缓冲区并从中创建一个numpy数组。在这个问题中解决了这个问题: How can I render a Matplotlib Axes object to an image (as a Numpy array)?
  2. 从numpy数组创建QImage。这个问题在这个问题中得到了解决:How to set an numpy array image on a QWidget using PyQt5以及Convert 16-bit grayscale to QImage
  3. 不幸的是,我目前无法正确显示RGB数组,但以下是将该图显示为灰度图像的解决方案:

    import io
    import sys
    from PyQt4 import QtGui
    import matplotlib.pyplot as plt
    import numpy as np
    
    def get_image():
        plt.plot([1,3,2])
        buff = io.BytesIO()
        plt.savefig(buff, format="png", dpi=100)
        buff.seek(0)
        img = plt.imread(buff)
        return img
    
    
    class App(QtGui.QWidget):
    
        def __init__(self):
            super(App, self).__init__()
            self.setGeometry(300, 300, 250, 150)
            self.setLayout(QtGui.QVBoxLayout())
            label = QtGui.QLabel()
            label2 = QtGui.QLabel("Some other text label") 
    
            img = get_image()
    
            im = img.mean(axis=2)
            im = ((im - im.min()) / (im.ptp() / 255.0)).astype(np.uint8)
            print im.shape, im.max(), im.min()
            temp_img = QtGui.QImage(im,im.shape[1],im.shape[0],im.shape[1], QtGui.QImage.Format_Indexed8)
            pixmap = QtGui.QPixmap(temp_img)
            label.setPixmap(pixmap)
    
            self.layout().addWidget(label)
            self.layout().addWidget(label2)
            self.show()
    
    
    if __name__ == '__main__':
        app = QtGui.QApplication([])
        ex = App()
        sys.exit(app.exec_())