11

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

2
  • It's a bit hard to understand, why you would do that at all. image is a numpy array already. Why producing a plot and saving as numpy array again? Commented Apr 6, 2018 at 14:04
  • I left that out, cause it is not really related to the question. There will be text and bounding boxes added to the plot with the help of matplotlib. Commented Apr 6, 2018 at 14:06

1 Answer 1

15

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()
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.