Reputation: 6408
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?
Upvotes: 324
Views: 527038
Reputation: 74645
In Python 3, use BytesIO
to turn the read string into a file-like object:
from io import BytesIO
from PIL import Image
from urllib.request import urlopen
Image.open(BytesIO(urlopen(url).read()))
Upvotes: 31
Reputation: 388
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()
Upvotes: 2
Reputation: 3703
For Python 3 using OpenCV:
import cv2
from urllib.request import urlopen
image_url = "IMAGE-URL-GOES-HERE"
resp = urlopen(image_url)
image = np.asarray(bytearray(resp.read()), dtype="uint8")
image = cv2.imdecode(image, cv2.IMREAD_COLOR) # The image object
# Optional: For testing & viewing the image
cv2.imshow('image',image)
For Python 3 using OpenCV and Google Colab/Jupyter Notebook:
import cv2
from google.colab.patches import cv2_imshow
from urllib.request import urlopen
image_url = "IMAGE-URL-GOES-HERE"
resp = urlopen(image_url)
image = np.asarray(bytearray(resp.read()), dtype="uint8")
image = cv2.imdecode(image, cv2.IMREAD_COLOR) # The image object
# Optional: For testing & viewing the image
cv2_imshow(image)
Upvotes: 3
Reputation: 3031
The solutions mentioned above might work, but it misses one point that I would like to highlight i.e. when we fetch or retrieve the image url to read, we might not always get the actual image content if we don't pass the headers while making the get request.
for example:
request without Headers
import requests
url = "https://www.roaringcreationsfilms.com/rcsfilms-media/chankya-quotes-in-hindi-32.jpg"
data = requests.get(url).content
if we check the data:
print(data)
b'<head><title>Not Acceptable!</title></head><body><h1>Not Acceptable!</h1><p>An
appropriate representation of the requested resource could not be found on this server.
This error was generated by Mod_Security.</p></body></html>'
you see, we don't actually get the content of the image.
request with Headers
import requests
url = "https://www.roaringcreationsfilms.com/rcsfilms-media/chankya-quotes-in-hindi-32.jpg"
headers = {"User-Agent": "PostmanRuntime/7.31.1"}
data = requests.get(url, headers=headers).content
and, if we now check the data:
print(data)
b'\xff\xd8\xff\xe0\x00\x10JFIF\x00\x01\x01\x00\x00\x01\x00\x01\x00\x00\xff\xdb\x00C\x00\t\x06\x06\........\xfb\x04El\xb3\xa8L\xbc\xa12\xc6<\xc4\x891\xf2L|\xf7\x9eV\x18\xc5\xd8\x8f\x02\xca\xdc\xb1c+-\x96\'\x86\xcb,l\xb12;\x16\xd4j\xfd/\xde\xbf\xff\xd9'
Now, we get the actual content of the image.
Things to note are that different urls might require different combinations of the headers (such as "User-Agent", "Accept", "Accept-Encoding", etc.) to successfully get the data and some even might not require any headers. But it's always a good practice to pass "User-Agent" as a minimum required header while making the request.
Upvotes: 0
Reputation: 388
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
Upvotes: 2
Reputation: 4855
The following works for Python 3:
from PIL import Image
import requests
im = Image.open(requests.get(url, stream=True).raw)
References:
Upvotes: 201
Reputation: 10353
Using a StringIO
import urllib, cStringIO
file = cStringIO.StringIO(urllib.urlopen(URL).read())
img = Image.open(file)
Upvotes: 173
Reputation: 3136
Using requests
:
from PIL import Image
import requests
from StringIO import StringIO
response = requests.get(url)
img = Image.open(StringIO(response.content))
Upvotes: 63
Reputation: 21
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)
Upvotes: 2
Reputation: 114
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)
Upvotes: 5
Reputation: 4856
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.
Upvotes: 28
Reputation: 4710
from urllib.request import urlopen
from PIL import Image
img = Image.open(urlopen(url))
img
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!
Upvotes: 54
Reputation: 1343
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()
Upvotes: 4
Reputation: 491
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)))
Upvotes: 24
Reputation: 5026
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))
Upvotes: 462