Skip to content

Instantly share code, notes, and snippets.

@ganeshkumartk
Last active March 5, 2020 17:29
Show Gist options
  • Save ganeshkumartk/dc1e7ff8b2c5e3ab61b2e045c5a858be to your computer and use it in GitHub Desktop.
Save ganeshkumartk/dc1e7ff8b2c5e3ab61b2e045c5a858be to your computer and use it in GitHub Desktop.
Index page: Place it in templates folder ---- main.css & main.js: Place in static folder
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <title>Demo</title>
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <link rel="stylesheet" type="text/css" href="{{ url_for('static',filename='main.css') }}" />
  </head>
<body>
<div class="main">
  <div class="title">
<h3>Image Classifier</h3>
</div>
  <div class="panel">
    <input id="file-upload" class="hidden" type="file" accept="image/x-png,image/gif,image/jpeg" />
    <label for="file-upload" id="file-drag" class="upload-box">
      <div id="upload-caption">Drop image here or click to select</div>
      <img id="image-preview" class="hidden" />
    </label>
  </div>
  <div style="margin-bottom: 2rem;">
    <input type="button" value="Submit" class="button" onclick="submitImage();" />
    <input type="button" value="Clear" class="button" onclick="clearImage();" />
  </div>
  <div id="image-box">
    <img id="image-display" />
    <div id="pred-result" class="hidden"></div>
    <svg id="loader" class="hidden" viewBox="0 0 32 32" width="32" height="32">
      <circle id="spinner" cx="16" cy="16" r="14" fill="none"></circle>
    </svg>
  </div>
</div>
</body>
<footer>
    <script src="{{ url_for('static',filename='main.js') }}"></script>
  </footer>
</html>
body {
  font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen,
    Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif;
  -webkit-font-smoothing: antialiased;
  background-color: #f8f8f8;
}
/* Global button style */
.button {
  font-family: inherit;
  text-align: center;
  cursor: pointer;
  border: none;
  text-decoration: none;
  outline: none;
  color: #ffffff;
  background-color: rgb(0, 120, 212);
  padding: 0.5rem 1.2rem;
  border-radius: 2px;
  font-size: 1rem;
  min-width: 6rem;
}
.button:hover {
  background-color: rgb(16, 110, 190);
}
.button.disabled {
  pointer-events: none;
  background-color: #cccccc;
  color: #666666;
}
/* Main section */
.main {
  box-sizing: border-box;
  display: flex;
  flex-direction: column;
  align-items: center;
}
.main .title h3 {
  font-size: 2.3rem;
  font-weight: 300;
  margin: 0.8rem 0;
}
.hidden {
  display: none;
}
.reveal {
  opacity: 0;
}
.reveal:hover {
  opacity: 0.2;
}
/* Upload box */
.upload-box {
  font-size: 0.8rem;
  color: #666666;
  cursor: pointer;
  width: 16rem;
  height: 10rem;
  background: #fff;
  border: 0.1rem dashed #838388;
  border-radius: 0.4rem;
  display: flex;
  justify-content: center;
  align-items: center;
  flex-direction: column;
  margin: 1rem 0 2rem 0;
}
.upload-box.dragover {
  /* background-color: grey; */
  color: #eeeeee;
  border: 0.1rem solid rgb(0, 120, 212);
  box-shadow: inset 0 0 0 0.1rem rgb(0, 120, 212);
}
.upload-box:hover {
  border-color: rgb(0, 120, 212);
}
.upload-box #image-preview {
  max-width: 14rem;
  max-height: 8rem;
  box-shadow: 0 4px 4px 0 rgba(0, 0, 0, 0.2), 0 6px 10px 0 rgba(0, 0, 0, 0.19);
}
#image-result {
  box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
  max-height: 20rem;
}
#image-box {
  position: relative;
  width: auto;
  float: left;
  margin-bottom: 2rem;
}
#image-display {
  box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
  max-height: 20rem;
}
#image-display.loading {
  filter: brightness(30%);
}
#pred-result {
  color: white;
  font-size: 1.5rem;
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}
#loader {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  z-index: 10;
  margin: 0 auto;
}
/* Animation */
#spinner {
  box-sizing: border-box;
  stroke: #cccccc;
  stroke-width: 3px;
  transform-origin: 50%;
  animation: line 1.6s cubic-bezier(0.4, 0, 0.2, 1) infinite,
    rotate 1.6s linear infinite;
}
@keyframes rotate {
  from {
    transform: rotate(0);
  }
  to {
    transform: rotate(450deg);
  }
}
@keyframes line {
  0% {
    stroke-dasharray: 2, 85.964;
    transform: rotate(0);
  }
  50% {
    stroke-dasharray: 65.973, 21.9911;
    stroke-dashoffset: 0;
  }
  100% {
    stroke-dasharray: 2, 85.964;
    stroke-dashoffset: -65.973;
    transform: rotate(90deg);
  }
}
var fileDrag = document.getElementById("file-drag");
var fileSelect = document.getElementById("file-upload");
// Add event listeners
fileDrag.addEventListener("dragover", fileDragHover, false);
fileDrag.addEventListener("dragleave", fileDragHover, false);
fileDrag.addEventListener("drop", fileSelectHandler, false);
fileSelect.addEventListener("change", fileSelectHandler, false);
function fileDragHover(e) {
  // prevent default behaviour
  e.preventDefault();
  e.stopPropagation();
  fileDrag.className = e.type === "dragover" ? "upload-box dragover" : "upload-box";
}
function fileSelectHandler(e) {
  // handle file selecting
  var files = e.target.files || e.dataTransfer.files;
  fileDragHover(e);
  for (var i = 0, f; (f = files[i]); i++) {
    previewFile(f);
  }
}
//========================================================================
// Web page elements for functions to use
//========================================================================
var imagePreview = document.getElementById("image-preview");
var imageDisplay = document.getElementById("image-display");
var uploadCaption = document.getElementById("upload-caption");
var predResult = document.getElementById("pred-result");
var loader = document.getElementById("loader");
//========================================================================
// Main button events
//========================================================================
function submitImage() {
  // action for the submit button
  console.log("submit");
  if (!imageDisplay.src || !imageDisplay.src.startsWith("data")) {
    window.alert("Please select an image before submit.");
    return;
  }
  loader.classList.remove("hidden");
  imageDisplay.classList.add("loading");
  // call the predict function of the backend
  predictImage(imageDisplay.src);
}
function clearImage() {
  // reset selected files
  fileSelect.value = "";
  // remove image sources and hide them
  imagePreview.src = "";
  imageDisplay.src = "";
  predResult.innerHTML = "";
  hide(imagePreview);
  hide(imageDisplay);
  hide(loader);
  hide(predResult);
  show(uploadCaption);
  imageDisplay.classList.remove("loading");
}
function previewFile(file) {
  // show the preview of the image
  console.log(file.name);
  var fileName = encodeURI(file.name);
  var reader = new FileReader();
  reader.readAsDataURL(file);
  reader.onloadend = () => {
    imagePreview.src = URL.createObjectURL(file);
    show(imagePreview);
    hide(uploadCaption);
    // reset
    predResult.innerHTML = "";
    imageDisplay.classList.remove("loading");
    displayImage(reader.result, "image-display");
  };
}
//========================================================================
// Helper functions
//========================================================================
function predictImage(image) {
  fetch("/predict", {
    method: "POST",
    headers: {
      "Content-Type": "application/json"
    },
    body: JSON.stringify(image)
  })
    .then(resp => {
      if (resp.ok)
        resp.json().then(data => {
          displayResult(data);
        });
    })
    .catch(err => {
      console.log("An error occured", err.message);
      window.alert("Oops! Something went wrong.");
    });
}
function displayImage(image, id) {
  // display image on given id <img> element
  let display = document.getElementById(id);
  display.src = image;
  show(display);
}
function displayResult(data) {
  // display the result
  // imageDisplay.classList.remove("loading");
  hide(loader);
  predResult.innerHTML = data.result;
  show(predResult);
}
function hide(el) {
  // hide an element
  el.classList.add("hidden");
}
function show(el) {
  // show an element
  el.classList.remove("hidden");
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment