matplotlib: Stretch image to cover the whole figure

元气小坏坏 提交于 2021-02-18 22:53:58

问题


I am quite used to working with matlab and now trying to make the shift matplotlib and numpy. Is there a way in matplotlib that an image you are plotting occupies the whole figure window.

import numpy as np
import matplotlib.pyplot as plt

# get image im as nparray
# ........

plt.figure()
plt.imshow(im)
plt.set_cmap('hot')

plt.savefig("frame.png")

I want the image to maintain its aspect ratio and scale to the size of the figure ... so when I do savefig it exactly the same size as the input figure, and it is completely covered by the image.

Thanks.


回答1:


I did this using the following snippet.

#!/usr/bin/env python
import numpy as np
import matplotlib.cm as cm
import matplotlib.mlab as mlab
import matplotlib.pyplot as plt
from pylab import *

delta = 0.025
x = y = np.arange(-3.0, 3.0, delta)
X, Y = np.meshgrid(x, y)
Z1 = mlab.bivariate_normal(X, Y, 1.0, 1.0, 0.0, 0.0)
Z2 = mlab.bivariate_normal(X, Y, 1.5, 0.5, 1, 1)
Z = Z2-Z1  # difference of Gaussians
ax = Axes(plt.gcf(),[0,0,1,1],yticks=[],xticks=[],frame_on=False)
plt.gcf().delaxes(plt.gca())
plt.gcf().add_axes(ax)
im = plt.imshow(Z, cmap=cm.gray)

plt.show()

Note the grey border on the sides is related to the aspect rario of the Axes which is altered by setting aspect='equal', or aspect='auto' or your ratio.

Also as mentioned by Zhenya in the comments Similar StackOverflow Question mentions the parameters to savefig of bbox_inches='tight' and pad_inches=-1 or pad_inches=0




回答2:


You can use a function like the one below. It calculates the needed size for the figure (in inches) according to the resolution in dpi you want.

import numpy as np
import matplotlib.pyplot as plt

def plot_im(image, dpi=80):
    px,py = im.shape # depending of your matplotlib.rc you may 
                              have to use py,px instead
    #px,py = im[:,:,0].shape # if image has a (x,y,z) shape 
    size = (py/np.float(dpi), px/np.float(dpi)) # note the np.float()

    fig = plt.figure(figsize=size, dpi=dpi)
    ax = fig.add_axes([0, 0, 1, 1])
    # Customize the axis
    # remove top and right spines
    ax.spines['right'].set_color('none')
    ax.spines['left'].set_color('none')
    ax.spines['top'].set_color('none')
    ax.spines['bottom'].set_color('none')
    # turn off ticks
    ax.xaxis.set_ticks_position('none')
    ax.yaxis.set_ticks_position('none')
    ax.xaxis.set_ticklabels([])
    ax.yaxis.set_ticklabels([])

    ax.imshow(im)
    plt.show()



回答3:


Here's a minimal object-oriented solution:

fig = plt.figure(figsize=(8, 8))
ax = fig.add_axes([0, 0, 1, 1], frameon=False, xticks=[], yticks=[])

Testing it out with

ax.imshow([[0]])
fig.savefig('test.png')

saves out a uniform purple block.

edit: As @duhaime points out below, this requires the figure to have the same aspect as the axes.

If you'd like the axes to resize to the figure, add aspect='auto' to imshow.

If you'd like the figure to resize to be resized to the axes, add

from matplotlib import tight_bbox
bbox = fig.get_tightbbox(fig.canvas.get_renderer())
tight_bbox.adjust_bbox(fig, bbox, fig.canvas.fixed_dpi) 

after the imshow call. This is the important bit of matplotlib's tight_layout functionality which is implicitly called by things like Jupyter's renderer.



来源:https://stackoverflow.com/questions/9642053/matplotlib-stretch-image-to-cover-the-whole-figure

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!