浏览代码

Add glasses from Jeeliz into AR face filter scan

master
Adwaith Rao 4 年前
父节点
当前提交
0acd6fe37d
共有 22 个文件被更改,包括 2601 次插入168 次删除
  1. +6
    -1
      angular.json
  2. +3
    -7
      src/app/ar-fan-cam/ar-fan-cam.page.html
  3. +177
    -160
      src/app/ar-fan-cam/ar-fan-cam.page.ts
  4. 二进制
      src/assets/ar-accessories/envMap.jpg
  5. +1
    -0
      src/assets/ar-accessories/models3D/face.json
  6. +27
    -0
      src/assets/ar-accessories/models3D/glassesFrames.json
  7. +27
    -0
      src/assets/ar-accessories/models3D/glassesFramesBranchesBent.json
  8. +27
    -0
      src/assets/ar-accessories/models3D/glassesLenses.json
  9. +1
    -0
      src/assets/ar-accessories/neuralNets/NN_4EXPR_0.json
  10. +1
    -0
      src/assets/ar-accessories/neuralNets/NN_DEFAULT.json
  11. +1
    -0
      src/assets/ar-accessories/neuralNets/NN_INTEL1536.json
  12. +1
    -0
      src/assets/ar-accessories/neuralNets/NN_LIGHT_0.json
  13. +1
    -0
      src/assets/ar-accessories/neuralNets/NN_VERYLIGHT_0.json
  14. +1
    -0
      src/assets/ar-accessories/neuralNets/NN_VIEWTOP_0.json
  15. +1
    -0
      src/assets/ar-accessories/neuralNets/NN_WIDEANGLES_0.json
  16. 二进制
      src/assets/ar-accessories/turban.png
  17. +328
    -0
      vendors/jeelizFaceFilter/JeelizResizer.js
  18. +445
    -0
      vendors/jeelizFaceFilter/JeelizThreeHelper.js
  19. +178
    -0
      vendors/jeelizFaceFilter/jeelizFaceFilter.js
  20. +1030
    -0
      vendors/jeelizFaceFilter/three.min.js
  21. +166
    -0
      vendors/jeelizFaceFilter/typescript/JeelizCanvas2DHelper.ts
  22. +179
    -0
      vendors/jeelizFaceFilter/typescript/JeelizFaceFilterInterfaces.ts

+ 6
- 1
angular.json 查看文件

@@ -40,7 +40,12 @@
"input": "src/global.scss"
}
],
"scripts": []
"scripts": [
"vendors/jeelizFaceFilter/jeelizFaceFilter.js",
"vendors/jeelizFaceFilter/three.min.js",
"vendors/jeelizFaceFilter/jeelizResizer.js",
"vendors/jeelizFaceFilter/jeelizThreeHelper.js"
]
},
"configurations": {
"production": {


+ 3
- 7
src/app/ar-fan-cam/ar-fan-cam.page.html 查看文件

@@ -3,20 +3,16 @@
<button class="back-button" (click)="back()"> <ion-icon name="close-outline"></ion-icon> </button>

<div class="container" #containerElement>
<img #glassesElement class="glass-image" [ngStyle]="glassProperties" src="/assets/ar-accessories/glass.png" alt=""/>
<video id="playback-video" width="{{ width }}" height="{{ height }}" #videoElement autoPlay></video>
<img id="source-image" #sourceImageElement width="{{ width }}" height="{{ height }}" />
<canvas id="source-canvas" #sourceCanvasElement width="{{ width }}" height="{{ height }}"></canvas>
<canvas id="result-canvas" #canvasElement width="{{ width }}" height="{{ height }}"></canvas>
</div>

<section class="temp-image" [ngClass]="{'active' : tempImg }">
<div *ngIf="!glassesFramesMeshLoaded || !glassesLensMeshLoaded">Loading</div>

<section class="temp-image" [ngClass]="{'active' : !!tempImg }">
<img *ngIf="tempImg" src="{{ tempImg }}">
</section>

<div class="action-buttons" *ngIf="!tempImg">
<!-- <button *ngIf="areNeuralNetsLoaded" (click)="stopCameraStream()">Stop stream</button> -->
<!-- <button *ngIf="areNeuralNetsLoaded" (click)="toggleDetection()">{{ isDetecting ? 'Stop detection' : 'Detect and draw' }}</button> -->

<button class="camera-button" (click)="capture()"> <ion-icon name="camera"></ion-icon> </button>



+ 177
- 160
src/app/ar-fan-cam/ar-fan-cam.page.ts 查看文件

@@ -1,8 +1,12 @@
import { Component, ElementRef, OnInit, ViewChild } from '@angular/core';
import { detectSingleFace, loadFaceExpressionModel, loadFaceLandmarkModel, loadFaceLandmarkTinyModel, loadFaceRecognitionModel, loadSsdMobilenetv1Model, loadTinyFaceDetectorModel, TinyFaceDetectorOptions } from 'face-api.js';
import { CameraPreview, CameraPreviewPictureOptions, CameraPreviewOptions, CameraPreviewDimensions } from '@ionic-native/camera-preview/ngx';
import { Location } from '@angular/common';
import { ModalController } from '@ionic/angular';
import { IJeelizFaceFilter } from 'vendors/jeelizFaceFilter/typescript/JeelizFaceFilterInterfaces';

declare var JEELIZFACEFILTER: IJeelizFaceFilter;
declare var JeelizThreeHelper: any;
declare var JeelizResizer: any;
declare var THREE: any;

@Component({
selector: 'app-ar-fan-cam',
@@ -10,205 +14,218 @@ import { ModalController } from '@ionic/angular';
styleUrls: ['./ar-fan-cam.page.scss'],
})
export class ArFanCamPage implements OnInit {
@ViewChild('videoElement') videoElement: ElementRef<HTMLVideoElement>;
@ViewChild('glassesElement') glassesElement: ElementRef<HTMLImageElement>;
@ViewChild('canvasElement') canvasElement: ElementRef<HTMLCanvasElement>;
@ViewChild('sourceImageElement') sourceImageElement: ElementRef<HTMLImageElement>;
@ViewChild('sourceCanvasElement') sourceCanvasElement: ElementRef<HTMLCanvasElement>;
mediaStream: MediaStream|null = null;
capturedImageStrings: Array<string> = [];

glassProperties: {
[property: string]: any,
} = {
transform: 'scale(0)',
};

areNeuralNetsLoaded = false;
isDetecting = false;
THREECAMERA = null;

width: number;
height: number;

tempImg = '';
stream: any;

glassesFramesMeshLoaded = false;
glassesLensMeshLoaded = false;

constructor(
private location: Location,
private modalController: ModalController,
private cameraPreview: CameraPreview
private modalController: ModalController
) {
this.sourceImageElement.nativeElement.onload = () => {
const context = this.sourceCanvasElement.nativeElement.getContext('2d');
context.drawImage(
this.sourceImageElement.nativeElement,
0,
0,
this.sourceCanvasElement.nativeElement.width,
this.sourceCanvasElement.nativeElement.height
);
}
}

loadNeuralNetModels = async () => {
await loadTinyFaceDetectorModel('/assets/weights');
await loadSsdMobilenetv1Model('/assets/weights');

await loadFaceLandmarkTinyModel('/assets/weights');
await loadFaceLandmarkModel('/assets/weights');

await loadFaceRecognitionModel('/assets/weights');
await loadFaceExpressionModel('/assets/weights');

this.areNeuralNetsLoaded = true;
}

back() {
this.modalController.dismiss();
this.stopCameraStream();
}

getCameraStream = async () => {
if (this.cameraPreview) {
const cameraPreviewOpts: CameraPreviewOptions = {
x: 0,
y: 0,
width: window.screen.width,
height: window.screen.height,
camera: 'rear',
tapPhoto: true,
previewDrag: true,
toBack: true,
alpha: 1
}
this.cameraPreview.startCamera(cameraPreviewOpts);
} else {
const stream = await window.navigator.mediaDevices.getUserMedia({
video: {
facingMode: 'user',
width: this.width,
height: this.height
},
}).then((stream) => {
this.mediaStream = stream;
this.videoElement.nativeElement.srcObject = stream;
}).catch(err => alert(JSON.stringify(err)));
}
};
// AR Face detection and drawing

stopCameraStream = async () => {
if (this.cameraPreview) {
this.cameraPreview.stopCamera();
}

if (this.mediaStream) {
this.mediaStream.getVideoTracks().forEach(track => {
track.stop();
});
this.mediaStream = null;
this.stream = null;

detect_callback(faceIndex, isDetected) {
if (isDetected) {
console.log('INFO in detect_callback(): DETECTED');
} else {
console.log('INFO in detect_callback(): LOST');
}
}

async capture() {
const canvas = this.canvasElement.nativeElement;
const context = canvas.getContext('2d');
context.drawImage(this.videoElement.nativeElement, 0, 0, canvas.width, canvas.height);

const getGlassesStyles = window.getComputedStyle(this.glassesElement.nativeElement);

const glassesTransformValue = getGlassesStyles.getPropertyValue("-webkit-transform") ||
getGlassesStyles.getPropertyValue("-moz-transform") ||
getGlassesStyles.getPropertyValue("-ms-transform") ||
getGlassesStyles.getPropertyValue("-o-transform") ||
getGlassesStyles.getPropertyValue("transform");
const glassesTransformMatrixValues = glassesTransformValue.split('(')[1].split(')')[0].split(',');

{
const a = Number(glassesTransformMatrixValues[0]);
const b = Number(glassesTransformMatrixValues[1]);
const c = Number(glassesTransformMatrixValues[2]);
const d = Number(glassesTransformMatrixValues[3]);
const e = Number(glassesTransformMatrixValues[4]);
const f = Number(glassesTransformMatrixValues[5]);
context.transform(a, b, c, d, e, f);
}
// build the 3D. called once when Jeeliz Face Filter is OK
init_threeScene(spec) {
const threeStuffs = JeelizThreeHelper.init(spec, this.detect_callback);
// improve WebGLRenderer settings:
threeStuffs.renderer.toneMapping = THREE.ACESFilmicToneMapping;
threeStuffs.renderer.outputEncoding = THREE.sRGBEncoding;
// CREATE THE GLASSES AND ADD THEM
const r = this.JeelizThreeGlassesCreator({
envMapURL: "assets/ar-accessories/envMap.jpg",
frameMeshURL: "assets/ar-accessories/models3D/glassesFramesBranchesBent.json",
lensesMeshURL: "assets/ar-accessories/models3D/glassesLenses.json",
occluderURL: "assets/ar-accessories/models3D/face.json"
});
// vertical offset:
const dy = 0.07;
// create and add the occluder:
r.occluder.rotation.set(0.3, 0, 0);
r.occluder.position.set(0, 0.03 + dy,-0.04);
r.occluder.scale.multiplyScalar(0.0084);
threeStuffs.faceObject.add(r.occluder);
context.drawImage(this.glassesElement.nativeElement, 0, 0);

const dataURI = canvas.toDataURL('image/png');
this.capturedImageStrings.push(dataURI);
// create and add the glasses mesh:
const threeGlasses = r.glasses;
//threeGlasses.rotation.set(-0.15,0,0); / /X neg -> rotate branches down
threeGlasses.position.set(0, dy, 0.4);
threeGlasses.scale.multiplyScalar(0.006);
threeStuffs.faceObject.add(threeGlasses);
// add a debug cube:
/* const sc = 0.1;
const debugCube = new THREE.Mesh(new THREE.BoxGeometry(sc,sc,sc), new THREE.MeshNormalMaterial());
threeStuffs.faceObject.add(debugCube); //*/
// CREATE THE CAMERA:
this.THREECAMERA = JeelizThreeHelper.create_camera();
}

this.tempImg = dataURI;
JeelizThreeGlassesCreator(spec) {
const threeGlasses = new THREE.Object3D();
// envMap texture:
const textureEquirec = new THREE.TextureLoader().load( spec.envMapURL );
textureEquirec.mapping = THREE.EquirectangularReflectionMapping;
textureEquirec.magFilter = THREE.LinearFilter;
textureEquirec.minFilter = THREE.LinearMipMapLinearFilter;
// glasses frames:
new THREE.BufferGeometryLoader().load(spec.frameMeshURL, function(glassesFramesGeometry){
glassesFramesGeometry.computeVertexNormals();
// custom material with fading at the end of the branches:
const us = THREE.ShaderLib.standard.uniforms;
const uniforms = {
roughness: {value: 0},
metalness: {value: 0.05},
reflectivity: {value: 1},
envMap: {value: textureEquirec},
envMapIntensity: {value: 1},
diffuse: {value: new THREE.Color().setHex(0xffffff)},
uBranchFading: {value: new THREE.Vector2(-90, 60)} // first value: position (lower -> to the back), second: transition brutality
};
// tweak vertex shader to give the Z of the current point:
let vertexShaderSource = "varying float vPosZ;\n" + THREE.ShaderLib.standard.vertexShader;
vertexShaderSource = vertexShaderSource.replace('#include <fog_vertex>', 'vPosZ = position.z;');
// tweak fragment shader to apply transparency at the end of the branches:
let fragmentShaderSource = "uniform vec2 uBranchFading;\n varying float vPosZ;\n" + THREE.ShaderLib.standard.fragmentShader;
const GLSLcomputeAlpha = 'gl_FragColor.a = smoothstep(uBranchFading.x - uBranchFading.y*0.5, uBranchFading.x + uBranchFading.y*0.5, vPosZ);'
fragmentShaderSource = fragmentShaderSource.replace('#include <fog_fragment>', GLSLcomputeAlpha);
const mat = new THREE.ShaderMaterial({
vertexShader: vertexShaderSource,
fragmentShader: fragmentShaderSource,
uniforms: uniforms,
flatShading: false,
transparent: true,
extensions: { // fix for https://github.com/jeeliz/jeelizFaceFilter/issues/154
//derivatives: true,
//shaderTextureLOD: true
}
});
mat.envMap = textureEquirec;
const glassesFramesMesh = new THREE.Mesh(glassesFramesGeometry, mat);
threeGlasses.add(glassesFramesMesh);

context.resetTransform();
context.clearRect(0, 0, window.innerWidth, window.innerHeight);
}
this.glassesFramesMeshLoaded = true;
// window.debugMatFrames = mat; // to debug the material il the JS console
});
// glasses lenses:
new THREE.BufferGeometryLoader().load(spec.lensesMeshURL, function(glassesLensesGeometry){
glassesLensesGeometry.computeVertexNormals();
const mat = new THREE.MeshBasicMaterial({
envMap: textureEquirec,
opacity: 0.7,
color: new THREE.Color().setHex(0x2233aa),
transparent: true,
fog: false
});
const glassesLensesMesh = new THREE.Mesh(glassesLensesGeometry, mat);
threeGlasses.add(glassesLensesMesh);

async getSnapshotFromPreview() {
const base64Image: string = await this.cameraPreview.takeSnapshot();
this.sourceImageElement.nativeElement.src = base64Image;
this.glassesLensMeshLoaded = true;
// window.debugMatLens = mat; // to debug the material il the JS console
});
const occluderMesh = JeelizThreeHelper.create_threejsOccluder(spec.occluderURL);
return {
glasses: threeGlasses,
occluder: occluderMesh
};
}

getSnapshotFromVideo() {
const sourceCanvas = this.sourceCanvasElement.nativeElement;
const context = sourceCanvas.getContext('2d');
context.drawImage(this.videoElement.nativeElement, 0, 0, sourceCanvas.width, sourceCanvas.height);
main(){
JeelizResizer.size_canvas({
canvasId: 'source-canvas',
isApplyCSS: true,
callback: (isError, bestVideoSettings) => {
this.init_faceFilter(bestVideoSettings);
}
})
}

detectAndDrawFace = async () => {
const tinyFaceDetectorOptions = new TinyFaceDetectorOptions();

if (this.cameraPreview) {
await this.getSnapshotFromPreview();
} else {
this.getSnapshotFromVideo();
}

let detectionWithLandmarks = await detectSingleFace(this.sourceCanvasElement.nativeElement, tinyFaceDetectorOptions).withFaceLandmarks(true);
init_faceFilter(videoSettings){
JEELIZFACEFILTER.init({
followZRot: true,
canvasId: 'source-canvas',
NNCPath: 'assets/ar-accessories/neuralNets/', // root of NN_DEFAULT.json file
maxFacesDetected: 1,
videoSettings: {
...videoSettings,
idealWidth: window.innerWidth,
idealHeight: window.innerHeight,
maxWidth: window.innerWidth,
maxHeight: window.innerHeight,
},
callbackReady: (errCode, spec) => {
if (errCode){
console.log('AN ERROR HAPPENS. ERR =', errCode);
return;
}
console.log('INFO: JEELIZFACEFILTER IS READY');
this.init_threeScene(spec);
},
if (detectionWithLandmarks) {
const leftEye = detectionWithLandmarks.landmarks.getLeftEye();
const rightEye = detectionWithLandmarks.landmarks.getRightEye();

const distanceBetweenEyes = Math.sqrt(Math.pow(rightEye[0].x - leftEye[0].x, 2) + Math.pow(rightEye[0].y - leftEye[0].y, 2));
const angleOfGlassesRotation = (Math.atan2(rightEye[0].y - leftEye[0].y, rightEye[0].x - leftEye[0].x) * 180) / Math.PI;

const scaleGlassesMultiplier = distanceBetweenEyes / 130;

this.glassProperties = {
transform: `translate(calc(-14.5% + ${leftEye[0].x}px), calc(-45% + ${leftEye[0].y}px)) scale(${scaleGlassesMultiplier}) rotate(${angleOfGlassesRotation}deg)`,
};
}

requestAnimationFrame(this.detectAndDrawFace);
// called at each render iteration (drawing loop):
callbackTrack: (detectState) => {
JeelizThreeHelper.render(detectState, this.THREECAMERA);
}
}); //end JEELIZFACEFILTER.init call
}

toggleDetection = () => {
if (!this.isDetecting) {
this.isDetecting = true;
this.detectAndDrawFace();
} else {
this.isDetecting = false;
}
// End AR Face detection and drawing

async capture() {
const dataURI = this.sourceCanvasElement.nativeElement.toDataURL('image/jpeg');
this.tempImg = dataURI;
}

ngOnInit() {
this.width = window.innerWidth;
this.height = window.innerHeight;
}

ngAfterViewInit() {
this.loadNeuralNetModels();
this.getCameraStream().then(() => this.detectAndDrawFace(), (err) => console.log(err));
this.main();
}

approveImage() {
this.stopCameraStream();
this.modalController.dismiss({
imageData: this.tempImg


二进制
src/assets/ar-accessories/envMap.jpg 查看文件

之前 之后
宽度: 4096  |  高度: 2048  |  大小: 731 KiB

+ 1
- 0
src/assets/ar-accessories/models3D/face.json
文件差异内容过多而无法显示
查看文件


+ 27
- 0
src/assets/ar-accessories/models3D/glassesFrames.json
文件差异内容过多而无法显示
查看文件


+ 27
- 0
src/assets/ar-accessories/models3D/glassesFramesBranchesBent.json
文件差异内容过多而无法显示
查看文件


+ 27
- 0
src/assets/ar-accessories/models3D/glassesLenses.json
文件差异内容过多而无法显示
查看文件


+ 1
- 0
src/assets/ar-accessories/neuralNets/NN_4EXPR_0.json
文件差异内容过多而无法显示
查看文件


+ 1
- 0
src/assets/ar-accessories/neuralNets/NN_DEFAULT.json
文件差异内容过多而无法显示
查看文件


+ 1
- 0
src/assets/ar-accessories/neuralNets/NN_INTEL1536.json
文件差异内容过多而无法显示
查看文件


+ 1
- 0
src/assets/ar-accessories/neuralNets/NN_LIGHT_0.json
文件差异内容过多而无法显示
查看文件


+ 1
- 0
src/assets/ar-accessories/neuralNets/NN_VERYLIGHT_0.json
文件差异内容过多而无法显示
查看文件


+ 1
- 0
src/assets/ar-accessories/neuralNets/NN_VIEWTOP_0.json
文件差异内容过多而无法显示
查看文件


+ 1
- 0
src/assets/ar-accessories/neuralNets/NN_WIDEANGLES_0.json
文件差异内容过多而无法显示
查看文件


二进制
src/assets/ar-accessories/turban.png 查看文件

之前 之后
宽度: 225  |  高度: 225  |  大小: 22 KiB

+ 328
- 0
vendors/jeelizFaceFilter/JeelizResizer.js 查看文件

@@ -0,0 +1,328 @@
/*
This helper can help for:
* adjusting the canvas resolution to the good size -> this is crucial to
optimize the code because if the canvas is too large,
there are too much pixels to compute => it will be slow

* to mirror horizontally or not the canvas -> if the front camera is used we
need it flipped (mirror effect), while if the rear camera is used we need it not flipped

* to get the best camera resolution (either above the canvas resolution or closer)
to balance between performance and quality
*/
"use strict";

const JeelizResizer = (function(){
// private vars:
let _domCanvas = null,
_whCanvasPx = null,
_isApplyCSS = false,
_resizeAttemptsCounter = 0,
_overSamplingFactor = 1,
_isFullScreen = false,
_timerFullScreen = null,
_callbackResize = null,
_isInvFullscreenWH = false;

const _cameraResolutions = [ // all resolutions should be in landscape mode
[640,480],
[768,480],
[800,600],
[960,640],
[960,720],
[1024,768],
[1280,720],
[1920, 1080]
];
//private functions
function add_CSStransform(domElement, CSS){
const CSStransform = domElement.style.transform;
if (CSStransform.indexOf(CSS) !== -1) return;
domElement.style.transform = CSS + ' ' + CSStransform;
}

// Compute overlap between 2 rectangles A and B
// characterized by their width and their height in pixels
// the rectangles are centered
// return the ratio (pixels overlaped)/(total pixels)
function compute_overlap(whA, whB){
const aspectRatioA = whA[0] / whA[1];
const aspectRatioB = whB[0] / whB[1]; //higher aspectRatio -> more landscape
var whLandscape, whPortrait;
if (aspectRatioA > aspectRatioB){
whLandscape = whA, whPortrait = whB;
} else {
whLandscape = whB, whPortrait = whA;
}

// The overlapped area will be always a rectangle
const areaOverlap = Math.min(whLandscape[0], whPortrait[0]) * Math.min(whLandscape[1], whPortrait[1]);
var areaTotal;
if (whLandscape[0]>=whPortrait[0] && whLandscape[1]>=whPortrait[1]){ //union is a rectangle
areaTotal = whLandscape[0]*whLandscape[1];
} else if (whPortrait[0]>whLandscape[0] && whPortrait[1]>whLandscape[1]){ //union is a rectangle
areaTotal = whPortrait[0]*whPortrait[1];
} else { //union is a cross
areaTotal = whLandscape[0]*whLandscape[1];
areaTotal += (whPortrait[1]-whLandscape[1])*whPortrait[0];
}

return areaOverlap / areaTotal;
} //end compute_overlap()

function update_sizeCanvas(){
const domRect = _domCanvas.getBoundingClientRect();
apply_sizeCanvas(domRect.width, domRect.height);
}

function apply_sizeCanvas(width, height){
_whCanvasPx = [
Math.round(_overSamplingFactor * width),
Math.round(_overSamplingFactor * height)
];

// set canvas resolution:
_domCanvas.setAttribute('width', _whCanvasPx[0]);
_domCanvas.setAttribute('height', _whCanvasPx[1]);

// canvas display size:
if (_isApplyCSS){
_domCanvas.style.width = width.toString() + 'px';
_domCanvas.style.height = height.toString() + 'px';
}
}

function on_windowResize(){
// avoid to resize too often using a timer
// (it can create weird bug with some browsers)
if (_timerFullScreen){
clearTimeout(_timerFullScreen);
}
_timerFullScreen = setTimeout(resize_fullScreen, 50);
}

function resize_canvasToFullScreen(){
const wh = [window['innerWidth'], window['innerHeight']];
if (_isInvFullscreenWH){
wh.reverse();
}
apply_sizeCanvas(wh[0], wh[1]);
}

function resize_fullScreen(){
resize_canvasToFullScreen();
JEELIZFACEFILTER.resize();
_timerFullScreen = null;
if (_callbackResize) {
_callbackResize();
}
}

// public methods:
const that = {
// return true or false if the device is in portrait or landscape mode
// see https://stackoverflow.com/questions/4917664/detect-viewport-orientation-if-orientation-is-portrait-display-alert-message-ad
is_portrait: function(){
try{
if (window['matchMedia']("(orientation: portrait)")['matches']){
return true;
} else {
return false;
}
} catch(e){
return (window['innerHeight'] > window['innerWidth']);
}
},

// check whether the user is using IOS or not
// see https://stackoverflow.com/questions/9038625/detect-if-device-is-ios
check_isIOS: function(){
const isIOS = /iPad|iPhone|iPod/.test(navigator['userAgent']) && !window['MSStream'];
return isIOS;
},

// Should be called only if IOS was detected
// see https://stackoverflow.com/questions/8348139/detect-ios-version-less-than-5-with-javascript
get_IOSVersion: function(){
const v = (navigator['appVersion']).match(/OS (\d+)_(\d+)_?(\d+)?/);
return (v.length > 2) ? [parseInt(v[1], 10), parseInt(v[2], 10), parseInt(v[3] || 0, 10)] : [0, 0, 0];
},

// Check whether the user is using Android or not
// see https://stackoverflow.com/questions/6031412/detect-android-phone-via-javascript-jquery
check_isAndroid: function(){
const ua = navigator['userAgent'].toLowerCase();
return (ua.indexOf('android') !== -1);
},

// Should be called only if Android was detected
// see https://stackoverflow.com/questions/7184573/pick-up-the-android-version-in-the-browser-by-javascript
get_androidVersion: function(){
const ua = navigator['userAgent'].toLowerCase();
const match = ua.match(/android\s([0-9\.]*)/i);
if (!match || match.length<2){
return [0,0,0];
}
const v = match[1].split('.');
return [
parseInt(v[0], 10),
parseInt(v[1], 10),
parseInt(v[2] || 0, 10)
];
},

// to get a video of 480x640 (480 width and 640 height)
// with a mobile phone in portrait mode, the default implementation
// should require a 480x640 video (Chrome, Firefox)
// but bad implementations needs to always request landscape resolutions (so 640x480)
// see https://github.com/jeeliz/jeelizFaceFilter/issues/144
require_flipVideoWHIfPortrait: function(){
// disabled because of https://github.com/jeeliz/jeelizFaceFilter/issues/144
// seems quite a mess though...
/* if (that.check_isIOS()){
//the user is using IOS
const version = that.get_IOSVersion();
if (version[0] >= 13){
if (version[1] <= 1 // IOS 13.0.X
|| (version[1] === 1 && version[2] < 3)){ // IOS 13.1.X with X<3
return false;
}
}
}

if (that.check_isAndroid()){
const version = that.get_androidVersion();
if (version[0] >= 9){ // Android 9+
return false;
}
} */

// normal implementation
return false;
},

// size canvas to the right resolution
// should be called after the page loading
// when the canvas has already the right size
// options:
// - <string> canvasId: id of the canvas
// - <HTMLCanvasElement> canvas: if canvasId is not provided
// - <function> callback: function to launch if there was an error or not
// - <float> overSamplingFactor: facultative. If 1, same resolution than displayed size (default).
// If 2, resolution twice higher than real size
// - <boolean> CSSFlipX: if we should flip the canvas or not. Default: false
// - <boolean> isFullScreen: if we should set the canvas fullscreen. Default: false
// - <function> onResize: function called when the window is resized. Only enabled if isFullScreen = true
// - <boolean> isInvWH: if we should invert width and height for fullscreen mode only. default = false
// - <boolean> isApplyCSS: if we should also apply canvas dimensions as CSS. default = false
size_canvas: function(optionsArg){
const options = Object.assign({
canvasId: 'undefinedCanvasId',
canvas: null,
overSamplingFactor: window.devicePixelRatio || 1,

isFullScreen: false,
isInvWH: false,
CSSFlipX: false,
isApplyCSS: false,
onResize: null,
callback: function(){}
}, optionsArg);

_domCanvas = (options.canvas) ? options.canvas : document.getElementById(options.canvasId);
_isFullScreen = options.isFullScreen;
_isInvFullscreenWH = options.isInvWH;
_isApplyCSS = options.isApplyCSS;
_overSamplingFactor = options.overSamplingFactor;

if (_isFullScreen){
// we are in fullscreen mode
_callbackResize = options.onResize;
resize_canvasToFullScreen();
window.addEventListener('resize', on_windowResize, false);
window.addEventListener('orientationchange', on_windowResize, false);
} else { // not fullscreen mode

// get display size of the canvas:
const domRect = _domCanvas.getBoundingClientRect();
if (domRect.width===0 || domRect.height===0){
console.log('WARNING in JeelizResize.size_canvas(): the canvas has its width or its height null, Retry a bit later...');
if (++_resizeAttemptsCounter > 20){
options.callback('CANNOT_RESIZECANVAS');
return;
}
setTimeout(that.size_canvas.bind(null, options), 50);
return;
}

// do resize canvas:
_resizeAttemptsCounter = 0;
update_sizeCanvas();
}

// flip horizontally if required:
if (options.CSSFlipX){
add_CSStransform(_domCanvas, 'rotateY(180deg)');
}

// compute the best camera resolutions:
const allResolutions = _cameraResolutions.map(function(x){
return x.slice(0)
});

// if we are in portrait mode, the camera is also in portrait mode
// so we need to set all resolutions to portrait mode
if (that.is_portrait() && that.require_flipVideoWHIfPortrait()){
allResolutions.forEach(function(wh){
wh.reverse();
});
}

// sort camera resolutions from the best to the worst:
allResolutions.sort(function(resA, resB){
return compute_overlap(resB, _whCanvasPx) - compute_overlap(resA, _whCanvasPx);
});

// pick the best camera resolution:
const bestCameraResolution = {
'idealWidth': allResolutions[0][0],
'idealHeight': allResolutions[0][1]
};

console.log('INFO in JeelizResizer: bestCameraResolution =', bestCameraResolution);

// launch the callback function after a small interval to let it
// some time to size:
setTimeout(options.callback.bind(null, false, bestCameraResolution), 1);
}, //end size_canvas()

// Should be called if the canvas is resized to update the canvas resolution:
resize_canvas: function(){
if (_isFullScreen){
resize_canvasToFullScreen()
} else {
update_sizeCanvas();
}
},

get_canvasSize: function(){
return _whCanvasPx;
}
}; //end that
return that;
})();

// Export ES6 module:
try {
module.exports = JeelizResizer;
} catch(e){
console.log('JeelizResizer ES6 Module not exported');
window.JeelizResizer = JeelizResizer;
}

+ 445
- 0
vendors/jeelizFaceFilter/JeelizThreeHelper.js 查看文件

@@ -0,0 +1,445 @@
/*
Helper for Three.js
*/

const JeelizThreeHelper = (function(){
// internal settings:
const _settings = {
rotationOffsetX: 0.0, // negative -> look upper. in radians
pivotOffsetYZ: [0.2, 0.6],// YZ of the distance between the center of the cube and the pivot
detectionThreshold: 0.8, // sensibility, between 0 and 1. Less -> more sensitive
detectionHysteresis: 0.02,

//tweakMoveYRotateX: 0,//0.5, // tweak value: move detection window along Y axis when rotate the face around X (look up <-> down)
cameraMinVideoDimFov: 35 // Field of View for the smallest dimension of the video in degrees
};

// private vars:
let _threeRenderer = null,
_threeScene = null,
_threeVideoMesh = null,
_threeVideoTexture = null,
_threeTranslation = null;

let _maxFaces = -1,
_isMultiFaces = false,
_detectCallback = null,
_isVideoTextureReady = false,
_isSeparateThreeCanvas = false,
_faceFilterCv = null,
_videoElement = null,
_isDetected = false,
_scaleW = 1,
_canvasAspectRatio = -1;

const _threeCompositeObjects = [];
let _gl = null,
_glVideoTexture = null,
_glShpCopyCut = null,
_glShpCopyCutVideoMatUniformPointer = null;

let _videoTransformMat2 = null;

// private funcs:
function destroy(){
_isVideoTextureReady = false;
_threeCompositeObjects.splice(0);
if (_threeVideoTexture){
_threeVideoTexture.dispose();
_threeVideoTexture = null;
}
}

function create_threeCompositeObjects(){
for (let i=0; i<_maxFaces; ++i){
// COMPOSITE OBJECT WHICH WILL TRACK A DETECTED FACE
const threeCompositeObject = new THREE.Object3D();
threeCompositeObject.frustumCulled = false;
threeCompositeObject.visible = false;

_threeCompositeObjects.push(threeCompositeObject);
_threeScene.add(threeCompositeObject);
}
}

function create_videoScreen(){
const videoScreenVertexShaderSource = "attribute vec2 position;\n\
uniform mat2 videoTransformMat2;\n\
varying vec2 vUV;\n\
void main(void){\n\
gl_Position = vec4(position, 0., 1.);\n\
vUV = 0.5 + videoTransformMat2 * position;\n\
}";
const videoScreenFragmentShaderSource = "precision lowp float;\n\
uniform sampler2D samplerVideo;\n\
varying vec2 vUV;\n\
void main(void){\n\
gl_FragColor = texture2D(samplerVideo, vUV);\n\
}";

if (_isSeparateThreeCanvas){
const compile_shader = function(source, type, typeString) {
const glShader = _gl.createShader(type);
_gl.shaderSource(glShader, source);
_gl.compileShader(glShader);
if (!_gl.getShaderParameter(glShader, _gl.COMPILE_STATUS)) {
alert("ERROR IN " + typeString + " SHADER: " + _gl.getShaderInfoLog(glShader));
return null;
}
return glShader;
};

const glShaderVertex = compile_shader(videoScreenVertexShaderSource, _gl.VERTEX_SHADER, 'VERTEX');
const glShaderFragment = compile_shader(videoScreenFragmentShaderSource, _gl.FRAGMENT_SHADER, 'FRAGMENT');

_glShpCopyCut = _gl.createProgram();
_gl.attachShader(_glShpCopyCut, glShaderVertex);
_gl.attachShader(_glShpCopyCut, glShaderFragment);

_gl.linkProgram(_glShpCopyCut);
const samplerVideo = _gl.getUniformLocation(_glShpCopyCut, 'samplerVideo');
_glShpCopyCutVideoMatUniformPointer = _gl.getUniformLocation(_glShpCopyCut, 'videoTransformMat2');
return;
}

// init video texture with red:
_threeVideoTexture = new THREE.DataTexture( new Uint8Array([255,0,0]), 1, 1, THREE.RGBFormat);
_threeVideoTexture.needsUpdate = true;

// CREATE THE VIDEO BACKGROUND:
const videoMaterial = new THREE.RawShaderMaterial({
depthWrite: false,
depthTest: false,
vertexShader: videoScreenVertexShaderSource,
fragmentShader: videoScreenFragmentShaderSource,
uniforms:{
samplerVideo: {value: _threeVideoTexture},
videoTransformMat2: {
value: _videoTransformMat2
}
}
});

const videoGeometry = new THREE.BufferGeometry()
const videoScreenCorners = new Float32Array([-1,-1, 1,-1, 1,1, -1,1]);
videoGeometry.addAttribute( 'position', new THREE.BufferAttribute( videoScreenCorners, 2 ) );
videoGeometry.setIndex(new THREE.BufferAttribute(new Uint16Array([0,1,2, 0,2,3]), 1));
_threeVideoMesh = new THREE.Mesh(videoGeometry, videoMaterial);
that.apply_videoTexture(_threeVideoMesh);
_threeVideoMesh.renderOrder = -1000; // render first
_threeVideoMesh.frustumCulled = false;
_threeScene.add(_threeVideoMesh);
} //end create_videoScreen()

function detect(detectState){
_threeCompositeObjects.forEach(function(threeCompositeObject, i){
_isDetected = threeCompositeObject.visible;
const ds = detectState[i];
if (_isDetected && ds.detected < _settings.detectionThreshold-_settings.detectionHysteresis){
// DETECTION LOST
if (_detectCallback) _detectCallback(i, false);
threeCompositeObject.visible = false;
} else if (!_isDetected && ds.detected > _settings.detectionThreshold+_settings.detectionHysteresis){
// FACE DETECTED
if (_detectCallback) _detectCallback(i, true);
threeCompositeObject.visible = true;
}
}); //end loop on all detection slots
}

function update_poses(ds, threeCamera){
// tan( <horizontal FoV> / 2 ):
const halfTanFOVX = Math.tan(threeCamera.aspect * threeCamera.fov * Math.PI/360); //tan(<horizontal FoV>/2), in radians (threeCamera.fov is vertical FoV)

_threeCompositeObjects.forEach(function(threeCompositeObject, i){
if (!threeCompositeObject.visible) return;
const detectState = ds[i];

// tweak Y position depending on rx:
//const tweak = _settings.tweakMoveYRotateX * Math.tan(detectState.rx);
const cz = Math.cos(detectState.rz), sz = Math.sin(detectState.rz);
// relative width of the detection window (1-> whole width of the detection window):
const W = detectState.s * _scaleW;

// distance between the front face of the cube and the camera:
const DFront = 1 / ( 2 * W * halfTanFOVX );
// D is the distance between the center of the unit cube and the camera:
const D = DFront + 0.5;

// coords in 2D of the center of the detection window in the viewport:
const xv = detectState.x * _scaleW;
const yv = detectState.y * _scaleW;

// coords in 3D of the center of the cube (in the view coordinates system):
const z = -D; // minus because view coordinate system Z goes backward
const x = xv * D * halfTanFOVX;
const y = yv * D * halfTanFOVX / _canvasAspectRatio;

// set position before pivot:
threeCompositeObject.position.set(-sz*_settings.pivotOffsetYZ[0], -cz*_settings.pivotOffsetYZ[0], -_settings.pivotOffsetYZ[1]);

// set rotation and apply it to position:
threeCompositeObject.rotation.set(detectState.rx+_settings.rotationOffsetX, detectState.ry, detectState.rz, "ZYX");
threeCompositeObject.position.applyEuler(threeCompositeObject.rotation);

// add translation part:
_threeTranslation.set(x, y+_settings.pivotOffsetYZ[0], z+_settings.pivotOffsetYZ[1]);
threeCompositeObject.position.add(_threeTranslation);
}); //end loop on composite objects
}

//public methods:
const that = {
// launched with the same spec object than callbackReady. set spec.threeCanvasId to the ID of the threeCanvas to be in 2 canvas mode:
init: function(spec, detectCallback){
destroy();

_maxFaces = spec.maxFacesDetected;
_glVideoTexture = spec.videoTexture;
_videoTransformMat2 = spec.videoTransformMat2;
_gl = spec.GL;
_faceFilterCv = spec.canvasElement;
_isMultiFaces = (_maxFaces>1);
_videoElement = spec.videoElement;

// enable 2 canvas mode if necessary:
let threeCanvas = null;
if (spec.threeCanvasId){
_isSeparateThreeCanvas = true;
// adjust the threejs canvas size to the threejs canvas:
threeCanvas = document.getElementById(spec.threeCanvasId);
threeCanvas.setAttribute('width', _faceFilterCv.width);
threeCanvas.setAttribute('height', _faceFilterCv.height);
} else {
threeCanvas = _faceFilterCv;
}

if (typeof(detectCallback) !== 'undefined'){
_detectCallback = detectCallback;
}

// init THREE.JS context:
_threeRenderer = new THREE.WebGLRenderer({
context: (_isSeparateThreeCanvas) ? null : _gl,
canvas: threeCanvas,
alpha: (_isSeparateThreeCanvas || spec.alpha) ? true : false
});

_threeScene = new THREE.Scene();
_threeTranslation = new THREE.Vector3();

create_threeCompositeObjects();
create_videoScreen();

// handle device orientation change:
window.addEventListener('orientationchange', function(){
setTimeout(JEELIZFACEFILTER.resize, 1000);
}, false);
const returnedDict = {
videoMesh: _threeVideoMesh,
renderer: _threeRenderer,
scene: _threeScene
};
if (_isMultiFaces){
returnedDict.faceObjects = _threeCompositeObjects
} else {
returnedDict.faceObject = _threeCompositeObjects[0];
}
return returnedDict;
}, //end that.init()

detect: function(detectState){
const ds = (_isMultiFaces) ? detectState : [detectState];

// update detection states:
detect(ds);
},

get_isDetected: function() {
return _isDetected;
},

render: function(detectState, threeCamera){
const ds = (_isMultiFaces) ? detectState : [detectState];

// update detection states then poses:
detect(ds);
update_poses(ds, threeCamera);

if (_isSeparateThreeCanvas){
// render the video texture on the faceFilter canvas:
_gl.viewport(0, 0, _faceFilterCv.width, _faceFilterCv.height);
_gl.useProgram(_glShpCopyCut);
_gl.uniformMatrix2fv(_glShpCopyCutVideoMatUniformPointer, false, _videoTransformMat2);
_gl.activeTexture(_gl.TEXTURE0);
_gl.bindTexture(_gl.TEXTURE_2D, _glVideoTexture);
_gl.drawElements(_gl.TRIANGLES, 3, _gl.UNSIGNED_SHORT, 0);
} else {
// reinitialize the state of THREE.JS because JEEFACEFILTER have changed stuffs:
// -> can be VERY costly !
_threeRenderer.state.reset();
}

// trigger the render of the THREE.JS SCENE:
_threeRenderer.render(_threeScene, threeCamera);
},

sortFaces: function(bufferGeometry, axis, isInv){ // sort faces long an axis
// Useful when a bufferGeometry has alpha: we should render the last faces first
const axisOffset = {X:0, Y:1, Z:2}[axis.toUpperCase()];
const sortWay = (isInv) ? -1 : 1;

// fill the faces array:
const nFaces = bufferGeometry.index.count/3;
const faces = new Array(nFaces);
for (let i=0; i<nFaces; ++i){
faces[i] = [bufferGeometry.index.array[3*i], bufferGeometry.index.array[3*i+1], bufferGeometry.index.array[3*i+2]];
}

// compute centroids:
const aPos = bufferGeometry.attributes.position.array;
const centroids = faces.map(function(face, faceIndex){
return [
(aPos[3*face[0]]+aPos[3*face[1]]+aPos[3*face[2]])/3, // X
(aPos[3*face[0]+1]+aPos[3*face[1]+1]+aPos[3*face[2]+1])/3, // Y
(aPos[3*face[0]+2]+aPos[3*face[1]+2]+aPos[3*face[2]+2])/3, // Z
face
];
});

// sort centroids:
centroids.sort(function(ca, cb){
return (ca[axisOffset]-cb[axisOffset]) * sortWay;
});

// reorder bufferGeometry faces:
centroids.forEach(function(centroid, centroidIndex){
const face = centroid[3];
bufferGeometry.index.array[3*centroidIndex] = face[0];
bufferGeometry.index.array[3*centroidIndex+1] = face[1];
bufferGeometry.index.array[3*centroidIndex+2] = face[2];
});
}, //end sortFaces

get_threeVideoTexture: function(){
return _threeVideoTexture;
},

apply_videoTexture: function(threeMesh){
if (_isVideoTextureReady){
return;
}
threeMesh.onAfterRender = function(){
// Replace _threeVideoTexture.__webglTexture by the real video texture:
try {
_threeRenderer.properties.update(_threeVideoTexture, '__webglTexture', _glVideoTexture);
_threeVideoTexture.magFilter = THREE.LinearFilter;
_threeVideoTexture.minFilter = THREE.LinearFilter;
_isVideoTextureReady = true;
} catch(e){
console.log('WARNING in JeelizThreeHelper: the glVideoTexture is not fully initialized');
}
delete(threeMesh.onAfterRender);
};
},

// create an occluder, IE a transparent object which writes on the depth buffer:
create_threejsOccluder: function(occluderURL, callback){
const occluderMesh = new THREE.Mesh();
new THREE.BufferGeometryLoader().load(occluderURL, function(occluderGeometry){
const mat = new THREE.ShaderMaterial({
vertexShader: THREE.ShaderLib.basic.vertexShader,
fragmentShader: "precision lowp float;\n void main(void){\n gl_FragColor=vec4(1.,0.,0.,1.);\n }",
uniforms: THREE.ShaderLib.basic.uniforms,
colorWrite: false
});
occluderMesh.renderOrder = -1; //render first
occluderMesh.material = mat;
occluderMesh.geometry = occluderGeometry;
if (typeof(callback)!=='undefined' && callback) callback(occluderMesh);
});
return occluderMesh;
},
set_pivotOffsetYZ: function(pivotOffset) {
_settings.pivotOffsetYZ = pivotOffset;
},

create_camera: function(zNear, zFar){
const threeCamera = new THREE.PerspectiveCamera(1, 1, (zNear) ? zNear : 0.1, (zFar) ? zFar : 100);
that.update_camera(threeCamera);

return threeCamera;
},

update_camera: function(threeCamera){
// compute aspectRatio:
const canvasElement = _threeRenderer.domElement;
const cvw = canvasElement.width;
const cvh = canvasElement.height;
_canvasAspectRatio = cvw / cvh;

// compute vertical field of view:
const vw = _videoElement.videoWidth;
const vh = _videoElement.videoHeight;
const videoAspectRatio = vw / vh;
const fovFactor = (vh > vw) ? (1.0 / videoAspectRatio) : 1.0;
const fov = _settings.cameraMinVideoDimFov * fovFactor;
console.log('INFO in JeelizThreeHelper - update_camera(): Estimated vertical video FoV is', fov);
// compute X and Y offsets in pixels:
let scale = 1.0;
if (_canvasAspectRatio > videoAspectRatio) {
// the canvas is more in landscape format than the video, so we crop top and bottom margins:
scale = cvw / vw;
} else {
// the canvas is more in portrait format than the video, so we crop right and left margins:
scale = cvh / vh;
}
const cvws = vw * scale, cvhs = vh * scale;
const offsetX = (cvws - cvw) / 2.0;
const offsetY = (cvhs - cvh) / 2.0;
_scaleW = cvw / cvws;

// apply parameters:
threeCamera.aspect = _canvasAspectRatio;
threeCamera.fov = fov;
console.log('INFO in JeelizThreeHelper.update_camera(): camera vertical estimated FoV is', fov, 'deg');
threeCamera.setViewOffset(cvws, cvhs, offsetX, offsetY, cvw, cvh);
threeCamera.updateProjectionMatrix();

// update drawing area:
_threeRenderer.setSize(cvw, cvh, false);
_threeRenderer.setViewport(0, 0, cvw, cvh);
}, //end update_camera()

resize: function(w, h, threeCamera){
_threeRenderer.domElement.width = w;
_threeRenderer.domElement.height = h;
JEELIZFACEFILTER.resize();
if (threeCamera){
that.update_camera(threeCamera);
}
}
}
return that;
})();


// Export ES6 module:
try {
module.exports = JeelizThreeHelper;
} catch(e){
console.log('JeelizThreeHelper ES6 Module not exported');
window.JeelizThreeHelper = JeelizThreeHelper;
}

+ 178
- 0
vendors/jeelizFaceFilter/jeelizFaceFilter.js 查看文件

@@ -0,0 +1,178 @@
/**
* Jeeliz Face Filter - https://github.com/jeeliz/jeelizFaceFilter
*
* Copyright 2018 Jeeliz ( https://jeeliz.com )
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

var JEELIZFACEFILTER=(function(){window.JEELIZFACEFILTERGEN=function(){function Jb(a){var c=null,d=null,e=null,f=0;this.A=function(m){this.df(m.gb);e.de({ec:m.ec,bc:m.bc})};this.Ae=function(m){return c[m]};this.df=function(m){var n=null;f=m.length;c=m.map(function(p,g){p=Object.assign({},p,{index:g,parent:this,nb:n,Ke:g===f-1});return n=g=0===g?Kb.instance(p):Lb.instance(p)});d=c[0];e=c[f-1];c.forEach(function(p,g){0!==g&&p.Ve()})};this.V=function(m){var n=m;c.forEach(function(p){n=p.V(n,!1)});return n};this.ze=function(){return d.F()};
this.Nb=function(){return e.Be()};this.Wc=function(){return e.Wc()};this.m=function(){c&&(c.forEach(function(m){m.m()}),e=d=c=null,f=0)};"undefined"!==typeof a&&this.A(a)}function db(a,c){var d=c%8;return a[(c-d)/8]>>7-d&1}function Mb(a){var c=JSON.parse(a);a=c.ne;var d=c.nf,e=c.n;var f="undefined"===typeof btoa?Buffer.from(c.data,"base64").toString("latin1"):atob(c.data);var m=f.length;c=new Uint8Array(m);for(var n=0;n<m;++n)c[n]=f.charCodeAt(n);f=new Float32Array(e);m=new Float32Array(d);n=a+d+
1;for(var p=0;p<e;++p){for(var g=n*p,v=0===db(c,g)?1:-1,A=g+1,r=1,l=0,B=A+a-1;B>=A;--B)l+=r*db(c,B),r*=2;A=l;g=g+1+a;r=m.length;l=0;for(B=g;B<g+r;++B)m[l]=db(c,B,!0),++l;for(r=g=0;r<d;++r)g+=m[r]*Math.pow(2,-r-1);f[p]=0===g&&0===A?0:v*(1+g)*Math.pow(2,1+A-Math.pow(2,a-1))}return f}function Ya(){return-1!==[fa.ready,fa.play,fa.pause].indexOf(ma)}function eb(){if(ma===fa.play)return!1;ma=fa.play;Ma.stop();rb(0)}function sb(){if(ma!==fa.play)return!1;Ma.stop();ma=fa.pause;return!0}function Fa(a,c,d,
e,f){a=4*(3*c+a)+d;return e+(X.buffer[a]/255+X.buffer[a+12]/65025)*(f-e)}function fb(){b.pixelStorei(b.UNPACK_FLIP_Y_WEBGL,!1);ua.da();U.reset();Y.reset();z.R();z.Kc();b.disable(b.DEPTH_TEST);b.disable(b.BLEND);U.Ea();z.xa()}function tb(){ua.P();b.viewport(0,0,3,2*L.o);z.set("s52");X.za.g(0);U.l(!1,!1);return ba.pb(0,0,3,2*L.o,X.buffer)}function rb(){ma!==fa.pause&&(z.Kc(),U.reset(),U.Ea(),b.disable(b.DEPTH_TEST),b.pixelStorei(b.UNPACK_FLIP_Y_WEBGL,!1),z.xa(),Z.fe?tb().then(function(){ub();vb()}).catch(gb):
(ub(),tb().then(vb).catch(gb)))}function ub(){ua.da();if(!y.bb)if(y.ab)y.element.needsUpdate&&(y.N.wf(y.element.arrayBuffer),y.element.needsUpdate=!1);else{var a=y.element.currentTime,c=a-y.ob;0>c&&(y.ob=a);1E3*c<Z.yf||(y.ob+=c,y.N.refresh())}a=qa.Xc();if(L.W.length>a)L.W.splice(0,L.W.length-a);else for(;L.W.length<a;)L.W.push(0);if(1!==L.o)if(pa.every(hb)){for(var d=0,e=c=0;e<pa.length;++e)pa[e].detected>d&&(d=pa[e].detected,c=0);for(d=0;d<a;++d)L.W[d]=c}else{c=L.md;d=0;for(e=!1;d<a;++d){if(hb(pa[c]))if(e){do++c===
L.o&&(c=0);while(hb(pa[c]))}else e=!0;L.W[d]=c++;c>=L.o&&(c=0)}L.md=c}for(a=0;a<qa.Xc();++a)L.ma=L.W[a],L.ac=(.5+L.ma)/L.o,L.hd=L.W.lastIndexOf(L.ma)===a,z.set("s54"),c=pa[L.ma],z.H("u41",1+Na.ic*(Math.cos(c.ry)-1)),O.ra&&z.H("u40",c.rz),1!==L.o&&z.H("u39",L.ac),aa.va.aa(),y.N.g(0),X.za.g(1),U.l(!1,!1),aa.va.g(0),Oa.V(aa.va);qa.rf()}function vb(){for(var a=0;a<L.o;++a)if(-1!==L.W.indexOf(a)){var c=a,d=Sa[c],e=[c],f=pa[c],m=ib[c],n=2*c;d.Sa=Fa(1,n,3,0,1);f.detected=va.X(f.detected,d.Sa,Z.Od);if(d.Sa<
Z.od)O.ra&&(f.rz=0,f.ry=0);else{var p=X.Ka;d.x=Fa(0,n,1,-1,1);d.y=Fa(0,n,2,-1,1);d.$=Fa(0,n,3,0,1);d.fc=Fa(1,n,0,-p[0],p[0]);d.hc=Fa(1,n,1,-p[1],p[1]);d.La=Fa(1,n,2,-p[2],p[2]);for(p=0;p<X.Y;++p)d.Rc[p]=X.Ia[p](Fa(2,n,p,0,1));e.Hb=d.x-f.xRaw;e.Ib=d.y-f.yRaw;e.Gb=d.$-f.sRaw;e.Db=d.fc-f.rx;e.Eb=d.hc-f.ry;e.Fb=O.ra?d.La:d.La-f.rz;n=qa.ue();e=(1-Za.hb(wa.translationFactorRange[0],wa.translationFactorRange[1],Math.sqrt(e.Hb*e.Hb+e.Ib*e.Ib+e.Gb*e.Gb)/n))*(1-Za.hb(wa.rotationFactorRange[0],wa.rotationFactorRange[1],
Math.sqrt(e.Db*e.Db+e.Eb*e.Eb+e.Fb*e.Fb)/n))*Za.hb(wa.qualityFactorRange[0],wa.qualityFactorRange[1],d.Sa);c=m[++jb[c]%m.length]=e;for(n=0;n<m.length;++n)c=Math.min(c,m[n]);c=Math.max(.5,c);e=Math.min(c,e);m=va.X(wa.alphaRange[1],wa.alphaRange[0],Math.pow(e,Z.Qd));f.xRaw=va.X(f.xRaw,d.x,m);f.yRaw=va.X(f.yRaw,d.y,m);f.sRaw=va.X(f.sRaw,d.$,m);f.rx=va.X(f.rx,d.fc,m);f.ry=va.X(f.ry,d.hc,m);f.rz=O.ra?f.rz+m*d.La:va.X(f.rz,d.La,m);c=f.sRaw*Na.Cb*Math.sin(f.ry);e=Math.sin(f.rz)*c/Pa;f.x=f.xRaw+Math.cos(f.rz)*
c;f.y=f.yRaw+e;f.s=f.sRaw;m=Math.max(m,Z.Pd);for(c=0;c<X.Y;++c)f.expressions[c]=va.X(f.expressions[c],d.Rc[c],m);++d.kb}}ua.uf();ua.reset();Y.reset();b.enable(b.DEPTH_TEST);O.Ra&&(1===L.o?O.Ra(pa[0]):O.Ra(pa));b.disable(b.BLEND);gb()}function gb(){ma===fa.play&&Ma.af(rb)}function wb(){aa.va=Y.instance({isPot:!0,isFloat:!1,width:Oa.ze()});for(var a=Z.Gd,c=L.o,d=new Float32Array([0,.5,.5,0,0,0,0,0,0,0,0,0]),e=new Float32Array(d.length*L.o),f=0,m;f<L.o;++f)for(m=0;m<d.length;++m)e[f*d.length+m]=d[m];
X.za=Nb.instance({width:a,height:c,isFloat:!0,isPot:!1,array:e})}function Ob(){function a(c){for(var d=[],e=0;e<L.o;++e)d.push(JSON.parse(JSON.stringify(c)));return d}X.buffer=new Uint8Array(8*Z.Gd*L.o);Sa=a({Sa:0,x:0,y:0,$:1,fc:0,hc:0,La:0,Rc:new Float32Array(X.Y),kb:0});pa=a({detected:0,x:0,y:0,s:1,xRaw:0,yRaw:0,sRaw:1,rx:0,ry:0,rz:0,expressions:new Float32Array(X.Y)});a({Hb:0,Ib:0,Gb:0,Db:0,Eb:0,Fb:0})}function kb(){z.T("s54",[{type:"1i",name:"u1",value:0},{type:"1i",name:"u37",value:1},{type:"2f",
name:"u38",value:aa.G},{type:"1f",name:"u39",value:.5},{type:"1f",name:"u40",value:0}]);z.T("s55",[{type:"1i",name:"u42",value:0},{type:"1i",name:"u37",value:1},{type:"1f",name:"u45",value:Z.sf},{type:"1f",name:"u46",value:oa.threshold},{type:"3f",name:"u44",value:[X.O[0]*aa.G[0],X.O[1]*aa.G[1],X.O[2]]},{type:"1f",name:"u39",value:.5},{type:"1f",name:"u47",value:1},{type:"1f",name:"u40",value:0}]);var a=[{type:"1i",name:"u42",value:0}];z.T("s56",a);z.T("s57",a);z.T("s52",[{type:"1i",name:"u37",value:0},
{type:"1f",name:"u50",value:aa.G[0]},{type:"2f",name:"u49",value:[0,.5/L.o]}])}function lb(){aa.G[0]=1;aa.G[1]=aa.D/aa.M;xb.A({mb:oa.overlapFactors,sd:oa.nScaleLevels,D:aa.D,M:aa.M,Bd:oa.scale0Factor,O:X.O,Cd:oa.scanCenterFirst})}function Pb(a){if(O.Aa)yb("string"===typeof O.Aa?JSON.parse(O.Aa):O.Aa,a);else{var c=O.vc;"JSON"!==c.toUpperCase().split(".").pop()&&(c+=Z.neuralNetworkPath);zb.get(c,function(d){d=JSON.parse(d);yb(d,a)})}}function yb(a,c){if(a.exportData){var d=a.exportData;d.rotationEulerAnglesFactors&&
(X.Ka=d.rotationEulerAnglesFactors);d.translationScalingFactors&&(X.O=d.translationScalingFactors);"undefined"!==typeof d.nExpressions&&(X.Y=d.nExpressions);Na.ic=.4;Na.Cb=.7;"undefined"!==typeof d.fgScaleXFactor&&(Na.ic=d.fgScaleXFactor);"undefined"!==typeof d.fgDisplaceXFactor&&(Na.Cb=d.fgDisplaceXFactor)}X.Y||(X.Y=Z.rd);if(!X.Ia)for(X.Ia=[],d=0;d<X.Y;++d)X.Ia.push(Z.oe);c(a)}function Qb(){if(Qa.A({zb:O.ea,width:aa.D,height:aa.M,debug:!1,td:function(){Ha("GLCONTEXT_LOST")},antialias:O.antialias,
premultipliedAlpha:!0}))return!0;Ha("GL_INCOMPATIBLE");return!1}function hb(a){return a.detected<=Z.od}function Ab(a,c,d,e){return d>a?Math.max(0,a+c/2-(d-e/2)):Math.max(0,d+e/2-(a-c/2))}function Rb(){return Sa.some(function(a,c){if(c===L.ma)return!1;c=Sa[L.ma];if(c.kb>a.kb||3>a.kb||Ab(c.x,c.$,a.x,a.$)<Z.pd*c.$)return!1;var d=aa.D/aa.M;return Ab(c.y,c.$*d,a.y,a.$*d)>Z.pd*c.$*d})}function Sb(){var a=L.ma;X.za.cf(1);1!==L.o&&(b.viewport(0,0,3,L.o),z.set("s0"),z.Fd("u1",1),U.l(!1,!1),z.Fd("u1",0));b.viewport(0,
a,1,1);z.set("s55");O.ra&&z.H("u40",pa[a].rz);1!==L.o&&z.H("u39",L.ac);if(1<L.o){var c=Rb()?0:1;z.H("u47",c)}z.hf("u43",xb.get());U.l(!1,!1);L.hd&&(b.viewport(1,a,1,1),z.set("s56"),U.l(!1,!1),b.viewport(2,a,1,1),z.set("s57"),U.l(!1,!1))}function Bb(){y.N&&y.N.remove();y.ab=y.element.isFakeVideo?!0:!1;if(y.ab){var a=Cb();a={isFlipY:!1,array:y.element.arrayBuffer,width:a.w,height:a.ua,isKeepArray:!0}}else a={I:y.element};y.nc=Y.instance(Object.assign({isPot:!1,isLinear:!0,isFloat:!1},a));y.N=y.nc}function Ia(){var a=
[{type:"mat2",name:"u36",value:y.v}];z.T("s53",[{type:"1i",name:"u1",value:0}].concat(a));z.T("s54",a)}function Ja(){y.L[0]=.5;y.L[1]=.5;var a=y.G[1]/y.G[0];Pa=Qa.U()/Qa.F();90===Math.abs(na.rotate)&&(a=1/a);a>Pa?y.L[1]*=Pa/a:y.L[0]*=a/Pa;z.T("s55",[{name:"u48",type:"1f",value:Pa}]);y.v[0]=0;y.v[1]=0;y.v[2]=0;y.v[3]=0;switch(na.rotate){case 0:y.v[0]=y.L[0];y.v[3]=y.L[1];break;case 180:y.v[0]=-y.L[0];y.v[3]=-y.L[1];break;case 90:y.v[1]=y.L[0];y.v[2]=-y.L[1];break;case -90:y.v[1]=-y.L[0],y.v[2]=y.L[1]}na.flipX&&
(y.v[0]*=-1,y.v[2]*=-1);y.bb||(y.v[1]*=-1,y.v[3]*=-1)}function Cb(){var a={w:y.element.videoWidth||y.element.width,ua:y.element.videoHeight||y.element.height};if(!a.w||!a.ua||4>a.w||4>a.ua)throw Error("INVALID VIDEO DIMENSIONS - width = "+a.w+" height = "+a.ua);return a}function mb(){var a=Cb(),c=y.G[0]!==a.w||y.G[1]!==a.ua;c&&(y.G[0]=a.w,y.G[1]=a.ua);return c}function $a(a,c){if(ma===fa.error)return!1;y.element=a;mb();c&&c();return!0}function Db(a,c,d){a&&a();y.Ga={video:{facingMode:{exact:na.facingMode},
width:{min:na.minWidth,max:na.maxWidth,ideal:na.idealWidth},height:{min:na.minHeight,max:na.maxHeight,ideal:na.idealHeight}},audio:!1};W.xc(y.Ga,na.deviceId);W.get(y.element?y.element:W.De(),function(e){c&&c(e);d(e)},function(){Ha("WEBCAM_UNAVAILABLE")},y.Ga)}function Ha(a){ma!==fa.error&&(ma=fa.error,O.Fa&&O.Fa(a))}var va={tg:function(a){return Math.ceil(Math.log2(a))},Mg:function(a){return Math.log2(a)},Ig:function(a){return 0===Math.log2(a)%1},If:function(a){var c=[0,0,0,0];a.forEach(function(d){c[0]+=
d[0];c[1]+=d[1];c[2]+=d[2];c[3]+=d[3]});return c},Jf:function(a,c,d){return Math.min(Math.max(a,c),d)},Mf:function(a){return a*Math.PI/180},Rg:function(a,c){c=Math.pow(10,c);return Math.round(a*c)/c},Sg:function(a){return Math.round(1E6*a)/1E6},ug:function(a,c){return(100*a/c).toFixed(3)},X:function(a,c,d){return a*(1-d)+c*d},je:function(a,c){return va.ae(a-c)},ae:function(a){for(;a>Math.PI;)a-=2*Math.PI;for(;a<=-Math.PI;)a+=2*Math.PI;return a},Pf:function(a,c){return Math.abs(va.je(a,c))},zf:function(a,
c){return Math.atan2(Math.sin(a)+Math.sin(c),Math.cos(a)+Math.cos(c))}},zb={get:function(a,c,d){var e=new XMLHttpRequest;e.open("GET",a,!0);e.withCredentials=!1;e.onreadystatechange=function(){4===e.readyState&&(200===e.status||0===e.status?c(e.responseText):"undefined"!==typeof d&&d(e.status))};e.send()},qg:function(a,c){zb.get(a,function(d){c(JSON.parse(d))})},Og:function(a,c,d){var e=new XMLHttpRequest;e.open("POST",a,!0);e.setRequestHeader("Content-type","application/x-www-form-urlencoded");e.onreadystatechange=
function(){4!==e.readyState||200!==e.status&&0!==e.status||d(e.responseText)};e.send(c)},fg:function(a,c){var d=new XMLHttpRequest;d.open("POST",a,!0);d.responseType="arraybuffer";d.onload=function(){c(d.response)};d.send()}},Tb={create:function(a,c){for(var d=Array(c),e=0;e<c;++e)d[e]=a;return d},Nf:function(a,c){for(var d=0;d<a.length;++d)c[d]=a[d]},clone:function(a){for(var c=Array(a.length),d=0;d<a.length;++d)c[d]=a[d];return c},Vg:function(a,c,d){a.forEach(function(e,f){c[f]=e*d})},fh:function(a){for(var c=
a.length-1;0<c;--c){var d=Math.floor(Math.random()*(c+1)),e=a[c];a[c]=a[d];a[d]=e}},qf:function(a){return Array.isArray(a)||a.constructor===Float32Array||a.constructor===Uint8Array}},nb={Ab:function(a,c){if(0===c||"object"!==typeof a)return a;a=Object.assign({},a);c=void 0===c||-1===c?-1:c-1;for(var d in a)a[d]=nb.Ab(a[d],c);return a}},Za={gh:function(a,c,d){a=Math.min(Math.max((d-a)/(c-a),0),1);return a*a*(3-2*a)},hb:function(a,c,d){return Math.min(Math.max((d-a)/(c-a),0),1)},$f:function(a,c,d,e){return Math.pow(Math.min(Math.max((e-
a)/(c-a),0),1),d)},kh:function(){return 0},Ng:function(){return 1},Lg:function(a){return a},Xf:function(a){return a*a},bg:function(a){return a*(2-a)},Uf:function(a){return.5>a?2*a*a:-1+(4-2*a)*a},Sf:function(a){return a*a*a},ag:function(a){return--a*a*a+1},Tf:function(a){return.5>a?4*a*a*a:(a-1)*(2*a-2)*(2*a-2)+1},Yf:function(a){return a*a*a*a},cg:function(a){return 1- --a*a*a*a},Vf:function(a){return.5>a?8*a*a*a*a:1-8*--a*a*a*a},Zf:function(a){return a*a*a*a*a},dg:function(a){return 1+--a*a*a*a*
a},Wf:function(a){return.5>a?16*a*a*a*a*a:1+16*--a*a*a*a*a}},Ub={qe:function(a,c,d){switch(a){case "relu":return d+"=max(vec4(0.,0.,0.,0.),"+c+");";case "elu":return d+"=mix(exp(-abs("+c+"))-vec4(1.,1.,1.,1.),"+c+",step(0.,"+c+"));";case "elu01":return d+"=mix(0.1*exp(-abs("+c+"))-vec4(0.1,0.1,0.1,0.1),"+c+",step(0.,"+c+"));";case "arctan":return d+"=atan(3.14159265359*texture2D(u0,vUV))/3.14159265359;";case "copy":return"";default:return!1}}},z=function(){function a(u,t,D){t=u.createShader(t);u.shaderSource(t,
D);u.compileShader(t);return u.getShaderParameter(t,u.COMPILE_STATUS)?t:!1}function c(u,t,D){t=a(u,u.VERTEX_SHADER,t);D=a(u,u.FRAGMENT_SHADER,D);u===b&&n.push(t,D);var K=u.createProgram();u.attachShader(K,t);u.attachShader(K,D);u.linkProgram(K);return K}function d(u,t){t.C=t.C?!0:!1;if(!t.C){void 0===t.qa&&(t.qa="precision lowp float;attribute vec2 a0;varying vec2 vv0;void main(){gl_Position=vec4(a0,0.,1.),vv0=a0*.5+vec2(.5,.5);}");void 0===t.Pa&&(t.Pa=["a0"]);void 0===t.Ca&&(t.Ca=[2]);if(void 0===
t.precision||"highp"===t.precision)t.precision=r;t.id=v++;void 0!==t.Dd&&(t.Dd.forEach(function(K,P){t.h=t.h.replace(K,t.qb[P])}),t.Dd.splice(0));t.uc=0;t.Ca.forEach(function(K){t.uc+=4*K});t.oa=c(u,t.qa,"precision "+t.precision+" float;\n"+t.h);t.B={};t.i.forEach(function(K){t.B[K]=u.getUniformLocation(t.oa,K)});t.attributes={};t.Da=[];t.Pa.forEach(function(K){var P=u.getAttribLocation(t.oa,K);t.attributes[K]=P;t.Da.push(P)});if(t.j){u.useProgram(t.oa);g=t;p=t.id;for(var D in t.j)u.uniform1i(t.B[D],
t.j[D])}t.na=!0}}function e(u){xa.gf(J);p!==u.id&&(J.R(),p=u.id,g=u,b.useProgram(u.oa),u.Da.forEach(function(t){0!==t&&b.enableVertexAttribArray(t)}))}function f(u,t,D){d(u,t,D);u.useProgram(t.oa);u.enableVertexAttribArray(0);p=-1;return g=t}function m(){return{h:"uniform sampler2D u1;varying vec2 vv0;void main(){gl_FragColor=texture2D(u1,vv0);}",i:["u1"],j:{u1:0}}}var n=[],p=-1,g=null,v=0,A=!1,r="highp",l=["u1"],B=["u0"],w={u1:0},k={u0:0},q={u1:0,u2:1},H={u3:0},M={s0:m(),s1:{h:"uniform sampler2D u1;varying vec2 vv0;void main(){gl_FragColor=texture2D(u1,vv0);}",
i:l,j:w,precision:"lowp"},s2:{h:"uniform sampler2D u1,u2;varying vec2 vv0;void main(){vec4 a=texture2D(u2,vv0),b=texture2D(u1,vv0);gl_FragColor=a*b;}",i:["u1","u2"],j:q},s3:{h:"uniform sampler2D u1;varying vec2 vv0;const vec4 f=vec4(1.,1.,1.,1.);void main(){vec4 a=texture2D(u1,vv0);gl_FragColor=a.r*f;}",i:l,j:w},s4:{h:"uniform sampler2D u1,u2;varying vec2 vv0;const vec4 f=vec4(1.,1.,1.,1.);void main(){vec4 a=texture2D(u2,vv0),b=texture2D(u1,vv0);gl_FragColor=a.a*b.r*f;}",i:["u1","u2"],j:q},s5:{h:"uniform sampler2D u1;varying vec2 vv0;void main(){gl_FragColor=texture2D(u1,vec2(1.-vv0.x,vv0.y));}",
i:l,j:w},s6:{h:"uniform sampler2D u1;varying vec2 vv0;void main(){gl_FragColor=texture2D(u1,vec2(vv0.x,1.-vv0.y));}",i:l,j:w},s7:{h:"uniform sampler2D u0;uniform float u4;varying vec2 vv0;void main(){vec4 a=texture2D(u0,vv0);gl_FragColor=a*u4;}",i:["u0","u4"],j:k},s8:{h:"uniform sampler2D u0;uniform float u4;varying vec2 vv0;const vec4 f=vec4(.25,.25,.25,.25),g=vec4(1.,1.,1.,1.);void main(){vec4 a=texture2D(u0,vv0);float b=dot(a*u4,f);gl_FragColor=b*g;}",i:["u0","u4"],j:k},s9:{h:"uniform sampler2D u1;varying vec2 vv0;const vec4 e=vec4(1.,1.,1.,1.);void main(){float a=.25*dot(e,texture2D(u1,vv0));gl_FragColor=a*e;}",
i:l,j:w},s10:{h:"uniform sampler2D u1,u5;uniform float u6;const vec4 f=vec4(1.,1.,1.,1.);varying vec2 vv0;void main(){vec4 a=texture2D(u1,vv0),b=texture2D(u5,vv0);gl_FragColor=mix(b,a,u6*f);}",i:["u1","u5","u6"],j:{u1:0,u5:1}},s11:{h:"uniform sampler2D u1;uniform vec2 u7;varying vec2 vv0;void main(){gl_FragColor=.25*(texture2D(u1,vv0+u7)+texture2D(u1,vv0+u7*vec2(1.,-1.))+texture2D(u1,vv0+u7*vec2(-1.,-1.))+texture2D(u1,vv0+u7*vec2(-1.,1.)));}",i:["u1","u7"],j:w},s12:{h:"uniform sampler2D u1;uniform vec4 u8;varying vec2 vv0;float g(float a,float b){a=floor(a)+.5;return floor(a/exp2(b));}float h(float a,float b){return floor(a*exp2(b)+.5);}float i(float a,float b){return mod(a,h(1.,b));}float e(float c,float a,float b){a=floor(a+.5),b=floor(b+.5);return i(g(c,a),b-a);}vec4 j(float a){if(a==0.)return vec4(0.,0.,0.,0.);float k=128.*step(a,0.);a=abs(a);float c=floor(log2(a)),l=c+127.,b=(a/exp2(c)-1.)*8388608.,d=l/2.,m=fract(d)*2.,n=floor(d),o=e(b,0.,8.),p=e(b,8.,16.),q=m*128.+e(b,16.,23.),r=k+n;return vec4(o,p,q,r)/255.;}void main(){float a=dot(texture2D(u1,vv0),u8);gl_FragColor=j(a);}",
i:["u1","u8"],j:w},s13:{h:"uniform sampler2D u0;varying vec2 vv0;const vec4 e=vec4(1.,1.,1.,1.);void main(){vec4 a=texture2D(u0,vv0),b=e/(e+exp(-a));gl_FragColor=b;}",i:B,j:k,C:!0},s14:{h:"uniform sampler2D u0;varying vec2 vv0;const vec4 f=vec4(0.,0.,0.,0.);void main(){vec4 a=texture2D(u0,vv0);gl_FragColor=max(f,a);}",i:B,j:k},s15:{h:"uniform sampler2D u0;varying vec2 vv0;const vec4 f=vec4(1.,1.,1.,1.);void main(){vec4 a=texture2D(u0,vv0);gl_FragColor=mix(exp(-abs(a))-f,a,step(0.,a));}",i:B,j:k},
s16:{h:"uniform sampler2D u0;varying vec2 vv0;const vec4 f=vec4(1.,1.,1.,1.);void main(){vec4 a=texture2D(u0,vv0),b=exp(-abs(a))-f;gl_FragColor=mix(.1*b,a,step(0.,a));}",i:B,j:k},s17:{h:"uniform sampler2D u0,u6,u9;varying vec2 vv0;const vec4 f=vec4(1.,1.,1.,1.);void main(){vec4 a=texture2D(u0,vv0),c=texture2D(u6,vv0),d=texture2D(u9,vv0),b=a/d;gl_FragColor=c*mix(exp(-abs(b))-f,b,step(0.,a));}",i:["u0","u6","u9"],j:{u0:0,u6:1,u9:2},C:!0},s18:{h:"uniform sampler2D u0;const float e=3.141593;varying vec2 vv0;void main(){gl_FragColor=atan(e*texture2D(u0,vv0))/e;}",
i:B,j:k},s19:{h:"uniform sampler2D u0;varying vec2 vv0;const vec4 f=vec4(1.,1.,1.,1.);void main(){vec4 a=texture2D(u0,vv0),b=log(f+a);gl_FragColor=b;}",i:B,j:k,C:!0},s20:{h:"uniform sampler2D u0,u10;uniform float u11;const vec2 e=vec2(.5,.5);const float f=1e-5;const vec4 g=vec4(1.,1.,1.,1.),i=vec4(0.,0.,0.,0.);varying vec2 vv0;void main(){vec4 a=texture2D(u10,e);float b=u11*u11;vec4 c=max(b*a,f*g);gl_FragColor=texture2D(u0,vv0)/c;}",i:["u0","u10","u11"],j:{u0:0,u10:1},C:!0},s21:{h:"uniform sampler2D u1;uniform vec2 u12;varying vec2 vv0;void main(){float a=u12.x*u12.y;vec2 b=floor(vv0*a)/a,c=fract(vv0*a),d=floor(b*u12.y),f=floor(u12.x*fract(b*u12.y)),g=(f*u12.y+d)/a;gl_FragColor=texture2D(u1,g+c/a);}",
i:["u1","u12"],j:w},s22:{h:"uniform sampler2D u13,u14,u15;varying vec2 vv0;void main(){vec4 a=texture2D(u15,vv0);vec2 b=a.rg,c=a.ba;vec4 d=texture2D(u13,b),f=texture2D(u14,c);gl_FragColor=d*f;}",i:["u13","u14","u15"],j:{u14:0,u13:1,u15:2},C:!0},s23:{h:"uniform float u16;uniform sampler2D u13,u14;varying vec2 vv0;void main(){vec2 a=fract(vv0*u16);vec4 b=texture2D(u13,vv0),c=texture2D(u14,a);gl_FragColor=b*c;}",i:["u14","u13","u16"],j:{u14:0,u13:1}},s24:{h:"uniform float u16;uniform sampler2D u13,u14,u17,u18,u19,u20;varying vec2 vv0;const vec4 e=vec4(1.,1.,1.,1.),g=vec4(1e-3,1e-3,1e-3,1e-3);void main(){vec2 h=vv0*u16,l=floor(h),c=h-l;vec4 m=texture2D(u13,vv0),d=texture2D(u14,c),a=texture2D(u20,vv0);a=a*255.;vec4 n=texture2D(u17,c),o=texture2D(u18,c),p=texture2D(u19,c),i=step(-g,-a),b=e-i,j=b*step(-e-g,-a);b*=e-j;vec4 k=b*step(-2.*e-g,-a);b*=e-k;vec4 q=b;d=i*d+j*n+k*o+q*p,gl_FragColor=m*d;}",
i:"u13 u14 u16 u20 u17 u18 u19".split(" "),j:{u14:0,u13:1,u20:3,u17:4,u18:5,u19:6},C:!0},s25:{h:"uniform sampler2D u13,u14,u21;uniform float u16,u22,u23,u24;varying vec2 vv0;const vec2 j=vec2(1.,1.);void main(){vec2 a=floor(u22*vv0),b=u22*vv0-a;float c=u16/u22;vec2 d=floor(b*c),f=b*c-d,g=(a+f)/u22;float k=u22*u24/u16;vec2 l=k*d,h=(l+f*u23)/u24,i=step(h,j);vec4 m=texture2D(u13,g),n=texture2D(u14,h),o=m*n*i.x*i.y,p=texture2D(u21,g);gl_FragColor=o*u23*u23+p;}",i:"u13 u14 u16 u22 u23 u24 u21".split(" "),
j:{u14:0,u13:1,u21:2}},s26:{h:"uniform sampler2D u13,u14;varying vec2 vv0;void main(){vec4 a=texture2D(u13,vv0),b=texture2D(u14,vv0);gl_FragColor=a*b;}",i:["u13","u14"],j:{u14:0,u13:1},C:!0},s27:{h:"uniform sampler2D u1,u21;uniform float u25;varying vec2 vv0;void main(){gl_FragColor=texture2D(u21,vv0)+u25*texture2D(u1,vv0);}",i:["u1","u21","u25"],j:{u1:0,u21:1}},s28:{h:"varying vec2 vv0;uniform sampler2D u1;const vec4 f=vec4(1.,1.,1.,1.),g=vec4(.299,.587,.114,0.);void main(){vec4 a=texture2D(u1,vv0);gl_FragColor=dot(a,g)*f;}",
i:l,j:w,precision:"lowp"},s29:{h:"varying vec2 vv0;uniform sampler2D u1;uniform float u26;const vec3 f=vec3(.299,.587,.114);void main(){vec3 a=texture2D(u1,vv0).rgb,b=texture2D(u1,vv0+vec2(0.,u26)).rgb,c=texture2D(u1,vv0+vec2(u26,u26)).rgb,d=texture2D(u1,vv0+vec2(u26,0.)).rgb;gl_FragColor=vec4(dot(a,f),dot(b,f),dot(c,f),dot(d,f));}",i:["u1","u26"],j:w,precision:"lowp"},s30:{h:"varying vec2 vv0;uniform sampler2D u1;uniform float u26;const vec3 f=vec3(.299,.587,.114);void main(){vec3 a=texture2D(u1,vv0).rgb,b=texture2D(u1,vv0+vec2(0.,u26)).rgb,c=texture2D(u1,vv0+vec2(u26,u26)).rgb,d=texture2D(u1,vv0+vec2(u26,0.)).rgb;gl_FragColor=vec4(a.r,b.g,c.b,dot(d,f));}",
i:["u1","u26"],j:w,precision:"lowp"},s31:{h:"varying vec2 vv0;uniform sampler2D u1,u2;uniform float u27;const vec4 f=vec4(1.,1.,1.,1.);void main(){vec4 a=vec4(0.);a-=texture2D(u1,vec2(vv0.x-u27,vv0.y-u27))*1.,a-=texture2D(u1,vec2(vv0.x-u27,vv0.y))*2.,a-=texture2D(u1,vec2(vv0.x-u27,vv0.y+u27))*1.,a+=texture2D(u1,vec2(vv0.x+u27,vv0.y-u27))*1.,a+=texture2D(u1,vec2(vv0.x+u27,vv0.y))*2.,a+=texture2D(u1,vec2(vv0.x+u27,vv0.y+u27))*1.;vec4 b=vec4(0.);b-=texture2D(u1,vec2(vv0.x-u27,vv0.y-u27))*1.,b-=texture2D(u1,vec2(vv0.x,vv0.y-u27))*2.,b-=texture2D(u1,vec2(vv0.x+u27,vv0.y-u27))*1.,b+=texture2D(u1,vec2(vv0.x-u27,vv0.y+u27))*1.,b+=texture2D(u1,vec2(vv0.x,vv0.y+u27))*2.,b+=texture2D(u1,vec2(vv0.x+u27,vv0.y+u27))*1.;vec3 c=sqrt(a.rgb*a.rgb+b.rgb*b.rgb);vec4 e=vec4(c,texture2D(u1,vv0).a),g=texture2D(u2,vv0);gl_FragColor=g.a*e.r*f;}",
i:["u1","u2","u27"],j:q,C:!0},s32:{h:"varying vec2 vv0;uniform sampler2D u1,u2;uniform float u27;const vec4 j=vec4(1.,1.,1.,1.);const vec2 k=vec2(1.,1.);void main(){float h=0.;vec2 l=k*u27,a,b;float c,d,i=0.;for(float e=-4.;e<=4.;e+=1.)for(float f=-4.;f<=4.;f+=1.)a=vec2(e,f),c=length(a)/2.,d=exp(-c*c),b=vv0+l*a,h+=d*texture2D(u1,b).r,i+=d;vec4 m=texture2D(u2,vv0);gl_FragColor=m.a*(texture2D(u1,b).r-h/i)*j;}",i:["u1","u2","u27"],j:q,C:!0},s33:{h:"uniform sampler2D u3;uniform vec2 u7;varying vec2 vv0;vec4 e(vec4 a,vec4 b){vec4 c=step(a,b);return mix(a,b,c);}const vec2 g=vec2(.5,.5),h=vec2(1.,0.),i=vec2(0.,1.);void main(){vec2 a=vv0-u7*g;vec4 b=texture2D(u3,a),c=texture2D(u3,a+u7*h),d=texture2D(u3,a+u7*i),j=texture2D(u3,a+u7),k=e(b,c),l=e(d,j);gl_FragColor=e(k,l);}",
i:["u3","u7"],j:H},s34:{h:"uniform sampler2D u3;uniform vec2 u7;varying vec2 vv0;const vec2 k=vec2(1.,0.),l=vec2(0.,1.),m=vec2(2.,0.),n=vec2(0.,2.);vec4 e(vec4 a,vec4 b){vec4 c=step(a,b);return mix(a,b,c);}vec4 f(vec2 a){vec4 b=texture2D(u3,a),c=texture2D(u3,a+u7*k),d=texture2D(u3,a+u7*l),g=texture2D(u3,a+u7),h=e(b,c),i=e(d,g);return e(h,i);}void main(){vec2 a=vv0+u7*vec2(-.55,-1.05);vec4 b=f(a),c=f(a+u7*m),d=f(a+u7*2.),g=f(a+u7*n),h=e(b,c),i=e(d,g);gl_FragColor=e(h,i);}",i:["u3","u7"],j:H,C:!0},
s35:{h:"uniform sampler2D u1;varying vec2 vv0;void main(){vec4 a=texture2D(u1,vv0);gl_FragColor=a*a;}",i:["u1"],j:w,precision:"lowp",C:!0},s36:{h:"uniform sampler2D u1;uniform vec2 u7;varying vec2 vv0;const float e=15444.;void main(){vec4 a=1001./e*texture2D(u1,vv0-3.*u7)+2002./e*texture2D(u1,vv0-2.*u7)+3003./e*texture2D(u1,vv0-u7)+3432./e*texture2D(u1,vv0)+3003./e*texture2D(u1,vv0+u7)+2002./e*texture2D(u1,vv0+2.*u7)+1001./e*texture2D(u1,vv0+3.*u7);gl_FragColor=a;}",i:["u7","u1"],j:w,precision:"lowp",
C:!0},s37:{h:"uniform sampler2D u1,u10,u28;varying vec2 vv0;const vec4 f=vec4(1.,1.,1.,1.);const float g=.1;void main(){vec4 a=texture2D(u10,vv0),b=texture2D(u28,vv0),c=texture2D(u1,vv0),d=max(f*g,b-a*a),h=sqrt(d);gl_FragColor=(c-a)/h;}",i:["u1","u10","u28"],j:{u1:0,u10:1,u28:2},C:!0}},E={s38:{h:"uniform float u16,u29;uniform sampler2D u13,u14,u21;varying vec2 vv0;const vec2 ZERO2=vec2(0.,0.),ONE2=vec2(1.,1.),HALF2=vec2(.5,.5),EPS2=vec2(1e-5,1e-5);void main(){vec4 sum=texture2D(u21,vv0);float toSparsity=1.1111;vec2 uvFrom,uvWeight,xyPatch=ZERO2,eps2=EPS2/u16,xyTo=floor(vv0*u16+eps2);float weightSize=toSparsity*u16;vec2 halfFromSparsity=ONE2*(toSparsity-1.)/2.;for(float patch_x=0.;patch_x<1.1111;patch_x+=1.){xyPatch.x=patch_x;for(float patch_y=0.;patch_y<1.1111;patch_y+=1.)xyPatch.y=patch_y,uvFrom=(xyTo+HALF2+u29*(xyPatch-halfFromSparsity))/u16,uvFrom+=step(uvFrom,-eps2),uvFrom-=step(ONE2-eps2,uvFrom),uvWeight=(xyTo*toSparsity+xyPatch+HALF2)/weightSize,sum+=texture2D(u13,uvWeight)*texture2D(u14,uvFrom);}gl_FragColor=sum,gl_FragColor*=2.2222;}",
i:["u16","u13","u14","u21","u29"],qb:["1.1111","gl_FragColor\\*=2.2222;"]},s39:{h:"uniform float u16,u29,u24;uniform sampler2D u13,u14,u21;varying vec2 vv0;const vec2 ZERO2=vec2(0.,0.),ONE2=vec2(1.,1.),HALF2=vec2(.5,.5),EPS2=vec2(1e-4,1e-4);void main(){vec4 sum=texture2D(u21,vv0);float fromSparsity=1.1111,shrinkFactor=3.3333;vec2 uvFrom,uvWeight,xyFrom,xyPatchTo,xyPatch=ZERO2,xyShrink=ZERO2,eps2=EPS2/u24,xyTo=floor(vv0*u16+eps2);float weightSize=fromSparsity*u24;vec2 halfFromSparsity=ONE2*(fromSparsity-1.)/2.;float toSparsity=weightSize/u16;vec2 xyFrom0=xyTo*shrinkFactor;for(float patch_x=0.;patch_x<1.1111;patch_x+=1.){xyPatch.x=patch_x;for(float patch_y=0.;patch_y<1.1111;patch_y+=1.){xyPatch.y=patch_y;for(float shrink_x=0.;shrink_x<3.3333;shrink_x+=1.){xyShrink.x=shrink_x;for(float shrink_y=0.;shrink_y<3.3333;shrink_y+=1.)xyShrink.y=shrink_y,xyFrom=xyFrom0+xyShrink+shrinkFactor*u29*(xyPatch-halfFromSparsity),uvFrom=(xyFrom+HALF2)/u24,uvFrom+=step(uvFrom,-eps2),uvFrom-=step(ONE2-eps2,uvFrom),xyPatchTo=xyPatch*shrinkFactor+xyShrink,uvWeight=(xyTo*toSparsity+xyPatchTo+HALF2)/weightSize,sum+=texture2D(u13,uvWeight)*texture2D(u14,uvFrom);}}}gl_FragColor=sum,gl_FragColor*=2.2222;}",
i:"u16 u24 u13 u14 u21 u29".split(" "),qb:["1.1111","gl_FragColor\\*=2.2222;","3.3333"]}},Q=null,F=null,J={fb:function(){return A},A:function(){if(!A){Q=nb.Ab(M,2);F=nb.Ab(E,2);r="highp";for(var u in Q)d(b,Q[u],u);z.set("s0");b.enableVertexAttribArray(0);A=!0}},zc:function(u){u.forEach(function(t){J.yc(t)})},yc:function(u){Q[u.id]=u;d(b,u,u.id)},$c:function(u,t,D){t||(t=u);Q[t]=Object.create(F[u]);Q[t].Je=!0;F[u].qb&&F[u].qb.forEach(function(K,P){Q[t].h=Q[t].h.replace(new RegExp(K,"g"),D[P])});d(b,
Q[t],t)},set:function(u){var t=Q[u];t.C&&(t.C=!1,d(b,t,u));e(t)},Ma:function(u){return f(u,m(),"s40")},kc:function(u){return f(u,{h:"void main(){gl_FragColor=vec4(.5,.5,.5,.5);}",i:[],precision:"highp"},"s41")},me:function(u){return"undefined"===typeof Q[u]?!1:Q[u].na},R:function(){-1!==p&&(p=-1,g.Da.forEach(function(u){0!==u&&b.disableVertexAttribArray(u)}))},mc:function(){var u=0;g.Da.forEach(function(t,D){D=g.Ca[D];b.vertexAttribPointer(t,D,b.FLOAT,!1,g.uc,u);u+=4*D})},Kc:function(){b.enableVertexAttribArray(0)},
xa:function(){J.rb(b)},rb:function(u){u.vertexAttribPointer(g.Da[0],2,u.FLOAT,!1,8,0)},Fd:function(u,t){b.uniform1i(g.B[u],t)},H:function(u,t){b.uniform1f(g.B[u],t)},pa:function(u,t,D){b.uniform2f(g.B[u],t,D)},Zg:function(u,t){b.uniform2fv(g.B[u],t)},hf:function(u,t){b.uniform3fv(g.B[u],t)},$g:function(u,t,D,K){b.uniform3f(g.B[u],t,D,K)},ah:function(u,t,D,K,P){b.uniform4f(g.B[u],t,D,K,P)},lc:function(u,t){b.uniform4fv(g.B[u],t)},bh:function(u,t){b.uniformMatrix2fv(g.B[u],!1,t)},dh:function(u,t){b.uniformMatrix3fv(g.B[u],
!1,t)},eh:function(u,t){b.uniformMatrix4fv(g.B[u],!1,t)},T:function(u,t){J.set(u);t.forEach(function(D){switch(D.type){case "4f":b.uniform4fv(g.B[D.name],D.value);break;case "3f":b.uniform3fv(g.B[D.name],D.value);break;case "2f":b.uniform2fv(g.B[D.name],D.value);break;case "1f":b.uniform1f(g.B[D.name],D.value);break;case "1i":b.uniform1i(g.B[D.name],D.value);break;case "mat2":b.uniformMatrix2fv(g.B[D.name],!1,D.value);break;case "mat3":b.uniformMatrix3fv(g.B[D.name],!1,D.value);break;case "mat4":b.uniformMatrix4fv(g.B[D.name],
!1,D.value)}})},sg:function(){return"lowp"},m:function(){b.disableVertexAttribArray(0);J.R();for(var u in Q){var t=Q[u];t.na&&(t.na=!1,b.deleteProgram(t.oa));t.Je&&delete Q[u]}n.forEach(function(D){b.deleteShader(D)});n.splice(0);v=0;A=!1;g=null;p=-1}};return J}(),b=null,Qa=function(){function a(r){console.log("ERROR in ContextFF: ",r);return!1}function c(r){function l(){Ca.m();ba.reset();w.getExtension("WEBGL_lose_context").loseContext()}if(navigator.userAgent&&-1!==navigator.userAgent.indexOf("forceWebGL1"))return!1;
var B=document.createElement("canvas");B.setAttribute("width",5);B.setAttribute("height",5);var w=null;try{w=B.getContext("webgl2",r)}catch(k){return!1}if(!w)return!1;d(w);ba.Lc(w);r=ba.Bb(w);if(!r.fa&&!r.ga)return l(),!1;r=Ca.Cc(w,r);l();return r?!0:!1}function d(r){r.clearColor(0,0,0,0);r.disable(r.DEPTH_TEST);r.disable(r.BLEND);r.disable(r.DITHER);r.disable(r.STENCIL_TEST);r.disable(r.CULL_FACE);r.GENERATE_MIPMAP_HINT&&r.hint(r.GENERATE_MIPMAP_HINT,r.FASTEST);r.disable(r.SAMPLE_ALPHA_TO_COVERAGE);
r.disable(r.SAMPLE_COVERAGE);r.depthFunc(r.LEQUAL);r.clearDepth(1)}var e=null,f=null,m=null,n=null,p=!0,g=null,v=null,A={F:function(){return e.width},U:function(){return e.height},jg:function(){return e},hg:function(){return b},ia:function(){return p},flush:function(){b.flush()},te:function(){g||(g=new Uint8Array(e.width*e.height*4));b.readPixels(0,0,e.width,e.height,b.RGBA,b.UNSIGNED_BYTE,g);return g},lg:function(){return e.toDataURL("image/jpeg")},mg:function(){ua.P();f||(f=document.createElement("canvas"),
m=f.getContext("2d"));f.width=e.width;f.height=e.height;for(var r=A.te(),l=m.createImageData(f.width,f.height),B=f.width,w=f.height,k=l.data,q=0;q<w;++q)for(var H=w-q-1,M=0;M<B;++M){var E=4*(q*B+M),Q=4*(H*B+M);k[E]=r[Q];k[E+1]=r[Q+1];k[E+2]=r[Q+2];k[E+3]=r[Q+3]}m.putImageData(l,0,0);return f.toDataURL("image/png")},kg:function(r){!f&&r&&(f=document.createElement("canvas"),m=f.getContext("2d"));var l=r?f:document.createElement("canvas");l.width=e.width;l.height=e.height;(r?m:l.getContext("2d")).drawImage(e,
0,0);return l},A:function(r){r.ee&&!r.zb?e=document.getElementById(r.ee):r.zb&&(e=r.zb);e||(e=document.createElement("canvas"));e.width=r&&void 0!==r.width?r.width:512;e.height=r&&void 0!==r.height?r.height:512;"undefined"===typeof r&&(r={});void 0===r.premultipliedAlpha&&(r.premultipliedAlpha=!1);void 0===r.dd&&(r.dd=!0);void 0===r.antialias&&(r.antialias=!1);if(b)p=b instanceof WebGL2RenderingContext;else{p=!0;var l={antialias:r.antialias,alpha:!0,preserveDrawingBuffer:!0,premultipliedAlpha:r.premultipliedAlpha,
stencil:!1,depth:r.dd};navigator&&navigator.userAgent&&-1!==navigator.userAgent.indexOf("noAntialiasing")&&(l.antialias=!1);var B=c(l);!B&&l.antialias&&(l.antialias=!1,B=c(l));B&&(b=e.getContext("webgl2",l));b?p=!0:((b=e.getContext("webgl",l))||(b=e.getContext("experimental-webgl",l)),p=!1)}if(!b)return a("WebGL1 and 2 are not enabled");(n=b.getExtension("WEBGL_lose_context"))&&r.td&&(v=r.td,e.addEventListener("webglcontextlost",v,!1));if(!ba.A())return a("Not enough GL capabilities");d(b);z.A();
U.A();return Ca.Cc(b,ba.se())?!0:a("Cannot filter float textures")},m:function(){b&&(ba.m(),Ca.m());n&&v&&(e.removeEventListener("webglcontextlost",v,!1),n=v=null);b=g=m=f=e=null}};return A}(),xa=function(){function a(){null===c&&("undefined"!==typeof z?c=z:"undefined"!==typeof JEShaders&&(c=JEShaders))}var c=null;a();return{gf:function(d){c!==d&&(c&&c.R(),c=d)},fb:function(){return c.fb()},xa:function(){return c.xa()},rb:function(d){return c.rb(d)},mc:function(){return c.mc()},R:function(){return c.R()},
set:function(d){return c.set(d)},Ma:function(d){a();return c.Ma(d)},kc:function(d){a();return c.kc(d)},m:function(){return c.m()}}}(),Ba=function(){function a(h){b.bindTexture(b.TEXTURE_2D,h)}function c(h){t[0]=h;h=D[0];var I=h>>16&32768,G=h>>12&2047,N=h>>23&255;return 103>N?I:142<N?I|31744|((255==N?0:1)&&h&8388607):113>N?(G|=2048,I|(G>>114-N)+(G>>113-N&1)):I=(I|N-112<<10|G>>1)+(G&1)}function d(h){var I=new Uint16Array(h.length);h.forEach(function(G,N){I[N]=c(G)});return I}function e(){if(null!==
K.Qb)return K.Qb;var h=m(d([.5,.5,.5,.5]));return null===h?!0:K.Qb=h}function f(){if(null!==K.Rb)return K.Rb;var h=m(new Uint8Array([127,127,127,127]));return null===h?!0:K.Rb=h}function m(h){if(!xa.fb()||!k)return null;var I=null,G=Math.sqrt(h.length/4);try{var N=b.getError();if("FUCKING_BIG_ERROR"===N)return!1;I=P.instance({isFloat:!1,S:!0,array:h,width:G});N=b.getError();if(N!==b.NO_ERROR)return!1}catch(ra){return!1}ka.P();b.viewport(0,0,G,G);b.clearColor(0,0,0,0);b.clear(b.COLOR_BUFFER_BIT);xa.set("s0");
I.Ac(0);la.l(!0,!0);h=4*G*G;N=new Uint8Array(h);b.readPixels(0,0,G,G,b.RGBA,b.UNSIGNED_BYTE,N);G=!0;for(var ha=0;ha<h;++ha)G=G&&3>Math.abs(N[ha]-127);I.remove();ka.da();return G}var n=0,p=null,g=0,v=null,A=null,r=null,l=null,B=null,w=null,k=!1,q=[],H={isFloat:!1,isPot:!0,isLinear:!1,isMipmap:!1,isAnisotropicFiltering:!1,isMirrorX:!1,isMirrorY:!1,isSrgb:!1,isKeepArray:!1,isFlipY:null,width:0,height:0,url:null,array:null,data:null,I:null,Pb:null,Ie:!1,S:!1,la:null,jb:4,Xb:0},M=!1,E=null,Q=null,F=[[1,
0,0,0],[0,1,0,0],[0,0,1,0],[0,0,0,1]],J=!1,u=!1,t=new Float32Array(1),D=new Int32Array(t.buffer),K={Qb:null,Rb:null},P={A:function(){k||(B=[b.RGBA,null,b.RGBA,b.RGBA],w=[b.RGBA,null,b.RGBA,b.RGBA],p=[b.TEXTURE0,b.TEXTURE1,b.TEXTURE2,b.TEXTURE3,b.TEXTURE4,b.TEXTURE5,b.TEXTURE6,b.TEXTURE7],J="undefined"!==typeof JEContext,u="undefined"!==typeof ba,J&&JEContext.Jg()&&p.push(b.TEXTURE8,b.TEXTURE9),v=[-1,-1,-1,-1,-1,-1,-1,-1],l=[b.UNSIGNED_BYTE,b.FLOAT,b.FLOAT],k=!0)},Fe:function(){if(!A){for(var h=new Float32Array(16384),
I=0;16384>I;++I)h[I]=2*Math.random()-1;A={random:P.instance({isFloat:!0,isPot:!0,array:h,width:64}),Ld:P.instance({isFloat:!1,isPot:!0,width:1,array:new Uint8Array([0,0,0,0])})}}P.xf()},Ag:function(){return A.Ld},xf:function(){l[1]=ba.Lb(b)},ef:function(){w=B=[b.RGBA,b.RGBA,b.RGBA,b.RGBA]},Ad:function(h){z.set("s1");ka.P();var I=h.F(),G=h.U();b.viewport(0,0,I,G);h.g(0);la.l(!1,!1)},Pg:function(h,I){P.Ad(h);b.readPixels(0,0,h.F(),h.U(),b.RGBA,b.UNSIGNED_BYTE,I)},Qg:function(h,I){P.Ad(h);return ba.pb(0,
0,h.F(),h.U(),I)},Tc:function(h,I,G,N,ha,ra,za){h.activeTexture(h.TEXTURE0);var x=h.createTexture();h.bindTexture(h.TEXTURE_2D,x);ha=ha instanceof Float32Array?ha:new Float32Array(ha);h.texParameteri(h.TEXTURE_2D,h.TEXTURE_WRAP_S,h.CLAMP_TO_EDGE);h.texParameteri(h.TEXTURE_2D,h.TEXTURE_WRAP_T,h.CLAMP_TO_EDGE);h.texParameteri(h.TEXTURE_2D,h.TEXTURE_MAG_FILTER,h.NEAREST);h.texParameteri(h.TEXTURE_2D,h.TEXTURE_MIN_FILTER,h.NEAREST);h.pixelStorei(h.UNPACK_FLIP_Y_WEBGL,ra);h.texImage2D(h.TEXTURE_2D,0,h.RGBA,
G,N,0,h.RGBA,h.FLOAT,ha);h.bindTexture(h.TEXTURE_2D,null);h.pixelStorei(h.UNPACK_FLIP_Y_WEBGL,!1);za&&(ka.da(),z.Ma(h));h.viewport(0,0,G,N);h.framebufferTexture2D(h.FRAMEBUFFER,h.COLOR_ATTACHMENT0,h.TEXTURE_2D,I,0);h.bindTexture(h.TEXTURE_2D,x);za?la.l(!0,!0):U.Wa(h);h.deleteTexture(x);k&&(v[0]=-1,r=null,n=0)},vb:function(h){h!==n&&(b.activeTexture(p[h]),n=h)},instance:function(h){function I(){R=void 0!==x.I.videoWidth?x.I.videoWidth:x.I.width;T=void 0!==x.I.videoHeight?x.I.videoHeight:x.I.height}
function G(C){var S=b.getError();if("FUCKING_BIG_ERROR"===S)return!1;b.texImage2D(b.TEXTURE_2D,0,ia,da,ea,C);S=b.getError();S!==b.NO_ERROR&&da!==b.RGBA&&(da=b.RGBA,b.texImage2D(b.TEXTURE_2D,0,ia,da,ea,C));return!0}function N(){if(!Eb){a(sa);Aa&&b.pixelStorei(b.UNPACK_FLIP_Y_WEBGL,Aa);x.isPot?(b.texParameteri(b.TEXTURE_2D,b.TEXTURE_WRAP_S,x.isMirrorX?b.MIRRORED_REPEAT:b.REPEAT),b.texParameteri(b.TEXTURE_2D,b.TEXTURE_WRAP_T,x.isMirrorY?b.MIRRORED_REPEAT:b.REPEAT)):(b.texParameteri(b.TEXTURE_2D,b.TEXTURE_WRAP_S,
b.CLAMP_TO_EDGE),b.texParameteri(b.TEXTURE_2D,b.TEXTURE_WRAP_T,b.CLAMP_TO_EDGE));x.isAnisotropicFiltering&&"undefined"!==typeof JESETTINGS&&b.texParameterf(b.TEXTURE_2D,JEContext.ng().TEXTURE_MAX_ANISOTROPY_EXT,JESETTINGS.Bf);b.texParameteri(b.TEXTURE_2D,b.TEXTURE_MAG_FILTER,x.isLinear?b.LINEAR:b.NEAREST);x.isLinear?b.texParameteri(b.TEXTURE_2D,b.TEXTURE_MIN_FILTER,x.isMipmap&&!Ka?b.NEAREST_MIPMAP_LINEAR:b.LINEAR):b.texParameteri(b.TEXTURE_2D,b.TEXTURE_MIN_FILTER,x.isMipmap&&!Ka?b.NEAREST_MIPMAP_NEAREST:
b.NEAREST);da=B[x.jb-1];ia=w[x.jb-1];ea=l[ob];if(ba.ia()){var C=ba.ve();da===b.RGBA&&ea===b.FLOAT?x.isMipmap||x.isLinear?ia=Ca.xe(b):ba.Dc()?C&&(ia=C):ia=b.RGBA16F||b.RGBA:da===b.RGB&&ea===b.FLOAT&&C&&(ia=C,da=b.RGBA)}if(x.S&&!x.isFloat||x.isFloat&&x.isMipmap&&Ca.Me())ia=ba.we(),ea=ba.Lb(b);x.Xb&&(ab=x.Xb);x.isSrgb&&4===x.jb&&(da=JEContext.yg());if(x.I)G(x.I);else if(x.url)G(Ga);else if(ta){C=ta;try{"FUCKING_BIG_ERROR"!==b.getError()&&(b.texImage2D(b.TEXTURE_2D,0,ia,R,T,0,da,ea,C),b.getError()!==
b.NO_ERROR&&(b.texImage2D(b.TEXTURE_2D,0,ia,R,T,0,da,ea,null),b.getError()!==b.NO_ERROR&&b.texImage2D(b.TEXTURE_2D,0,b.RGBA,R,T,0,b.RGBA,b.UNSIGNED_BYTE,null)))}catch(gc){b.texImage2D(b.TEXTURE_2D,0,ia,R,T,0,da,ea,null)}x.isKeepArray||(ta=null)}else C=b.getError(),"FUCKING_BIG_ERROR"!==C&&(b.texImage2D(b.TEXTURE_2D,0,ia,R,T,0,da,ea,null),C=b.getError(),C!==b.NO_ERROR&&(da=b.RGBA,x.S&&ea!==b.FLOAT&&(ea=b.FLOAT,b.texImage2D(b.TEXTURE_2D,0,ia,R,T,0,da,ea,null))));if(x.isMipmap)if(!Ka&&ca)ca.Kb(),bb=
!0;else if(Ka){C=Math.log2(Math.min(R,T));Ra=Array(1+C);Ra[0]=sa;for(var S=1;S<=C;++S){var ja=Math.pow(2,S),V=R/ja;ja=T/ja;var La=b.createTexture();a(La);b.texParameteri(b.TEXTURE_2D,b.TEXTURE_MIN_FILTER,b.NEAREST);b.texParameteri(b.TEXTURE_2D,b.TEXTURE_MAG_FILTER,b.NEAREST);b.texImage2D(b.TEXTURE_2D,0,ia,V,ja,0,da,ea,null);a(null);Ra[S]=La}bb=!0}a(null);v[n]=-1;Aa&&b.pixelStorei(b.UNPACK_FLIP_Y_WEBGL,!1);Ta=!0;x.la&&ca&&(x.la(ca),x.la=null)}}function ha(){for(var C=R*T,S=2*C,ja=3*C,V=0;V<C;++V)ya[0][V]=
Ua[V],ya[1][V]=Ua[V+C],ya[2][V]=Ua[V+S],ya[3][V]=Ua[V+ja]}function ra(){var C=R*T*4;Da=[new Uint8Array(C),new Uint8Array(C),new Uint8Array(C),new Uint8Array(C)];ya=[new Float32Array(Da[0].buffer),new Float32Array(Da[1].buffer),new Float32Array(Da[2].buffer),new Float32Array(Da[3].buffer)];cb=new Uint8Array(4*C);Ua=new Float32Array(cb.buffer);Va=!0}function za(){Ea.wb=new Uint8Array(R*T*4);Ea.Uc=new Float32Array(Ea.buffer);Ea.Ub=!0}var x=Object.assign({},H,h),Wa=g++;null===x.isFlipY&&(x.isFlipY=x.url||
x.array?!0:!1);x.data&&(x.array="string"===typeof x.data?Mb(x.data):x.isFloat?new Float32Array(x.data):new Uint8Array(x.data),x.isFlipY=!1);var ob=0,Fb=x.I?!0:!1,Xa=null,pb=null,Gb=!1,qb=null;x.S=x.S||x.isFloat;x.S&&(ob=1);!x.Ie&&x.isFloat&&u&&!ba.Dc()&&(x.isFloat=!1);x.isFloat&&(ob=2);x.isAnisotropicFiltering&&J&&!JEContext.Dg()&&(x.isAnisotropicFiltering=!1);var sa=x.Pb||b.createTexture(),Ga=null,ta=!1,R=0,T=0,Ta=!1,Eb=!1,Va=!1,ya=null,Da=null,cb=null,Ua=null,ia=null,da=null,ea=null,Aa=x.isFlipY,
Vb=(h=x.S&&x.isMipmap)&&Ca.Wd(),Ka=h&&Vb?!0:!1,Ra=null,ab=-1,bb=!1,Ea={Ub:!1,wb:null,Uc:null};x.width&&(R=x.width,T=x.height?x.height:R);var ca={get:function(){return sa},F:function(){return R},U:function(){return T},Bg:function(){return x.url},Eg:function(){return x.isFloat},Gg:function(){return x.S},Hg:function(){return x.isLinear},Kb:function(){b.generateMipmap(b.TEXTURE_2D)},Ud:function(C,S){Ka?(C||(C=ca.Yc()),P.vb(S),a(Ra[C]),v[S]=-1):ca.g(S)},Yc:function(){-1===ab&&(ab=Math.log(R)/Math.log(2));
return ab},pe:function(C){if(Ka){C||(C=ca.Yc());z.set("s11");P.vb(0);for(var S=R,ja=T,V=1;V<=C;++V)S/=2,ja/=2,z.pa("u7",.25/S,.25/ja),b.viewport(0,0,S,ja),a(Ra[V-1]),b.framebufferTexture2D(ka.Za(),b.COLOR_ATTACHMENT0,b.TEXTURE_2D,Ra[V],0),la.l(!1,1===V);v[0]=-1}else ca.Kb()},Yg:function(C){(Fb=!Tb.qf(C))?(ta=null,x.I=C,I()):ta=C},g:function(C){if(!Ta)return!1;P.vb(C);if(v[C]===Wa)return!1;a(sa);v[C]=Wa;return!0},Ac:function(C){b.activeTexture(p[C]);n=C;a(sa);v[C]=Wa},u:function(){r=ca;b.framebufferTexture2D(ka.Za(),
b.COLOR_ATTACHMENT0,b.TEXTURE_2D,sa,0)},aa:function(){r=ca;b.viewport(0,0,R,T);b.framebufferTexture2D(ka.Za(),b.COLOR_ATTACHMENT0,b.TEXTURE_2D,sa,0)},sc:P.sc,resize:function(C,S){R=C;T=S;N()},clone:function(C){C=P.instance({width:R,height:T,S:x.S,isFloat:x.isFloat,isLinear:x.isLinear,isMirrorY:x.isMirrorY,isFlipY:C?!Aa:Aa,isPot:x.isPot});xa.set("s0");ka.da();C.u();b.viewport(0,0,R,T);ca.g(0);la.l(!0,!0);return C},jf:function(){b.viewport(0,0,R,T)},remove:function(){b.deleteTexture(sa);Eb=!0;q.splice(q.indexOf(ca),
1);ca=null},refresh:function(){ca.Ac(0);Aa&&b.pixelStorei(b.UNPACK_FLIP_Y_WEBGL,!0);Fb?b.texImage2D(b.TEXTURE_2D,0,ia,da,ea,x.I):b.texImage2D(b.TEXTURE_2D,0,ia,R,T,0,da,ea,ta);Aa&&b.pixelStorei(b.UNPACK_FLIP_Y_WEBGL,!1)},zd:function(){Va||ra();b.readPixels(0,0,R,4*T,b.RGBA,b.UNSIGNED_BYTE,cb);ha();return ya},Ye:function(){Va||ra();return ba.pb(0,0,R,4*T,cb).then(function(){ha();return ya})},$e:function(){Ea.Ub||za();b.readPixels(0,0,R,T,b.RGBA,b.UNSIGNED_BYTE,Ea.wb);return Ea.Uc},Ze:function(){Ea.Ub||
za();return ba.pb(0,0,R,T,Ea.wb)},Ic:function(C){ka.P();z.set("s12");ca.g(0);if(C)b.viewport(0,0,R,T),z.lc("u8",.25,.25,.25,.25),la.l(!1,!0);else for(C=0;4>C;++C)b.viewport(0,T*C,R,T),z.lc("u8",F[C]),la.l(!1,0===C)},wf:function(C){var S=ea===l[0]&&!f();a(sa);Aa&&b.pixelStorei(b.UNPACK_FLIP_Y_WEBGL,!0);S?(Gb||(Xa=document.createElement("canvas"),Xa.width=R,Xa.height=T,pb=Xa.getContext("2d"),qb=pb.createImageData(R,T),Gb=!0),qb.data.set(C),pb.putImageData(qb,0,0),b.texImage2D(b.TEXTURE_2D,0,ia,da,ea,
Xa)):b.texImage2D(b.TEXTURE_2D,0,ia,R,T,0,da,ea,C);v[n]=Wa;Aa&&b.pixelStorei(b.UNPACK_FLIP_Y_WEBGL,!1)},jh:function(C,S){a(sa);S&&b.pixelStorei(b.UNPACK_FLIP_Y_WEBGL,!0);b.texImage2D(b.TEXTURE_2D,0,ia,da,ea,C);v[n]=Wa;S&&b.pixelStorei(b.UNPACK_FLIP_Y_WEBGL,!1)},Wg:function(C,S){var ja=R*T,V=4*ja;C=x.S?C?"RGBE":"JSON":"RGBA";S&&(C=S);S=ba.ia()&&!1;var La=null;switch(C){case "RGBE":La="s42";break;case "JSON":La=S?"s0":"s12";break;case "RGBA":case "RGBAARRAY":La="s6"}Va||("RGBA"===C||"RGBE"===C||"RGBAARRAY"===
C?(Da=new Uint8Array(V),Va=!0):"JSON"!==C||S||ra());ka.P();z.set(La);ca.g(0);V=null;if("RGBA"===C||"RGBE"===C||"RGBAARRAY"===C){b.viewport(0,0,R,T);la.l(!0,!0);b.readPixels(0,0,R,T,b.RGBA,b.UNSIGNED_BYTE,Da);if("RGBAARRAY"===C)return{data:Da};M||(E=document.createElement("canvas"),Q=E.getContext("2d"),M=!0);E.width=R;E.height=T;ja=Q.createImageData(R,T);ja.data.set(Da);Q.putImageData(ja,0,0);V=E.toDataURL("image/png")}else if("JSON"===C)if(S)V=new Float32Array(ja),b.viewport(0,0,R,T),la.l(!0,!0),
b.readPixels(0,0,R,T,b.RGBA,b.FLOAT,V);else{for(V=0;4>V;++V)b.viewport(0,T*V,R,T),z.lc("u8",F[V]),la.l(!V,!V);ca.zd();V=Array(ja);for(S=0;S<ja;++S)V[4*S]=ya[0][S],V[4*S+1]=ya[1][S],V[4*S+2]=ya[2][S],V[4*S+3]=ya[3][S]}return{format:C,data:V,width:R,height:T,isMirrorY:x.isMirrorY,isFlipY:"RGBA"===C?x.isFlipY:!x.isFlipY}}};x.isMipmap&&!Ka&&Ta&&!bb&&(ca.Kb(),bb=!0);if(x.url)a(sa),b.texImage2D(b.TEXTURE_2D,0,b.RGBA,1,1,0,b.RGBA,b.UNSIGNED_BYTE,null),Ga=new Image,Ga.Of="Anonymous",Ga.crossOrigin="Anonymous",
Ga.src=x.url,Ga.onload=function(){R=Ga.width;T=Ga.height;N()};else if(x.I){var Hb=function(){I();R?N():setTimeout(Hb,1)};Hb()}else x.array?(x.S&&!x.isFloat?x.array instanceof Uint16Array?(ta=x.array,N()):e()?(ta=d(x.array),N()):(N(),P.Tc(b,sa,ca.F(),ca.U(),x.array,Aa,!0)):(ta=x.isFloat?x.array instanceof Float32Array?x.array:new Float32Array(x.array):x.array instanceof Uint8Array?x.array:new Uint8Array(x.array),N()),x.isKeepArray||(ta&&ta!==x.array&&(ta=null),delete x.array)):x.Pb?Ta=!0:N();ca.xg=
ca.F;x.la&&Ta&&(x.la(ca),x.la=null);q.push(ca);return ca},P:function(h){h!==n&&(b.activeTexture(p[h]),n=h);v[h]=-1;a(null)},Ef:function(h){A.random.g(h)},sc:function(){r=null;b.framebufferTexture2D(ka.Za(),b.COLOR_ATTACHMENT0,b.TEXTURE_2D,null,0)},reset:function(){0!==n&&b.activeTexture(p[0]);for(var h=0;h<p.length;++h)v[h]=-1;n=-1},Tg:function(){n=-1},tf:function(){for(var h=0;h<p.length;++h)P.P(h)},Vc:function(){A&&(A.random.remove(),A.Ld.remove())},ih:function(h,I){if("RGBA"===h.format||"RGBE"===
h.format){var G=new Image;G.src=h.data;G.onload=function(){P.instance({isMirrorY:h.isMirrorY,isFlipY:h.isFlipY,isFloat:!1,I:G,la:function(N){if("RGBA"===h.format)I(N);else{var ha=h.width,ra=h.height,za=P.instance({isMirrorY:h.isMirrorY,isFloat:!0,width:ha,height:ra,isFlipY:h.isFlipY});ka.da();b.viewport(0,0,ha,ra);z.set("s43");za.u();N.g(0);la.l(!0,!0);P.P(0);I(za);b.flush();setTimeout(N.remove,50)}}})}}else"JSON"===h.format?I(P.instance({isFloat:!0,isFlipY:h.isFlipY,width:h.width,height:h.height,
array:new Float32Array(h.data)})):I(!1)},be:d,m:function(){r&&(ua.da(),P.sc(),ua.P());P.tf();q.slice(0).forEach(function(h){h.remove()});q.splice(0);k=!1;g=0;"undefined"!==typeof Ca&&Ca.m();A=null}};return P}(),Nb=function(){return{instance:function(a){var c=[Ba.instance(a),Ba.instance(a)],d=[c[1],c[0]],e=d,f={cf:function(m){e[1].u();e[0].g(m);f.Hd()},Xg:function(m){e[1].aa();e[0].g(m);f.Hd()},Hd:function(){e=e===c?d:c},refresh:function(){e[0].refresh();e[1].refresh()},g:function(m){e[0].g(m)},Df:function(m){e[1].g(m)},
rg:function(){return e[0]},vg:function(){return e[1]},remove:function(){e[0].remove();e[1].remove();e=null}};return f}}}(),la=function(){function a(g){var v={ba:null,K:null};v.ba=g.createBuffer();g.bindBuffer(g.ARRAY_BUFFER,v.ba);g.bufferData(g.ARRAY_BUFFER,new Float32Array([-1,-1,3,-1,-1,3]),g.STATIC_DRAW);v.K=g.createBuffer();g.bindBuffer(g.ELEMENT_ARRAY_BUFFER,v.K);g.bufferData(g.ELEMENT_ARRAY_BUFFER,new Uint16Array([0,1,2]),g.STATIC_DRAW);return v}var c=null,d=0,e=!1,f=[],m=-2,n=-2,p={reset:function(){n=
m=-2},A:function(){e||(c=a(b),p.Ea(),e=!0)},instance:function(g){var v=d++,A=g.K?g.K.length:0,r="undefined"===typeof g.mode?b.STATIC_DRAW:g.mode,l=b.createBuffer();b.bindBuffer(b.ARRAY_BUFFER,l);b.bufferData(b.ARRAY_BUFFER,g.ba instanceof Float32Array?g.ba:new Float32Array(g.ba),r);m=v;var B=null,w=null,k=null;if(g.K){B=b.createBuffer();b.bindBuffer(b.ELEMENT_ARRAY_BUFFER,B);var q=null;65536>g.K.length?(q=Uint16Array,w=b.UNSIGNED_SHORT,k=2):(q=Uint32Array,w=b.UNSIGNED_INT,k=4);q=g.K instanceof q?
g.K:new q(g.K);b.bufferData(b.ELEMENT_ARRAY_BUFFER,q,r);n=v}var H={Vd:function(M){m!==v&&(b.bindBuffer(b.ARRAY_BUFFER,l),m=v);M&&xa.mc()},Sd:function(){n!==v&&(b.bindBuffer(b.ELEMENT_ARRAY_BUFFER,B),n=v)},bind:function(M){H.Vd(M);H.Sd()},Qf:function(){b.drawElements(b.TRIANGLES,A,w,0)},Rf:function(M,E){b.drawElements(b.TRIANGLES,M,w,E*k)},remove:function(){b.deleteBuffer(l);g.K&&b.deleteBuffer(B);H=null}};f.push(H);return H},Ea:function(){-1!==m&&(b.bindBuffer(b.ARRAY_BUFFER,c.ba),m=-1);-1!==n&&(b.bindBuffer(b.ELEMENT_ARRAY_BUFFER,
c.K),n=-1)},l:function(g,v){g&&la.Ea();v&&xa.xa();b.drawElements(b.TRIANGLES,3,b.UNSIGNED_SHORT,0)},Wa:function(g){g=g||b;var v=a(g);g.bindBuffer(g.ARRAY_BUFFER,v.ba);g.bindBuffer(g.ELEMENT_ARRAY_BUFFER,v.K);xa.rb(g);g.clear(g.COLOR_BUFFER_BIT);g.drawElements(g.TRIANGLES,3,g.UNSIGNED_SHORT,0);g.flush();g.bindBuffer(g.ARRAY_BUFFER,null);g.bindBuffer(g.ELEMENT_ARRAY_BUFFER,null);g.deleteBuffer(v.ba);g.deleteBuffer(v.K);p.reset();e&&(p.Ea(),xa.xa())},Vc:function(){var g=b,v=c;g.deleteBuffer(v.ba);g.deleteBuffer(v.K)},
m:function(){p.Vc();f.forEach(function(g){g.remove()});b.bindBuffer(b.ARRAY_BUFFER,null);b.bindBuffer(b.ELEMENT_ARRAY_BUFFER,null);p.reset();e=!1;f.splice(0);d=0}};return p}(),ka=function(){var a=null,c=null,d=null,e=!1,f=[],m={J:-2,Sc:1},n={fb:function(){return e},A:function(){if(!e){a=b.createFramebuffer();var p=ba.ia();c=p&&b.DRAW_FRAMEBUFFER?b.DRAW_FRAMEBUFFER:b.FRAMEBUFFER;d=p&&b.READ_FRAMEBUFFER?b.READ_FRAMEBUFFER:b.FRAMEBUFFER;e=!0}},og:function(){return c},ye:function(){return d},Za:function(){return b.FRAMEBUFFER},
wg:function(){return m},gg:function(){return a},instance:function(p){void 0===p.cd&&(p.cd=!1);var g=p.N?p.N:null,v=p.width,A=void 0!==p.height?p.height:p.width,r=a,l=null,B=!1,w=!1,k=0;g&&(v=v?v:g.F(),A=A?A:g.U());var q={Ed:function(){B||(r=b.createFramebuffer(),B=!0,k=m.Sc++)},Nd:function(){q.Ed();q.u();l=b.createRenderbuffer();b.bindRenderbuffer(b.RENDERBUFFER,l);b.renderbufferStorage(b.RENDERBUFFER,b.DEPTH_COMPONENT16,v,A);b.framebufferRenderbuffer(c,b.DEPTH_ATTACHMENT,b.RENDERBUFFER,l);b.clearDepth(1)},
bind:function(H,M){k!==m.J&&(b.bindFramebuffer(c,r),m.J=k);g&&g.u();M&&b.viewport(0,0,v,A);H&&b.clear(b.COLOR_BUFFER_BIT|b.DEPTH_BUFFER_BIT)},Cf:function(){k!==m.J&&(b.bindFramebuffer(c,r),m.J=k)},clear:function(){b.clear(b.COLOR_BUFFER_BIT|b.DEPTH_BUFFER_BIT)},Kf:function(){b.clear(b.COLOR_BUFFER_BIT)},Lf:function(){b.clear(b.DEPTH_BUFFER_BIT)},jf:function(){b.viewport(0,0,v,A)},u:function(){k!==m.J&&(b.bindFramebuffer(c,r),m.J=k)},rtt:function(H){g=H;m.J!==k&&(b.bindFramebuffer(b.FRAMEBUFFER,r),
m.J=k);H.u()},P:function(){b.bindFramebuffer(c,null);m.J=-1},resize:function(H,M){v=H;A=M;l&&(b.bindRenderbuffer(b.RENDERBUFFER,l),b.renderbufferStorage(b.RENDERBUFFER,b.DEPTH_COMPONENT16,v,A))},remove:function(){r===a||w||(b.bindFramebuffer(c,r),b.framebufferTexture2D(c,b.COLOR_ATTACHMENT0,b.TEXTURE_2D,null,0),l&&b.framebufferRenderbuffer(c,b.DEPTH_ATTACHMENT,b.RENDERBUFFER,null),b.bindFramebuffer(c,null),b.deleteFramebuffer(r),l&&b.deleteRenderbuffer(l));w=!0}};p.cd&&q.Nd();f.push(q);return q},
P:function(){b.bindFramebuffer(c,null);m.J=-1},uf:function(){b.bindFramebuffer(c,null);b.clear(b.COLOR_BUFFER_BIT|b.DEPTH_BUFFER_BIT);b.viewport(0,0,ba.F(),ba.U());m.J=-1},reset:function(){m.J=-2},da:function(){0!==m.J&&(b.bindFramebuffer(c,a),m.J=0)},clear:function(){b.viewport(0,0,ba.F(),ba.U());b.clear(b.COLOR_BUFFER_BIT)},m:function(){n.P();f.forEach(function(p){p.remove()});null!==a&&(b.deleteFramebuffer(a),a=null);n.reset();e=!1;f.splice(0);m.Sc=1}};return n}(),ba=function(){function a(){e=
"undefined"===typeof Qa?JEContext:Qa;f=!0}function c(k,q){for(var H=0;H<k.length;++H){var M=q.getExtension(k[H]);if(M)return M}return null}function d(){null!==l.tb&&(clearInterval(l.tb),l.tb=null);l.Ja=!1}var e=null,f=!1,m={ed:!1,oc:null,pc:null,jd:!1,Le:!1,qc:null,kd:!1,rc:null,fd:!1,xb:null,Ge:!1,yb:null,He:!1},n=null,p={fa:!0,ga:!0,Jb:!0,yd:!1},g=null,v=!0,A=null,r=null,l={Ja:!1,sa:null,$a:null,Ob:-1,ta:null,tb:null},B="undefined"===typeof window?{}:window,w={A:function(){if(f)return!0;w.reset();
f||a();var k=b;if(!n.ed){n.oc=w.Oc(k);B.GL_EXT_FLOAT=n.oc;n.jd=n.oc?!0:!1;if(n.jd||w.ia())n.pc=w.Pc(k),n.Le=n.pc?!0:!1,B.GL_EXT_FLOATLINEAR=n.pc;n.ed=!0}if(!n.fd){n.qc=w.Va(k);n.qc&&(n.kd=!0,B.GL_EXT_HALFFLOAT=n.qc);if(n.kd||w.ia())n.rc=w.Qc(k),B.GL_EXT_HALFFLOATLINEAR=n.rc;n.Cg=n.rc?!0:!1;n.fd=!0}n.xb=w.Mc(k);n.Ge=n.xb?!0:!1;B.GL_EXT_COLORBUFFERFLOAT=n.xb;n.yb=w.Nc(k);n.He=n.yb?!0:!1;B.GL_EXT_COLORBUFFERHALFFLOAT=n.yb;ka.A();Ba.A();if(!w.ge())return!1;la.A();Ba.Fe();return!0},reset:function(){n=
Object.assign({},m);g=Object.assign({},p)},F:function(){f||a();return e.F()},U:function(){f||a();return e.U()},ia:function(){f||a();return e.ia()},Lc:function(k){w.Mc(k);w.Nc(k);w.Oc(k);w.Pc(k);w.Va(k);w.Qc(k)},Mc:c.bind(null,["EXT_color_buffer_float","WEBGL_color_buffer_float","OES_color_buffer_float"]),Nc:c.bind(null,["EXT_color_buffer_half_float","WEBGL_color_buffer_half_float","OES_color_buffer_half_float"]),Oc:c.bind(null,["OES_texture_float","MOZ_OES_texture_float","WEBKIT_OES_texture_float"]),
Pc:c.bind(null,["OES_texture_float_linear","MOZ_OES_texture_float_linear","WEBKIT_OES_texture_float_linear"]),Va:c.bind(null,["OES_texture_half_float","MOZ_OES_texture_half_float","WEBKIT_OES_texture_half_float"]),Qc:c.bind(null,["OES_texture_half_float_linear","MOZ_OES_texture_half_float_linear","WEBKIT_OES_texture_half_float_linear"]),Lb:function(k){var q=w.Va(k);return q&&q.HALF_FLOAT_OES?q.HALF_FLOAT_OES:k.HALF_FLOAT||k.FLOAT},ve:function(){return r||b.RGBA32F||b.RGBA},we:function(){return A||
b.RGBA16F||b.RGBA},se:function(){return g},Dc:function(){return g.fa},Gf:function(){return g.ga},Ff:function(){return g.Jb},Xd:function(){return g.yd&&v},Jd:function(k){v=k;!k&&l.Ja&&(b.deleteSync(l.$a),b.bindBuffer(l.ta,null),l.Ja=!1)},sb:function(k,q,H){function M(){k.bindTexture(k.TEXTURE_2D,null);k.bindFramebuffer(E,null);k.deleteTexture(J);k.deleteFramebuffer(F)}var E=k.FRAMEBUFFER,Q=k.NEAREST,F=k.createFramebuffer();k.bindFramebuffer(E,F);var J=k.createTexture();k.activeTexture(k.TEXTURE0);
k.bindTexture(k.TEXTURE_2D,J);k.pixelStorei(k.UNPACK_FLIP_Y_WEBGL,!1);k.texParameteri(k.TEXTURE_2D,k.TEXTURE_WRAP_S,k.CLAMP_TO_EDGE);k.texParameteri(k.TEXTURE_2D,k.TEXTURE_WRAP_T,k.CLAMP_TO_EDGE);k.texParameteri(k.TEXTURE_2D,k.TEXTURE_MAG_FILTER,Q);k.texParameteri(k.TEXTURE_2D,k.TEXTURE_MIN_FILTER,Q);k.texImage2D(k.TEXTURE_2D,0,q,3,3,0,k.RGBA,H,null);k.framebufferTexture2D(k.FRAMEBUFFER,k.COLOR_ATTACHMENT0,k.TEXTURE_2D,J,0);if(k.checkFramebufferStatus(k.READ_FRAMEBUFFER||k.FRAMEBUFFER)!==k.FRAMEBUFFER_COMPLETE)return M(),
!1;xa.kc(k);k.clearColor(0,0,0,0);k.viewport(0,0,3,3);k.disable(k.DEPTH_TEST);k.clear(k.COLOR_BUFFER_BIT);la.Wa(k);k.bindFramebuffer(E,null);xa.Ma(k);k.activeTexture(k.TEXTURE0);k.bindTexture(k.TEXTURE_2D,J);la.Wa(k);q=new Uint8Array(36);k.readPixels(0,0,3,3,k.RGBA,k.UNSIGNED_BYTE,q);M();for(H=0;36>H;++H)if(3!==H%4&&3<Math.abs(q[H]-127))return!1;return!0},Bb:function(k){var q={fa:!1,ga:!1};k.disable(k.BLEND);k.clearColor(0,0,0,0);k.clear(k.COLOR_BUFFER_BIT);k.RGBA32F&&w.sb(k,k.RGBA32F,k.FLOAT)&&(q.fa=
!0,r=k.RGBA32F);!q.fa&&w.sb(k,k.RGBA,k.FLOAT)&&(q.fa=!0,r=k.RGBA);var H=w.Lb(k);A=null;k.RGBA16F&&w.sb(k,k.RGBA16F,H)&&(q.ga=!0,A=k.RGBA16F);!q.ga&&w.sb(k,k.RGBA,H)&&(q.ga=!0,A=k.RGBA);return q},he:function(){var k=ka.instance({width:2});k.Ed();var q=Ba.instance({width:2,isFloat:!0,jb:3});k.u();q.u();b.flush();b.checkFramebufferStatus(ka.ye())!==b.FRAMEBUFFER_COMPLETE?(Ba.ef(),g.Jb=!1):g.Jb=!0;k.remove();q.remove()},ie:function(){var k=!1;w.ia()&&(k="PIXEL_PACK_BUFFER STREAM_READ SYNC_GPU_COMMANDS_COMPLETE WAIT_FAILED fenceSync deleteSync createBuffer".split(" ").every(function(q){return"undefined"!==
typeof b[q]}));g.yd=k},ge:function(){var k=w.Bb(b);Object.assign(g,k);if(!g.fa&&!g.ga)return!1;w.he();w.ie();return!0},pb:function(k,q,H,M,E){if(!w.Xd())return b.readPixels(k,q,H,M,b.RGBA,b.UNSIGNED_BYTE,E),Promise.resolve(E);null===l.sa&&(l.ta=b.PIXEL_PACK_BUFFER,l.sa=b.createBuffer(),l.Ob=-1);b.bindBuffer(l.ta,l.sa);E.byteLength!==l.Ob&&(b.bufferData(l.ta,E.byteLength,b.STREAM_READ),l.Ob=E.byteLength);b.readPixels(k,q,H,M,b.RGBA,b.UNSIGNED_BYTE,0);l.$a=b.fenceSync(b.SYNC_GPU_COMMANDS_COMPLETE,0);
b.flush();return new Promise(function(Q,F){function J(){if(!l.Ja)return d(),F(),!1;switch(b.clientWaitSync(l.$a,0,0)){case b.TIMEOUT_EXPIRED:return!1;case b.WAIT_FAILED:return d(),F(),!1;default:return d(),b.deleteSync(l.$a),b.getBufferSubData(l.ta,0,E),b.bindBuffer(l.ta,null),Q(E),!0}}d();l.Ja=!0;J()||(l.tb=setInterval(J,0))})},m:function(){d();Ba.m();xa.m();ka.m();la.m();null!==l.sa&&(b.deleteBuffer(l.sa),l.sa=null);f=!1}};return w}(),U=la,ua=ka,Y=Ba,Ca=function(){function a(F,J,u,t){q.texParameteri(q.TEXTURE_2D,
q.TEXTURE_MIN_FILTER,t?q.NEAREST_MIPMAP_NEAREST:q.LINEAR);var D=null;if(null!==u)try{D=q.getError();if("FUCKING_BIG_ERROR"===D)return!1;q.texImage2D(q.TEXTURE_2D,0,F,4,4,0,q.RGBA,J,u);D=q.getError();if(D!==q.NO_ERROR)return!1}catch(K){return!1}t&&q.generateMipmap(q.TEXTURE_2D);q.clear(q.COLOR_BUFFER_BIT);U.Wa(q);D=q.getError();if("FUCKING_BIG_ERROR"===D)return!1;q.readPixels(0,0,2,2,q.RGBA,q.UNSIGNED_BYTE,A);D=q.getError();D===q.INVALID_OPERATION&&"undefined"!==typeof q.PIXEL_PACK_BUFFER&&(q.bindBuffer(q.PIXEL_PACK_BUFFER,
null),q.readPixels(0,0,2,2,q.RGBA,q.UNSIGNED_BYTE,A),D=q.getError());if(D!==q.NO_ERROR)return!1;u=!0;for(t=0;16>t;++t)u=u&&4>Math.abs(A[t]-127);u&&(g.vd=J,g.bd=F);return u}function c(F,J){return H.fa&&a(F,q.FLOAT,new Float32Array(r),J)?(p=n.wc,!0):!1}function d(F,J,u){if(!H.ga)return!1;var t=Ba.be(r),D=ba.Va(q);if(D&&D.HALF_FLOAT_OES&&a(F,D.HALF_FLOAT_OES,t,J)||q.HALF_FLOAT&&a(F,q.HALF_FLOAT,t,J))return p=n.Ba,!0;t=new Float32Array(r);if(a(F,q.FLOAT,t,J))return p=n.Ba,!0;q.bindTexture(q.TEXTURE_2D,
u);q.texImage2D(q.TEXTURE_2D,0,q.RGBA,2,2,0,q.RGBA,q.UNSIGNED_BYTE,null);q.bindFramebuffer(g.Ta,Q);Ba.Tc(q,u,2,2,t,!1,!1);q.bindFramebuffer(g.Ta,null);q.bindTexture(q.TEXTURE_2D,u);return a(F,null,null,J)?(p=n.Ba,!0):!1}function e(F,J,u){v=!0;if(d(F,!0,u)||c(J,!0))return!0;v=!1;return d(F,!1,u)||c(J,!1)?!0:!1}function f(F){if(p===n.R){q=F||b;p=n.RGBA8;v=!0;ba.Lc(q);H||(H=ba.Bb(q));ua.reset();Q=q.createFramebuffer();g.Ta=q.DRAW_FRAMEBUFFER||q.FRAMEBUFFER;q.bindFramebuffer(g.Ta,null);q.clearColor(0,
0,0,0);q.viewport(0,0,2,2);z.R();M=z.Ma(q);F=q.createTexture();q.activeTexture(q.TEXTURE0);q.bindTexture(q.TEXTURE_2D,F);q.texParameteri(q.TEXTURE_2D,q.TEXTURE_WRAP_S,q.REPEAT);q.texParameteri(q.TEXTURE_2D,q.TEXTURE_WRAP_T,q.REPEAT);q.texParameteri(q.TEXTURE_2D,q.TEXTURE_MAG_FILTER,q.NEAREST);E=F;var J=F=q.RGBA,u=q.RGBA16F,t=q.RGBA32F;t&&(F=t);u&&(J=u);if((u||t)&&e(J,F,E))return m(),!0;F=J=q.RGBA;if(e(J,F,E))return m(),!0;p=n.RGBA8;m();return!1}}function m(){q.deleteProgram(M.oa);q.deleteTexture(E);
E=M=null}for(var n={R:-1,wc:3,Ba:2,RGBA8:0},p=n.R,g={vd:null,bd:null,Ta:null},v=!0,A=new Uint8Array(16),r=Array(64),l=0;4>l;++l)for(var B=0;4>B;++B){var w=0===(B+l)%2?1:0,k=4*l+B;r[4*k]=w;r[4*k+1]=w;r[4*k+2]=w;r[4*k+3]=w}var q=null,H=null,M=null,E=null,Q=null;return{Wd:function(F){f(F);return v},Cc:function(F,J){p===n.R&&(typeof("undefined"!==J)&&(H=J),f(F));return p!==n.RGBA8},Fg:function(F){f(F);return p===n.wc},Me:function(F){f(F);return p===n.Ba},pg:function(F){f(F);return g.vd},xe:function(F){f(F);
return g.bd},m:function(){q=null;v=!0;p=n.R;H=null}}}(),Wb=function(){return{instance:function(a){var c=Y.instance(a.alpha),d=Y.instance(a.beta);return{ke:function(){c.g(1);d.g(2)}}}}}(),Kb=function(){return{instance:function(a){var c=null,d=!1,e=!1,f=null,m=!1,n=!1,p=null,g="undefined"===typeof a.preprocessing?!1:a.preprocessing,v="undefined"===typeof a.preprocessingSize?a.size:a.preprocessingSize;a.mask&&(d=!0,Z&&void 0!==Z.Rd&&(a.mask=Z.Rd+a.mask),c=Y.instance({isFloat:!1,url:a.mask}));var A=!1;
a.customInputShader&&(A="s44",z.yc({name:"_",id:A,h:a.customInputShader,hh:["uSource"],precision:"lowp"}),z.T(A,[{type:"1i",name:"_",value:0}]));switch(g){case "sobel":p="s31";m=!0;break;case "meanNormalization":p="s32";m=!0;break;case "grayScale":p="s28";m=!1;break;case "grayScaleTilt":p="s29";n=!0;m=!1;break;case "rgbGrayTilt":p="s30";n=!0;m=!1;break;case "copy":p=A?A:"s0";break;case "inputLightRegulation":p=A?A:"s28";f=Xb.instance({ad:v,ud:a.size,qd:a.nBlurPass,eb:!1});e=!0;break;case "inputMix0":p=
"none";f=Yb.instance({D:v,Md:a.varianceMin,Bc:a.blurKernelSizePx,eb:!1});e=!0;break;case "direct":case "none":p="abort";break;default:p="s3"}n&&z.T(p,[{name:"u26",type:"1f",value:a.tilt}]);d&&(p+="Mask");var r=Y.instance({isFloat:!1,isPot:!1,width:a.size}),l={F:function(){return v},Mb:function(){return l.F()},Be:function(){return e?f.Nb():r},V:function(B){ua.da();"abort"!==p&&("none"!==p&&(z.set(p),m&&z.H("u27",1/a.size),r.aa(),d&&c.g(1),U.l(!1,!1),r.g(0),B=r),e&&f.process(B))},m:function(){r.remove();
d&&c.remove()}};return l}}}(),Lb=function(){return{instance:function(a){function c(h){f.forEach(function(I,G){m[G][0]=h[0][I];m[G][1]=h[1][I];m[G][2]=h[2][I];m[G][3]=h[3][I]});return m}"undefined"===typeof a.normalize&&(a.normalize=!1);var d={input:null,Qa:null,Sb:null,Z:null,lb:null,cc:null,dc:null},e=null,f=[],m=[],n=!1,p=null,g=!0,v=-1,A=a.isReorganize?a.isReorganize:!1,r=a.kernelsCount?!0:!1,l=a.dynPelu?Wb.instance(a.dynPelu):!1,B=l?!0:!1,w={isEnabled:!1};a.Ke?(a.sparsity="undefined"!==typeof a.sparsity?
a.sparsity:a.nb.Mb(),g=!1):"full"===a.connectivityUp&&(a.sparsity=a.nb.Mb());var k={elu:"s15",elu01:"s16",relu:"s14",arctan:"s18",sigmoid:"s13",copy:"s0",softplus:"s19",dynPelu:"s17"}[a.activation],q=a.sparsity*a.sparsity,H=!1,M=a.size,E="";if(a.maxPooling){switch(a.maxPooling.size){case 2:E="s33";break;case 4:E="s34"}H=!0;M/=a.maxPooling.size;d.cc=Y.instance({isFloat:!0,isPot:!1,width:M})}var Q=void 0!==a.Se&&a.Se?!0:!1,F=null,J=null,u=null;if(Q){F="s45"+a.index.toString();z.$c("s45",F,[((a.normalization.n-
1)/2).toFixed(1)]);z.T(F,[{type:"1i",name:"u1",value:0},{type:"2f",name:"u7",value:[1/a.size,1/a.size]},{type:"1f",name:"u6",value:a.normalization.alpha},{type:"1f",name:"u9",value:a.normalization.beta},{type:"1f",name:"u30",value:a.normalization.k}]);var t={isFloat:!0,isPot:!0,width:a.size};J=Y.instance(t);u=Y.instance(t)}var D=-1,K=null;g&&(d.Z=Y.instance({isFloat:!0,isPot:!1,width:a.size}));d.Qa=Y.instance(a.bias);var P={F:function(){return a.size},Mb:function(){return M},Wc:function(){return a.classesCount},
Td:function(h){e.g(h)},Ve:function(){a.remap&&a.remap.isEnabled&&(w={isEnabled:!0,Oe:Y.instance({isFloat:!1,isFlipY:!1,array:new Uint8Array(a.remap.maskTexture.data),width:a.remap.maskTexture.width,isPot:!1}),gb:a.remap.layers.map(function(h){return a.parent.Ae(h)}),depth:a.remap.depth})},ff:function(){switch(a.connectivityUp){case "direct":K=Zb.instance(a.connectivity);break;case "square":K=$b.instance(a.connectivity);break;case "squareFast":K=ac.instance(a.connectivity,a.activation);break;case "full":K=
bc.instance(a.connectivity);break;case "conv":v=a.kernelsCount,K=cc.instance(a.connectivity),A&&(d.lb=Y.instance({width:M,isFloat:!0,isFlipY:!1,isPot:!1}))}if(K.ya){var h=a.size*a.sparsity;D=Math.log(h/a.size)/Math.log(2);d.input=Y.instance({isMipmap:!0,isFloat:!0,isPot:!0,width:h,Xb:D});d.Sb=Y.instance({isFloat:!0,isPot:!0,width:a.size})}},V:function(h,I){e=h;K.ya?(d.input.aa(),r&&d.Qa.g(2),K.V(w),d.input.g(0),d.input.pe(D),d.Sb.aa(),r?z.set("s0"):(z.set("s27"),z.H("u25",q),d.Qa.g(1)),d.input.Ud(D,
0),U.l(!1,!1),z.set(k),Q?J.u():d.Z.u(),d.Sb.g(0),B&&l.ke(),U.l(!1,!1)):(d.Z.aa(),d.Qa.g(1),K.V());Q&&(z.set(F),u.u(),J.g(0),U.l(!1,!1),z.set("s46"),z.H("u6",1),d.Z.u(),u.g(1),U.l(!1,!1));if(g)return H?(d.cc.aa(),d.Z.g(0),z.set(E),z.pa("u7",1/a.size,1/a.size),U.l(!1,!1),I=d.cc):I=d.Z,I.g(0),A&&(d.lb.u(),z.set("s21"),z.pa("u12",v,M/v),U.l(!1,!1),I=d.lb,d.lb.g(0)),I;var G=d.Z;a.normalize&&(z.set("gpuRawAvg"===n?"s8":"s7"),z.H("u4",1/a.size),d.dc.aa(),d.Z.g(0),U.l(!1,!1),G=d.dc);h=null;switch(n){case "cpuRGBA2Float":G.Ic(!1);
I?h=P.We(G).then(p):(G=P.Xe(G),p(G));break;case "cpuMeanFloat":G.Ic(!0);I?h=G.Ze().then(p):(G=G.$e(),p(G));break;case "gpuRawAvg":case "gpuRaw":G.g(0);case "none":null!==p&&p(G)}I&&null===h&&(h=Promise.resolve());return h},de:function(h){h&&(n=h.ec||"none",p=h.bc||null);d.Z=Y.instance({isFloat:!0,isPot:!0,isMipmap:!1,width:a.size});h="undefined"!==typeof a.classesCount&&a.classesCount?a.classesCount:a.size*a.size;for(var I=0,G=0,N=0;I<h;++I)f.push(G+(a.size-1-N)*a.size),m.push([-1,-1,-1,-1]),++G,
G===a.size&&(G=0,++N);a.normalize&&(d.dc=Y.instance({isFloat:!0,isPot:!0,width:a.size}))},We:function(h){return h.Ye().then(c)},Xe:function(h){h=h.zd();c(h);return m},m:function(){for(var h in d){var I=d[h];I&&I.remove()}K&&(K.m(),K=null)}};a.nb&&P.ff(a.nb);return P}}}(),Zb=function(){return{instance:function(a){var c=Y.instance(a.weights);return{ya:!0,Ya:function(){return 1},m:function(){c.remove()},Ee:function(){return c},V:function(){z.set("s26");c.g(1);U.l(!1,!1)}}}}}(),bc=function(){return{instance:function(a){var c=
a.fromLayerSize,d=Y.instance(a.weights);return{ya:!0,Ya:function(){return c},m:function(){d.remove()},V:function(e){if(e.isEnabled){z.set("s24");e.Oe.g(3);var f,m=Math.min(e.gb.length,e.depth);for(f=0;f<m;++f)e.gb[f].Td(4+f)}else z.set("s23");z.H("u16",a.toLayerSize);d.g(1);U.l(!1,!1)}}}}}(),$b=function(){return{instance:function(a){for(var c=a.fromLayerSize,d=a.toLayerSize,e=a.toSparsity,f=e*d,m=f/c,n=c/d,p=0,g=0,v=0,A=Array(e*d*e*d*4),r=Array(e*d*e*d*4),l=Array(c*c),B=0;B<l.length;++B)l[B]=0;B=
Math.floor(e/2);for(var w=.5/d,k=.5/c,q=.5/f,H=0;H<d;++H)for(var M=Math.round(H*n),E=0;E<d;++E){var Q=Math.round(E*n),F=H/d,J=E/d;F+=w;J+=w;for(var u=0;u<e;++u){var t=M+u-B;0>t&&(t+=c);t>=c&&(t-=c);for(var D=0;D<e;++D){var K=p/f,P=g/f,h=Q+D-B;0>h&&(h+=c);h>=c&&(h-=c);var I=t/c,G=h/c;P=1-P-1/f;I+=k;G+=k;K+=q;P+=q;var N=H*e+u,ha=E*e+D;ha=d*e-ha-1;N=ha*d*e+N;A[4*N]=K;A[4*N+1]=P;A[4*N+2]=I;A[4*N+3]=G;G=l[h*c+t]++;N=G%m;I=t*m+N;h=h*m+(G-N)/m;h=c*m-1-h;h=h*c*m+I;r[4*h]=K;r[4*h+1]=P;r[4*h+2]=F;r[4*h+3]=
J;++p>=f&&(p=0,++g);++v}}}l=null;var ra=Y.instance(a.weights);delete a.weights.data;var za=Y.instance({width:f,isFloat:!0,array:new Float32Array(r),isPot:!0});r=null;var x=Y.instance({width:f,isFloat:!0,array:new Float32Array(A),isPot:!0});A=null;return{ya:!0,Ya:function(){return m},m:function(){za.remove();x.remove();ra.remove()},V:function(){z.set("s22");ra.g(1);x.g(2);U.l(!1,!1)}}}}}(),cc=function(){return{instance:function(a){var c=a.kernelsCount,d=a.toSparsity,e=d*a.toLayerSize/a.fromLayerSize,
f=Y.instance(a.weights);return{ya:!0,Ya:function(){return e},zg:function(){return d},Ee:function(){return f},m:function(){f.remove()},V:function(){z.set("s25");z.H("u22",c);z.H("u23",d);z.H("u16",a.toLayerSize);z.H("u24",a.fromLayerSize);f.g(1);U.l(!1,!1)}}}}}(),ac=function(){return{instance:function(a,c){var d=a.fromLayerSize,e=a.toLayerSize,f=a.toSparsity,m=a.stride?a.stride:1,n=f*e/d,p=e<d,g=d/e,v=Y.instance(a.weights),A="s47"+[d.toString(),e.toString(),f.toString(),m.toString(),c].join("_");z.me(A)||
(a=Ub.qe(c,"gl_FragColor","gl_FragColor"),e=[{type:"1f",name:"u16",value:e},{type:"1f",name:"u29",value:m}],p&&e.push({type:"1f",name:"u24",value:d}),d=[(p?n:f).toFixed(1),a],p&&d.push(g.toFixed(1)),z.$c(p?"s39":"s38",A,d),z.T(A,e.concat([{type:"1i",name:"u14",value:0},{type:"1i",name:"u21",value:1},{type:"1i",name:"u13",value:3}])));return{ya:!1,Ya:function(){return n},m:function(){v.remove()},V:function(){z.set(A);v.g(3);U.l(!1,!1)}}}}}(),Xb=function(){return{instance:function(a){var c=a.qd?a.qd:
3,d=a.ad?a.ad:64,e=a.ud?a.ud:64,f=a.eb?!0:!1;a={isFloat:!1,width:d,isPot:!1,isFlipY:!1};var m=Y.instance(a),n=Y.instance(a),p=Y.instance(a),g=Y.instance(a),v=Y.instance({isFloat:!0,width:e,isPot:!1,isFlipY:!1}),A=1/d;return{process:function(r){z.set("s35");g.u();U.l(f,!1);z.set("s36");for(var l=0;l<c;++l)m.u(),z.pa("u7",A,0),U.l(f,!1),p.u(),g.g(0),U.l(f,!1),n.u(),m.g(0),z.pa("u7",0,A),U.l(f,!1),g.u(),p.g(0),U.l(f,!1),l!==c-1&&n.g(0);z.set("s37");v.u();r.g(0);n.g(1);g.g(2);U.l(f,!1);v.g(0)},Nb:function(){return v}}}}}(),
Yb=function(){return{instance:function(a){function c(v){return Y.instance({isFloat:v,width:d.D,isPot:!1,isFlipY:!1})}var d=Object.assign({Md:.1,Bc:9,D:128,eb:!1},a),e=c(!1),f=[c(!1),c(!1),c(!1)],m=[c(!1),c(!1),c(!1)],n=c(!0),p=[e,m[0],m[1]];a="uniform sampler2D u1;const float e=1.1111,g=2.2222;uniform vec2 u31;varying vec2 vv0;void main(){float b=0.,c=0.;for(float a=-e;a<=e;a+=1.){vec2 i=u31*a,j=vv0+i*g;float d=1.2*a/e,f=exp(-d*d);b+=f*texture2D(u1,j).r,c+=f;}b/=c,gl_FragColor=vec4(b,0.,0.,1.);}".replace("1.1111",
Math.round((d.Bc-1)/2).toFixed(2)).replace("2.2222",(1/d.D).toFixed(6));var g={u1:0};z.zc([{id:"s49",name:"_",h:"uniform sampler2D u1;varying vec2 vv0;const vec3 f=vec3(.2126,.7152,.0722),g=vec3(1.,1.,1.);void main(){vec3 b=texture2D(u1,vv0).rgb;float a=dot(b,f);gl_FragColor=vec4(a,a,a,a);}",j:g,i:["u1"],precision:"lowp"},{id:"s50",name:"_",h:a,j:g,i:["u1","u31"],precision:"lowp"},{id:"s51",name:"_",h:"uniform sampler2D u32,u33,u34,u35;const float f=1.1111;const vec3 g=vec3(1.,1.,1.);varying vec2 vv0;void main(){vec3 a=texture2D(u32,vv0).rgb;float c=texture2D(u33,vv0).r,d=texture2D(u34,vv0).r,h=texture2D(u35,vv0).r,i=a.r*a.r;vec3 b=vec3(c,d,h),j=max(g*f,abs(i-b*b)),k=sqrt(j);gl_FragColor=vec4(a.r,(a-b)/k);}".replace("1.1111",
d.Md.toFixed(4)),j:{u32:0,u33:1,u34:2,u35:3},i:["u32","u33","u34","u35"],precision:"highp"}]);return{process:function(){z.set("s49");e.aa();U.l(d.eb,!1);z.set("s50");for(var v=0;3>v;++v)z.pa("u31",1,0),f[v].u(),p[v].g(0),U.l(!1,!1),z.pa("u31",0,1),m[v].u(),f[v].g(0),U.l(!1,!1);z.set("s51");n.u();e.g(0);m[0].g(1);m[1].g(2);m[2].g(3);U.l(!1,!1);n.g(0)},Nb:function(){return n}}}}}(),W={De:function(){return W.Hc()?document.createElement("video"):!1},Ha:function(a,c){a[c]=!0;a.setAttribute(c,"true")},
$d:function(){var a=!1,c=navigator.userAgent||navigator.vendor||window.opera;if(/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i.test(c)||/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(c.substr(0,
4)))a=!0;return a},Ec:function(){return/iPad|iPhone|iPod/.test(navigator.userAgent)&&!window.MSStream},re:function(){var a=navigator.appVersion.match(/OS (\d+)_(\d+)_?(\d+)?/);return a&&a.length&&2<a.length?[parseInt(a[1],10),parseInt(a[2],10),parseInt(a[3]||0,10)]:[0,0,0]},ld:function(){try{return window.matchMedia("(orientation: portrait)").matches?!0:!1}catch(a){return window.innerHeight>window.innerWidth}},Zd:function(){return W.Fc()||W.Ec()},Fc:function(){var a=navigator.userAgent.toLowerCase();
return-1!==a.indexOf("safari")&&-1===a.indexOf("chrome")?!0:!1},eg:function(){return W.$d()?W.ld()?window.innerHeight/window.innerWidth*45:45:45},Hc:function(){return navigator.mediaDevices&&navigator.mediaDevices.getUserMedia?!0:!1},pause:function(a){a.pause()},Ug:function(a){a.play()},release:function(a){a.pause();a.videoStream&&a.videoStream.stop();a.videoStream=null},Gc:function(a){if(!a)return a;var c=null;if(a.video){var d=function(e){return e&&"object"===typeof e?Object.assign({},e):e};c={};
"undefined"!==typeof a.video.width&&(c.width=d(a.video.width));"undefined"!==typeof a.video.height&&(c.height=d(a.video.height));"undefined"!==typeof a.video.facingMode&&(c.facingMode=d(a.video.facingMode))}c={audio:a.audio,video:c};"undefined"!==typeof a.deviceId&&W.xc(c,a.deviceId);return c},xc:function(a,c){c&&(a.video=a.video||{},a.video.deviceId={exact:c},a.video.facingMode&&delete a.video.facingMode)},Id:function(a){var c=a.video.width;a.video.width=a.video.height;a.video.height=c;return a},
ce:function(a){function c(l){return[480,576,640,648,720,768,800,960,1080,1152,1280,1366,1920].sort(function(B,w){return Math.abs(B-l)-Math.abs(w-l)})}function d(l){var B=W.Gc(a);l=l(B);f.push(l);e(l)}function e(l){if(l.video&&l.video.facingMode&&l.video.facingMode.exact){var B=l.video.facingMode.exact;l=W.Gc(l);delete l.video.facingMode.exact;l.video.facingMode.ideal=B;f.push(l)}}var f=[];if(!a||!a.video)return f;e(a);if(a.video.width&&a.video.height){if(a.video.width.ideal&&a.video.height.ideal){var m=
c(a.video.width.ideal).slice(0,3),n=c(a.video.height.ideal).slice(0,3),p={},g=0;for(p.ka=void 0;g<m.length;p={ka:p.ka},++g){p.ka=m[g];var v={},A=0;for(v.ja=void 0;A<n.length;v={ja:v.ja},++A)if(v.ja=n[A],p.ka!==a.video.width.ideal||v.ja!==a.video.height.ideal){var r=Math.max(p.ka,v.ja)/Math.min(p.ka,v.ja);r<4/3-.1||r>16/9+.1||d(function(l,B){return function(w){w.video.width.ideal=l.ka;w.video.height.ideal=B.ja;return w}}(p,v))}}}d(function(l){return W.Id(l)})}a.video.width&&a.video.height&&(a.video.width.ideal&&
a.video.height.ideal&&d(function(l){delete l.video.width.ideal;delete l.video.height.ideal;return l}),d(function(l){delete l.video.width;delete l.video.height;return l}));a.video.facingMode&&(d(function(l){delete l.video.facingMode;return l}),a.video.width&&a.video.height&&d(function(l){W.Id(l);delete l.video.facingMode;return l}));f.push({audio:a.audio,video:!0});return f},pf:function(a){if(W.ld()){if(!a||!a.video)return!1;var c=a.video.width,d=a.video.height;if(!c||!d)return!1;if(c.ideal&&d.ideal&&
c.ideal>d.ideal)return a.video.height=c,a.video.width=d,!0}return!1},ib:function(a){a.volume=0;W.Ha(a,"muted");if(W.Fc()){if(1===a.volume){var c=function(){a.volume=0;window.removeEventListener("mousemove",c,!1);window.removeEventListener("touchstart",c,!1)};window.addEventListener("mousemove",c,!1);window.addEventListener("touchstart",c,!1)}setTimeout(function(){a.volume=0;W.Ha(a,"muted")},5)}},Kd:function(a,c,d){return null===a?Promise.resolve():new Promise(function(e,f){if(a.srcObject&&a.srcObject.getVideoTracks){var m=
a.srcObject.getVideoTracks();1!==m.length?f("INVALID_TRACKNUMBER"):(m=m[0],c?W.get(a,e,f,d):(m.stop(),e()))}else f("BAD_IMPLEMENTATION")})},Zc:function(a,c,d,e){function f(n){m||(m=!0,d(n))}var m=!1;return navigator.mediaDevices.getUserMedia(e).then(function(n){function p(){setTimeout(function(){if(a.currentTime){var v=a.videoWidth,A=a.videoHeight;if(0===v||0===A)f("VIDEO_NULLSIZE");else{v&&(a.style.width=v.toString()+"px");A&&(a.style.height=A.toString()+"px");v={Yd:null,kf:null,Pe:null};try{var r=
n.getVideoTracks()[0];r&&(v.Pe=r,v.Yd=r.getCapabilities(),v.kf=r.getSettings())}catch(l){}W.Zd()?a.parentNode&&null!==a.parentNode?(m||c(a,n,v),setTimeout(function(){a.play()},100)):(document.body.appendChild(a),W.ib(a),m||c(a,n,v),setTimeout(function(){a.style.transform="scale(0.0001,0.0001)";a.style.position="fixed";a.style.bottom="0px";a.style.right="0px";W.ib(a);setTimeout(function(){a.play()},100)},80)):m||c(a,n,v)}}else f("VIDEO_NOTSTARTED")},700)}function g(){a.removeEventListener("loadeddata",
g,!1);var v=a.play();W.ib(a);"undefined"===typeof v?p():v.then(function(){p()}).catch(function(){f("VIDEO_PLAYPROMISEREJECTED")})}"undefined"!==typeof a.srcObject?a.srcObject=n:(a.src=window.URL.createObjectURL(n),a.videoStream=n);W.ib(a);a.addEventListener("loadeddata",g,!1)}).catch(function(n){f(n)})},get:function(a,c,d,e){if(!a)return d&&d("VIDEO_NOTPROVIDED"),!1;if(!W.Hc())return d&&d("MEDIASTREAMAPI_NOTFOUND"),!1;if(e&&e.video){if(W.Ec()){var f=W.re();0!==f[0]&&(12>f[0]||12===f[0]&&2>f[1])&&
W.pf(e)}e.video.width&&e.video.width.ideal&&(a.style.width=e.video.width.ideal+"px");e.video.height&&e.video.height.ideal&&(a.style.height=e.video.height.ideal+"px")}W.Ha(a,"autoplay");W.Ha(a,"playsinline");e&&e.audio?a.volume=0:W.Ha(a,"muted");W.Zc(a,c,function(){function m(p){if(0===p.length)d("INVALID_FALLBACKCONSTRAINTS");else{var g=p.shift();W.Zc(a,c,function(){m(p)},g)}}var n=W.ce(e);m(n)},e)},Ce:function(a){if(!navigator.mediaDevices||!navigator.mediaDevices.enumerateDevices)return a(!1,"NOTSUPPORTED"),
!1;navigator.mediaDevices.enumerateDevices().then(function(c){(c=c.filter(function(d){return d.kind&&-1!==d.kind.toLowerCase().indexOf("video")&&d.label&&d.deviceId}))&&c.length&&0<c.length?a(c,!1):a(!1,"NODEVICESFOUND")}).catch(function(){a(!1,"PROMISEREJECTED")})},Hf:function(a,c,d){var e={};e[c]=d;c=[];c.push(e);a.applyConstraints({advanced:c}).catch(function(){})}},qa=function(){var a={n:5,Zb:1,nd:0,Xa:[30,45],Ua:[2,200],k:.7,vf:200,Ue:.05},c=-1,d=null,e=-1,f=-1,m=0,n=-1,p=-1,g=0,v=0,A=a.Ua[1],
r={Xc:function(){switch(c){case -1:return-1;case 0:return p+d.nd;case 1:return g}},ig:function(l){return Math.pow(Math.min(Math.max(n,0),d.n-1)/(d.n-1),l||1)},A:function(l){d=Object.assign({},a,l);n=p=d.Zb;c=0;r.reset()},rf:function(l){l=("undefined"===typeof l?Date.now():l)||0;var B=Math.min(Math.max(l-v,d.Ua[0]),d.Ua[1]);A=B;v=l;var w=-1===e?0:d.k;e=Math.min(Math.max(1E3/B,5),120)*(1-w)+e*w;l-f>d.vf&&5<++m&&(B=d.k,n=n*(1-B)+(e<d.Xa[0]?p-1:e>d.Xa[1]?p+1:p)*B,Math.abs(n-p)>1-d.Ue&&(B=Math.min(Math.max(Math.round(n),
0),d.n-1),B!==p&&(n=p=B,e=(d.Xa[1]-d.Xa[0])/2)),f=l)},jc:function(l){g=l;c=1},tc:function(){c=0;r.reset()},reset:function(){A=a.Ua[1];f=e=-1;m=0},ue:function(){return A}};return r}(),Ma=function(){function a(){d(r+v.Yb);l.port.postMessage("DONE")}function c(){k.Oa=0===v.Na?window.requestAnimationFrame(d):window.requestAnimationFrame(e)}function d(E){w.wa&&null!==A&&(E-=r,E=Math.min(Math.max(E,v.Jc[0]),v.Jc[1]),r+=E,m(),A(r))}function e(E){w.wa&&(k.timeout=window.setTimeout(d.bind(null,E),v.Na))}function f(){A=
null;w.wa=!1;m()}function m(){k.Oa&&(window.cancelAnimationFrame(k.Oa),k.Oa=null);k.timeout&&(window.clearTimeout(k.timeout),k.timeout=null)}function n(E){E&&!w.ha?(w.ha=!0,B&&qa.tc(),l.port.postMessage("STOP"),ba.Jd(!0),c()):!E&&w.ha&&(w.ha=!1,B&&qa.jc(1),ba.Jd(!1),l.port.postMessage("START"))}function p(E){E.target.hidden?H():q()}var g={gd:!0,Jc:[1,200],Yb:20,Na:0},v=null,A=null,r=0,l=null,B=!1,w={na:!1,ha:!0,Wb:!1,Vb:!1,Tb:!1,wa:!1},k={Oa:null,timeout:null},q=n.bind(null,!0),H=n.bind(null,!1),
M={A:function(E){v=Object.assign(g,E);Object.assign(w,{ha:!0,na:!0,wa:!1});if(v.gd){E=!1;try{if("undefined"===typeof SharedWorker){var Q=URL.createObjectURL(new Blob(["let handler = null;\n self.addEventListener('message', function(e){\n if (handler !== null){\n clearTimeout(handler);\n handler = null;\n }\n switch (e.data) {\n case 'START':\n case 'DONE':\n handler = setTimeout(function(){\n self.postMessage('TICK');\n }, "+
v.Yb.toString()+");\n break;\n case 'STOP':\n break;\n };\n }, false);"],{type:"text/javascript"})),F=new Worker(Q);F.addEventListener("message",a);l={xd:F,port:F};w.Wb=!0}else{var J=URL.createObjectURL(new Blob(["let handler = null;\n onconnect = function(e) {\n const port = e.ports[0];\n port.addEventListener('message', function(e) {\n \n if (handler !== null){\n clearTimeout(handler);\n handler = null;\n }\n switch (e.data) {\n case 'START':\n case 'DONE':\n handler = setTimeout(function(){\n port.postMessage('TICK');\n }, "+
v.Yb.toString()+");\n break;\n case 'STOP':\n break;\n };\n \n });\n \n port.start();\n } // end onconnect()"],{type:"text/javascript"})),u=new SharedWorker(J);u.port.start();u.port.addEventListener("message",a);l={xd:u,port:u.port};w.Vb=!0}E=!0}catch(t){}E&&("onvisibilitychange"in document?document.addEventListener("visibilitychange",p):(window.addEventListener("blur",H),window.addEventListener("focus",q)),w.Tb=!0)}B=
"undefined"!==typeof qa},m:function(){f();w.Tb&&("onvisibilitychange"in document?document.removeEventListener("visibilitychange",p):(window.removeEventListener("blur",H),window.removeEventListener("focus",q)),w.Tb=!1);w.Vb?(l.port.close(),w.Vb=!1):w.Wb&&(l.xd.terminate(),w.Wb=!1);Object.assign(w,{ha:!0,na:!1,wa:!1});A=null},Kg:function(){return w.ha},update:function(E){Object.assign(v,E)},af:function(E){w.na||M.A({});m();w.wa=!0;A=E;w.ha&&c()},stop:f};return M}(),xb=function(){var a={sd:4,mb:[1.5,
1.5,2],O:[.1,.1,.1],Bd:1,D:-1,M:-1,mf:2,Te:1,Cd:!0,le:.8},c=null,d=[],e=0,f=[.5,.5,1];return{A:function(m){c=Object.assign({},a,m);d.splice(0);m=c.mb[0]*c.O[0];var n=c.mb[1]*c.O[1],p=1/(1+c.mb[2]*c.O[2]),g=c.Bd*Math.min(c.D,c.M),v=g/c.D;g/=c.M;var A=.5*c.le;A*=A;for(var r=0;r<c.sd;++r){var l=Math.pow(p,r),B=v*l,w=g*l;l=B*m;var k=w*n,q=B/2;w/=2;for(var H=1+(1-q-q)/l,M=1+(1-w-w)/k,E=0;E<M;++E)for(var Q=w+E*k,F=Q-.5,J=0;J<H;++J){var u=q+J*l,t=u-.5;t*t+F*F>A||d.push([u,Q,B*c.Te])}}c.Cd&&d.sort(function(D,
K){var P=D[0]-.5;D=D[1]-.5;var h=K[0]-.5;K=K[1]-.5;return P*P+D*D-(h*h+K*K)})},get:function(){var m=d.length;if(0===m)return f;e>=m&&(e=0);var n=d[Math.floor(e)];e=(e+1/c.mf)%m;return n}}}(),Z={neuralNetworkPath:"NN_DEFAULT.json",ca:0,ub:[2,7],bf:{threshold:1,nScaleLevels:2,scale0Factor:.8,overlapFactors:[2,2,3],scanCenterFirst:!0,nDetectsPerLoop:-1},sf:50,pd:.5,od:.4,Qe:8,lf:{translationFactorRange:[.0015,.005],rotationFactorRange:[.003,.02],qualityFactorRange:[.9,
.98],alphaRange:[.05,1]},Ka:[.65,1,.262],O:[.092,.092,.3],Od:.2,Qd:2,Pd:.1,Re:8,rd:1,oe:Za.hb.bind(null,.3,.7),yf:20,fe:!0,Gd:3},na={facingMode:"user",idealWidth:800,idealHeight:600,minWidth:480,maxWidth:1920,minHeight:480,maxHeight:1920,rotate:0,flipX:!1},fa={$b:-3,Ne:-1,error:-2,ready:1,play:2,pause:3},ma=fa.$b,y=null,dc={bb:!1,nc:null,element:null,N:null,G:[0,0],L:[.5,.5],v:[.5,0,0,.5],ob:0,Ga:null,ab:!1},O=null,ec={Fa:null,Ra:null,antialias:!0,vc:"./",Aa:null,ea:null,ca:Z.ca,wd:Z.ca,cb:!1,ra:!0},
Oa=null,oa=null,wa=null,Pa=1,Na={ic:-1,Cb:-1},aa=null,fc={D:0,M:0,G:[0,0],va:null},X={za:null,buffer:null,O:null,Ka:null,Y:Z.rd,Ia:null},Sa=null,pa=null,L={o:1,ma:0,W:null,hd:!1,md:0,ac:0},ib=[],jb=[],Ib={VERSION:"2.1.2",init:function(a){function c(){ma!==fa.error&&2===++e&&(Ja(),Bb(),Ia(),O.Fa&&(ma=fa.ready,O.Fa(!1,{GL:b,canvasElement:O.ea,videoTexture:y.N.get(),videoTransformMat2:y.v,maxFacesDetected:L.o,videoElement:y.element}),fb()),eb())}if(ma!==fa.$b)return a.callbackReady&&a.callbackReady("ALREADY_INITIALIZED"),
!1;ma=fa.Ne;y=Object.assign({},dc);O=Object.assign({},ec);aa=Object.assign({},fc);L.W=[0];X.O=Z.O.slice(0);X.Ka=Z.Ka.slice(0);"undefined"!==typeof a.antialias&&(O.antialias=a.antialias);a.callbackReady&&(O.Fa=a.callbackReady);a.callbackTrack&&(O.Ra=a.callbackTrack);a.nExpressions&&(X.Y=a.nExpressions);a.expressionsEasings&&(X.Ia=a.expressionsEasings);"undefined"!==typeof a.animateDelay&&(O.ca=a.animateDelay);"undefined"!==typeof a.NNCPath&&(O.vc=a.NNCPath);"undefined"!==typeof a.NNC&&(O.Aa=a.NNC);
"undefined"!==typeof a.maxFacesDetected&&(L.o=Math.max(1,a.maxFacesDetected));"undefined"!==typeof a.followZRot&&(O.ra=a.followZRot?!0:!1);if(L.o>Z.Qe)return Ha("MAXFACES_TOOHIGH"),!1;if(!a.canvasId&&!a.canvas)return Ha("NO_CANVASID"),!1;O.ea=a.canvas?a.canvas:document.getElementById(a.canvasId);if(!O.ea)return Ha("INVALID_CANVASID"),!1;aa.D=O.ea.width;aa.M=O.ea.height;if(!aa.D||!aa.M)return Ha("INVALID_CANVASDIMENSIONS"),!1;for(var d=0;d<L.o;++d)ib.push(new Float32Array(Z.Re)),jb.push(0);Ma.A({gd:a.isKeepRunningOnWinFocusLost||
!1,Na:O.ca});qa.A({Zb:0,n:Z.ub[1]-Z.ub[0]+1,nd:Z.ub[0]});oa=Object.create(Z.bf);a.scanSettings&&(Object.assign(oa,a.scanSettings),-1!==oa.nDetectsPerLoop?qa.jc(oa.nDetectsPerLoop):qa.tc());wa=Object.create(Z.lf);a.stabilizationSettings&&Object.assign(wa,a.stabilizationSettings);var e=0;a.videoSettings&&a.videoSettings.videoElement?$a(a.videoSettings.videoElement,c):(a.videoSettings&&Object.assign(na,a.videoSettings),Db(a.onWebcamAsk,a.onWebcamGet,function(f){$a(f,c)}));Pb(function(f){if(!Qb())return!1;
Oa=new Jb({gb:f.layers,ec:"gpuRawAvg",bc:Sb});z.zc([{id:"s53",name:"_",qa:"attribute vec2 a0;uniform mat2 u36;varying vec2 vv0;void main(){gl_Position=vec4(a0,0.,1.),vv0=vec2(.5,.5)+u36*a0;}",Pa:["a0"],Ca:[2],h:"uniform sampler2D u1;varying vec2 vv0;void main(){gl_FragColor=texture2D(u1,vv0);}",i:["u1","u36"],precision:"lowp"},{id:"s54",name:"_",h:"uniform sampler2D u1;varying vec2 vv0;void main(){gl_FragColor=texture2D(u1,vv0);}",qa:"attribute vec2 a0;uniform sampler2D u37;uniform mat2 u36;uniform vec2 u38;uniform float u39,u40,u41;varying vec2 vv0;void main(){vec4 a=texture2D(u37,vec2(.17,u39));vec2 f=a.gb,g=a.a*u38,b=a0;b.x*=u41;float c=cos(u40),d=sin(u40);vec2 h=mat2(c,d,-d,c)*b,i=f+h*.5*g,j=i-.5;vv0=.5+2.*u36*j,gl_Position=vec4(a0,0.,1.);}",
Pa:["a0"],Ca:[2],i:"u1 u37 u38 u39 u40 u41 u36".split(" "),precision:"lowp"},{id:"s55",name:"_",h:"uniform sampler2D u42,u37;uniform vec3 u43,u44;uniform float u45,u46,u39,u47,u40,u48;const vec4 e=vec4(.25,.25,.25,.25);void main(){vec4 d=texture2D(u42,vec2(.625,.625)),f=texture2D(u42,vec2(.875,.625)),a=texture2D(u37,vec2(.17,u39));float g=dot(d-f,e);bool h=g>u46;h?a.r=2.:a.r>u45?a.r=0.:a.r>1.9?a.r+=1.:0.,a.r*=u47;if(a.r<.9)a=vec4(1.,u43);else{a.r*=step(1.9,a.r);float i=dot(e,texture2D(u42,vec2(.875,.875))),j=dot(e,texture2D(u42,vec2(.125,.625))),k=dot(e,texture2D(u42,vec2(.375,.625))),b=cos(u40),c=sin(u40);vec2 l=mat2(b,c*u48,-c/u48,b)*vec2(i,j);a.gba+=vec3(l,k)*u44*a.a;}gl_FragColor=a;}",
qa:"attribute vec2 a0;void main(){gl_Position=vec4(a0,0.,1.);}",i:"u42 u37 u43 u45 u44 u47 u40 u48 u46 u39".split(" ")},{id:"s56",name:"_",qa:"attribute vec2 a0;void main(){gl_Position=vec4(a0,0.,1.);}",h:"uniform sampler2D u42;const vec4 e=vec4(.25,.25,.25,.25);const vec3 f=vec3(.5,.5,.5);void main(){float a=dot(e,texture2D(u42,vec2(.125,.875))),b=dot(e,texture2D(u42,vec2(.375,.875))),c=dot(e,texture2D(u42,vec2(.625,.875))),d=dot(e,texture2D(u42,vec2(.625,.625)));vec3 g=vec3(a,b,c)*.5+f;gl_FragColor=vec4(g,d);}",
i:["u42"]},{id:"s57",name:"_",qa:"attribute vec2 a0;void main(){gl_Position=vec4(a0,0.,1.);}",h:"uniform sampler2D u42;const vec4 e=vec4(.25,.25,.25,.25);void main(){float a=dot(e,texture2D(u42,vec2(.375,.375))),b=dot(e,texture2D(u42,vec2(.625,.375))),c=dot(e,texture2D(u42,vec2(.875,.375))),d=dot(e,texture2D(u42,vec2(.125,.125)));gl_FragColor=vec4(a,b,c,d);}",i:["u42"]},{id:"s52",name:"_",h:"uniform sampler2D u37;uniform vec2 u49;uniform float u50;varying vec2 vv0;void main(){float f=step(.5,mod(gl_FragCoord.y+1.5,2.)),c=step(.33,vv0.x);vec4 a=texture2D(u37,vv0+u49);a.a=mix(a.a*u50,a.a,c);vec4 d=floor(255.*a),g=255.*(255.*a-d),b=mix(d,g,f)/255.;b.x=mix(step(a.x,1.5),b.x,c),gl_FragColor=b;}",
i:["u37","u50","u49"]}]);wb();Ob();lb();kb();c()});return!0},destroy:function(){Ma.m();return new Promise(function(a){Ib.toggle_pause(!0,!0).finally(function(){Oa&&Oa.m();Qa.m();Oa=pa=Sa=null;ib.splice(0);jb.splice(0);aa.va=null;X.za=null;y.N=null;ma=fa.$b;a()}).catch(function(){})})},toggle_pause:function(a,c){if(!Ya())return Promise.reject("NOT_READY");var d=null;d=y.ab?Promise.resolve():c?W.Kd(y.element,!a,y.Ga):Promise.resolve();a?sb():d.then(function(){eb()});return d},update_videoSettings:function(a){sb();
return new Promise(function(c,d){W.Kd(y.element,!1,y.Ga).then(function(){Object.assign(na,a);Db(null,null,function(e){$a(e,function(){Ja();Ia();eb();c()})})}).catch(d)})},toggle_slow:function(a){Ya()&&ma===fa.play&&(a&&!O.cb?(O.wd=O.ca,oa.nDetectsPerLoop=1,this.set_animateDelay(Z.Af),O.cb=!0):!a&&O.cb&&(oa.nDetectsPerLoop=-1,this.set_animateDelay(O.wd),O.cb=!1))},set_animateDelay:function(a){O.ca=a;Ma.update({Na:O.ca})},resize:function(){if(!Ya())return!1;var a=O.ea.width,c=O.ea.height;if(!mb()&&
a===aa.D&&c===aa.M)return!1;aa.D=a;aa.M=c;z.R();lb();kb();Ja();Ia();return!0},set_inputTexture:function(a,c,d){y.G[0]=c;y.G[1]=d;y.N=Y.instance({width:c,height:d,Pb:a});y.bb=!0;Ja();fb();Ia()},reset_GLState:function(){fb();aa.va.remove();X.za.remove();wb()},render_video:function(){ua.P();z.set("s53");b.viewport(0,0,aa.D,aa.M);y.N.g(0);U.l(!0,!0)},reset_inputTexture:function(){y.bb=!1;y.N=y.nc;mb();Ja();Ia()},get_videoDevices:function(a){return W.Ce(a)},set_scanSettings:function(a){Object.assign(oa,
a);-1!==oa.nDetectsPerLoop?qa.jc(oa.nDetectsPerLoop):qa.tc();lb();kb()},set_stabilizationSettings:function(a){Object.assign(wa,a)},set_videoOrientation:function(a,c){Ya()&&(na.flipX=c,na.rotate=a,Ja(),Ia())},update_videoElement:function(a,c){$a(a?a:y.element,function(){Bb();Ja();Ia();c&&c()})},create_new:function(){return window.JEELIZFACEFILTERGEN()}};return Ib};window.JEELIZFACEFILTER=window.JEELIZFACEFILTERGEN();
;return JEELIZFACEFILTER||window.JEELIZFACEFILTER;})();

+ 1030
- 0
vendors/jeelizFaceFilter/three.min.js
文件差异内容过多而无法显示
查看文件


+ 166
- 0
vendors/jeelizFaceFilter/typescript/JeelizCanvas2DHelper.ts 查看文件

@@ -0,0 +1,166 @@

/*
Usage: JeelizCanvas2DHelper(spec) where spec is the returned object of the initialization function (callbackReady)
Return an object width these properties:

- canvas: the CANVAS element
- ctx: the canvas drawing context
- update_canvasTexture: function to launch each time the canvas has been updated (somethink has been drawn on it)
- draw: draw the video with the canvas above
- getCoordinates: transform the detectedState relative 2D viewport coords into canvas 2D pixel coordinates
- resize: to call if the HTML canvas size has changed
*/

import { IJeelizFaceFilterDetectState, IJeelizFaceFilterInitResult as IJeelizFaceFilterInitResult } from "./JeelizFaceFilterInterfaces";

export class JeelizCanvas2DHelper {

private GL : WebGL2RenderingContext | null = null;
private CANVASTEXTURE : WebGLTexture | null= null;
private CANVASTEXTURENEEDSUPDATE : boolean | null= null;
private SHADERCOPY : WebGLProgram | null | undefined= null;
private VIDEOTEXTURE : WebGLUniformLocation | null= null;
private VIDEOTEXTURETRANSFORMMAT2 : number[] | null= null;
private UUVTRANSFORM : WebGLUniformLocation | null= null;
private spec:IJeelizFaceFilterInitResult;

public CV : HTMLCanvasElement | null= null;
public CANVAS2D: HTMLCanvasElement | null = null;
public CTX : any | CanvasRenderingContext2D= null;

public COORDINATES = {
x:0, y:0, s:0, w:0, h:0
};

constructor(spec:IJeelizFaceFilterInitResult){
this.spec = spec;
// affect some globalz:
this.GL = spec.GL;
this.CV = spec.canvasElement;
this.VIDEOTEXTURE = spec.videoTexture;
this.VIDEOTEXTURETRANSFORMMAT2 = spec.videoTransformMat2;
// create and size the 2D canvas and its drawing context:
this.CANVAS2D = document.createElement('canvas');
if (this.CANVAS2D == null) return;
this.CANVAS2D.width = this.CV.width;
this.CANVAS2D.height = this.CV.height;
this.CTX = this.CANVAS2D.getContext('2d');
// create the Webthis.GL texture with the canvas:
this.CANVASTEXTURE = this.GL.createTexture();
this.GL.bindTexture(this.GL.TEXTURE_2D, this.CANVASTEXTURE);
this.GL.texImage2D(this.GL.TEXTURE_2D, 0, this.GL.RGBA, this.GL.RGBA, this.GL.UNSIGNED_BYTE, this.CANVAS2D);
this.GL.texParameteri(this.GL.TEXTURE_2D, this.GL.TEXTURE_MAG_FILTER, this.GL.LINEAR);
this.GL.texParameteri(this.GL.TEXTURE_2D, this.GL.TEXTURE_MIN_FILTER, this.GL.LINEAR);
this.GL.texParameteri(this.GL.TEXTURE_2D, this.GL.TEXTURE_WRAP_S, this.GL.CLAMP_TO_EDGE);
this.GL.texParameteri(this.GL.TEXTURE_2D, this.GL.TEXTURE_WRAP_T, this.GL.CLAMP_TO_EDGE);
// build the copy shader program:
const copyVertexShaderSource = "attribute vec2 position;\n\
uniform mat2 UVTransformMat2;\n\
varying vec2 vUV;\n\
void main(void){\n\
gl_Position = vec4(position, 0., 1.);\n\
vUV = vec2(0.5,0.5) + UVTransformMat2 * position;\n\
}";
const copyFragmentShaderSource = "precision lowp float;\n\
uniform sampler2D samplerImage;\n\
varying vec2 vUV;\n\
\n\
void main(void){\n\
gl_FragColor = texture2D(samplerImage, vUV);\n\
}";
this.SHADERCOPY = this.build_shaderProgram(copyVertexShaderSource, copyFragmentShaderSource, 'VIDEO');
if (this.SHADERCOPY == null) return;
const uSampler = this.GL.getUniformLocation(this.SHADERCOPY, 'samplerImage');
this.UUVTRANSFORM = this.GL.getUniformLocation(this.SHADERCOPY, 'UVTransformMat2');
this.GL.useProgram(this.SHADERCOPY);
this.GL.uniform1i(uSampler, 0);
}

//BEGIN WEBthis.GL HELPERS
// compile a shader:
private compile_shader(source, glType, typeString) {
if (this.GL == null) return;
const glShader = this.GL.createShader(glType);
if (glShader == null) return;
this.GL.shaderSource(glShader, source);
this.GL.compileShader(glShader);
if (!this.GL.getShaderParameter(glShader, this.GL.COMPILE_STATUS)) {
alert("ERROR IN " + typeString + " SHADER: " + this.GL.getShaderInfoLog(glShader));
return null;
}
return glShader;
}

// helper function to build the shader program:
private build_shaderProgram(shaderVertexSource, shaderFragmentSource, id) {
if (this.GL == null) return;
// compile both shader separately:
const glShaderVertex = this.compile_shader(shaderVertexSource, this.GL.VERTEX_SHADER, "VERTEX " + id);
const glShaderFragment = this.compile_shader(shaderFragmentSource, this.GL.FRAGMENT_SHADER, "FRAGMENT " + id);

const glShaderProgram = this.GL.createProgram();
if (glShaderProgram == null || glShaderVertex == null || glShaderFragment == null) return;
this.GL.attachShader(glShaderProgram, glShaderVertex);
this.GL.attachShader(glShaderProgram, glShaderFragment);

// start the linking stage:
this.GL.linkProgram(glShaderProgram);
return glShaderProgram;
}
//END WEBthis.GL HELPERS

public update_canvasTexture() {
this.CANVASTEXTURENEEDSUPDATE = true;
}

public draw (detectState: IJeelizFaceFilterDetectState) { // draw the video and the canvas above
if (this.CV == null || this.GL == null || this.SHADERCOPY == null || this.VIDEOTEXTURETRANSFORMMAT2 == null || this.CANVAS2D == null) return;
this.GL.viewport(0, 0, this.CV.width, this.CV.height);
this.GL.useProgram(this.SHADERCOPY);

// enable blending:
this.GL.enable(this.GL.BLEND);
this.GL.blendFunc(this.GL.SRC_ALPHA, this.GL.ONE_MINUS_SRC_ALPHA);

// draw the video first:
this.GL.bindTexture(this.GL.TEXTURE_2D, this.VIDEOTEXTURE);
this.GL.uniformMatrix2fv(this.UUVTRANSFORM, false, this.VIDEOTEXTURETRANSFORMMAT2);
this.GL.drawElements(this.GL.TRIANGLES, 3, this.GL.UNSIGNED_SHORT, 0);

// then draw the canvas:
this.GL.bindTexture(this.GL.TEXTURE_2D, this.CANVASTEXTURE);
this.GL.uniformMatrix2fv(this.UUVTRANSFORM, false, [0.5, 0, 0, 0.5]);
if (this.CANVASTEXTURENEEDSUPDATE) {
this.GL.texImage2D(this.GL.TEXTURE_2D, 0, this.GL.RGBA, this.GL.RGBA, this.GL.UNSIGNED_BYTE, this.CANVAS2D);
}
this.GL.drawElements(this.GL.TRIANGLES, 3, this.GL.UNSIGNED_SHORT, 0);
this.GL.disable(this.GL.BLEND);
}

public getCoordinates(detectedState: IJeelizFaceFilterDetectState) {
if (this.CV == null) return this.COORDINATES;
this.COORDINATES.x = Math.round((0.5+0.5*detectedState.x-0.5*detectedState.s)*this.CV.width);
this.COORDINATES.y = Math.round((0.5+0.5*detectedState.y-0.5*detectedState.s)*this.CV.height);
this.COORDINATES.w = Math.round(detectedState.s*this.CV.width);
this.COORDINATES.h = this.COORDINATES.w;
return this.COORDINATES;
}

public resize() {
if (this.CANVAS2D == null ||this.CV == null) return;
this.CANVAS2D.width = this.CV.width;
this.CANVAS2D.height = this.CV.height;
}
}



+ 179
- 0
vendors/jeelizFaceFilter/typescript/JeelizFaceFilterInterfaces.ts 查看文件

@@ -0,0 +1,179 @@
export interface JeelizFaceFilterInitVideoSettings {
/**
* not set by default. <video> element used
WARN: If you specify this parameter,
1. all other settings will be useless
2. it means that you fully handle the video aspect
3. in case of using web-camera device make sure that
initialization goes after `loadeddata` event of the `videoElement`,
otherwise face detector will yield very low `detectState.detected` values
(to be more sure also await first `timeupdate` event)
*/
videoElement?: HTMLVideoElement;
/** not set by default */
deviceId?: string;
/** to use the rear camera, set to 'environment' */
facingMode?: string;
/** ideal video width in pixels */
idealWidth?: number;
/** ideal video height in pixels */
idealHeight?: number;
/** min video width in pixels */
minWidth?: number;
/** max video width in pixels */
maxWidth?: number;
/** min video height in pixels */
minHeight?: number;
/** max video height in pixels, */
maxHeight?: number;
/** rotation in degrees possible values: 0,90,-90,180 */
rotate?: number;
/** if we should flip horizontally the video. Default: false */
flipX?: boolean;
}
export interface IJeelizFaceFilterScanSettings {
minScale: number;
maxScale: number;
borderwidth: number;
borderHeight: number;
nStepsX: number;
nStepsY: number;
nStepsScale: number;
nDetectsPerLoop: number;
}
export interface IJeelizFaceFilterStabilizationSettings {
translationFactorRange: [number, number];
rotationFactorRange: [number, number];
qualityFactorRange: [number, number];
alphaRange: [number, number];
}
export interface IJeelizFaceFilterDetectState {
/** the face detection probability, between 0 and 1, */
detected: 0 | 1;
/** : The 2D coordinates of the center of the detection frame in the viewport (each between -1 and 1, x from left to right and y from bottom to top), */
x: number;
/** : The 2D coordinates of the center of the detection frame in the viewport (each between -1 and 1, x from left to right and y from bottom to top), */
y: number;
/** the scale along the horizontal axis of the detection frame, between 0 and 1 (1 for the full width). The detection frame is always square, */
s: number;
/** the Euler angles of the head rotation in radians. */
rx: number;
/** the Euler angles of the head rotation in radians. */
ry: number;
/** the Euler angles of the head rotation in radians. */
rz: number;
/** array listing the facial expression coefficients:
expressions[0]: mouth opening coefficient (0 → mouth closed, 1 → mouth fully opened) */
expressions: Float32Array;
}
export interface IJeelizFaceFilterInitParams {
callbackReady?: (err: string | false, spec: IJeelizFaceFilterInitResult) => void;
callbackTrack?: (detectState: IJeelizFaceFilterDetectState) => void;
/**
* It is used only in normal rendering mode (not in slow rendering mode). With this statement you can set accurately the number of milliseconds during which the browser wait at the end of the rendering loop before starting another detection. If you use the canvas of this API as a secondary element (for example in PACMAN or EARTH NAVIGATION demos) you should set a small animateDelay value (for example 2 milliseconds) in order to avoid rendering lags.
*/
animateDelay?: number;
NNCPath?: string;
NNC?: string;
/**
* Only for multiple face detection - maximum number of faces which can be detected and tracked. Should be between 1 (no multiple detection) and 8,
*/
maxFacesDetected?: number;
/**
* Allow full rotation around depth axis. Default value: false. See Issue 42 for more details,
*/
followZRot?: boolean;
canvasId?: string;
canvas?: HTMLCanvasElement;
scanSettings?: IJeelizFaceFilterScanSettings;
stabilizationSettings?: IJeelizFaceFilterStabilizationSettings;
videoSettings?: JeelizFaceFilterInitVideoSettings;
/**
* Function launched just before asking for the user to allow its webcam sharing,
*/
onWebcamAsk?: () => void;
onWebcamGet?: (videoElement: HTMLVideoElement, stream?: MediaStream, videoTrackInfo?: any) => void;
}
export interface IJeelizFaceFilterInitResult {
/** the <canvas> element, */
canvasElement:HTMLCanvasElement;
/** the WebGL context. The rendering 3D engine should use this WebGL context, */
GL:WebGL2RenderingContext;
/** a WebGL texture displaying the camera video. It has the same resolution as the camera video, */
videoTexture:WebGLTexture;
/** the video used as source for the webgl texture videoTexture, */
videoElement:HTMLVideoElement;
/** flatten 2x2 matrix encoding a scaling and a rotation. We should apply this matrix to viewport coordinates to render videoTexture in the viewport, */
videoTransformMat2:number[];
/** the maximum number of detected faces. */
maxFacesDetected: number;
}
export interface IJeelizFaceFilter {

init(params: IJeelizFaceFilterInitParams): boolean;
/** Should be called before the init method. 2 arguments are provided to the callback function:

<array> mediaDevices: an array with all the devices founds. Each device is a javascript object having a deviceId string attribute. This value can be provided to the init method to use a specific webcam. If an error happens, this value is set to false,
<string> errorLabel: if an error happens, the label of the error. It can be: NOTSUPPORTED, NODEVICESFOUND or PROMISEREJECTED.
*/
get_videoDevices(callback: (mediaDevices: Array<{deviceId: string}> | false, errorLabel?: string) => void): any;

/** Change the video input by a WebGL Texture instance. The dimensions of the texture, in pixels, should be provided, Come back to the user's video as input texture, */
reset_inputTexture(): void;

/** should be called after resizing the <canvas> element to adapt the cut of the video.
* It should also be called if the device orientation is changed to take account of new video dimensions, */
resize(): boolean;
/** Change the animateDelay (see init() arguments), */
set_animateDelay(delay: number): void;

set_inputTexture(tex: WebGLTexture, width: number, height: number): void;

/** Override scan settings. scanSettings is a dictionnary with the following properties:

<float> scale0Factor: Relative width (1 -> full width) of the searching window at the largest scale level. Default value is 0.8,
<int> nScaleLevels: Number of scale levels. Default is 3,
[<float>, <float>, <float>] overlapFactors: relative overlap according to X,Y and scale axis between 2 searching window positions. Higher values make scan faster but it may miss some positions. Set to [1, 1, 1] for no overlap. Default value is [2, 2, 3],
<int> nDetectsPerLoop: specify the number of detection per drawing loop. -1 for adaptative value. Default: -1 */
set_scanSettings(settings: IJeelizFaceFilterScanSettings): void;

/** Override detection stabilization settings. The output of the neural network is always noisy, so we need to stabilize it using a floatting average to avoid shaking artifacts. The internal algorithm computes first a stabilization factor k between 0 and 1. If k==0.0, the detection is bad and we favor responsivity against stabilization. It happens when the user is moving quickly, rotating the head or when the detection is bad. On the contrary, if k is close to 1, the detection is nice and the user does not move a lot so we can stabilize a lot. stabilizationSettings is a dictionnary with the following properties:

[<float> minValue, <float> maxValue] translationFactorRange: multiply k by a factor kTranslation depending on the translation speed of the head (relative to the viewport). kTranslation=0 if translationSpeed<minValue and kTranslation=1 if translationSpeed>maxValue. The regression is linear. Default value: [0.0015, 0.005],
[<float> minValue, <float> maxValue] rotationFactorRange: analogous to translationFactorRange but for rotation speed. Default value: [0.003, 0.02],
[<float> minValue, <float> maxValue] qualityFactorRange: analogous to translationFactorRange but for the head detection coefficient. Default value: [0.9, 0.98],
[<float> minValue, <float> maxValue] alphaRange: it specify how to apply k. Between 2 successive detections, we blend the previous detectState values with the current detection values using a mixing factor alpha. alpha=<minValue> if k<0.0 and alpha=<maxValue> if k>1.0. Between the 2 values, the variation is quadratic. Default value: [0.05, 1]. */
set_stabilizationSettings(settings: IJeelizFaceFilterStabilizationSettings): void;

/** pause/resume. This method will completely stop the rendering/detection loop. If isShutOffVideo is set to true, the media stream track will be */
toggle_pause(isPause?: boolean, isShutOffVideo?: boolean): any;

/** : toggle the slow rendering mode: because this API consumes a lot of GPU resources, it may slow down other elements of the application.
* If the user opens a CSS menu for example, the CSS transitions and the DOM update can be slow. With this function you can
* slow down the rendering in order to relieve the GPU. Unfortunately the tracking and the 3D rendering will also be slower
* but this is not a problem is the user is focusing on other elements of the application. We encourage to enable the slow mode
* as soon as a the user's attention is focused on a different part of the canvas, */
toggle_slow(isSlow?: boolean): any;

/** change the video element used for the face detection (which can be provided via VIDEOSETTINGS.videoElement) by another video element.
* A callback function can be called when it is done. */
update_videoElement(video: HTMLVideoElement, callback: () => void): void;

/** Dynamically change the video settings (see Optional init arguments for the properties of videoSettings). It is useful to change the camera from
* the selfie camera (user) to the back (environment) camera. A Promise is returned.
*/
update_videoSettings(videoSettings: JeelizFaceFilterInitVideoSettings): Promise<void>;

/** Dynamically change videoSettings.rotate and videoSettings.flipX. This method should be called after initialization.
* The default values are 0 and false. The angle should be chosen among these values: 0, 90, 180, -90, */
set_videoOrientation(angle: number, flipX: boolean);

/** Clean both graphic memory and JavaScript memory, uninit the library. After that you need to init the library again. A Promise is returned, */
destroy(): Promise<void>;

/** reset the WebGL context */
reset_GLState();

/** render the video on the <canvas> element. */
render_video();
}

正在加载...
取消
保存