Flask将png图像发送到浏览器并在javascript画布中显示 [英] Flask send a png image to the browser and display in javascript canvas

查看:60
本文介绍了Flask将png图像发送到浏览器并在javascript画布中显示的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

仍将继续学习Flask和Web开发人员.我不知道如何将烧瓶中的png图像发送到浏览器.我只想进行一些图像处理,然后在完成后将其发送到浏览器,以便可以在javascript画布中查看它.图像不是静态的,而是动态生成的.因此,我只是将它们保存在平面文件中,不知何故需要将其发送给浏览器,以便可以在JavaScript画布中查看它.我不知道我在做什么错.我已经转换了图像,我只想能够在JavaScript画布中打开它.

Still learning Flask and web dev in general. I have no clue how to send a png image from flask to the browser. I just want to be do some image processing then send it to the browser when I'm done so I can view it in a javascript canvas. The images are not static but get generated on the fly. So I just save them in flat files and somehow need to send it the browser so I can view it in a JavaScript canvas. I don't know what I'm doing wrong. I have the image converted I just want to be able to open it in a JavaScript canvas.

非常感谢您的任何帮助或建议!

Any help or advice would be greatly appreciated thank you!

烧瓶png->浏览器???

Flask png -> Browser ???

#Flask stuff 
from flask import Flask, render_template, url_for, request,jsonify, json, after_this_request, send_file
import base64
import io


#just have to figure out how to SEND images back to browser!!!
@app.route('/getImage', methods=['GET'])
def get_Image():
    #...
    #process image with cv2 then save so I can send it the the browser 
    #...
    image = get_encoded_img("img\\truthMask.png")
    return jsonify({'image_url': image})

def get_encoded_img(image_path):
    img = Image.open(image_path, mode='r')
    img_byte_arr = io.BytesIO()
    img.save(img_byte_arr, format='PNG')
    my_encoded_img = base64.encodebytes(img_byte_arr.getvalue()).decode('ascii')
    return my_encoded_img




const canvasMask = document.getElementById('myCanvas');
/*The user mask 2d context*/
const ctxcanvasMask = canvasFinalConsensusMask.getContext('2d');


document.getElementById("getMask").addEventListener('click', () => {
    var xhr = new XMLHttpRequest();

    // Setup our listener to process compeleted requests
    xhr.onreadystatechange = function () {
        // Only run if the request is complete
        if (xhr.readyState !== 4) return;

        // Process our return data
        if (xhr.status >= 200 && xhr.status < 300) {
            // What do when the request is successful
            console.log("I got the image");
            console.log(JSON.parse(xhr.responseText));
            let data = JSON.parse(xhr.responseText);

            var img = new Image(),
                f = data.image_url,
                url = window.URL || window.webkitURL,
                src = url.createObjectURL(f);
            img.src = src;
            img.onload = function () {
                ctxFinalConsensusMask.drawImage(img, 0, 0);
                url.revokeObjectURL(src);
            }
        }
    };
    // Create and send a GET request
    // The first argument is the post type (GET, POST, PUT, DELETE, etc.)
    // The second argument is the endpoint URL
    xhr.open('GET', 'http://127.0.0.1:5000/getImage');
    xhr.send();
});


<canvas id="myCanvas" width="100" height="100" style="z-index: 1;">
                    Your browser does not support the HTML canvas tag.</canvas>
<button name="getMask" id="getMask"> Show Mask </button>

推荐答案

我用您的代码创建了最小的工作代码-它将图像发送到浏览器.

I used your code to create minimal working code - and it sends image to browser.

所有问题都与JavaScript中的变量名称有关.

All problem was with names of variables in JavaScript.

您创建了对象 canvasMask ctxcanvasMask ,但是您尝试从 canvasFinalConsensusMask ctxFinalConsensusMask 获取数据,而对象不存在.

You create objects canvasMask and ctxcanvasMask but you try to get data from canvasFinalConsensusMask and ctxFinalConsensusMask which don't exist.

const canvasMask = document.getElementById('myCanvas');
const ctxcanvasMask = canvasMask.getContext('2d');

我对 url.createObjectURL(f)也有问题,因此我使用带有前缀的 base64 图像将图像直接分配给varialble img.src data:image/jpeg; base64,

I had also problem with url.createObjectURL(f) so I assign image directly to varialble img.src using base64 image with prefix data:image/jpeg;base64,

img.src='data:image/jpeg;base64,...image in base64...'

像这样:

        let data = JSON.parse(xhr.responseText);

        console.log(data.image_url);

        var img = new Image();
        img.src = 'data:image/jpeg;base64,' + data.image_url;
        
        img.onload = function () {
            ctxcanvasMask.drawImage(img, 0, 0);
        }


最低工作代码


Minimal working code


from flask import Flask, jsonify
from PIL import Image
import base64
import io

app = Flask(__name__)

@app.route('/getImage') # as default it uses `methods=['GET']`
def get_Image():

    #...
    #process image with cv2 then save so I can send it the the browser 
    #...
    
    #image = get_encoded_img("img\\truthMask.png")
    image = get_encoded_img("img/lenna.png")  # I use Linux path with `/` instead of `\\`
    
    return jsonify({'image_url': image})

def get_encoded_img(image_path):
    img = Image.open(image_path, mode='r')
    img_byte_arr = io.BytesIO()
    img.save(img_byte_arr, format='PNG')
    my_encoded_img = base64.encodebytes(img_byte_arr.getvalue()).decode('ascii')
    return my_encoded_img

@app.route('/')
def index():
    return """<!DOCTYPE html>
<html>
<body>    

<canvas id="myCanvas" width="100" height="100" style="z-index: 1;">
                    Your browser does not support the HTML canvas tag.</canvas>
<button name="getMask" id="getMask"> Show Mask </button>

<script>    
const canvasMask = document.getElementById('myCanvas');
const ctxcanvasMask = canvasMask.getContext('2d');

document.getElementById("getMask").addEventListener('click', () => {
    var xhr = new XMLHttpRequest();

    // Setup our listener to process compeleted requests
    xhr.onreadystatechange = function () {
        // Only run if the request is complete
        if (xhr.readyState !== 4) return;

        // Process our return data
        if (xhr.status >= 200 && xhr.status < 300) {
            // What do when the request is successful
            console.log("I got the image");
            
            let data = JSON.parse(xhr.responseText);

            console.log(data.image_url);

            var img = new Image();
            img.src = 'data:image/jpeg;base64,' + data.image_url;
            
            img.onload = function () {
                ctxcanvasMask.drawImage(img, 0, 0);
            }
        }
    };
    // Create and send a GET request
    // The first argument is the post type (GET, POST, PUT, DELETE, etc.)
    // The second argument is the endpoint URL
    xhr.open('GET', 'http://127.0.0.1:5000/getImage');
    xhr.send();
});
</script>

</body>
</html>
    """

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

结果:

顺便说一句::我使用了维基百科

BTW: I used image lenna.png from Wikipedia Lenna

如果使用 cv2 (或 numpy )创建图像,则不必保存图像,但可以直接转换 Image.fromarray(cv_image)

If you use cv2 (or numpy) to create image then you don't have to save it but you can directly convert Image.fromarray(cv_image)

@app.route('/getImage') # as default it uses `methods=['GET']`
def get_Image():
    img = cv2.imread("img/lenna.png")
    img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    img = cv2.resize(img, (100, 100))
    
    img = Image.fromarray(img)
    img_byte_arr = io.BytesIO()
    img.save(img_byte_arr, format='PNG')
    image = base64.encodebytes(img_byte_arr.getvalue()).decode('ascii')
    
    return jsonify({'image_url': image})

您甚至可以将 cv2 图像转换为 base64 ,而无需 pillow BytesIO

You can even convert cv2 image to base64 without pillow and BytesIO

@app.route('/getImage') # as default it uses `methods=['GET']`
def get_Image():
    img = cv2.imread("img/lenna.png")
    img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    img = cv2.resize(img, (100, 100))
    
    ret, buf = cv2.imencode('.png', img)
    
    image = base64.b64encode(buf).decode('ascii')
    
    return jsonify({'image_url': image})

您可以使用现代的 fetch()

<script>    
const canvasMask = document.getElementById('myCanvas');
const ctxcanvasMask = canvasMask.getContext('2d');

document.getElementById("getMask").addEventListener('click', () => {

    fetch('http://127.0.0.1:5000/getImage')
    .then(res => res.json())
    .then(data => {
        var img = new Image();
        img.src = 'data:image/jpeg;base64,' + data.image_url;
        img.onload = () => ctxcanvasMask.drawImage(img, 0, 0);
    })
    .catch(err => alert("PROBLEM\\n\\n" + err));
    
});
</script>


最终代码:


The final code:

from flask import Flask, jsonify
import cv2
import base64

app = Flask(__name__)

@app.route('/getImage')
def get_image():
    img = cv2.imread("img/lenna.png")
    img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    img = cv2.resize(img, (100, 100))
    
    ret, buf = cv2.imencode('.png', img)
    
    image = base64.b64encode(buf).decode('ascii')
    
    return jsonify({'image_url': image})

@app.route('/')
def index():
    return """<!DOCTYPE html>
<html>
<body>    

<canvas id="myCanvas" width="100" height="100" style="z-index: 1;">
                    Your browser does not support the HTML canvas tag.</canvas>
<button name="getMask" id="getMask"> Show Mask </button>

<script>    
const canvasMask = document.getElementById('myCanvas');
const ctxcanvasMask = canvasMask.getContext('2d');

document.getElementById("getMask").addEventListener('click', () => {

    fetch('http://127.0.0.1:5000/getImage')
    .then(res => res.json())
    .then(data => {
        var img = new Image();
        img.src = 'data:image/jpeg;base64,' + data.image_url;
        img.onload = () => ctxcanvasMask.drawImage(img, 0, 0);
    })
    .catch(err => alert("PROBLEM\\n\\n" + err));
    
});
</script>

</body>
</html>
"""

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


如果仅要将 filename 转换为 base64 ,则不需要 Image BytesIO .您只需要 open(...,'rb').read()

If you want only convert filename to base64 them you don't need Image and BytesIO. You need only open(..., 'rb').read()

@app.route('/getImage')
def get_image():
    image = get_encoded_img("img/lenna.png")

    return jsonify({'image_url': image})

def get_encoded_img(image_path):
    data = open(image_path, 'rb').read()
    return base64.encodebytes(data).decode('ascii')

这篇关于Flask将png图像发送到浏览器并在javascript画布中显示的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆