UNPKG

handsfree

Version:

A Face Pointer and Pose Estimator for interacting with pages, desktops, robots, and more via gestures

1,182 lines (1,157 loc) 201 kB
/** * @license * Copyright 2020 Google LLC. All Rights Reserved. * 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. * ============================================================================= */ (function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@tensorflow/tfjs-core'), require('path'), require('fs')) : typeof define === 'function' && define.amd ? define(['exports', '@tensorflow/tfjs-core', 'path', 'fs'], factory) : (global = global || self, factory((global.tf = global.tf || {}, global.tf.wasm = global.tf.wasm || {}), global.tf, global.path, global.fs)); }(this, (function (exports, tfjsCore, path, fs) { 'use strict'; path = path && path.hasOwnProperty('default') ? path['default'] : path; fs = fs && fs.hasOwnProperty('default') ? fs['default'] : fs; /** * @license * Copyright 2019 Google LLC. All Rights Reserved. * 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. * ============================================================================= */ // This enum must align with the enum defined in cc/backend.h. var CppDType; (function (CppDType) { CppDType[CppDType["float32"] = 0] = "float32"; CppDType[CppDType["int32"] = 1] = "int32"; CppDType[CppDType["bool"] = 2] = "bool"; CppDType[CppDType["string"] = 3] = "string"; CppDType[CppDType["complex64"] = 4] = "complex64"; })(CppDType || (CppDType = {})); // Must match enum in cc/fusable_activations.h. var FusableActivation; (function (FusableActivation) { FusableActivation[FusableActivation["linear"] = 0] = "linear"; FusableActivation[FusableActivation["relu"] = 1] = "relu"; FusableActivation[FusableActivation["relu6"] = 2] = "relu6"; FusableActivation[FusableActivation["prelu"] = 3] = "prelu"; })(FusableActivation || (FusableActivation = {})); /** * @license * Copyright 2019 Google LLC. All Rights Reserved. * 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. * ============================================================================= */ let wasmFusedMatMul; function setup(backend) { wasmFusedMatMul = backend.wasm.cwrap(tfjsCore._FusedMatMul, null /* void */, [ 'number', 'array', 'number', 'number', 'array', 'number', 'number', 'number', 'number', 'number', 'number', 'number' // out_id ]); } function fusedBatchMatMul(args) { const { inputs, backend, attrs } = args; const { a, b, bias, preluActivationWeights } = inputs; if (a.dtype !== 'float32' || b.dtype !== 'float32') { throw new Error(`_FusedMatMul for non non-float32 tensors not yet supported.`); } const { transposeA, transposeB, activation } = attrs; const aId = backend.dataIdMap.get(a.dataId).id; const bId = backend.dataIdMap.get(b.dataId).id; let biasId = 0; if (bias != null) { const biasData = backend.dataIdMap.get(bias.dataId); if (biasData.shape.length !== 1) { throw new Error(`_FusedMatMul only supports rank-1 bias but got ` + `rank ${biasData.shape.length}.`); } biasId = biasData.id; } const preluActivationWeightsId = preluActivationWeights == null ? 0 : backend.dataIdMap.get(preluActivationWeights.dataId).id; const fusedActivation = FusableActivation[activation]; if (fusedActivation == null) { throw new Error(`${activation} activation not yet supported for FusedConv2D ` + `in the wasm backend.`); } const leftDim = transposeA ? a.shape[2] : a.shape[1]; const rightDim = transposeB ? b.shape[1] : b.shape[2]; const batchDim = a.shape[0]; const out = backend.makeOutput([batchDim, leftDim, rightDim], a.dtype); const outId = backend.dataIdMap.get(out.dataId).id; const aShapeBytes = new Uint8Array(new Int32Array(a.shape).buffer); const bShapeBytes = new Uint8Array(new Int32Array(b.shape).buffer); wasmFusedMatMul(aId, aShapeBytes, a.shape.length, bId, bShapeBytes, b.shape.length, transposeA, transposeB, fusedActivation, biasId, preluActivationWeightsId, outId); return out; } const fusedMatMulConfig = { kernelName: tfjsCore._FusedMatMul, backendName: 'wasm', setupFunc: setup, kernelFunc: fusedBatchMatMul }; /** * @license * Copyright 2019 Google LLC. All Rights Reserved. * 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. * ============================================================================= */ function createUnaryKernelConfig(kernelName) { let wasmFunc; function setupFunc(backend) { wasmFunc = backend.wasm.cwrap(kernelName, null /* void */, ['number', 'number']); } function kernelFunc(args) { const { backend, inputs: { x } } = args; const xId = backend.dataIdMap.get(x.dataId).id; const out = backend.makeOutput(x.shape, x.dtype); const outId = backend.dataIdMap.get(out.dataId).id; // Short-circuit zero-sized tensors. if (tfjsCore.util.sizeFromShape(out.shape) === 0) { return out; } wasmFunc(xId, outId); return out; } return { kernelName, backendName: 'wasm', setupFunc, kernelFunc }; } /** * @license * Copyright 2019 Google LLC. All Rights Reserved. * 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. * ============================================================================= */ const absConfig = createUnaryKernelConfig(tfjsCore.Abs); /** * @license * Copyright 2019 Google LLC. All Rights Reserved. * 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. * ============================================================================= */ function createBinaryKernelConfig(kernelName, supportsFullBroadcast, dtype) { let wasmFunc; function setupFunc(backend) { wasmFunc = backend.wasm.cwrap(kernelName, null /* void */, [ 'number', 'array', 'number', 'number', 'array', 'number', 'number', 'number' // out_id ]); } function kernelFunc(args) { const { backend, inputs } = args; const { a, b } = inputs; const aId = backend.dataIdMap.get(a.dataId).id; const bId = backend.dataIdMap.get(b.dataId).id; const outputType = dtype != null ? dtype : a.dtype; const newShape = tfjsCore.backend_util.assertAndGetBroadcastShape(a.shape, b.shape); const out = backend.makeOutput(newShape, outputType); // Short-circuit zero-sized tensors. if (tfjsCore.util.sizeFromShape(newShape) === 0) { return out; } const aShapeBytes = new Uint8Array(new Int32Array(a.shape).buffer); const bShapeBytes = new Uint8Array(new Int32Array(b.shape).buffer); const outId = backend.dataIdMap.get(out.dataId).id; const kernelFunc = () => wasmFunc(aId, aShapeBytes, a.shape.length, bId, bShapeBytes, b.shape.length, CppDType[a.dtype], outId); // Currently only some float operations support full broadcast. if (supportsFullBroadcast && a.dtype === 'float32') { kernelFunc(); return out; } const aBroadcastDims = tfjsCore.backend_util.getBroadcastDims(a.shape, newShape); const bBroadcastDims = tfjsCore.backend_util.getBroadcastDims(b.shape, newShape); const loopsOverAllOfA = aBroadcastDims.every((v, i) => v === i); const loopsOverAllOfB = bBroadcastDims.every((v, i) => v === i); if (loopsOverAllOfA && loopsOverAllOfB) { kernelFunc(); return out; } else { throw new Error(`Broadcasting along outer dims is not yet ` + `supported for ${a.dtype} ${kernelName}.`); } } return { kernelName, backendName: 'wasm', setupFunc, kernelFunc }; } /** * @license * Copyright 2019 Google LLC. All Rights Reserved. * 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. * ============================================================================= */ const supportsFullBroadcast = true; const addConfig = createBinaryKernelConfig(tfjsCore.Add, supportsFullBroadcast); /** * @license * Copyright 2019 Google LLC. All Rights Reserved. * 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. * ============================================================================= */ let wasmFunc; function setupFunc(backend) { wasmFunc = backend.wasm.cwrap(tfjsCore.AddN, null /* void */, [ 'array', 'number', 'number', 'number', ]); } function addn(args) { const { inputs, backend } = args; const out = backend.makeOutput(inputs[0].shape, inputs[0].dtype); // Short-circuit zero-sized tensors. if (tfjsCore.util.sizeFromShape(out.shape) === 0) { return out; } const inputIds = inputs.map(x => backend.dataIdMap.get(x.dataId).id); const inputIdsBytes = new Uint8Array(new Int32Array(inputIds).buffer); const outId = backend.dataIdMap.get(out.dataId).id; wasmFunc(inputIdsBytes, inputIds.length, CppDType[out.dtype], outId); return out; } const addNConfig = { kernelName: tfjsCore.AddN, backendName: 'wasm', setupFunc, kernelFunc: addn, }; /** * @license * Copyright 2020 Google LLC. All Rights Reserved. * 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. * ============================================================================= */ function identity(args) { const { inputs: { x }, backend } = args; const out = backend.makeOutput(x.shape, x.dtype); const inVals = backend.typedArrayFromHeap(x); const outVals = backend.typedArrayFromHeap(out); outVals.set(inVals); return out; } const identityConfig = { kernelName: tfjsCore.Identity, backendName: 'wasm', kernelFunc: identity, }; /** * @license * Copyright 2019 Google LLC. All Rights Reserved. * 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. * ============================================================================= */ let wasmTranspose; function setup$1(backend) { wasmTranspose = backend.wasm.cwrap(tfjsCore.Transpose, null /* void */, [ 'number', 'array', 'number', 'number', 'number', 'array', 'number', ]); } function transpose(args) { const { inputs, backend, attrs } = args; // Reduce any dimensions with size one. Lower-rank transpose kernel performs // better due to simpler memory access pattern. const [reducedShape, perm] = removeOneSizeDims(inputs.x.shape, attrs.perm); let permIsNoOp = true; for (let i = 0; i < perm.length; i++) { if (perm[i] !== i) { permIsNoOp = false; } } const outShape = computeOutShape(inputs.x.shape, attrs.perm); const x = { dataId: inputs.x.dataId, shape: reducedShape, dtype: inputs.x.dtype }; if (permIsNoOp) { const cloned = identity({ inputs, backend }); cloned.shape = outShape; return cloned; } const out = backend.makeOutput(outShape, x.dtype); const xId = backend.dataIdMap.get(x.dataId).id; const outId = backend.dataIdMap.get(out.dataId).id; const permBytes = new Uint8Array(new Int32Array(perm).buffer); const xShapeBytes = new Uint8Array(new Int32Array(x.shape).buffer); wasmTranspose(xId, xShapeBytes, x.shape.length, CppDType[x.dtype], outId, permBytes, perm.length); return out; } function computeOutShape(inShape, perm) { const outShape = new Array(inShape.length); for (let i = 0; i < outShape.length; i++) { outShape[i] = inShape[perm[i]]; } return outShape; } function removeOneSizeDims(shape, perm) { const newShape = []; const newPerm = []; for (let i = 0; i < shape.length; ++i) { if (shape[i] !== 1) { newShape.push(shape[i]); } if (shape[perm[i]] !== 1) { newPerm.push(perm[i]); } } for (let i = 0; i < newPerm.length; ++i) { let minValIdx = -1; for (let j = 0; j < newPerm.length; ++j) { if (newPerm[j] >= i && (minValIdx === -1 || newPerm[minValIdx] > newPerm[j])) { minValIdx = j; } } newPerm[minValIdx] = i; } return [newShape, newPerm]; } const transposeConfig = { kernelName: tfjsCore.Transpose, backendName: 'wasm', kernelFunc: transpose, setupFunc: setup$1, }; /** * @license * Copyright 2020 Google Inc. All Rights Reserved. * 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. * ============================================================================= */ /** * Compute permutation axes and do a transpose if necessary. * * Used by reduction ops. * @param x input TensorInfo * @param axis reduction axes * @param backend wasm backend instance */ function permuteAxesAndTranspose(x, axis, backend) { const xShape = x.shape; const xRank = x.shape.length; const originalAxes = tfjsCore.util.parseAxisParam(axis, xShape); let axes = originalAxes; const permutedAxes = tfjsCore.backend_util.getAxesPermutation(axes, xRank); let xTransposed = null; let inputWasTransposed = false; if (permutedAxes != null) { const newShape = new Array(xRank); for (let i = 0; i < newShape.length; i++) { newShape[i] = xShape[permutedAxes[i]]; } axes = tfjsCore.backend_util.getInnerMostAxes(axes.length, xRank); xTransposed = transpose({ inputs: { x }, attrs: { perm: permutedAxes }, backend }); const xId = backend.dataIdMap.get(x.dataId).id; const transposedId = backend.dataIdMap.get(xTransposed.dataId).id; if (transposedId !== xId) { inputWasTransposed = true; } } return { transposed: xTransposed, originalAxes, axes, inputWasTransposed }; } /** * @license * Copyright 2019 Google LLC. All Rights Reserved. * 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. * ============================================================================= */ let wasmFunc$1; function setup$2(backend) { wasmFunc$1 = backend.wasm.cwrap(tfjsCore.ArgMax, null /* void */, [ 'number', 'number', 'number', 'number', 'number' // out_id ]); } function argmax(args) { const { backend, inputs, attrs } = args; const { axis } = attrs; const { x } = inputs; const xId = backend.dataIdMap.get(x.dataId).id; let inputId = xId; let input = x; const { transposed, axes, inputWasTransposed } = permuteAxesAndTranspose(x, axis, backend); if (inputWasTransposed) { const transposedId = backend.dataIdMap.get(transposed.dataId).id; if (transposedId !== xId) { // transpose was not a no-op. We will need to dispose of this // once we are done. input = transposed; inputId = transposedId; } } const outShape = input.shape.slice(0, -1); const out = backend.makeOutput(outShape, 'int32'); const outId = backend.dataIdMap.get(out.dataId).id; const outerSize = tfjsCore.util.sizeFromShape(out.shape); const innerSize = input.shape[axes[0]]; wasmFunc$1(inputId, CppDType[input.dtype], outerSize, innerSize, outId); if (inputWasTransposed) { // dispose of the transposed tensor. backend.disposeData(transposed.dataId); } return out; } const argMaxConfig = { kernelName: tfjsCore.ArgMax, backendName: 'wasm', kernelFunc: argmax, setupFunc: setup$2 }; /** * @license * Copyright 2019 Google LLC. All Rights Reserved. * 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. * ============================================================================= */ let wasmAvgPool; function setup$3(backend) { wasmAvgPool = backend.wasm.cwrap(tfjsCore.AvgPool, null /* void */, [ 'number', 'number', 'number', 'number', 'number', 'number', 'number', 'number', 'number', 'number', 'number', 'number', 'number', 'number', ]); } function avgPool(args) { const { inputs, attrs, backend } = args; const x = inputs.x; const xId = backend.dataIdMap.get(x.dataId).id; const { filterSize, strides, pad, dimRoundingMode } = attrs; const convInfo = tfjsCore.backend_util.computePool2DInfo(x.shape, filterSize, strides, 1 /* dilations */, pad, dimRoundingMode); const filterHeight = convInfo.filterHeight; const filterWidth = convInfo.filterWidth; const padTop = convInfo.padInfo.top; const padRight = convInfo.padInfo.right; const padBottom = convInfo.padInfo.bottom; const padLeft = convInfo.padInfo.left; const strideHeight = convInfo.strideHeight; const strideWidth = convInfo.strideWidth; const channels = convInfo.inChannels; if (convInfo.dataFormat !== 'channelsLast') { throw new Error(`wasm backend does not support dataFormat:'` + `${convInfo.dataFormat}'. Please use 'channelsLast'.`); } if (convInfo.dilationWidth !== 1 || convInfo.dilationHeight !== 1) { throw new Error(`was backend only supports average pooling with dilation = [1, 1], ` + `got [${convInfo.dilationHeight}, ${convInfo.dilationWidth}].`); } const out = backend.makeOutput(convInfo.outShape, 'float32'); const outId = backend.dataIdMap.get(out.dataId).id; wasmAvgPool(xId, x.shape[0], x.shape[1], x.shape[2], filterHeight, filterWidth, padTop, padRight, padBottom, padLeft, strideHeight, strideWidth, channels, outId); return out; } const avgPoolConfig = { kernelName: tfjsCore.AvgPool, backendName: 'wasm', setupFunc: setup$3, kernelFunc: avgPool }; /** * @license * Copyright 2019 Google LLC. All Rights Reserved. * 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. * ============================================================================= */ let wasmBatchMatMul; function setup$4(backend) { wasmBatchMatMul = backend.wasm.cwrap(tfjsCore.BatchMatMul, null /* void */, [ 'number', 'array', 'number', 'number', 'array', 'number', 'number', 'number', 'number' // out_id ]); } function batchMatMul(args) { const { inputs, backend, attrs } = args; const { a, b } = inputs; if (a.dtype !== 'float32' || b.dtype !== 'float32') { throw new Error(`BatchMatMul for non non-float32 tensors not yet supported.`); } const { transposeA, transposeB } = attrs; const aId = backend.dataIdMap.get(a.dataId).id; const bId = backend.dataIdMap.get(b.dataId).id; const leftDim = transposeA ? a.shape[2] : a.shape[1]; const rightDim = transposeB ? b.shape[1] : b.shape[2]; const batchDim = a.shape[0]; const out = backend.makeOutput([batchDim, leftDim, rightDim], a.dtype); const outId = backend.dataIdMap.get(out.dataId).id; const aShapeBytes = new Uint8Array(new Int32Array(a.shape).buffer); const bShapeBytes = new Uint8Array(new Int32Array(b.shape).buffer); wasmBatchMatMul(aId, aShapeBytes, a.shape.length, bId, bShapeBytes, b.shape.length, transposeA, transposeB, outId); return out; } const batchMatMulConfig = { kernelName: tfjsCore.BatchMatMul, backendName: 'wasm', setupFunc: setup$4, kernelFunc: batchMatMul }; /** * @license * Copyright 2019 Google LLC. All Rights Reserved. * 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. * ============================================================================= */ function cast(args) { const { inputs: { x }, attrs: { dtype }, backend } = args; const out = backend.makeOutput(x.shape, dtype); const inVals = backend.typedArrayFromHeap(x); const outVals = backend.typedArrayFromHeap(out); outVals.set(inVals); return out; } const castConfig = { kernelName: tfjsCore.Cast, backendName: 'wasm', kernelFunc: cast, }; /** * @license * Copyright 2019 Google LLC. All Rights Reserved. * 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. * ============================================================================= */ let wasmClip; function setup$5(backend) { wasmClip = backend.wasm.cwrap(tfjsCore.ClipByValue, null /* void */, [ 'number', 'number', 'number', 'number' // out_id ]); } function clip(args) { const { inputs, backend, attrs } = args; const { x } = inputs; const { clipValueMin, clipValueMax } = attrs; const xId = backend.dataIdMap.get(x.dataId).id; const out = backend.makeOutput(x.shape, 'float32'); const outId = backend.dataIdMap.get(out.dataId).id; wasmClip(xId, clipValueMin, clipValueMax, outId); return out; } const clipByValueConfig = { kernelName: tfjsCore.ClipByValue, backendName: 'wasm', setupFunc: setup$5, kernelFunc: clip }; /** * @license * Copyright 2019 Google LLC. All Rights Reserved. * 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. * ============================================================================= */ function concat(args) { const { inputs, backend } = args; const axis = tfjsCore.util.parseAxisParam(args.attrs.axis, inputs[0].shape)[0]; const outShape = tfjsCore.backend_util.computeOutShape(inputs.map(t => t.shape), axis); const out = backend.makeOutput(outShape, inputs[0].dtype); const batchDim = tfjsCore.util.sizeFromShape(inputs[0].shape.slice(0, axis)); let sumInnerDims = 0; const innerDims = inputs.map(input => { const innerDim = tfjsCore.util.sizeFromShape(input.shape.slice(axis)); sumInnerDims += innerDim; return innerDim; }); const inVals = inputs.map(input => backend.typedArrayFromHeap(input)); const outVals = backend.typedArrayFromHeap(out); for (let b = 0; b < batchDim; b++) { let outOffset = b * sumInnerDims; for (let i = 0; i < inVals.length; i++) { const innerDim = innerDims[i]; const inOffset = b * innerDim; const vals = inVals[i].subarray(inOffset, inOffset + innerDim); outVals.set(vals, outOffset); outOffset += innerDim; } } return out; } const concatConfig = { kernelName: tfjsCore.Concat, backendName: 'wasm', kernelFunc: concat, }; /** * @license * Copyright 2019 Google LLC. All Rights Reserved. * 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. * ============================================================================= */ let wasmConv2d; function setup$6(backend) { wasmConv2d = backend.wasm.cwrap(tfjsCore.Conv2D, null /* void */, [ 'number', 'number', 'number', 'number', 'number', 'number', 'number', 'number', 'number', 'number', 'number', 'number', 'number', 'number', 'number', 'number', 'number', 'number', 'number', ]); } function conv2d(args) { const { inputs, attrs, backend } = args; const { x, filter } = inputs; const xId = backend.dataIdMap.get(x.dataId).id; const filterId = backend.dataIdMap.get(filter.dataId).id; const { strides, dilations, pad, dimRoundingMode, dataFormat } = attrs; const $dataFormat = tfjsCore.backend_util.convertConv2DDataFormat(dataFormat); const convInfo = tfjsCore.backend_util.computeConv2DInfo(x.shape, filter.shape, strides, dilations, pad, dimRoundingMode, false, $dataFormat); const filterHeight = convInfo.filterHeight; const filterWidth = convInfo.filterWidth; const padTop = convInfo.padInfo.top; const padRight = convInfo.padInfo.right; const padBottom = convInfo.padInfo.bottom; const padLeft = convInfo.padInfo.left; const dilationHeight = convInfo.dilationHeight; const dilationWidth = convInfo.dilationWidth; const strideHeight = convInfo.strideHeight; const strideWidth = convInfo.strideWidth; const inputChannels = convInfo.inChannels; const outputChannels = convInfo.outChannels; const isSamePad = convInfo.padInfo.type === 'SAME' ? 1 : 0; if (convInfo.dataFormat !== 'channelsLast') { throw new Error(`wasm backend Conv2D does not support dataFormat:'` + `${convInfo.dataFormat}'. Please use 'channelsLast'.`); } const out = backend.makeOutput(convInfo.outShape, 'float32'); const outId = backend.dataIdMap.get(out.dataId).id; wasmConv2d(xId, x.shape[0], x.shape[1], x.shape[2], filterId, filterHeight, filterWidth, padTop, padRight, padBottom, padLeft, isSamePad, dilationHeight, dilationWidth, strideHeight, strideWidth, inputChannels, outputChannels, outId); return out; } const conv2DConfig = { kernelName: tfjsCore.Conv2D, backendName: 'wasm', setupFunc: setup$6, kernelFunc: conv2d }; /** * @license * Copyright 2020 Google LLC. All Rights Reserved. * 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. * ============================================================================= */ let wasmConv2DBackpropInput; function setup$7(backend) { wasmConv2DBackpropInput = backend.wasm.cwrap(tfjsCore.Conv2DBackpropInput, null, [ 'number', 'number', 'number', 'number', 'number', 'number', 'number', 'number', 'number', 'number', 'number', 'number', 'number', 'number', 'number', 'number', 'number', 'number', 'number', 'number', 'number', 'number', 'number', 'number', 'number', 'number', 'number', ]); } function conv2DBackpropInput(args) { const { backend, inputs, attrs } = args; const { dy, filter } = inputs; const { strides, pad, dataFormat, dimRoundingMode, inputShape } = attrs; const dilations = 1; const $dataFormat = tfjsCore.backend_util.convertConv2DDataFormat(dataFormat); const convInfo = tfjsCore.backend_util.computeConv2DInfo(inputShape, filter.shape, strides, dilations, pad, dimRoundingMode, false /* depthwise */, $dataFormat); const { batchSize, filterHeight, filterWidth, inChannels, inHeight, inWidth, outChannels, outHeight, outWidth, strideHeight, strideWidth } = convInfo; const topPad = filterHeight - 1 - convInfo.padInfo.top; const leftPad = filterWidth - 1 - convInfo.padInfo.left; const isChannelsLast = convInfo.dataFormat === 'channelsLast'; const dxStrides = tfjsCore.util.computeStrides(convInfo.inShape); const dyStrides = tfjsCore.util.computeStrides(dy.shape); const [fltS0, fltS1, fltS2] = tfjsCore.util.computeStrides(filter.shape); const xBatchStride = dxStrides[0]; const xRowStride = isChannelsLast ? dxStrides[1] : dxStrides[2]; const xColStride = isChannelsLast ? dxStrides[2] : 1; const xChannelStride = isChannelsLast ? 1 : dxStrides[1]; const yBatchStride = dyStrides[0]; const yRowStride = isChannelsLast ? dyStrides[1] : dyStrides[2]; const yColStride = isChannelsLast ? dyStrides[2] : 1; const yChannelStride = isChannelsLast ? 1 : dyStrides[1]; const out = backend.makeOutput(convInfo.inShape, 'float32'); const outId = backend.dataIdMap.get(out.dataId).id; const dyId = backend.dataIdMap.get(dy.dataId).id; const filterId = backend.dataIdMap.get(filter.dataId).id; wasmConv2DBackpropInput(dyId, filterId, batchSize, filterHeight, filterWidth, inHeight, inWidth, inChannels, outHeight, outWidth, outChannels, strideHeight, strideWidth, topPad, leftPad, fltS0, fltS1, fltS2, xBatchStride, xRowStride, xColStride, xChannelStride, yBatchStride, yRowStride, yColStride, yChannelStride, outId); return out; } const conv2DBackpropInputConfig = { kernelName: tfjsCore.Conv2DBackpropInput, backendName: 'wasm', setupFunc: setup$7, kernelFunc: conv2DBackpropInput }; /** * @license * Copyright 2019 Google LLC. All Rights Reserved. * 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. * ============================================================================= */ const cosConfig = createUnaryKernelConfig(tfjsCore.Cos); /** * @license * Copyright 2019 Google LLC. All Rights Reserved. * 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. * ============================================================================= */ // Must match enum in CropAndResize.cc var InterpolationMethod; (function (InterpolationMethod) { InterpolationMethod[InterpolationMethod["bilinear"] = 0] = "bilinear"; InterpolationMethod[InterpolationMethod["nearest"] = 1] = "nearest"; })(InterpolationMethod || (InterpolationMethod = {})); let wasmCropAndResize; function setup$8(backend) { wasmCropAndResize = backend.wasm.cwrap(tfjsCore.CropAndResize, null /*void*/, [ 'number', 'number', 'number', 'number', 'array', 'number', 'number', 'number', 'number', 'number' // out id ]); } function cropAndResize(args) { const { backend, inputs, attrs } = args; const { method, extrapolationValue, cropSize } = attrs; const { image, boxes, boxInd } = inputs; const numBoxes = boxes.shape[0]; const [cropHeight, cropWidth] = cropSize; const outShape = [numBoxes, cropHeight, cropWidth, image.shape[3]]; let imagesData = backend.dataIdMap.get(image.dataId); let castedData; if (image.dtype !== 'float32') { castedData = cast({ backend, inputs: { x: image }, attrs: { dtype: 'float32' } }); imagesData = backend.dataIdMap.get(castedData.dataId); } const imagesId = imagesData.id; const boxesId = backend.dataIdMap.get(boxes.dataId).id; const boxIndId = backend.dataIdMap.get(boxInd.dataId).id; const out = backend.makeOutput(outShape, 'float32'); const outId = backend.dataIdMap.get(out.dataId).id; const imagesShapeBytes = new Uint8Array(new Int32Array(image.shape).buffer); wasmCropAndResize(imagesId, boxesId, boxIndId, numBoxes, imagesShapeBytes, cropHeight, cropWidth, InterpolationMethod[method], extrapolationValue, outId); if (castedData != null) { backend.disposeData(castedData.dataId); } return out; } const cropAndResizeConfig = { kernelName: tfjsCore.CropAndResize, backendName: 'wasm', setupFunc: setup$8, kernelFunc: cropAndResize }; /** * @license * Copyright 2019 Google LLC. All Rights Reserved. * 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. * ============================================================================= */ let wasmDepthwiseConv2d; function setup$9(backend) { wasmDepthwiseConv2d = backend.wasm.cwrap(tfjsCore.DepthwiseConv2dNative, null /* void */, [ 'number', 'number', 'number', 'number', 'number', 'number', 'number', 'number', 'number', 'number', 'number', 'number', 'number', 'number', 'number', 'number', 'number', 'number', 'number', ]); } function depthwiseConv2d(args) { const { inputs, attrs, backend } = args; const { x, filter } = inputs; const xId = backend.dataIdMap.get(x.dataId).id; const filterId = backend.dataIdMap.get(filter.dataId).id; const { strides, dilations, pad, dimRoundingMode } = attrs; const $dilations = dilations == null ? [1, 1] : dilations; const convInfo = tfjsCore.backend_util.computeConv2DInfo(x.shape, filter.shape, strides, $dilations, pad, dimRoundingMode, true /* depthwise */); const filterHeight = convInfo.filterHeight; const filterWidth = convInfo.filterWidth; const padTop = convInfo.padInfo.top; const padRight = convInfo.padInfo.right; const padBottom = convInfo.padInfo.bottom; const padLeft = convInfo.padInfo.left; const dilationHeight = convInfo.dilationHeight; const dilationWidth = convInfo.dilationWidth; const strideHeight = convInfo.strideHeight; const strideWidth = convInfo.strideWidth; const inputChannels = convInfo.inChannels; const outputChannels = convInfo.outChannels; const isSamePad = convInfo.padInfo.type === 'SAME' ? 1 : 0; if (convInfo.dataFormat !== 'channelsLast') { throw new Error(`wasm backend DepthwiseConv2dNative does not support dataFormat:'` + `${convInfo.dataFormat}'. Please use 'channelsLast'.`); } const out = backend.makeOutput(convInfo.outShape, 'float32'); const outId = backend.dataIdMap.get(out.dataId).id; wasmDepthwiseConv2d(xId, x.shape[0], x.shape[1], x.shape[2], filterId, filterHeight, filterWidth, padTop, padRight, padBottom, padLeft, isSamePad, dilationHeight, dilationWidth, strideHeight, strideWidth, inputChannels, outputChannels, outId); return out; } const depthwiseConv2DNativeConfig = { kernelName: tfjsCore.DepthwiseConv2dNative, backendName: 'wasm', setupFunc: setup$9, kernelFunc: depthwiseConv2d }; /** * @license * Copyright 2019 Google LLC. All Rights Reserved. * 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. * ============================================================================= */ const supportsFullBroadcast$1 = true; const divConfig = createBinaryKernelConfig(tfjsCore.Div, supportsFullBroadcast$1); /** * @license * Copyright 2020 Google LLC. All Rights Reserved. * 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. * ============================================================================= */ const supportsFullBroadcast$2 = false; const equalConfig = createBinaryKernelConfig(tfjsCore.Equal, supportsFullBroadcast$2, 'bool'); /** * @license * Copyright 2019 Google LLC. All Rights Reserved. * 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. * ==================