UnidentifiedImageError: cannot identify image file when running Streamlit - image

I'm writing some code for the Streamlit app, where I want the user to upload a .jpg image file and it gives me this error, "UnidentifiedImageError: cannot identify image file <_io.BytesIO object at 0x00000293778F98B0>"
My code is as follows:
import streamlit as st
import pandas as pd
import numpy as np
from PIL import Image
st.title("Image classification Web App")
# loading images
def load_image(image):
image = image.resize((224,224))
im_array = np.array(image)/255 # a normalised 2D array
im_array = im_array.reshape(-1, 224, 224, 3) # to shape as (1, 224, 224, 3)
return im_array
...
if st.button("Try with the Default Image"):
image=load_image(Image.open('C:/Users/.../image21.jpg'))
st.subheader("Human is detected")
st.image(image)
st.image(initialize_model(model_name, image))
st.subheader("Upload an image file")
uploaded_file = st.file_uploader("Upload a JPG image file", type=["jpg", "jpeg"])
if uploaded_file:
image = load_image(Image.open(uploaded_file))
st.image(initialize_model(model_name, image))
However, I have no problem uploading an image with this line,
st.image(Image.open('C:/Users/../image21.jpg'))
Can anyone advise me whats wrong here?
Thanks.

You got that error because uploaded files in streamlit are file-like objects meaning they are not actual files. To Solve this problem, you will have to save the uploaded file to local directory, fetch the file from that directory and proceed with the rest of execution. This method gives you a total control of the file.
I will recommend you create a new function to accept and save user inputs. And after saving, return the path of the saved file, then read from that path, when that is successful, pass the file as a second argument to initialize_model.
Example:
import os
def get_user_input():
st.subheader("Upload an image file")
uploaded_file = st.file_uploader("Upload a JPG image file", type=["jpg", "jpeg"])
if uploaded_file is not None:
user_file_path = os.path.join("users_uploads/", uploaded_file.name)
with open(user_file_path, "wb") as user_file:
user_file.write(uploaded_file.getbuffer())
return user_file_path
uploaded_file = get_user_input()
if uploaded_file is not None:
image = load_image(uploaded_file)
st.image(initialize_model(model_name, image))

Related

How Can You Read Image Files from a URL and display it in Google Colab?

Using Google Colab, I would like to be able to read in some number of image files each of which is at a different url and then display each of them. I got the following code to work but it only displays the first image (no output for the 2nd or error messages) Also, if I add a print statement to the output, then no image display at all. So what's the trick? Thanks.
!pip install pillow
import urllib.request
from PIL import Image
# First Image
imageURL1 = "https://www.example.com/dir/imagefile1.jpg"
imageName1="file1.jpg"
urllib.request.urlretrieve(imageURL1, imageName1)
img1 = Image.open(imageName1)
img1 # this works but only if it is the only output
# Second Image
imageURL2 = "https://www.example.com/dir/imagefile2.jpg"
imageName2="file2.jpg"
urllib.request.urlretrieve(imageURL2, imageName2)
img2 = Image.open(imageName2)
img2 # does not display
#print("x") # a print kills the image display
Found an answer that works. Use IPython to display the image. It works with multiple images and the print() works as well.
!pip install pillow
import urllib.request
from PIL import Image
from IPython.display import display
# First Image
imageURL1 = "https://www.example.com/dir/imagefile1.jpg"
imageName1="file1.jpg"
urllib.request.urlretrieve(imageURL1, imageName1)
img1 = Image.open(imageName1)
display(img1) # this works but only if it is the only output
print("AND THE PRINT WORKS")
# Second Image
imageURL2 = "https://www.example.com/dir/imagefile2.jpg"
imageName2="file2.jpg"
urllib.request.urlretrieve(imageURL2, imageName2)
img2 = Image.open(imageName2)
display(img2)

Python3 tkinter: showing images from the Internet on a label (urllib) does not work

I would like to show Images from the Internet in a Label. I can do it with Images from the harddisk. Then I looked for a way to do it with Photos from the Internet and I wrote the following code:
self.res = requests.get('https://dog.ceo/api/breeds/image/random')
print(self.res)
self.jason = json.loads(self.res.content)
print (self.jason)
bild = self.jason['message']
print (bild)
u = urllib.request.urlopen(bild)
raw_data = u.read()
u.close()
b64_data = base64.encodestring(raw_data)
image = tk.PhotoImage(data = b64_data)
self.pic_label["image"] = image
But I get the following error message:
*Exception in Tkinter callback
Traceback (most recent call last):
File "/usr/lib/python3.6/tkinter/__init__.py", line 1705, in __call__
return self.func(*args)
File "/home/wolfgang/Eigene Programme/python_buch/api.py", line 42, in api
image = tk.PhotoImage(data = b64_data)
File "/usr/lib/python3.6/tkinter/__init__.py", line 3545, in __init__
Image.__init__(self, 'photo', name, cnf, master, **kw)
File "/usr/lib/python3.6/tkinter/__init__.py", line 3501, in __init__
self.tk.call(('image', 'create', imgtype, name,) + options)
_tkinter.TclError: couldn't recognize image data*
What am I doing wrong? Thanks in advance
P.S.: I am using Linux, if that should matter.
Update:
In the meanwhile I updated my function. But it still doesn't show images. Does it maybe have to do with the api? Any ideas what I have to change?
def api(self):
self.res = requests.get('https://dog.ceo/api/breeds/image/random')
print(self.res)
self.jason = json.loads(self.res.content)
print (self.jason)
bild = self.jason['message']
image_bytes = urllib.request.urlopen(bild).read()
data_stream = io.BytesIO(image_bytes)
pil_image = Image.open(data_stream)
tk_image = ImageTk.PhotoImage(pil_image)
self.anzeige = tk.Label(self.root,image=tk_image)
self.anzeige.pack()
Thanks in advance
When I ran your code it returned a jpg image. The tkinter.PhotoImage class doesn't directly support jpg. You'll need to use PIL/Pillow to create the image and hand it off to tkinter, or use some other library to convert it to png or gif before creating a PhotoImage.
For how to display jpeg images in tkinter see How do I insert a JPEG image into a python Tkinter window?

Unable to add an image to a tkinter window

I am trying to add an image to my tkinter GUI. However I keep receiving errors, in particular my image does not have a 'read' attribute. I have tried this with TIF, GIF and PNG formatted files but none seem to work. I have checked and other seems not to have a problem adding an a image in png format. I have a feeling the problem is obvious but I am missing it.
import tkinter as tk
from PIL import ImageTk, Image
class Window(tk.Frame):
def __init__(self, master=None):
tk.Frame.__init__(self, master)
self.master = master
self.init_window()
def init_window(self):
self.master.title("Lifespan Data Analyser")
self.pack(fill=tk.BOTH, expand=1)
path = Image.open('I:/python_work/TemplateRack_GUI.tif')
img = ImageTk.PhotoImage(file = path) #problem is here I think
panel = tk.Label(root, image = img)
panel.pack(side = "bottom", fill = "both", expand = "yes")
panel.image=img
root = tk.Tk()
root.geometry("400x300")
app = Window(root)
root.mainloop()
Receive this attribute error:
AttributeError: 'TiffImageFile' object has no attribute 'read'
AttributeError: 'JpegImageFile' object has no attribute 'read'
try with:
path = 'I:/python_work/TemplateRack_GUI.tif'
no open
with this change your code works well, try with another tif

Reading image file (file storage object) using OpenCV

I am sending an image by curl to flask server, i am using this curl command
curl -F "file=#image.jpg" http://localhost:8000/home
and I am trying to read the file using OpenCV on the server side.
On the server side I handle the image by this code
#app.route('/home', methods=['POST'])
def home():
data =request.files['file']
img = cv.imread(data)
fact_resp= model.predict(img)
return jsonify(fact_resp)
I am getting this error-
img = cv.imread(data)
TypeError: expected string or Unicode object, FileStorage found
How do I read the file using OpenCV on the server side?
Thanks!
I had similar issues while using opencv with flask server, for that first i saved the image to disk and read that image using saved filepath again using cv.imread()
Here is a sample code:
data =request.files['file']
filename = secure_filename(file.filename) # save file
filepath = os.path.join(app.config['imgdir'], filename);
file.save(filepath)
cv.imread(filepath)
But now i have got even more efficient approach from here by using cv.imdecode() to read image from numpy array as below:
#read image file string data
filestr = request.files['file'].read()
#convert string data to numpy array
file_bytes = numpy.fromstring(filestr, numpy.uint8)
# convert numpy array to image
img = cv.imdecode(file_bytes, cv.IMREAD_UNCHANGED)
After a bit of experimentation, I myself figured out a way to read the file using CV2.
For this I first read the image using PIL.image method
This is my code,
#app.route('/home', methods=['POST'])
def home():
data =request.files['file']
img = Image.open(request.files['file'])
img = np.array(img)
img = cv2.resize(img,(224,224))
img = cv2.cvtColor(np.array(img), cv2.COLOR_BGR2RGB)
fact_resp= model.predict(img)
return jsonify(fact_resp)
I wonder if there is any straight forward way to do this without using PIL.
So incase you want to do something like ,
file = request.files['file']
img = cv.imread(file)
then do it like this
import numpy as np
file = request.files['file']
file_bytes = np.fromfile(file, np.uint8)
file = cv.imdecode(file_bytes, cv.IMREAD_COLOR)
Now you don't need to do cv.imread() again, but can use this in the next line of codes.
This applies to OpenCV v3.x and onwards
Two-line solution, change grayscale to what you need
file_bytes = numpy.fromfile(request.files['image'], numpy.uint8)
# convert numpy array to image
img = cv.imdecode(file_bytes, cv.IMREAD_GRAYSCALE)

How to load images from a directory on the computer in Python

Hello I am New to python and I wanted to know how i can load images from a directory on the computer into python variable.
I have a set of images in a folder on disk and I want to display these images in a loop.
You can use PIL (Python Imaging Library) http://www.pythonware.com/products/pil/ to load images.
Then you can make an script to read images from a directory and load them to python, something like this.
#!/usr/bin/python
from os import listdir
from PIL import Image as PImage
def loadImages(path):
# return array of images
imagesList = listdir(path)
loadedImages = []
for image in imagesList:
img = PImage.open(path + image)
loadedImages.append(img)
return loadedImages
path = "/path/to/your/images/"
# your images in an array
imgs = loadImages(path)
for img in imgs:
# you can show every image
img.show()
pip install ThreadedFileLoader
You can use ThreadedFileLoader module. It uses threading to load images.
from ThreadedFileLoader.ThreadedFileLoader import *
instance = ThreadedImageLoader("path_to_folder/*.jpg")
instance.start_loading()
images = instance.loaded_objects
print(len(images))
print(images[0].shape)
You can use glob and imageio python packages to achieve the same. Below is code in python 3:
import glob
import imageio
for image_path in glob.glob("<your image directory path>\\*.png"):
im = imageio.imread(image_path)
print (im.shape)
print (im.dtype)
If you have images in your google drive, and want to load, resize and save the images, then the following code works well.
import os, sys
from os import listdir
from PIL import Image
from google.colab import drive
import matplotlib.pyplot as plt
drive.mount('/content/gdrive')
# need to enter password to access your google drive
from google.colab import files
main_dir = "/content/gdrive/My Drive/Panda/"
files = listdir(main_dir)
# you can change file extension below to read other image types
images_list = [i for i in files if i.endswith('.jpg')] ## output file names only
for idx,image in enumerate(images_list):
print(idx)
img = Image.open(main_dir + image)
#print(img.size)
#plt.imshow(img)
img = img.resize((480, 600))
img.save(main_dir + image)

Resources