【问题标题】:Can I do something like imsave() with text overlay?我可以用文本覆盖做类似 imsave() 的事情吗?
【发布时间】:2015-11-17 09:43:14
【问题描述】:

我按顺序使用imsave() 制作了许多PNG,我将它们组合成一个AVI,我想添加移动文本注释。我使用ImageJ 制作 AVI 或 GIF。

我不想要坐标轴、数字、边框或任何东西,只想要带有文本(可能还有箭头)的彩色图像(例如imsave() 提供的)。这些将逐帧更改。请原谅使用喷气机。

我可以使用 savefig() 并关闭标记,然后进行裁剪作为后期处理,但是有没有更方便、直接或“matplotlibithic”的方式来做到这一点,这对我的硬盘来说不会那么难? (最后的事情会非常大)。

一个代码sn-p,由请求添加:

import numpy as np
import matplotlib.pyplot as plt

nx, ny = 101, 101

phi   = np.zeros((ny, nx), dtype = 'float')
do_me = np.ones_like(phi, dtype='bool')

x0, y0, r0 = 40, 65, 12

x = np.arange(nx, dtype = 'float')[None,:]
y = np.arange(ny, dtype = 'float')[:,None]
rsq = (x-x0)**2 + (y-y0)**2

circle = rsq <= r0**2

phi[circle] = 1.0
do_me[circle] = False

do_me[0,:], do_me[-1,:], do_me[:,0], do_me[:,-1] = False, False, False, False

n, nper = 100, 100
phi_hold = np.zeros((n+1, ny, nx))
phi_hold[0] = phi

for i in range(n):

    for j in range(nper):
        phi2 = 0.25*(np.roll(phi,  1, axis=0) +
                     np.roll(phi, -1, axis=0) +
                     np.roll(phi,  1, axis=1) +
                     np.roll(phi, -1, axis=1) )

        phi[do_me] = phi2[do_me]

    phi_hold[i+1] = phi

change = phi_hold[1:] - phi_hold[:-1]

places = [(32, 20), (54,25), (11,32), (3, 12)]

plt.figure()
plt.imshow(change[50])
for (x, y) in places:
    plt.text(x, y, "WOW", fontsize=16)
plt.text(5, 95, "Don't use Jet!", color="white", fontsize=20)
plt.show()

【问题讨论】:

    标签: animation numpy video matplotlib png


    【解决方案1】:

    方法一

    使用an excellent answer to another question 作为参考,我想出了以下简化的变体,它似乎工作得很好——只要确保figsize (which is given in inches) 的纵横比与绘图数据的大小比相匹配:

    import numpy as np
    import matplotlib.pyplot as plt
    
    test_image = np.eye(100)
    fig = plt.figure(figsize=(4,4))
    ax = plt.axes(frameon=False, xticks=[],yticks=[])
    ax.imshow(test_image)
    plt.savefig('test.png', bbox_inches='tight', pad_inches=0)
    

    请注意,我将 imshowtest_image 一起使用,这可能与其他绘图功能不同...如果您想做其他事情,请在评论中告诉我。

    还要注意,图像将被(重新)采样,因此figsize 会影响写入图像的分辨率。

    作为pointed out in the commentsfigsize 设置与输出图像的大小(或屏幕上的大小,就此而言)不匹配。为了克服这个问题,使用...

    方法二

    阅读常见问题解答条目Move the edge of an axes to make room for tick labels,我找到了一种方法,可以让figsize 参数直接设置输出图像大小,方法是将轴的刻度移出可见区域:

    import numpy as np
    import matplotlib.pyplot as plt
    
    test_image = np.eye(100)
    fig = plt.figure(figsize=(4,4))
    ax = fig.add_axes([0,0,1,1])
    ax.imshow(test_image)
    plt.savefig('test.png')
    

    请注意,savefig 具有默认 DPI 设置(在我的情况下为 100),它与 figsize 结合使用 - 确定保存图像的 x 和 y 方向的像素数。你可以用dpi 关键字参数覆盖它savefig

    如果你想在屏幕上显示图像而不是保存它(通过使用plt.show()而不是上面代码中的plt.savefig行),图形的大小取决于(除了已经熟悉的@ 987654341@ 参数)figure 的 DPI 设置,它也有默认值(我的系统上为 80)。可以通过将 dpi 关键字参数传递给 plt.figure() 调用来覆盖此值。

    【讨论】:

    • 效果很好!感谢@FriendFX 的解决方案。我认为这正是我所需要的,我将研究重采样问题。另一个答案的链接也有助于背景。我只是好奇,figsize=(4,4) 中的单位是什么?
    • @uhoh,figsize的单位是inches。我会将其添加到答案中。很高兴它成功了!
    • 很好 - 但是嗯...英寸在哪里?。该图在我的笔记本电脑显示屏上大约为 2 英寸,如果我在各种图形程序或 PPT 中打开“test.png”,它们都说它是 3.1 x 3.1 英寸。如果没有bbox_inches='tight,也许它会是什么尺寸?我可以随时将它拨到我需要的地方,所以它根本不会影响解决方案。
    • @uhoh 有趣的一点。你是对的,如果我们从代码中删除bbox_inches='tight',(保存的)图像 4 x 4 英寸。通过一些阅读和实验,我发现了另一种(可能更干净)的方法,其中figsize 实际上与输出大小匹配(至少与 SVG 输出相匹配,因为它实际上存储了分辨率)。我会将其添加到答案中。
    • 超级答案 - 我希望我能投票两次!感谢@FriendFX 的时间和调查工作!仅供参考,我已经 already linked 到您要求的代码 sn-p,好主意。
    猜你喜欢
    • 2022-12-17
    • 2017-11-21
    • 1970-01-01
    • 2020-03-08
    • 1970-01-01
    • 1970-01-01
    • 2011-06-03
    • 1970-01-01
    • 2013-09-26
    相关资源
    最近更新 更多