UNPKG

@quadible/web-sdk

Version:

The web sdk for Quadible's behavioral authentication service.

235 lines 8.65 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); // tslint:disable: no-bitwise const eventemitter2_1 = require("eventemitter2"); var THREE; (function (THREE) { class PerspectiveCamera { constructor(fov, aspect, near, far) { } position; aspect; updateProjectionMatrix() { } } THREE.PerspectiveCamera = PerspectiveCamera; class Scene { add(obj) { } } THREE.Scene = Scene; class WebGLRenderer { constructor(options) { } domElement; setSize(width, height) { } sortObjects; render(scene, camera) { } } THREE.WebGLRenderer = WebGLRenderer; class VideoTexture { constructor(video) { } } THREE.VideoTexture = VideoTexture; class Object3D { add(obj) { } scale; rotation; } THREE.Object3D = Object3D; class PlaneGeometry { constructor(width, height, canvasWidth, canvasHeight) { } verticesNeedUpdate; getAttribute(name) { return new BufferAttribute; } } THREE.PlaneGeometry = PlaneGeometry; class Mesh { constructor(geometry, material) { } position; } THREE.Mesh = Mesh; class MeshBasicMaterial { constructor(options) { } } THREE.MeshBasicMaterial = MeshBasicMaterial; class BufferAttribute { setZ(index, value) { } getZ(index) { return 0; } needsUpdate; } THREE.BufferAttribute = BufferAttribute; class Color { constructor(color) { } r; g; b; } THREE.Color = Color; let AdditiveBlending; (function (AdditiveBlending) { })(AdditiveBlending = THREE.AdditiveBlending || (THREE.AdditiveBlending = {})); })(THREE || (THREE = {})); const fov = 70; const canvasWidth = 320 / 2; const canvasHeight = 240 / 2; const tiltSpeed = 0.1; const tiltAmount = 0.5; const viewportWidth = 400; const viewportHeight = 500; class WebcamWireframe extends eventemitter2_1.EventEmitter2 { options; lastFrameWithPredictions; debug = false; camera = new THREE.PerspectiveCamera(fov, viewportWidth / viewportHeight, 1, 5000); scene = new THREE.Scene(); renderer = new THREE.WebGLRenderer({ antialias: true }); video; videoTexture; mainGroup = new THREE.Object3D(); geometry = new THREE.PlaneGeometry(640, 480, canvasWidth, canvasHeight); vidCanvas = document.createElement('canvas'); ctx = this.vidCanvas.getContext('2d'); fdCanvas = document.createElement('canvas'); fdCtx = this.fdCanvas.getContext('2d'); pixels = new Uint8ClampedArray(); isDisposed = false; wireMaterial = new THREE.MeshBasicMaterial({ opacity: 0.1, color: 0xffffff, wireframe: true, blending: THREE.AdditiveBlending, transparent: true }); meshMaterial; constructor(options) { THREE = window['THREE']; super(); this.options = options; this.video = this.options.videoWorker.video; this.videoTexture = new THREE.VideoTexture(this.video); this.meshMaterial = new THREE.MeshBasicMaterial({ opacity: 1, map: this.options.wireframe.showOriginalVideo ? this.videoTexture : undefined, color: '#333' }); this.scene.add(this.camera); this.camera.position.z = 600; this.scene.add(this.mainGroup); const mirror = new THREE.Mesh(this.geometry, this.meshMaterial); this.mainGroup.add(mirror); const wiremirror = new THREE.Mesh(this.geometry, this.wireMaterial); this.mainGroup.add(wiremirror); wiremirror.position.z = 5; this.renderer.sortObjects = false; this.renderer.setSize(viewportWidth, viewportHeight); this.renderer.domElement.addEventListener('dblclick', this.toggleDebug.bind(this)); Object.assign(this.renderer.domElement.style, { position: 'absolute', top: '0px', left: '0px', display: 'block' }); Object.assign(this.vidCanvas.style, { display: 'none' }); Object.assign(this.fdCanvas.style, { position: 'absolute', top: '0px', left: '0px', width: '100%', display: 'none' }); this.fdCanvas.width = 400; this.fdCanvas.height = 400; document.addEventListener('mousewheel', this.onWheel.bind(this), false); this.options.videoWorker.on('predictions', this.predictionsHandler); this.options.wrapper.append(this.renderer.domElement, this.vidCanvas, this.fdCanvas); this.onResize(); this.animate(); } dispose() { this.isDisposed = true; this.options.videoWorker.off('predictions', this.predictionsHandler); } predictionsHandler = (async ({ predictions, imageBase64 }) => { if (predictions.length) { this.lastFrameWithPredictions = { predictions, imageBase64 }; } if (this.debug) { this.drawPredictionRectangle(predictions, imageBase64); } }).bind(this); toggleDebug() { this.debug = !this.debug; this.fdCanvas.style.display = this.debug ? 'block' : 'none'; } getZDepths() { this.ctx.drawImage(this.video, 0, 0, canvasWidth + 1, canvasHeight + 1); this.pixels = this.ctx.getImageData(0, 0, canvasWidth + 1, canvasHeight + 1).data; for (let i = 0; i < canvasWidth + 1; i++) { for (let j = 0; j < canvasHeight + 1; j++) { const color = new THREE.Color(this.getColor(i, j)); const brightness = this.getBrightness(color); const gotoZ = this.options.wireframe.zDepth * brightness - this.options.wireframe.zDepth / 2; const position = this.geometry.getAttribute('position'); position.setZ(j * (canvasWidth + 1) + i, position.getZ(j * (canvasWidth + 1) + i) + (gotoZ - position.getZ(j * (canvasWidth + 1) + i)) / 5); position.needsUpdate = true; } } this.geometry['verticesNeedUpdate'] = true; } async animate() { this.getZDepths(); this.render(); requestAnimationFrame(this.animate.bind(this)); } async drawPredictionRectangle(predictions, imageBase64) { const image = new Image(); image.src = imageBase64; await new Promise(resolve => image.onload = resolve); this.fdCtx.drawImage(image, 0, 0); for (const prediction of predictions) { const start = prediction.topLeft; const end = prediction.bottomRight; const probability = prediction.probability; const size = [end[0] - start[0], end[1] - start[1]]; this.fdCtx.beginPath(); this.fdCtx.strokeStyle = 'green'; this.fdCtx.lineWidth = 4; this.fdCtx.rect(start[0], start[1], size[0], size[1]); this.fdCtx.stroke(); const prob = (probability[0] * 100).toPrecision(5).toString(); const text = prob + '%'; this.fdCtx.fillStyle = 'red'; this.fdCtx.font = '13pt sans-serif'; this.fdCtx.fillText(text, start[0] + 5, start[1] + 20); } } render() { if (!this.isDisposed) { this.mainGroup.scale.setScalar(this.options.wireframe.zoom); this.mainGroup.rotation.x += (0 * tiltAmount - this.mainGroup.rotation.x) * tiltSpeed; this.mainGroup.rotation.y += (0 * tiltAmount - this.mainGroup.rotation.y) * tiltSpeed; this.renderer.render(this.scene, this.camera); } } onResize() { this.renderer.setSize(viewportWidth, viewportHeight); this.camera.aspect = viewportWidth / viewportHeight; this.camera.updateProjectionMatrix(); } getColor(x, y) { const base = (Math.floor(y) * (canvasWidth + 1) + Math.floor(x)) * 4; const c = { r: this.pixels[base + 0], g: this.pixels[base + 1], b: this.pixels[base + 2], a: this.pixels[base + 3] }; return (c.r << 16) + (c.g << 8) + c.b; } getBrightness(c) { return 0.34 * c.r + 0.5 * c.g + 0.16 * c.b; } onWheel(event) { this.options.wireframe.zoom += event.wheelDelta * 0.002; this.options.wireframe.zoom = Math.max(this.options.wireframe.zoom, 0.1); this.options.wireframe.zoom = Math.min(this.options.wireframe.zoom, 5); } } exports.default = WebcamWireframe; //# sourceMappingURL=WebcamWireframe.js.map