Read a .jpg from RAM - python-3.x

from io import StringIO
from PIL import Image
import requests
response = requests.get(image.url)
# Works fine, but requests a disk write.
f = open('tmp.jpg', 'bw')
f.write(response.content)
img = Image.open('tmp.jpg')
# Fails with `OSError: cannot identify image file <_io.StringIO object at 0x7fb666238a68>`
#file = StringIO(str(response.content))
#img = Image.open(file)
I am trying to run the code from this tutorial but in python3. The commented out version is the closest I have gone to the original idea of "get an image from the network into RAM and work with that". I don't mind using cv2 if easier. How do I write this code pythonically and efficiently?

As Mark Setchell said, you likely want BytesIO not StringIO.
from io import BytesIO
from PIL import Image
import requests
response = requests.get(image.url)
file = BytesIO(response.content)
img = Image.open(file)

Related

Can't read PNG files from S3 in Python 3?

I have a bucket on S3.
I want to be able to connect to it and read the pictures/PDFs into my EC2 machine memory, perform OCR and get needed fields.
Here is what I have done so far but unfortunately it doesn't work.
import cv2
import boto3
import matplotlib
import pytesseract
from PIL import Image
boto3.setup_default_session(profile_name='default-mfasession')
s3_client = boto3.client('s3')
s3_resource = boto3.resource('s3')
bucket_name = "my_bucket"
key = "my-files/._Screenshot 2020-04-20 at 14.21.20.png"
bucket = s3_resource.Bucket(bucket_name)
object = bucket.Object(key)
response = object.get()
file_stream = response['Body']
im = Image.open(file_stream)
np.array(im)
Returns me an error:
UnidentifiedImageError: cannot identify image file <_io.BytesIO object
at 0x7fae33dce110>
I have tried all the answers related to this issue in SO nothing helped.
Including:
matplotlib: ValueError: invalid PNG header
and
PIL cannot identify image file for io.BytesIO object
Please advise how to solve it?
This is what I usually use. Maybe it will work for you as well:
def image_from_s3(bucket, key):
bucket = s3_resource.Bucket(bucket)
image = bucket.Object(key)
img_data = image.get().get('Body').read()
return Image.open(io.BytesIO(img_data))
And in your handler you execute this:
img = image_from_s3(image_bucket, image_key)
img should be Pillow's image if it successfully executes.

How can I resize image with quality without saving image in Python?

I use this code but it need to save
from PIL import Image
import requests
from io import BytesIO
response = requests.get(url)
img = Image.open(BytesIO(response.content))
image = img.resize((W, H), Image.ANTIALIAS)
image.save('De7k.jpeg', optimize=True, quality=Quality)
If you would like to "save" the file while keeping it in memory instead of writing a file to disk, you can write it to another BytesIO object.
from PIL import Image
import requests
from io import BytesIO
response = requests.get(url)
img = Image.open(BytesIO(response.content))
image = img.resize((W, H), Image.ANTIALIAS)
output = BytesIO()
image.save(output, format="JPEG", optimize=True, quality=Quality)

Error Opening PGM file with PIL and SKIMAGE

I have following Image file:
Image
I used PIL and Skimage to open it but I get following errors
First with PIL (tried with and without trucate option):
Code:
from PIL import Image, ImageFile
ImageFile.LOAD_TRUNCATED_IMAGES = True
img = Image.open("image_output.pgm")
Erorr:
OSError: cannot identify image file 'image_output.pgm'
And with Skimage:
Code:
from skimage import io
img = io.imread("image_output.pgm")
Error:
OSError: cannot identify image file <_io.BufferedReader name='image_output.pgm'>
I can open the file with GUI applications like system photo viewer and Matlab.
How can I diagnose what is wrong with image? I compared the byte data with other PGM files which I can open in Python, but could not identify the difference.
Thanks.
Your file is P2 type PGM, which means it is in ASCII - you can view it in a normal text editor. It seems neither PIL, nor skimage want to read that, but are happy to read the corresponding P5 type which is identical except it is written in binary, rather than ASCII.
There are a few options...
1) You could use OpenCV to read it:
import cv2
im = cv2.imread('a.pgm')
2) You could convert it to P5 with ImageMagick and then read the output.pgm file with skimage or PIL:
magick input.pgm output.pgm
3) If adding OpenCV, or ImageMagick as a dependency is a real pain for you, it is possible to read a PGM image yourself:
#!/usr/bin/env python3
import re
import numpy as np
# Open image file, slurp the lot
with open('input.pgm') as f:
s = f.read()
# Find anything that looks like numbers
# Technically, there could be comments that should be ignored
l=re.findall(r'[0-9P]+',s)
# List "l" will contain: P5, width, height, 255, pixel1, pixel2, pixel3...
# Technically, if l[3]>255, you should change the type of the Numpy array to uint16, but that is not the case
w, h = int(l[1]), int(l[2])
# Make Numpy image from data
ni = np.array(l[4:],dtype=np.uint8).reshape((h,w))

Display image from url using holoviews

How can I display an image from url.
This result an error
import urllib
img = urllib.request.urlopen('https://www.edgystl.com/wp-content/uploads/2018/01/leather-bicker-jacket-model-street-style-men-1-e1530998880646.jpg')
hv.RGB(img)
HoloViews RGB elements expect generally expect a NumPy array, the easiest way of getting an array from an Image is to use the PIL (or Pillow) library and download it using requests. Here's what that looks like:
from PIL import Image
import requests
from io import BytesIO
url = 'https://www.edgystl.com/wp-content/uploads/2018/01/leather-bicker-jacket-model-street-style-men-1-e1530998880646.jpg'
response = requests.get(url)
img = Image.open(BytesIO(response.content))
hv.RGB(np.array(img))
Turns out it can be done with skimage
import holoviews as hv
from skimage import io
img = io.imread('https://www.edgystl.com/wp-content/uploads/2018/01/leather-bicker-jacket-model-street-style-men-1-e1530998880646.jpg')
hv.RGB(np.array(img))

opencv2 python3 imread with NoneType

I program in Ubuntu system with python3, opencv2. There are several images in the folder that need to be processed. When I use imread, print(img.shape) shows AttributeError: 'NoneType' object has no attribute 'shape'. And I checked the created images' size is 0 bytes. The strange thing is that there are some images can be read successfully, but some are NoneType. Thanks for your help.
import glob as gb
import cv2
import random
import os
import numpy as np
shared_path="/home/train_1/"
folder_list=["HTC-1-M7"]
for j in range(len(folder_list)):
output_path=os.path.join("/home/test/",folder_list[j])
camera_path= os.path.join(shared_path,folder_list[j])
img_path = gb.glob(camera_path+"/*.jpg")
counter=1
for path in img_path:
img = cv2.imread(path)
print(img.shape)
kernel = np.array([[-1,2,-2,2,-1],[2,-6,8,-6,2],[-2,8,-12,8,-2],[2,-6,8,-6,2],[-1,2,-2,2,-1]],np.float32)/12
img = cv2.filter2D(img,-1,kernel)
It means that somewhere a function which should return a image just returned None and therefore it has no shape attribute.
Try print(img) to check if your image is None or an actual numpy object. You probably get this error because your image path may be wrong in a way. Make sure your path is completely correct.

Resources