Skip to content
Advertisement

Sent information from backend (flask) to frontend without refreshing the page

  1. I have an interface where I can draw a picture.
  2. I have a machine learning model that can recognize this image.

What I want? After clicking on the button “Recognize” I want to send the output from a machine learning model to an external interface i.e. a text field WITHOUT REFRESHING THE PAGE.

  1. Before pressing the button “Recognize”
  2. After pressing the button “Recognize”

With the code below I can print the output of the model to the terminal, but I need to send it to a text field.

paint.html

<html>
<head>
<meta charset="utf-8">
<title>Drawing App</title>
<link rel="stylesheet" href="static/style.css" type="text/css" media="screen" title="no title">
<link href='https://fonts.googleapis.com/css?family=Open+Sans:300' rel='stylesheet' type='text/css'>
</head>
<body>
  <h2>Phone Number Recognition<img src="https://cdn1.iconfinder.com/data/icons/fatcow/32/painbrush.png" alt="" class="paint"></h2>
<canvas width="1024" height="256" id="mainCanvas"></canvas>
<div class="controls">
    <button id="clear" onclick='clear_canvas()'>Clear</button>
    <button id="recognize" onclick='recognize_number()'>Recognize</button>
    <label id="label1"></label>
    </div>
</div>
<script src="https://code.jquery.com/jquery-1.11.0.min.js" type="text/javascript" charset="utf-8"></script>
<script src="static/main.js" type="text/javascript" charset="utf-8"></script>
</body>
</html>

style.css

* {
    margin: 0;
    padding: 0;
}

body {
    background: #F5F5F5;
    font-family: sans-serif;
    height: 100%;
    width: 100%;
}

h2 {
  text-align: center;
  margin: 20px;
  font-family: 'Open Sans', sans-serif;
}

.paint {
  padding-top: 2px;
}

/* CANVAS STYLING
===================*/

canvas {
    display: block;
    margin: 40px auto 10px;
    border-radius: 5px;
    border-left: 1px solid #E0E0E0;
    border-right: 1px solid #E0E0E0;
    border-top: 1px solid #E0E0E0;
    box-shadow: 0 4px 0 0 #E0E0E0;
    cursor: url(../img/cursor.png), crosshair;
}

.controls {
    min-height: 60px;
    margin: 0 auto;
    width: 600px;
    border-radius: 5px;
    overflow: hidden;
}
ul {
    list-style:none;
    margin: 0;
    float:  left;
    padding: 10px 0 20px;
    width: 100%;
    text-align: center;
}

/* BUTTON STYLES
==============*/

button {
    background: #68B25B;
    box-shadow: 0 3px 0 0 #6A845F;
    color: #fff;
    outline: none;
    cursor: pointer;
    text-shadow: 0 1px #6A845F;
    display: block;
    font-size: 16px;
    line-height: 40px;
}
label {
    background: #c7ebc1;
    box-shadow: 0 3px 0 0 #6A845F;
    color: rgb(0, 0, 0);
    outline: none;
    cursor: pointer;
    text-shadow: 0 1px #6A845F;
    display: block;
    font-size: 16px;
    line-height: 40px;
}
#clear {
    border: none;
    border-radius: 5px;
    margin: 10px auto;
    padding: 0 20px;
    width: 160px;
    height: 40px;
}
#recognize {
    border: none;
    border-radius: 5px;
    margin: 10px auto;
    padding: 0 20px;
    width: 160px;
    height: 40px;
}
#label1 {
    border: none;
    border-radius: 5px;
    margin: 10px auto;
    padding: 0 20px;
    width: 260px;
    height: 40px;
}

main.js

var colour = $(".selected").css("background-color");
var $canvas = $("canvas");
var context = $canvas[0].getContext("2d");
var lastEvent;
var mouseDown = false;

context.fillStyle = "white";
context.fillRect(0, 0, $canvas[0].width, $canvas[0].height);

// On mouse events on the canvas
$canvas.mousedown(function (e) {
    lastEvent = e;
    mouseDown = true;
}).mousemove(function (e) {
    // Draw lines
    if (mouseDown) {
        context.beginPath();
        context.moveTo(lastEvent.offsetX, lastEvent.offsetY);
        context.lineTo(e.offsetX, e.offsetY);
        context.strokeStyle = colour;
        context.lineWidth = 10;
        context.lineCap = 'round';
        context.stroke();
        lastEvent = e;
    }
}).mouseup(function () {
    mouseDown = false;
}).mouseleave(function () {
    $canvas.mouseup();
});

// Clear the canvas when button is clicked
function clear_canvas() {
    context.fillStyle = "white";
    context.fillRect(0, 0, $canvas[0].width, $canvas[0].height);
}

function recognize_number() {
    var imgURL = $canvas[0].toDataURL('image/jpg');
    $.ajax({
        type: "POST",
        url: "http://172.28.104.162:8080/hook",
        data:{
          imageBase64: imgURL
        }
      }).done(function() {
        console.log('sent');
      });
}

Flask

from flask import Flask, render_template, request
import os
import base64
import re

SAVE_PATH = '../data_from_flask'
app = Flask(__name__)

def some_model(img_path):
  return 'some_output'

@app.route("/")
def home():
    return render_template("paint.html")

@app.route('/hook', methods=['GET', 'POST'])
def recognize_image():
    image_b64 = request.values['imageBase64']
    image_data = re.sub('^data:image/.+;base64,', '', image_b64)
    image_path = f"{SAVE_PATH}/flask_{len(os.listdir(SAVE_PATH))}.jpg"
    with open(image_path, "wb") as fh:
        fh.write(base64.decodebytes(bytes(image_data, encoding='UTF-8')))
    
    recognized_number = some_model(img_path=image_path)
    print(recognized_number)
    return render_template('paint.html')

if __name__ == "__main__":
    app.run(host='0.0.0.0', port='8080', debug=False)

Advertisement

Answer

You can get your element by its id and set the text to your computed output.

const labelElement = document.getElementById('label1');

function recognize_number() {
    var imgURL = $canvas[0].toDataURL('image/jpg');
    $.ajax({
        type: "POST",
        url: "http://172.28.104.162:8080/hook",
        data:{
          imageBase64: imgURL
        }
      }).done(function(output) {
        labelElement.innerText = output;
      });
}

Advertisement