1'use strict'; 2 3var videoLoop = function () { 4 var _ref = _asyncToGenerator(regeneratorRuntime.mark(function _callee(t) { 5 var dt; 6 return regeneratorRuntime.wrap(function _callee$(_context) { 7 while (1) { 8 switch (_context.prev = _context.next) { 9 case 0: 10 dt = t - lastTime; 11 _context.next = 3; 12 return update(dt); 13 14 case 3: 15 16 lastTime = t; 17 if (scrollY > innerHeight * 0.8) { 18 setTimeout(videoLoop, 1000); 19 } else { 20 lastFrame = requestAnimationFrame(videoLoop); 21 } 22 23 case 5: 24 case 'end': 25 return _context.stop(); 26 } 27 } 28 }, _callee, this); 29 })); 30 31 return function videoLoop(_x) { 32 return _ref.apply(this, arguments); 33 }; 34}(); 35 36var squeezenet = function () { 37 var _ref2 = _asyncToGenerator(regeneratorRuntime.mark(function _callee2() { 38 var keras_model, keras_model_meta, buffer, network, compiled; 39 return regeneratorRuntime.wrap(function _callee2$(_context2) { 40 while (1) { 41 switch (_context2.prev = _context2.next) { 42 case 0: 43 _context2.next = 2; 44 return loadJSON('models/rps.json'); 45 46 case 2: 47 keras_model = _context2.sent; 48 _context2.next = 5; 49 return loadJSON('models/rps_metadata.json'); 50 51 case 5: 52 keras_model_meta = _context2.sent; 53 _context2.next = 8; 54 return loadBuffer('models/rps-weights.buf'); 55 56 case 8: 57 buffer = _context2.sent; 58 59 // var buffer = await loadBuffer('models/rps-0.9575_weights.buf'); 60 61 console.log(keras_model, keras_model_meta, buffer); 62 63 // var image = (await loadArrayFromURL('data/cat-227x227x3')).transpose(1, 0, 2); 64 65 // ;(new Tensor(gl, image)).show({ offset: 0.5, scale: 1/256, flipY: true }) 66 67 68 network = import_keras_network(keras_model, keras_model_meta, buffer); 69 70 console.log(network); 71 console.log(network.splice(-2, 2)); // cut off the last two layers, do that in JS 72 73 _context2.next = 15; 74 return compile(gl, network, { input_1: zeros([227, 227, 3]) }); 75 76 case 15: 77 compiled = _context2.sent; 78 79 C = compiled; 80 81 // await destroy(gl, compiled) 82 83 case 17: 84 case 'end': 85 return _context2.stop(); 86 } 87 } 88 }, _callee2, this); 89 })); 90 91 return function squeezenet() { 92 return _ref2.apply(this, arguments); 93 }; 94}(); 95 96var update = function () { 97 var _ref3 = _asyncToGenerator(regeneratorRuntime.mark(function _callee3(dt) { 98 var compiled, videox, vwidth, im, data, results, imagedata, factor; 99 return regeneratorRuntime.wrap(function _callee3$(_context3) { 100 while (1) { 101 switch (_context3.prev = _context3.next) { 102 case 0: 103 // await model.ready() 104 105 ctx.clearRect(0, 0, canvas.width, canvas.height); 106 107 compiled = C; 108 109 // var videox = window.game_state === 'playing' 110 // ? 0 111 // : canvas.width / 4 112 113 videox = 0; 114 115 116 if (hasVideo) { 117 118 ctx.save(); 119 ctx.translate(canvas.width / 2, 0); 120 ctx.scale(-1, 1); 121 122 vwidth = canvas.height / video.videoHeight * video.videoWidth; 123 124 ctx.drawImage(video, (video.videoWidth - video.videoHeight) / 2, 0, video.videoHeight, video.videoHeight, videox, 0, canvas.height, canvas.height);
125 ctx.restore(); 126 } 127 128 im = ctx.getImageData(videox, 0, 227, 227); 129 _context3.next = 7; 130 return run(gl, compiled, { input_1: preprocess_input(im) }); 131 132 case 7: 133 data = compiled.info['global_average_pooling2d_1'].output.read().data; 134 results = softmax(Array.from(data)); 135 imagedata = tickerCtx.getImageData(0, 0, ticker.width, ticker.height); 136 137 tickerCtx.clearRect(0, 0, ticker.width, ticker.height); 138 tickerCtx.putImageData(imagedata, -1, 0); 139 140 factor = .6; 141 142 results.map(function (x) { 143 return Math.sqrt(x); 144 }).forEach(function (r, i) { 145 derps[i] = derps[i] * factor + r * (1 - factor); 146 tickerCtx.fillStyle = colors[i]; 147 tickerCtx.fillRect(ticker.width - 1, Math.round(ticker.height / 4 * (i + .5 - derps[i] / 2 * 0.9)), 1, Math.round(ticker.height / 4 * (derps[i] * 0.9))); 148 }); 149 150 person_move = results.indexOf(Math.max.apply(Math, _toConsumableArray(results))); 151 // person_move = derps.indexOf(Math.max(...derps)) 152 153 avg_person_move = derps.indexOf(Math.max.apply(Math, derps)); 154 if (avg_person_move === 2) { 155 // rock 156 if (Date.now() - last_nonrock > 700) { 157 // woot we're ready to partaaay 158 window.game_state = 'playing'; 159 } 160 } else { 161 last_nonrock = Date.now(); 162 } 163 164 ctx.font = '15px Arial'; 165 ctx.fillStyle = '#fff'; 166 ctx.textAlign = 'center'; 167 ctx.textBaseline = 'middle'; 168 ctx.fillText('YOU: ' + wins, videox + canvas.width / 4, 20); 169 ctx.fillText('COMPUTER: ' + losses, videox + canvas.width * 3 / 4, 20); 170 171 ctx.font = '40px Arial'; 172 ctx.fillStyle = '#fff'; 173 ctx.textAlign = 'center'; 174 ctx.textBaseline = 'middle'; 175 ctx.fillText('vs', videox + canvas.width / 2, canvas.height / 2); 176 177 ctx.font = '30px Arial'; 178 ctx.fillStyle = '#fff'; 179 ctx.textAlign = 'right'; 180 ctx.textBaseline = 'bottom'; 181 ctx.fillText(MOVES[person_move], videox + canvas.width / 2 - 20, canvas.height - 15); 182 183 // ctx.font = '100px Arial' 184 // ctx.fillStyle = '#fff' 185 // ctx.textAlign = 'center' 186 // ctx.textBaseline = 'middle' 187 // ctx.fillText( 188 // MOVES[person_move], 189 // videox + canvas.width/4 , 190 // canvas.height / 2 191 // ) 192 193 if (window.game_state === 'playing') { 194 if (animations[cur_animation](dt)) { 195 cur_animation++; 196 if (cur_animation >= animations.length) { 197 cur_animation = 0; 198 window.game_state = 'waiting'; 199 } 200 // cur_animation = (cur_animation + 1) % animations.length 201 } 202 } else { 203 ctx.fillStyle = 'white'; 204 ctx.textAlign = 'center'; 205 ctx.textBaseline = 'middle'; 206 ctx.font = '20px Arial'; 207 ctx.fillText('to begin game', canvas.width / 4 * 3, canvas.height / 2 - 15); 208 ctx.fillText('raise â rock', canvas.width / 4 * 3, canvas.height / 2 + 15); 209 } 210 211 case 34: 212 case 'end': 213 return _context3.stop(); 214 } 215 } 216 }, _callee3, this); 217 })); 218 219 return function update(_x2) { 220 return _ref3.apply(this, arguments); 221 }; 222}(); 223 224var gotVideo = function () { 225 var _ref4 = _asyncToGenerator(regeneratorRuntime.mark(function _callee4() { 226 return regeneratorRuntime.wrap(function _callee4$(_context4) { 227 while (1) { 228 switch (_context4.prev = _context4.next) { 229 case 0: 230 hasVideo = true; 231 _context4.next = 3; 232 return squeezenet(); 233 234 case 3: 235 start(); 236 237 case 4: 238 case 'end': 239 return _context4.stop(); 240 } 241 } 242 }, _callee4, this); 243 })); 244 245 return function gotVideo() { 246 return _ref4.apply(this, arguments); 247 }; 248}(); 249 250function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } } 251 252function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { tr
252y { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; } 253 254var gl = TF.createGL(document.getElementById('glCanvas')), 255 OutputTensor = TF.OutputTensor, 256 Tensor = TF.Tensor, 257 InPlaceTensor = TF.InPlaceTensor, 258 TP = function TP(s) { 259 return function (out, opt) { 260 return TF.Run(s.join(''), out, opt); 261 }; 262}; 263gl.canvas.width = 227; 264gl.canvas.height = 227; 265 266var canvas = document.getElementById('canvas'), 267 ctx = canvas.getContext('2d'); 268 269// var img = new Image; 270// img.src = 'data/sims.png' 271// img.onload = function(){ 272// ctx.drawImage(img, 0, 0, canvas.width, canvas.height) 273// } 274 275var lastFrame, lastTime; 276function start() { 277 lastTime = performance.now(); 278 videoLoop(lastTime); 279} 280 281var animations = []; 282var cur_animation = 0; 283 284var register_animation = function register_animation(duration, cb) { 285 var left = duration; 286 animations.push(function (dt) { 287 left -= dt; 288 if (left <= 0) { 289 cb(1); 290 left = duration; 291 return true; 292 } 293 cb(1 - left / duration); 294 }); 295}; 296 297var flash = function flash(text, legend) { 298 return function (r) { 299 var d = r < .5 ? r * 2 : (1 - r) * 2; 300 301 // ctx.fillStyle = 'rgba(255,255,0,'+ d / 2 + .5 +')' 302 ctx.fillStyle = 'rgba(255,255,0,1)'; 303 ctx.textAlign = 'center'; 304 ctx.textBaseline = 'middle'; 305 ctx.font = '100px Arial'; 306 307 ctx.fillText(text, canvas.width / 4 * 3, canvas.height / 2 + d * 40 - 40); 308 309 if (r > .5 || legend) { 310 ctx.font = '20px Arial'; 311 ctx.fillText(['', 'scissors', 'paper', 'rock'][text], canvas.width / 4 * 3, canvas.height / 2 + 50); 312 } 313 }; 314}; 315 316var MOVES = ['ð¶', 'â', 'â', 'âï¸']; 317var losers = ['none', 2, 3, 1]; 318window.colors = ['#eee', '#48f', 'yellow', 'rgb(255, 123, 0)']; 319 320var computer_move = 0; 321var person_move = 0; 322 323// register_animation(800, flash('Ready...')) 324register_animation(800, flash(3)); 325register_animation(800, flash(2)); 326register_animation(800, flash(1)); 327register_animation(400, function (r) { 328 return flash(1)(r / 2); 329}); 330register_animation(0, function () { 331 computer_move = Math.floor(Math.random() * 3) + 1; 332 333 // console.log('computer_move', computer_move) 334 // ctx.textBaseline = 'middle' 335 // tickerCtx.textAlign = 'right' 336 // tickerCtx.fillText(MOVES[person_move], ticker.width, ticker.height / 4 * (person_move + .5) ) 337 338}); 339register_animation(1000, function (r) { 340 ctx.fillStyle = 'rgba(255,255,255,' + (1 - r) / 2 + ')'; 341 ctx.fillRect(0, 0, canvas.width, canvas.height); 342 343 ctx.textAlign = 'center'; 344 ctx.textBaseline = 'middle'; 345 ctx.font = '100px Arial'; 346 ctx.fillStyle = 'rgba(255,255,255,1)'; 347 ctx.fillText(MOVES[computer_move], canvas.width / 4 * 3, canvas.height / 2); 348}); 349 350var wins = 0, 351 losses = 0, 352 ties = 0; 353var human_move = void 0; 354 355register_animation(0, function () { 356 human_move = avg_person_move; 357 358 ctx.textAlign = 'center'; 359 ctx.textBaseline = 'middle'; 360 ctx.font = '100px Arial'; 361 ctx.fillStyle = 'rgba(255,255,255,1)'; 362 ctx.fillText(MOVES[computer_move], canvas.width / 4 * 3, canvas.height / 2); 363 364 // ctx.fillText(MOVES[human_move],canvas.width / 4 ,canvas.height / 2) 365 if (computer_move === losers[human_move]) { 366 wins++; 367 tickerCtx.fillStyle = 'rgba(0,255,0,0.5)'; 368 } else if (computer_move != human_move) { 369 losses++; 370 tickerCtx.fillStyle = 'rgba(255,0,0,0.5)'; 371 } else { 372 ties++; 373 tickerCtx.fillStyle = 'rgba(0,0,0,0.5)'; 374 } 375 376 console.log('wins: ', wins, 'losses: ', losses, 'ties: ', ties); 377 378 tickerCtx.fillRect(ticker.width - 1, 0, 1, ticker.height); 379}); 380 381register_animation(1500, function (r) { 382 ctx.textAlign = 'center'; 383 ctx.textBaseline = 'middle'; 384 ctx.font = '100px Arial'; 385 ctx.fillStyle = 'rgba(255,255,255,' + (1 - r) + ')'; 386 // ctx.fillStyle = '#fff' 387 ctx.fillText(MOVES[computer_move], canvas.width / 4 * 3, canvas.height / 2); 388 389 ctx.font = '70px Arial'; 390 ctx.fillStyle = 'rgba(0,0,0,' + Math.min(0.5, 2 * r) + ')'; 391 ctx.fillRect(0, (canvas.height - 120) / 2, canvas.width, 120); 392 ctx.fillStyle = 'white'; 393 if (computer_move === losers[human_move]) { 394 ctx.fillText('You Win!', canvas.width / 2, canvas.height / 2 - 20); 395 396 ctx.font = '30px Arial'; 397 ctx.fillText(MOVES[human_move] + '>
397' + MOVES[computer_move], canvas.width / 2, canvas.height / 2 + 40); 398 } else if (computer_move != human_move) { 399 ctx.fillText('You Lose!', canvas.width / 2, canvas.height / 2 - 20); 400 401 ctx.font = '30px Arial'; 402 ctx.fillText(MOVES[human_move] + '<' + MOVES[computer_move], canvas.width / 2, canvas.height / 2 + 40); 403 } else { 404 ctx.fillText('Tie!', canvas.width / 2, canvas.height / 2 - 20); 405 406 ctx.font = '30px Arial'; 407 ctx.fillText(MOVES[human_move] + '=' + MOVES[computer_move], canvas.width / 2, canvas.height / 2 + 40); 408 } 409}); 410 411register_animation(1000, function (r) {}); 412 413var C; 414var video = document.getElementById('videoElement'); 415 416function softmax(arr) { 417 var maxVal = arr[0]; 418 for (var i = 1; i < arr.length; i++) { 419 if (arr[i] > maxVal) maxVal = arr[i]; 420 }var exp = arr.map(function (k) { 421 return Math.exp(k - maxVal); 422 }), 423 expSum = exp.reduce(function (a, b) { 424 return a + b; 425 }); 426 return exp.map(function (k) { 427 return k / expSum; 428 }); 429} 430 431function normalize(arr) { 432 var maxVal = arr[0]; 433 for (var i = 1; i < arr.length; i++) { 434 if (arr[i] > maxVal) maxVal = arr[i]; 435 }return arr.map(function (k) { 436 return k / maxVal; 437 }); 438} 439 440var avg_person_move; 441 442function preprocess_input(im) { 443 // data processing 444 // see https://github.com/fchollet/keras/blob/master/keras/applications/imagenet_utils.py 445 var dataTensor = ndarray(new Float32Array(im.data), [im.width, im.height, 4]); 446 var dataProcessedTensor = ndarray(new Float32Array(im.width * im.height * 3), [im.width, im.height, 3]); 447 ndops.subseq(dataTensor.pick(null, null, 2), 103.939); 448 ndops.subseq(dataTensor.pick(null, null, 1), 116.779); 449 ndops.subseq(dataTensor.pick(null, null, 0), 123.68); 450 ndops.assign(dataProcessedTensor.pick(null, null, 0), dataTensor.pick(null, null, 2)); 451 ndops.assign(dataProcessedTensor.pick(null, null, 1), dataTensor.pick(null, null, 1)); 452 ndops.assign(dataProcessedTensor.pick(null, null, 2), dataTensor.pick(null, null, 0)); 453 return dataProcessedTensor; 454} 455 456var derps = [0, 0, 0, 0]; 457 458var tickerCtx = ticker.getContext('2d'); 459 460ticker.width = 400; 461ticker.height = 200; 462 463var last_nonrock = 0; 464 465var hasVideo = false; 466 467function connectWebcam() { 468 document.querySelector('.demo').classList.remove('waiting'); 469 document.querySelector('.demo').classList.add('training'); 470 471 if (navigator.mediaDevices) { 472 navigator.mediaDevices.getUserMedia({ video: true }).then(function (mediaStream) { 473 video.srcObject = mediaStream; 474 475 gotVideo(); 476 }).catch(function (err) { 477 console.log(err.name + ": " + err.message); 478 }); // always check for errors at the end. 479 } else { 480 navigator.getUserMedia({ video: true }, function (stream) { 481 video.src = window.URL.createObjectURL(stream); 482 gotVideo(); 483 }, function () { 484 console.log('error'); 485 }); 486 } 487} 488 489if (!(navigator.mediaDevices || navigator.getUserMedia)) { 490 document.body.classList.add('no-gum'); 491}
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.