我正在尝试在HTML5画布上显示在python后端中生成的图像。
我尝试过的烧瓶代码的两个变体:
1)
@app.route(r'/api/a', methods=["GET", "POST"])
def send_heatmap():
return open(r"..\\a\\b\\50.png", "rb").read()
2)
@app.route(r'/api/a', methods=["POST"])
def send_heatmap():
img = io.BytesIO(open(r"..\\a\\b\\50.png", "rb").read())
return send_file(img, mimetype='image/png', as_attachment=True, attachment_filename="heatmap.png")
其中一种JS尝试:
console.log(result);
var canvas = document.getElementsByTagName('canvas');
context = canvas[1].getContext('2d');
var a = new ImageData(result["content"], 480)
context.putImageData(a, 0, 0);
我的另一种JS尝试从图像中删除了标头信息,但也没有切块。
我收到Uncaught DOMException: Failed to construct 'ImageData': The source width is zero or not a number.
等问题。如何将数据从python发送到js?
答案 0 :(得分:1)
通过这个最小的工作示例,我可以在画布上看到图像。
如果您访问主页http://localhost:5000/,则脚本将从http://localhost:5000/api/a加载图像并在画布上绘制。
from flask import Flask, send_file
app = Flask(__name__)
@app.route('/api/a')
def image():
return send_file('/home/user/images/ball.png', mimetype='image/png')
@app.route('/')
def index():
return '''
<canvas></canvas>
<script>
var canvas = document.getElementsByTagName('canvas');
var ctx = canvas[0].getContext('2d');
var img = new Image();
img.src = "/api/a";
// it can't draw it at once. it has to wait till image is loaded
//ctx.drawImage(img, 0, 0);
img.onload = function() {
img.style.display = 'none'; // I don't know why they hide it
ctx.drawImage(img, 0, 0); // draw on canvas
};
</script>
'''
app.run()
要转换Image to
ImageData you have to draw it on
画布`。
img.onload = function() {
console.log('WxH: ' + img.width + 'x' + img.height)
img.style.display = 'none'; // hide it
ctx.drawImage(img, 0, 0); // draw Image on canvas
var imageData = ctx.getImageData(0, 0, img.width, img.height); // get ImageData from canvas
ctx.putImageData(imageData, 10, 10); // put ImageData in differen place
};
我从Pixel manipulation with canvas那里获得的有关画布的信息
编辑:生成图像并发送但不保存在磁盘上。
import numpy as np
from PIL import Image
import io
@app.route('/api/a')
def array():
arr = np.array([
[255, 255, 0, 0, 0, 0, 0, 0, 255, 255],
[255, 0, 255, 255, 255, 255, 255, 255, 0, 255],
[ 0, 255, 255, 255, 255, 255, 255, 255, 255, 0],
[ 0, 255, 255, 0, 255, 255, 0, 255, 255, 0],
[ 0, 255, 255, 255, 255, 255, 255, 255, 255, 0],
[ 0, 255, 255, 255, 255, 255, 255, 255, 255, 0],
[ 0, 255, 0, 255, 255, 255, 255, 0, 255, 0],
[ 0, 255, 255, 0, 0, 0, 0, 255, 255, 0],
[255, 0, 255, 255, 255, 255, 255, 255, 0, 255],
[255, 255, 0, 0, 0, 0, 0, 0, 255, 255],
])
img = Image.fromarray(arr.astype('uint8')) # convert arr to image
file_object = io.BytesIO() # create file in memory
img.save(file_object, 'PNG') # save PNG in file in memory
file_object.seek(0) # move to beginning of file
return send_file(file_object, mimetype='image/png')
完整代码:
from flask import Flask, send_file
import numpy as np
from PIL import Image
import io
app = Flask(__name__)
@app.route('/')
def index():
return '''
<!DOCTYPE html>
<html>
<body>
<canvas></canvas>
<script>
var canvas = document.getElementsByTagName('canvas');
var ctx = canvas[0].getContext('2d');
var img = new Image();
img.src = "/api/b";
// it can't draw it at once. it has to wait till it is loaded
//ctx.drawImage(img, 0, 0);
img.onload = function() {
img.style.display = 'none'; // I don't know why they hide it
console.log('WxH: ' + img.width + 'x' + img.height)
// convert Image to ImageData
//(it has to draw on canvas so it could need second canvas for this)
ctx.drawImage(img, 0, 0);
var imageData = ctx.getImageData(0, 0, img.width, img.height)
//put ImageData many times
for(x = 0 ; x < 100 ; x += 10) {
for(y = 0 ; y < 100 ; y += 10) {
ctx.putImageData(imageData, x, y);
}
}
};
</script>
</body>
</html>
'''
@app.route('/api/b')
def array():
'''
generate image from numpy.array using PIL.Image
and send without saving on disk using io.BytesIO'''
arr = np.array([
[255, 255, 0, 0, 0, 0, 0, 0, 255, 255],
[255, 0, 255, 255, 255, 255, 255, 255, 0, 255],
[ 0, 255, 255, 255, 255, 255, 255, 255, 255, 0],
[ 0, 255, 255, 0, 255, 255, 0, 255, 255, 0],
[ 0, 255, 255, 255, 255, 255, 255, 255, 255, 0],
[ 0, 255, 255, 255, 255, 255, 255, 255, 255, 0],
[ 0, 255, 0, 255, 255, 255, 255, 0, 255, 0],
[ 0, 255, 255, 0, 0, 0, 0, 255, 255, 0],
[255, 0, 255, 255, 255, 255, 255, 255, 0, 255],
[255, 255, 0, 0, 0, 0, 0, 0, 255, 255],
])
img = Image.fromarray(arr.astype('uint8')) # convert arr to image
file_object = io.BytesIO() # create file in memory
img.save(file_object, 'PNG') # save as PNG in file in memory
file_object.seek(0) # move to beginning of file
# so send_file() will read data from beginning of file
return send_file(file_object, mimetype='image/png')
app.run()