如何使用 pyqt 在场景中输出颜色图?
How do I output a colormap in a scene using pyqt?
TL;DR: 您只需要阅读 "Update" 部分。
How do you output numpy.random.random((256, 256))
as a colormap to a
qt scene?
这就是总结的总结。
更新:
以下是我要保存到文件中的颜色图。
scaled_image = Image.fromarray(np.uint8(self.image*255))
plt.savefig("/home/test.png")
self.image
是一个 256x256 的 numpy 数组,它的所有值都在 -1 到 1 之间。
如何将此图像输出到 Qt 中的场景中?可以用self.image = numpy.random.random((256, 256))
来和我类似的起点。如何将随机值的 2D numpy 数组作为颜色图放到 pyqt 场景中?
1016 年 2 月 24 日更新
这么近。这似乎行得通,但规模已经颠倒了。蓝色现在是热的,红色是冷的。我该如何切换它,使其看起来像上图?
scene = QGraphicsScene(self)
scaled_image = Image.fromarray(np.uint8(self.image*255))
gcf().canvas.draw() # IMPORTANT!
stringBuffer = gcf().canvas.buffer_rgba() # IMPORTANT!
l, b, w, h = gcf().bbox.bounds
qImage = QtGui.QImage(stringBuffer,
w,
h,
QtGui.QImage.Format_ARGB32)
pixmap = QtGui.QPixmap.fromImage(qImage)
pixmapItem = QtGui.QGraphicsPixmapItem(pixmap)
scene.addItem(pixmapItem)
self.graphicsView.setScene(scene)
我尝试过的 23/02/2016
以下显示黑屏
scene = QGraphicsScene(self)
scaled_image = Image.fromarray(np.uint8(self.image*255))
pixMap = QPixmap(scaled_image)
scene.addPixmap(pixMap)
self.graphicsView.setScene(scene)
下面给我一张输出到Qt场景的灰度图。为什么不是彩色的?
scene = QGraphicsScene(self)
scaled_image = Image.fromarray(np.uint8(self.image*255))
imgQ = ImageQt(scaled_image)
pixMap = QtGui.QPixmap.fromImage(imgQ)
scene.addPixmap(pixMap)
self.graphicsView.setScene(scene)
我从颜色映射问题的解决方案进行了逆向工程 here and displaying an image here。
使用发布的解决方案中的建议,我尝试先创建一个 QGraphicsPixmapItem
,然后将项目添加到场景中。官方文档有点混乱,所以我终于从更清晰的 pyside docs 中得到了我需要的东西。可悲的是,我得到了与上面相同的灰度。代码如下:
scene = QGraphicsScene(self)
scaled_image = Image.fromarray(np.uint8(self.image*255))
imgQ = ImageQt(scaled_image)
pixMap = QtGui.QPixmap.fromImage(imgQ)
pixMapItem = QtGui.QGraphicsPixmapItem(pixMap)
scene.addItem(pixMapItem)
self.graphicsView.setScene(scene)
我尝试过的其他事情(较早):
self.image
是 numpy 二维数组,它的所有值都在 -1 和 1 之间。
我按如下方式缩放,得到一张灰度图。但是,我想要一个颜色图:
scene = QGraphicsScene(self)
scaled_image = (self.image + 1) * (255 / 2)
scene.addPixmap(QPixmap.fromImage(qimage2ndarray.array2qimage(scaled_image)))
self.graphicsView.setScene(scene)
#min(self.image) = -0.64462
#max(self.image) = 1.0
如果我改为执行以下操作,我会得到我想要的颜色图,例如我之前开发的网络应用程序的下图
>>> fig = plt.figure()
>>> ax = fig.add_subplot(111)
>>> imgplot = ax.imshow(self.image)
如何向 qt 场景添加颜色图,而不仅仅是灰度图?
QPixmap
支持大于 255 和 multiple image formats 的颜色值。如果不是这样,Qt 中的所有图标都会被灰度化(显然不是这样;))。
你可以用任何你想要的方式生成你的颜色图(在(使用 OpenCV 和 numpy)之前或在将它转换为 QImage
(使用 Qt)之后),将它转换为 QPixmap
并使用 QGraphicsPixmapItem
(不要将 QPixmap
直接用作 QGraphicScene
的一部分) 将其附加到您的 QGraphicsScene
。
编辑:
我误读了文档。您实际上可以通过使用 addPixmap()
在 QGraphicScene 中直接使用 QPixmap
。对于那个很抱歉。作为道歉,这里有一些代码供您使用。 :P
import sys
from PyQt4.QtCore import *
from PyQt4.QtGui import *
class ImageView(QGraphicsView):
def __init__(self, pixmap=None, parent=None):
'''
QGraphicsView shows the image
'''
super(ImageView, self).__init__(parent)
self.pixmap = pixmap
class Widget(QWidget):
def __init__(self, parent=None):
super(Widget, self).__init__(parent)
layout = QVBoxLayout(self)
pic = QPixmap('/home/-----/Pictures/7 Cat Sins - Wrath.jpg')
grview = ImageView(pic, self)
layout.addWidget(grview)
self.setFixedSize(pic.size())
scene = QGraphicsScene(self)
scene.addPixmap(pic)
grview.setScene(scene)
self.show()
def main():
app = QApplication(sys.argv)
w = Widget()
return sys.exit(app.exec_())
if __name__ == '__main__':
main()
它产生以下结果:
图片来源: 在 Google 上寻找 7 Cat Sins - Wrath ;)
基本上你创建一个图像查看器,创建场景图,向场景图中添加一个像素图,将图像查看器的场景设置为该图,并使用该查看器在屏幕上显示像素图。
编辑2:
好的,看来您在 matplotlib
的实际集成方面遇到了问题。以下是您的操作方法(取自 here,对 gcf().canvas.buffer_rgba()
稍作改动):
import numpy as np
from matplotlib import use
use('AGG')
from matplotlib.pylab import *
from PySide import QtCore,QtGui
# Following are used for the generation of the image but you have your own imports so you don't need them
from matplotlib.transforms import Bbox
from matplotlib.path import Path
from matplotlib.patches import Rectangle
# Generation of the figure (you can skip all that and use your stuff)
rect = Rectangle((-1, -1), 2, 2, facecolor="#aaaaaa")
gca().add_patch(rect)
bbox = Bbox.from_bounds(-1, -1, 2, 2)
for i in range(12):
vertices = (np.random.random((4, 2)) - 0.5) * 6.0
vertices = np.ma.masked_array(vertices, [[False, False], [True, True], [False, False], [False, False]])
path = Path(vertices)
if path.intersects_bbox(bbox):
color = 'r'
else:
color = 'b'
plot(vertices[:,0], vertices[:,1], color=color)
# The conversion and display of the plot
app = QtGui.QApplication(sys.argv)
gcf().canvas.draw() # IMPORTANT!
stringBuffer = gcf().canvas.buffer_rgba() # IMPORTANT!
l, b, w, h = gcf().bbox.bounds
qImage = QtGui.QImage(stringBuffer,
w,
h,
QtGui.QImage.Format_ARGB32)
scene = QtGui.QGraphicsScene()
view = QtGui.QGraphicsView(scene)
pixmap = QtGui.QPixmap.fromImage(qImage)
pixmapItem = QtGui.QGraphicsPixmapItem(pixmap)
scene.addItem(pixmapItem)
view.show()
app.exec_()
编辑 3:
对于您的反向色图问题,请参阅 here (documentation) and here (SO).
PS:不要使用额外的库,例如 qimage2ndarray
将 OpenCV 图像转换为 QImage
s 我建议您自己做,看看究竟需要什么完毕。如果您对 material 有丰富的经验并且您只需要节省一些时间,那么这样的库会很整洁。除了这个原因 - 远离他们。
所以这行得通...但是我觉得这样做很脏:
scene = QGraphicsScene(self)
scaled_image = Image.fromarray(np.uint8(self.image*255))
plt.savefig(".../Downloads/itworks.png")
pixMap = QPixmap(".../Downloads/itworks.png")
scene.addPixmap(pixMap)
self.graphicsView.setScene(scene)
是否真的必须依赖于将图像保存到文件然后将其重新加载为 QPixmap 才能工作...?对于我认为是 pyqt 的一个非常标准的需求,这不是一个非常非 pythonic 的管道胶带答案吗?我担心每次都必须将图像保存到文件中会在我扩展时产生瓶颈,而且,因为我必须管理文件系统的东西而变得烦人。
我将悬赏留给任何可以提供将 numpy.random.random((256, 256))
输出到 qt 场景而无需保存到文件的中间步骤的人。
与此同时,这种胶带解决方案有效:
更新: 作为参考,这是我最终使用 and 中的代码完美运行的结果。谢谢大家!
scene = self.QScene(self)
scaled_image = Image.fromarray(255-np.uint8(self.image*255))
plt.imshow(scaled_image, interpolation = "nearest")
gcf().canvas.draw() # IMPORTANT!
stringBuffer = gcf().canvas.buffer_rgba() # IMPORTANT!
l, b, w, h = gcf().bbox.bounds
qImage = QtGui.QImage(stringBuffer,
w,
h,
QtGui.QImage.Format_ARGB32)
pixmap = QtGui.QPixmap.fromImage(qImage)
pixmapItem = QtGui.QGraphicsPixmapItem(pixmap)
scene.addItem(pixmapItem)
self.graphicsView.setScene(scene)
你应该继续Matplotlib's imshow route (probably also along with colormap customisation) using matplotlib's PyQt4 backend。
我以前使用过这个 mpl-PyQt4 工具,虽然一开始看起来很麻烦,但它正是您要找的(使用本机工具,没有技术 translation/bridging)并且 最 可扩展。这些属性在示例中通过动画和 QLayout 布置的图显示
您的代码几乎可以正常工作。您使用以下方法获取图像:
scaled_image = Image.fromarray(np.uint8(self.image*255))
要反转,您只需从 255 中减去当前数据即可。
scaled_image = Image.fromarray(255-np.uint8(self.image*255))
这里我假设您当前的代码工作正常并且只有反转值。但是,如果您的数据确实是从 -1 到 1,那么当前代码会将一半结果限制为零(因为 uint8 的最小值为零)。值从 -1 到 1 的正确代码应该稍微修改一下:
scaled_image = Image.fromarray(255 - (self.image + 1)*127.5)
P.S。您可以通过使用不同的颜色图(例如 'jet_r'
)在没有任何数学运算的情况下反转颜色。但请确保您的值已正确缩放
TL;DR: 您只需要阅读 "Update" 部分。
How do you output
numpy.random.random((256, 256))
as a colormap to a qt scene?
这就是总结的总结。
更新:
以下是我要保存到文件中的颜色图。
scaled_image = Image.fromarray(np.uint8(self.image*255))
plt.savefig("/home/test.png")
self.image
是一个 256x256 的 numpy 数组,它的所有值都在 -1 到 1 之间。
如何将此图像输出到 Qt 中的场景中?可以用self.image = numpy.random.random((256, 256))
来和我类似的起点。如何将随机值的 2D numpy 数组作为颜色图放到 pyqt 场景中?
1016 年 2 月 24 日更新
这么近。这似乎行得通,但规模已经颠倒了。蓝色现在是热的,红色是冷的。我该如何切换它,使其看起来像上图?
scene = QGraphicsScene(self)
scaled_image = Image.fromarray(np.uint8(self.image*255))
gcf().canvas.draw() # IMPORTANT!
stringBuffer = gcf().canvas.buffer_rgba() # IMPORTANT!
l, b, w, h = gcf().bbox.bounds
qImage = QtGui.QImage(stringBuffer,
w,
h,
QtGui.QImage.Format_ARGB32)
pixmap = QtGui.QPixmap.fromImage(qImage)
pixmapItem = QtGui.QGraphicsPixmapItem(pixmap)
scene.addItem(pixmapItem)
self.graphicsView.setScene(scene)
我尝试过的 23/02/2016
以下显示黑屏
scene = QGraphicsScene(self)
scaled_image = Image.fromarray(np.uint8(self.image*255))
pixMap = QPixmap(scaled_image)
scene.addPixmap(pixMap)
self.graphicsView.setScene(scene)
下面给我一张输出到Qt场景的灰度图。为什么不是彩色的?
scene = QGraphicsScene(self)
scaled_image = Image.fromarray(np.uint8(self.image*255))
imgQ = ImageQt(scaled_image)
pixMap = QtGui.QPixmap.fromImage(imgQ)
scene.addPixmap(pixMap)
self.graphicsView.setScene(scene)
我从颜色映射问题的解决方案进行了逆向工程 here and displaying an image here。
使用发布的解决方案中的建议,我尝试先创建一个 QGraphicsPixmapItem
,然后将项目添加到场景中。官方文档有点混乱,所以我终于从更清晰的 pyside docs 中得到了我需要的东西。可悲的是,我得到了与上面相同的灰度。代码如下:
scene = QGraphicsScene(self)
scaled_image = Image.fromarray(np.uint8(self.image*255))
imgQ = ImageQt(scaled_image)
pixMap = QtGui.QPixmap.fromImage(imgQ)
pixMapItem = QtGui.QGraphicsPixmapItem(pixMap)
scene.addItem(pixMapItem)
self.graphicsView.setScene(scene)
我尝试过的其他事情(较早):
self.image
是 numpy 二维数组,它的所有值都在 -1 和 1 之间。
我按如下方式缩放,得到一张灰度图。但是,我想要一个颜色图:
scene = QGraphicsScene(self)
scaled_image = (self.image + 1) * (255 / 2)
scene.addPixmap(QPixmap.fromImage(qimage2ndarray.array2qimage(scaled_image)))
self.graphicsView.setScene(scene)
#min(self.image) = -0.64462
#max(self.image) = 1.0
如果我改为执行以下操作,我会得到我想要的颜色图,例如我之前开发的网络应用程序的下图
>>> fig = plt.figure()
>>> ax = fig.add_subplot(111)
>>> imgplot = ax.imshow(self.image)
如何向 qt 场景添加颜色图,而不仅仅是灰度图?
QPixmap
支持大于 255 和 multiple image formats 的颜色值。如果不是这样,Qt 中的所有图标都会被灰度化(显然不是这样;))。
你可以用任何你想要的方式生成你的颜色图(在(使用 OpenCV 和 numpy)之前或在将它转换为 QImage
(使用 Qt)之后),将它转换为 QPixmap
并使用 将其附加到您的 QGraphicsPixmapItem
(不要将 QPixmap
直接用作 QGraphicScene
的一部分)QGraphicsScene
。
编辑:
我误读了文档。您实际上可以通过使用 addPixmap()
在 QGraphicScene 中直接使用 QPixmap
。对于那个很抱歉。作为道歉,这里有一些代码供您使用。 :P
import sys
from PyQt4.QtCore import *
from PyQt4.QtGui import *
class ImageView(QGraphicsView):
def __init__(self, pixmap=None, parent=None):
'''
QGraphicsView shows the image
'''
super(ImageView, self).__init__(parent)
self.pixmap = pixmap
class Widget(QWidget):
def __init__(self, parent=None):
super(Widget, self).__init__(parent)
layout = QVBoxLayout(self)
pic = QPixmap('/home/-----/Pictures/7 Cat Sins - Wrath.jpg')
grview = ImageView(pic, self)
layout.addWidget(grview)
self.setFixedSize(pic.size())
scene = QGraphicsScene(self)
scene.addPixmap(pic)
grview.setScene(scene)
self.show()
def main():
app = QApplication(sys.argv)
w = Widget()
return sys.exit(app.exec_())
if __name__ == '__main__':
main()
它产生以下结果:
图片来源: 在 Google 上寻找 7 Cat Sins - Wrath ;)
基本上你创建一个图像查看器,创建场景图,向场景图中添加一个像素图,将图像查看器的场景设置为该图,并使用该查看器在屏幕上显示像素图。
编辑2:
好的,看来您在 matplotlib
的实际集成方面遇到了问题。以下是您的操作方法(取自 here,对 gcf().canvas.buffer_rgba()
稍作改动):
import numpy as np
from matplotlib import use
use('AGG')
from matplotlib.pylab import *
from PySide import QtCore,QtGui
# Following are used for the generation of the image but you have your own imports so you don't need them
from matplotlib.transforms import Bbox
from matplotlib.path import Path
from matplotlib.patches import Rectangle
# Generation of the figure (you can skip all that and use your stuff)
rect = Rectangle((-1, -1), 2, 2, facecolor="#aaaaaa")
gca().add_patch(rect)
bbox = Bbox.from_bounds(-1, -1, 2, 2)
for i in range(12):
vertices = (np.random.random((4, 2)) - 0.5) * 6.0
vertices = np.ma.masked_array(vertices, [[False, False], [True, True], [False, False], [False, False]])
path = Path(vertices)
if path.intersects_bbox(bbox):
color = 'r'
else:
color = 'b'
plot(vertices[:,0], vertices[:,1], color=color)
# The conversion and display of the plot
app = QtGui.QApplication(sys.argv)
gcf().canvas.draw() # IMPORTANT!
stringBuffer = gcf().canvas.buffer_rgba() # IMPORTANT!
l, b, w, h = gcf().bbox.bounds
qImage = QtGui.QImage(stringBuffer,
w,
h,
QtGui.QImage.Format_ARGB32)
scene = QtGui.QGraphicsScene()
view = QtGui.QGraphicsView(scene)
pixmap = QtGui.QPixmap.fromImage(qImage)
pixmapItem = QtGui.QGraphicsPixmapItem(pixmap)
scene.addItem(pixmapItem)
view.show()
app.exec_()
编辑 3: 对于您的反向色图问题,请参阅 here (documentation) and here (SO).
PS:不要使用额外的库,例如 qimage2ndarray
将 OpenCV 图像转换为 QImage
s 我建议您自己做,看看究竟需要什么完毕。如果您对 material 有丰富的经验并且您只需要节省一些时间,那么这样的库会很整洁。除了这个原因 - 远离他们。
所以这行得通...但是我觉得这样做很脏:
scene = QGraphicsScene(self)
scaled_image = Image.fromarray(np.uint8(self.image*255))
plt.savefig(".../Downloads/itworks.png")
pixMap = QPixmap(".../Downloads/itworks.png")
scene.addPixmap(pixMap)
self.graphicsView.setScene(scene)
是否真的必须依赖于将图像保存到文件然后将其重新加载为 QPixmap 才能工作...?对于我认为是 pyqt 的一个非常标准的需求,这不是一个非常非 pythonic 的管道胶带答案吗?我担心每次都必须将图像保存到文件中会在我扩展时产生瓶颈,而且,因为我必须管理文件系统的东西而变得烦人。
我将悬赏留给任何可以提供将 numpy.random.random((256, 256))
输出到 qt 场景而无需保存到文件的中间步骤的人。
与此同时,这种胶带解决方案有效:
更新: 作为参考,这是我最终使用
scene = self.QScene(self)
scaled_image = Image.fromarray(255-np.uint8(self.image*255))
plt.imshow(scaled_image, interpolation = "nearest")
gcf().canvas.draw() # IMPORTANT!
stringBuffer = gcf().canvas.buffer_rgba() # IMPORTANT!
l, b, w, h = gcf().bbox.bounds
qImage = QtGui.QImage(stringBuffer,
w,
h,
QtGui.QImage.Format_ARGB32)
pixmap = QtGui.QPixmap.fromImage(qImage)
pixmapItem = QtGui.QGraphicsPixmapItem(pixmap)
scene.addItem(pixmapItem)
self.graphicsView.setScene(scene)
你应该继续Matplotlib's imshow route (probably also along with colormap customisation) using matplotlib's PyQt4 backend。
我以前使用过这个 mpl-PyQt4 工具,虽然一开始看起来很麻烦,但它正是您要找的(使用本机工具,没有技术 translation/bridging)并且 最 可扩展。这些属性在示例中通过动画和 QLayout 布置的图显示
您的代码几乎可以正常工作。您使用以下方法获取图像:
scaled_image = Image.fromarray(np.uint8(self.image*255))
要反转,您只需从 255 中减去当前数据即可。
scaled_image = Image.fromarray(255-np.uint8(self.image*255))
这里我假设您当前的代码工作正常并且只有反转值。但是,如果您的数据确实是从 -1 到 1,那么当前代码会将一半结果限制为零(因为 uint8 的最小值为零)。值从 -1 到 1 的正确代码应该稍微修改一下:
scaled_image = Image.fromarray(255 - (self.image + 1)*127.5)
P.S。您可以通过使用不同的颜色图(例如 'jet_r'
)在没有任何数学运算的情况下反转颜色。但请确保您的值已正确缩放