Hello I am trying to display a picture from an url using the Matplotlib module but the problem is the following :
When I execute the code the picture has not a good quality.
Here is my code :
import requests
from PIL import Image
from io import BytesIO
fig, ax = plt.subplots()
picture_url = "https://www.google.fr/images/branding/googlelogo/1x/googlelogo_color_272x92dp.png"
response = requests/get(picture_url)
img = Image.open(BytesIO(response.content))
ax.imshow(img)
plt.show()
Could you help me please ?
Thank you !
While some would say this is the type of answer only a 10x engineer could answer, in this case it only took a 2x!
Try this URL:
https://www.google.fr/images/branding/googlelogo/2x/googlelogo_color_272x92dp.png
The difference is in the "2x" in the URL, which provides a larger png!
The problem is that if the axes is not precisely as large as the image, the image will be interpolated. This results in little artifacts.
You can calculate the figure size and margins such that the image fits exactly into the axes.
import numpy as np
import matplotlib
matplotlib.use("TkAgg")
import matplotlib.pyplot as plt
import requests
from PIL import Image
from io import BytesIO
picture_url = "https://www.google.fr/images/branding/googlelogo/1x/googlelogo_color_272x92dp.png"
response = requests.get(picture_url)
img = np.array(Image.open(BytesIO(response.content)))
dpi = 100
bottom=0.2; left=0.1; right=0.9; top=0.9
width = img.shape[1]/(right-left)/dpi
height= img.shape[0]/(top-bottom)/dpi
fig, ax = plt.subplots(dpi=dpi, figsize=(width, height))
fig.subplots_adjust(bottom=bottom, left=left, right=right, top=top)
ax.imshow(img)
fig.savefig("googlelogo.png")
plt.show()
Related
I am trying to add an image as a layer on top of a figure to show a location of a few oceanographic weather buoys on a map.
It works for me up to a certain offset. When I go over a certain tuple number, my whole image gets dislocated and a large white space shows on the bottom. I am using bbox_inches=tight to save the figure the way I need.
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
from matplotlib.offsetbox import OffsetImage
from netCDF4 import Dataset as netcdf_dataset
import cartopy.crs as ccrs
varfigsizex=6
varfigsizey=7
fig = plt.figure(figsize=(varfigsizex, varfigsizey))
varllcrnrlon2=-121
varurcrnrlon2=-117
varllcrnrlat2=32.12
varurcrnrlat2=34.7
ax = plt.axes(projection=ccrs.PlateCarree())
ax.set_extent((varllcrnrlon2,varurcrnrlon2,varllcrnrlat2,varurcrnrlat2))
ax.coastlines()
buoy_img = mpimg.imread('buoy_img.png')
add_buoy = OffsetImage(buoy_img, zoom=0.4)
add_buoy.set_offset((230,720))
add_buoy.set_zorder(10)
ax.add_artist(add_buoy)
add_buoy_2 = OffsetImage(buoy_img, zoom=0.4)
add_buoy_2.set_offset((400,720))
add_buoy_2.set_zorder(10)
ax.add_artist(add_buoy_2)
add_buoy_3 = OffsetImage(buoy_img, zoom=0.4)
add_buoy_3.set_offset((650,590))
add_buoy_3.set_zorder(10)
ax.add_artist(add_buoy_3)
add_buoy_4 = OffsetImage(buoy_img, zoom=0.4)
add_buoy_4.set_offset((800,600))
add_buoy_4.set_zorder(10)
ax.add_artist(add_buoy_4)
name_file=''.join(['ca_buoy.png'])
fig.savefig(name_file, bbox_inches='tight', pad_inches=0, format='png', dpi=300)
When I add additional layer images that I need, for example with set_offset((1200,100):
add_buoy_5 = OffsetImage(buoy_img, zoom=0.4)
add_buoy_5.set_offset((1200,100))
add_buoy_5.set_zorder(10)
ax.add_artist(add_buoy_5)
this is what happens:
I would like some help to understand why this happens, and how to properly fix my code.
This question already has answers here:
Plt.show shows full graph but savefig is cropping the image
(3 answers)
Closed 1 year ago.
I am trying to save sns matplotlib output as jpg file and reopen it with cv2.
but i am facing distinct data loss, would someone help me to resolve, i tried in several savefig options and documentations.
sample code
import pandas as pd
import numpy as np
import cv2
import seaborn as sns
import matplotlib.pyplot as plt
by_c = None
fig = plt.Figure(figsize=(5, 4), dpi=100)
g = sns.FacetGrid(pd.DataFrame(np.random.random(10)*150, columns=['col']), col=None, row=None, height=3.5, aspect=1)
g.map_dataframe(sns.histplot, x='col')
plt.title('col'+' - '+str(by_c)+'-', fontsize=12)
plt.xlabel('Value')
plt.ylabel('Frequency')
plt.savefig('temp.png')
plt.show()
Out:
Saved picture example of 'temp.png'
out:
reopening image
im = cv2.imread('temp.png')
plt.imshow(im)
Out1:
Image title and lables sliced bit, i am not sure how else i can save it. Would someone please help to resolve it
To set the quality of the image use the dpi, and also specify the bbox_inches for a full layout. If not, it will consider the nearest view of the image
import pandas as pd
import numpy as np
import cv2
import seaborn as sns
import matplotlib.pyplot as plt
by_c = None
fig = plt.Figure(figsize=(5, 4), dpi=100)
g = sns.FacetGrid(pd.DataFrame(np.random.random(10)*150, columns=['col']), col=None, row=None, height=3.5, aspect=1)
g.map_dataframe(sns.histplot, x='col')
plt.title('col'+' - '+str(by_c)+'-', fontsize=12)
plt.xlabel('Value')
plt.ylabel('Frequency')
plt.savefig('temp.png',dpi=300, bbox_inches = "tight")
#plt.savefig('temp.png')
plt.show()
im = cv2.imread('temp.png')
plt.imshow(im)
Resultant Image:
How does matplotlib ensure that a dataset can be within plot with specified size.
How do i from a plot stored as numpy, How do i read the color of the pixels illustration a datapoint (0,4) - in the plot.
example:
import numpy as np
import matplotlib.pyplot as plt
import matplotlib
from PIL import Image
import librosa
import librosa.display
from matplotlib import cm
fig = plt.figure(figsize=(12,4))
min = -1.828067
max = 22.70058
data = np.random.uniform(low=min, high=max, size=(474,40))
librosa.display.specshow(data.T,sr=16000,x_axis='frames',y_axis='mel',hop_length=160,cmap=cm.jet)
plt.show()
raw_input("sadas")
convert = plt.get_cmap(cm.jet)
numpy_output_static = convert(data.T)
plt.imshow(numpy_output_static, aspect = 'auto')
plt.show()
raw_input("asds")
First plot being :
Second plot being:
so the first has been resized to plot size 12,4 where the last basically plots the same data but just using the data shape as size... how do i change that?
Librosa just performs pcolormesh according to the GitHub source code
You need to define another figure with its own size for the second figure.
import numpy as np
import matplotlib.pyplot as plt
import matplotlib
from PIL import Image
import librosa
import librosa.display
from matplotlib import cm
fig = plt.figure(figsize=(12,4))
min = -1.828067
max = 22.70058
data = np.random.uniform(low=min, high=max, size=(474,40))
librosa.display.specshow(data.T,sr=16000,x_axis='frames',y_axis='mel',hop_length=160,cmap=cm.jet)
plt.show()
raw_input("sadas")
convert = plt.get_cmap(cm.jet)
numpy_output_static = convert(data.T)
fig = plt.figure(figsize=(12,4))
plt.imshow(numpy_output_static, aspect = 'auto')
plt.show()
raw_input("asds")
I searched for other similar questions but that didn't solve my problem. Below is a simple code that generates an animation in the form of a gif image in matplotlib:
import numpy as np
import matplotlib.pylab as plt
import matplotlib.animation as anm
fig = plt.figure()
def draw(i):
x = np.linspace(0, 5, num = 1000)
y = np.sin(x-i*0.1)
plt.clf()
plt.plot(x, y, 'r-')
anim = anm.FuncAnimation(fig, draw, frames = 10, interval = 500, repeat = False)
anim.save('test.gif', fps = 1, writer = 'imagemagick')
This generates the animation I want but once I open the final image (with eog), it keeps repeating. Since I would be presenting animation in the presentation, I would like it to stop after it is shown once. As you can notice, I have added repeat = False in the FuncAnimation but that doesn't stop repeating the image. What is wrong with my code?
Thanks in advance
My solution to the problem was to change from imagemagick to pillow as a writer.
Try the following:
from matplotlib.animation import FuncAnimation, PillowWriter
anim = FuncAnimation(fig, update, frames=range(1, 51), interval=.001, repeat=False)
anim.save('test.gif', dpi=80, writer=PillowWriter(fps=5))
The quality of the image is a bit worse than with imagemagick from my opinion, but it's a much easier and faster solution.
Using PillowWriter didn't solve the problem for me, so I came up with a workaround: just remove the loop as a post-processing step with PIL. Here is the code:
from PIL import Image
import io
def convert(old_filename, new_filename, duration):
images = []
with Image.open(old_filename) as im:
for i in range(im.n_frames):
im.seek(i)
buf = io.BytesIO()
im.save(buf, format='png')
buf.seek(0)
images.append(Image.open(buf))
images[0].save(new_filename, save_all=True, append_images=images[1:], optimize=False, duration=duration)
convert("myAnimation.gif", "myAnimationNoLoop.gif", 100)
I'm trying to display a grayscale TIFF file using Python and MatPlotLib,
So far I have read the file this:
import scipy as N
import gdal
import sys
import matplotlib.pyplot as pyplot
try:
tif = gdal.Open('filename.tif')
tifArray = tif.ReadAsArray()
except:
print 'The file does not exist.'
sys.exit(0)
band1 = tif.GetRasterBand(1)
band2 = tif.GetRasterBand(2)
band3 = tif.GetRasterBand(3)
band1Array = band1.ReadAsArray()
band2Array = band2.ReadAsArray()
band3Array = band3.ReadAsArray()
But then I don't know what else should I do... I'm so clueless.
Anyone would help me in this?
Once you processed your file into a 2 Array, you could use ANY function in matplotlib that plots 2D arrays, e.g. cmap, imshow etc.
Here is the output with the marbles example
import matplotlib.image as mpimg
import matplotlib.pyplot as plt
img=mpimg.imread('MARBLES.TIF ')
imgplot = plt.imshow(img)
Here is what you get if you view only band3 of the image:
imgplot2 = plt.imshow(band3Array)
plt.show()
Look further into image viewing in MPL and 2D array functions...