将 matplotlib 图形复制到具有更高分辨率的 QClipboard
Posted
技术标签:
【中文标题】将 matplotlib 图形复制到具有更高分辨率的 QClipboard【英文标题】:Copy matplotlib figure to QClipboard with increased resolution 【发布时间】: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)
【问题讨论】:
【参考方案1】:以下是不完整的答案。因此,仍然欢迎提供进一步的答案,制作完整或替代解决方案。
您可以不将图像保存到磁盘,而是将其保存到文件缓冲区并从那里读取。但是,将缓冲区直接读入QImage
可能很困难。有人问过here,但答案使用了一种解决方法,首先将文件保存到磁盘。这是不希望的。
相反,您可以将数字以 numpy 数组的形式读入QImage
。
这可能涉及到
-
将具有所需分辨率的图形保存到缓冲区,然后读取缓冲区并从中创建一个 numpy 数组。这在这个问题中得到解决:
How can I render a Matplotlib Axes object to an image (as a Numpy array)?
从 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 添加“复制到剪贴板”功能。我曾尝试过类似于您的解决方案,但是颜色不同 - 请参阅我的问题的编辑。以上是关于将 matplotlib 图形复制到具有更高分辨率的 QClipboard的主要内容,如果未能解决你的问题,请参考以下文章
matplotlib 设置图形大小时 figsize 与 dpi 的关系
matplotlib 中的 figsize 不会改变图形大小? [复制]