Digits Recognizer using Python and React. Create UI

Close
Do you have any questions? Contact us!
I agree the Terms of Service
published April 12, 2018

We've passed through the training machine learning algorithm, image processing, and integrating the trained algorithm with the Flask backend. Now I am here to put the final by implementing a React application for drawing digits.
#Environment setup

I used a CRA boilerplate, but it's not so important. You can configure your application from scratch if time allows you.
create-react-app frontend
cd frontend

So after setting up React environment, we also need one more dependency for drawing. My choice fell on react-sketch. It perfectly matches our needs.
npm i react-sketch
Now we have everything to make up our drawer.
#Implement the app

The whole App can be written in just 80 lines of code.
import React, { Component } from "react";
import logo from "./assets/logo.svg";
import "./assets/App.css";
import { SketchField, Tools } from "react-sketch";
import { makePrediction } from "./api";

const pixels = count => `${count}px`;
const percents = count => `${count}px`;

const MAIN_CONTAINER_WIDTH_PX = 200;
const MAIN_CONTAINER_HEIGHT = 100;
const MAIN_CONTAINER_STYLE = {
  width: pixels(MAIN_CONTAINER_WIDTH_PX),
  height: percents(MAIN_CONTAINER_HEIGHT),
  margin: "0 auto"
};

const SKETCH_CONTAINER_STYLE = {
  border: "1px solid black",
  width: pixels(MAIN_CONTAINER_WIDTH_PX - 2),
  height: pixels(MAIN_CONTAINER_WIDTH_PX - 2),
  backgroundColor: "white"
};

class App extends Component {
  state = {
    prediction: undefined,
    errors: undefined
  };

  handleSubmit = e => {
    const image = this.sketch.toDataURL();
    this.setState({
      prediction: undefined,
      errors: undefined
    });
    makePrediction(image)
      .then(prediction => this.setState({ prediction }))
      .catch(errors => this.setState({ errors }));
  };

  handleClear = e => this.sketch.clear();

  render() {
    const { prediction, errors } = this.state;
    return (
      <div className="App" style={MAIN_CONTAINER_STYLE}>
        <div>
          <header className="App-header">
            <img src={logo} className="App-logo" alt="logo" />
            <h1 className="App-title">Draw a digit</h1>
          </header>
          <div style={SKETCH_CONTAINER_STYLE}>
            <SketchField
              ref={sketch => (this.sketch = sketch)}
              width="100%"
              height="100%"
              tool={Tools.Pencil}
              imageFormat="jpg"
              backgroundColor="white"
              lineColor="gray"
              lineWidth={8}
            />
          </div>
          {prediction && <h3>Predicted value is: {prediction}</h3>}
          <button onClick={this.handleClear}>Clear</button>
          <button onClick={this.handleSubmit}>Guess the number</button>
          {errors && <p style={{ color: "red" }}>Something went wrong</p>}
        </div>
      </div>
    );
  }
}

export default App;
There are no unfamiliar things, I guess, except the SketchField component. It has props that are correctly named, so as you see, we have width and height attributes, the tool with which we'll draw our image, its format, the colors of background and pencil, and the width of the line. But I did not say anything about the ref. It is used here to get our image. So we assign SketchField ref to this sketch, and then when the "Submit" button is clicked, we can get the drawn image named .toDataURL().

One more unknown thing is makePrediction function. It is a simple API command with status code validation.
const validateStatusCode = response =>
  new Promise((resolve, reject) => {
    const status = response.status;
    const next = status < 400 ? resolve : reject;
    response.text().then(next);
  });

export const makePrediction = image =>
  fetch("/api/predict", {
    method: "POST",
    headers: {
      "Content-Type": "application/json"
    },
    body: JSON.stringify({ image })
  }).then(validateStatusCode);
#Test the app

Let's now test our application. Start it with:
npm run start
And go to the localhost:3000.
Check out the DEMO. All code is available on my Github repository.

#Conclusion

I understand that the quality of this classifier is not as good as you want. The reason is the big difference between artificial and actual data. But the reason for creating this project is learning something new and sharing this knowledge with others. Thank you for reading this article. I hope you've discovered lots of exciting things, keep on studying and improving.
Did you like this article?
Share article on social networks

Originally published at
teimurjan.github.io.
Teimur Gasanov
Python/Go/Javascript full stack developer
Made on
Tilda