【问题标题】:Copy matplotlib figure to QClipboard with increased resolution将 matplotlib 图形复制到具有更高分辨率的 QClipboard
【发布时间】:2018-05-07 02:10:25
【问题描述】:

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

【问题讨论】:

    标签: python matplotlib pyqt clipboard dpi


    【解决方案1】:

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

    您可以不将图像保存到磁盘,而是将其保存到文件缓冲区并从那里读取。但是,将缓冲区直接读入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

    不幸的是,我目前无法正确显示 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_())
    

    【讨论】:

    • 将图像显示为 RGB 的剩余步骤可能很小,但我无法使用 RGB 值。因此,非常欢迎任何有关如何使用 RGB 值进行这项工作的见解(请随意使用上述代码获取另一个答案或编辑此答案)。
    • 非常感谢您的支持,但恐怕解决方案对我的需求来说太复杂了……我会继续使用我的两班轮船。在搜索网络时,我还发现下一个 matplotlib 版本之一将向 NavigationToolbar 添加“复制到剪贴板”功能。我曾尝试过类似于您的解决方案,但是颜色不同 - 请参阅我的问题的编辑。
    猜你喜欢
    • 2017-02-13
    • 2016-07-15
    • 2012-12-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-09-12
    • 2013-08-06
    • 1970-01-01
    相关资源
    最近更新 更多