将绘图保存到 numpy 数组
在 Python 和 Matplotlib 中,可以轻松地将绘图显示为弹出窗口或将绘图保存为 PNG 文件。如何将绘图保存为 RGB 格式的 numpy 数组?
In Python and Matplotlib, it is easy to either display the plot as a popup window or save the plot as a PNG file. How can I instead save the plot to a numpy array in RGB format?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(9)
当您需要与保存的绘图进行像素到像素的比较时,这对于单元测试等来说是一个方便的技巧。
一种方法是使用
fig.canvas.tostring_rgb
,然后使用numpy.fromstring
以及适当的数据类型。还有其他方法,但这是我倾向于使用的一种。例如
This is a handy trick for unit tests and the like, when you need to do a pixel-to-pixel comparison with a saved plot.
One way is to use
fig.canvas.tostring_rgb
and thennumpy.fromstring
with the approriate dtype. There are other ways as well, but this is the one I tend to use.E.g.
@JUN_NETWORKS 的答案有一个更简单的选项。您可以使用其他格式,例如
raw
或rgba
并跳过cv2
,而不是将图形保存为png
解码步骤。换句话说,实际的绘图到 numpy 的转换归结为:
希望,这有帮助。
There is a bit simpler option for @JUN_NETWORKS's answer. Instead of saving the figure in
png
, one can use other format, likeraw
orrgba
and skip thecv2
decoding step.In other words the actual plot-to-numpy conversion boils down to:
Hope, this helps.
有人提出了这样的方法当然
,这段代码可以工作。但是,输出 numpy 数组图像的分辨率很低。
我的提案代码是这样的。
这段代码运行良好。
如果您在 dpi 参数上设置较大的数字,则可以获得 numpy 数组形式的高分辨率图像。
Some people propose a method which is like this
Ofcourse, this code work. But, output numpy array image is so low resolution.
My proposal code is this.
This code works well.
You can get a high-resolution image as a numpy array if you set a large number on the dpi argument.
是时候对您的解决方案进行基准测试了。
在这种情况下,IO 原始缓冲区是将 matplotlib 图转换为 numpy 数组最快的。
附加说明:
如果您无权访问该图形,您始终可以从轴中提取它:
fig = ax.figure
如果您需要
channel x height x 中的数组宽度
格式,做im = im.transpose((2, 0, 1))
。Time to benchmark your solutions.
Under this scenario, IO raw buffers are the fastest to convert a matplotlib figure to a numpy array.
Additional remarks:
if you don't have an access to the figure, you can always extract it from the axes:
fig = ax.figure
if you need the array in the
channel x height x width
format, doim = im.transpose((2, 0, 1))
.如果有人想要一个即插即用的解决方案,而不修改任何先前的代码(获取对 pyplot 图和所有内容的引用),下面的内容对我有用。只需在所有
pyplot
语句之后添加此内容,即在pyplot.show()
之前In case somebody wants a plug and play solution, without modifying any prior code (getting the reference to pyplot figure and all), the below worked for me. Just add this after all
pyplot
statements i.e. just beforepyplot.show()
MoviePy 使得将图形转换为 numpy 数组非常简单。它有一个名为
mplfig_to_npimage()
的内置函数。你可以这样使用它:MoviePy makes converting a figure to a numpy array quite simple. It has a built-in function for this called
mplfig_to_npimage()
. You can use it like this:正如 Joe Kington 所指出的,一种方法是在画布上绘图,将画布转换为字节字符串,然后将其重新整形为正确的形状。
但是,由于
canvas.get_width_height()
返回显示坐标中的宽度和高度,因此有时会在此答案中解决缩放问题。As Joe Kington has pointed out, one way is to draw on the canvas, convert the canvas to a byte string and then reshape it into the correct shape.
However as
canvas.get_width_height()
returns width and height in display coordinates, there are sometimes scaling issues that are resolved in this answer.Jonan Gueorguiev 答案的清理版本:
Cleaned up version of the answer by Jonan Gueorguiev:
所有 matplotlib 方法的问题是,即使您执行 plt.ioff() 或返回图形,matplotlib 仍然可以渲染和显示绘图,即使您成功,但它在不同平台上的行为不同(因为 matplotlib 将其委托给后端取决于操作系统) - 绘制 numpy 数组时性能会受到影响。
我测量了之前建议的所有 matplotlib 方法,结果需要几毫秒,最常见的是几十毫秒,有时甚至更多毫秒。
我找不到一个简单的库可以做到这一点,不得不自己编写这个东西。完全矢量化的 numpy(不是单个循环)中的 numpy 绘图,用于所有部分,例如散点、连接、轴、网格,包括点的大小和厚度,并且在微秒内完成
https://github.com/bedbad/justpyplot
The issues with all the matplotlib approaches is that matplotlib can still render and display plot even if you do plt.ioff() or return the figure and even if you do succeed while it behaves differently on a different platform(because matplotlib delegates it to backend depending on os) - you get a performance hit for getting plotted numpy array.
I measured all previosly suggested matplotlib approaches and it rakes in milliseconds, most often dozens, sometimes even more milliseconds.
I couldn't find a simple library that just does it, had to write the thing myself. A plot to numpy in fully vectorized numpy(not a single loop) for all the parts such as scatter, connected, axis, grid, including size of the points and thickness and it does it in microseconds
https://github.com/bedbad/justpyplot