Reputation: 3693
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:
which does not have any white borders around it
However after the code above, it looks like the following:
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
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.
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.
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