Matplotlib plots: removing axis, legends and white

2019-01-02 14:28发布

I'm new to Python and Matplotlib, I would like to simply apply colormap to an image and write the resulting image, without using axes, labels, titles or anything usually automatically added by matplotlib. Here is what I did:

def make_image(inputname,outputname):
    data = mpimg.imread(inputname)[:,:,0]
    fig = plt.imshow(data)
    fig.set_cmap('hot')
    fig.axes.get_xaxis().set_visible(False)
    fig.axes.get_yaxis().set_visible(False)
    plt.savefig(outputname)

It successfully removes the axis of the figure, but the figure saved presents a white padding and a frame around the actual image. How can I remove them (at least the white padding)? Thanks

8条回答
柔情千种
2楼-- · 2019-01-02 14:55

No one mentioned imsave yet, which makes this a one-liner:

import matplotlib.pyplot as plt
import numpy as np

data = np.arange(10000).reshape((100, 100))
plt.imsave("/tmp/foo.png", data, format="png", cmap="hot")

It directly stores the image as it is, i.e. does not add any axes or border/padding.

enter image description here

查看更多
人间绝色
3楼-- · 2019-01-02 15:00

I learned this trick from matehat, here:

import matplotlib.pyplot as plt
import numpy as np

def make_image(data, outputname, size=(1, 1), dpi=80):
    fig = plt.figure()
    fig.set_size_inches(size)
    ax = plt.Axes(fig, [0., 0., 1., 1.])
    ax.set_axis_off()
    fig.add_axes(ax)
    plt.set_cmap('hot')
    ax.imshow(data, aspect='equal')
    plt.savefig(outputname, dpi=dpi)

# data = mpimg.imread(inputname)[:,:,0]
data = np.arange(1,10).reshape((3, 3))

make_image(data, '/tmp/out.png')

yields

enter image description here

查看更多
不再属于我。
4楼-- · 2019-01-02 15:05

I think that the command axis('off') takes care of one of the problems more succinctly than changing each axis and the border separately. It still leaves the white space around the border however. Adding bbox_inches='tight' to the savefig command almost gets you there, you can see in the example below that the white space left is much smaller, but still present.

from numpy import random
import matplotlib.pyplot as plt

data = random.random((5,5))
img = plt.imshow(data, interpolation='nearest')
img.set_cmap('hot')
plt.axis('off')
plt.savefig("test.png", bbox_inches='tight')

enter image description here

查看更多
公子世无双
5楼-- · 2019-01-02 15:08

This should remove all padding and borders:

from matplotlib import pyplot as plt

fig = plt.figure()
fig.patch.set_visible(False)

ax = fig.add_subplot(111)

plt.axis('off')
plt.imshow(data)

extent = ax.get_window_extent().transformed(fig.dpi_scale_trans.inverted())
plt.savefig("../images/test.png", bbox_inches=extent)
查看更多
不再属于我。
6楼-- · 2019-01-02 15:09

I liked ubuntu's answer, but it was not showing explicitly how to set the size for non-square images out-of-the-box, so I modified it for easy copy-paste:

import matplotlib.pyplot as plt
import matplotlib.image as mpimg
import numpy as np

def save_image_fix_dpi(data, dpi=100):
    shape=np.shape(data)[0:2][::-1]
    size = [float(i)/dpi for i in shape]

    fig = plt.figure()
    fig.set_size_inches(size)
    ax = plt.Axes(fig,[0,0,1,1])
    ax.set_axis_off()
    fig.add_axes(ax)
    ax.imshow(data)
    fig.savefig('out.png', dpi=dpi)
    plt.show()

Saving images without border is easy whatever dpi you choose if pixel_size/dpi=size is kept.

data = mpimg.imread('test.png')
save_image_fix_dpi(data, dpi=100)

enter image description here

However displaying is spooky. If you choose small dpi, your image size can be larger than your screen and you get border during display. Nevertheless, this does not affect saving.

So for

save_image_fix_dpi(data, dpi=20)

The display becomes bordered (but saving works): enter image description here

查看更多
若你有天会懂
7楼-- · 2019-01-02 15:15

You can also specify the extent of the figure to the bbox_inches argument. This would get rid of the white padding around the figure.

def make_image(inputname,outputname):
    data = mpimg.imread(inputname)[:,:,0]
    fig = plt.imshow(data)
    fig.set_cmap('hot')
    ax = fig.gca()
    ax.set_axis_off()
    ax.autoscale(False)
    extent = ax.get_window_extent().transformed(plt.gcf().dpi_scale_trans.inverted())
    plt.savefig(outputname, bbox_inches=extent)
查看更多
登录 后发表回答