Flask将png图像发送到浏览器并在javascript画布中显示 [英] Flask send a png image to the browser and display in javascript canvas
问题描述
仍将继续学习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屋!