【问题标题】:Matplotlib: Inconsistent results with imagesMatplotlib:与图像不一致的结果
【发布时间】:2019-04-09 19:21:11
【问题描述】:

我正在尝试使用 matplotlib 在图中绘制多个图像。

基本上,我使用 PIl 库读取图像,将其转换为 numpy 数组并对其进行一些操作(将一行中的元素设置为零)。到目前为止一切正常。但是当我尝试使用 matplotlib 保存结果时,我得到的结果不一致。

请看一下我的代码。

导入库

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

加载文件

fileName = 'n01978287_43.jpg'
img = PI.open(fileName)
size = 224
img = img.resize((size, size))
img = np.asarray(img, dtype=np.uint8).astype(np.float32)
img = img/255

结果 1

temp_img = np.copy(img)
temp_img[51, :, :] = 0*temp_img[51, :, :]
fig = plt.figure()
ax1 = plt.subplot(1, 6, 1)
ax1.imshow(img, interpolation='none')
ax2 = plt.subplot(1, 6, 2)
ax2.imshow(temp_img, interpolation='none')
plt.savefig('test_516.png') 
plt.close(fig) 

结果 2

temp_img = np.copy(img)
temp_img[52, :, :] = 0*temp_img[52, :, :]
fig = plt.figure()
ax1 = plt.subplot(1, 6, 1)
ax1.imshow(img, interpolation='none')
ax2 = plt.subplot(1, 6, 2)
ax2.imshow(temp_img, interpolation='none')
plt.savefig('test_526.png') 
plt.close(fig) 

结果 3

temp_img = np.copy(img)
temp_img[51, :, :] = 0*temp_img[51, :, :]
fig = plt.figure()
ax1 = plt.subplot(1, 2, 1)
ax1.imshow(img, interpolation='none')
ax2 = plt.subplot(1, 2, 2)
ax2.imshow(temp_img, interpolation='none')
plt.savefig('test_512.png') 
plt.close(fig)

结果 4

temp_img = np.copy(img)
temp_img[56, :, :] = 0*temp_img[56, :, :]
fig = plt.figure()
ax1 = plt.subplot(1, 2, 1)
ax1.imshow(img, interpolation='none')
ax2 = plt.subplot(1, 2, 2)
ax2.imshow(temp_img, interpolation='none')
plt.savefig('test_562.png') 
plt.close(fig)

现在,如果您查看结果,您会注意到不一致之处。

  • 首先,对于前两张图像(6 轴图形),您仅在其中一张图像中看到黑线。 (如果您将所有行清零(一次一个)然后尝试保存结果,则有一种模式。
  • 在最后两张图像中,黑线变粗。 (在这种情况下我没有找到任何模式)。

系统设置 - Python3、Matplotlib3、PIL、Numpy

更新:

在寻找以所需分辨率(在本例中为 224*224)保存图形的方法后,我编写了以下代码(使用来自网络的多个资源)。

导入库并加载图片文件

import numpy as np
import matplotlib.pyplot as plt
from PIL import Image, ImageDraw, ImageFont

fileName = 'n01978287_43.jpg'
img = Image.open(fileName)
size = 224
img = img.resize((size, size))
img = np.asarray(img, dtype=np.uint8).astype(np.float32)
img = img/255

绘制图像网格的功能

def plt_save(grid, idx, name):

    nRows = len(grid)
    nCols = len(grid[0])
    print('Clearing figure')
    plt.rcParams.update({'font.size': 8})
    wFig = (nCols+2) # Figure width (two more than nCols because I want to add ylabels on the very left and very right of figure)
    hFig = (nRows+1) # Figure height (one more than nRows becasue I want to add xlabels to the top of figure)
    fig = plt.figure(figsize=( wFig, hFig )) 
    fig.subplots_adjust(left=0, bottom=0, right=1, top=1, wspace=0, hspace=0)

    fig.patch.set_facecolor('grey')

    for r in range(nRows):
        for c in range(nCols):

            ax = plt.subplot2grid( shape=[hFig, wFig], loc=[r+1, c+1] )  
            im= ax.imshow(grid[r][c], interpolation='none')
            ax.spines['bottom'].set_visible(False)
            ax.spines['top'].set_visible(False)
            ax.spines['right'].set_visible(False)
            ax.spines['left'].set_visible(False)
            ax.set_xticks([])
            ax.set_yticks([])
            #fig.colorbar(im, ax=ax)
            #ax.set_aspect('auto')

            if not r:
                ax.set_title('Image',
                             rotation=22.5,
                             horizontalalignment='left',
                             verticalalignment='bottom')

            if not c:
                ax.set_ylabel('leftLabel',
                             rotation=0,
                             horizontalalignment='right',
                             verticalalignment='center')

            if c == wFig-3:
                ax2 = ax.twinx()
                #ax2.axis('off')
                ax2.set_xticks([])
                ax2.set_yticks([])
                ax2.spines['top'].set_visible(False)
                ax2.spines['right'].set_visible(False)
                ax2.spines['bottom'].set_visible(False)
                ax2.spines['left'].set_visible(False)
                ax2.set_ylabel( 'rightLabel',
                                rotation=0,
                                verticalalignment='center',
                                horizontalalignment='left' )

    print('Saving file')
    plt.savefig( ( str(idx) + '_' + name + '_' + fileName.split('.')[0] + '.png'), 
                 orientation='landscape', 
                 #bbox_inches='tight', 
                 facecolor = fig.get_facecolor(),
                 dpi=224, # DPI is 224 becasue the axis size is 1x1 inch and I want 224x224 pixels in each axis
                 transparent=True, 
                 frameon=False )
    plt.close(fig)

循环将图像的行清零(一次一个)

for i in range(0, 224):
    temp_img = np.copy(img)
    temp_img[i, :, :] = 0*temp_img[i, :, :]
    # 1*4 Grid of images (can vary based on the requirement)
    grid = [img, temp_img, img, temp_img]
    grid = [grid, grid] #2*4 grid of images
    plt_save(grid, i, 'PLT_')

这是 224 张图片中的一张的样子。

问题是,只要我坚持这种情节,它就可以完美运行。但是当我尝试进行一些更改时(例如添加颜色条,每个轴之间有一些空间等),图像分辨率会发生变化。如果我在保存图形时使用 bbox_inches = 'tight',它会调整所有内容,但会更改原始分辨率,同时保持图形大小不变。

有没有其他类似于bbox_inches='tight'的方式,可以在相应调整图形大小的同时保持轴分辨率固定。或者如果matplotlib中没有这样的东西,你能建议我用其他方法来合并颜色条(轴之间的小空间,每个轴的ylabel等),同时保持图像分辨率固定。

【问题讨论】:

    标签: python python-3.x matplotlib


    【解决方案1】:

    您开始使用的图像高度为 224 像素。

    在前两种情况下,您将这些超过 72 像素的像素分布在生成的图像中。这意味着图像的任何一行都有 72/224=32% 的机会出现在最终图中。在第 52 行中,您很幸运,并获得了这三分之一的机会。

    在后两种情况下,生成的图像高度为 226 像素(即仅比原始图像稍大)。在这里,您有 2/224=0.9% 的机会,一行将占用两个像素。在行号的情况下。 56 你碰上了那个倒霉的机会。

    【讨论】:

    • 嘿,你能帮我解决我在修改后的问题中提到的问题吗?我没有单独把它放在那里,因为这两个问题都是相关的。
    • 我猜你需要根据添加的空格、颜色条等计算新的图形大小。这确实很麻烦。
    猜你喜欢
    • 2022-01-16
    • 1970-01-01
    • 2012-03-04
    • 1970-01-01
    • 1970-01-01
    • 2022-11-04
    • 2021-01-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多