This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const [punch, kick, nothing] = Array.from((model.predict( | |
mobilenet(tf.fromPixels(scaled)) | |
) as tf.Tensor1D).dataSync() as Float32Array); | |
const detect = (window as any).Detect; | |
if (nothing >= 0.4) return; | |
if (kick > punch && kick >= 0.35) { | |
detect.onKick(); | |
return; | |
} | |
if (punch > kick && punch >= 0.35) detect.onPunch(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const model = tf.sequential(); | |
model.add(tf.layers.inputLayer({ inputShape: [1024] })); | |
model.add(tf.layers.dense({ units: 1024, activation: 'relu' })); | |
model.add(tf.layers.dense({ units: 3, activation: 'softmax' })); | |
await model.compile({ | |
optimizer: tf.train.adam(1e-6), | |
loss: tf.losses.sigmoidCrossEntropy, | |
metrics: ['accuracy'] | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const punches = require('fs') | |
.readdirSync(Punches) | |
.filter(f => f.endsWith('.jpg')) | |
.map(f => `${Punches}/${f}`); | |
const kicks = require('fs') | |
.readdirSync(Kicks) | |
.filter(f => f.endsWith('.jpg')) | |
.map(f => `${Kicks}/${f}`); | |
const others = require('fs') | |
.readdirSync(Others) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const startInterval = (mobilenet, model) => () => { | |
setInterval(() => { | |
canvas.getContext('2d').drawImage(video, 0, 0); | |
grayscale(scale | |
.getContext('2d') | |
.drawImage( | |
canvas, 0, 0, canvas.width, | |
canvas.width / (ImageSize.Width / ImageSize.Height), | |
0, 0, ImageSize.Width, ImageSize.Height | |
)); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
let mobilenet: (p: any) => tf.Tensor<tf.Rank>; | |
tf.loadModel('http://localhost:5000/model.json').then(model => { | |
mobileNet | |
.load() | |
.then((mn: any) => mobilenet = mobilenetInfer(mn)) | |
.then(startInterval(mobilenet, model)); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const grayscale = (canvas: HTMLCanvasElement) => { | |
const imageData = canvas.getContext('2d').getImageData(0, 0, canvas.width, canvas.height); | |
const data = imageData.data; | |
for (let i = 0; i < data.length; i += 4) { | |
const avg = (data[i] + data[i + 1] + data[i + 2]) / 3; | |
data[i] = avg; | |
data[i + 1] = avg; | |
data[i + 2] = avg; | |
} | |
canvas.getContext('2d').putImageData(imageData, 0, 0); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const video = document.getElementById('cam'); | |
const Layer = 'global_average_pooling2d_1'; | |
const mobilenetInfer = m => (p): tf.Tensor<tf.Rank> => m.infer(p, Layer); | |
const canvas = document.getElementById('canvas'); | |
const scale = document.getElementById('crop'); | |
const ImageSize = { | |
Width: 100, | |
Height: 56 | |
}; | |
navigator.mediaDevices |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
await model.fit(xs, ys, { | |
epochs: Epochs, | |
batchSize: parseInt(((punches.length + others.length) * BatchSize).toFixed(0)), | |
callbacks: { | |
onBatchEnd: async (_, logs) => { | |
console.log('Cost: %s, accuracy: %s', logs.loss.toFixed(5), logs.acc.toFixed(5)); | |
await tf.nextFrame(); | |
} | |
} | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
export const readInput = img => imageToInput(readImage(img), TotalChannels); | |
const readImage = path => jpeg.decode(fs.readFileSync(path), true); | |
const imageToInput = image => { | |
const values = serializeImage(image); | |
return tf.tensor3d(values, [image.height, image.width, 3], 'int32'); | |
}; | |
const serializeImage = image => { | |
const totalPixels = image.width * image.height; | |
const result = new Int32Array(totalPixels * 3); | |
for (let i = 0; i < totalPixels; i++) { |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const punches = require('fs') | |
.readdirSync(Punches) | |
.filter(f => f.endsWith('.jpg')) | |
.map(f => `${Punches}/${f}`); | |
const others = require('fs') | |
.readdirSync(Others) | |
.filter(f => f.endsWith('.jpg')) | |
.map(f => `${Others}/${f}`); | |
const ys = tf.tensor1d( | |
new Array(punches.length).fill(1) |
NewerOlder