What I’m trying to do is fairly simple when we’re dealing with a local file, but the problem comes when I try to do this with a remote URL.
Basically, I’m trying to create a PIL image object from a file pulled from a URL. Sure, I could always just fetch the URL and store it in a temp file, then open it into an image object, but that feels very inefficient.
Here’s what I have:
Image.open(urlopen(url))
It flakes out complaining that seek() isn’t available, so then I tried this:
Image.open(urlopen(url).read())
But that didn’t work either. Is there a Better Way to do this, or is writing to a temporary file the accepted way of doing this sort of thing?
Answers:
Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.
Method 1
In Python3 the StringIO and cStringIO modules are gone.
In Python3 you should use:
from PIL import Image import requests from io import BytesIO response = requests.get(url) img = Image.open(BytesIO(response.content))
Method 2
Using a StringIO
import urllib, cStringIO file = cStringIO.StringIO(urllib.urlopen(URL).read()) img = Image.open(file)
Method 3
The following works for Python 3:
from PIL import Image import requests im = Image.open(requests.get(url, stream=True).raw)
References:
- https://github.com/python-pillow/Pillow/pull/1151
- https://github.com/python-pillow/Pillow/blob/master/CHANGES.rst#280-2015-04-01
Method 4
Using requests:
from PIL import Image import requests from StringIO import StringIO response = requests.get(url) img = Image.open(StringIO(response.content))
Method 5
Python 3
from urllib.request import urlopen from PIL import Image img = Image.open(urlopen(url)) img
Jupyter Notebook and IPython
import IPython url = 'https://newevolutiondesigns.com/images/freebies/colorful-background-14.jpg' IPython.display.Image(url, width = 250)
Unlike other methods, this method also works in a for loop!
Method 6
Use StringIO to turn the read string into a file-like object:
from StringIO import StringIO import urllib Image.open(StringIO(urllib.requests.urlopen(url).read()))
Method 7
For those doing some sklearn/numpy post processing (i.e. Deep learning) you can wrap the PIL object with np.array(). This might save you from having to Google it like I did:
from PIL import Image import requests import numpy as np from StringIO import StringIO response = requests.get(url) img = np.array(Image.open(StringIO(response.content)))
Method 8
The arguably recommended way to do image input/output these days is to use the dedicated package ImageIO. Image data can be read directly from a URL with one simple line of code:
from imageio import imread
image = imread('https://cdn.sstatic.net/Sites/stackoverflow/img/logo.png')
Many answers on this page predate the release of that package and therefore do not mention it. ImageIO started out as component of the Scikit-Image toolkit. It supports a number of scientific formats on top of the ones provided by the popular image-processing library PILlow. It wraps it all in a clean API solely focused on image input/output. In fact, SciPy removed its own image reader/writer in favor of ImageIO.
Method 9
select the image in chrome, right click on it, click on Copy image address, paste it into a str variable (my_url) to read the image:
import shutil
import requests
my_url = 'https://www.washingtonian.com/wp-content/uploads/2017/06/6-30-17-goat-yoga-congressional-cemetery-1-994x559.jpg'
response = requests.get(my_url, stream=True)
with open('my_image.png', 'wb') as file:
shutil.copyfileobj(response.raw, file)
del response
open it;
from PIL import Image
img = Image.open('my_image.png')
img.show()
Method 10
Manually wrapping in BytesIO is no longer needed since PIL >= 2.8.0. Just use Image.open(response.raw)
Adding on top of Vinícius’s comment:
You should pass stream=True as noted https://requests.readthedocs.io/en/master/user/quickstart/#raw-response-content
So
img = Image.open(requests.get(url, stream=True).raw)
Method 11
from PIL import Image
import cv2
import numpy as np
import requests
image=Image.open(requests.get("https://previews.123rf.com/images/darrenwhi/darrenwhi1310/darrenwhi131000024/24022179-photo-of-many-cars-with-one-a-different-color.jpg", stream=True).raw)
#image =resize((420,250))
image_array=np.array(image)
image
Method 12
To directly get image as numpy array without using PIL
import requests, io import matplotlib.pyplot as plt response = requests.get(url).content img = plt.imread(io.BytesIO(response), format='JPG') plt.imshow(img)
Method 13
USE urllib.request.urlretrieve() AND PIL.Image.open() TO DOWNLOAD AND READ IMAGE DATA :
import requests
import urllib.request
import PIL
urllib.request.urlretrieve("https://i.imgur.com/ExdKOOz.png", "sample.png")
img = PIL.Image.open("sample.png")
img.show()
or Call requests.get(url) with url as the address of the object file to download via a GET request. Call io.BytesIO(obj) with obj as the content of the response to load the raw data as a bytes object. To load the image data, call PIL.Image.open(bytes_obj) with bytes_obj as the bytes object:
import io
response = requests.get("https://i.imgur.com/ExdKOOz.png")
image_bytes = io.BytesIO(response.content)
img = PIL.Image.open(image_bytes)
img.show()
All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0