flask と socket.ioで2つの画像を合成する


#概要
canvasのデータをflask_socketioで、送り
サーバー側でbase64デコード、numpyにして
opencvで合成し、再度base64にエンコードして送り返す
いろいろ試しましたが、この方法じゃないと、ノイズが出たりとうまくいきませんでした。


#環境
mac10.15
python3.9.2


#template
```javascript:top.html
<html>
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
            <script src="https://cdn.socket.io/3.1.3/socket.io.min.js" integrity="sha384-cPwlPLvBTa3sKAgddT6krw0cJat7egBga3DJepJyrLl4Q9/5WLra3rrnMcyTyOnh" crossorigin="anonymous"></script>
            
    </head>
    <body>
        <br>
        <button id="scan">scan</button>
        <br>
        <img  id="img1" src="{{ url_for('static', filename = 'bg.jpg') }}" width=300 height=200>
        <img  id="img2" src="{{ url_for('static', filename = '02.jpg') }}" width=300 height=200>     
        <canvas id="compimg" width=300 height=200></canvas>
    </body>

    <script>

    const imgw = 300;
    const imgh = 200;

    var scanButton = document.getElementById('scan');
    scanButton.addEventListener('click', function() {

        const canvas1 = document.createElement("canvas");
        canvas1.width = imgw;
        canvas1.height = imgh;
        const img1 = document.getElementById("img1");
        const ctx1 = canvas1.getContext("2d");
        ctx1.drawImage(img1, 0, 0);
        const canvas1data = canvas1.toDataURL("image/jpeg");

        const canvas2 = document.createElement("canvas");
        canvas2.width = imgw;
        canvas2.height = imgh;
        const img2 = document.getElementById("img2");
        const ctx2 = canvas2.getContext("2d");
        ctx2.drawImage(img2, 0, 0);
        const canvas2data = canvas2.toDataURL("image/jpeg");

        
        socket.emit( 'image', canvas1data, canvas2data);

    });
    
    const socket = io.connect();
     socket.on('connect', () => {
        console.log('connect');
    }); 
      
    socket.on('response', function(msg) {


        console.log('response');
        const compimg = document.getElementById('compimg');
        const compimgCtx = compimg.getContext('2d')

        var itemimage = new Image();
        itemimage.src= "data:image/jpeg;base64,"+msg.image;
        itemimage.onload = function () {      
            compimgCtx.drawImage(itemimage, 0, 0, imgw, imgh)
        }



    });
            
    

    </script>

</html>

```

#flask
```python:app.py
from flask import Flask, render_template, request
from flask_socketio import SocketIO, emit, disconnect
    
import cv2
import numpy as np
import base64
from PIL import Image
import io

app = Flask(__name__)
async_mode = None 
socketio = SocketIO(app, async_mode=async_mode,async_handlers=True)

@socketio.event
def connect():
    print("connect")

@app.route('/')
def top():
    return render_template('top.html')
    
@socketio.event
def image(img_base64,imgbg_base64):#base64
    print("recieve")
    im = Image.open(io.BytesIO(base64.b64decode(img_base64.split(',')[1])))
    imbg = Image.open(io.BytesIO(base64.b64decode(imgbg_base64.split(',')[1])))
    
    img1 = np.array(im)
    h,w = img1.shape[:2]
    imbgresize =  imbg.resize((w, h))
    img2 = np.array(imbgresize)
    
    dst = img1 * 0.5 + img2 * 0.5

    if dst is None:
        print("Image is empty!!")
    else:
        print("Image")
        buffer = io.BytesIO()
        Image.fromarray(dst.astype(np.uint8)).save(buffer, format="JPEG")
        new_image = base64.b64encode(buffer.getvalue()).decode("ascii")
        emit('response',{'image': new_image})

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

```

#使用した素材
https://www.pakutaso.com/


#完成

![gif](https://user-images.githubusercontent.com/45844502/129522762-6708036c-56c3-402d-8631-2de78e9bd4d6.gif)