21

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!

Christoph Rackwitz
  • 11,317
  • 4
  • 27
  • 36
AKSHAYAA VAIDYANATHAN
  • 2,715
  • 7
  • 30
  • 51
  • 1
    See https://stackoverflow.com/questions/17170752/python-opencv-load-image-from-byte-string for a (simpler) way. Note that having cv2 available implies that numpy (np) is available. – Dave W. Smith Dec 01 '17 at 14:27

4 Answers4

42

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)
Christoph Rackwitz
  • 11,317
  • 4
  • 27
  • 36
flamelite
  • 2,654
  • 3
  • 22
  • 42
7

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.

AKSHAYAA VAIDYANATHAN
  • 2,715
  • 7
  • 30
  • 51
5

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

Christoph Rackwitz
  • 11,317
  • 4
  • 27
  • 36
Sahana M
  • 485
  • 6
  • 4
1

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)
Christoph Rackwitz
  • 11,317
  • 4
  • 27
  • 36
James
  • 523
  • 4
  • 19