Issue
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!
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>
Solution
I used your code to create minimal working code - and it sends image to browser.
All problem was with names of variables in JavaScript.
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');
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...'
like this:
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)
Result:
BTW: I used image lenna.png
from Wikipedia Lenna
EDIT:
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})
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})
Instead of old XMLHttpRequest()
you can use modern 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)
EDIT:
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')
Answered By - furas
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.