如何在 matplotlib 中设置 figsize 和 dpi 以使图像具有所需的尺寸和质量?

问题描述 投票:0回答:1

我需要将图像合二为一。我希望生成的图像包含 7 行和 9 列。每个分量图像的尺寸为 256 x 256。我希望不调整这些图像的大小,也就是说,我希望生成的图像的尺寸至少为 9 * 256 x 7 * 256 = 2304 x 1792。最简单的方法对我来说,这样做将使用 numpy 并使用例如 np.concatenate 将图像连接在一起。但是,我决定使用 matplotlib,因为用它向轴添加标签要容易得多。

不幸的是,我无法设置正确的 figsize 和 dpi 值。

我发现一个好方法是将 dpi 参数设置为 100,例如将高度设置为以像素为单位的高度除以 dpi 值。如下所示。

cols = 9
rows = 7

img_size = (256, 256)
dpi = 100

fig, axes = plt.subplots(rows, cols, figsize=(img_size[0] * cols // dpi, img_size[1] * rows // dpi), dpi=dpi)
  1. 不幸的是,当我保存这张图片时,它的尺寸是 2359 x 1720.

  2. 我的第二个问题是,尽管设置了 wspace=0 和 hspace=0,但子图之间仍然存在间隙。

plt.subplots_adjust(wspace=0, hspace=0, left=0, bottom=0, right=1, top=1)

  1. 此外,我不知道保存这张图片的最佳格式是什么,这样文字质量好,缩放时图片质量不会显着降低(我将使用这张图片在乳胶中)。

下面我附上一个简单的例子进行复现

from PIL import Image
import numpy as np
import matplotlib.pyplot as plt

cols = 9
rows = 7

img_size = (256, 256)
dpi = 100

fig, axes = plt.subplots(rows, cols, figsize=(img_size[0] * cols // dpi, img_size[1] * rows // dpi), dpi=dpi)

for row_idx, row in enumerate(axes):
    images = [Image.new('RGB', (256, 256), color='grey') for i in range(cols)]
    
    for col_idx, (col, image) in enumerate(zip(row, images)):
        col.imshow(image)
        
        col.spines['top'].set_visible(False)
        col.spines['right'].set_visible(False)
        col.spines['bottom'].set_visible(False)
        col.spines['left'].set_visible(False)
        col.set_xticks([])
        col.set_yticks([])

        if col_idx == 0:
            col.set_ylabel('name', fontsize=30)
            

plt.subplots_adjust(wspace=0, hspace=0, left=0, bottom=0, right=1, top=1)
plt.savefig('example.png', bbox_inches='tight', format='png')
plt.show()
python python-3.x matplotlib image-processing latex
1个回答
0
投票
  1. 我不明白为什么你需要特定的尺寸。根据最终文档中图像的缩放比例,尺寸将变得无关紧要。

  2. 不幸的是,我没有针对这些差距的直接解决方案,但由于我想知道为什么不在 numpy 中组合图像然后使用 matplotlib 进行标记,我根据您的代码进行了一些尝试(顺便说一下,感谢非常好的示例代码!):

from PIL import Image
import numpy as np
import matplotlib.pyplot as plt

cols = 9
rows = 7

img_size = (256, 256)
dpi = 500
fig = plt.figure(figsize=(13, 9), dpi=dpi)

# generating a single image 
idx = 0
image = np.array([])
for row_idx in range(rows):
    colors = ['grey', 'blue']  # used to crate a chessboard pattern, which was better for visual feedback

    images = [Image.new('RGB', (256, 256), color=colors[(row_idx + i) % 2]) for i in range(cols)]
    row_image = np.concatenate(images, axis=1)
    if row_idx == 0:
        image = row_image
    else:
        image = np.concatenate((image, row_image))

plt.imshow(image, origin="lower")
axes = plt.gca()
axes.spines['top'].set_visible(False)
axes.spines['bottom'].set_visible(False)
axes.spines['left'].set_visible(False)
axes.set_xticks([])

axes.set_yticks([128 + idx * 256 for idx in range(rows)])
axes.set_yticklabels(["Name" for _ in range(rows)], rotation=90, fontsize=30, va="center")  # va="center" centers the label nicely

plt.subplots_adjust(wspace=0, hspace=0, left=0, bottom=0, right=1, top=1)

plt.savefig('example1.pdf', bbox_inches='tight', format='pdf') 
plt.savefig('example1.png', bbox_inches='tight', format='png')  
plt.show()

  1. 为了避免由于分辨率问题导致的可读性困难,最好使用矢量格式。我不确定 LaTeX 是否可以处理 .svg。因此我尝试了 .pdf 导出,效果很好。此外,如果您在 .png 中也使用 500 的 dpi,则即使对于非常大的缩放(超出对 LaTeX 文档有用的东西),标签也易于阅读。因此,我建议选择其中一种选择。
© www.soinside.com 2019 - 2024. All rights reserved.