@srsergio/taptapp-ar 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +62 -0
- package/dist/compiler/aframe.d.ts +1 -0
- package/dist/compiler/aframe.js +275 -0
- package/dist/compiler/compiler-base.d.ts +12 -0
- package/dist/compiler/compiler-base.js +165 -0
- package/dist/compiler/compiler.d.ts +9 -0
- package/dist/compiler/compiler.js +24 -0
- package/dist/compiler/compiler.worker.d.ts +1 -0
- package/dist/compiler/compiler.worker.js +28 -0
- package/dist/compiler/controller.d.ts +101 -0
- package/dist/compiler/controller.js +400 -0
- package/dist/compiler/controller.worker.d.ts +1 -0
- package/dist/compiler/controller.worker.js +61 -0
- package/dist/compiler/detector/crop-detector.d.ts +65 -0
- package/dist/compiler/detector/crop-detector.js +59 -0
- package/dist/compiler/detector/detector.d.ts +98 -0
- package/dist/compiler/detector/detector.js +1049 -0
- package/dist/compiler/detector/freak.d.ts +1 -0
- package/dist/compiler/detector/freak.js +89 -0
- package/dist/compiler/detector/kernels/cpu/binomialFilter.d.ts +6 -0
- package/dist/compiler/detector/kernels/cpu/binomialFilter.js +51 -0
- package/dist/compiler/detector/kernels/cpu/buildExtremas.d.ts +6 -0
- package/dist/compiler/detector/kernels/cpu/buildExtremas.js +89 -0
- package/dist/compiler/detector/kernels/cpu/computeExtremaAngles.d.ts +7 -0
- package/dist/compiler/detector/kernels/cpu/computeExtremaAngles.js +79 -0
- package/dist/compiler/detector/kernels/cpu/computeExtremaFreak.d.ts +6 -0
- package/dist/compiler/detector/kernels/cpu/computeExtremaFreak.js +68 -0
- package/dist/compiler/detector/kernels/cpu/computeFreakDescriptors.d.ts +6 -0
- package/dist/compiler/detector/kernels/cpu/computeFreakDescriptors.js +57 -0
- package/dist/compiler/detector/kernels/cpu/computeLocalization.d.ts +6 -0
- package/dist/compiler/detector/kernels/cpu/computeLocalization.js +54 -0
- package/dist/compiler/detector/kernels/cpu/computeOrientationHistograms.d.ts +6 -0
- package/dist/compiler/detector/kernels/cpu/computeOrientationHistograms.js +118 -0
- package/dist/compiler/detector/kernels/cpu/downsampleBilinear.d.ts +6 -0
- package/dist/compiler/detector/kernels/cpu/downsampleBilinear.js +29 -0
- package/dist/compiler/detector/kernels/cpu/extremaReduction.d.ts +6 -0
- package/dist/compiler/detector/kernels/cpu/extremaReduction.js +50 -0
- package/dist/compiler/detector/kernels/cpu/fakeShader.d.ts +20 -0
- package/dist/compiler/detector/kernels/cpu/fakeShader.js +80 -0
- package/dist/compiler/detector/kernels/cpu/index.d.ts +1 -0
- package/dist/compiler/detector/kernels/cpu/index.js +25 -0
- package/dist/compiler/detector/kernels/cpu/prune.d.ts +1 -0
- package/dist/compiler/detector/kernels/cpu/prune.js +103 -0
- package/dist/compiler/detector/kernels/cpu/smoothHistograms.d.ts +6 -0
- package/dist/compiler/detector/kernels/cpu/smoothHistograms.js +47 -0
- package/dist/compiler/detector/kernels/cpu/upsampleBilinear.d.ts +6 -0
- package/dist/compiler/detector/kernels/cpu/upsampleBilinear.js +43 -0
- package/dist/compiler/detector/kernels/index.d.ts +1 -0
- package/dist/compiler/detector/kernels/index.js +2 -0
- package/dist/compiler/detector/kernels/webgl/binomialFilter.d.ts +6 -0
- package/dist/compiler/detector/kernels/webgl/binomialFilter.js +67 -0
- package/dist/compiler/detector/kernels/webgl/buildExtremas.d.ts +6 -0
- package/dist/compiler/detector/kernels/webgl/buildExtremas.js +101 -0
- package/dist/compiler/detector/kernels/webgl/computeExtremaAngles.d.ts +6 -0
- package/dist/compiler/detector/kernels/webgl/computeExtremaAngles.js +78 -0
- package/dist/compiler/detector/kernels/webgl/computeExtremaFreak.d.ts +6 -0
- package/dist/compiler/detector/kernels/webgl/computeExtremaFreak.js +86 -0
- package/dist/compiler/detector/kernels/webgl/computeFreakDescriptors.d.ts +6 -0
- package/dist/compiler/detector/kernels/webgl/computeFreakDescriptors.js +52 -0
- package/dist/compiler/detector/kernels/webgl/computeLocalization.d.ts +6 -0
- package/dist/compiler/detector/kernels/webgl/computeLocalization.js +58 -0
- package/dist/compiler/detector/kernels/webgl/computeOrientationHistograms.d.ts +6 -0
- package/dist/compiler/detector/kernels/webgl/computeOrientationHistograms.js +116 -0
- package/dist/compiler/detector/kernels/webgl/downsampleBilinear.d.ts +6 -0
- package/dist/compiler/detector/kernels/webgl/downsampleBilinear.js +46 -0
- package/dist/compiler/detector/kernels/webgl/extremaReduction.d.ts +6 -0
- package/dist/compiler/detector/kernels/webgl/extremaReduction.js +48 -0
- package/dist/compiler/detector/kernels/webgl/index.d.ts +1 -0
- package/dist/compiler/detector/kernels/webgl/index.js +25 -0
- package/dist/compiler/detector/kernels/webgl/smoothHistograms.d.ts +6 -0
- package/dist/compiler/detector/kernels/webgl/smoothHistograms.js +49 -0
- package/dist/compiler/detector/kernels/webgl/upsampleBilinear.d.ts +6 -0
- package/dist/compiler/detector/kernels/webgl/upsampleBilinear.js +56 -0
- package/dist/compiler/estimation/esimate-experiment.d.ts +5 -0
- package/dist/compiler/estimation/esimate-experiment.js +267 -0
- package/dist/compiler/estimation/estimate.d.ts +5 -0
- package/dist/compiler/estimation/estimate.js +51 -0
- package/dist/compiler/estimation/estimator.d.ts +13 -0
- package/dist/compiler/estimation/estimator.js +30 -0
- package/dist/compiler/estimation/refine-estimate-experiment.d.ts +6 -0
- package/dist/compiler/estimation/refine-estimate-experiment.js +429 -0
- package/dist/compiler/estimation/refine-estimate.d.ts +6 -0
- package/dist/compiler/estimation/refine-estimate.js +299 -0
- package/dist/compiler/estimation/utils.d.ts +10 -0
- package/dist/compiler/estimation/utils.js +80 -0
- package/dist/compiler/image-list.d.ts +13 -0
- package/dist/compiler/image-list.js +52 -0
- package/dist/compiler/index.d.ts +3 -0
- package/dist/compiler/index.js +10 -0
- package/dist/compiler/input-loader.d.ts +23 -0
- package/dist/compiler/input-loader.js +88 -0
- package/dist/compiler/matching/hamming-distance.d.ts +1 -0
- package/dist/compiler/matching/hamming-distance.js +20 -0
- package/dist/compiler/matching/hierarchical-clustering.d.ts +7 -0
- package/dist/compiler/matching/hierarchical-clustering.js +109 -0
- package/dist/compiler/matching/hough.d.ts +1 -0
- package/dist/compiler/matching/hough.js +169 -0
- package/dist/compiler/matching/matcher.d.ts +28 -0
- package/dist/compiler/matching/matcher.js +48 -0
- package/dist/compiler/matching/matching.d.ts +41 -0
- package/dist/compiler/matching/matching.js +197 -0
- package/dist/compiler/matching/ransacHomography.d.ts +1 -0
- package/dist/compiler/matching/ransacHomography.js +136 -0
- package/dist/compiler/offline-compiler.d.ts +10 -0
- package/dist/compiler/offline-compiler.js +450 -0
- package/dist/compiler/tensorflow-setup.d.ts +7 -0
- package/dist/compiler/tensorflow-setup.js +73 -0
- package/dist/compiler/three.d.ts +66 -0
- package/dist/compiler/three.js +310 -0
- package/dist/compiler/tracker/extract-utils.d.ts +1 -0
- package/dist/compiler/tracker/extract-utils.js +29 -0
- package/dist/compiler/tracker/extract.d.ts +4 -0
- package/dist/compiler/tracker/extract.js +349 -0
- package/dist/compiler/tracker/tracker.d.ts +38 -0
- package/dist/compiler/tracker/tracker.js +327 -0
- package/dist/compiler/utils/cumsum.d.ts +5 -0
- package/dist/compiler/utils/cumsum.js +39 -0
- package/dist/compiler/utils/geometry.d.ts +8 -0
- package/dist/compiler/utils/geometry.js +101 -0
- package/dist/compiler/utils/homography.d.ts +1 -0
- package/dist/compiler/utils/homography.js +138 -0
- package/dist/compiler/utils/images.d.ts +24 -0
- package/dist/compiler/utils/images.js +99 -0
- package/dist/compiler/utils/randomizer.d.ts +5 -0
- package/dist/compiler/utils/randomizer.js +25 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +7 -0
- package/dist/react/AREditor.d.ts +5 -0
- package/dist/react/AREditor.js +159 -0
- package/dist/react/ProgressDialog.d.ts +13 -0
- package/dist/react/ProgressDialog.js +57 -0
- package/dist/react/types.d.ts +22 -0
- package/dist/react/types.js +14 -0
- package/package.json +53 -0
- package/src/astro/ARScene.astro +59 -0
- package/src/astro/ARVideoTrigger.astro +73 -0
- package/src/astro/overlays/ErrorOverlay.astro +40 -0
- package/src/astro/overlays/LoadingOverlay.astro +28 -0
- package/src/astro/overlays/ScanningOverlay.astro +119 -0
- package/src/astro/scripts/ARScripts.astro +118 -0
- package/src/astro/styles/ARStyles.astro +147 -0
- package/src/compiler/aframe.js +343 -0
- package/src/compiler/compiler-base.js +195 -0
- package/src/compiler/compiler.js +25 -0
- package/src/compiler/compiler.worker.js +30 -0
- package/src/compiler/controller.js +473 -0
- package/src/compiler/controller.worker.js +77 -0
- package/src/compiler/detector/crop-detector.js +68 -0
- package/src/compiler/detector/detector.js +1130 -0
- package/src/compiler/detector/freak.js +91 -0
- package/src/compiler/detector/kernels/cpu/binomialFilter.js +59 -0
- package/src/compiler/detector/kernels/cpu/buildExtremas.js +108 -0
- package/src/compiler/detector/kernels/cpu/computeExtremaAngles.js +91 -0
- package/src/compiler/detector/kernels/cpu/computeExtremaFreak.js +92 -0
- package/src/compiler/detector/kernels/cpu/computeFreakDescriptors.js +68 -0
- package/src/compiler/detector/kernels/cpu/computeLocalization.js +71 -0
- package/src/compiler/detector/kernels/cpu/computeOrientationHistograms.js +141 -0
- package/src/compiler/detector/kernels/cpu/downsampleBilinear.js +33 -0
- package/src/compiler/detector/kernels/cpu/extremaReduction.js +53 -0
- package/src/compiler/detector/kernels/cpu/fakeShader.js +88 -0
- package/src/compiler/detector/kernels/cpu/index.js +26 -0
- package/src/compiler/detector/kernels/cpu/prune.js +114 -0
- package/src/compiler/detector/kernels/cpu/smoothHistograms.js +57 -0
- package/src/compiler/detector/kernels/cpu/upsampleBilinear.js +51 -0
- package/src/compiler/detector/kernels/index.js +2 -0
- package/src/compiler/detector/kernels/webgl/binomialFilter.js +72 -0
- package/src/compiler/detector/kernels/webgl/buildExtremas.js +109 -0
- package/src/compiler/detector/kernels/webgl/computeExtremaAngles.js +82 -0
- package/src/compiler/detector/kernels/webgl/computeExtremaFreak.js +105 -0
- package/src/compiler/detector/kernels/webgl/computeFreakDescriptors.js +56 -0
- package/src/compiler/detector/kernels/webgl/computeLocalization.js +70 -0
- package/src/compiler/detector/kernels/webgl/computeOrientationHistograms.js +129 -0
- package/src/compiler/detector/kernels/webgl/downsampleBilinear.js +50 -0
- package/src/compiler/detector/kernels/webgl/extremaReduction.js +50 -0
- package/src/compiler/detector/kernels/webgl/index.js +26 -0
- package/src/compiler/detector/kernels/webgl/smoothHistograms.js +53 -0
- package/src/compiler/detector/kernels/webgl/upsampleBilinear.js +62 -0
- package/src/compiler/estimation/esimate-experiment.js +316 -0
- package/src/compiler/estimation/estimate.js +67 -0
- package/src/compiler/estimation/estimator.js +34 -0
- package/src/compiler/estimation/refine-estimate-experiment.js +512 -0
- package/src/compiler/estimation/refine-estimate.js +365 -0
- package/src/compiler/estimation/utils.js +97 -0
- package/src/compiler/image-list.js +62 -0
- package/src/compiler/index.js +13 -0
- package/src/compiler/input-loader.js +107 -0
- package/src/compiler/matching/hamming-distance.js +23 -0
- package/src/compiler/matching/hierarchical-clustering.js +131 -0
- package/src/compiler/matching/hough.js +206 -0
- package/src/compiler/matching/matcher.js +59 -0
- package/src/compiler/matching/matching.js +237 -0
- package/src/compiler/matching/ransacHomography.js +192 -0
- package/src/compiler/offline-compiler.js +553 -0
- package/src/compiler/tensorflow-setup.js +88 -0
- package/src/compiler/three.js +368 -0
- package/src/compiler/tracker/extract-utils.js +34 -0
- package/src/compiler/tracker/extract.js +419 -0
- package/src/compiler/tracker/tracker.js +397 -0
- package/src/compiler/utils/cumsum.js +40 -0
- package/src/compiler/utils/geometry.js +114 -0
- package/src/compiler/utils/homography.js +150 -0
- package/src/compiler/utils/images.js +111 -0
- package/src/compiler/utils/randomizer.js +29 -0
- package/src/index.ts +8 -0
- package/src/react/AREditor.tsx +394 -0
- package/src/react/ProgressDialog.tsx +185 -0
- package/src/react/types.ts +35 -0
|
@@ -0,0 +1,299 @@
|
|
|
1
|
+
import { Matrix, inverse } from "ml-matrix";
|
|
2
|
+
import { applyModelViewProjectionTransform, buildModelViewProjectionTransform, computeScreenCoordiate, } from "./utils.js";
|
|
3
|
+
const TRACKING_THRESH = 5.0; // default
|
|
4
|
+
const K2_FACTOR = 4.0; // Question: should it be relative to the size of the screen instead of hardcoded?
|
|
5
|
+
const ICP_MAX_LOOP = 10;
|
|
6
|
+
const ICP_BREAK_LOOP_ERROR_THRESH = 0.1;
|
|
7
|
+
const ICP_BREAK_LOOP_ERROR_RATIO_THRESH = 0.99;
|
|
8
|
+
const ICP_BREAK_LOOP_ERROR_THRESH2 = 4.0;
|
|
9
|
+
// some temporary/intermediate variables used later. Declare them beforehand to reduce new object allocations
|
|
10
|
+
let mat = [[], [], []];
|
|
11
|
+
let J_U_Xc = [[], []]; // 2x3
|
|
12
|
+
let J_Xc_S = [[], [], []]; // 3x6
|
|
13
|
+
const refineEstimate = ({ initialModelViewTransform, projectionTransform, worldCoords, screenCoords, }) => {
|
|
14
|
+
// Question: shall we normlize the screen coords as well?
|
|
15
|
+
// Question: do we need to normlize the scale as well, i.e. make coords from -1 to 1
|
|
16
|
+
//
|
|
17
|
+
// normalize world coords - reposition them to center of mass
|
|
18
|
+
// assume z coordinate is always zero (in our case, the image target is planar with z = 0
|
|
19
|
+
let dx = 0;
|
|
20
|
+
let dy = 0;
|
|
21
|
+
for (let i = 0; i < worldCoords.length; i++) {
|
|
22
|
+
dx += worldCoords[i].x;
|
|
23
|
+
dy += worldCoords[i].y;
|
|
24
|
+
}
|
|
25
|
+
dx /= worldCoords.length;
|
|
26
|
+
dy /= worldCoords.length;
|
|
27
|
+
const normalizedWorldCoords = [];
|
|
28
|
+
for (let i = 0; i < worldCoords.length; i++) {
|
|
29
|
+
normalizedWorldCoords.push({
|
|
30
|
+
x: worldCoords[i].x - dx,
|
|
31
|
+
y: worldCoords[i].y - dy,
|
|
32
|
+
z: worldCoords[i].z,
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
const diffModelViewTransform = [[], [], []];
|
|
36
|
+
for (let j = 0; j < 3; j++) {
|
|
37
|
+
for (let i = 0; i < 3; i++) {
|
|
38
|
+
diffModelViewTransform[j][i] = initialModelViewTransform[j][i];
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
diffModelViewTransform[0][3] =
|
|
42
|
+
initialModelViewTransform[0][0] * dx +
|
|
43
|
+
initialModelViewTransform[0][1] * dy +
|
|
44
|
+
initialModelViewTransform[0][3];
|
|
45
|
+
diffModelViewTransform[1][3] =
|
|
46
|
+
initialModelViewTransform[1][0] * dx +
|
|
47
|
+
initialModelViewTransform[1][1] * dy +
|
|
48
|
+
initialModelViewTransform[1][3];
|
|
49
|
+
diffModelViewTransform[2][3] =
|
|
50
|
+
initialModelViewTransform[2][0] * dx +
|
|
51
|
+
initialModelViewTransform[2][1] * dy +
|
|
52
|
+
initialModelViewTransform[2][3];
|
|
53
|
+
// use iterative closest point algorithm to refine the modelViewTransform
|
|
54
|
+
const inlierProbs = [1.0, 0.8, 0.6, 0.4, 0.0];
|
|
55
|
+
let updatedModelViewTransform = diffModelViewTransform; // iteratively update this transform
|
|
56
|
+
let finalModelViewTransform = null;
|
|
57
|
+
for (let i = 0; i < inlierProbs.length; i++) {
|
|
58
|
+
const ret = _doICP({
|
|
59
|
+
initialModelViewTransform: updatedModelViewTransform,
|
|
60
|
+
projectionTransform,
|
|
61
|
+
worldCoords: normalizedWorldCoords,
|
|
62
|
+
screenCoords,
|
|
63
|
+
inlierProb: inlierProbs[i],
|
|
64
|
+
});
|
|
65
|
+
updatedModelViewTransform = ret.modelViewTransform;
|
|
66
|
+
//console.log("err", ret.err);
|
|
67
|
+
if (ret.err < TRACKING_THRESH) {
|
|
68
|
+
finalModelViewTransform = updatedModelViewTransform;
|
|
69
|
+
break;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
if (finalModelViewTransform === null)
|
|
73
|
+
return null;
|
|
74
|
+
// de-normalize
|
|
75
|
+
finalModelViewTransform[0][3] =
|
|
76
|
+
finalModelViewTransform[0][3] -
|
|
77
|
+
finalModelViewTransform[0][0] * dx -
|
|
78
|
+
finalModelViewTransform[0][1] * dy;
|
|
79
|
+
finalModelViewTransform[1][3] =
|
|
80
|
+
finalModelViewTransform[1][3] -
|
|
81
|
+
finalModelViewTransform[1][0] * dx -
|
|
82
|
+
finalModelViewTransform[1][1] * dy;
|
|
83
|
+
finalModelViewTransform[2][3] =
|
|
84
|
+
finalModelViewTransform[2][3] -
|
|
85
|
+
finalModelViewTransform[2][0] * dx -
|
|
86
|
+
finalModelViewTransform[2][1] * dy;
|
|
87
|
+
return finalModelViewTransform;
|
|
88
|
+
};
|
|
89
|
+
// ICP iteration
|
|
90
|
+
// Question: can someone provide theoretical reference / mathematical proof for the following computations?
|
|
91
|
+
const _doICP = ({ initialModelViewTransform, projectionTransform, worldCoords, screenCoords, inlierProb, }) => {
|
|
92
|
+
const isRobustMode = inlierProb < 1;
|
|
93
|
+
let modelViewTransform = initialModelViewTransform;
|
|
94
|
+
let err0 = 0.0;
|
|
95
|
+
let err1 = 0.0;
|
|
96
|
+
let E = new Array(worldCoords.length);
|
|
97
|
+
let E2 = new Array(worldCoords.length);
|
|
98
|
+
let dxs = new Array(worldCoords.length);
|
|
99
|
+
let dys = new Array(worldCoords.length);
|
|
100
|
+
for (let l = 0; l <= ICP_MAX_LOOP; l++) {
|
|
101
|
+
const modelViewProjectionTransform = buildModelViewProjectionTransform(projectionTransform, modelViewTransform);
|
|
102
|
+
for (let n = 0; n < worldCoords.length; n++) {
|
|
103
|
+
const u = computeScreenCoordiate(modelViewProjectionTransform, worldCoords[n].x, worldCoords[n].y, worldCoords[n].z);
|
|
104
|
+
const dx = screenCoords[n].x - u.x;
|
|
105
|
+
const dy = screenCoords[n].y - u.y;
|
|
106
|
+
dxs[n] = dx;
|
|
107
|
+
dys[n] = dy;
|
|
108
|
+
E[n] = dx * dx + dy * dy;
|
|
109
|
+
}
|
|
110
|
+
let K2; // robust mode only
|
|
111
|
+
err1 = 0.0;
|
|
112
|
+
if (isRobustMode) {
|
|
113
|
+
const inlierNum = Math.max(3, Math.floor(worldCoords.length * inlierProb) - 1);
|
|
114
|
+
for (let n = 0; n < worldCoords.length; n++) {
|
|
115
|
+
E2[n] = E[n];
|
|
116
|
+
}
|
|
117
|
+
E2.sort((a, b) => {
|
|
118
|
+
return a - b;
|
|
119
|
+
});
|
|
120
|
+
K2 = Math.max(E2[inlierNum] * K2_FACTOR, 16.0);
|
|
121
|
+
for (let n = 0; n < worldCoords.length; n++) {
|
|
122
|
+
if (E2[n] > K2)
|
|
123
|
+
err1 += K2 / 6;
|
|
124
|
+
else
|
|
125
|
+
err1 += (K2 / 6.0) * (1.0 - (1.0 - E2[n] / K2) * (1.0 - E2[n] / K2) * (1.0 - E2[n] / K2));
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
else {
|
|
129
|
+
for (let n = 0; n < worldCoords.length; n++) {
|
|
130
|
+
err1 += E[n];
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
err1 /= worldCoords.length;
|
|
134
|
+
//console.log("icp loop", inlierProb, l, err1);
|
|
135
|
+
if (err1 < ICP_BREAK_LOOP_ERROR_THRESH)
|
|
136
|
+
break;
|
|
137
|
+
//if (l > 0 && err1 < ICP_BREAK_LOOP_ERROR_THRESH2 && err1/err0 > ICP_BREAK_LOOP_ERROR_RATIO_THRESH) break;
|
|
138
|
+
if (l > 0 && err1 / err0 > ICP_BREAK_LOOP_ERROR_RATIO_THRESH)
|
|
139
|
+
break;
|
|
140
|
+
if (l === ICP_MAX_LOOP)
|
|
141
|
+
break;
|
|
142
|
+
err0 = err1;
|
|
143
|
+
const dU = [];
|
|
144
|
+
const allJ_U_S = [];
|
|
145
|
+
for (let n = 0; n < worldCoords.length; n++) {
|
|
146
|
+
if (isRobustMode && E[n] > K2) {
|
|
147
|
+
continue;
|
|
148
|
+
}
|
|
149
|
+
const J_U_S = _getJ_U_S({
|
|
150
|
+
modelViewProjectionTransform,
|
|
151
|
+
modelViewTransform,
|
|
152
|
+
projectionTransform,
|
|
153
|
+
worldCoord: worldCoords[n],
|
|
154
|
+
});
|
|
155
|
+
if (isRobustMode) {
|
|
156
|
+
const W = (1.0 - E[n] / K2) * (1.0 - E[n] / K2);
|
|
157
|
+
for (let j = 0; j < 2; j++) {
|
|
158
|
+
for (let i = 0; i < 6; i++) {
|
|
159
|
+
J_U_S[j][i] *= W;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
dU.push([dxs[n] * W]);
|
|
163
|
+
dU.push([dys[n] * W]);
|
|
164
|
+
}
|
|
165
|
+
else {
|
|
166
|
+
dU.push([dxs[n]]);
|
|
167
|
+
dU.push([dys[n]]);
|
|
168
|
+
}
|
|
169
|
+
for (let i = 0; i < J_U_S.length; i++) {
|
|
170
|
+
allJ_U_S.push(J_U_S[i]);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
const dS = _getDeltaS({ dU, J_U_S: allJ_U_S });
|
|
174
|
+
if (dS === null)
|
|
175
|
+
break;
|
|
176
|
+
modelViewTransform = _updateModelViewTransform({ modelViewTransform, dS });
|
|
177
|
+
}
|
|
178
|
+
return { modelViewTransform, err: err1 };
|
|
179
|
+
};
|
|
180
|
+
const _updateModelViewTransform = ({ modelViewTransform, dS }) => {
|
|
181
|
+
/**
|
|
182
|
+
* dS has 6 paragrams, first half is rotation, second half is translation
|
|
183
|
+
* rotation is expressed in angle-axis,
|
|
184
|
+
* [S[0], S[1] ,S[2]] is the axis of rotation, and the magnitude is the angle
|
|
185
|
+
*/
|
|
186
|
+
let ra = dS[0] * dS[0] + dS[1] * dS[1] + dS[2] * dS[2];
|
|
187
|
+
let q0, q1, q2;
|
|
188
|
+
if (ra < 0.000001) {
|
|
189
|
+
q0 = 1.0;
|
|
190
|
+
q1 = 0.0;
|
|
191
|
+
q2 = 0.0;
|
|
192
|
+
ra = 0.0;
|
|
193
|
+
}
|
|
194
|
+
else {
|
|
195
|
+
ra = Math.sqrt(ra);
|
|
196
|
+
q0 = dS[0] / ra;
|
|
197
|
+
q1 = dS[1] / ra;
|
|
198
|
+
q2 = dS[2] / ra;
|
|
199
|
+
}
|
|
200
|
+
const cra = Math.cos(ra);
|
|
201
|
+
const sra = Math.sin(ra);
|
|
202
|
+
const one_cra = 1.0 - cra;
|
|
203
|
+
// mat is [R|t], 3D rotation and translation
|
|
204
|
+
mat[0][0] = q0 * q0 * one_cra + cra;
|
|
205
|
+
mat[0][1] = q0 * q1 * one_cra - q2 * sra;
|
|
206
|
+
mat[0][2] = q0 * q2 * one_cra + q1 * sra;
|
|
207
|
+
mat[0][3] = dS[3];
|
|
208
|
+
mat[1][0] = q1 * q0 * one_cra + q2 * sra;
|
|
209
|
+
mat[1][1] = q1 * q1 * one_cra + cra;
|
|
210
|
+
mat[1][2] = q1 * q2 * one_cra - q0 * sra;
|
|
211
|
+
mat[1][3] = dS[4];
|
|
212
|
+
mat[2][0] = q2 * q0 * one_cra - q1 * sra;
|
|
213
|
+
mat[2][1] = q2 * q1 * one_cra + q0 * sra;
|
|
214
|
+
mat[2][2] = q2 * q2 * one_cra + cra;
|
|
215
|
+
mat[2][3] = dS[5];
|
|
216
|
+
// the updated transform is the original transform x delta transform
|
|
217
|
+
const mat2 = [[], [], []];
|
|
218
|
+
for (let j = 0; j < 3; j++) {
|
|
219
|
+
for (let i = 0; i < 4; i++) {
|
|
220
|
+
mat2[j][i] =
|
|
221
|
+
modelViewTransform[j][0] * mat[0][i] +
|
|
222
|
+
modelViewTransform[j][1] * mat[1][i] +
|
|
223
|
+
modelViewTransform[j][2] * mat[2][i];
|
|
224
|
+
}
|
|
225
|
+
mat2[j][3] += modelViewTransform[j][3];
|
|
226
|
+
}
|
|
227
|
+
return mat2;
|
|
228
|
+
};
|
|
229
|
+
const _getDeltaS = ({ dU, J_U_S }) => {
|
|
230
|
+
const J = new Matrix(J_U_S);
|
|
231
|
+
const U = new Matrix(dU);
|
|
232
|
+
const JT = J.transpose();
|
|
233
|
+
const JTJ = JT.mmul(J);
|
|
234
|
+
const JTU = JT.mmul(U);
|
|
235
|
+
let JTJInv;
|
|
236
|
+
try {
|
|
237
|
+
JTJInv = inverse(JTJ);
|
|
238
|
+
}
|
|
239
|
+
catch (e) {
|
|
240
|
+
return null;
|
|
241
|
+
}
|
|
242
|
+
const S = JTJInv.mmul(JTU);
|
|
243
|
+
return S.to1DArray();
|
|
244
|
+
};
|
|
245
|
+
const _getJ_U_S = ({ modelViewProjectionTransform, modelViewTransform, projectionTransform, worldCoord, }) => {
|
|
246
|
+
const T = modelViewTransform;
|
|
247
|
+
const { x, y, z } = worldCoord;
|
|
248
|
+
const u = applyModelViewProjectionTransform(modelViewProjectionTransform, x, y, z);
|
|
249
|
+
const z2 = u.z * u.z;
|
|
250
|
+
// Question: This is the most confusing matrix to me. I've no idea how to derive this.
|
|
251
|
+
//J_U_Xc[0][0] = (projectionTransform[0][0] * u.z - projectionTransform[2][0] * u.x) / z2;
|
|
252
|
+
//J_U_Xc[0][1] = (projectionTransform[0][1] * u.z - projectionTransform[2][1] * u.x) / z2;
|
|
253
|
+
//J_U_Xc[0][2] = (projectionTransform[0][2] * u.z - projectionTransform[2][2] * u.x) / z2;
|
|
254
|
+
//J_U_Xc[1][0] = (projectionTransform[1][0] * u.z - projectionTransform[2][0] * u.y) / z2;
|
|
255
|
+
//J_U_Xc[1][1] = (projectionTransform[1][1] * u.z - projectionTransform[2][1] * u.y) / z2;
|
|
256
|
+
//J_U_Xc[1][2] = (projectionTransform[1][2] * u.z - projectionTransform[2][2] * u.y) / z2;
|
|
257
|
+
// The above is the original implementation, but simplify to below becuase projetionTransform[2][0] and [2][1] are zero
|
|
258
|
+
J_U_Xc[0][0] = (projectionTransform[0][0] * u.z) / z2;
|
|
259
|
+
J_U_Xc[0][1] = (projectionTransform[0][1] * u.z) / z2;
|
|
260
|
+
J_U_Xc[0][2] = (projectionTransform[0][2] * u.z - projectionTransform[2][2] * u.x) / z2;
|
|
261
|
+
J_U_Xc[1][0] = (projectionTransform[1][0] * u.z) / z2;
|
|
262
|
+
J_U_Xc[1][1] = (projectionTransform[1][1] * u.z) / z2;
|
|
263
|
+
J_U_Xc[1][2] = (projectionTransform[1][2] * u.z - projectionTransform[2][2] * u.y) / z2;
|
|
264
|
+
/*
|
|
265
|
+
J_Xc_S should be like this, but z is zero, so we can simplify
|
|
266
|
+
[T[0][2] * y - T[0][1] * z, T[0][0] * z - T[0][2] * x, T[0][1] * x - T[0][0] * y, T[0][0], T[0][1], T[0][2]],
|
|
267
|
+
[T[1][2] * y - T[1][1] * z, T[1][0] * z - T[1][2] * x, T[1][1] * x - T[1][0] * y, T[1][0], T[1][1], T[1][2]],
|
|
268
|
+
[T[2][2] * y - T[2][1] * z, T[2][0] * z - T[2][2] * x, T[2][1] * x - T[2][0] * y, T[2][0], T[2][1], T[2][2]],
|
|
269
|
+
*/
|
|
270
|
+
J_Xc_S[0][0] = T[0][2] * y;
|
|
271
|
+
J_Xc_S[0][1] = -T[0][2] * x;
|
|
272
|
+
J_Xc_S[0][2] = T[0][1] * x - T[0][0] * y;
|
|
273
|
+
J_Xc_S[0][3] = T[0][0];
|
|
274
|
+
J_Xc_S[0][4] = T[0][1];
|
|
275
|
+
J_Xc_S[0][5] = T[0][2];
|
|
276
|
+
J_Xc_S[1][0] = T[1][2] * y;
|
|
277
|
+
J_Xc_S[1][1] = -T[1][2] * x;
|
|
278
|
+
J_Xc_S[1][2] = T[1][1] * x - T[1][0] * y;
|
|
279
|
+
J_Xc_S[1][3] = T[1][0];
|
|
280
|
+
J_Xc_S[1][4] = T[1][1];
|
|
281
|
+
J_Xc_S[1][5] = T[1][2];
|
|
282
|
+
J_Xc_S[2][0] = T[2][2] * y;
|
|
283
|
+
J_Xc_S[2][1] = -T[2][2] * x;
|
|
284
|
+
J_Xc_S[2][2] = T[2][1] * x - T[2][0] * y;
|
|
285
|
+
J_Xc_S[2][3] = T[2][0];
|
|
286
|
+
J_Xc_S[2][4] = T[2][1];
|
|
287
|
+
J_Xc_S[2][5] = T[2][2];
|
|
288
|
+
const J_U_S = [[], []];
|
|
289
|
+
for (let j = 0; j < 2; j++) {
|
|
290
|
+
for (let i = 0; i < 6; i++) {
|
|
291
|
+
J_U_S[j][i] = 0.0;
|
|
292
|
+
for (let k = 0; k < 3; k++) {
|
|
293
|
+
J_U_S[j][i] += J_U_Xc[j][k] * J_Xc_S[k][i];
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
return J_U_S;
|
|
298
|
+
};
|
|
299
|
+
export { refineEstimate };
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export function buildModelViewProjectionTransform(projectionTransform: any, modelViewTransform: any): any[][];
|
|
2
|
+
export function applyModelViewProjectionTransform(modelViewProjectionTransform: any, x: any, y: any, z: any): {
|
|
3
|
+
x: any;
|
|
4
|
+
y: any;
|
|
5
|
+
z: any;
|
|
6
|
+
};
|
|
7
|
+
export function computeScreenCoordiate(modelViewProjectionTransform: any, x: any, y: any, z: any): {
|
|
8
|
+
x: number;
|
|
9
|
+
y: number;
|
|
10
|
+
};
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
const buildModelViewProjectionTransform = (projectionTransform, modelViewTransform) => {
|
|
2
|
+
// assume the projectTransform has the following format:
|
|
3
|
+
// [[fx, 0, cx],
|
|
4
|
+
// [0, fy, cy]
|
|
5
|
+
// [0, 0, 1]]
|
|
6
|
+
const modelViewProjectionTransform = [
|
|
7
|
+
[
|
|
8
|
+
projectionTransform[0][0] * modelViewTransform[0][0] +
|
|
9
|
+
projectionTransform[0][2] * modelViewTransform[2][0],
|
|
10
|
+
projectionTransform[0][0] * modelViewTransform[0][1] +
|
|
11
|
+
projectionTransform[0][2] * modelViewTransform[2][1],
|
|
12
|
+
projectionTransform[0][0] * modelViewTransform[0][2] +
|
|
13
|
+
projectionTransform[0][2] * modelViewTransform[2][2],
|
|
14
|
+
projectionTransform[0][0] * modelViewTransform[0][3] +
|
|
15
|
+
projectionTransform[0][2] * modelViewTransform[2][3],
|
|
16
|
+
],
|
|
17
|
+
[
|
|
18
|
+
projectionTransform[1][1] * modelViewTransform[1][0] +
|
|
19
|
+
projectionTransform[1][2] * modelViewTransform[2][0],
|
|
20
|
+
projectionTransform[1][1] * modelViewTransform[1][1] +
|
|
21
|
+
projectionTransform[1][2] * modelViewTransform[2][1],
|
|
22
|
+
projectionTransform[1][1] * modelViewTransform[1][2] +
|
|
23
|
+
projectionTransform[1][2] * modelViewTransform[2][2],
|
|
24
|
+
projectionTransform[1][1] * modelViewTransform[1][3] +
|
|
25
|
+
projectionTransform[1][2] * modelViewTransform[2][3],
|
|
26
|
+
],
|
|
27
|
+
[
|
|
28
|
+
modelViewTransform[2][0],
|
|
29
|
+
modelViewTransform[2][1],
|
|
30
|
+
modelViewTransform[2][2],
|
|
31
|
+
modelViewTransform[2][3],
|
|
32
|
+
],
|
|
33
|
+
];
|
|
34
|
+
return modelViewProjectionTransform;
|
|
35
|
+
/*
|
|
36
|
+
// this is the full computation if the projectTransform does not look like the expected format, but more computations
|
|
37
|
+
//
|
|
38
|
+
const modelViewProjectionTransform = [[],[],[]];
|
|
39
|
+
for (let j = 0; j < 3; j++ ) {
|
|
40
|
+
for (let i = 0; i < 4; i++) {
|
|
41
|
+
modelViewProjectionTransform[j][i] = projectionTransform[j][0] * modelViewTransform[0][i]
|
|
42
|
+
+ projectionTransform[j][1] * modelViewTransform[1][i]
|
|
43
|
+
+ projectionTransform[j][2] * modelViewTransform[2][i];
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
return modelViewProjectionTransform;
|
|
47
|
+
*/
|
|
48
|
+
};
|
|
49
|
+
const applyModelViewProjectionTransform = (modelViewProjectionTransform, x, y, z) => {
|
|
50
|
+
// assume z is zero
|
|
51
|
+
const ux = modelViewProjectionTransform[0][0] * x +
|
|
52
|
+
modelViewProjectionTransform[0][1] * y +
|
|
53
|
+
modelViewProjectionTransform[0][3];
|
|
54
|
+
const uy = modelViewProjectionTransform[1][0] * x +
|
|
55
|
+
modelViewProjectionTransform[1][1] * y +
|
|
56
|
+
modelViewProjectionTransform[1][3];
|
|
57
|
+
const uz = modelViewProjectionTransform[2][0] * x +
|
|
58
|
+
modelViewProjectionTransform[2][1] * y +
|
|
59
|
+
modelViewProjectionTransform[2][3];
|
|
60
|
+
return { x: ux, y: uy, z: uz };
|
|
61
|
+
};
|
|
62
|
+
const computeScreenCoordiate = (modelViewProjectionTransform, x, y, z) => {
|
|
63
|
+
const { x: ux, y: uy, z: uz, } = applyModelViewProjectionTransform(modelViewProjectionTransform, x, y, z);
|
|
64
|
+
//if( Math.abs(uz) < 0.000001 ) return null;
|
|
65
|
+
return { x: ux / uz, y: uy / uz };
|
|
66
|
+
};
|
|
67
|
+
const screenToMarkerCoordinate = (modelViewProjectionTransform, sx, sy) => {
|
|
68
|
+
const c11 = modelViewProjectionTransform[2][0] * sx - modelViewProjectionTransform[0][0];
|
|
69
|
+
const c12 = modelViewProjectionTransform[2][1] * sx - modelViewProjectionTransform[0][1];
|
|
70
|
+
const c21 = modelViewProjectionTransform[2][0] * sy - modelViewProjectionTransform[1][0];
|
|
71
|
+
const c22 = modelViewProjectionTransform[2][1] * sy - modelViewProjectionTransform[1][1];
|
|
72
|
+
const b1 = modelViewProjectionTransform[0][3] - modelViewProjectionTransform[2][3] * sx;
|
|
73
|
+
const b2 = modelViewProjectionTransform[1][3] - modelViewProjectionTransform[2][3] * sy;
|
|
74
|
+
const m = c11 * c22 - c12 * c21;
|
|
75
|
+
return {
|
|
76
|
+
x: (c22 * b1 - c12 * b2) / m,
|
|
77
|
+
y: (c11 * b2 - c21 * b1) / m,
|
|
78
|
+
};
|
|
79
|
+
};
|
|
80
|
+
export { buildModelViewProjectionTransform, applyModelViewProjectionTransform, computeScreenCoordiate, };
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Construye una lista de imágenes con diferentes escalas para detección de características
|
|
3
|
+
* @param {Object} inputImage - Imagen de entrada con propiedades width, height y data
|
|
4
|
+
* @returns {Array<Object>} Lista de imágenes escaladas con propiedades data, width, height y scale
|
|
5
|
+
*/
|
|
6
|
+
export function buildImageList(inputImage: Object): Array<Object>;
|
|
7
|
+
/**
|
|
8
|
+
* Construye una lista optimizada de imágenes para tracking
|
|
9
|
+
* Genera dos versiones escaladas (256px y 128px) para tracking eficiente
|
|
10
|
+
* @param {Object} inputImage - Imagen de entrada con propiedades width, height y data
|
|
11
|
+
* @returns {Array<Object>} Lista de imágenes escaladas para tracking
|
|
12
|
+
*/
|
|
13
|
+
export function buildTrackingImageList(inputImage: Object): Array<Object>;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { resize } from "./utils/images.js";
|
|
2
|
+
/**
|
|
3
|
+
* Tamaño mínimo de píxeles para el procesamiento de imágenes
|
|
4
|
+
* Un valor más bajo permite detectar imágenes más pequeñas pero aumenta el tiempo de procesamiento
|
|
5
|
+
* @constant {number}
|
|
6
|
+
*/
|
|
7
|
+
const MIN_IMAGE_PIXEL_SIZE = 100;
|
|
8
|
+
/**
|
|
9
|
+
* Construye una lista de imágenes con diferentes escalas para detección de características
|
|
10
|
+
* @param {Object} inputImage - Imagen de entrada con propiedades width, height y data
|
|
11
|
+
* @returns {Array<Object>} Lista de imágenes escaladas con propiedades data, width, height y scale
|
|
12
|
+
*/
|
|
13
|
+
const buildImageList = (inputImage) => {
|
|
14
|
+
const minScale = MIN_IMAGE_PIXEL_SIZE / Math.min(inputImage.width, inputImage.height);
|
|
15
|
+
const scaleList = [];
|
|
16
|
+
let c = minScale;
|
|
17
|
+
while (true) {
|
|
18
|
+
scaleList.push(c);
|
|
19
|
+
c *= Math.pow(2.0, 1.0 / 3.0);
|
|
20
|
+
if (c >= 0.95) {
|
|
21
|
+
c = 1;
|
|
22
|
+
break;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
scaleList.push(c);
|
|
26
|
+
scaleList.reverse();
|
|
27
|
+
const imageList = [];
|
|
28
|
+
for (let i = 0; i < scaleList.length; i++) {
|
|
29
|
+
const w = inputImage.width * scaleList[i];
|
|
30
|
+
const h = inputImage.height * scaleList[i];
|
|
31
|
+
imageList.push(Object.assign(resize({ image: inputImage, ratio: scaleList[i] }), { scale: scaleList[i] }));
|
|
32
|
+
}
|
|
33
|
+
return imageList;
|
|
34
|
+
};
|
|
35
|
+
/**
|
|
36
|
+
* Construye una lista optimizada de imágenes para tracking
|
|
37
|
+
* Genera dos versiones escaladas (256px y 128px) para tracking eficiente
|
|
38
|
+
* @param {Object} inputImage - Imagen de entrada con propiedades width, height y data
|
|
39
|
+
* @returns {Array<Object>} Lista de imágenes escaladas para tracking
|
|
40
|
+
*/
|
|
41
|
+
const buildTrackingImageList = (inputImage) => {
|
|
42
|
+
const minDimension = Math.min(inputImage.width, inputImage.height);
|
|
43
|
+
const scaleList = [];
|
|
44
|
+
const imageList = [];
|
|
45
|
+
scaleList.push(256.0 / minDimension);
|
|
46
|
+
scaleList.push(128.0 / minDimension);
|
|
47
|
+
for (let i = 0; i < scaleList.length; i++) {
|
|
48
|
+
imageList.push(Object.assign(resize({ image: inputImage, ratio: scaleList[i] }), { scale: scaleList[i] }));
|
|
49
|
+
}
|
|
50
|
+
return imageList;
|
|
51
|
+
};
|
|
52
|
+
export { buildImageList, buildTrackingImageList };
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export class InputLoader {
|
|
2
|
+
constructor(width: any, height: any);
|
|
3
|
+
width: any;
|
|
4
|
+
height: any;
|
|
5
|
+
texShape: any[];
|
|
6
|
+
context: CanvasRenderingContext2D | null;
|
|
7
|
+
program: {
|
|
8
|
+
variableNames: string[];
|
|
9
|
+
outputShape: any[];
|
|
10
|
+
userCode: string;
|
|
11
|
+
};
|
|
12
|
+
tempPixelHandle: any;
|
|
13
|
+
_loadInput(input: any): tf.Tensor3D;
|
|
14
|
+
loadInput(input: any): tf.Tensor<tf.Rank>;
|
|
15
|
+
buildProgram(width: any, height: any): {
|
|
16
|
+
variableNames: string[];
|
|
17
|
+
outputShape: any[];
|
|
18
|
+
userCode: string;
|
|
19
|
+
};
|
|
20
|
+
_compileAndRun(program: any, inputs: any): tf.Tensor<tf.Rank>;
|
|
21
|
+
_runWebGLProgram(program: any, inputs: any, outputType: any): tf.Tensor<tf.Rank>;
|
|
22
|
+
}
|
|
23
|
+
import * as tf from "@tensorflow/tfjs";
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import * as tf from "@tensorflow/tfjs";
|
|
2
|
+
// More efficient implementation for tf.browser.fromPixels
|
|
3
|
+
// original implementation: /node_modules/@tensorflow/tfjs-backend-webgl/src/kernels/FromPixels.ts
|
|
4
|
+
//
|
|
5
|
+
// This implementation return grey scale instead of RGBA in the orignal implementation
|
|
6
|
+
class InputLoader {
|
|
7
|
+
constructor(width, height) {
|
|
8
|
+
this.width = width;
|
|
9
|
+
this.height = height;
|
|
10
|
+
this.texShape = [height, width];
|
|
11
|
+
const context = document.createElement("canvas").getContext("2d");
|
|
12
|
+
context.canvas.width = width;
|
|
13
|
+
context.canvas.height = height;
|
|
14
|
+
this.context = context;
|
|
15
|
+
this.program = this.buildProgram(width, height);
|
|
16
|
+
const backend = tf.backend();
|
|
17
|
+
//this.tempPixelHandle = backend.makeTensorInfo(this.texShape, 'int32');
|
|
18
|
+
this.tempPixelHandle = backend.makeTensorInfo(this.texShape, "float32");
|
|
19
|
+
// warning!!!
|
|
20
|
+
// usage type should be TextureUsage.PIXELS, but tfjs didn't export this enum type, so we hard-coded 2 here
|
|
21
|
+
// i.e. backend.texData.get(tempPixelHandle.dataId).usage = TextureUsage.PIXELS;
|
|
22
|
+
backend.texData.get(this.tempPixelHandle.dataId).usage = 2;
|
|
23
|
+
}
|
|
24
|
+
// old method
|
|
25
|
+
_loadInput(input) {
|
|
26
|
+
return tf.tidy(() => {
|
|
27
|
+
let inputImage = tf.browser.fromPixels(input);
|
|
28
|
+
inputImage = inputImage.mean(2);
|
|
29
|
+
return inputImage;
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
// input is instance of HTMLVideoElement or HTMLImageElement
|
|
33
|
+
loadInput(input) {
|
|
34
|
+
const context = this.context;
|
|
35
|
+
context.clearRect(0, 0, this.context.canvas.width, this.context.canvas.height);
|
|
36
|
+
const isInputRotated = input.width === this.height && input.height === this.width;
|
|
37
|
+
if (isInputRotated) {
|
|
38
|
+
// rotate 90 degree and draw
|
|
39
|
+
let x = this.context.canvas.width / 2;
|
|
40
|
+
let y = this.context.canvas.height / 2;
|
|
41
|
+
let angleInDegrees = 90;
|
|
42
|
+
context.save(); // save the current context state
|
|
43
|
+
context.translate(x, y); // move the context origin to the center of the image
|
|
44
|
+
context.rotate((angleInDegrees * Math.PI) / 180); // rotate the context
|
|
45
|
+
// draw the image with its center at the origin
|
|
46
|
+
context.drawImage(input, -input.width / 2, -input.height / 2);
|
|
47
|
+
context.restore(); // restore the context to its original state
|
|
48
|
+
}
|
|
49
|
+
else {
|
|
50
|
+
this.context.drawImage(input, 0, 0, input.width, input.height);
|
|
51
|
+
}
|
|
52
|
+
const backend = tf.backend();
|
|
53
|
+
backend.gpgpu.uploadPixelDataToTexture(backend.getTexture(this.tempPixelHandle.dataId), this.context.canvas);
|
|
54
|
+
//const res = backend.compileAndRun(this.program, [this.tempPixelHandle]);
|
|
55
|
+
const res = this._compileAndRun(this.program, [this.tempPixelHandle]);
|
|
56
|
+
//const res = this._runWebGLProgram(this.program, [this.tempPixelHandle], 'float32');
|
|
57
|
+
//backend.disposeData(tempPixelHandle.dataId);
|
|
58
|
+
return res;
|
|
59
|
+
}
|
|
60
|
+
buildProgram(width, height) {
|
|
61
|
+
const textureMethod = tf.env().getNumber("WEBGL_VERSION") === 2 ? "texture" : "texture2D";
|
|
62
|
+
const program = {
|
|
63
|
+
variableNames: ["A"],
|
|
64
|
+
outputShape: this.texShape,
|
|
65
|
+
userCode: `
|
|
66
|
+
void main() {
|
|
67
|
+
ivec2 coords = getOutputCoords();
|
|
68
|
+
int texR = coords[0];
|
|
69
|
+
int texC = coords[1];
|
|
70
|
+
vec2 uv = (vec2(texC, texR) + halfCR) / vec2(${width}.0, ${height}.0);
|
|
71
|
+
|
|
72
|
+
vec4 values = ${textureMethod}(A, uv);
|
|
73
|
+
setOutput((0.299 * values.r + 0.587 * values.g + 0.114 * values.b) * 255.0);
|
|
74
|
+
}
|
|
75
|
+
`,
|
|
76
|
+
};
|
|
77
|
+
return program;
|
|
78
|
+
}
|
|
79
|
+
_compileAndRun(program, inputs) {
|
|
80
|
+
const outInfo = tf.backend().compileAndRun(program, inputs);
|
|
81
|
+
return tf.engine().makeTensorFromDataId(outInfo.dataId, outInfo.shape, outInfo.dtype);
|
|
82
|
+
}
|
|
83
|
+
_runWebGLProgram(program, inputs, outputType) {
|
|
84
|
+
const outInfo = tf.backend().runWebGLProgram(program, inputs, outputType);
|
|
85
|
+
return tf.engine().makeTensorFromDataId(outInfo.dataId, outInfo.shape, outInfo.dtype);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
export { InputLoader };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export function compute(options: any): number;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
// Fast computation on number of bit sets
|
|
2
|
+
// Ref: https://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetParallel
|
|
3
|
+
const compute = (options) => {
|
|
4
|
+
const { v1, v2 } = options;
|
|
5
|
+
let d = 0;
|
|
6
|
+
for (let i = 0; i < v1.length; i++) {
|
|
7
|
+
let x = (v1[i] ^ v2[i]) >>> 0;
|
|
8
|
+
d += bitCount(x);
|
|
9
|
+
}
|
|
10
|
+
return d;
|
|
11
|
+
};
|
|
12
|
+
const bitCount = (v) => {
|
|
13
|
+
var c = v - ((v >> 1) & 0x55555555);
|
|
14
|
+
c = ((c >> 2) & 0x33333333) + (c & 0x33333333);
|
|
15
|
+
c = ((c >> 4) + c) & 0x0f0f0f0f;
|
|
16
|
+
c = ((c >> 8) + c) & 0x00ff00ff;
|
|
17
|
+
c = ((c >> 16) + c) & 0x0000ffff;
|
|
18
|
+
return c;
|
|
19
|
+
};
|
|
20
|
+
export { compute };
|