Code viewer for World: Preprocessing to improve c...

// Cloned by Abdelshafa Abdala on 17 Nov 2021 from World "Preprocessing to improve character recognition" by Philip 
// Please leave this clone trail here.
 
const PIXELS=28,
PIXELSSQUARED=PIXELS*PIXELS,

NOTRAIN=6e4,
NOTEST=1e4,

noinput=PIXELSSQUARED,
nohidden=64,
nooutput=10,

learningrate=.1;

let do_training=!0;

const TRAINPERSTEP=30,
TESTPERSTEP=5,



ZOOMFACTOR=7,
ZOOMPIXELS=7*PIXELS,

canvaswidth=PIXELS+ZOOMPIXELS+50,
canvasheight=3*ZOOMPIXELS+100,




DOODLE_THICK=11,
DOODLE_BLUR=3;

let mnist,

nn,

doodle,demo,
trainrun=1,
train_index=0,

testrun=1,
test_index=0,
total_tests=0,
total_correct=0,

doodle_exists=!1,
demo_exists=!1,

mousedrag=!1;

var train_inputs,test_inputs,demo_inputs,doodle_inputs;


function randomWeight()
{
    return AB.randomFloatAtoB(-.5,.5)}$("#runheaderbox").css({"max-height":"95vh"});
    let htmlPositions=[0,1,3,4,5,6,7,8,9,10,2,11,12,13];
    
    var thehtml;
    
    thehtml="<hr> <h1> 1. Doodle </h1> Top row: Doodle (left) and shrunk (right). <br>  Draw your doodle in top LHS. <button onclick='wipeDoodle();' class='normbutton' >Clear doodle</button> <br> "+validateDoodleHtml(),
    AB.msg(thehtml,htmlPositions[1]),
    
    thehtml="<hr> <h1> 2. Training </h1> Middle row: Training image magnified (left) and original (right). <br>   <button onclick='do_training = false;' class='normbutton' >Stop training</button> <br> ",
    AB.msg(thehtml,htmlPositions[3]),
    
    thehtml="<h3> Hidden tests </h3> ",
    AB.msg(thehtml,htmlPositions[5]),
    
    thehtml="<hr> <h1> 3. Demo </h1>The Demos begin to run automatically at 80% accuracy unless turned off! Bottom row: Test image magnified (left) and  original (right). <br> The network is <i>not</i> trained on any of these images. <br>  <button onclick='makeDemo();' class='normbutton' >Demo test image</button> <br> ",
    AB.msg(thehtml,htmlPositions[7]),
    
    thehtml="<hr> <h1> 4. Test against Stored Doodles </h1> <br> <button onclick='testSavedDoodles();' class='normbutton' >This became pointless as I began to modify different things such as the filters and how the images were preprocessed</button> <br>",
    AB.msg(thehtml,htmlPositions[12]);
    
    const greenspan="<span style='font-weight:bold; font-size:x-large; color:darkgreen'> ";
    
    function setup()
    
    {
        startTime=Math.round((new Date).getTime()/1e3),createCanvas(canvaswidth,canvasheight),
        (
            doodle=createGraphics(ZOOMPIXELS,ZOOMPIXELS)).pixelDensity(1),
            
            AB.loadingScreen(),
            
            $.getScript("/uploads/codingtrain/matrix.js",function()
            
            {
                $.getScript("/uploads/codingtrain/nn.js",function()
                
                {
                    $.getScript("/uploads/codingtrain/mnist.js",function()
                    
                    {
                        console.log("All JS loaded"),
                        nn=new NeuralNetwork(noinput,nohidden,nooutput);
                        new ActivationFunction(e=>e>0?e:0,e=>e>0?1:0);
                        nn.setLearningRate(learningrate),
                        loadData()
                        
                    })
                    
                })
                
            })}
            
            function loadData()
            {
                loadMNIST(function(e)
                {
                    mnist=e,
                    console.log("All data loaded into mnist object:"),
                    console.log(mnist),AB.removeLoading()
                    
                })
                
            }
            function getImage(e)
            {
                let t=createImage(PIXELS,PIXELS);
                t.loadPixels();
                
                for(let o=0;o<PIXELSSQUARED;o++)
                {
                    let n=e[o],
                    r=4*o;
                    t.pixels[r+0]=n,
                    t.pixels[r+1]=n,
                    t.pixels[r+2]=n,
                    t.pixels[r+3]=n
                    
                }
                return t.updatePixels(),
                t
                
            }
            function getInputs(e)
            {
                let t=[];
                for(let o=0;o<PIXELSSQUARED;o++)
                {let n=e[o];
                t[o]=n/255
                    
                }
                return t
                
                
            }
            function trainit(e) 
            {
                let t=mnist.train_images[train_index],
                o=mnist.train_labels[train_index];
                
                if(e)
                {
                    var n=getImage(t);
                    image(n,0,ZOOMPIXELS+50,
                    ZOOMPIXELS,ZOOMPIXELS),
                    image(n,ZOOMPIXELS+50,
                    ZOOMPIXELS+50,
                    PIXELS,PIXELS
                    )
                    
                }
                
                //////////
                let r=getInputs(t),
                i=[0,0,0,0,0,0,0,0,0,0];i[o]=1,
                train_inputs=r,nn.train(arrayManipulations(r,!1,!0),i),
                thehtml=" trainrun: "+trainrun+"<br> no: "+train_index+"<br> Time Passed: "+runTime()+" seconds",
                AB.msg(thehtml,htmlPositions[4]),++train_index==NOTRAIN&&(train_index=0,
                
                console.log("finished trainrun: "+trainrun),trainrun++)
                
            }
            function testit()
            {
                let e=mnist.test_images[test_index],
                t=mnist.test_labels[test_index],
                o=getInputs(e);test_inputs=o;
                
                let n=findMax(nn.predict(arrayManipulations(o,!1,!0)));
                total_tests++,n==t&&total_correct++;
                let r=total_correct/total_tests*100;
                currentPercent=r,calculateLandmarkTimes(r),
                
                thehtml=" testrun: "+testrun+"<br> no: "+total_tests+" <br>  correct: "+total_correct+"<br>  score: "+greenspan+r.toFixed(2)+"</span> <br>  Time to 10%: "+timeToArray[0]+" <br>  Time to 20%: "+timeToArray[1]+" <br>  Time to 30%: "+timeToArray[2]+" <br>  Time to 40%: "+timeToArray[3]+" <br>  Time to 50%: "+timeToArray[4]+" <br>  Time to 60%: "+timeToArray[5]+" <br>  Time to 70%: "+timeToArray[6]+" <br>  Time to 80%: "+timeToArray[7]+" <br>  Time to 85%: "+timeToArray[8]+" <br>  Time to 90%: "+timeToArray[9]+" <br>  Time to 100%: "+timeToArray[10],
                
                AB.msg(thehtml,htmlPositions[6]),
                ++test_index==NOTEST&&
                (
                    console.log("finished testrun: "+testrun+" score: "+r.toFixed(2)),
                    testrun++,test_index=0,total_tests=0,total_correct=0)
                
            }
            function find12(e)
            {
                let t=0,
                o=0,
                n=0,
                r=0;
                
                for(let i=0;i<e.length;i++)
                e[i]>n?(t=i,n=e[i])
                :e[i]>r&&(o=i,r=e[i]);
                
                return[t,o]
                
            }
            function findMax(e)
            {
                let t=0,
                o=0;
                for(let n=0;
                n<e.length;n++)e[n]>o&&(t=n,o=e[n]);
                
                return t
                
            }
            function draw()
            
            {
                if(reportDoodleAccuracy(),
                void 0!==mnist)
                {
                    if(background("black"),do_training)
                    {
                        for(let e=0;
                        e<TRAINPERSTEP;e++)trainit(0==e);
                        for(let e=0;
                        e<TESTPERSTEP;e++)testit()
                        
                    }
                    if(demo_exists&&(drawDemo(),
                    guessDemo()),
                    currentPercent>demoThreshold&&makeDemoBlind(),
                    doodle_exists&&(drawDoodle(),guessDoodle()),mouseIsPressed)
                    {
                        var e=ZOOMPIXELS+20;
                        mouseX<e&&mouseY<e&&pmouseX<e&&pmouseY<e&&(mousedrag=!0,
                        doodle_exists=!0,
                        
                        doodle.stroke("white"),
                        doodle.strokeWeight(DOODLE_THICK),
                        doodle.line(mouseX,mouseY,pmouseX,pmouseY))
                        
                    }
                    else mousedrag&&(rawDoodle=getRawDoodleInputs(doodle),
                    mousedrag=!1,
                    applyDoodleFilters())}
                
            }
            function makeDemo()
            {
                demo_exists=!0;
                var e=AB.randomIntAtoB(0,NOTEST-1);
                demo=mnist.test_images[e],
                demoLabel=mnist.test_labels[e],
                thehtml="Test image no: "+e+"<br>Classification: "+label+"<br>",
                AB.msg(thehtml,htmlPositions[8])
                
            }
            function drawDemo()
            {
                var e=getImage(demo);
                image(e,0,canvasheight-ZOOMPIXELS,ZOOMPIXELS,ZOOMPIXELS),
                image(e,ZOOMPIXELS+50,canvasheight-ZOOMPIXELS,PIXELS,PIXELS)
                
            }
            function guessDemo()
            {
                let e=getInputs(demo);demo_inputs=e;
                let t=findMax(nn.predict(e));
                
                thehtml=" We classify it as: "+greenspan+t+"</span>",
                AB.msg(thehtml,htmlPositions[9])
                
            }
            function drawDoodle()
            {
                let e=doodle.get();e.loadPixels(),
                drawFromImage(e)
                
            }
            function drawFromImage(e)
            {
                image(e,0,0,ZOOMPIXELS,ZOOMPIXELS),
                image(e,ZOOMPIXELS+50,0,PIXELS,PIXELS)
                
            }
            function guessDoodle(){getDoodleInputs(doodle);
            let e=find12(nn.predict(arrayManipulations(doodle_inputs,!0,!1)));
            doodleGuess=e[0],
            thehtml=" We classify it as: "+greenspan+e[0]+"</span> <br> No.2 guess is: "+greenspan+e[1]+"</span>",
            
            AB.msg(thehtml,htmlPositions[2])
                
            }
            function wipeDoodle()
            {
                doodle_exists=!1,doodle.background("black")
                
            }
            function showInputs(e)
            {
                var t="";
                for(let o=0;
                o<e.length;o++){o%PIXELS==0&&(t+="\n"),t=t+" "+e[o].toFixed(2)
                    
                    
                }
                console.log(t)
                
            }
            let startTime=0,timeToArray=[0,0,0,0,0,0,0,0,0,0,0],
            doodleAccuracy=0,
            numberOfDoodles=0,
            correctDoodles=0,
            incorrectDoodles=0,
            currentPercent=0,
            doodleGuess=null,
            demoLabel=null,numberOfDemos=0,
            numberOfCorrectDemoGuesses=0,
            demoAccuracy=0,
            demoThreshold=80,
            rawDoodle=[],localStoragePrefix="doodle_";
            
            function runTime()
            {
                return Math.round((new Date).getTime()/1e3)-startTime
                
            }
            function calculateLandmarkTimes(e)
            {
                updateTimeArray(0,10,e),
                updateTimeArray(1,20,e)
                ,updateTimeArray(2,30,e),
                updateTimeArray(3,40,e),
                updateTimeArray(4,50,e),
                updateTimeArray(5,60,e),
                updateTimeArray(6,70,e),
                updateTimeArray(7,80,e),
                updateTimeArray(8,85,e),
                updateTimeArray(9,90,e),
                updateTimeArray(10,100,e)
                
            }
            function updateTimeArray(e,t,o)
            {
                0==timeToArray[e]&&o>t&&(timeToArray[e]=runTime())
                
            }
            function validateDoodle(e){numberOfDoodles+=1,e==doodleGuess?correctDoodles+=1:incorrectDoodles+=1,
            getDoodleInputs(doodle),wipeDoodle()
                
            }
            function calculateDoodleAccuracy(){doodleAccuracy=correctDoodles/numberOfDoodles*100
                
            }
            function calculateDemoAccuracy(e){numberOfDemos>0&&(demoLabel==e&&(numberOfCorrectDemoGuesses+=1),
            demoAccuracy=numberOfCorrectDemoGuesses/numberOfDemos*100);
            var t="<br> Score :  "+demoAccuracy+"<br>";AB.msg(t,htmlPositions[11])
                
            }
            function reportDoodleAccuracy()
            {
                if(numberOfDoodles>0){calculateDoodleAccuracy();
                var e="<br> Score :  "+doodleAccuracy+"<br>";AB.msg(e,htmlPositions[10])}
                
            }
            function validateDoodleHtml()
            {return" Validate: <br> <button onclick='validateDoodle(0);' class='normbutton' >0</button>  <br> <button onclick='validateDoodle(1);' class='normbutton' >1</button>  <br> <button onclick='validateDoodle(2);' class='normbutton' >2</button>  <br> <button onclick='validateDoodle(3);' class='normbutton' >3</button>  <br> <button onclick='validateDoodle(4);' class='normbutton' >4</button>  <br> <button onclick='validateDoodle(5);' class='normbutton' >5</button>  <br> <button onclick='validateDoodle(6);' class='normbutton' >6</button>  <br> <button onclick='validateDoodle(7);' class='normbutton' >7</button>  <br> <button onclick='validateDoodle(8);' class='normbutton' >8</button>  <br> <button onclick='validateDoodle(9);' class='normbutton' >9</button>  <br> "
                
            }
            function makeDemoBlind()
            {
                numberOfDemos+=1;
                var e=AB.randomIntAtoB(0,NOTEST-1);
                demo=mnist.test_images[e],demoLabel=mnist.test_labels[e];
                let t=getInputs(demo);
                demo_inputs=t,
                calculateDemoAccuracy(findMax(nn.predict(arrayManipulations(t,!1,!0))))
                
            }
            function getDoodleInputs(e)
            {
                let t=e.get();t.resize(PIXELS,PIXELS),t.loadPixels();
                let o=[];
                for(let e=0;
                e<PIXELSSQUARED;e++)o[e]=t.pixels[4*e]/255;
                return doodle_inputs=o,o
                
            }
            function testSavedDoodles()
            {
                var e=0,t=0;AB.restoreData(
                    function(o)
                    {
                        for(var n=0;
                        n<o.length;n++)
                        {
                            var r=o[n];e+=1;
                            var i=getDoodleAsImage(r.doodle);applyFilters(i),i.resize(PIXELS,PIXELS),i.loadPixels();
                            for(var a=[],l=0;
                            l<i.pixels.length;l+=4)a.push(i.pixels[l]/255);find12(nn.predict(a))[0]==r.classification&&(t+=1)
                            
                        }
                        var s=" <br> Score : "+(t/e*100).toFixed(2)+" <br> Saved Doodles : "+e;AB.msg(s,htmlPositions[13])})
                
            }
            function getRawDoodleInputs(e)
            {
                let t=e.get();t.loadPixels();
                let o=[];
                for(let e=0;e<ZOOMPIXELS*ZOOMPIXELS;e++)o[e]=t.pixels[4*e];
                return o
                
            }
            function convertRawDoodleToPixelsSquared(e)
            {
                let t=[];
                for(let o=0;
                o<ZOOMPIXELS*ZOOMPIXELS;o++)t[o]=e[4*o];
                return t
                
            }
            function getDoodleAsImage(e)
            {
                let t=createImage(ZOOMPIXELS,ZOOMPIXELS);t.loadPixels();
                for(
                    var o=0;
                    o<e.length;o++)t.pixels[o]=e[o],
                    t.pixels[o+1]=e[o],
                    t.pixels[o+2]=e[o],
                    t.pixels[o+3]=e[o];
                    
                    return t.updatePixels(),
                    t
                
            }
            function addDoodleToHistory(e)
            {
                AB.runloggedin,AB.queryDataExists
                (
                    function(t){t?AB.restoreData(function(t){t.push(e),
                    AB.saveData(t)}):AB.saveData([e])})
                
            }
            function removeRandomPixels(e)
            {
                for(var t=0;t<e.length;t++)t-1>0&&0!=e[t-1]||t+1<e.length&&0!=e[t+1]||t+28<e.length&&0!=e[t+28]||t-28>0&&0!=e[t-28]||(e[t]=0);
                return e}function fillHoles(e){for(var t=0;t<e.length;t++)t-1>0&&0!=e[t-1]||t+1<e.length&&0!=e[t+1]||t+28<e.length&&0!=e[t+28]||t-28>0&&0!=e[t-28]||(e[t]=(e[t-1]+e[t+1]+e[t+28]+e[t-28])/4);
                return e}function thickenLines(e){for(var t=0;t<e.length;t++)e[t]&&(t-1>0&&t+1<e.length&&0==e[t-1]&&0==e[t+1]&&(e[t-1]=e[t+1]=e[t]),t+28<e.length&&t-28>0&&0==e[t+28]&&0==e[t-28]&&(e[t-28]=e[t+28]=e[t]));
                return e}function shiftToTopLeft(e)
                
                {
                    for(var t=0;t<e.length;t++)if(0!=e[t]){firstValuedIndex=t;
                    
                    break}var o=Math.floor(firstValuedIndex/28);if(o>0){e=e.slice(28*o,e.length);
                    for(t=0;t<28*o;t++)e.push(0)}var n=0,r=999;
                    for(t=0;t<PIXELS;t++)for(var i=0;i<PIXELS;i++)0!=e[t+i*PIXELS]&&t<r&&(n=t+i*PIXELS,r=t);
                    if(n>0&&r<999)for(t=0;t<PIXELS;t++)for(i=0;i<PIXELS;i++)i+r>PIXELS-1?(e[t*PIXELS+i-r]=e[t*PIXELS+i],e[t*PIXELS+i]=0):i-r>=0&&(e[t*PIXELS+i-r]=e[t*PIXELS+i]);
                    return e}function addNoise(e){for(var t=0;t<e.length;t++)0==e[t]&&(e[t]=AB.randomPick(0,Math.round(255*Math.random())));
                    return e}function rotateImage(e,t){for(var o=[],n=999,r=0;r<PIXELS;r++)for(var i=0;i<PIXELS;i++)ir=r*cos(t)-i*sin(t),jr=r*sin(t)+i*cos(t),ir=Math.round(ir)+100,jr=Math.round(jr)+100,ir<n&&(n=ir),o[ir]?o[ir][jr]=e[r*PIXELS+i]+(o[ir][jr]?o[ir][jr]:0):(o[ir]=[],o[ir][jr]=e[r*PIXELS+i]+0);
                    
                    var a=o.length-n;
                    for(r=0;r<a;r++)o[r]=o[n+r];o=o.slice(0,a);
                    var l=0,s=999;for(r=0;r<o.length;r++)o[r].length>l&&(l=o[r].length);
                    for(r=0;r<o.length;r++)for(i=l-1;i>0;i--)
                    void 0!==o[r][i]&&i<s&&(s=i);
                    for(r=0;r<o.length;r++)
                    for(i=s;i<l;i++)o[r][i]||(o[r][i]=0);
                    
                    var d=l-s,u=d-PIXELS;
                    for(r=0;r<o.length;r++)
                    {
                        for(i=0;i<d;i++)o[r][i]=o[r][i+s];
                        if(o[r]=o[r].slice(Math.floor(u/2),l-Math.floor(u/2)),o[r].length>PIXELS)o[r]=o[r].slice(0,PIXELS);
                        else if(o[r].length<PIXELS)
                        for(i=PIXELS-1;i>0;i++)o[r][i]||(o[r][i]=0)}
                        var m=o.length-PIXELS;
                        
                        if((o=o.slice(m/2,o.length-m/2)).length<PIXELS)
                        for(r=28;r>0&&!o[r];i++){o[r]=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]}o=o.flat();
                        
                        for(r=0;r<PIXELS;r++)
                        for(i=3;i<PIXELS-3;i++)0!=o[r*PIXELS+i]&&((0==o[r*PIXELS+i+1]&&0==o[r*PIXELS+i+2]&&0!=o[r*PIXELS+i+3]||0==o[r*PIXELS+i+1]&&0!=o[r*PIXELS+i+2])&&(o[r*PIXELS+i+1]=o[r*PIXELS+i+2]=(o[r*PIXELS+i+3]+o[r*PIXELS+i])/2),(0==o[r*PIXELS+i-1]&&0==o[r*PIXELS+i-2]&&0!=o[r*PIXELS+i-3]||0==o[r*PIXELS+i-1]&&0!=o[r*PIXELS+i-2])&&(o[r*PIXELS+i+1]=o[r*PIXELS+i+2]=(o[r*PIXELS+i+3]+o[r*PIXELS+i])/2));
                        
                        return o}function applyDoodleFilters(){applyFilters(doodle)
                            
                        }
                        function applyFilters(e){doodle.filter(BLUR,3)
                            
                        }
                        function arrayManipulations(e,t,o)
                        {
                            return e=shiftToTopLeft(e=removeRandomPixels(e=Array.from(e)))}