├── CollectShapeData
└── CollectShapeData.pde
├── LICENSE
├── README.md
└── shapeclassifier_ml5
├── index.html
├── model
├── model.json
├── model.weights.bin
└── model_meta.json
└── sketch.js
/CollectShapeData/CollectShapeData.pde:
--------------------------------------------------------------------------------
1 | void setup() {
2 | size(256, 256);
3 | }
4 |
5 | void draw() {
6 |
7 | for (int i = 0; i < 3; i++) {
8 | background(255);
9 | noFill();
10 | strokeWeight(8);
11 | color c = color(random(128), random(128), random(128));
12 | stroke(c);
13 | translate(width/2, height/2);
14 | float x = random(-32, 32);
15 | float y = random(-32, 32);
16 | float r = random(24, 72);
17 | if (i == 0) {
18 | circle(x, y, r*2);
19 | saveFrame("data/circle####.png");
20 | } else if (i == 1) {
21 | rectMode(CENTER);
22 | square(x, y, r*2);
23 | saveFrame("data/square####.png");
24 | } else if (i == 2) {
25 | triangle(x-r, y+r, x, y-r, x+r, y+r);
26 | saveFrame("data/triangle####.png");
27 | }
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2020 Daniel Shiffman
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # ShapeClassifierCNN
2 | test code for new tutorial
3 |
--------------------------------------------------------------------------------
/shapeclassifier_ml5/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Neural Network
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 | Convolutional Neural Network
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/shapeclassifier_ml5/model/model.json:
--------------------------------------------------------------------------------
1 | {"modelTopology":{"class_name":"Sequential","config":{"name":"sequential_1","layers":[{"class_name":"Conv2D","config":{"filters":8,"kernel_initializer":{"class_name":"VarianceScaling","config":{"scale":1,"mode":"fan_in","distribution":"normal","seed":null}},"kernel_regularizer":null,"kernel_constraint":null,"kernel_size":[5,5],"strides":[1,1],"padding":"valid","data_format":"channels_last","dilation_rate":[1,1],"activation":"relu","use_bias":true,"bias_initializer":{"class_name":"Zeros","config":{}},"bias_regularizer":null,"activity_regularizer":null,"bias_constraint":null,"name":"conv2d_Conv2D1","trainable":true,"batch_input_shape":[null,128,128,4],"dtype":"float32"}},{"class_name":"MaxPooling2D","config":{"pool_size":[2,2],"padding":"valid","strides":[2,2],"data_format":"channels_last","name":"max_pooling2d_MaxPooling2D1","trainable":true}},{"class_name":"Conv2D","config":{"filters":16,"kernel_initializer":{"class_name":"VarianceScaling","config":{"scale":1,"mode":"fan_in","distribution":"normal","seed":null}},"kernel_regularizer":null,"kernel_constraint":null,"kernel_size":[5,5],"strides":[1,1],"padding":"valid","data_format":"channels_last","dilation_rate":[1,1],"activation":"relu","use_bias":true,"bias_initializer":{"class_name":"Zeros","config":{}},"bias_regularizer":null,"activity_regularizer":null,"bias_constraint":null,"name":"conv2d_Conv2D2","trainable":true}},{"class_name":"MaxPooling2D","config":{"pool_size":[2,2],"padding":"valid","strides":[2,2],"data_format":"channels_last","name":"max_pooling2d_MaxPooling2D2","trainable":true}},{"class_name":"Flatten","config":{"name":"flatten_Flatten1","trainable":true}},{"class_name":"Dense","config":{"units":3,"activation":"softmax","use_bias":true,"kernel_initializer":{"class_name":"VarianceScaling","config":{"scale":1,"mode":"fan_in","distribution":"normal","seed":null}},"bias_initializer":{"class_name":"Zeros","config":{}},"kernel_regularizer":null,"bias_regularizer":null,"activity_regularizer":null,"kernel_constraint":null,"bias_constraint":null,"name":"dense_Dense1","trainable":true}}]},"keras_version":"tfjs-layers 1.7.2","backend":"tensor_flow.js"},"weightsManifest":[{"paths":["./model.weights.bin"],"weights":[{"name":"conv2d_Conv2D1/kernel","shape":[5,5,4,8],"dtype":"float32"},{"name":"conv2d_Conv2D1/bias","shape":[8],"dtype":"float32"},{"name":"conv2d_Conv2D2/kernel","shape":[5,5,8,16],"dtype":"float32"},{"name":"conv2d_Conv2D2/bias","shape":[16],"dtype":"float32"},{"name":"dense_Dense1/kernel","shape":[13456,3],"dtype":"float32"},{"name":"dense_Dense1/bias","shape":[3],"dtype":"float32"}]}]}
--------------------------------------------------------------------------------
/shapeclassifier_ml5/model/model.weights.bin:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shiffman/ShapeClassifierCNN/d2e839ec9c360a6255ca11689c492f65eb941c2b/shapeclassifier_ml5/model/model.weights.bin
--------------------------------------------------------------------------------
/shapeclassifier_ml5/model/model_meta.json:
--------------------------------------------------------------------------------
1 | {"inputUnits":[128,128,4],"outputUnits":3,"inputs":{"image":{"dtype":"array","min":0,"max":255}},"outputs":{"label":{"dtype":"string","min":0,"max":1,"uniqueValues":["circle","square","triangle"],"legend":{"circle":[1,0,0],"square":[0,1,0],"triangle":[0,0,1]}}},"isNormalized":true}
--------------------------------------------------------------------------------
/shapeclassifier_ml5/sketch.js:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2019 ml5
2 | //
3 | // This software is released under the MIT License.
4 | // https://opensource.org/licenses/MIT
5 |
6 | /* ===
7 | ml5 Example
8 | Image classification using Convolutional Neural Network
9 | This example uses a callback pattern to create the classifier
10 | === */
11 |
12 | const circles = [];
13 | const squares = [];
14 | const triangles = [];
15 |
16 | let resultsP;
17 | let shapeClassifier;
18 | let video;
19 |
20 | // function preload() {
21 | // for (let i = 0; i < 100; i++) {
22 | // circles[i] = loadImage(`data/circle${nf(i+1,4,0)}.png`)
23 | // squares[i] = loadImage(`data/square${nf(i+1,4,0)}.png`)
24 | // triangles[i] = loadImage(`data/triangle${nf(i+1,4,0)}.png`)
25 | // console.log(`data/circle${nf(i+1,4,0)}.png`);
26 | // }
27 |
28 | // }
29 |
30 | let canvas;
31 | let graphics;
32 |
33 | function setup() {
34 | canvas = createCanvas(128, 128);
35 | video = createCapture(VIDEO);
36 | video.size(128, 128);
37 | video.hide();
38 | //graphics = createGraphics(128, 128);
39 | //pixelDensity(1);
40 | const options = {
41 | inputs: [128, 128, 4],
42 | task: 'imageClassification',
43 | debug: true,
44 | };
45 | resultsP = createP('');
46 |
47 | // construct the neural network
48 | shapeClassifier = ml5.neuralNetwork(options);
49 | shapeClassifier.load({
50 | model: 'model/model.json',
51 | metadata: 'model/model_meta.json',
52 | weights: 'model/model.weights.bin'
53 | }, modelLoaded);
54 |
55 | // add data
56 | // for (let i = 0; i < circles.length; i += 1) {
57 | // shapeClassifier.addData({ image: circles[i] }, { label: "circle"});
58 | // shapeClassifier.addData({ image: squares[i] }, { label: "square"});
59 | // shapeClassifier.addData({ image: triangles[i] }, { label: "triangle"});
60 | // }
61 |
62 | // normalize data
63 | // shapeClassifier.normalizeData();
64 |
65 | // shapeClassifier.train({ epochs: 50 }, finishedTraining);
66 | }
67 |
68 | function draw() {
69 | image(video, 0,0,width,height);
70 | }
71 |
72 | function modelLoaded() {
73 | shapeClassifier.classify({ image: video }, gotResults);
74 |
75 | // graphics.translate(width/2,height/2);
76 | // noLoop();
77 | // graphics.background(255);
78 | // graphics.noFill();
79 | // graphics.strokeWeight(8);
80 | // const c = color(random(128), random(128), random(128));
81 | // graphics.stroke(c);
82 | // const x = random(-16, 16);
83 | // const y = random(-16, 16);
84 | // const r = random(12, 48);
85 | // graphics.rectMode(CENTER);
86 | // graphics.square(x, y, r*2);
87 |
88 | // graphics.loadPixels();
89 | // shapeClassifier.classify({ image: video }, gotResults);
90 |
91 | // image(graphics, 0, 0);
92 | }
93 |
94 |
95 |
96 | // function finishedTraining() {
97 | // console.log('finished training');
98 | // // method 1: you can pass in an object with a matching key and the p5 image
99 | // }
100 |
101 | function gotResults(err, results) {
102 | if (err) {
103 | console.log(err);
104 | return;
105 | }
106 | console.log(results);
107 | const percent = 100 * results[0].confidence;
108 | resultsP.html(`${results[0].label} ${nf(percent, 2, 1)}%`);
109 | shapeClassifier.classify({ image: video }, gotResults);
110 |
111 | }
112 |
--------------------------------------------------------------------------------