首页 > 解决方案 > Matplotlib 图形的输出图像在不同操作系统中具有不同的大小

问题描述

我们的一项测试失败了,因为输出图像的大小有时会略有不同。在 Linux 上为 579x517 像素,在 Windows 上为 582x520 像素。我检查了 and 的版本,matplotlib它们pandas是相同的。有细微差别matplotlib.rcParams;我尝试更改看起来相关的参数,但没有帮助。

是不是因为两台机器的显示尺寸略有不同?如果我在 Windows 机器上设置dpi=99.99savefig输出大小为 579x517 像素。我不想在应用程序中更改它,因为它只是为了修复一个失败的测试。

这是我们正在使用的绘图函数,percentages是一个pandas数据框。

def plot_and_save(percentages, output_directory, filename, title, legend, x_label, y_label,
                  font_size=16):
    """Plot data and save figure to file."""
    matplotlib.rcParams['font.size'] = font_size
    ax1 = percentages.plot.bar(color=['#484D7A', '#F6A124'])
    ax1.grid(which='major', axis='y', color='#4A4A49', alpha=0.1)
    ax1.set_axisbelow(True)  # Puts gridlines below the bars
    ax1.set(xlabel=x_label, ylabel=y_label, title=title)
    ax1.legend(legend, framealpha=1)

    output_path = os.path.join(output_directory, filename)

    plt.savefig(output_path, bbox_inches='tight')
    plt.close()

编辑:我有一个更简单的复制案例。在我的 Linux 机器上运行这段代码,我得到一个 576x455 像素的图像。

    plt.plot(1)
    plt.title('Title')
    plt.xlabel('Label')
    plt.ylabel('Label')
    plt.savefig('test.png', bbox_inches='tight')

Windows 机器生成 576x453 像素的图像,因此如果我将预期像素大小除以实际像素大小,然后按该比率更改默认图像大小,它应该会生成正确大小的图像。

    exp_x, exp_y = 576, 455

    plt.plot(1)
    fig = plt.gcf()
    def_size = fig.get_size_inches()
    print('default size', def_size)
    new_size = (def_size[0] * exp_x / act_x, def_size[1] * exp_y / act_y)
    print('new size', new_size)
    fig.set_size_inches(*new_size)
    plt.title('Title')
    plt.xlabel('Label')
    plt.ylabel('Label')
    plt.savefig('test.png', bbox_inches='tight')

输出是一个 576x454 像素的图像,所以必须进行一些舍入。

default size [6.4 4.8]
new size (6.4, 4.821192052980132)

标签: pythonmatplotlib

解决方案


这是意外行为。Matplotlib 旨在在所有平台上生成像素相同的输出图像。

我无法重现您描述的行为。.png使用您的最小示例,我在任一平台上使用 Matplotlib 3.4.2 在 Linux(Ubuntu 20.04 LTS)和 Windows(10)上获得逐字节相同的图像。分辨率为 576×455 像素,这是您为 Linux 报告的,但不是 Windows。

对于基本测试,例如创建一个简单的图形(如您的示例),Matplotlib 测试套件将它们呈现在测试系统上,然后将最终输出与源代码存储库中的“基线”图像进行比较,例如这个简单的图形. 请参阅Matplotlib 开发人员指南中的“编写图像比较测试”处理比较的测试夹具的默认容差为零,对于某些测试,它会被覆盖,但对于那个简单的图形却不是​​。然后它只是numpy.array_equal用来比较实际和预期的图像。换句话说:应该没有区别,尤其是在分辨率上。这些测试通常在 Linux、macOS 和 Windows 上运行

所以你描述的行为是非常出乎意料的,只能用你暗示的默认值的差异来解释,在matplotlib.rcParams. 可以说最干净的解决方案是使用 Matplotlib 附带的确切配置并相应地调整您的绘图例程。否则考虑在两个系统上运行 Matplotlib 测试套件以缩小偏差。您的 Windows 安装更可能是罪魁祸首。


推荐阅读