// For this I decided to make my own instead of port or build on another code base// link for python code for neural net training https://colab.research.google.com/drive/1hPdGIQm1UCjRe9ImYwQwpjx-Jm12MkZK?usp=sharing// link for dataset used https://www.kaggle.com/datasets/sachinpatel21/az-handwritten-alphabets-in-csv-format// This code uses tensorflow js library to import the model trained in python (keras) and use it on the web to make predictions// I have uploaded the tf.min.js library and the trained model files on AB// following is the architecture of the model I build in keras library in python/*
Model: "sequential_1"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
conv2d_3 (Conv2D) (None, 28, 28, 32) 320
max_pooling2d_2 (MaxPooling (None, 14, 14, 32) 0
2D)
conv2d_4 (Conv2D) (None, 14, 14, 64) 18496
max_pooling2d_3 (MaxPooling (None, 7, 7, 64) 0
2D)
flatten_1 (Flatten) (None, 3136) 0
dense_2 (Dense) (None, 100) 313700
dense_3 (Dense) (None, 26) 2626
=================================================================
Total params: 335,142
Trainable params: 335,142
Non-trainable params: 0
*/
let model;
let correctPreds =0;
let wrongPreds =0;
let totalPreds =0;function getRandomAlphabet(){return"abcdefghijklmnopqrstuvwxyz".toUpperCase()[Math.floor(Math.random()*26)];}
let currentChar = getRandomAlphabet();function setup(){
createCanvas(400,400);
background(0,0,0);// loading the tensorflow js script
$.getScript ("/uploads/prashantk047/tf.min.js",function(){// loading the model from the uploded file model.json this function also make the request for the// associated weights file group1-shard1of1.bin which is also uploaded on AB
tf.loadLayersModel("/uploads/prashantk047/model.json").then(model_ =>{
model = model_;
model.summary();});});// making the markup for interaction and prediction
let thehtml ="Press the button to predict after drawing on the canvas<br> "+" <button onclick='predict()' class='normbutton' >Predict</button> <br> ";
AB.msg ( thehtml,3);
thehtml ="Press to Clear the canvas "+" <button onclick='clean()' class='normbutton' >Clear</button> <br> ";
AB.msg ( thehtml,4);
thehtml =`PredictedCharacter: NULL`
AB.msg ( thehtml,5);
thehtml ="<h2>This section is to check the accuracy of the predictions</h2>";
AB.msg( thehtml,8);
thehtml =`Draw the Alphabet<p style="color: blue; font-weight: bold; font-size:30px">${currentChar}</p>`;
AB.msg( thehtml,9);
thehtml =`<table style="width:100%; border: 3px solid green; margin: 1rem 0"><tr><th style="text-align:center">CorrectGuesses</th><th style="text-align:center">WrongGuesses</th></tr><tr><td style="text-align:center">${correctPreds}</td><td style="text-align:center">${wrongPreds}</td></tr></table>`;
AB.msg( thehtml,10);//---------------------------------------------------}function predict(){
totalPreds++;
let labels ="abcdefghijklmnopqrstuvwxyz".toUpperCase();// this model expects an input of type tensor and of dimension nullx28x28x1 where the// first is null because there can be multiple images for prediction// here we will be prediction one 1 character at a time// so the input dimension will be 1x28x28x1// this takes the canvas created by p5 js and converts it to a matrix from pixels
let image = tf.browser.fromPixels(document.getElementById('defaultCanvas0')).resizeNearestNeighbor([28,28])// converting the matrix to 28x28 as the model expects the image to be of this size.mean(2)// as the image from canvas has 3 color channels, this gets rid of the channel dimension.expandDims(2)// this add an extra dimension to make it 28x28x1.expandDims()// adds one more dimension to match the input size of 1 1x28x28x1.toFloat().div(255);// normalize the values from 0-255 to 0-1
let pred = model.predict(image).as1D()
let argMax = pred.argMax().dataSync()[0];
let finalPred = labels[argMax];if( finalPred == currentChar){
correctPreds++;}else{
wrongPreds++;}
AB.msg (`PredictedCharacter:<br/><p style="color:red; font-size: 30px; font-weight:bold">${finalPred}</p> ${finalPred == currentChar?'Correct!!':'Wrong'}`,5);
currentChar = getRandomAlphabet();
thehtml =`Draw the Alphabet<p style="color: blue; font-weight: bold; font-size:30px">${currentChar}</p>`;
AB.msg( thehtml,9);
thehtml =`<table style="width:100%; border: 3px solid green; margin: 1rem 0"><tr><th style="text-align:center">CorrectGuesses</th><th style="text-align:center">WrongGuesses</th></tr><tr><td style="text-align:center">${correctPreds}</td><td style="text-align:center">${wrongPreds}</td></tr></table>`;
AB.msg( thehtml,10);
thehtml =`Accuracy: ${parseFloat(correctPreds*100/totalPreds).toFixed(2)}%`
AB.msg( thehtml,11);
console.log(labels[argMax]);}function clean(){
clear();
background(0,0,0);}function mouseDragged(){
noStroke();
fill(255,255,255);
ellipse(mouseX, mouseY,25);}