I am trying to convert Gradio app to flask api. In Gradio app, it is using components like Image, Text, and so on. I have to change that component to request form data. However, I am suffering with image processing. I need any help.
This is my code.
cloth_image = gr.Image(label="Your label...", type="pil") cloth_mask_image = gr.Image(label="Your label...", type="pil")
How can I get the same return value as gr.Image component by preprocessing of cloth_image = request.files['cloth_image']
If you need image (as PIL
) only on server then you can use directly
from PIL import Image
cloth_image = Image.open( request.files["cloth_image"] )
Because files["cloth_image"]
has method .read()
so it can be treated as file-like object, and Image.open()
can use file-like object instead of filename.
And you can convert between pillow
and numpy
(and opencv
)
# from pillow to numpy/opencv
arr = numpy.array(cloth_image)
# from numpy/opencv to pillow
cloth_image = Image.fromarray(arr)
(opencv
may need to convert colors between RGB
and BGR
)
Minimal working code:
from flask import Flask, request
from PIL import Image
app = Flask(__name__)
@app.route('/', methods=['GET', 'POST'])
def index():
if request.method == 'POST':
if "cloth_image" in request.files:
img = request.files["cloth_image"] # it has method .read() so it can be treated as file-like object
cloth_image = Image.open(img) # it can use file-like object instead of filename
# ... process image ...
return """
<form method="POST" enctype="multipart/form-data">
<input type="file" name="cloth_image">
<button type="submit">Send</button>
</form>"""
if __name__ == '__main__':
app.run()
But if you need to send it back then you may need to use io.BytesIO
to save image in file-like object in memory, convert it to base64
, and display it as
html = '<img src="data:image/png;base64,{}">'.format(data)
More complex code which gets image, draw rectangle and send it back to browser.
from flask import Flask, request
from PIL import Image, ImageDraw
import io
import base64
app = Flask(__name__)
@app.route('/', methods=['GET', 'POST'])
def index():
img = 'empty'
if request.method == 'POST':
if "image" in request.files:
print(request.files)
# get image
img = request.files["image"] # it has method .read()
# read to pillow
image = Image.open(img)
# draw something
draw = ImageDraw.Draw(image) # https://pillow.readthedocs.io/en/stable/reference/ImageDraw.html
draw.rectangle([(20,20), (280,280)], outline=(255,0,0), width=3) # https://pillow.readthedocs.io/en/stable/reference/ImageDraw.html#PIL.ImageDraw.ImageDraw.rectangle
draw.text((15,5), "Hello World!") # https://pillow.readthedocs.io/en/stable/reference/ImageDraw.html#PIL.ImageDraw.ImageDraw.text
# convert to file-like data
obj = io.BytesIO() # file in memory to save image without using disk #
image.save(obj, format='png') # save in file (BytesIO) # https://pillow.readthedocs.io/en/stable/reference/Image.html#PIL.Image.Image.save
obj.seek(0)
# convert to bases64
data = obj.read() # get data from file (BytesIO)
data = base64.b64encode(data) # convert to base64 as bytes
data = data.decode() # convert bytes to string
# convert to <img> with embed image
img = '<img src="data:image/png;base64,{}">'.format(data)
return '<form method="POST" enctype="multipart/form-data"><input type="file" name="image"><button type="submit">Send</button></form><br>' + img
if __name__ == '__main__':
app.run()
And if you need it without reloading page then you may have to use JavaScript. But I skip this problem.