@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.
Files changed (125) hide show
  1. package/dist/compiler/controller.d.ts +15 -22
  2. package/dist/compiler/controller.js +73 -92
  3. package/dist/compiler/detector/crop-detector.d.ts +20 -51
  4. package/dist/compiler/detector/crop-detector.js +21 -15
  5. package/dist/compiler/input-loader.d.ts +15 -17
  6. package/dist/compiler/input-loader.js +58 -76
  7. package/dist/compiler/matching/hamming-distance.js +4 -4
  8. package/dist/compiler/matching/matcher.js +2 -2
  9. package/dist/compiler/matching/matching.d.ts +2 -16
  10. package/dist/compiler/matching/matching.js +72 -60
  11. package/dist/compiler/offline-compiler.d.ts +14 -65
  12. package/dist/compiler/offline-compiler.js +86 -55
  13. package/dist/compiler/three.js +0 -4
  14. package/dist/compiler/tracker/tracker.d.ts +26 -12
  15. package/dist/compiler/tracker/tracker.js +158 -259
  16. package/dist/compiler/utils/worker-pool.d.ts +2 -1
  17. package/dist/compiler/utils/worker-pool.js +4 -8
  18. package/package.json +1 -1
  19. package/src/compiler/controller.js +71 -93
  20. package/src/compiler/detector/crop-detector.js +26 -15
  21. package/src/compiler/input-loader.js +62 -88
  22. package/src/compiler/matching/hamming-distance.js +4 -4
  23. package/src/compiler/matching/hough.js +1 -1
  24. package/src/compiler/matching/matcher.js +2 -2
  25. package/src/compiler/matching/matching.js +80 -72
  26. package/src/compiler/offline-compiler.js +92 -58
  27. package/src/compiler/three.js +0 -4
  28. package/src/compiler/tracker/tracker.js +183 -283
  29. package/src/compiler/utils/worker-pool.js +4 -8
  30. package/dist/compiler/compiler-base.d.ts +0 -8
  31. package/dist/compiler/compiler-base.js +0 -179
  32. package/dist/compiler/compiler.d.ts +0 -9
  33. package/dist/compiler/compiler.js +0 -24
  34. package/dist/compiler/compiler.worker.d.ts +0 -1
  35. package/dist/compiler/compiler.worker.js +0 -28
  36. package/dist/compiler/detector/detector.d.ts +0 -97
  37. package/dist/compiler/detector/detector.js +0 -1042
  38. package/dist/compiler/detector/kernels/cpu/binomialFilter.d.ts +0 -6
  39. package/dist/compiler/detector/kernels/cpu/binomialFilter.js +0 -50
  40. package/dist/compiler/detector/kernels/cpu/buildExtremas.d.ts +0 -6
  41. package/dist/compiler/detector/kernels/cpu/buildExtremas.js +0 -89
  42. package/dist/compiler/detector/kernels/cpu/computeExtremaAngles.d.ts +0 -7
  43. package/dist/compiler/detector/kernels/cpu/computeExtremaAngles.js +0 -79
  44. package/dist/compiler/detector/kernels/cpu/computeExtremaFreak.d.ts +0 -6
  45. package/dist/compiler/detector/kernels/cpu/computeExtremaFreak.js +0 -68
  46. package/dist/compiler/detector/kernels/cpu/computeFreakDescriptors.d.ts +0 -6
  47. package/dist/compiler/detector/kernels/cpu/computeFreakDescriptors.js +0 -57
  48. package/dist/compiler/detector/kernels/cpu/computeLocalization.d.ts +0 -6
  49. package/dist/compiler/detector/kernels/cpu/computeLocalization.js +0 -50
  50. package/dist/compiler/detector/kernels/cpu/computeOrientationHistograms.d.ts +0 -6
  51. package/dist/compiler/detector/kernels/cpu/computeOrientationHistograms.js +0 -100
  52. package/dist/compiler/detector/kernels/cpu/downsampleBilinear.d.ts +0 -6
  53. package/dist/compiler/detector/kernels/cpu/downsampleBilinear.js +0 -29
  54. package/dist/compiler/detector/kernels/cpu/extremaReduction.d.ts +0 -6
  55. package/dist/compiler/detector/kernels/cpu/extremaReduction.js +0 -50
  56. package/dist/compiler/detector/kernels/cpu/fakeShader.d.ts +0 -20
  57. package/dist/compiler/detector/kernels/cpu/fakeShader.js +0 -80
  58. package/dist/compiler/detector/kernels/cpu/index.d.ts +0 -1
  59. package/dist/compiler/detector/kernels/cpu/index.js +0 -25
  60. package/dist/compiler/detector/kernels/cpu/prune.d.ts +0 -7
  61. package/dist/compiler/detector/kernels/cpu/prune.js +0 -62
  62. package/dist/compiler/detector/kernels/cpu/smoothHistograms.d.ts +0 -6
  63. package/dist/compiler/detector/kernels/cpu/smoothHistograms.js +0 -47
  64. package/dist/compiler/detector/kernels/cpu/upsampleBilinear.d.ts +0 -6
  65. package/dist/compiler/detector/kernels/cpu/upsampleBilinear.js +0 -43
  66. package/dist/compiler/detector/kernels/index.d.ts +0 -1
  67. package/dist/compiler/detector/kernels/index.js +0 -2
  68. package/dist/compiler/detector/kernels/webgl/binomialFilter.d.ts +0 -6
  69. package/dist/compiler/detector/kernels/webgl/binomialFilter.js +0 -67
  70. package/dist/compiler/detector/kernels/webgl/buildExtremas.d.ts +0 -6
  71. package/dist/compiler/detector/kernels/webgl/buildExtremas.js +0 -101
  72. package/dist/compiler/detector/kernels/webgl/computeExtremaAngles.d.ts +0 -6
  73. package/dist/compiler/detector/kernels/webgl/computeExtremaAngles.js +0 -78
  74. package/dist/compiler/detector/kernels/webgl/computeExtremaFreak.d.ts +0 -6
  75. package/dist/compiler/detector/kernels/webgl/computeExtremaFreak.js +0 -86
  76. package/dist/compiler/detector/kernels/webgl/computeFreakDescriptors.d.ts +0 -6
  77. package/dist/compiler/detector/kernels/webgl/computeFreakDescriptors.js +0 -52
  78. package/dist/compiler/detector/kernels/webgl/computeLocalization.d.ts +0 -6
  79. package/dist/compiler/detector/kernels/webgl/computeLocalization.js +0 -58
  80. package/dist/compiler/detector/kernels/webgl/computeOrientationHistograms.d.ts +0 -6
  81. package/dist/compiler/detector/kernels/webgl/computeOrientationHistograms.js +0 -116
  82. package/dist/compiler/detector/kernels/webgl/downsampleBilinear.d.ts +0 -6
  83. package/dist/compiler/detector/kernels/webgl/downsampleBilinear.js +0 -46
  84. package/dist/compiler/detector/kernels/webgl/extremaReduction.d.ts +0 -6
  85. package/dist/compiler/detector/kernels/webgl/extremaReduction.js +0 -48
  86. package/dist/compiler/detector/kernels/webgl/index.d.ts +0 -1
  87. package/dist/compiler/detector/kernels/webgl/index.js +0 -25
  88. package/dist/compiler/detector/kernels/webgl/smoothHistograms.d.ts +0 -6
  89. package/dist/compiler/detector/kernels/webgl/smoothHistograms.js +0 -49
  90. package/dist/compiler/detector/kernels/webgl/upsampleBilinear.d.ts +0 -6
  91. package/dist/compiler/detector/kernels/webgl/upsampleBilinear.js +0 -56
  92. package/dist/compiler/tensorflow-setup.d.ts +0 -6
  93. package/dist/compiler/tensorflow-setup.js +0 -99
  94. package/src/compiler/compiler-base.js +0 -210
  95. package/src/compiler/compiler.js +0 -25
  96. package/src/compiler/compiler.worker.js +0 -30
  97. package/src/compiler/detector/detector.js +0 -1119
  98. package/src/compiler/detector/kernels/cpu/binomialFilter.js +0 -58
  99. package/src/compiler/detector/kernels/cpu/buildExtremas.js +0 -108
  100. package/src/compiler/detector/kernels/cpu/computeExtremaAngles.js +0 -91
  101. package/src/compiler/detector/kernels/cpu/computeExtremaFreak.js +0 -92
  102. package/src/compiler/detector/kernels/cpu/computeFreakDescriptors.js +0 -68
  103. package/src/compiler/detector/kernels/cpu/computeLocalization.js +0 -67
  104. package/src/compiler/detector/kernels/cpu/computeOrientationHistograms.js +0 -124
  105. package/src/compiler/detector/kernels/cpu/downsampleBilinear.js +0 -33
  106. package/src/compiler/detector/kernels/cpu/extremaReduction.js +0 -53
  107. package/src/compiler/detector/kernels/cpu/fakeShader.js +0 -88
  108. package/src/compiler/detector/kernels/cpu/index.js +0 -26
  109. package/src/compiler/detector/kernels/cpu/prune.js +0 -78
  110. package/src/compiler/detector/kernels/cpu/smoothHistograms.js +0 -57
  111. package/src/compiler/detector/kernels/cpu/upsampleBilinear.js +0 -51
  112. package/src/compiler/detector/kernels/index.js +0 -2
  113. package/src/compiler/detector/kernels/webgl/binomialFilter.js +0 -72
  114. package/src/compiler/detector/kernels/webgl/buildExtremas.js +0 -109
  115. package/src/compiler/detector/kernels/webgl/computeExtremaAngles.js +0 -82
  116. package/src/compiler/detector/kernels/webgl/computeExtremaFreak.js +0 -105
  117. package/src/compiler/detector/kernels/webgl/computeFreakDescriptors.js +0 -56
  118. package/src/compiler/detector/kernels/webgl/computeLocalization.js +0 -70
  119. package/src/compiler/detector/kernels/webgl/computeOrientationHistograms.js +0 -129
  120. package/src/compiler/detector/kernels/webgl/downsampleBilinear.js +0 -50
  121. package/src/compiler/detector/kernels/webgl/extremaReduction.js +0 -50
  122. package/src/compiler/detector/kernels/webgl/index.js +0 -26
  123. package/src/compiler/detector/kernels/webgl/smoothHistograms.js +0 -53
  124. package/src/compiler/detector/kernels/webgl/upsampleBilinear.js +0 -62
  125. 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
- for (let j = 0; j < querypoints.length; j++) {
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 ? keyframe.max : keyframe.min;
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
- // Access descriptor directly from binary buffer (Zero-copy)
48
- const keypointDescriptor = col.d.subarray(idx * 84, (idx + 1) * 84);
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 || (1.0 * bestD1) / bestD2 < HAMMING_THRESHOLD)
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, // Protocol V3 uses .w, .h
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
- for (let j = 0; j < querypoints.length; j++) {
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 mapquerypoint = multiplyPointHomographyInhomogenous([querypoint.x, querypoint.y], HInv);
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 ? keyframe.max : keyframe.min;
131
+ const col = querypoint.maxima ? kmax : kmin;
127
132
  if (!col) continue;
128
133
 
129
- for (let k = 0; k < col.x.length; k++) {
130
- const dx = col.x[k] - mapquerypoint[0];
131
- const dy = col.y[k] - mapquerypoint[1];
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 keypointDescriptor = col.d.subarray(k * 84, (k + 1) * 84);
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 || (1.0 * bestD1) / bestD2 < HAMMING_THRESHOLD)
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 distances = [];
213
- for (let i = 0; i < childrenOrIndices.length; i++) {
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.subarray(cIdx * 84, (cIdx + 1) * 84),
219
- v2: querypoint.descriptors,
223
+ v1: descriptors,
224
+ v1Offset: cIdx * 84,
225
+ v2: qDesc,
220
226
  });
221
- distances.push(d);
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 < childrenOrIndices.length; i++) {
230
- if (distances[i] !== minD) {
231
- queue.push({ node: childrenOrIndices[i], d: distances[i] });
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 += 1;
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 querypoint = matches[i].querypoint;
255
- const keypoint = matches[i].keypoint;
256
- const mp = multiplyPointHomographyInhomogenous([keypoint.x, keypoint.y], H);
257
- const d2 =
258
- (mp[0] - querypoint.x) * (mp[0] - querypoint.x) +
259
- (mp[1] - querypoint.y) * (mp[1] - querypoint.y);
260
- if (d2 <= threshold2) {
261
- goodMatches.push(matches[i]);
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
- const [os, path, url, workerModule] = await Promise.all([
50
- import("os"),
51
- import("path"),
52
- import("url"),
53
- import("./utils/worker-pool.js")
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
- this.workerPool = new workerModule.WorkerPool(workerPath, numWorkers);
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
- // Fase 1: Matching (50%)
113
- console.time("⏱️ Fase Matching");
114
- const matchingDataList = await this._compileMatch(targetImages, (percent) => {
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
- // Fase 2: Tracking (50%)
120
- console.time("⏱️ Fase Tracking");
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
- // Compilar resultado
127
- this.data = targetImages.map((targetImage, i) => ({
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
- const results = [];
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
- // Procesar secuencialmente para evitar overhead de workers
148
- // (los workers son útiles para muchas imágenes, pero añaden latencia)
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
- const results = [];
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
- // Ya no de-columnarizamos aquí. Los motores (Tracker/Matcher)
332
- // ahora están optimizados para leer directamente de los buffers.
333
- this.data = content.dataList;
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();
@@ -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;