Vivek
Vivek

Reputation: 315

Remove whitespace in matplotlib when plotting on top of image

I have tried many methods, but none seem to work. Everywhere I look people say set bbox_inches='tight' but that doesn't seem to work.

Basically my goal is to plot some points on top of the image in pixel coordinates and then save it without the any whitespace around the border. My code currently looks like this:

import matplotlib.pyplot as plt
plt.ion()
img = plt.imread('myimage.jpg')
ymax, xmax, _ = img.shape
plt.imshow(img, extent=[0,xmax,ymax,0]) # switch to pixel coords
plt.plot([100,200,300],[100,200,300],'ro')
plt.imshow(img, extent=[0,xmax,ymax,0]) # recenter plot
plt.axis('off')
plt.savefig('out.jpg', bbox_inches='tight', pad_inches=0)

But my saved image still have a white border around it. How can I fix this?

Upvotes: 1

Views: 2814

Answers (1)

hashmuke
hashmuke

Reputation: 3335

It seems the bbox_inches='tight' option tries to fit your figure with axis ticks in mind. In order to avoid that you can provide the the actual extent of the figure to plt.savefig method.

import matplotlib.pyplot as plt
img = plt.imread('myimage.jpg')

ymax, xmax, _ = img.shape
plt.imshow(img, extent=[0,xmax,ymax,0]) # switch to pixel coords
plt.plot([100,200,300],[100,200,300],'ro')
plt.imshow(img, extent=[0,xmax,ymax,0]) # recenter plot
plt.axis('off')

# get figure and axis handle 
fig = plt.gcf()
ax = plt.gca()
# get axis extent
extent = ax.get_window_extent().transformed(fig.dpi_scale_trans.inverted())
plt.savefig('out.jpg', bbox_inches=extent)

If, for some reason, you want to add a small white edge to your figure, you can still do that; just expand the extent as follow

extent2 = extent.expanded(1.01, 1.01)
plt.savefig('out.jpg', bbox_inches=extent2)

An other option will be to get-rid off the axis boundary completely using matehat's suggestion.

import matplotlib.pyplot as plt


img = plt.imread('myimage.jpg')
ymax, xmax, _ = img.shape
my_dpi = 80.
my_figsize = [xmax/my_dpi, ymax/my_dpi]
fig  = plt.figure(figsize=my_figsize, dpi=my_dpi)
ax = plt.Axes(fig, [0., 0., 1., 1.])
ax.set_axis_off()
fig.add_axes(ax)

h_im = ax.imshow(img, aspect = 'equal', extent=[0,xmax,ymax,0])
plt.plot([100,200,300],[100,200,300],'ro')
plt.axis(h_im.get_extent())
plt.savefig('out.jpg', dpi = my_dpi)

Although the final image has the original image size there is a sub-pixle difference between the two images. The figure below shows the difference between the myimage.jpg and out.jpg.

Difference between original image and output image

Upvotes: 1

Related Questions