17
votes

I am plotting an image in matplotlib, and it keeps giving me some padding. This is what I have tried:

def field_plot():
    x = [i[0] for i in path]
    y = [i[1] for i in path]
    plt.clf()
    plt.axis([0, 560, 0, 820])
    im = plt.imread('field.jpg')
    field = plt.imshow(im)
    for i in range(len(r)):
        plt.plot(r[i][0],r[i][1],c=(rgb_number(speeds[i]),0,1-rgb_number(speeds[i])),linewidth=1)
    plt.axis('off')
    plt.savefig( IMG_DIR + 'match.png',bbox_inches='tight', transparent="True")
    plt.clf()

This is how i see the image

5
Where in the image is the padding you're referring to? Also, your example is not very useful since we can't run it without your image file. - BrenBarn
@BrenBarn On the left and below the image are the biggest paddings. Above and on the right I have smaller paddings. It's like if it leaves space for labels and so - andresmechali
Can you provide a runnable example that doesn't rely on external files? Also see previous questions here and here. If those don't work, please explain what they don't do that you need them to do. - BrenBarn
@BrenBarn I am very new to this, so I don't know how to provide a better example for this.. I am very sorry, I don't know how to think it without the images.. :( - andresmechali
@Tshepang I have attached the image as it is saved. As you may see if you download it, it has white big paddings. r is a list, which has [x,x+1],[y,y+1] for every point (the coordinates of each plot) - andresmechali

5 Answers

16
votes

Try using pad_inches=0, i.e.

plt.savefig( IMG_DIR + 'match.png',bbox_inches='tight', transparent="True", pad_inches=0)

From the documentation:

pad_inches: Amount of padding around the figure when bbox_inches is ‘tight’.

I think the default is pad_inches=0.1

5
votes

This worked for me. After plotting, get the Axes object from plt using ax = plt.gca(). Then set the xlim, and ylim of ax object to match image width and image height. Matplotlib seems to automatically increase xlim and ylim of viewing area when you plot. Note that while setting y_lim you have to invert the order of coordinates.

for i in range(len(r)):
  plt.plot(r[i][0],r[i][1],c=(rgb_number(speeds[i]),0,1-rgb_number(speeds[i])),linewidth=1)

plt.axis('off')
ax = plt.gca();
ax.set_xlim(0.0, width_of_im);
ax.set_ylim(height_of_im, 0.0);
plt.savefig( IMG_DIR + 'match.png',bbox_inches='tight', transparent="True")
5
votes

Just add plt.tight_layout() before plt.savefig() !!

plt.figure(figsize=(16, 10))

# ... Doing Something ...

plt.tight_layout()
plt.savefig('wethers.png')
plt.show()
3
votes

All previous approaches didn't quite work for me, they all left some padding around the figure.

The following lines successfully removed the white or transparent padding that was left:

plt.axis('off')
ax = plt.gca()
ax.xaxis.set_major_locator(matplotlib.ticker.NullLocator())
ax.yaxis.set_major_locator(matplotlib.ticker.NullLocator())
plt.savefig(IMG_DIR + 'match.png', pad_inches=0, bbox_inches='tight', transparent=True)
1
votes

Use plt.gca().set_position((0, 0, 1, 1)) to let the axes span the whole figure, see reference. If plt.imshow is used, this requires that the figure has the correct aspect ratio.

import matplotlib as mpl
import matplotlib.pyplot as plt

# set the correct aspect ratio
dpi = mpl.rcParams["figure.dpi"]
plt.figure(figsize=(560/dpi, 820/dpi))

plt.axis('off')
plt.gca().set_position((0, 0, 1, 1))

im = plt.imread('field.jpg')
plt.imshow(im)

plt.savefig("test.png")
plt.close()