@srsergio/taptapp-ar 1.0.38 → 1.0.41
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 +3 -8
- package/dist/compiler/controller.js +10 -38
- package/dist/compiler/tracker/tracker.d.ts +0 -8
- package/dist/compiler/tracker/tracker.js +10 -29
- package/package.json +1 -1
- package/src/compiler/controller.js +10 -35
- package/src/compiler/tracker/tracker.js +11 -29
|
@@ -65,16 +65,12 @@ export class Controller {
|
|
|
65
65
|
dummyRun(input: any): void;
|
|
66
66
|
getProjectionMatrix(): number[];
|
|
67
67
|
getRotatedZ90Matrix(m: any): any[];
|
|
68
|
-
getWorldMatrix(modelViewTransform: any, targetIndex: any): any[]
|
|
68
|
+
getWorldMatrix(modelViewTransform: any, targetIndex: any): any[];
|
|
69
69
|
_detectAndMatch(inputData: any, targetIndexes: any): Promise<{
|
|
70
70
|
targetIndex: any;
|
|
71
71
|
modelViewTransform: any;
|
|
72
72
|
}>;
|
|
73
|
-
_trackAndUpdate(inputData: any, lastModelViewTransform: any, targetIndex: any): Promise<
|
|
74
|
-
modelViewTransform: any;
|
|
75
|
-
inliers: number;
|
|
76
|
-
octaveIndex: number;
|
|
77
|
-
} | null>;
|
|
73
|
+
_trackAndUpdate(inputData: any, lastModelViewTransform: any, targetIndex: any): Promise<any>;
|
|
78
74
|
processVideo(input: any): void;
|
|
79
75
|
stopProcessVideo(): void;
|
|
80
76
|
detect(input: any): Promise<{
|
|
@@ -102,7 +98,6 @@ export class Controller {
|
|
|
102
98
|
x: number;
|
|
103
99
|
y: number;
|
|
104
100
|
}[];
|
|
105
|
-
octaveIndex: number;
|
|
106
101
|
debugExtra: {};
|
|
107
102
|
}>;
|
|
108
103
|
trackUpdate(modelViewTransform: any, trackFeatures: any): Promise<any>;
|
|
@@ -129,7 +124,7 @@ export class Controller {
|
|
|
129
124
|
_workerTrackUpdate(modelViewTransform: any, trackingFeatures: any): Promise<any>;
|
|
130
125
|
workerTrackDone: ((data: any) => void) | undefined;
|
|
131
126
|
_trackUpdateOnMainThread(modelViewTransform: any, trackingFeatures: any): Promise<never[][] | null>;
|
|
132
|
-
_glModelViewMatrix(modelViewTransform: any, targetIndex: any): any[]
|
|
127
|
+
_glModelViewMatrix(modelViewTransform: any, targetIndex: any): any[];
|
|
133
128
|
_glProjectionMatrix({ projectionTransform, width, height, near, far }: {
|
|
134
129
|
projectionTransform: any;
|
|
135
130
|
width: any;
|
|
@@ -181,18 +181,14 @@ class Controller {
|
|
|
181
181
|
return { targetIndex: matchedTargetIndex, modelViewTransform };
|
|
182
182
|
}
|
|
183
183
|
async _trackAndUpdate(inputData, lastModelViewTransform, targetIndex) {
|
|
184
|
-
const
|
|
185
|
-
if (
|
|
184
|
+
const { worldCoords, screenCoords } = this.tracker.track(inputData, lastModelViewTransform, targetIndex);
|
|
185
|
+
if (worldCoords.length < 6)
|
|
186
186
|
return null; // Umbral de puntos mínimos para mantener el seguimiento
|
|
187
187
|
const modelViewTransform = await this._workerTrackUpdate(lastModelViewTransform, {
|
|
188
|
-
worldCoords
|
|
189
|
-
screenCoords
|
|
188
|
+
worldCoords,
|
|
189
|
+
screenCoords,
|
|
190
190
|
});
|
|
191
|
-
return
|
|
192
|
-
modelViewTransform,
|
|
193
|
-
inliers: result.worldCoords.length,
|
|
194
|
-
octaveIndex: result.octaveIndex
|
|
195
|
-
};
|
|
191
|
+
return modelViewTransform;
|
|
196
192
|
}
|
|
197
193
|
processVideo(input) {
|
|
198
194
|
if (this.processingVideo)
|
|
@@ -206,7 +202,6 @@ class Controller {
|
|
|
206
202
|
currentModelViewTransform: null,
|
|
207
203
|
trackCount: 0,
|
|
208
204
|
trackMiss: 0,
|
|
209
|
-
stabilityCount: 0, // Nuevo: Contador para Live Adaptation
|
|
210
205
|
filter: new OneEuroFilter({ minCutOff: this.filterMinCF, beta: this.filterBeta }),
|
|
211
206
|
});
|
|
212
207
|
}
|
|
@@ -219,22 +214,18 @@ class Controller {
|
|
|
219
214
|
return acc + (!!s.isTracking ? 1 : 0);
|
|
220
215
|
}, 0);
|
|
221
216
|
// detect and match only if less then maxTrack
|
|
222
|
-
// BUG FIX: Only match if we are NOT in a "ghosting" period for a target
|
|
223
|
-
// to prevent the "found but immediately lost" loop that keeps opacity at 1.
|
|
224
217
|
if (nTracking < this.maxTrack) {
|
|
225
218
|
const matchingIndexes = [];
|
|
226
219
|
for (let i = 0; i < this.trackingStates.length; i++) {
|
|
227
220
|
const trackingState = this.trackingStates[i];
|
|
228
221
|
if (trackingState.isTracking === true)
|
|
229
222
|
continue;
|
|
230
|
-
if (trackingState.showing === true)
|
|
231
|
-
continue; // Don't try to re-detect if we are still buffers-showing the last position
|
|
232
223
|
if (this.interestedTargetIndex !== -1 && this.interestedTargetIndex !== i)
|
|
233
224
|
continue;
|
|
234
225
|
matchingIndexes.push(i);
|
|
235
226
|
}
|
|
236
227
|
const { targetIndex: matchedTargetIndex, modelViewTransform } = await this._detectAndMatch(inputData, matchingIndexes);
|
|
237
|
-
if (matchedTargetIndex !== -1
|
|
228
|
+
if (matchedTargetIndex !== -1) {
|
|
238
229
|
this.trackingStates[matchedTargetIndex].isTracking = true;
|
|
239
230
|
this.trackingStates[matchedTargetIndex].currentModelViewTransform = modelViewTransform;
|
|
240
231
|
}
|
|
@@ -243,29 +234,12 @@ class Controller {
|
|
|
243
234
|
for (let i = 0; i < this.trackingStates.length; i++) {
|
|
244
235
|
const trackingState = this.trackingStates[i];
|
|
245
236
|
if (trackingState.isTracking) {
|
|
246
|
-
let
|
|
247
|
-
if (
|
|
237
|
+
let modelViewTransform = await this._trackAndUpdate(inputData, trackingState.currentModelViewTransform, i);
|
|
238
|
+
if (modelViewTransform === null) {
|
|
248
239
|
trackingState.isTracking = false;
|
|
249
|
-
trackingState.stabilityCount = 0;
|
|
250
240
|
}
|
|
251
241
|
else {
|
|
252
|
-
trackingState.currentModelViewTransform =
|
|
253
|
-
// --- LIVE MODEL ADAPTATION LOGIC ---
|
|
254
|
-
// Si el tracking es muy sólido (muchos inliers) y estable, refinamos el modelo
|
|
255
|
-
// Requisito: > 35 inliers (muy exigente) para evitar polución por ruido
|
|
256
|
-
if (result.inliers > 35) {
|
|
257
|
-
trackingState.stabilityCount++;
|
|
258
|
-
if (trackingState.stabilityCount > 30) { // 30 frames (~1s) de estabilidad absoluta
|
|
259
|
-
this.tracker.applyLiveFeedback(i, result.octaveIndex, 0.05); // Menor alpha (5%) para ser más conservador
|
|
260
|
-
if (this.debugMode)
|
|
261
|
-
console.log(`✨ Live Reification: Target ${i} (Octave ${result.octaveIndex}) updated.`);
|
|
262
|
-
trackingState.stabilityCount = 0;
|
|
263
|
-
}
|
|
264
|
-
}
|
|
265
|
-
else {
|
|
266
|
-
trackingState.stabilityCount = Math.max(0, trackingState.stabilityCount - 1);
|
|
267
|
-
}
|
|
268
|
-
// -----------------------------------
|
|
242
|
+
trackingState.currentModelViewTransform = modelViewTransform;
|
|
269
243
|
}
|
|
270
244
|
}
|
|
271
245
|
// if not showing, then show it once it reaches warmup number of frames
|
|
@@ -297,7 +271,7 @@ class Controller {
|
|
|
297
271
|
}
|
|
298
272
|
}
|
|
299
273
|
// if showing, then call onUpdate, with world matrix
|
|
300
|
-
if (trackingState.showing
|
|
274
|
+
if (trackingState.showing) {
|
|
301
275
|
const worldMatrix = this._glModelViewMatrix(trackingState.currentModelViewTransform, i);
|
|
302
276
|
trackingState.trackingMatrix = trackingState.filter.filter(Date.now(), worldMatrix);
|
|
303
277
|
let clone = [];
|
|
@@ -438,8 +412,6 @@ class Controller {
|
|
|
438
412
|
return finalModelViewTransform;
|
|
439
413
|
}
|
|
440
414
|
_glModelViewMatrix(modelViewTransform, targetIndex) {
|
|
441
|
-
if (!modelViewTransform)
|
|
442
|
-
return null;
|
|
443
415
|
const height = this.markerDimensions[targetIndex][1];
|
|
444
416
|
const openGLWorldMatrix = [
|
|
445
417
|
modelViewTransform[0][0],
|
|
@@ -20,7 +20,6 @@ export class Tracker {
|
|
|
20
20
|
x: number;
|
|
21
21
|
y: number;
|
|
22
22
|
}[];
|
|
23
|
-
octaveIndex: number;
|
|
24
23
|
debugExtra: {};
|
|
25
24
|
};
|
|
26
25
|
/**
|
|
@@ -34,11 +33,4 @@ export class Tracker {
|
|
|
34
33
|
* Pure JS implementation of Bilinear Warping
|
|
35
34
|
*/
|
|
36
35
|
_computeProjection(M: any, inputData: any, prebuilt: any): void;
|
|
37
|
-
/**
|
|
38
|
-
* Refines the target data (Living Mind Map) using actual camera feedback
|
|
39
|
-
* @param {number} targetIndex
|
|
40
|
-
* @param {number} octaveIndex
|
|
41
|
-
* @param {number} alpha - Blending factor (e.g. 0.1 for 10% new data)
|
|
42
|
-
*/
|
|
43
|
-
applyLiveFeedback(targetIndex: number, octaveIndex: number, alpha: number): void;
|
|
44
36
|
}
|
|
@@ -87,7 +87,16 @@ class Tracker {
|
|
|
87
87
|
});
|
|
88
88
|
}
|
|
89
89
|
}
|
|
90
|
-
|
|
90
|
+
if (this.debugMode) {
|
|
91
|
+
debugExtra = {
|
|
92
|
+
octaveIndex,
|
|
93
|
+
projectedImage: Array.from(projectedImage),
|
|
94
|
+
matchingPoints,
|
|
95
|
+
goodTrack,
|
|
96
|
+
trackedPoints: screenCoords,
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
return { worldCoords, screenCoords, debugExtra };
|
|
91
100
|
}
|
|
92
101
|
/**
|
|
93
102
|
* Pure JS implementation of NCC matching
|
|
@@ -223,33 +232,5 @@ class Tracker {
|
|
|
223
232
|
}
|
|
224
233
|
}
|
|
225
234
|
}
|
|
226
|
-
/**
|
|
227
|
-
* Refines the target data (Living Mind Map) using actual camera feedback
|
|
228
|
-
* @param {number} targetIndex
|
|
229
|
-
* @param {number} octaveIndex
|
|
230
|
-
* @param {number} alpha - Blending factor (e.g. 0.1 for 10% new data)
|
|
231
|
-
*/
|
|
232
|
-
applyLiveFeedback(targetIndex, octaveIndex, alpha) {
|
|
233
|
-
if (targetIndex === undefined || octaveIndex === undefined)
|
|
234
|
-
return;
|
|
235
|
-
const targetPrebuilts = this.prebuiltData[targetIndex];
|
|
236
|
-
if (!targetPrebuilts)
|
|
237
|
-
return;
|
|
238
|
-
const prebuilt = targetPrebuilts[octaveIndex];
|
|
239
|
-
if (!prebuilt || !prebuilt.projectedImage || !prebuilt.data)
|
|
240
|
-
return;
|
|
241
|
-
const markerPixels = prebuilt.data;
|
|
242
|
-
const projectedPixels = prebuilt.projectedImage;
|
|
243
|
-
const count = markerPixels.length;
|
|
244
|
-
// Blend the projected (camera-sourced) pixels into the marker reference data
|
|
245
|
-
// This allows the NCC matching to adapt to real-world lighting and print quality
|
|
246
|
-
for (let i = 0; i < count; i++) {
|
|
247
|
-
const val = projectedPixels[i];
|
|
248
|
-
if (isNaN(val))
|
|
249
|
-
continue; // Don't pollute with NaN
|
|
250
|
-
// Simple linear blend
|
|
251
|
-
markerPixels[i] = (1 - alpha) * markerPixels[i] + alpha * val;
|
|
252
|
-
}
|
|
253
|
-
}
|
|
254
235
|
}
|
|
255
236
|
export { Tracker };
|
package/package.json
CHANGED
|
@@ -226,21 +226,17 @@ class Controller {
|
|
|
226
226
|
return { targetIndex: matchedTargetIndex, modelViewTransform };
|
|
227
227
|
}
|
|
228
228
|
async _trackAndUpdate(inputData, lastModelViewTransform, targetIndex) {
|
|
229
|
-
const
|
|
229
|
+
const { worldCoords, screenCoords } = this.tracker.track(
|
|
230
230
|
inputData,
|
|
231
231
|
lastModelViewTransform,
|
|
232
232
|
targetIndex,
|
|
233
233
|
);
|
|
234
|
-
if (
|
|
234
|
+
if (worldCoords.length < 6) return null; // Umbral de puntos mínimos para mantener el seguimiento
|
|
235
235
|
const modelViewTransform = await this._workerTrackUpdate(lastModelViewTransform, {
|
|
236
|
-
worldCoords
|
|
237
|
-
screenCoords
|
|
236
|
+
worldCoords,
|
|
237
|
+
screenCoords,
|
|
238
238
|
});
|
|
239
|
-
return
|
|
240
|
-
modelViewTransform,
|
|
241
|
-
inliers: result.worldCoords.length,
|
|
242
|
-
octaveIndex: result.octaveIndex
|
|
243
|
-
};
|
|
239
|
+
return modelViewTransform;
|
|
244
240
|
}
|
|
245
241
|
|
|
246
242
|
processVideo(input) {
|
|
@@ -256,7 +252,6 @@ class Controller {
|
|
|
256
252
|
currentModelViewTransform: null,
|
|
257
253
|
trackCount: 0,
|
|
258
254
|
trackMiss: 0,
|
|
259
|
-
stabilityCount: 0, // Nuevo: Contador para Live Adaptation
|
|
260
255
|
filter: new OneEuroFilter({ minCutOff: this.filterMinCF, beta: this.filterBeta }),
|
|
261
256
|
});
|
|
262
257
|
}
|
|
@@ -272,14 +267,11 @@ class Controller {
|
|
|
272
267
|
}, 0);
|
|
273
268
|
|
|
274
269
|
// detect and match only if less then maxTrack
|
|
275
|
-
// BUG FIX: Only match if we are NOT in a "ghosting" period for a target
|
|
276
|
-
// to prevent the "found but immediately lost" loop that keeps opacity at 1.
|
|
277
270
|
if (nTracking < this.maxTrack) {
|
|
278
271
|
const matchingIndexes = [];
|
|
279
272
|
for (let i = 0; i < this.trackingStates.length; i++) {
|
|
280
273
|
const trackingState = this.trackingStates[i];
|
|
281
274
|
if (trackingState.isTracking === true) continue;
|
|
282
|
-
if (trackingState.showing === true) continue; // Don't try to re-detect if we are still buffers-showing the last position
|
|
283
275
|
if (this.interestedTargetIndex !== -1 && this.interestedTargetIndex !== i) continue;
|
|
284
276
|
|
|
285
277
|
matchingIndexes.push(i);
|
|
@@ -288,7 +280,7 @@ class Controller {
|
|
|
288
280
|
const { targetIndex: matchedTargetIndex, modelViewTransform } =
|
|
289
281
|
await this._detectAndMatch(inputData, matchingIndexes);
|
|
290
282
|
|
|
291
|
-
if (matchedTargetIndex !== -1
|
|
283
|
+
if (matchedTargetIndex !== -1) {
|
|
292
284
|
this.trackingStates[matchedTargetIndex].isTracking = true;
|
|
293
285
|
this.trackingStates[matchedTargetIndex].currentModelViewTransform = modelViewTransform;
|
|
294
286
|
}
|
|
@@ -299,31 +291,15 @@ class Controller {
|
|
|
299
291
|
const trackingState = this.trackingStates[i];
|
|
300
292
|
|
|
301
293
|
if (trackingState.isTracking) {
|
|
302
|
-
let
|
|
294
|
+
let modelViewTransform = await this._trackAndUpdate(
|
|
303
295
|
inputData,
|
|
304
296
|
trackingState.currentModelViewTransform,
|
|
305
297
|
i,
|
|
306
298
|
);
|
|
307
|
-
if (
|
|
299
|
+
if (modelViewTransform === null) {
|
|
308
300
|
trackingState.isTracking = false;
|
|
309
|
-
trackingState.stabilityCount = 0;
|
|
310
301
|
} else {
|
|
311
|
-
trackingState.currentModelViewTransform =
|
|
312
|
-
|
|
313
|
-
// --- LIVE MODEL ADAPTATION LOGIC ---
|
|
314
|
-
// Si el tracking es muy sólido (muchos inliers) y estable, refinamos el modelo
|
|
315
|
-
// Requisito: > 35 inliers (muy exigente) para evitar polución por ruido
|
|
316
|
-
if (result.inliers > 35) {
|
|
317
|
-
trackingState.stabilityCount++;
|
|
318
|
-
if (trackingState.stabilityCount > 30) { // 30 frames (~1s) de estabilidad absoluta
|
|
319
|
-
this.tracker.applyLiveFeedback(i, result.octaveIndex, 0.05); // Menor alpha (5%) para ser más conservador
|
|
320
|
-
if (this.debugMode) console.log(`✨ Live Reification: Target ${i} (Octave ${result.octaveIndex}) updated.`);
|
|
321
|
-
trackingState.stabilityCount = 0;
|
|
322
|
-
}
|
|
323
|
-
} else {
|
|
324
|
-
trackingState.stabilityCount = Math.max(0, trackingState.stabilityCount - 1);
|
|
325
|
-
}
|
|
326
|
-
// -----------------------------------
|
|
302
|
+
trackingState.currentModelViewTransform = modelViewTransform;
|
|
327
303
|
}
|
|
328
304
|
}
|
|
329
305
|
|
|
@@ -358,7 +334,7 @@ class Controller {
|
|
|
358
334
|
}
|
|
359
335
|
|
|
360
336
|
// if showing, then call onUpdate, with world matrix
|
|
361
|
-
if (trackingState.showing
|
|
337
|
+
if (trackingState.showing) {
|
|
362
338
|
const worldMatrix = this._glModelViewMatrix(trackingState.currentModelViewTransform, i);
|
|
363
339
|
trackingState.trackingMatrix = trackingState.filter.filter(Date.now(), worldMatrix);
|
|
364
340
|
|
|
@@ -525,7 +501,6 @@ class Controller {
|
|
|
525
501
|
}
|
|
526
502
|
|
|
527
503
|
_glModelViewMatrix(modelViewTransform, targetIndex) {
|
|
528
|
-
if (!modelViewTransform) return null;
|
|
529
504
|
const height = this.markerDimensions[targetIndex][1];
|
|
530
505
|
|
|
531
506
|
const openGLWorldMatrix = [
|
|
@@ -127,7 +127,17 @@ class Tracker {
|
|
|
127
127
|
}
|
|
128
128
|
}
|
|
129
129
|
|
|
130
|
-
|
|
130
|
+
if (this.debugMode) {
|
|
131
|
+
debugExtra = {
|
|
132
|
+
octaveIndex,
|
|
133
|
+
projectedImage: Array.from(projectedImage),
|
|
134
|
+
matchingPoints,
|
|
135
|
+
goodTrack,
|
|
136
|
+
trackedPoints: screenCoords,
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
return { worldCoords, screenCoords, debugExtra };
|
|
131
141
|
}
|
|
132
142
|
|
|
133
143
|
/**
|
|
@@ -290,34 +300,6 @@ class Tracker {
|
|
|
290
300
|
}
|
|
291
301
|
}
|
|
292
302
|
}
|
|
293
|
-
|
|
294
|
-
/**
|
|
295
|
-
* Refines the target data (Living Mind Map) using actual camera feedback
|
|
296
|
-
* @param {number} targetIndex
|
|
297
|
-
* @param {number} octaveIndex
|
|
298
|
-
* @param {number} alpha - Blending factor (e.g. 0.1 for 10% new data)
|
|
299
|
-
*/
|
|
300
|
-
applyLiveFeedback(targetIndex, octaveIndex, alpha) {
|
|
301
|
-
if (targetIndex === undefined || octaveIndex === undefined) return;
|
|
302
|
-
const targetPrebuilts = this.prebuiltData[targetIndex];
|
|
303
|
-
if (!targetPrebuilts) return;
|
|
304
|
-
|
|
305
|
-
const prebuilt = targetPrebuilts[octaveIndex];
|
|
306
|
-
if (!prebuilt || !prebuilt.projectedImage || !prebuilt.data) return;
|
|
307
|
-
|
|
308
|
-
const markerPixels = prebuilt.data;
|
|
309
|
-
const projectedPixels = prebuilt.projectedImage;
|
|
310
|
-
const count = markerPixels.length;
|
|
311
|
-
|
|
312
|
-
// Blend the projected (camera-sourced) pixels into the marker reference data
|
|
313
|
-
// This allows the NCC matching to adapt to real-world lighting and print quality
|
|
314
|
-
for (let i = 0; i < count; i++) {
|
|
315
|
-
const val = projectedPixels[i];
|
|
316
|
-
if (isNaN(val)) continue; // Don't pollute with NaN
|
|
317
|
-
// Simple linear blend
|
|
318
|
-
markerPixels[i] = (1 - alpha) * markerPixels[i] + alpha * val;
|
|
319
|
-
}
|
|
320
|
-
}
|
|
321
303
|
}
|
|
322
304
|
|
|
323
305
|
export { Tracker };
|