removing all white margins from plt.show() when trying do show an image - matplotlib

hello i'm trying to load an image and display it without having any margins
I could not find any solution to this and would appreciate assistance
code:
from matplotlib.image import imread
import matplotlib.pyplot as plt
path = 'some legal image path'
im = imread(path)
fig, ax = plt.subplots(figsize=plt.figaspect(im))
plt.axis('off')
fig.subplots_adjust(0, 0, 1, 1)
ax.imshow(im)
plt.show()
this still produces margins
enter image description here

Related

display image with maximum width keeping an equal ratio

How to display an image with imshow on all the width of an axe (viewport) but keeping the ratio 'equal' ?
import matplotlib.pyplot as plt
import numpy as np
fig, ax = plt.subplots(nrows=2, figsize=(8,8))
img = ax[0].imshow(np.random.random((10,10)), aspect='equal')
line = ax[1].plot([12,34],[45,78])
I would like that the image width be aligned on the line plot keeping an equal ratio even if that implies having blank around. My application has a zooming feature coded on the image in fact so I would to offer all the width possible for its display.
So in few words, I would like the same width as with aspect='auto' but with square pixels.
Is it possible ? Thanks.
Found with a reading of Axes class - set explicitly size (width/height) of axes in given units
and the use of
set_adjustable('datalim')
import matplotlib.pyplot as plt
import numpy as np
fig, ax = plt.subplots(nrows=2, figsize=(8,8))
img = ax[0].imshow(np.random.random((10,10)), aspect='equal')
ax[0].set_adjustable('datalim')
line = ax[1].plot([12,34],[45,78])

Plotting a rasterio raster on a Cartopy GeoAxes

I've seen a few other questions on this topic, but the library has changed enough that the answers to those no longer seem to apply.
Rasterio used to include an example for plotting a rasterio raster on a Cartopy GeoAxes. The example went roughly like this:
import matplotlib.pyplot as plt
import rasterio
from rasterio import plot
import cartopy
import cartopy.crs as ccrs
world = rasterio.open(r"../tests/data/world.rgb.tif")
fig = plt.figure(figsize=(20, 12))
ax = plt.axes(projection=ccrs.InterruptedGoodeHomolosine())
ax.set_global()
plot.show(world, origin='upper', transform=ccrs.PlateCarree(), interpolation=None, ax=ax)
ax.coastlines()
ax.add_feature(cartopy.feature.BORDERS)
However, this code no longer draws the raster. Instead, I get something like this:
It should look like this:
When I asked about this in the rasterio issues tracker, they told me the example was deprecated (and deleted the example). Still, I wonder if there's some way to do what I'm trying to do. Can anyone point me in the right direction?
I think you may want to read the data to a numpy.ndarray and plot it using ax.imshow, where ax is your cartopy.GeoAxes (as you have it already). I offer an example of what I mean, below.
I clipped a small chunk of Landsat surface temperature and some agricultural fields for this example. Get them on this drive link.
Note fields are in WGS 84 (epsg 4326), Landsat image is in UTM Zone 12 (epsg 32612), and I want my map in Lambert Conformal Conic. Cartopy makes this easy.
import numpy as np
import cartopy.crs as ccrs
from cartopy.io.shapereader import Reader
from cartopy.feature import ShapelyFeature
import rasterio
import matplotlib.pyplot as plt
def cartopy_example(raster, shapefile):
with rasterio.open(raster, 'r') as src:
raster_crs = src.crs
left, bottom, right, top = src.bounds
landsat = src.read()[0, :, :]
landsat = np.ma.masked_where(landsat <= 0,
landsat,
copy=True)
landsat = (landsat - np.min(landsat)) / (np.max(landsat) - np.min(landsat))
proj = ccrs.LambertConformal(central_latitude=40,
central_longitude=-110)
fig = plt.figure(figsize=(20, 16))
ax = plt.axes(projection=proj)
ax.set_extent([-110.8, -110.4, 45.3, 45.6], crs=ccrs.PlateCarree())
shape_feature = ShapelyFeature(Reader(shapefile).geometries(),
ccrs.PlateCarree(), edgecolor='blue')
ax.add_feature(shape_feature, facecolor='none')
ax.imshow(landsat, transform=ccrs.UTM(raster_crs['zone']),
cmap='inferno',
extent=(left, right, bottom, top))
plt.savefig('surface_temp.png')
feature_source = 'fields.shp'
raster_source = 'surface_temperature_32612.tif'
cartopy_example(raster_source, feature_source)
The trick with Cartopy is to remember to use the projection keyword for your axes object, as this renders the map in a nice projection of your choice (LCC in my case). Use transform keyword to indicate what projection system your data is in, so Cartopy knows how to render it.
No need of rasterio. Get a bluemarble image, then plot it.
Here is the working code:
import cartopy
import matplotlib.pyplot as plt
import cartopy.crs as ccrs
fig = plt.figure(figsize=(10, 5))
ax = plt.axes(projection=ccrs.InterruptedGoodeHomolosine())
# source of the image:
# https://eoimages.gsfc.nasa.gov/images/imagerecords/73000/73909/world.topo.bathy.200412.3x5400x2700.jpg
fname = "./world.topo.bathy.200412.3x5400x2700.jpg"
img_origin = 'lower'
img = plt.imread(fname)
img = img[::-1]
ax.imshow(img, origin=img_origin, transform=ccrs.PlateCarree(), extent=[-180, 180, -90, 90])
ax.coastlines()
ax.add_feature(cartopy.feature.BORDERS)
ax.set_global()
plt.show()
The output plot:

Skimage resize function returns black images

I'm trying to resize some images that I've loaded using matplotlib's imread function.
An example:
plt.figure()
plt.imshow(imgs[0])
plt.colorbar()
plt.grid(False)
plt.show()
However, when I try to apply the resize function and then replot:
def rescale_image(img):
"""Rescale the jpg range of 0-255 to 0-1"""
img = resize(img, (100, 100), anti_aliasing=True)
return img /255
#imgs = [rescale_image(i) for i in imgs]
io = rescale_image(imgs[0])
plt.figure()
plt.imshow(io)
plt.colorbar()
plt.grid(False)
plt.show()
The result is:
Why?
UPDATE: The import statements:
%matplotlib inline
import matplotlib.pyplot as plt
from matplotlib.image import imread
from skimage.transform import resize
imgs = [imread(p) for p in paths_list]# paths list is generated by glob.glob on the folder of images
Your image starts out with pixels in the range 0..1. When you resize it, you divide by 255, so the range is now 0..0.003 so it looks black.
Solution?
Change this line:
return img /255
to this:
return img

How to resave image without borders in matplotlib

I am just want to show and then save the same image on plot but got borders.
import numpy as np
import skimage.io
import matplotlib
import matplotlib.pyplot as plt
fileName = "1.jpg"
image=mpimg.imread(fileName)
height, width = image.shape[:2]
my_dpi = 96 / 2
fg, ax = plt.subplots(1, figsize=(1080/my_dpi, 1920/my_dpi), dpi=my_dpi)
ax.set_ylim(height, 0)
ax.set_xlim(0, width)
ax.axis('off')
ax.imshow(image.astype(np.uint8))
plt.savefig("res.png")
Source image:
Result image after resaving:
How to remove the borders and make the result image be the same as original without borders?

Matplotlib - sequence is off when using plt.imshow()

I write a dog-classifier in a Jupyter notebook that, every time a dog is detected in an image, should show the image and print some text describing it. Somehow, the images are always displayed after all the text was printed, no matter in which order I put plt.imshow() and print(). Does anybody know why this is the case?
Thank you!
Here is my code-snippet:
for i in range (0, 1,1):
all_counter+=1
if dog_detector(dog_files_short[i]):
img = image.load_img(dog_files_short[i], target_size=(224, 224))
plt.show()
plt.imshow(img)
time.sleep(5)
print("That's a dog!!!!")
dog_counter+=1
print("______________")
else:
print("______________")
img = image.load_img(dog_files_short[i], target_size=(224, 224))
plt.show()
plt.imshow(img)
print("No Doggo up here :(")
print(ResNet50_predict_labels(dog_files_short[i]))
print("______________")
print((dog_counter/all_counter)*100, "% of the dog pictures are classified as dogs")
The output is like this:
It seems you are using Juypter notebook. This always shows any autogenerated output (like the matplotlib figures) last in the output.
You may use IPython.display.display to display the figures at the position of the output where they belong.
import matplotlib.pyplot as plt
import numpy as np
from IPython.display import display
images = [np.random.rayleigh((i+1)/8., size=(180, 200, 3)) for i in range(4)]
dog_detector = lambda x: np.random.choice([True,False])
dog_counter = 0
for i in range(len(images)):
if dog_detector(images[i]):
dog_counter+=1
fig, ax = plt.subplots(figsize=(3,2))
ax.imshow(images[i])
display(fig)
display("That's a dog!!!!")
display("______________")
else:
display("______________")
fig, ax = plt.subplots(figsize=(3,2))
ax.imshow(images[i])
display(fig)
display("No Doggo up here :(")
display("______________")
perc = (dog_counter/float(len(images)))*100
display("{}% of the dog pictures are classified as dogs".format(perc))
plt.close()
Output:
I tried this in my ipython notebook, if I first call plt.imshow(img) and plt.show() right after I get the image first and the text after.