惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

I
InfoQ
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Apple Machine Learning Research
Apple Machine Learning Research
月光博客
月光博客
B
Blog
罗磊的独立博客
GbyAI
GbyAI
博客园 - 三生石上(FineUI控件)
雷峰网
雷峰网
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
Microsoft Security Blog
Microsoft Security Blog
宝玉的分享
宝玉的分享
The GitHub Blog
The GitHub Blog
人人都是产品经理
人人都是产品经理
博客园 - Franky
有赞技术团队
有赞技术团队
WordPress大学
WordPress大学
博客园 - 聂微东
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
V
Visual Studio Blog
MyScale Blog
MyScale Blog
Google DeepMind News
Google DeepMind News
G
Google Developers Blog
aimingoo的专栏
aimingoo的专栏

jdhao's digital space

Conversion between base64 and OpenCV or PIL Image 腾讯云对象存储博客图床开启 CDN 加速(不需要购买额外域名) Search and Replace in Multiple Files in Vim/Neovim Change Table Column Width in LaTeX Image or Table Side by Side in LaTeX LaTeX 并排显示图像或表格 Firenvim: Neovim inside Your Browser Content inside HTML tags missing in Latest Hugo? Creating Markdown Front Matter with Ultisnips Labelme JSON 标注格式转 voc XML 格式 Nifty Nvim Techniques That Make My Life Easier -- Series 6 macOS 下如何为视频制作字幕 Running Command Asynchronously inside Neovim Resolving Merge Conflict after Git Stash Pop Pylint: command not found? A Hands-on Experience with Neovim's Built-in LSP Support How to Convert PDF to Images with Imagemagick 互联网上常用缩略语集锦 File Backup in Neovim Converting PDF Pages to Images with Poppler Nifty Nvim Techniques That Make My Life Easier -- Series 5 Neovim Configuration for System-wide Use How to sort a list of tuple or list in Python -- lambda or itemgetter? Building A Vim Statusline from Scratch 人类第一颗原子弹爆炸始末 Distributed Training in PyTorch with Horovod Learning Expect Programming Essential Knowledge about SSH Nifty LaTeX Techniques -- Series 1 更改 Adsense 邮寄地址,重新寄送 PIN
Build Web API with Flask -- Post and Receive Image
2020-04-12 · via jdhao's digital space

In this post, I want to write about how to build a simple image processing web API that returns the size of an image. The topics include how to build this web API with Flask and how to post image to this web API and get response.

There are mainly two ways by which we can send an image to the web service. Based on how you send the image, the way to get the uploaded image on the server side also varies.

Post binary image#

You can directly post binary image to the server using the files parameter of requests.post():

url = 'http://127.0.0.1:5000/im_size'
my_img = {'image': open('test.jpg', 'rb')}
r = requests.post(url, files=my_img)

# convert server response into JSON format.
print(r.json())

In the above code, the Content-Type of the Header of the POST request will be multipart/form-data. Then in the server side, you can get the posted image like this:

from flask import Flask, request, jsonify

app = Flask(__name__)

@app.route("/im_size", methods=["POST"])
def process_image():
    file = request.files['image']
    # Read the image via file.stream
    img = Image.open(file.stream)

    return jsonify({'msg': 'success', 'size': [img.width, img.height]})


if __name__ == "__main__":
    app.run(debug=True)

In the server side, the posted image will be in request.files['image'], which is of type werkzeug.datastructures.FileStorage. You can save the image to disk via save() method of this object:

file.save('im-received.jpg')

The image is also stored in file.stream, which is a file-like object so that you can easily read the image for later processing:

# img is PIL Image object
img = Image.open(file.stream)

Finally, we construct a Python dict and convert it to JSON format via the jsonify() method provided by Flask.

How to post multiple files#

To post multiple images to the server, you can post a list of file tuples like the following:

multiple_files = [
    ('image', ('test.jpg', open('test.jpg', 'rb'))),
    ('image', ('test.jpg', open('test.jpg', 'rb')))
]
# simplified form
# multiple_files = [
#     ('image', open('test.jpg', 'rb')),
#     ('image', open('test.jpg', 'rb'))
# ]
r = requests.post(url, files=multiple_files, data=data)

In the server side, you can still receive the posted images using request.files:

from flask import Flask, request
# ... other code
files = request.files.to_dict(flat=False) ## files is a list containing two images.
for i, file in enumerate(files):
    file.save(f'image-{i}.jpg')

Post additional data#

We usually want to post more meta info than merely the image itself. We can use the data parameter in requests.post():

payload = {'id': '123', 'type': 'jpg'}
r = requests.post(url, files=files, data=payload)

To get the payload dict in the server side, we use request.form, which is of type werkzeug.datastructures.ImmutableMultiDict. We use request.form.to_dict() to convert the received form data into Python dict:

payload = request.form.to_dict()
id = payload['id']
im_type = payload['type']

Post base64 encoded image#

Another way is to just encode the image with base64 and post all the info via data parameter in requests.post() in the client side.

import base64

with open('test.jpg', 'rb') as f:
    im_b64 = base64.b64encode(f.read())

payload = {'id': '123', 'type': 'jpg', 'box': [0, 0, 100, 100], 'image': im_b64}

In the server side, we fetch the posted payload, get the base64 encoded image and decode it:

import base64
import io
from PIL import Image

payload = request.form.to_dict(flat=False)

im_b64 = payload['image'][0]  # remember that now each key corresponds to list.
# see https://jdhao.github.io/2020/03/17/base64_opencv_pil_image_conversion/
# for more info on how to convert base64 image to PIL Image object.
im_binary = base64.b64decode(im_b64)
buf = io.BytesIO(im_binary)
img = Image.open(buf)

Post multiple based64 encoded image#

To post multiple base64 encoded images to the server, post them as a list of base64 string:

b64_ims = []
for im_path in im_paths:
    with open(im_path, 'rb') as f:
        im_b64 = base64.encode(f.read())
    b64_ims.append(im_b64)
payload = {"images": b64_ims}

In the server side, you can get the posted dict and decode the base64 image one by one, just like what I have shown above for a single image.

References#