江戸画像合成API

はじめに

厳しい寒さが続いておりますが、時折見せる青空や日差しの心地良さに、ふと春を感じる瞬間も多くなってきましたね!

江戸時代は、地球はミニ氷河期の時代でもあり、江戸は今と比べて積雪量が多く隅田川も凍ることがあるぐらいとても寒かったそうです。

さて今回は、Pythonフレームワーク「Flask」による画像処理APIを紹介します。「Pythonによる機械学習をサービスとして導入したい」といった方々のご参考になれば幸いです。

API情報

名称:(江戸)画像合成API
メソッド: POST
エンドポイント: /image_mix/

API処理概要

2つの画像をBase64エンコードされた形式で受け取り、Flask側でデコードして画像を復元します。その復元した画像を合成し、その合成画像をBase64エンコードして返却します。

リクエスJSON

[
    {
        id : 1
        image : iVBORw0KGgoAAAANSUhEUgAABk...(base64でエンコードされた画像)
    },
    {
        id : 2
        image : iVBORw0KGgoAAAANSUhEUgAAAK...(base64でエンコードされた画像)
    }
]

f:id:KenjiU:20210127221826p:plain
id : 1(背景画像)
f:id:KenjiU:20210127221908p:plain
id : 2(貼り付ける画像)

ソース

from flask import Flask, jsonify, request
import cv2
import numpy as np
import base64
from PIL import Image

app = Flask(__name__)

@app.route("/image_mix/", methods=["POST"])
def post():

    layer1_flg = False
    layer2_flg = False

    for json in request.json:
        # リクエストのjsonのidをセット
        id = json['id']

        # リクエストのjsonのimageをデコード
        img_stream = base64.b64decode(json['image'])

        # 配列に変換
        img_array = np.asarray(bytearray(img_stream), dtype=np.uint8)

        # 画像として読み込む
        img_trans = cv2.imdecode(img_array, cv2.IMREAD_UNCHANGED)

        # 画像を書き込む
        if id == "1": # 背景画像
            cv2.imwrite(id+'_result.png', img_trans)
            layer1 = Image.open(id+'_result.png')
            layer1_flg = True
        elif id == "2": # 貼り付ける画像
            cv2.imwrite(id+'_result.png', img_trans)
            layer2 = Image.open(id+'_result.png')
            layer2_flg = True
        else:
            pass

    # 背景画像(layer1)と貼り付ける画像(layer2)が存在する場合
    if layer1_flg and layer2_flg:
        # layer1と同じサイズの画像を透過(A=0)で作成
        c = Image.new('RGBA', layer1.size, (255, 255,255, 0))

        # layer2を指定した座標位置にペースト
        c.paste(layer2, (780,570), layer2)

        # 重ね合わせる
        result = Image.alpha_composite(layer1, c)

        # 画像を書き込む
        result.save('mix_result.png')

        # 画像をBase64文字列にエンコードする
        with open('mix_result.png', "rb") as f:
            img_base64 = base64.b64encode(f.read()).decode('utf-8')
        
        # レスポンスのjsonにセット
        return jsonify({'result' : img_base64})

    # 対象画像が存在しない場合
    else:
        return jsonify({'result' : "対象の画像なし"})

if __name__ == '__main__':
    app.run()

結果

f:id:KenjiU:20210127222250p:plain
合成結果
きれいにお侍くんが合成されました!(キラッ)