@srsergio/taptapp-ar 1.0.8 → 1.0.10
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/dist/compiler/controller.d.ts +15 -22
- package/dist/compiler/controller.js +73 -92
- package/dist/compiler/detector/crop-detector.d.ts +20 -51
- package/dist/compiler/detector/crop-detector.js +21 -15
- package/dist/compiler/input-loader.d.ts +15 -17
- package/dist/compiler/input-loader.js +58 -76
- package/dist/compiler/matching/hamming-distance.js +4 -4
- package/dist/compiler/matching/matcher.js +2 -2
- package/dist/compiler/matching/matching.d.ts +2 -16
- package/dist/compiler/matching/matching.js +72 -60
- package/dist/compiler/offline-compiler.d.ts +14 -65
- package/dist/compiler/offline-compiler.js +86 -55
- package/dist/compiler/three.js +0 -4
- package/dist/compiler/tracker/tracker.d.ts +26 -12
- package/dist/compiler/tracker/tracker.js +158 -259
- package/dist/compiler/utils/worker-pool.d.ts +2 -1
- package/dist/compiler/utils/worker-pool.js +4 -8
- package/package.json +1 -1
- package/src/compiler/controller.js +71 -93
- package/src/compiler/detector/crop-detector.js +26 -15
- package/src/compiler/input-loader.js +62 -88
- package/src/compiler/matching/hamming-distance.js +4 -4
- package/src/compiler/matching/hough.js +1 -1
- package/src/compiler/matching/matcher.js +2 -2
- package/src/compiler/matching/matching.js +80 -72
- package/src/compiler/offline-compiler.js +92 -58
- package/src/compiler/three.js +0 -4
- package/src/compiler/tracker/tracker.js +183 -283
- package/src/compiler/utils/worker-pool.js +4 -8
- package/dist/compiler/compiler-base.d.ts +0 -8
- package/dist/compiler/compiler-base.js +0 -179
- package/dist/compiler/compiler.d.ts +0 -9
- package/dist/compiler/compiler.js +0 -24
- package/dist/compiler/compiler.worker.d.ts +0 -1
- package/dist/compiler/compiler.worker.js +0 -28
- package/dist/compiler/detector/detector.d.ts +0 -97
- package/dist/compiler/detector/detector.js +0 -1042
- package/dist/compiler/detector/kernels/cpu/binomialFilter.d.ts +0 -6
- package/dist/compiler/detector/kernels/cpu/binomialFilter.js +0 -50
- package/dist/compiler/detector/kernels/cpu/buildExtremas.d.ts +0 -6
- package/dist/compiler/detector/kernels/cpu/buildExtremas.js +0 -89
- package/dist/compiler/detector/kernels/cpu/computeExtremaAngles.d.ts +0 -7
- package/dist/compiler/detector/kernels/cpu/computeExtremaAngles.js +0 -79
- package/dist/compiler/detector/kernels/cpu/computeExtremaFreak.d.ts +0 -6
- package/dist/compiler/detector/kernels/cpu/computeExtremaFreak.js +0 -68
- package/dist/compiler/detector/kernels/cpu/computeFreakDescriptors.d.ts +0 -6
- package/dist/compiler/detector/kernels/cpu/computeFreakDescriptors.js +0 -57
- package/dist/compiler/detector/kernels/cpu/computeLocalization.d.ts +0 -6
- package/dist/compiler/detector/kernels/cpu/computeLocalization.js +0 -50
- package/dist/compiler/detector/kernels/cpu/computeOrientationHistograms.d.ts +0 -6
- package/dist/compiler/detector/kernels/cpu/computeOrientationHistograms.js +0 -100
- package/dist/compiler/detector/kernels/cpu/downsampleBilinear.d.ts +0 -6
- package/dist/compiler/detector/kernels/cpu/downsampleBilinear.js +0 -29
- package/dist/compiler/detector/kernels/cpu/extremaReduction.d.ts +0 -6
- package/dist/compiler/detector/kernels/cpu/extremaReduction.js +0 -50
- package/dist/compiler/detector/kernels/cpu/fakeShader.d.ts +0 -20
- package/dist/compiler/detector/kernels/cpu/fakeShader.js +0 -80
- package/dist/compiler/detector/kernels/cpu/index.d.ts +0 -1
- package/dist/compiler/detector/kernels/cpu/index.js +0 -25
- package/dist/compiler/detector/kernels/cpu/prune.d.ts +0 -7
- package/dist/compiler/detector/kernels/cpu/prune.js +0 -62
- package/dist/compiler/detector/kernels/cpu/smoothHistograms.d.ts +0 -6
- package/dist/compiler/detector/kernels/cpu/smoothHistograms.js +0 -47
- package/dist/compiler/detector/kernels/cpu/upsampleBilinear.d.ts +0 -6
- package/dist/compiler/detector/kernels/cpu/upsampleBilinear.js +0 -43
- package/dist/compiler/detector/kernels/index.d.ts +0 -1
- package/dist/compiler/detector/kernels/index.js +0 -2
- package/dist/compiler/detector/kernels/webgl/binomialFilter.d.ts +0 -6
- package/dist/compiler/detector/kernels/webgl/binomialFilter.js +0 -67
- package/dist/compiler/detector/kernels/webgl/buildExtremas.d.ts +0 -6
- package/dist/compiler/detector/kernels/webgl/buildExtremas.js +0 -101
- package/dist/compiler/detector/kernels/webgl/computeExtremaAngles.d.ts +0 -6
- package/dist/compiler/detector/kernels/webgl/computeExtremaAngles.js +0 -78
- package/dist/compiler/detector/kernels/webgl/computeExtremaFreak.d.ts +0 -6
- package/dist/compiler/detector/kernels/webgl/computeExtremaFreak.js +0 -86
- package/dist/compiler/detector/kernels/webgl/computeFreakDescriptors.d.ts +0 -6
- package/dist/compiler/detector/kernels/webgl/computeFreakDescriptors.js +0 -52
- package/dist/compiler/detector/kernels/webgl/computeLocalization.d.ts +0 -6
- package/dist/compiler/detector/kernels/webgl/computeLocalization.js +0 -58
- package/dist/compiler/detector/kernels/webgl/computeOrientationHistograms.d.ts +0 -6
- package/dist/compiler/detector/kernels/webgl/computeOrientationHistograms.js +0 -116
- package/dist/compiler/detector/kernels/webgl/downsampleBilinear.d.ts +0 -6
- package/dist/compiler/detector/kernels/webgl/downsampleBilinear.js +0 -46
- package/dist/compiler/detector/kernels/webgl/extremaReduction.d.ts +0 -6
- package/dist/compiler/detector/kernels/webgl/extremaReduction.js +0 -48
- package/dist/compiler/detector/kernels/webgl/index.d.ts +0 -1
- package/dist/compiler/detector/kernels/webgl/index.js +0 -25
- package/dist/compiler/detector/kernels/webgl/smoothHistograms.d.ts +0 -6
- package/dist/compiler/detector/kernels/webgl/smoothHistograms.js +0 -49
- package/dist/compiler/detector/kernels/webgl/upsampleBilinear.d.ts +0 -6
- package/dist/compiler/detector/kernels/webgl/upsampleBilinear.js +0 -56
- package/dist/compiler/tensorflow-setup.d.ts +0 -6
- package/dist/compiler/tensorflow-setup.js +0 -99
- package/src/compiler/compiler-base.js +0 -210
- package/src/compiler/compiler.js +0 -25
- package/src/compiler/compiler.worker.js +0 -30
- package/src/compiler/detector/detector.js +0 -1119
- package/src/compiler/detector/kernels/cpu/binomialFilter.js +0 -58
- package/src/compiler/detector/kernels/cpu/buildExtremas.js +0 -108
- package/src/compiler/detector/kernels/cpu/computeExtremaAngles.js +0 -91
- package/src/compiler/detector/kernels/cpu/computeExtremaFreak.js +0 -92
- package/src/compiler/detector/kernels/cpu/computeFreakDescriptors.js +0 -68
- package/src/compiler/detector/kernels/cpu/computeLocalization.js +0 -67
- package/src/compiler/detector/kernels/cpu/computeOrientationHistograms.js +0 -124
- package/src/compiler/detector/kernels/cpu/downsampleBilinear.js +0 -33
- package/src/compiler/detector/kernels/cpu/extremaReduction.js +0 -53
- package/src/compiler/detector/kernels/cpu/fakeShader.js +0 -88
- package/src/compiler/detector/kernels/cpu/index.js +0 -26
- package/src/compiler/detector/kernels/cpu/prune.js +0 -78
- package/src/compiler/detector/kernels/cpu/smoothHistograms.js +0 -57
- package/src/compiler/detector/kernels/cpu/upsampleBilinear.js +0 -51
- package/src/compiler/detector/kernels/index.js +0 -2
- package/src/compiler/detector/kernels/webgl/binomialFilter.js +0 -72
- package/src/compiler/detector/kernels/webgl/buildExtremas.js +0 -109
- package/src/compiler/detector/kernels/webgl/computeExtremaAngles.js +0 -82
- package/src/compiler/detector/kernels/webgl/computeExtremaFreak.js +0 -105
- package/src/compiler/detector/kernels/webgl/computeFreakDescriptors.js +0 -56
- package/src/compiler/detector/kernels/webgl/computeLocalization.js +0 -70
- package/src/compiler/detector/kernels/webgl/computeOrientationHistograms.js +0 -129
- package/src/compiler/detector/kernels/webgl/downsampleBilinear.js +0 -50
- package/src/compiler/detector/kernels/webgl/extremaReduction.js +0 -50
- package/src/compiler/detector/kernels/webgl/index.js +0 -26
- package/src/compiler/detector/kernels/webgl/smoothHistograms.js +0 -53
- package/src/compiler/detector/kernels/webgl/upsampleBilinear.js +0 -62
- package/src/compiler/tensorflow-setup.js +0 -116
|
@@ -15,17 +15,18 @@ const match = ({ keyframe, querypoints, querywidth, queryheight, debugMode }) =>
|
|
|
15
15
|
let debugExtra = {};
|
|
16
16
|
|
|
17
17
|
const matches = [];
|
|
18
|
-
|
|
18
|
+
const qlen = querypoints.length;
|
|
19
|
+
const kmax = keyframe.max;
|
|
20
|
+
const kmin = keyframe.min;
|
|
21
|
+
|
|
22
|
+
for (let j = 0; j < qlen; j++) {
|
|
19
23
|
const querypoint = querypoints[j];
|
|
20
|
-
const col = querypoint.maxima ?
|
|
24
|
+
const col = querypoint.maxima ? kmax : kmin;
|
|
21
25
|
if (!col || col.x.length === 0) continue;
|
|
22
26
|
|
|
23
27
|
const rootNode = col.t;
|
|
24
|
-
|
|
25
28
|
const keypointIndexes = [];
|
|
26
|
-
const queue = new TinyQueue([], (a1, a2) =>
|
|
27
|
-
return a1.d - a2.d;
|
|
28
|
-
});
|
|
29
|
+
const queue = new TinyQueue([], (a1, a2) => a1.d - a2.d);
|
|
29
30
|
|
|
30
31
|
// query potential candidates from the columnar tree
|
|
31
32
|
_query({
|
|
@@ -41,13 +42,15 @@ const match = ({ keyframe, querypoints, querywidth, queryheight, debugMode }) =>
|
|
|
41
42
|
let bestD1 = Number.MAX_SAFE_INTEGER;
|
|
42
43
|
let bestD2 = Number.MAX_SAFE_INTEGER;
|
|
43
44
|
|
|
45
|
+
const qDesc = querypoint.descriptors;
|
|
46
|
+
const cDesc = col.d;
|
|
47
|
+
|
|
44
48
|
for (let k = 0; k < keypointIndexes.length; k++) {
|
|
45
49
|
const idx = keypointIndexes[k];
|
|
46
50
|
|
|
47
|
-
//
|
|
48
|
-
const
|
|
51
|
+
// Use offsets to avoid subarray allocation
|
|
52
|
+
const d = hammingCompute({ v1: cDesc, v1Offset: idx * 84, v2: qDesc });
|
|
49
53
|
|
|
50
|
-
const d = hammingCompute({ v1: keypointDescriptor, v2: querypoint.descriptors });
|
|
51
54
|
if (d < bestD1) {
|
|
52
55
|
bestD2 = bestD1;
|
|
53
56
|
bestD1 = d;
|
|
@@ -59,36 +62,31 @@ const match = ({ keyframe, querypoints, querywidth, queryheight, debugMode }) =>
|
|
|
59
62
|
|
|
60
63
|
if (
|
|
61
64
|
bestIndex !== -1 &&
|
|
62
|
-
(bestD2 === Number.MAX_SAFE_INTEGER || (
|
|
65
|
+
(bestD2 === Number.MAX_SAFE_INTEGER || (bestD1 / bestD2) < HAMMING_THRESHOLD)
|
|
63
66
|
) {
|
|
64
67
|
matches.push({
|
|
65
68
|
querypoint,
|
|
66
69
|
keypoint: {
|
|
67
70
|
x: col.x[bestIndex],
|
|
68
71
|
y: col.y[bestIndex],
|
|
69
|
-
angle: col.a[bestIndex]
|
|
72
|
+
angle: col.a[bestIndex],
|
|
73
|
+
scale: col.s ? col.s[bestIndex] : keyframe.s
|
|
70
74
|
}
|
|
71
75
|
});
|
|
72
76
|
}
|
|
73
77
|
}
|
|
74
78
|
|
|
75
|
-
if (debugMode) {
|
|
76
|
-
debugExtra.matches = matches;
|
|
77
|
-
}
|
|
78
|
-
|
|
79
79
|
if (matches.length < MIN_NUM_INLIERS) return { debugExtra };
|
|
80
80
|
|
|
81
81
|
const houghMatches = computeHoughMatches({
|
|
82
|
-
keywidth: keyframe.w,
|
|
82
|
+
keywidth: keyframe.w,
|
|
83
83
|
keyheight: keyframe.h,
|
|
84
84
|
querywidth,
|
|
85
85
|
queryheight,
|
|
86
86
|
matches,
|
|
87
87
|
});
|
|
88
88
|
|
|
89
|
-
if (debugMode)
|
|
90
|
-
debugExtra.houghMatches = houghMatches;
|
|
91
|
-
}
|
|
89
|
+
if (debugMode) debugExtra.houghMatches = houghMatches;
|
|
92
90
|
|
|
93
91
|
const H = computeHomography({
|
|
94
92
|
srcPoints: houghMatches.map((m) => [m.keypoint.x, m.keypoint.y]),
|
|
@@ -104,37 +102,46 @@ const match = ({ keyframe, querypoints, querywidth, queryheight, debugMode }) =>
|
|
|
104
102
|
threshold: INLIER_THRESHOLD,
|
|
105
103
|
});
|
|
106
104
|
|
|
107
|
-
if (debugMode)
|
|
108
|
-
debugExtra.inlierMatches = inlierMatches;
|
|
109
|
-
}
|
|
110
|
-
|
|
105
|
+
if (debugMode) debugExtra.inlierMatches = inlierMatches;
|
|
111
106
|
if (inlierMatches.length < MIN_NUM_INLIERS) return { debugExtra };
|
|
112
107
|
|
|
113
108
|
// Second pass with homography guided matching
|
|
114
109
|
const HInv = matrixInverse33(H, 0.00001);
|
|
115
|
-
const dThreshold2 = 10 * 10
|
|
110
|
+
const dThreshold2 = 100; // 10 * 10
|
|
116
111
|
const matches2 = [];
|
|
117
112
|
|
|
118
|
-
|
|
113
|
+
const hi00 = HInv[0], hi01 = HInv[1], hi02 = HInv[2];
|
|
114
|
+
const hi10 = HInv[3], hi11 = HInv[4], hi12 = HInv[5];
|
|
115
|
+
const hi20 = HInv[6], hi21 = HInv[7], hi22 = HInv[8];
|
|
116
|
+
|
|
117
|
+
for (let j = 0; j < qlen; j++) {
|
|
119
118
|
const querypoint = querypoints[j];
|
|
120
|
-
const
|
|
119
|
+
const qx = querypoint.x, qy = querypoint.y;
|
|
120
|
+
|
|
121
|
+
// Inline multiplyPointHomographyInhomogenous
|
|
122
|
+
const uz = (qx * hi20) + (qy * hi21) + hi22;
|
|
123
|
+
const invZ = 1.0 / uz;
|
|
124
|
+
const mapX = ((qx * hi00) + (qy * hi01) + hi02) * invZ;
|
|
125
|
+
const mapY = ((qx * hi10) + (qy * hi11) + hi12) * invZ;
|
|
121
126
|
|
|
122
127
|
let bestIndex = -1;
|
|
123
128
|
let bestD1 = Number.MAX_SAFE_INTEGER;
|
|
124
129
|
let bestD2 = Number.MAX_SAFE_INTEGER;
|
|
125
130
|
|
|
126
|
-
const col = querypoint.maxima ?
|
|
131
|
+
const col = querypoint.maxima ? kmax : kmin;
|
|
127
132
|
if (!col) continue;
|
|
128
133
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
134
|
+
const cx = col.x, cy = col.y, cd = col.d;
|
|
135
|
+
const qDesc = querypoint.descriptors;
|
|
136
|
+
|
|
137
|
+
for (let k = 0, clen = cx.length; k < clen; k++) {
|
|
138
|
+
const dx = cx[k] - mapX;
|
|
139
|
+
const dy = cy[k] - mapY;
|
|
132
140
|
const d2 = dx * dx + dy * dy;
|
|
133
141
|
|
|
134
142
|
if (d2 > dThreshold2) continue;
|
|
135
143
|
|
|
136
|
-
const
|
|
137
|
-
const d = hammingCompute({ v1: keypointDescriptor, v2: querypoint.descriptors });
|
|
144
|
+
const d = hammingCompute({ v1: cd, v1Offset: k * 84, v2: qDesc });
|
|
138
145
|
|
|
139
146
|
if (d < bestD1) {
|
|
140
147
|
bestD2 = bestD1;
|
|
@@ -147,22 +154,21 @@ const match = ({ keyframe, querypoints, querywidth, queryheight, debugMode }) =>
|
|
|
147
154
|
|
|
148
155
|
if (
|
|
149
156
|
bestIndex !== -1 &&
|
|
150
|
-
(bestD2 === Number.MAX_SAFE_INTEGER || (
|
|
157
|
+
(bestD2 === Number.MAX_SAFE_INTEGER || (bestD1 / bestD2) < HAMMING_THRESHOLD)
|
|
151
158
|
) {
|
|
152
159
|
matches2.push({
|
|
153
160
|
querypoint,
|
|
154
161
|
keypoint: {
|
|
155
162
|
x: col.x[bestIndex],
|
|
156
163
|
y: col.y[bestIndex],
|
|
157
|
-
angle: col.a[bestIndex]
|
|
164
|
+
angle: col.a[bestIndex],
|
|
165
|
+
scale: col.s ? col.s[bestIndex] : keyframe.s
|
|
158
166
|
}
|
|
159
167
|
});
|
|
160
168
|
}
|
|
161
169
|
}
|
|
162
170
|
|
|
163
|
-
if (debugMode)
|
|
164
|
-
debugExtra.matches2 = matches2;
|
|
165
|
-
}
|
|
171
|
+
if (debugMode) debugExtra.matches2 = matches2;
|
|
166
172
|
|
|
167
173
|
const houghMatches2 = computeHoughMatches({
|
|
168
174
|
keywidth: keyframe.w,
|
|
@@ -172,9 +178,7 @@ const match = ({ keyframe, querypoints, querywidth, queryheight, debugMode }) =>
|
|
|
172
178
|
matches: matches2,
|
|
173
179
|
});
|
|
174
180
|
|
|
175
|
-
if (debugMode)
|
|
176
|
-
debugExtra.houghMatches2 = houghMatches2;
|
|
177
|
-
}
|
|
181
|
+
if (debugMode) debugExtra.houghMatches2 = houghMatches2;
|
|
178
182
|
|
|
179
183
|
const H2 = computeHomography({
|
|
180
184
|
srcPoints: houghMatches2.map((m) => [m.keypoint.x, m.keypoint.y]),
|
|
@@ -190,16 +194,13 @@ const match = ({ keyframe, querypoints, querywidth, queryheight, debugMode }) =>
|
|
|
190
194
|
threshold: INLIER_THRESHOLD,
|
|
191
195
|
});
|
|
192
196
|
|
|
193
|
-
if (debugMode)
|
|
194
|
-
debugExtra.inlierMatches2 = inlierMatches2;
|
|
195
|
-
}
|
|
197
|
+
if (debugMode) debugExtra.inlierMatches2 = inlierMatches2;
|
|
196
198
|
|
|
197
199
|
return { H: H2, matches: inlierMatches2, debugExtra };
|
|
198
200
|
};
|
|
199
201
|
|
|
200
202
|
const _query = ({ node, descriptors, querypoint, queue, keypointIndexes, numPop }) => {
|
|
201
203
|
const isLeaf = node[0] === 1;
|
|
202
|
-
const centerIdx = node[1];
|
|
203
204
|
const childrenOrIndices = node[2];
|
|
204
205
|
|
|
205
206
|
if (isLeaf) {
|
|
@@ -209,56 +210,63 @@ const _query = ({ node, descriptors, querypoint, queue, keypointIndexes, numPop
|
|
|
209
210
|
return;
|
|
210
211
|
}
|
|
211
212
|
|
|
212
|
-
const
|
|
213
|
-
|
|
213
|
+
const qDesc = querypoint.descriptors;
|
|
214
|
+
let minD = Number.MAX_SAFE_INTEGER;
|
|
215
|
+
const clen = childrenOrIndices.length;
|
|
216
|
+
const distances = new Int32Array(clen);
|
|
217
|
+
|
|
218
|
+
for (let i = 0; i < clen; i++) {
|
|
214
219
|
const childNode = childrenOrIndices[i];
|
|
215
220
|
const cIdx = childNode[1];
|
|
216
221
|
|
|
217
222
|
const d = hammingCompute({
|
|
218
|
-
v1: descriptors
|
|
219
|
-
|
|
223
|
+
v1: descriptors,
|
|
224
|
+
v1Offset: cIdx * 84,
|
|
225
|
+
v2: qDesc,
|
|
220
226
|
});
|
|
221
|
-
distances
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
let minD = Number.MAX_SAFE_INTEGER;
|
|
225
|
-
for (let i = 0; i < childrenOrIndices.length; i++) {
|
|
226
|
-
minD = Math.min(minD, distances[i]);
|
|
227
|
+
distances[i] = d;
|
|
228
|
+
if (d < minD) minD = d;
|
|
227
229
|
}
|
|
228
230
|
|
|
229
|
-
for (let i = 0; i <
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
for (let i = 0; i < childrenOrIndices.length; i++) {
|
|
235
|
-
if (distances[i] === minD) {
|
|
231
|
+
for (let i = 0; i < clen; i++) {
|
|
232
|
+
const dist = distances[i];
|
|
233
|
+
if (dist !== minD) {
|
|
234
|
+
queue.push({ node: childrenOrIndices[i], d: dist });
|
|
235
|
+
} else {
|
|
236
236
|
_query({ node: childrenOrIndices[i], descriptors, querypoint, queue, keypointIndexes, numPop });
|
|
237
237
|
}
|
|
238
238
|
}
|
|
239
239
|
|
|
240
240
|
if (numPop < CLUSTER_MAX_POP && queue.length > 0) {
|
|
241
241
|
const { node } = queue.pop();
|
|
242
|
-
numPop
|
|
243
|
-
_query({ node, descriptors, querypoint, queue, keypointIndexes, numPop });
|
|
242
|
+
_query({ node, descriptors, querypoint, queue, keypointIndexes, numPop: numPop + 1 });
|
|
244
243
|
}
|
|
245
244
|
};
|
|
246
245
|
|
|
247
246
|
const _findInlierMatches = (options) => {
|
|
248
247
|
const { H, matches, threshold } = options;
|
|
249
|
-
|
|
250
248
|
const threshold2 = threshold * threshold;
|
|
251
249
|
|
|
250
|
+
const h00 = H[0], h01 = H[1], h02 = H[2];
|
|
251
|
+
const h10 = H[3], h11 = H[4], h12 = H[5];
|
|
252
|
+
const h20 = H[6], h21 = H[7], h22 = H[8];
|
|
253
|
+
|
|
252
254
|
const goodMatches = [];
|
|
253
255
|
for (let i = 0; i < matches.length; i++) {
|
|
254
|
-
const
|
|
255
|
-
const
|
|
256
|
-
const
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
256
|
+
const m = matches[i];
|
|
257
|
+
const qp = m.querypoint;
|
|
258
|
+
const kp = m.keypoint;
|
|
259
|
+
|
|
260
|
+
// Inline multiplyPointHomographyInhomogenous
|
|
261
|
+
const uz = (kp.x * h20) + (kp.y * h21) + h22;
|
|
262
|
+
const invZ = 1.0 / uz;
|
|
263
|
+
const mx = ((kp.x * h00) + (kp.y * h01) + h02) * invZ;
|
|
264
|
+
const my = ((kp.x * h10) + (kp.y * h11) + h12) * invZ;
|
|
265
|
+
|
|
266
|
+
const dx = mx - qp.x;
|
|
267
|
+
const dy = my - qp.y;
|
|
268
|
+
if (dx * dx + dy * dy <= threshold2) {
|
|
269
|
+
goodMatches.push(m);
|
|
262
270
|
}
|
|
263
271
|
}
|
|
264
272
|
return goodMatches;
|
|
@@ -20,6 +20,7 @@ import { extractTrackingFeatures } from "./tracker/extract-utils.js";
|
|
|
20
20
|
import { DetectorLite } from "./detector/detector-lite.js";
|
|
21
21
|
import { build as hierarchicalClusteringBuild } from "./matching/hierarchical-clustering.js";
|
|
22
22
|
import * as msgpack from "@msgpack/msgpack";
|
|
23
|
+
import { WorkerPool } from "./utils/worker-pool.js";
|
|
23
24
|
|
|
24
25
|
// Detect environment
|
|
25
26
|
const isNode = typeof process !== "undefined" &&
|
|
@@ -46,22 +47,30 @@ export class OfflineCompiler {
|
|
|
46
47
|
|
|
47
48
|
async _initNodeWorkers() {
|
|
48
49
|
try {
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
50
|
+
// Use variables to prevent bundlers from trying to bundle these
|
|
51
|
+
const pathModule = "path";
|
|
52
|
+
const urlModule = "url";
|
|
53
|
+
const osModule = "os";
|
|
54
|
+
const workerThreadsModule = "node:worker_threads";
|
|
55
|
+
|
|
56
|
+
const [path, url, os, { Worker }] = await Promise.all([
|
|
57
|
+
import(pathModule),
|
|
58
|
+
import(urlModule),
|
|
59
|
+
import(osModule),
|
|
60
|
+
import(workerThreadsModule)
|
|
54
61
|
]);
|
|
55
62
|
|
|
56
63
|
const __filename = url.fileURLToPath(import.meta.url);
|
|
57
64
|
const __dirname = path.dirname(__filename);
|
|
58
65
|
const workerPath = path.join(__dirname, "node-worker.js");
|
|
59
66
|
|
|
67
|
+
// Limit workers to avoid freezing system
|
|
60
68
|
const numWorkers = Math.min(os.cpus().length, 4);
|
|
61
|
-
|
|
69
|
+
|
|
70
|
+
this.workerPool = new WorkerPool(workerPath, numWorkers, Worker);
|
|
62
71
|
console.log(`🚀 OfflineCompiler: Node.js mode with ${numWorkers} workers`);
|
|
63
72
|
} catch (e) {
|
|
64
|
-
console.log("⚡ OfflineCompiler: Running without workers");
|
|
73
|
+
console.log("⚡ OfflineCompiler: Running without workers (initialization failed)", e);
|
|
65
74
|
}
|
|
66
75
|
}
|
|
67
76
|
|
|
@@ -104,48 +113,57 @@ export class OfflineCompiler {
|
|
|
104
113
|
|
|
105
114
|
targetImages.push({
|
|
106
115
|
data: greyImageData,
|
|
107
|
-
height: img.height,
|
|
108
116
|
width: img.width,
|
|
117
|
+
height: img.height,
|
|
109
118
|
});
|
|
110
119
|
}
|
|
111
120
|
|
|
112
|
-
//
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
progressCallback(percent * 0.5);
|
|
121
|
+
// Compilar Match y Track por separado
|
|
122
|
+
const matchingDataList = await this._compileMatch(targetImages, (p) => {
|
|
123
|
+
progressCallback(p * 0.7); // 70% Match
|
|
116
124
|
});
|
|
117
|
-
console.timeEnd("⏱️ Fase Matching");
|
|
118
125
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
const trackingDataList = await this._compileTrack(targetImages, (percent) => {
|
|
122
|
-
progressCallback(50 + percent * 0.5);
|
|
126
|
+
const trackingDataList = await this._compileTrack(targetImages, (p) => {
|
|
127
|
+
progressCallback(70 + p * 0.3); // 30% Track
|
|
123
128
|
});
|
|
124
|
-
console.timeEnd("⏱️ Fase Tracking");
|
|
125
129
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
targetImage: { width: targetImage.width, height: targetImage.height },
|
|
129
|
-
trackingData: trackingDataList[i],
|
|
130
|
+
this.data = targetImages.map((img, i) => ({
|
|
131
|
+
targetImage: img,
|
|
130
132
|
matchingData: matchingDataList[i],
|
|
133
|
+
trackingData: trackingDataList[i],
|
|
131
134
|
}));
|
|
132
135
|
|
|
133
136
|
console.timeEnd("⏱️ Compilación total");
|
|
134
|
-
|
|
135
137
|
return this.data;
|
|
136
138
|
}
|
|
137
139
|
|
|
138
|
-
/**
|
|
139
|
-
* Compila datos de matching usando DetectorLite (JS puro)
|
|
140
|
-
*/
|
|
141
140
|
async _compileMatch(targetImages, progressCallback) {
|
|
142
141
|
const percentPerImage = 100 / targetImages.length;
|
|
143
142
|
let currentPercent = 0;
|
|
144
143
|
|
|
145
|
-
|
|
144
|
+
// Use workers if available
|
|
145
|
+
if (this.workerPool) {
|
|
146
|
+
const progressMap = new Float32Array(targetImages.length);
|
|
147
|
+
|
|
148
|
+
const wrappedPromises = targetImages.map((targetImage, index) => {
|
|
149
|
+
return this.workerPool.runTask({
|
|
150
|
+
type: 'match',
|
|
151
|
+
targetImage,
|
|
152
|
+
percentPerImage,
|
|
153
|
+
basePercent: 0,
|
|
154
|
+
onProgress: (p) => {
|
|
155
|
+
progressMap[index] = p;
|
|
156
|
+
const sum = progressMap.reduce((a, b) => a + b, 0);
|
|
157
|
+
progressCallback(sum);
|
|
158
|
+
}
|
|
159
|
+
});
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
return Promise.all(wrappedPromises);
|
|
163
|
+
}
|
|
146
164
|
|
|
147
|
-
//
|
|
148
|
-
|
|
165
|
+
// Serial Fallback
|
|
166
|
+
const results = [];
|
|
149
167
|
for (let i = 0; i < targetImages.length; i++) {
|
|
150
168
|
const targetImage = targetImages[i];
|
|
151
169
|
const imageList = buildImageList(targetImage);
|
|
@@ -182,15 +200,30 @@ export class OfflineCompiler {
|
|
|
182
200
|
return results;
|
|
183
201
|
}
|
|
184
202
|
|
|
185
|
-
/**
|
|
186
|
-
* Compila datos de tracking usando extractTrackingFeatures (JS puro)
|
|
187
|
-
*/
|
|
188
203
|
async _compileTrack(targetImages, progressCallback) {
|
|
189
204
|
const percentPerImage = 100 / targetImages.length;
|
|
190
205
|
let currentPercent = 0;
|
|
191
206
|
|
|
192
|
-
|
|
207
|
+
if (this.workerPool) {
|
|
208
|
+
const progressMap = new Float32Array(targetImages.length);
|
|
209
|
+
const wrappedPromises = targetImages.map((targetImage, index) => {
|
|
210
|
+
return this.workerPool.runTask({
|
|
211
|
+
type: 'compile',
|
|
212
|
+
targetImage,
|
|
213
|
+
percentPerImage,
|
|
214
|
+
basePercent: 0,
|
|
215
|
+
onProgress: (p) => {
|
|
216
|
+
progressMap[index] = p;
|
|
217
|
+
const sum = progressMap.reduce((a, b) => a + b, 0);
|
|
218
|
+
progressCallback(sum);
|
|
219
|
+
}
|
|
220
|
+
});
|
|
221
|
+
});
|
|
222
|
+
return Promise.all(wrappedPromises);
|
|
223
|
+
}
|
|
193
224
|
|
|
225
|
+
// Serial Fallback
|
|
226
|
+
const results = [];
|
|
194
227
|
for (let i = 0; i < targetImages.length; i++) {
|
|
195
228
|
const targetImage = targetImages[i];
|
|
196
229
|
const imageList = buildTrackingImageList(targetImage);
|
|
@@ -207,42 +240,26 @@ export class OfflineCompiler {
|
|
|
207
240
|
return results;
|
|
208
241
|
}
|
|
209
242
|
|
|
210
|
-
/**
|
|
211
|
-
* Método público para compilar tracking (compatibilidad con API anterior)
|
|
212
|
-
* @param {Object} options - Opciones de compilación
|
|
213
|
-
* @param {Function} options.progressCallback - Callback de progreso
|
|
214
|
-
* @param {Array} options.targetImages - Lista de imágenes objetivo
|
|
215
|
-
* @param {number} options.basePercent - Porcentaje base
|
|
216
|
-
* @returns {Promise<Array>} Datos de tracking
|
|
217
|
-
*/
|
|
218
243
|
async compileTrack({ progressCallback, targetImages, basePercent = 0 }) {
|
|
219
244
|
return this._compileTrack(targetImages, (percent) => {
|
|
220
245
|
progressCallback(basePercent + percent * (100 - basePercent) / 100);
|
|
221
246
|
});
|
|
222
247
|
}
|
|
223
248
|
|
|
224
|
-
/**
|
|
225
|
-
* Método público para compilar matching (compatibilidad con API anterior)
|
|
226
|
-
*/
|
|
227
249
|
async compileMatch({ progressCallback, targetImages, basePercent = 0 }) {
|
|
228
250
|
return this._compileMatch(targetImages, (percent) => {
|
|
229
251
|
progressCallback(basePercent + percent * (50 - basePercent) / 100);
|
|
230
252
|
});
|
|
231
253
|
}
|
|
232
254
|
|
|
233
|
-
/**
|
|
234
|
-
* Exporta datos compilados en formato binario columnar optimizado
|
|
235
|
-
*/
|
|
236
255
|
exportData() {
|
|
237
256
|
if (!this.data) {
|
|
238
257
|
throw new Error("No hay datos compilados para exportar");
|
|
239
258
|
}
|
|
240
259
|
|
|
241
260
|
const dataList = this.data.map((item) => {
|
|
242
|
-
// Optimizamos MatchingData convirtiéndolo a formato columnar
|
|
243
261
|
const matchingData = item.matchingData.map((kf) => this._packKeyframe(kf));
|
|
244
262
|
|
|
245
|
-
// Optimizamos TrackingData (Zero-copy layout)
|
|
246
263
|
const trackingData = item.trackingData.map((td) => {
|
|
247
264
|
const count = td.points.length;
|
|
248
265
|
const px = new Float32Array(count);
|
|
@@ -292,12 +309,14 @@ export class OfflineCompiler {
|
|
|
292
309
|
const x = new Float32Array(count);
|
|
293
310
|
const y = new Float32Array(count);
|
|
294
311
|
const angle = new Float32Array(count);
|
|
312
|
+
const scale = new Float32Array(count);
|
|
295
313
|
const descriptors = new Uint8Array(count * 84); // 84 bytes per point (FREAK)
|
|
296
314
|
|
|
297
315
|
for (let i = 0; i < count; i++) {
|
|
298
316
|
x[i] = points[i].x;
|
|
299
317
|
y[i] = points[i].y;
|
|
300
318
|
angle[i] = points[i].angle;
|
|
319
|
+
scale[i] = points[i].scale;
|
|
301
320
|
descriptors.set(points[i].descriptors, i * 84);
|
|
302
321
|
}
|
|
303
322
|
|
|
@@ -305,6 +324,7 @@ export class OfflineCompiler {
|
|
|
305
324
|
x,
|
|
306
325
|
y,
|
|
307
326
|
a: angle,
|
|
327
|
+
s: scale,
|
|
308
328
|
d: descriptors,
|
|
309
329
|
t: this._compactTree(tree.rootNode),
|
|
310
330
|
};
|
|
@@ -317,9 +337,6 @@ export class OfflineCompiler {
|
|
|
317
337
|
return [0, node.centerPointIndex || 0, node.children.map((c) => this._compactTree(c))];
|
|
318
338
|
}
|
|
319
339
|
|
|
320
|
-
/**
|
|
321
|
-
* Importa datos - Mantiene el formato columnar para máximo rendimiento (Zero-copy)
|
|
322
|
-
*/
|
|
323
340
|
importData(buffer) {
|
|
324
341
|
const content = msgpack.decode(new Uint8Array(buffer));
|
|
325
342
|
|
|
@@ -328,10 +345,29 @@ export class OfflineCompiler {
|
|
|
328
345
|
return [];
|
|
329
346
|
}
|
|
330
347
|
|
|
331
|
-
//
|
|
332
|
-
|
|
333
|
-
|
|
348
|
+
// Restore Float32Arrays from Uint8Arrays returned by msgpack
|
|
349
|
+
const dataList = content.dataList;
|
|
350
|
+
for (let i = 0; i < dataList.length; i++) {
|
|
351
|
+
const item = dataList[i];
|
|
352
|
+
for (const kf of item.matchingData) {
|
|
353
|
+
for (const col of [kf.max, kf.min]) {
|
|
354
|
+
if (col.x instanceof Uint8Array) {
|
|
355
|
+
col.x = new Float32Array(col.x.buffer.slice(col.x.byteOffset, col.x.byteOffset + col.x.byteLength));
|
|
356
|
+
}
|
|
357
|
+
if (col.y instanceof Uint8Array) {
|
|
358
|
+
col.y = new Float32Array(col.y.buffer.slice(col.y.byteOffset, col.y.byteOffset + col.y.byteLength));
|
|
359
|
+
}
|
|
360
|
+
if (col.a instanceof Uint8Array) {
|
|
361
|
+
col.a = new Float32Array(col.a.buffer.slice(col.a.byteOffset, col.a.byteOffset + col.a.byteLength));
|
|
362
|
+
}
|
|
363
|
+
if (col.s instanceof Uint8Array) {
|
|
364
|
+
col.s = new Float32Array(col.s.buffer.slice(col.s.byteOffset, col.s.byteOffset + col.s.byteLength));
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
}
|
|
334
369
|
|
|
370
|
+
this.data = dataList;
|
|
335
371
|
return this.data;
|
|
336
372
|
}
|
|
337
373
|
|
|
@@ -355,6 +391,7 @@ export class OfflineCompiler {
|
|
|
355
391
|
x: col.x[i],
|
|
356
392
|
y: col.y[i],
|
|
357
393
|
angle: col.a[i],
|
|
394
|
+
scale: col.s ? col.s[i] : 1.0,
|
|
358
395
|
descriptors: col.d.slice(i * 84, (i + 1) * 84),
|
|
359
396
|
});
|
|
360
397
|
}
|
|
@@ -377,9 +414,6 @@ export class OfflineCompiler {
|
|
|
377
414
|
};
|
|
378
415
|
}
|
|
379
416
|
|
|
380
|
-
/**
|
|
381
|
-
* Destruye el pool de workers
|
|
382
|
-
*/
|
|
383
417
|
async destroy() {
|
|
384
418
|
if (this.workerPool) {
|
|
385
419
|
await this.workerPool.destroy();
|
package/src/compiler/three.js
CHANGED
|
@@ -8,8 +8,6 @@ import {
|
|
|
8
8
|
Group,
|
|
9
9
|
sRGBEncoding,
|
|
10
10
|
} from "three";
|
|
11
|
-
import * as tf from "@tensorflow/tfjs";
|
|
12
|
-
//import { CSS3DRenderer } from '../libs/CSS3DRenderer.js';
|
|
13
11
|
import { CSS3DRenderer } from "three/addons/renderers/CSS3DRenderer.js";
|
|
14
12
|
import { Controller } from "./controller.js";
|
|
15
13
|
import { UI } from "../ui/ui.js";
|
|
@@ -362,5 +360,3 @@ if (!window.MINDAR.IMAGE) {
|
|
|
362
360
|
}
|
|
363
361
|
|
|
364
362
|
window.MINDAR.IMAGE.MindARThree = MindARThree;
|
|
365
|
-
//window.MINDAR.IMAGE.THREE = THREE;
|
|
366
|
-
window.MINDAR.IMAGE.tf = tf;
|