I want to POST the image as json and receive it in flask. However, bytes type data cannot be used as the json value, so some ingenuity is required.
I set up a server locally and tried it.
As mentioned above, binary data cannot be an element of json. Text data is OK.
In that case, the binary data may be converted into text data once according to a certain rule, transmitted, and then converted into the original binary data at the receiving destination.
One of the rules for converting binary data to text data is base64.
Explained fairly carefully.
First on the client side. The transition of data is as follows.
Import an image as a Pillow Image ⇒ Convert to bytes ⇒ Encode with base64 (still bytes) ⇒ Convert data that was bytes to str ⇒ json .dumps to json ⇒ You can safely POST with json
client.py
import requests
from PIL import Image
import json
import base64
from io import BytesIO
img = Image.open("iruka.jpeg ")
#Convert Pillow Image to bytes and then to base64
buffered = BytesIO()
img.save(buffered, format="JPEG")
img_byte = buffered.getvalue() # bytes
img_base64 = base64.b64encode(img_byte) #Base64-encoded bytes * not str
#It's still bytes so json.Convert to str to dumps(Because the json element does not support bytes type)
img_str = img_base64.decode('utf-8') # str
files = {
"text":"hogehoge",
"img":img_str
}
r = requests.post("http://127.0.0.1:5000", json=json.dumps(files)) #POST to server as json
print(r.json())
>>>{'img_shape': [750, 500], 'text': 'hogehogefuga'}
Then server side. The transition of data is as follows.
Receive with json ⇒ Extract the desired data (base64-encoded text data) from json ⇒ Decode base64-encoded text data and convert it to bytes ⇒ Convert to _io.BytesIO so that it can be handled by Pillow ⇒ You can get the original Pillow Image safely
server.py
from flask import Flask, jsonify, request
from PIL import Image
import json
import base64
from io import BytesIO
import matplotlib.pyplot as plt
app = Flask(__name__)
@app.route("/", methods=["GET", "POST"])
def index():
json_data = request.get_json() #Get the POSTed json
dict_data = json.loads(json_data) #Convert json to dictionary
img = dict_data["img"] #Take out base64# str
img = base64.b64decode(img) #Convert image data converted to base64 to original binary data# bytes
img = BytesIO(img) # _io.Converted to be handled by BytesIO pillow
img = Image.open(img)
img_shape = img.size #Appropriately process the acquired image
text = dict_data["text"] + "fuga" #Properly process with the acquired text
#Return the processing result to the client
response = {
"text":text,
"img_shape":img_shape
}
return jsonify(response)
if __name__ == "__main__":
app.debug = True
app.run()
It was confirmed from the response of the server that the image was processed correctly.
By the way The input of base64.b64encode () is bytes and the output is bytes. The input of base64.b64decode () can be bytes or str, but the output is bytes.
python --command --decode base64 from POST and use it in PIL
How to convert PIL Image.image object to base64 string? [duplicate]