如何在matplotlib中设置figsize和dpi,使图像具有所需的大小和质量?

v9tzhpje  于 2023-05-07  发布在  其他
关注(0)|答案(1)|浏览(253)

我需要把这些图像合成一个。我想得到的图像由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。
1.我的第二个问题是,尽管设置了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()
up9lanfz

up9lanfz1#

1.我不明白为什么你需要具体的尺寸。根据最终文档中图像的缩放比例,尺寸将变得无关紧要。
1.不幸的是,我没有一个直接的解决方案来解决这些差距,但是因为我想知道为什么不在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文档的有用范围)。因此,我建议选择其中一种。

相关问题