Flask OpenCV Send and Receive Images in Bytes
Flask OpenCV Send and Receive Images in Bytes
I want to send and receive images in bytes in my flask API. I also want to send some json alongside the image. How can I achieve this?
Below is my current solution that does not work
flask:
@app.route('/add_face', methods=['GET', 'POST'])
def add_face():
if request.method == 'POST':
# print(request.json)
nparr = np.fromstring(request.form['img'], np.uint8)
print(request.form['img'])
img = cv2.imdecode(nparr, cv2.IMREAD_COLOR)
cv2.imshow("frame", img)
cv2.waitKey(1)
return "list of names & faces"
client:
def save_encoding(img_file):
URL = "http://localhost:5000/add_face"
img = open(img_file, 'rb').read()
response = requests.post(URL, data="name":"obama", "img":str(img))
print(response.content)
produced error:
cv2.imshow("frame", img)
cv2.error: OpenCV(3.4.3) /io/opencv/modules/highgui/src/window.cpp:356: error: (-215:Assertion failed) size.width>0 && size.height>0 in function 'imshow'
What is the error/exception are you getting?
– Ishan Bhatt
Sep 14 '18 at 6:06
@randomir updated error
– El Houssine Talab
Sep 14 '18 at 8:00
@IshanBhatt updated error
– El Houssine Talab
Sep 14 '18 at 8:00
What does len(request.form[img]) and nparr.shape return? Before that, did you check img variable is correct at client side?
– unlut
Sep 14 '18 at 8:19
2 Answers
2
The following has worked for me.
I don't have the client code but I have a curl request. That should do the trick,
SERVER
from flask import request
from PIL import Image
import io
@app.route("/add_face", methods=["POST"])
def predict():
image = request.files["image"]
image_bytes = Image.open(io.BytesIO(image.read()))
CLIENT SIDE
curl -X POST -F image=@PATH/TO/FILE 'http://localhost:5000/add_face'
but this would be slower if you have a continuous stream of frames between a server and client
– El Houssine Talab
Sep 14 '18 at 9:49
No idea about that, I hit requests sporadically, So never felt it. You can wrap your flask app with gunicorn or gevent if you like.
– Ishan Bhatt
Sep 14 '18 at 10:03
It is easier to send images in base64 format, by doing that you get rid of problems about sending/receiving binary data since you just work with a string. Also it is more convenient in web stuff. Tested code below:
Server side:
from flask import Flask, render_template, request
import pandas as pd
import cv2
import numpy as np
import base64
app = Flask(__name__)
@app.route('/add_face', methods=['GET', 'POST'])
def add_face():
if request.method == 'POST':
# read encoded image
imageString = base64.b64decode(request.form['img'])
# convert binary data to numpy array
nparr = np.fromstring(imageString, np.uint8)
# let opencv decode image to correct format
img = cv2.imdecode(nparr, cv2.IMREAD_ANYCOLOR);
cv2.imshow("frame", img)
cv2.waitKey(0)
return "list of names & faces"
if __name__ == '__main__':
app.run(debug=True, port=5000)
Client side:
import requests
import base64
URL = "http://localhost:5000/add_face"
# first, encode our image with base64
with open("block.png", "rb") as imageFile:
img = base64.b64encode(imageFile.read())
response = requests.post(URL, data="name":"obama", "img":str(img))
print(response.content)
You can use COLOR instead of ANYCOLOR if you are sure about your input images.
still generates same error mentioned in the question.
– El Houssine Talab
Sep 14 '18 at 9:25
Then please answer my question in the comments. What does len(request.form[img]) and nparr.shape return? Before that, did you check img variable is correct at client side?
– unlut
Sep 14 '18 at 9:26
I have answered it
– El Houssine Talab
Sep 14 '18 at 9:48
Thanks for contributing an answer to Stack Overflow!
But avoid …
To learn more, see our tips on writing great answers.
Required, but never shown
Required, but never shown
By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.
What do you mean by "it doesn't work"? In what way?
– randomir
Sep 14 '18 at 5:55