├── .gitattributes ├── LICENSE.txt ├── README.md ├── chapter1 └── activation_functions.html ├── chapter3 └── tfjs_xor_batching.js ├── chapter5 ├── 0_webglFirstRendering │ ├── index.html │ └── script.js ├── 1_mandelBrot │ ├── index.html │ └── script.js ├── 2_renderToTexture │ ├── index.html │ ├── scriptCPU.js │ └── scriptGPU.js ├── 3_RTTfloat │ ├── IDL_Rainbow.png │ ├── index.html │ ├── initialState.png │ └── script.js ├── 4_WGLMatrix │ ├── WGLMatrix.js │ ├── index.html │ └── script.js ├── 5_MNIST │ ├── WGLMatrix.js │ ├── data │ │ ├── mnist_batch_0.png │ │ ├── mnist_batch_1.png │ │ ├── mnist_batch_10.png │ │ ├── mnist_batch_11.png │ │ ├── mnist_batch_12.png │ │ ├── mnist_batch_13.png │ │ ├── mnist_batch_14.png │ │ ├── mnist_batch_15.png │ │ ├── mnist_batch_16.png │ │ ├── mnist_batch_17.png │ │ ├── mnist_batch_18.png │ │ ├── mnist_batch_19.png │ │ ├── mnist_batch_2.png │ │ ├── mnist_batch_20.png │ │ ├── mnist_batch_3.png │ │ ├── mnist_batch_4.png │ │ ├── mnist_batch_5.png │ │ ├── mnist_batch_6.png │ │ ├── mnist_batch_7.png │ │ ├── mnist_batch_8.png │ │ ├── mnist_batch_9.png │ │ └── mnist_labels.js │ ├── index.html │ ├── mnist_loader.js │ ├── network.js │ └── script.js ├── 6_MNISTimproved │ ├── WGLMatrix.js │ ├── data │ │ ├── mnist_batch_0.png │ │ ├── mnist_batch_1.png │ │ ├── mnist_batch_10.png │ │ ├── mnist_batch_11.png │ │ ├── mnist_batch_12.png │ │ ├── mnist_batch_13.png │ │ ├── mnist_batch_14.png │ │ ├── mnist_batch_15.png │ │ ├── mnist_batch_16.png │ │ ├── mnist_batch_17.png │ │ ├── mnist_batch_18.png │ │ ├── mnist_batch_19.png │ │ ├── mnist_batch_2.png │ │ ├── mnist_batch_20.png │ │ ├── mnist_batch_3.png │ │ ├── mnist_batch_4.png │ │ ├── mnist_batch_5.png │ │ ├── mnist_batch_6.png │ │ ├── mnist_batch_7.png │ │ ├── mnist_batch_8.png │ │ ├── mnist_batch_9.png │ │ └── mnist_labels.js │ ├── index.html │ ├── mnist_loader.js │ ├── network.js │ └── script.js └── README.md ├── chapter6 ├── 1_images │ ├── loading.html │ ├── segmentation.html │ └── shapes.html ├── 2_video │ ├── capturing.html │ ├── streaming.html │ └── video_classification_dljs.html ├── 3_audio │ ├── decoding.html │ └── recording.html ├── 4_frameworks │ ├── kerasjs.html │ ├── tfjs.html │ └── webdnn.html ├── README.md └── data │ ├── Large-dog-barks - LICENSE.txt │ ├── Large-dog-barks.mp3 │ ├── bike.jpg │ ├── bike_object.png │ ├── cat.jpeg │ └── rand.bin ├── chapter7 ├── .gitignore ├── 1_binary_data │ ├── data.py │ ├── data │ │ ├── Large-dog-barks - LICENSE.txt │ │ ├── Large-dog-barks.mp3 │ │ ├── bike.jpg │ │ ├── bike_object.png │ │ ├── cat.jpeg │ │ └── rand.bin │ ├── image_data.html │ ├── lib │ │ └── protobuf.js │ ├── proto │ │ ├── caffe.json │ │ └── tf.json │ ├── protobuf_caffe.html │ └── protobuf_tensorflow.html ├── 2_drawing_charts │ ├── chart_types_1.html │ ├── chart_types_2.html │ ├── lib │ │ └── chart.min.js │ ├── line_chart.html │ ├── update_chart_1.html │ └── update_chart_2.html ├── 3_drawing_sketches │ └── index.html ├── 4_audio_spectogram │ ├── index.html │ ├── lib │ │ ├── chart.min.js │ │ └── dsp.js │ └── worker.js └── 5_face_tracking │ ├── faceFilter.html │ ├── face_detector.html │ ├── lib │ ├── face.min.js │ └── tracking.min.js │ └── tracking_js.html └── cover.jpg /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2018 Bleeding Edge Press 2 | 3 | Permission is hereby granted, free of charge, to any person 4 | obtaining a copy of this software and associated documentation 5 | files (the "Software"), to deal in the Software without 6 | restriction, including without limitation the rights to use, 7 | copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the 9 | Software is furnished to do so, subject to the following 10 | conditions: 11 | 12 | The above copyright notice and this permission notice shall be 13 | included in all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 17 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 19 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 20 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 딥러닝 인 더 브라우저 2 | 3 |

4 | 5 |

6 | 7 | **출판사** 제이펍 8 | **원출판사** Bleeding Edge Press 9 | **원서명** Deep Learning In The Browser(원서 ISBN: 9789386052988) 10 | **저자명** 자비에르 보우리, 카이 사사키, 크리스토프 코너, 레이이치로 나카노 11 | **역자명** 이수진 12 | **출판일** 2020년 2월 20일 13 | **페이지** 244쪽 14 | **시리즈** I♥A.I. 23(아이러브 인공지능 23) 15 | **ISBN** 979-11-88621-83-5(93000) 16 | 17 | [### 도서 소개 페이지 바로 가기 ###](https://jpub.tistory.com/1012?category=208491) 18 | 19 | 20 | ## 페이지 소개 21 | 《딥러닝 인 더 브라우저》의 공식 저장소 입니다. 책 내 소스 코드를 확인할 수 있습니다. 22 | 23 | ## 책 소개 24 | 이 책은 딥러닝과 웹 개발의 교차점에 있습니다. 두 기술 모두 성숙 단계에 접어들었고, 이들이 만난다면 누구도 상상하지 못한 환상적인 애플리케이션을 만들 수 있습니다. 25 | 26 | 이 책은 기본적인 웹 프로그래밍과 더불어 WebGL 등을 사용한 자바스크립트 딥러닝 프레임워크 사용법을 설명합니다. 브라우저와 딥러닝의 만남은 아직 걸음마 수준에 불과하지만, 하루가 다르게 눈부시게 발전하고 있습니다. 지금이야말로 시작하기 가장 좋을 때입니다. 이 책과 함께 놀라운 딥러닝의 세계를 느껴보기를 바랍니다. 자, 새로운 여행을 떠나 볼까요? 27 | 28 | ### 목차 29 | * [Chapter 1: 딥러닝 소개 - 활성화 함수 그래프](/chapter1) 30 | * [Chapter 3: 자바스크립트 딥러닝 프레임워크](/chapter3) 31 | * [Chapter 5: WebGL을 이용한 GPU 가속화](/chapter5) 32 | * [Chapter 6: 웹 브라우저에서의 데이터 추출](/chapter6) 33 | * [Chapter 7: 고급 데이터 조작을 위한 레시피](/chapter7) 34 | * [Chapter 8: TensorFlow.js 애플리케이션 개발](/chapter8) 35 | 36 | ### 데모 37 | * [가위바위보 게임](https://reiinakano.com/tfjs-rock-paper-scissors/) 38 | * [텍스트 생성 모델](https://reiinakano.com/tfjs-lstm-text-generation/) 39 | 40 | ### 설치 방법 41 | 42 | git 명령어로 저장소를 다운받은 후 서브모듈을 업데이트 합니다. 43 | 44 | ```sh 45 | $ git clone git@github.com:backstopmedia/deep-learning-browser.git 46 | $ cd deep-learning-browser 47 | $ git submodule update --init --recursive 48 | ``` 49 | 50 | 웹 서버로 각 챕터의 디렉터리를 실행할 수 있습니다. http-server를 전역으로 설치한 다음 해당 챕터를 실행합니다. 51 | 52 | ```sh 53 | $ npm install http-server -g 54 | $ http-server chapter6 --cors -p 8081 55 | ``` 56 | 57 | [localhost:8081](http://localhost:8081)을 열어 해당 하위 디렉터리를 이동해 확인할 수 있습니다. 58 | 59 | ## 라이센스 60 | 61 | 본 저장소는 원작 의 [공식 깃허브 저장소](https://github.com/backstopmedia/deep-learning-browser)에 따라 MIT 라이센스를 준수합니다. [/LICENSE.txt](/LICENSE.txt) 에서 상세한 내용을 확인할 수 있습니다. 단, `/lib` 와 `/data`는 디렉터리는 예외입니다. -------------------------------------------------------------------------------- /chapter1/activation_functions.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |
5 | 6 | 11 | 12 | -------------------------------------------------------------------------------- /chapter3/tfjs_xor_batching.js: -------------------------------------------------------------------------------- 1 | const hiddenNumNeurons = 20; 2 | const hidden2NumNeurons = 5; 3 | 4 | const learningRate = 0.01; 5 | const num_iterations = 100; 6 | const batch_size = 20; 7 | 8 | const weights = tf.variable(tf.randomNormal([2, hiddenNumNeurons])); 9 | const biases = tf.variable(tf.zeros([hiddenNumNeurons])); 10 | const weights2 = tf.variable(tf.randomNormal([hiddenNumNeurons, hidden2NumNeurons])); 11 | const biases2 = tf.variable(tf.zeros([hidden2NumNeurons])); 12 | const outWeights = tf.variable(tf.randomNormal([hidden2NumNeurons, 1])); 13 | const outBias = tf.variable(tf.zeros([1])); 14 | 15 | const optimizer = tf.train.adam(learningRate); 16 | 17 | const epsilon = tf.scalar(1e-7); 18 | const one = tf.scalar(1); 19 | 20 | /* 21 | * Given an input, have our model output a prediction 22 | */ 23 | function predict(input) { 24 | return tf.tidy(() => { 25 | 26 | const hidden = input.matMul(weights).add(biases).relu(); 27 | const hidden2 = hidden.matMul(weights2).add(biases2).relu(); 28 | const out = hidden2.matMul(outWeights).add(outBias).sigmoid().as1D(); 29 | 30 | return out; 31 | }); 32 | } 33 | 34 | /* 35 | * Calculate the loss of our model's prediction vs the actual label 36 | */ 37 | function loss(prediction, actual) { 38 | // Having a good error metric is key for training a machine learning model 39 | return tf.tidy(() => { 40 | return tf.add( 41 | actual.mul(prediction.add(epsilon).log()), 42 | one.sub(actual).mul(one.sub(prediction).add(epsilon).log())) 43 | .mean() 44 | .neg().asScalar(); 45 | }); 46 | } 47 | 48 | /* 49 | * This function trains our model asynchronously 50 | */ 51 | async function train(numIterations, done) { 52 | 53 | for (let iter = 0; iter < numIterations; iter++) { 54 | 55 | let xs, ys, cost; 56 | [xs, ys] = getNRandomSamples(batch_size); 57 | 58 | cost = tf.tidy(() => { 59 | cost = optimizer.minimize(() => { 60 | const pred = predict(tf.tensor2d(xs)); 61 | const pretfoss = loss(pred, tf.tensor1d(ys)); 62 | 63 | return pretfoss; 64 | }, true); 65 | 66 | return cost; 67 | }) 68 | 69 | if (iter % 10 == 0) { 70 | await cost.data().then((data) => console.log(`Iteration: ${iter} Loss: ${data}`)); 71 | } 72 | 73 | await tf.nextFrame(); 74 | } 75 | 76 | done(); 77 | } 78 | 79 | /* 80 | * This function calculates the accuracy of our model 81 | */ 82 | function test(xs, ys) { 83 | tf.tidy(() => { 84 | const predictedYs = xs.map((x) => Math.round(predict(tf.tensor2d(x, [1, 2])).dataSync())); 85 | 86 | var predicted = 0; 87 | for (let i = 0; i < xs.length; i++) { 88 | if (ys[i] == predictedYs[i]) { 89 | predicted++; 90 | } 91 | } 92 | console.log(`Num correctly predicted: ${predicted} out of ${xs.length}`); 93 | console.log(`Accuracy: ${predicted/xs.length}`); 94 | }) 95 | } 96 | 97 | /* 98 | * This function returns a random sample and its corresponding label 99 | */ 100 | function getRandomSample() { 101 | let x; 102 | x = [Math.random()*2-1, Math.random()*2-1]; 103 | let y; 104 | if (x[0] > 0 && x[1] > 0 || x[0] < 0 && x[1] < 0) { 105 | y = 0; 106 | } else { 107 | y = 1; 108 | } 109 | return [x, y]; 110 | } 111 | 112 | /* 113 | * This function returns n random samples 114 | */ 115 | function getNRandomSamples(n) { 116 | let xs = []; 117 | let ys = []; 118 | for (let iter = 0; iter < n; iter++) { 119 | let x, y; 120 | [x, y] = getRandomSample(); 121 | xs.push(x); 122 | ys.push(y); 123 | } 124 | return [xs, ys]; 125 | } 126 | 127 | let testX, testY; 128 | [testX, testY] = getNRandomSamples(100); 129 | 130 | // Test before training 131 | console.log(`Before training: `); 132 | test(testX, testY); 133 | 134 | console.log('============='); 135 | console.log(`Training ${num_iterations} epochs...`); 136 | 137 | // Train, then test right after 138 | train(num_iterations, () => { 139 | console.log('============='); 140 | console.log( 141 | `After training:`) 142 | test(testX, testY); 143 | }); 144 | 145 | -------------------------------------------------------------------------------- /chapter5/0_webglFirstRendering/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | WebGL first rendering 5 | 6 | 7 | 23 | 24 | 25 |
26 |

WebGL first rendering

27 |

28 | We draw 2 triangles to fill the viewport. They are colored by their coordinates value (RED for the horizontal axis, and GREEN for the vertical axis). 29 |

30 | 31 |
32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /chapter5/0_webglFirstRendering/script.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * This software is released under MIT licence : 4 | * 5 | * Copyright (c) 2018 Xavier Bourry ( xavier@jeeliz.com ) 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | function main(){ 27 | 28 | // CREATE WEBGL CONTEXT : 29 | var myCanvas=document.getElementById('myWebGLCanvas'); 30 | var GL; 31 | try { 32 | GL=myCanvas.getContext('webgl', {antialias: false, depth: false}); 33 | } catch(e) { 34 | alert('You are not WebGL compatible :('); 35 | } 36 | 37 | 38 | // CREATE THE VERTEX BUFFER OBJECTS : 39 | //declare vertices and indices of a quad : 40 | var quadVertices = new Float32Array([ 41 | -1, -1, //bottom left corner -> indice 0 42 | -1, 1, //top left corner -> indice 1 43 | 1, 1, //top right corner -> indice 2 44 | 1, -1 //bottom right corner -> indice 3 45 | ]); 46 | var quadIndices = new Uint16Array([ 47 | 0,1,2, //first triangle if made with points of indices 0,1,2 48 | 0,2,3 //second triangle 49 | ]); 50 | 51 | //send vertices to the GPU : 52 | var quadVerticesVBO= GL.createBuffer(); 53 | GL.bindBuffer(GL.ARRAY_BUFFER, quadVerticesVBO); 54 | GL.bufferData(GL.ARRAY_BUFFER, quadVertices, GL.STATIC_DRAW); 55 | 56 | //send indices to the GPU : 57 | var quadIndicesVBO= GL.createBuffer(); 58 | GL.bindBuffer(GL.ELEMENT_ARRAY_BUFFER, quadIndicesVBO); 59 | GL.bufferData(GL.ELEMENT_ARRAY_BUFFER, quadIndices, GL.STATIC_DRAW); 60 | 61 | 62 | //CREATE THE SHADER PROGRAM : 63 | //declare shader sources as string 64 | var shaderVertexSource="attribute vec2 position;\n" 65 | +"void main(void){\n" 66 | +"gl_Position=vec4(position, 0., 1.);\n" 67 | +"}"; 68 | var shaderFragmentSource="precision highp float;\n" 69 | +"uniform vec2 resolution;\n" 70 | +"void main(void){\n" 71 | +"vec2 pixelPosition=gl_FragCoord.xy/resolution;\n" 72 | +"gl_FragColor=vec4(pixelPosition, 0.,1.);\n" 73 | +"}"; 74 | 75 | //helper function to compile a shader 76 | function compile_shader(source, type, typeString) { 77 | var shader = GL.createShader(type); 78 | GL.shaderSource(shader, source); 79 | GL.compileShader(shader); 80 | if (!GL.getShaderParameter(shader, GL.COMPILE_STATUS)) { 81 | alert("ERROR IN "+typeString+ " SHADER : " + GL.getShaderInfoLog(shader)); 82 | return false; 83 | } 84 | return shader; 85 | }; 86 | //compile both shader separately 87 | var shaderVertex=compile_shader(shaderVertexSource, GL.VERTEX_SHADER, "VERTEX"); 88 | var shaderFragment=compile_shader(shaderFragmentSource, GL.FRAGMENT_SHADER, "FRAGMENT"); 89 | 90 | var shaderProgram=GL.createProgram(); 91 | GL.attachShader(shaderProgram, shaderVertex); 92 | GL.attachShader(shaderProgram, shaderFragment); 93 | 94 | //start the linking stage : 95 | GL.linkProgram(shaderProgram); 96 | 97 | //link attributes : 98 | var _positionAttributePointer = GL.getAttribLocation(shaderProgram, "position"); 99 | GL.enableVertexAttribArray(_positionAttributePointer); 100 | 101 | //link uniforms : 102 | var _resolutionUniform = GL.getUniformLocation(shaderProgram, "resolution"); 103 | 104 | 105 | //RENDERING TIME ! 106 | //bind VBOs 107 | GL.bindBuffer(GL.ARRAY_BUFFER, quadVerticesVBO); 108 | GL.vertexAttribPointer(_positionAttributePointer, 2, GL.FLOAT, false, 8,0); 109 | GL.bindBuffer(GL.ELEMENT_ARRAY_BUFFER, quadIndicesVBO); 110 | 111 | //rendering : 112 | GL.useProgram(shaderProgram); 113 | //update GLSL "resolution" value in the fragment shader : 114 | GL.viewport(0,0,myCanvas.width, myCanvas.height); 115 | //update GLSL "resolution" value in the fragment shader : 116 | GL.uniform2f(_resolutionUniform, myCanvas.width, myCanvas.height); 117 | //trigger the rendering : 118 | GL.drawElements(GL.TRIANGLES, 6, GL.UNSIGNED_SHORT, 0); 119 | GL.flush(); 120 | 121 | } //end main() 122 | -------------------------------------------------------------------------------- /chapter5/1_mandelBrot/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Mandelbrot fractal 5 | 6 | 7 | 8 | 9 | 25 | 26 | 27 |
28 |

Mandelbrot fractal

29 |

30 | By changing a few lines from the previous example, we draw this beautiful Mandelbrot fractal. All pixels are computed in parallel, which is particularly interesting if their computation is not trivial like in this example. It illustrates the power of GPU acceleration. 31 |

32 | 33 | 34 | Fast and easy high resolution fractals with a pixel shader
35 | About the Mandelbrot fractal
36 | View on shadertoy.com 37 |
38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /chapter5/1_mandelBrot/script.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * This software is released under MIT licence : 4 | * 5 | * Copyright (c) 2018 Xavier Bourry ( xavier@jeeliz.com ) 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | function main(){ 27 | 28 | // CREATE WEBGL CONTEXT : 29 | var myCanvas=document.getElementById('myWebGLCanvas'); 30 | var GL; 31 | try { 32 | GL=myCanvas.getContext('webgl', {antialias: false, depth: false}); 33 | } catch(e) { 34 | alert('You are not WebGL compatible :('); 35 | } 36 | 37 | 38 | // CREATE THE VERTEX BUFFER OBJECTS : 39 | //declare vertices and indices of a quad : 40 | var quadVertices = new Float32Array([ 41 | -1, -1, //bottom left corner -> indice 0 42 | -1, 1, //top left corner -> indice 1 43 | 1, 1, //top right corner -> indice 2 44 | 1, -1 //bottom right corner -> indice 3 45 | ]); 46 | var quadIndices = new Uint16Array([ 47 | 0,1,2, //first triangle if made with points of indices 0,1,2 48 | 0,2,3 //second triangle 49 | ]); 50 | 51 | //send vertices to the GPU : 52 | var quadVerticesVBO= GL.createBuffer(); 53 | GL.bindBuffer(GL.ARRAY_BUFFER, quadVerticesVBO); 54 | GL.bufferData(GL.ARRAY_BUFFER, quadVertices, GL.STATIC_DRAW); 55 | 56 | //send indices to the GPU : 57 | var quadIndicesVBO= GL.createBuffer(); 58 | GL.bindBuffer(GL.ELEMENT_ARRAY_BUFFER, quadIndicesVBO); 59 | GL.bufferData(GL.ELEMENT_ARRAY_BUFFER, quadIndices, GL.STATIC_DRAW); 60 | 61 | 62 | //CREATE THE SHADER PROGRAM : 63 | //declare shader sources as string 64 | var shaderVertexSource="attribute vec2 position;\n" 65 | +"void main(void){\n" 66 | +"gl_Position=vec4(position, 0., 1.);\n" 67 | +"}"; 68 | var shaderFragmentSource="precision highp float;\n" 69 | +"uniform vec2 resolution;\n" 70 | +"void main(void){\n" 71 | +"vec2 pixelPosition=gl_FragCoord.xy/resolution;\n" 72 | +"vec2 pixelPositionCentered=1.3*(pixelPosition*2.-vec2(1.55,1.));\n" 73 | +"vec2 z = pixelPositionCentered, newZ;\n" 74 | +"float j=0.;\n" 75 | +"for(int i=0; i<=200; i+=1) {\n" 76 | +" newZ = pixelPositionCentered+vec2(z.x * z.x - z.y * z.y, 2. * z.y * z.x);\n" 77 | +" if(length(newZ) > 2.) break;\n" 78 | +" z=newZ; j+=1.;\n" 79 | +"}\n" 80 | +"vec3 color=step(j, 199.)*vec3(j/20., j*j/4000., 0.);\n" 81 | +"gl_FragColor = vec4(color,1.);\n" 82 | +"}"; 83 | 84 | //helper function to compile a shader 85 | function compile_shader(source, type, typeString) { 86 | var shader = GL.createShader(type); 87 | GL.shaderSource(shader, source); 88 | GL.compileShader(shader); 89 | if (!GL.getShaderParameter(shader, GL.COMPILE_STATUS)) { 90 | alert("ERROR IN "+typeString+ " SHADER : " + GL.getShaderInfoLog(shader)); 91 | return false; 92 | } 93 | return shader; 94 | }; 95 | //compile both shader separately 96 | var shaderVertex=compile_shader(shaderVertexSource, GL.VERTEX_SHADER, "VERTEX"); 97 | var shaderFragment=compile_shader(shaderFragmentSource, GL.FRAGMENT_SHADER, "FRAGMENT"); 98 | 99 | var shaderProgram=GL.createProgram(); 100 | GL.attachShader(shaderProgram, shaderVertex); 101 | GL.attachShader(shaderProgram, shaderFragment); 102 | 103 | //start the linking stage : 104 | GL.linkProgram(shaderProgram); 105 | 106 | //link attributes : 107 | var _positionAttributePointer = GL.getAttribLocation(shaderProgram, "position"); 108 | GL.enableVertexAttribArray(_positionAttributePointer); 109 | 110 | //link uniforms : 111 | var _resolutionUniform = GL.getUniformLocation(shaderProgram, "resolution"); 112 | 113 | 114 | //RENDERING TIME ! 115 | //bind VBOs 116 | GL.bindBuffer(GL.ARRAY_BUFFER, quadVerticesVBO); 117 | GL.vertexAttribPointer(_positionAttributePointer, 2, GL.FLOAT, false, 8,0); 118 | GL.bindBuffer(GL.ELEMENT_ARRAY_BUFFER, quadIndicesVBO); 119 | 120 | //rendering : 121 | GL.useProgram(shaderProgram); 122 | //update GLSL "resolution" value in the fragment shader : 123 | GL.viewport(0,0,myCanvas.width, myCanvas.height); 124 | //update GLSL "resolution" value in the fragment shader : 125 | GL.uniform2f(_resolutionUniform, myCanvas.width, myCanvas.height); 126 | //trigger the rendering : 127 | GL.drawElements(GL.TRIANGLES, 6, GL.UNSIGNED_SHORT, 0); 128 | GL.flush(); 129 | 130 | } //end main() 131 | -------------------------------------------------------------------------------- /chapter5/2_renderToTexture/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Render to Texture : Conway game of life 5 | 6 | 7 | 8 | 9 | 10 | 26 | 27 | 28 |
29 |

Conway game of life

30 |

31 | We simulate a Conway game of life for 2000 iteration. Regular shapes emerge from random values. We have to use render to texture to update the texture storing cell states at each iteration. This is a discrete simulation (each cell is either alive or dead), so we do not need floating point textures. 32 |

33 |
34 |
35 | About the Conway game of life
36 |

37 | Open the web console to view the benchmarks. 38 |

39 |
40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /chapter5/2_renderToTexture/scriptCPU.js: -------------------------------------------------------------------------------- 1 | function main_CPU(){ 2 | //do the conway game of life on GPU. use SETTINGS of scriptGPU 3 | 4 | var data0=new Uint8Array(SETTINGS.simuSize*SETTINGS.simuSize); 5 | var data1=new Uint8Array(SETTINGS.simuSize*SETTINGS.simuSize); 6 | 7 | //randomly init cells live or dead 8 | for (var i=0; i0.5)?1:0; 10 | data1[i]=data0[i]; 11 | } 12 | 13 | var datas=[data0, data1]; 14 | 15 | function getVal(dataArr, x, y){ //reproduce the GL.CLAMP_TO_EDGE behaviour 16 | var xClamped=Math.min(Math.max(x, 0), SETTINGS.simuSize-1); 17 | var yClamped=Math.min(Math.max(y, 0), SETTINGS.simuSize-1); 18 | return dataArr[yClamped*SETTINGS.simuSize+xClamped]; 19 | } 20 | 21 | var x, y, dataInput, dataOutput,nNeighbors; 22 | 23 | var tStart=performance.now(); 24 | //simulation loop : 25 | for (i=0; i indice 0 48 | -1, 1, //top left corner -> indice 1 49 | 1, 1, //top right corner -> indice 2 50 | 1, -1 //bottom right corner -> indice 3 51 | ]); 52 | var quadIndices = new Uint16Array([ 53 | 0,1,2, //first triangle if made with points of indices 0,1,2 54 | 0,2,3 //second triangle 55 | ]); 56 | 57 | //send vertices to the GPU : 58 | var quadVerticesVBO= GL.createBuffer(); 59 | GL.bindBuffer(GL.ARRAY_BUFFER, quadVerticesVBO); 60 | GL.bufferData(GL.ARRAY_BUFFER, quadVertices, GL.STATIC_DRAW); 61 | 62 | //send indices to the GPU : 63 | var quadIndicesVBO= GL.createBuffer(); 64 | GL.bindBuffer(GL.ELEMENT_ARRAY_BUFFER, quadIndicesVBO); 65 | GL.bufferData(GL.ELEMENT_ARRAY_BUFFER, quadIndices, GL.STATIC_DRAW); 66 | 67 | 68 | //CREATE THE RENDERING SHADER PROGRAM : 69 | //declare shader sources as string 70 | var shaderVertexSource="attribute vec2 position;\n" 71 | +"void main(void){\n" 72 | +"gl_Position=vec4(position, 0., 1.);\n" 73 | +"}"; 74 | var shaderFragmentSourceRendering="precision highp float;\n" 75 | +"uniform vec2 resolution;\n" 76 | +"uniform sampler2D samplerTexture;\n" 77 | +"void main(void){\n" 78 | +"vec2 uv=gl_FragCoord.xy/resolution;\n" //texture UV coordinates 79 | +"vec4 color=texture2D(samplerTexture, uv);\n" //fetch texture color 80 | +"gl_FragColor=vec4(color.r*vec3(1.,1.,0.) ,1.);\n" 81 | +"}"; 82 | 83 | //helper function to compile a shader 84 | function compile_shader(source, type, typeString) { 85 | var shader = GL.createShader(type); 86 | GL.shaderSource(shader, source); 87 | GL.compileShader(shader); 88 | if (!GL.getShaderParameter(shader, GL.COMPILE_STATUS)) { 89 | alert("ERROR IN "+typeString+ " SHADER : " + GL.getShaderInfoLog(shader)); 90 | return false; 91 | } 92 | return shader; 93 | }; 94 | 95 | //helper function to build the shader program : 96 | function build_shaderProgram(shaderVertexSource, shaderFragmentSource, name) { 97 | //compile both shader separately 98 | var shaderVertex=compile_shader(shaderVertexSource, GL.VERTEX_SHADER, "VERTEX "+name); 99 | var shaderFragment=compile_shader(shaderFragmentSource, GL.FRAGMENT_SHADER, "FRAGMENT "+name); 100 | 101 | var shaderProgram=GL.createProgram(); 102 | GL.attachShader(shaderProgram, shaderVertex); 103 | GL.attachShader(shaderProgram, shaderFragment); 104 | 105 | //start the linking stage : 106 | GL.linkProgram(shaderProgram); 107 | return shaderProgram; 108 | } 109 | 110 | //build rendering shader program : 111 | var shaderProgramRendering = build_shaderProgram(shaderVertexSource, shaderFragmentSourceRendering, 'RENDERING'); 112 | //link attributes : 113 | var _positionAttributePointer = GL.getAttribLocation(shaderProgramRendering, 'position'); 114 | GL.enableVertexAttribArray(_positionAttributePointer); 115 | //link uniforms : 116 | var _resolutionRenderingUniform = GL.getUniformLocation(shaderProgramRendering, 'resolution'); 117 | var _samplerTextureRenderingUniform = GL.getUniformLocation(shaderProgramRendering, 'samplerTexture'); 118 | 119 | 120 | //BIND VBOs 121 | GL.bindBuffer(GL.ARRAY_BUFFER, quadVerticesVBO); 122 | GL.vertexAttribPointer(_positionAttributePointer, 2, GL.FLOAT, false, 8,0); 123 | GL.bindBuffer(GL.ELEMENT_ARRAY_BUFFER, quadIndicesVBO); 124 | 125 | 126 | //RENDER TO TEXTURE INITIALIZATION : 127 | //initialize and bind the FBO 128 | var rttFbo=GL.createFramebuffer(); 129 | GL.bindFramebuffer(GL.FRAMEBUFFER, rttFbo); 130 | 131 | //instantiate the textures : 132 | //helper function to create a texture 133 | function create_rttTexture(width, height, data){ 134 | var texture=GL.createTexture(); 135 | GL.bindTexture(GL.TEXTURE_2D, texture); 136 | //texture filtering : always pick the nearest pixel from the texture UV coordinates : 137 | GL.texParameteri(GL.TEXTURE_2D, GL.TEXTURE_MAG_FILTER, GL.NEAREST); 138 | GL.texParameteri(GL.TEXTURE_2D, GL.TEXTURE_MIN_FILTER, GL.NEAREST); 139 | 140 | //does not repeat texture along axis 141 | //(otherwise may throw errors if dimensions of the texture are not power of 2) : 142 | GL.texParameteri( GL.TEXTURE_2D, GL.TEXTURE_WRAP_S, GL.CLAMP_TO_EDGE ); 143 | GL.texParameteri( GL.TEXTURE_2D, GL.TEXTURE_WRAP_T, GL.CLAMP_TO_EDGE ); 144 | GL.texImage2D(GL.TEXTURE_2D, 0, GL.RGBA, width, height, 0, GL.RGBA, GL.UNSIGNED_BYTE, data); 145 | return texture; 146 | } 147 | var data0=new Uint8Array(SETTINGS.simuSize*SETTINGS.simuSize*4); 148 | //randomly init cells live or dead 149 | for (var i=0; i0.5)?255:0; 151 | } 152 | //uncomment this code chunk to get the illustration of the book : 153 | //init a square of SETTINGS.simuSize/4 wide at the center of the texture with 1 154 | /* data0=new Uint8Array(SETTINGS.simuSize*SETTINGS.simuSize*4); //reset all values to 0 155 | var sMin=Math.round(SETTINGS.simuSize/2-SETTINGS.simuSize/4); 156 | var sMax=Math.round(SETTINGS.simuSize/2+SETTINGS.simuSize/4); 157 | for (var y=sMin; y=4.0){\n" 195 | +" cellState=0.0;\n" //die 196 | +"};\n" 197 | +"gl_FragColor=vec4(cellState, 0., 0.,1.);\n" 198 | +"}"; 199 | //build rendering shader program : 200 | var shaderProgramComputing = build_shaderProgram(shaderVertexSource, shaderFragmentSourceComputing, 'COMPUTING'); 201 | //the rendering vertex shader is the same so attributes have the same name, number and dimension than the rendering shader program 202 | //so we do not need to link and enable them again 203 | //link uniforms : 204 | var _resolutionComputingUniform = GL.getUniformLocation(shaderProgramComputing, "resolution"); 205 | var _samplerTextureComputingUniform = GL.getUniformLocation(shaderProgramComputing, 'samplerTexture') 206 | 207 | 208 | //COMPUTING TIME ! 209 | GL.useProgram(shaderProgramComputing); 210 | GL.viewport(0,0,SETTINGS.simuSize,SETTINGS.simuSize); 211 | GL.uniform2f(_resolutionComputingUniform, SETTINGS.simuSize, SETTINGS.simuSize); 212 | GL.uniform1i(_samplerTextureComputingUniform, 0); 213 | //next bound texture will be bound on sampler 0 : 214 | GL.activeTexture(GL.TEXTURE0); 215 | 216 | //computing loop 217 | var tStart=performance.now(); 218 | for (var i=0; i 2 | 3 | 4 | Render on floating point texture : heat simulation 5 | 6 | 7 | 8 | 9 | 21 | 22 | 23 |
24 |

Heat equation simulation

25 |

26 | We start from the previous example (the Conway game of life) to implement a continuous simulation. We simulate the thermal diffusion in a steel block using the head equation in 2D. Unlike the Conway game of life, the state is represented by floating point parameters (the heat and the heat gradients). So we need to implement render to floating point texture. 27 |

28 | 29 |

30 | The total area of the simulation is a square of 2.56 meters wide. The initial state is a square area of 1.28 meters wide at 100°C. The steel around is at 0°C. The simulation lasts 3000 seconds. We show the heat using the IDL_Rainbow color map calibrated from 0°C (black) to 100°C (red). This is the color map : 31 | 32 |

33 | 34 |

35 | On the left : initial state, on the right : result of the simulation
36 | 37 | 38 |

39 | 40 | About the heat equation
41 | About the colorMap 42 |
43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /chapter5/3_RTTfloat/initialState.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jpub/DeepLearningBrowser/6884b8fb5a239922153b98fc61117435fd9d45ed/chapter5/3_RTTfloat/initialState.png -------------------------------------------------------------------------------- /chapter5/3_RTTfloat/script.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * This software is released under MIT licence : 4 | * 5 | * Copyright (c) 2018 Xavier Bourry ( xavier@jeeliz.com ) 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | 27 | /* 28 | 2D Thermal simulation of a square of iron heated at 100°C 29 | The square is 2.56 meters large 30 | The total area of the simulation is 2.56 meters 31 | The duration of the simulation is 3000 seconds 32 | */ 33 | 34 | //parameters. Physical parameters are in the computing fragment shader 35 | var SETTINGS={ 36 | simuSize: 256, 37 | nIterations: 3000 //time step is 1 seconds. So the total duration of the simulation is nIterations seconds 38 | }; 39 | 40 | //global variables 41 | var GL, FLOATPIXELTYPE, ISWEBGL2; 42 | 43 | //test if it is possible to do RTT with FLOAT/HALF FLOAT textures : 44 | function test_canRTT(internalFormat, pixelType){ 45 | var testFbo=GL.createFramebuffer(); 46 | GL.bindFramebuffer(GL.FRAMEBUFFER, testFbo); 47 | 48 | var testTexture=GL.createTexture(); 49 | GL.bindTexture(GL.TEXTURE_2D, testTexture); 50 | GL.texImage2D(GL.TEXTURE_2D, 0, internalFormat, 1, 1, 0, GL.RGBA, pixelType, null); 51 | 52 | GL.framebufferTexture2D(GL.FRAMEBUFFER, GL.COLOR_ATTACHMENT0, GL.TEXTURE_2D, testTexture, 0); 53 | var fbStatus=GL.checkFramebufferStatus(GL.FRAMEBUFFER); 54 | 55 | return(fbStatus===GL.FRAMEBUFFER_COMPLETE); 56 | } 57 | 58 | function enable_webGL12extensions(){ 59 | GL.getExtension('EXT_color_buffer_float'); 60 | GL.getExtension('WEBGL_color_buffer_float'); 61 | GL.getExtension('OES_color_buffer_float'); 62 | } 63 | 64 | function get_webgl1extensions(){ 65 | if (GL.getExtension('OES_texture_float') && test_canRTT(GL.RGBA, GL.FLOAT)){ 66 | FLOATPIXELTYPE=GL.FLOAT; 67 | return true; 68 | } 69 | if (GL.getExtension('OES_texture_half_float') && test_canRTT(GL.RGBA, GL.HALF_FLOAT)){ 70 | FLOATPIXELTYPE=GL.HALF_FLOAT; 71 | return true; 72 | } 73 | return false; 74 | } 75 | 76 | //helper function to compile a shader 77 | function compile_shader(source, type, typeString) { 78 | var shader = GL.createShader(type); 79 | GL.shaderSource(shader, source); 80 | GL.compileShader(shader); 81 | if (!GL.getShaderParameter(shader, GL.COMPILE_STATUS)) { 82 | alert("ERROR IN "+typeString+ " SHADER : " + GL.getShaderInfoLog(shader)); 83 | return false; 84 | } 85 | return shader; 86 | }; 87 | 88 | //helper function to build the shader program : 89 | function build_shaderProgram(shaderVertexSource, shaderFragmentSource, name) { 90 | //compile both shader separately 91 | var shaderVertex=compile_shader(shaderVertexSource, GL.VERTEX_SHADER, "VERTEX "+name); 92 | var shaderFragment=compile_shader(shaderFragmentSource, GL.FRAGMENT_SHADER, "FRAGMENT "+name); 93 | 94 | var shaderProgram=GL.createProgram(); 95 | GL.attachShader(shaderProgram, shaderVertex); 96 | GL.attachShader(shaderProgram, shaderFragment); 97 | 98 | //start the linking stage : 99 | GL.linkProgram(shaderProgram); 100 | return shaderProgram; 101 | } 102 | 103 | function create_andBindVBOs(positionAttributePointer){ 104 | // CREATE THE VERTEX BUFFER OBJECTS : 105 | //declare vertices and indices of a quad : 106 | var quadVertices = new Float32Array([ 107 | -1, -1, //bottom left corner -> indice 0 108 | -1, 1, //top left corner -> indice 1 109 | 1, 1, //top right corner -> indice 2 110 | 1, -1 //bottom right corner -> indice 3 111 | ]); 112 | var quadIndices = new Uint16Array([ 113 | 0,1,2, //first triangle if made with points of indices 0,1,2 114 | 0,2,3 //second triangle 115 | ]); 116 | 117 | //send vertices to the GPU : 118 | var quadVerticesVBO= GL.createBuffer(); 119 | GL.bindBuffer(GL.ARRAY_BUFFER, quadVerticesVBO); 120 | GL.bufferData(GL.ARRAY_BUFFER, quadVertices, GL.STATIC_DRAW); 121 | 122 | //send indices to the GPU : 123 | var quadIndicesVBO= GL.createBuffer(); 124 | GL.bindBuffer(GL.ELEMENT_ARRAY_BUFFER, quadIndicesVBO); 125 | GL.bufferData(GL.ELEMENT_ARRAY_BUFFER, quadIndices, GL.STATIC_DRAW); 126 | 127 | //BIND VBOs 128 | GL.bindBuffer(GL.ARRAY_BUFFER, quadVerticesVBO); 129 | GL.vertexAttribPointer(positionAttributePointer, 2, GL.FLOAT, false, 8,0); 130 | GL.bindBuffer(GL.ELEMENT_ARRAY_BUFFER, quadIndicesVBO); 131 | } 132 | 133 | //helper function to create a texture 134 | function create_rttTexture(width, height, data){ 135 | var texture=GL.createTexture(); 136 | GL.bindTexture(GL.TEXTURE_2D, texture); 137 | //texture filtering : always pick the nearest pixel from the texture UV coordinates : 138 | GL.texParameteri(GL.TEXTURE_2D, GL.TEXTURE_MAG_FILTER, GL.NEAREST); 139 | GL.texParameteri(GL.TEXTURE_2D, GL.TEXTURE_MIN_FILTER, GL.NEAREST); 140 | 141 | //does not repeat texture along axis 142 | //(otherwise may throw errors if dimensions of the texture are not power of 2) : 143 | GL.texParameteri( GL.TEXTURE_2D, GL.TEXTURE_WRAP_S, GL.CLAMP_TO_EDGE ); 144 | GL.texParameteri( GL.TEXTURE_2D, GL.TEXTURE_WRAP_T, GL.CLAMP_TO_EDGE ); 145 | 146 | if (FLOATPIXELTYPE===GL.FLOAT){ //32 bit precision 147 | GL.texImage2D(GL.TEXTURE_2D, 0, (ISWEBGL2)?GL.RGBA32F:GL.RGBA, width, height, 0, GL.RGBA, FLOATPIXELTYPE, data); 148 | } else { //16 bits precision 149 | GL.texImage2D(GL.TEXTURE_2D, 0, (ISWEBGL2)?GL.RGBA16F:GL.RGBA, width, height, 0, GL.RGBA, FLOATPIXELTYPE, convert_arrayToUInt16Array(data)); 150 | } 151 | return texture; 152 | } 153 | 154 | //convert a float value to Float16 encoding 155 | //ref : https://esdiscuss.org/topic/float16array 156 | function convert_floatToInt16(val){ 157 | var floatView = new Float32Array(1); 158 | var int32View = new Int32Array(floatView.buffer); 159 | 160 | floatView[0] = val; 161 | var x = int32View[0]; 162 | 163 | var bits = (x >> 16) & 0x8000; /* Get the sign */ 164 | var m = (x >> 12) & 0x07ff; /* Keep one extra bit for rounding */ 165 | var e = (x >> 23) & 0xff; /* Using int is faster here */ 166 | 167 | /* If zero, or denormal, or exponent underflows too much for a denormal 168 | * half, return signed zero. */ 169 | if (e < 103) { 170 | return bits; 171 | } 172 | 173 | /* If NaN, return NaN. If Inf or exponent overflow, return Inf. */ 174 | if (e > 142) { 175 | bits |= 0x7c00; 176 | /* If exponent was 0xff and one mantissa bit was set, it means NaN, 177 | * not Inf, so make sure we set one mantissa bit too. */ 178 | bits |= ((e == 255) ? 0 : 1) && (x & 0x007fffff); 179 | return bits; 180 | } 181 | 182 | /* If exponent underflows but not too much, return a denormal */ 183 | if (e < 113) { 184 | m |= 0x0800; 185 | /* Extra rounding may overflow and set mantissa to 0 and exponent 186 | * to 1, which is OK. */ 187 | bits |= (m >> (114 - e)) + ((m >> (113 - e)) & 1); 188 | return bits; 189 | } 190 | 191 | bits |= ((e - 112) << 10) | (m >> 1); 192 | /* Extra rounding. An overflow will set mantissa to 0 and increment 193 | * the exponent, which is OK. */ 194 | bits += m & 1; 195 | return bits; 196 | }; //end convert_floatToInt16() 197 | 198 | //convert an array with float values or a Float32Array 199 | //to an Uint16array with 16bits encoded float 200 | //(see https://en.wikipedia.org/wiki/Half-precision_floating-point_format for the encoding) 201 | function convert_arrayToUInt16Array(arr){ 202 | var arr16=new Uint16Array(arr.length); 203 | arr.forEach(function(val, ind) { 204 | arr16[ind]=convert_floatToInt16(val); 205 | }); 206 | return arr16; 207 | }; 208 | 209 | //entry point : 210 | function main(){ 211 | 212 | // CREATE WEBGL CONTEXT : 213 | var myCanvas=document.getElementById('myWebGLCanvas'); 214 | var webglOptions={antialias: false, depth: false}; 215 | 216 | try { 217 | ISWEBGL2=true; 218 | GL=myCanvas.getContext('webgl2', webglOptions); 219 | enable_webGL12extensions(); 220 | if (test_canRTT(GL.RGBA32F, GL.FLOAT)){ 221 | FLOATPIXELTYPE=GL.FLOAT; 222 | } else { 223 | FLOATPIXELTYPE=GL.HALF_FLOAT; 224 | } 225 | } catch(e) { //no webgl2. try webgl1 ? 226 | 227 | console.log('WARNING : You are not compatible with WebGL2'); 228 | try { 229 | ISWEBGL2=false; 230 | GL=myCanvas.getContext('webgl', webglOptions); 231 | enable_webGL12extensions(); 232 | if (!get_webgl1extensions()){ 233 | alert('WebGL2 is not here and cannot found right WebGL1 extensions'); 234 | return; 235 | } 236 | } catch(e) { //no webgl at all =( 237 | alert('error : you are not compatible with WebGL at all'); 238 | return; 239 | } 240 | 241 | } 242 | 243 | //disable dithering : 244 | GL.disable(GL.DITHER); 245 | 246 | //CREATE THE RENDERING SHADER PROGRAM : 247 | //declare shader sources as string 248 | var shaderVertexSource="attribute vec2 position;\n" 249 | +"void main(void){\n" 250 | +"gl_Position=vec4(position, 0., 1.);\n" 251 | +"}"; 252 | 253 | //rendering shader juste apply a colorMap to display the heat scalar value 254 | //the colormap function comes from https://github.com/kbinani/glsl-colormap 255 | //it encodes the IDL_Rainbow colorMap 256 | var shaderFragmentSourceRendering="precision lowp float;\n" 257 | +"uniform vec2 resolution;\n" 258 | +"uniform sampler2D samplerTexture;\n" 259 | 260 | //begin code from https://github.com/kbinani/glsl-colormap 261 | +"float colormap_red(float x) {\n" 262 | +" if (x < 100.0) {\n" 263 | +" return (-9.55123422981038E-02 * x + 5.86981763554179E+00) * x - 3.13964093701986E+00;\n" 264 | +" } else {\n" 265 | +" return 5.25591836734694E+00 * x - 8.32322857142857E+02;\n" 266 | +" }\n" 267 | +"}\n" 268 | +"float colormap_green(float x) {\n" 269 | +" if (x < 150.0) {\n" 270 | +" return 5.24448979591837E+00 * x - 3.20842448979592E+02;\n" 271 | +" } else {\n" 272 | +" return -5.25673469387755E+00 * x + 1.34195877551020E+03;\n" 273 | +" }\n" 274 | +"}\n" 275 | +"float colormap_blue(float x) {\n" 276 | +" if (x < 80.0) {\n" 277 | +" return 4.59774436090226E+00 * x - 2.26315789473684E+00;\n" 278 | +" } else {\n" 279 | +" return -5.25112244897959E+00 * x + 8.30385102040816E+02;\n" 280 | +" }\n" 281 | +"}\n" 282 | +"vec4 colormap(float x) {\n" 283 | +" float t = x * 255.0;\n" 284 | +" float r = clamp(colormap_red(t) / 255.0, 0.0, 1.0);\n" 285 | +" float g = clamp(colormap_green(t) / 255.0, 0.0, 1.0);\n" 286 | +" float b = clamp(colormap_blue(t) / 255.0, 0.0, 1.0);\n" 287 | +" return vec4(r, g, b, 1.0);\n" 288 | +"}\n" 289 | //end code from https://github.com/kbinani/glsl-colormap 290 | 291 | +"void main(void){\n" 292 | +"vec2 uv=gl_FragCoord.xy/resolution;\n" //texture UV coordinates 293 | +"vec4 color=texture2D(samplerTexture, uv);\n" //fetch texture color. heat is stored in red channel 294 | +"gl_FragColor=colormap(color.r/100.);\n" 295 | +"}"; 296 | 297 | //build rendering shader program : 298 | var shaderProgramRendering = build_shaderProgram(shaderVertexSource, shaderFragmentSourceRendering, 'RENDERING'); 299 | //link attributes : 300 | var _positionAttributePointer = GL.getAttribLocation(shaderProgramRendering, 'position'); 301 | GL.enableVertexAttribArray(_positionAttributePointer); 302 | create_andBindVBOs(_positionAttributePointer); 303 | 304 | //link uniforms : 305 | var _resolutionRenderingUniform = GL.getUniformLocation(shaderProgramRendering, 'resolution'); 306 | var _samplerTextureRenderingUniform = GL.getUniformLocation(shaderProgramRendering, 'samplerTexture'); 307 | 308 | 309 | //RENDER TO TEXTURE INITIALIZATION : 310 | //initialize and bind the FBO 311 | var rttFbo=GL.createFramebuffer(); 312 | GL.bindFramebuffer(GL.FRAMEBUFFER, rttFbo); 313 | 314 | //instantiate the textures : 315 | var data0=new Float32Array(SETTINGS.simuSize*SETTINGS.simuSize*4); 316 | //set all temperatures values to 0°C 317 | for (var i=0; i 2 | 3 | 4 | WGLMatrix : Linear algebra library with WebGL 5 | 6 | 7 | 8 | 9 | 10 | 27 | 28 | 29 |
30 |

WGLMatrix

31 |

32 | Test the mythical WGLMatrix library : 33 | 34 |

35 |
36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /chapter5/4_WGLMatrix/script.js: -------------------------------------------------------------------------------- 1 | /* 2 | Test our WebGL linear algebra lib WGLMatrix 3 | */ 4 | 5 | //entry point 6 | function main(){ 7 | log('Please take a look at the source code of script.js'); 8 | log('Matrix are logged flattened'); 9 | 10 | //FIRST TEST SERIE 11 | log('\n==== FIRST TEST ===='); 12 | var a=new WGLMatrix.Matrix(4,4,[1,2,3,4, 5,6,7,8, 9,10,11,12, 13,14,15,16]); 13 | var b=new WGLMatrix.Matrix(4,4,[0.2,0.6,0.7,0.8, 0.9,0.1,10,1, 1,2,3,3, -1,-10,0,0]); 14 | var r=new WGLMatrix.MatrixZero(4,4); 15 | 16 | logMatrix('TEST READ MATRIX : A =', a.read()[0]); 17 | logMatrix('TEST READ MATRIX 2 (GREEN CHANNEL) : A =', a.read()[1]); 18 | logMatrix('TEST READ MATRIX : B =', b.read()[0]); 19 | 20 | a.add(b,r); 21 | logMatrix('TEST ADD MATRICES : A+B =', r.read()[0]); 22 | 23 | a.multiplyScalar(0.1, r); 24 | logMatrix('TEST MULTIPLYSCALAR : A*0.1 =', r.read()[0]); 25 | 26 | WGLMatrix.addFunction('y=cos(x);', 'COS'); 27 | a.apply('COS', r); 28 | logMatrix('TEST APPLY : cos(A) =', r.read()[0]); 29 | 30 | 31 | 32 | //SECOND TEST 33 | log('\n==== SECOND TEST ===='); 34 | var m=new WGLMatrix.Matrix(3,3,[0,1,2, 3,4,5, 6,7,8]); 35 | var v=new WGLMatrix.Matrix(3,1,[1,2,3]); 36 | var w=new WGLMatrix.MatrixZero(3,1); 37 | 38 | logMatrix('TEST READ MATRIX : M =', m.read()[0]); 39 | logMatrix('TEST READ VECTOR : V =', v.read()[0]); 40 | 41 | m.multiply(v, w); //do matrix operation M*V and put the result to W 42 | logMatrix('TEST MULTIPLY MATRICES : M*V =', w.read()[0]); 43 | log('( expected value : [8,26,44] )'); 44 | 45 | 46 | 47 | //THIRD TEST 48 | log('\n==== THIRD TEST ===='); 49 | var a=new WGLMatrix.Matrix(2,4,[1,3,5,7, 2,4,6,8]); 50 | var b=new WGLMatrix.Matrix(4,3,[1,8,9, 2,7,10, 3,6,11, 4,5,12]); 51 | var r=new WGLMatrix.MatrixZero(2,3); 52 | 53 | logMatrix('TEST READ MATRIX : A =', a.read()[0]); 54 | logMatrix('TEST READ MATRIX : B =', b.read()[0]); 55 | 56 | a.multiply(b, r); //do matrix operation A*B and put the result to R 57 | logMatrix('TEST MULTIPLY MATRICES : A*B =', r.read()[0]); 58 | log('( expected value : [50,94,178, 60,120,220] )'); 59 | } //end main() 60 | 61 | function log(msg){ 62 | document.getElementById('logArea').value+=msg+'\n'; 63 | } 64 | 65 | function logMatrix(msg, matrixArray){ 66 | var m=msg+'['+matrixArray.toString()+']'; 67 | log(m); 68 | } -------------------------------------------------------------------------------- /chapter5/5_MNIST/data/mnist_batch_0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jpub/DeepLearningBrowser/6884b8fb5a239922153b98fc61117435fd9d45ed/chapter5/5_MNIST/data/mnist_batch_0.png -------------------------------------------------------------------------------- /chapter5/5_MNIST/data/mnist_batch_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jpub/DeepLearningBrowser/6884b8fb5a239922153b98fc61117435fd9d45ed/chapter5/5_MNIST/data/mnist_batch_1.png -------------------------------------------------------------------------------- /chapter5/5_MNIST/data/mnist_batch_10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jpub/DeepLearningBrowser/6884b8fb5a239922153b98fc61117435fd9d45ed/chapter5/5_MNIST/data/mnist_batch_10.png -------------------------------------------------------------------------------- /chapter5/5_MNIST/data/mnist_batch_11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jpub/DeepLearningBrowser/6884b8fb5a239922153b98fc61117435fd9d45ed/chapter5/5_MNIST/data/mnist_batch_11.png -------------------------------------------------------------------------------- /chapter5/5_MNIST/data/mnist_batch_12.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jpub/DeepLearningBrowser/6884b8fb5a239922153b98fc61117435fd9d45ed/chapter5/5_MNIST/data/mnist_batch_12.png -------------------------------------------------------------------------------- /chapter5/5_MNIST/data/mnist_batch_13.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jpub/DeepLearningBrowser/6884b8fb5a239922153b98fc61117435fd9d45ed/chapter5/5_MNIST/data/mnist_batch_13.png -------------------------------------------------------------------------------- /chapter5/5_MNIST/data/mnist_batch_14.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jpub/DeepLearningBrowser/6884b8fb5a239922153b98fc61117435fd9d45ed/chapter5/5_MNIST/data/mnist_batch_14.png -------------------------------------------------------------------------------- /chapter5/5_MNIST/data/mnist_batch_15.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jpub/DeepLearningBrowser/6884b8fb5a239922153b98fc61117435fd9d45ed/chapter5/5_MNIST/data/mnist_batch_15.png -------------------------------------------------------------------------------- /chapter5/5_MNIST/data/mnist_batch_16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jpub/DeepLearningBrowser/6884b8fb5a239922153b98fc61117435fd9d45ed/chapter5/5_MNIST/data/mnist_batch_16.png -------------------------------------------------------------------------------- /chapter5/5_MNIST/data/mnist_batch_17.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jpub/DeepLearningBrowser/6884b8fb5a239922153b98fc61117435fd9d45ed/chapter5/5_MNIST/data/mnist_batch_17.png -------------------------------------------------------------------------------- /chapter5/5_MNIST/data/mnist_batch_18.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jpub/DeepLearningBrowser/6884b8fb5a239922153b98fc61117435fd9d45ed/chapter5/5_MNIST/data/mnist_batch_18.png -------------------------------------------------------------------------------- /chapter5/5_MNIST/data/mnist_batch_19.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jpub/DeepLearningBrowser/6884b8fb5a239922153b98fc61117435fd9d45ed/chapter5/5_MNIST/data/mnist_batch_19.png -------------------------------------------------------------------------------- /chapter5/5_MNIST/data/mnist_batch_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jpub/DeepLearningBrowser/6884b8fb5a239922153b98fc61117435fd9d45ed/chapter5/5_MNIST/data/mnist_batch_2.png -------------------------------------------------------------------------------- /chapter5/5_MNIST/data/mnist_batch_20.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jpub/DeepLearningBrowser/6884b8fb5a239922153b98fc61117435fd9d45ed/chapter5/5_MNIST/data/mnist_batch_20.png -------------------------------------------------------------------------------- /chapter5/5_MNIST/data/mnist_batch_3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jpub/DeepLearningBrowser/6884b8fb5a239922153b98fc61117435fd9d45ed/chapter5/5_MNIST/data/mnist_batch_3.png -------------------------------------------------------------------------------- /chapter5/5_MNIST/data/mnist_batch_4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jpub/DeepLearningBrowser/6884b8fb5a239922153b98fc61117435fd9d45ed/chapter5/5_MNIST/data/mnist_batch_4.png -------------------------------------------------------------------------------- /chapter5/5_MNIST/data/mnist_batch_5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jpub/DeepLearningBrowser/6884b8fb5a239922153b98fc61117435fd9d45ed/chapter5/5_MNIST/data/mnist_batch_5.png -------------------------------------------------------------------------------- /chapter5/5_MNIST/data/mnist_batch_6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jpub/DeepLearningBrowser/6884b8fb5a239922153b98fc61117435fd9d45ed/chapter5/5_MNIST/data/mnist_batch_6.png -------------------------------------------------------------------------------- /chapter5/5_MNIST/data/mnist_batch_7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jpub/DeepLearningBrowser/6884b8fb5a239922153b98fc61117435fd9d45ed/chapter5/5_MNIST/data/mnist_batch_7.png -------------------------------------------------------------------------------- /chapter5/5_MNIST/data/mnist_batch_8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jpub/DeepLearningBrowser/6884b8fb5a239922153b98fc61117435fd9d45ed/chapter5/5_MNIST/data/mnist_batch_8.png -------------------------------------------------------------------------------- /chapter5/5_MNIST/data/mnist_batch_9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jpub/DeepLearningBrowser/6884b8fb5a239922153b98fc61117435fd9d45ed/chapter5/5_MNIST/data/mnist_batch_9.png -------------------------------------------------------------------------------- /chapter5/5_MNIST/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | MNIST learning demo 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 57 | 58 | 59 |
60 |

WebGL MNIST learning

61 |

62 | We have transcoded a simple neuron network learning MNIST dataset from python to WebGL. We use our WGLMatrix library to process all linear algebra computations. 63 |

64 | 65 |

66 | The full learning may take a few tens of minutes. 67 |

68 | 69 | 70 |

Controls :

71 |

The whole dataset may be too large for you graphic card memory. If it overflows, the WebGL context is killed. You need to refresh this webpage and to try again with a reduced version of the dataset. 72 |

73 | 74 | 75 | 76 | 77 | 78 | 79 |

Network hyperparameters :

80 |
81 |
    82 |
  • Input layer : 784 neurons (28x28 pixel digit image) 83 |
  • Hidden layer : 30 neurons 84 |
  • Output layer : 10 neurons (1 per digit) 85 |
86 |
87 |
SIGMOID
88 |
fully connected
89 | 90 | 91 |


Learning parameters :

92 |
50000
93 |
10000
94 |
30
95 |
8
96 |
3.0
97 | 98 | 99 |


Monitoring :

100 |
101 | 102 | Logging console : 103 | 104 | 105 | 106 |

References :

107 | 112 |
113 | 114 | 115 | 116 | -------------------------------------------------------------------------------- /chapter5/5_MNIST/mnist_loader.js: -------------------------------------------------------------------------------- 1 | /* 2 | Javascript equivalent of https://github.com/mnielsen/neural-networks-and-deep-learning/blob/master/src/mnist_loader.py 3 | except we load original MNIST data instead of python wrapped MNIST data 4 | 5 | We do not load validation data (not used for the first example) 6 | */ 7 | 8 | //closure 9 | var mnist_loader=(function(){ 10 | var _data={ 11 | training_data: [], 12 | test_data: [] 13 | }; 14 | var _dataCounter=0; 15 | 16 | //working canvas and ctx 17 | var _canvas=document.createElement('canvas'); 18 | _canvas.setAttribute('width', 784); 19 | _canvas.setAttribute('height', 3000); 20 | var _ctx=_canvas.getContext('2d'); 21 | 22 | function load_imgData(dataSetdivideFactor, img){ 23 | //draw the image on the canvas to be able to read pixel values 24 | _ctx.drawImage(img, 0,0); 25 | 26 | for (var line=0, targetData; line<3000; line++){ 27 | 28 | //where to put the tupple [X,Y] : 29 | if (_dataCounter>=60000/dataSetdivideFactor){ 30 | return false; //stop loading 31 | } else if (_dataCounter<50000/dataSetdivideFactor){ //first fill training data 32 | targetData=_data.training_data; 33 | } else { //then fill test data 34 | targetData=_data.test_data; 35 | } 36 | 37 | //compute input vector 38 | var iData=_ctx.getImageData(0, line, 784, 1); 39 | var learningInputVector=new Uint8Array(784); 40 | for (var i=0; i 0; i--) { 16 | j = Math.floor(Math.random() * (i + 1)); 17 | x = a[i]; 18 | a[i] = a[j]; 19 | a[j] = x; 20 | } 21 | } 22 | // get index of the max value in an array : 23 | function argmax(arr) { 24 | for (var i = 1, max = arr[0], maxIndex=0; i < arr.length; ++i) { 25 | if (arr[i] > max) { 26 | maxIndex = i; 27 | max = arr[i]; 28 | } 29 | } 30 | return maxIndex; 31 | } 32 | 33 | 34 | var that={ //public methods and objects 35 | //Network constructor : 36 | Network: function(sizes){ 37 | /*The list ``sizes`` contains the number of neurons in the 38 | respective layers of the network. For example, if the list 39 | was [2, 3, 1] then it would be a three-layer network, with the 40 | first layer containing 2 neurons, the second layer 3 neurons, 41 | and the third layer 1 neuron. The biases and weights for the 42 | network are initialized randomly, using a Gaussian 43 | distribution with mean 0, and variance 1. Note that the first 44 | layer is assumed to be an input layer, and by convention we 45 | won't set any biases for those neurons, since biases are only 46 | ever used in computing the outputs from later layers.*/ 47 | var self=this, i; 48 | 49 | self.num_layers = sizes.length; 50 | self.sizes=sizes; 51 | self._nConnections = sizes.length-1; 52 | 53 | for (i=0, self.biases=[], self.weights=[], 54 | self._weightsTransposed=[], self._weightsUpdated=[], self._biasesUpdated=[], 55 | self._delta_biases=[], self._delta_weights=[], 56 | self._z=[], self._y=[], 57 | self._nabla_b=[], self._nabla_w=[], self._delta_nabla_b=[], self._delta_nabla_w=[], 58 | self._nabla_bUpdated=[], self._nabla_wUpdated=[], 59 | self._actFuncPrimeZ=[], self._preDelta=[], self._delta=[]; 60 | i y=Infinite/Infinite = NaN 108 | WGLMatrix.addFunction('vec4 xMaj=max(x, -15.*ONE); vec4 a=(ONE+exp(-xMaj)); y=exp(-xMaj)/(a*a);', 'ACTIVATIONPRIME'); //sigmoidPrime 109 | 110 | //public dynamic methods : 111 | self.feedforward=function(a){ 112 | //Return the output of the network if ``a`` is input. 113 | for (var i=0, inp=a; i 2 | 3 | 4 | MNIST learning improved 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 57 | 58 | 59 |
60 |

WebGL MNIST learning improved

61 |

62 | We have improved the previous MNIST implementation in order to make this implementation faster than the Python/Numpy one. We still use our WGLMatrix library to process all linear algebra computations. 63 |

64 | 65 |

66 | The full learning may take a few tens of minutes. 67 |

68 | 69 | 70 |

Controls :

71 |

The whole dataset may be too large for you graphic card memory. If it overflows, the WebGL context is killed. You need to refresh this webpage and to try again with a reduced version of the dataset. 72 |

73 | 74 | 75 | 76 | 77 | 78 | 79 |

Network hyperparameters :

80 |
81 |
    82 |
  • Input layer : 784 neurons (28x28 pixel digit image) 83 |
  • Hidden layers : 256, 64 neurons 84 |
  • Output layer : 10 neurons (1 per digit) 85 |
86 |
87 |
SIGMOID
88 |
fully connected
89 | 90 | 91 |


Learning parameters :

92 |
50000
93 |
10000
94 |
20
95 |
8
96 |
1.0
97 | 98 | 99 |


Monitoring :

100 |
101 | 102 | Logging console : 103 | 104 | 105 | 106 |

References :

107 | 112 |
113 | 114 | 115 | 116 | -------------------------------------------------------------------------------- /chapter5/6_MNISTimproved/mnist_loader.js: -------------------------------------------------------------------------------- 1 | /* 2 | Javascript equivalent of https://github.com/mnielsen/neural-networks-and-deep-learning/blob/master/src/mnist_loader.py 3 | except we load original MNIST data instead of python wrapped MNIST data 4 | 5 | We do not load validation data (not used for the first example) 6 | */ 7 | 8 | "use strict"; 9 | 10 | //closure 11 | var mnist_loader=(function(){ 12 | var _data={ 13 | training_data: [], 14 | test_data: [] 15 | }; 16 | var _dataCounter=0; 17 | 18 | //working canvas and ctx 19 | var _canvas=document.createElement('canvas'); 20 | _canvas.setAttribute('width', 784); 21 | _canvas.setAttribute('height', 3000); 22 | var _ctx=_canvas.getContext('2d'); 23 | 24 | function load_imgData(dataSetdivideFactor, img){ 25 | //draw the image on the canvas to be able to read pixel values 26 | _ctx.drawImage(img, 0,0); 27 | 28 | for (var line=0, targetData; line<3000; line++){ 29 | 30 | //where to put the tupple [X,Y] : 31 | if (_dataCounter>=60000/dataSetdivideFactor){ 32 | return false; //stop loading 33 | } else if (_dataCounter<50000/dataSetdivideFactor){ //first fill training data 34 | targetData=_data.training_data; 35 | } else { //then fill test data 36 | targetData=_data.test_data; 37 | } 38 | 39 | //compute input vector 40 | var iData=_ctx.getImageData(0, line, 784, 1); 41 | var learningInputVector=new Uint8Array(784); 42 | for (var i=0; i 0; i--) { 18 | j = Math.floor(Math.random() * (i + 1)); 19 | x = a[i]; 20 | a[i] = a[j]; 21 | a[j] = x; 22 | } 23 | } 24 | // get index of the max value in an array : 25 | function argmax(arr) { 26 | for (var i = 1, max = arr[0], maxIndex=0; i < arr.length; ++i) { 27 | if (arr[i] > max) { 28 | maxIndex = i; 29 | max = arr[i]; 30 | } 31 | } 32 | return maxIndex; 33 | } 34 | 35 | 36 | var that={ //public methods and objects 37 | //Network constructor : 38 | Network: function(sizes){ 39 | /*The list ``sizes`` contains the number of neurons in the 40 | respective layers of the network. For example, if the list 41 | was [2, 3, 1] then it would be a three-layer network, with the 42 | first layer containing 2 neurons, the second layer 3 neurons, 43 | and the third layer 1 neuron. The biases and weights for the 44 | network are initialized randomly, using a Gaussian 45 | distribution with mean 0, and variance 1. Note that the first 46 | layer is assumed to be an input layer, and by convention we 47 | won't set any biases for those neurons, since biases are only 48 | ever used in computing the outputs from later layers.*/ 49 | var self=this, i; 50 | 51 | self.num_layers = sizes.length; 52 | self.sizes=sizes; 53 | self.inputSize=sizes[0]; 54 | self.outputSize=sizes[sizes.length-1]; 55 | 56 | self._nConnections = sizes.length-1; 57 | 58 | for (i=0, self.biases=[], self.weights=[], 59 | self._weightsTransposed=[], self._weightsUpdated=[], self._biasesUpdated=[], 60 | self._delta_biases=[], self._delta_weights=[], 61 | self._z=[], self._y=[], 62 | self._nabla_b=[], self._nabla_w=[], self._delta_nabla_b=[], self._delta_nabla_w=[], 63 | self._nabla_bUpdated=[], self._nabla_wUpdated=[], 64 | self._actFuncPrimeZ=[], self._preDelta=[], self._delta=[]; 65 | i y=Infinite/Infinite = NaN 112 | WGLMatrix.addFunction('vec4 xMaj=max(x, -15.*ONE); vec4 a=(ONE+exp(-xMaj)); y=exp(-xMaj)/(a*a);', 'ACTIVATIONPRIME'); //sigmoidPrime 113 | 114 | //public dynamic methods : 115 | self.feedforward=function(a){ 116 | //Return the output of the network if ``a`` is input. 117 | for (var i=0, inp=a; i 2 | 3 | 4 | 88 | -------------------------------------------------------------------------------- /chapter6/1_images/segmentation.html: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /chapter6/1_images/shapes.html: -------------------------------------------------------------------------------- 1 | 2 | 95 | -------------------------------------------------------------------------------- /chapter6/2_video/capturing.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /chapter6/2_video/streaming.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /chapter6/2_video/video_classification_dljs.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 |
7 | 8 |
9 | 10 | 19 | 20 | -------------------------------------------------------------------------------- /chapter6/3_audio/decoding.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /chapter6/3_audio/recording.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /chapter6/4_frameworks/kerasjs.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 41 | -------------------------------------------------------------------------------- /chapter6/4_frameworks/tfjs.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 63 | -------------------------------------------------------------------------------- /chapter6/4_frameworks/webdnn.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 54 | -------------------------------------------------------------------------------- /chapter6/README.md: -------------------------------------------------------------------------------- 1 | # Chapter 6 2 | 3 | ## Getting Started 4 | 5 | ```sh 6 | $ http-server 7 | 8 | Starting up http-server, serving ./ 9 | Available on: 10 | http://127.0.0.1:8080 11 | Hit CTRL-C to stop the server 12 | ``` 13 | -------------------------------------------------------------------------------- /chapter6/data/Large-dog-barks - LICENSE.txt: -------------------------------------------------------------------------------- 1 | 2 | Hello, 3 | 4 | 5 | Stock audio - Free sound effects, loops and music. 6 | 7 | 8 | There are no hidden costs or need to sign-up. 9 | 10 | 11 | 12 | License: The sound effect is permitted for commercial use under license "Creative Commons Attribution 4.0 International License 13 | 14 | 15 | http://www.orangefreesounds.com/ -------------------------------------------------------------------------------- /chapter6/data/Large-dog-barks.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jpub/DeepLearningBrowser/6884b8fb5a239922153b98fc61117435fd9d45ed/chapter6/data/Large-dog-barks.mp3 -------------------------------------------------------------------------------- /chapter6/data/bike.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jpub/DeepLearningBrowser/6884b8fb5a239922153b98fc61117435fd9d45ed/chapter6/data/bike.jpg -------------------------------------------------------------------------------- /chapter6/data/bike_object.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jpub/DeepLearningBrowser/6884b8fb5a239922153b98fc61117435fd9d45ed/chapter6/data/bike_object.png -------------------------------------------------------------------------------- /chapter6/data/cat.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jpub/DeepLearningBrowser/6884b8fb5a239922153b98fc61117435fd9d45ed/chapter6/data/cat.jpeg -------------------------------------------------------------------------------- /chapter6/data/rand.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jpub/DeepLearningBrowser/6884b8fb5a239922153b98fc61117435fd9d45ed/chapter6/data/rand.bin -------------------------------------------------------------------------------- /chapter7/.gitignore: -------------------------------------------------------------------------------- 1 | *.caffemodel 2 | *.pb -------------------------------------------------------------------------------- /chapter7/1_binary_data/data.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | def main(filename="data/rand.bin", size=100): 4 | # create an array 5 | r = np.random.rand(size, size) 6 | 7 | # write the array to disk 8 | with open(filename, 'wb') as f: 9 | f.write(r.astype(np.float32).tostring()) 10 | 11 | if __name__ == '__main__': 12 | main() -------------------------------------------------------------------------------- /chapter7/1_binary_data/data/Large-dog-barks - LICENSE.txt: -------------------------------------------------------------------------------- 1 | 2 | Hello, 3 | 4 | 5 | Stock audio - Free sound effects, loops and music. 6 | 7 | 8 | There are no hidden costs or need to sign-up. 9 | 10 | 11 | 12 | License: The sound effect is permitted for commercial use under license "Creative Commons Attribution 4.0 International License 13 | 14 | 15 | http://www.orangefreesounds.com/ -------------------------------------------------------------------------------- /chapter7/1_binary_data/data/Large-dog-barks.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jpub/DeepLearningBrowser/6884b8fb5a239922153b98fc61117435fd9d45ed/chapter7/1_binary_data/data/Large-dog-barks.mp3 -------------------------------------------------------------------------------- /chapter7/1_binary_data/data/bike.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jpub/DeepLearningBrowser/6884b8fb5a239922153b98fc61117435fd9d45ed/chapter7/1_binary_data/data/bike.jpg -------------------------------------------------------------------------------- /chapter7/1_binary_data/data/bike_object.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jpub/DeepLearningBrowser/6884b8fb5a239922153b98fc61117435fd9d45ed/chapter7/1_binary_data/data/bike_object.png -------------------------------------------------------------------------------- /chapter7/1_binary_data/data/cat.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jpub/DeepLearningBrowser/6884b8fb5a239922153b98fc61117435fd9d45ed/chapter7/1_binary_data/data/cat.jpeg -------------------------------------------------------------------------------- /chapter7/1_binary_data/data/rand.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jpub/DeepLearningBrowser/6884b8fb5a239922153b98fc61117435fd9d45ed/chapter7/1_binary_data/data/rand.bin -------------------------------------------------------------------------------- /chapter7/1_binary_data/image_data.html: -------------------------------------------------------------------------------- 1 | 2 | 74 | -------------------------------------------------------------------------------- /chapter7/1_binary_data/protobuf_caffe.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /chapter7/1_binary_data/protobuf_tensorflow.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /chapter7/2_drawing_charts/chart_types_1.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 |
17 |
18 | 19 | 20 | 21 | 22 |
23 | 24 | -------------------------------------------------------------------------------- /chapter7/2_drawing_charts/chart_types_2.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 9 | 10 | 11 |
12 | 13 | 14 |
15 | 16 | -------------------------------------------------------------------------------- /chapter7/2_drawing_charts/line_chart.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 9 | 10 | 11 |
12 | 13 | 14 |
15 | 16 | -------------------------------------------------------------------------------- /chapter7/2_drawing_charts/update_chart_1.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /chapter7/2_drawing_charts/update_chart_2.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /chapter7/3_drawing_sketches/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |

Draw your sketch in this box. Extract the pen strokes by running `sketch.data()` in the console.

5 | 6 | 12 | 13 | 93 | -------------------------------------------------------------------------------- /chapter7/4_audio_spectogram/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 | 5 |
6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /chapter7/4_audio_spectogram/worker.js: -------------------------------------------------------------------------------- 1 | self.importScripts('lib/dsp.js'); 2 | 3 | function spectogram(audioBuffer) { 4 | const fft = new FFT(audioBuffer.length, audioBuffer.sampleRate); 5 | fft.forward(audioBuffer.data); 6 | return fft.spectrum; 7 | } 8 | 9 | self.addEventListener('message', function(e) { 10 | const s = spectogram(e.data); 11 | self.postMessage(s); 12 | }, false); -------------------------------------------------------------------------------- /chapter7/5_face_tracking/faceFilter.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | FACE TRACKING USING JEELIZ FACEFILTER API DEMO 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 |
44 | Github repository 45 | 46 | 47 | -------------------------------------------------------------------------------- /chapter7/5_face_tracking/face_detector.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /chapter7/5_face_tracking/lib/tracking.min.js: -------------------------------------------------------------------------------- 1 | /** 2 | * tracking - A modern approach for Computer Vision on the web. 3 | * @author Eduardo Lundgren 4 | * @version v1.1.3 5 | * @link http://trackingjs.com 6 | * @license BSD 7 | */ 8 | !function(t,r){t.tracking=t.tracking||{},tracking.inherits=function(t,r){function n(){}n.prototype=r.prototype,t.superClass_=r.prototype,t.prototype=new n,t.prototype.constructor=t,t.base=function(t,n){var e=Array.prototype.slice.call(arguments,2);return r.prototype[n].apply(t,e)}},tracking.initUserMedia_=function(r,n){t.navigator.mediaDevices.getUserMedia({video:!0,audio:!(!n||!n.audio)}).then(function(t){r.srcObject=t})["catch"](function(t){throw Error("Cannot capture user camera.")})},tracking.isNode=function(t){return t.nodeType||this.isWindow(t)},tracking.isWindow=function(t){return!!(t&&t.alert&&t.document)},tracking.one=function(t,r){return this.isNode(t)?t:(r||document).querySelector(t)},tracking.track=function(t,r,n){if(t=tracking.one(t),!t)throw new Error("Element not found, try a different element or selector.");if(!r)throw new Error("Tracker not specified, try `tracking.track(element, new tracking.FaceTracker())`.");switch(t.nodeName.toLowerCase()){case"canvas":return this.trackCanvas_(t,r,n);case"img":return this.trackImg_(t,r,n);case"video":return n&&n.camera&&this.initUserMedia_(t,n),this.trackVideo_(t,r,n);default:throw new Error("Element not supported, try in a canvas, img, or video.")}},tracking.trackCanvas_=function(t,r){var n=this,e=new tracking.TrackerTask(r);return e.on("run",function(){n.trackCanvasInternal_(t,r)}),e.run()},tracking.trackCanvasInternal_=function(t,r){var n=t.width,e=t.height,a=t.getContext("2d"),i=a.getImageData(0,0,n,e);r.track(i.data,n,e)},tracking.trackImg_=function(t,r){var n=t.width,e=t.height,a=document.createElement("canvas");a.width=n,a.height=e;var i=new tracking.TrackerTask(r);return i.on("run",function(){tracking.Canvas.loadImage(a,t.src,0,0,n,e,function(){tracking.trackCanvasInternal_(a,r)})}),i.run()},tracking.trackVideo_=function(r,n){var e,a,i=document.createElement("canvas"),o=i.getContext("2d"),c=function(){e=r.offsetWidth,a=r.offsetHeight,i.width=e,i.height=a};c(),r.addEventListener("resize",c);var s,g=function(){s=t.requestAnimationFrame(function(){if(r.readyState===r.HAVE_ENOUGH_DATA){try{o.drawImage(r,0,0,e,a)}catch(t){}tracking.trackCanvasInternal_(i,n)}g()})},h=new tracking.TrackerTask(n);return h.on("stop",function(){t.cancelAnimationFrame(s)}),h.on("run",function(){g()}),h.run()},t.URL||(t.URL=t.URL||t.webkitURL||t.msURL||t.oURL),navigator.getUserMedia||(navigator.getUserMedia=navigator.getUserMedia||navigator.webkitGetUserMedia||navigator.mozGetUserMedia||navigator.msGetUserMedia)}(window),function(){tracking.EventEmitter=function(){},tracking.EventEmitter.prototype.events_=null,tracking.EventEmitter.prototype.addListener=function(t,r){if("function"!=typeof r)throw new TypeError("Listener must be a function");return this.events_||(this.events_={}),this.emit("newListener",t,r),this.events_[t]||(this.events_[t]=[]),this.events_[t].push(r),this},tracking.EventEmitter.prototype.listeners=function(t){return this.events_&&this.events_[t]},tracking.EventEmitter.prototype.emit=function(t){var r=this.listeners(t);if(r){for(var n=Array.prototype.slice.call(arguments,1),e=0;e>2),i=0,o=0,c=0;c0&&(s=new Int32Array(r*n)),tracking.Image.computeIntegralImage(t,r,n,k,f,u,s);for(var l=c[0],m=c[1],d=e*a,v=d*l|0,p=d*m|0;v0&&this.isTriviallyExcluded(o,s,w,T,r,v,p)||this.evalStages_(c,k,f,u,w,T,r,v,p,d)&&(h[g++]={width:v,height:p,x:T,y:w});d*=a,v=d*l|0,p=d*m|0}return this.mergeRectangles_(h)},tracking.ViolaJones.isTriviallyExcluded=function(t,r,n,e,a,i,o){var c=n*a+e,s=c+i,g=c+o*a,h=g+i,k=(r[c]-r[s]-r[g]+r[h])/(i*o*255);return k0&&(v=Math.sqrt(d));for(var p=t.length,y=2;y=this.REGIONS_OVERLAP&&h/(f*(k/f))>=this.REGIONS_OVERLAP&&r.union(n,a)}}for(var u={},l=0;l>1)*(this.N>>5)),a=0,i=this.getRandomOffsets_(r),o=0,c=0;c>1,i=n.length>>1,o=new Array(a),c=0;c>5;fn},tracking.Fast.isCorner=function(t,r,n){if(this.isTriviallyExcluded(r,t,n))return!1;for(var e=0;e<16;e++){for(var a=!0,i=!0,o=0;o<9;o++){var c=r[e+o&15];if(!this.isBrighter(t,c,n)&&(i=!1,a===!1))break;if(!this.isDarker(t,c,n)&&(a=!1,i===!1))break}if(i||a)return!0}return!1},tracking.Fast.isDarker=function(t,r,n){return r-t>n},tracking.Fast.isTriviallyExcluded=function(t,r,n){var e=0,a=t[8],i=t[12],o=t[4],c=t[0];return this.isBrighter(c,r,n)&&e++,this.isBrighter(o,r,n)&&e++,this.isBrighter(a,r,n)&&e++,this.isBrighter(i,r,n)&&e++,e<3&&(e=0,this.isDarker(c,r,n)&&e++,this.isDarker(o,r,n)&&e++,this.isDarker(a,r,n)&&e++,this.isDarker(i,r,n)&&e++,e<3)},tracking.Fast.getCircleOffsets_=function(t){if(this.circles_[t])return this.circles_[t];var r=new Int32Array(16);return r[0]=-t-t-t,r[1]=r[0]+1,r[2]=r[1]+t+1,r[3]=r[2]+t+1,r[4]=r[3]+t,r[5]=r[4]+t,r[6]=r[5]+t-1,r[7]=r[6]+t-1,r[8]=r[7]-1,r[9]=r[8]-1,r[10]=r[9]-t-1,r[11]=r[10]-t-1,r[12]=r[11]-t,r[13]=r[12]-t,r[14]=r[13]-t+1,r[15]=r[14]-t+1,this.circles_[t]=r,r}}(),function(){tracking.Math={},tracking.Math.distance=function(t,r,n,e){var a=n-t,i=e-r;return Math.sqrt(a*a+i*i)},tracking.Math.hammingWeight=function(t){return t-=t>>1&1431655765,t=(858993459&t)+(t>>2&858993459),16843009*(t+(t>>4)&252645135)>>24},tracking.Math.uniformRandom=function(t,r){return t+Math.random()*(r-t)},tracking.Math.intersectRect=function(t,r,n,e,a,i,o,c){return!(a>n||oe||cn&&(n=c),se&&(e=s)}return{width:n-a,height:e-i,x:a,y:i}},tracking.ColorTracker.prototype.getColors=function(){return this.colors},tracking.ColorTracker.prototype.getMinDimension=function(){return this.minDimension},tracking.ColorTracker.prototype.getMaxDimension=function(){return this.maxDimension},tracking.ColorTracker.prototype.getMinGroupSize=function(){return this.minGroupSize},tracking.ColorTracker.prototype.getNeighboursForWidth_=function(t){if(tracking.ColorTracker.neighbours_[t])return tracking.ColorTracker.neighbours_[t];var r=new Int32Array(8);return r[0]=4*-t,r[1]=4*-t+4,r[2]=4,r[3]=4*t+4,r[4]=4*t,r[5]=4*t-4,r[6]=-4,r[7]=4*-t-4,tracking.ColorTracker.neighbours_[t]=r,r},tracking.ColorTracker.prototype.mergeRectangles_=function(t){for(var r,n=[],e=this.getMinDimension(),a=this.getMaxDimension(),i=0;i=e&&o.height>=e&&o.width<=a&&o.height<=a&&n.push(o)}return n},tracking.ColorTracker.prototype.setColors=function(t){this.colors=t},tracking.ColorTracker.prototype.setMinDimension=function(t){this.minDimension=t},tracking.ColorTracker.prototype.setMaxDimension=function(t){this.maxDimension=t},tracking.ColorTracker.prototype.setMinGroupSize=function(t){this.minGroupSize=t},tracking.ColorTracker.prototype.track=function(t,r,n){var e=this,a=this.getColors();if(!a)throw new Error('Colors not specified, try `new tracking.ColorTracker("magenta")`.');var i=[];a.forEach(function(a){i=i.concat(e.trackColor_(t,r,n,a))}),this.emit("track",{data:i})},tracking.ColorTracker.prototype.trackColor_=function(n,e,a,i){var o,c,s,g,h,k=tracking.ColorTracker.knownColors_[i],f=new Int32Array(n.length>>2),u=new Int8Array(n.length),l=this.getMinGroupSize(),m=this.getNeighboursForWidth_(e),d=new Int32Array(n.length),v=[],p=-4;if(!k)return v;for(var y=0;y=0;)if(s=d[h--],c=d[h--],g=d[h--],k(n[g],n[g+1],n[g+2],n[g+3],g,c,s)){f[o++]=s,f[o++]=c;for(var T=0;T=0&&M=0&&_=l){var C=this.calculateDimensions_(f,o);C&&(C.color=i,v.push(C))}}return this.mergeRectangles_(v)},tracking.ColorTracker.registerColor("cyan",function(t,r,n){var e=50,a=70,i=t-0,o=r-255,c=n-255;return r-t>=e&&n-t>=a||i*i+o*o+c*c<6400}),tracking.ColorTracker.registerColor("magenta",function(t,r,n){var e=50,a=t-255,i=r-0,o=n-255;return t-r>=e&&n-r>=e||a*a+i*i+o*o<19600}),tracking.ColorTracker.registerColor("yellow",function(t,r,n){var e=50,a=t-255,i=r-255,o=n-0;return t-n>=e&&r-n>=e||a*a+i*i+o*o<1e4});var t=new Int32Array([-1,-1,0,1,1,1,0,-1]),r=new Int32Array([0,1,1,1,0,-1,-1,-1])}(),function(){tracking.ObjectTracker=function(t){tracking.ObjectTracker.base(this,"constructor"),t&&(Array.isArray(t)||(t=[t]),Array.isArray(t)&&t.forEach(function(r,n){if("string"==typeof r&&(t[n]=tracking.ViolaJones.classifiers[r]),!t[n])throw new Error('Object classifier not valid, try `new tracking.ObjectTracker("face")`.')})),this.setClassifiers(t)},tracking.inherits(tracking.ObjectTracker,tracking.Tracker),tracking.ObjectTracker.prototype.edgesDensity=.2,tracking.ObjectTracker.prototype.initialScale=1,tracking.ObjectTracker.prototype.scaleFactor=1.25,tracking.ObjectTracker.prototype.stepSize=1.5,tracking.ObjectTracker.prototype.getClassifiers=function(){return this.classifiers},tracking.ObjectTracker.prototype.getEdgesDensity=function(){return this.edgesDensity},tracking.ObjectTracker.prototype.getInitialScale=function(){return this.initialScale},tracking.ObjectTracker.prototype.getScaleFactor=function(){return this.scaleFactor},tracking.ObjectTracker.prototype.getStepSize=function(){return this.stepSize},tracking.ObjectTracker.prototype.track=function(t,r,n){var e=this,a=this.getClassifiers();if(!a)throw new Error('Object classifier not specified, try `new tracking.ObjectTracker("face")`.');var i=[];a.forEach(function(a){i=i.concat(tracking.ViolaJones.detect(t,r,n,e.getInitialScale(),e.getScaleFactor(),e.getStepSize(),e.getEdgesDensity(),a))}),this.emit("track",{data:i})},tracking.ObjectTracker.prototype.setClassifiers=function(t){this.classifiers=t},tracking.ObjectTracker.prototype.setEdgesDensity=function(t){this.edgesDensity=t},tracking.ObjectTracker.prototype.setInitialScale=function(t){this.initialScale=t},tracking.ObjectTracker.prototype.setScaleFactor=function(t){this.scaleFactor=t},tracking.ObjectTracker.prototype.setStepSize=function(t){this.stepSize=t}}(),function(){tracking.LandmarksTracker=function(){tracking.LandmarksTracker.base(this,"constructor")},tracking.inherits(tracking.LandmarksTracker,tracking.ObjectTracker),tracking.LandmarksTracker.prototype.track=function(t,r,n){var e=tracking.ViolaJones.classifiers.face,a=tracking.ViolaJones.detect(t,r,n,this.getInitialScale(),this.getScaleFactor(),this.getStepSize(),this.getEdgesDensity(),e),i=tracking.LBF.align(t,r,n,a);this.emit("track",{data:{faces:a,landmarks:i}})}}(),function(){tracking.LBF={},tracking.LBF.Regressor=function(t){this.maxNumStages=t,this.rfs=new Array(t),this.models=new Array(t);for(var r=0;r 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /cover.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jpub/DeepLearningBrowser/6884b8fb5a239922153b98fc61117435fd9d45ed/cover.jpg --------------------------------------------------------------------------------