Kev1n91
Kev1n91

Reputation: 3693

Removing the white border around an image when using matplotlib without saving the image

I have the following code:

#load in image
image = cv2.imread('lenna.png')
title = "foo"

ax = plt.axes([0,0,1,1])
ax.clear()
height, width = image.shape[:2]
ax.axis('off')
ax.set_title(title)

#some things plotted etc.

But then I need the figure as numpy array for further computation, so I am doing the following:

masked_image = image
ax.imshow(masked_image.astype(np.uint8),interpolation="nearest")
ax.figure.canvas.draw()
w,h = ax.figure.get_size_inches()*ax.figure.get_dpi()
I = np.fromstring(ax.figure.canvas.tostring_rgb(),dtype=np.uint8).reshape(int(h),int(w),3)

#Has the white borders around it
Image.fromarray(I)

However, I still has now white borders around it, is there an easy way to remove the white borders without saving the figure?

The image I used is the following:

enter image description here

which does not have any white borders around it

However after the code above, it looks like the following: enter image description here

Which now has white bars around it.

Other already posted solution to this are all relying on saving the image, which I do not want

Upvotes: 11

Views: 8527

Answers (1)

ImportanceOfBeingErnest
ImportanceOfBeingErnest

Reputation: 339660

It doesn't actually matter if you save the figure or not. There are two conditions that need to be fulfilled to have no whitespace around an image.

1. Figure margins

You need to have no space between axes and figure edge. This can be achieved via setting the subplot params

fig, ax = plt.subplots()
fig.subplots_adjust(0,0,1,1)

or by manually setting the axes position

fig= plt.figure()
fig.add_axes([0,0,1,1])

The latter is the approach you took in the question, so this part is fine.

2. The figure aspect

Images are shown with an equal aspect, which means that each pixel is squared. This is usually desired for images, but it leads to axes not expanding to both directions equally.
The problem you face here is caused by the figure having a different aspect than the image.

Say you have an image of shape (n,m) (m pixels wide, n pixels high); then the necessary condition to get no whitespace around your image is that

n/m == h/w

where w, h are the figure width and height, respectively.

So you may directly set the figure size to the array shape times the dpi,

fig, ax = plt.subplots(figsize=(m*100,n*100), dpi=100)

or any other multiple in case you do not need to have one pixel per pixel in the output. In case you do not care about the figure size at all, but still need a figure with the same aspect as the image you may use figaspect

figsize=plt.figaspect(image)

To provide a full working examples here, the following creates a figure with an image which has no whitespace around it.

import matplotlib.pyplot as plt
import numpy as np

a = np.random.rand(5,3)

fig, ax = plt.subplots(figsize=plt.figaspect(a))
fig.subplots_adjust(0,0,1,1)
ax.imshow(a)

plt.show()

Upvotes: 14

Related Questions