Spaces:
Runtime error
Runtime error
<html lang="en"> | |
<head> | |
<meta charset="UTF-8"> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
<link rel="icon" type="image/png" href="/static/favicon.png"> | |
<link rel="icon" type="image/x-icon" href="/static/favicon.ico"> | |
<title>Draw and Predict Handwritten Digits</title> | |
<style> | |
body { | |
font-family: 'Montserrat', sans-serif; | |
} | |
#prediction-result { | |
} | |
.prediction-item { | |
margin-bottom: 10px; | |
display: flex; | |
} | |
.prediction-digit { | |
font-size: 14px; | |
} | |
.progress-container { | |
display: flex; | |
align-items: center; | |
} | |
.progress-bar { | |
width: 100px; | |
height: 10px; | |
background-color: #ccc; | |
border-radius: 6px; | |
margin-left: 10px; | |
} | |
.progress { | |
height: 100%; | |
border-radius: 5px; | |
background-color: #088395; | |
transition: width 0.3s ease-in-out; | |
} | |
#whiteboard { | |
border: 3px solid #088395; | |
/* Simple black border */ | |
border-radius: 10px; | |
/* Rounded corners */ | |
box-shadow: 2px 2px 5px rgba(0, 0, 0, 0.3); | |
/* Subtle shadow effect */ | |
background-color: #088395; | |
} | |
#capture-button { | |
background-color: #071952; | |
color: white; | |
border: none; | |
padding: 10px 20px; | |
cursor: pointer; | |
font-size: 16px; | |
border-radius: 3px; | |
margin-top: 10px; | |
width: 190px; | |
margin-right: 20px; | |
} | |
#clear-button { | |
background-color: #F2F7A1; | |
color: black; | |
border: none; | |
padding: 10px 20px; | |
cursor: pointer; | |
font-size: 16px; | |
border-radius: 3px; | |
margin-top: 10px; | |
width: 190px; | |
} | |
#container { | |
display: flex; | |
flex-direction: column; | |
align-items: center; | |
justify-content: center; | |
margin-right: 10px; | |
} | |
#btn-container { | |
display: flex; | |
flex-direction: row; | |
align-items: center; | |
} | |
#parent { | |
display: flex; | |
justify-content: center; | |
align-items: center; | |
} | |
</style> | |
</head> | |
<body> | |
<h3 style="text-align:center;">Draw and Predict Handwritten Digits</h3> | |
<div id="parent"> | |
<div id='container'> | |
<canvas id="whiteboard" width="400" height="200"></canvas> | |
<div id='btn-container'> | |
<button id="capture-button">Predict</button> | |
<button id="clear-button">Clear</button> | |
</div> | |
</div> | |
<div id="prediction-result"></div> | |
</div> | |
<script> | |
var canvas = document.getElementById('whiteboard'); | |
var context = canvas.getContext('2d'); | |
var drawing = false; | |
context.strokeStyle = 'white'; | |
context.lineWidth = 15; | |
canvas.addEventListener('mousedown', function (e) { | |
drawing = true; | |
context.beginPath(); | |
context.moveTo(e.clientX - canvas.getBoundingClientRect().left, e.clientY - canvas.getBoundingClientRect().top); | |
}); | |
canvas.addEventListener('mousemove', function (e) { | |
if (drawing) { | |
context.lineTo(e.clientX - canvas.getBoundingClientRect().left, e.clientY - canvas.getBoundingClientRect().top); | |
context.stroke(); | |
} | |
}); | |
canvas.addEventListener('mouseup', function () { | |
drawing = false; | |
}); | |
canvas.addEventListener('mouseout', function () { | |
drawing = false; | |
}); | |
var clearButton = document.getElementById('clear-button'); | |
clearButton.addEventListener('click', function () { | |
context.clearRect(0, 0, canvas.width, canvas.height); | |
}); | |
function isCanvasEmpty(canvas) { | |
const context = canvas.getContext('2d'); | |
const pixelBuffer = new Uint32Array(context.getImageData(0, 0, canvas.width, canvas.height).data.buffer); | |
return !pixelBuffer.some(color => color !== 0); | |
} | |
var predictionResult = document.getElementById('prediction-result'); | |
var captureButton = document.getElementById('capture-button'); | |
captureButton.addEventListener('click', function () { | |
captureButton.disabled = true | |
captureButton.style.opacity = "0.5"; | |
captureButton.innerText = 'Loading...' | |
var imageData = canvas.toDataURL("image/png"); | |
var formData = new FormData(); | |
formData.append("image", dataURLtoBlob(imageData), "image.png"); | |
fetch('/predict', { | |
method: 'POST', | |
body: formData, | |
}) | |
.then(response => response.json()) | |
.then(data => { | |
predictionResult.innerHTML = ''; | |
data.prediction.forEach(item => { | |
const digitItem = document.createElement('div'); | |
digitItem.classList.add('prediction-item'); | |
const digitText = document.createElement('div'); | |
digitText.classList.add('prediction-digit'); | |
digitText.textContent = `Digit ${item.digit}:`; | |
const progressContainer = document.createElement('div'); | |
progressContainer.classList.add('progress-container'); | |
const progressBar = document.createElement('div'); | |
progressBar.classList.add('progress-bar'); | |
const progress = document.createElement('div'); | |
progress.classList.add('progress'); | |
progress.style.width = item.prob; | |
progressBar.appendChild(progress); | |
progressContainer.appendChild(progressBar); | |
digitItem.appendChild(digitText); | |
digitItem.appendChild(progressContainer); | |
predictionResult.appendChild(digitItem); | |
captureButton.disabled = false | |
captureButton.style.opacity = "1"; | |
captureButton.innerText = 'Predict' | |
}); | |
}) | |
.catch(error => { | |
console.error('Error:', error); | |
predictionResult.textContent = 'Something went wrong, try again.'; | |
captureButton.disabled = false | |
captureButton.style.opacity = "1"; | |
captureButton.innerText = 'Predict' | |
}); | |
}); | |
// Function to convert a data URL to a Blob | |
function dataURLtoBlob(dataURL) { | |
var arr = dataURL.split(','); | |
var mime = arr[0].match(/:(.*?);/)[1]; | |
var bstr = atob(arr[1]); | |
var n = bstr.length; | |
var u8arr = new Uint8Array(n); | |
while (n--) { | |
u8arr[n] = bstr.charCodeAt(n); | |
} | |
return new Blob([u8arr], { type: mime }); | |
} | |
</script> | |
</body> | |
</html> |