@srsergio/taptapp-ar 1.0.92 → 1.0.94

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 (52) hide show
  1. package/README.md +16 -14
  2. package/dist/compiler/offline-compiler.d.ts +3 -3
  3. package/dist/compiler/offline-compiler.js +50 -33
  4. package/dist/core/constants.d.ts +2 -0
  5. package/dist/core/constants.js +4 -1
  6. package/dist/core/detector/detector-lite.d.ts +6 -5
  7. package/dist/core/detector/detector-lite.js +46 -16
  8. package/dist/core/image-list.d.ts +24 -6
  9. package/dist/core/image-list.js +4 -4
  10. package/dist/core/matching/matcher.d.ts +1 -1
  11. package/dist/core/matching/matcher.js +7 -4
  12. package/dist/core/matching/matching.d.ts +2 -1
  13. package/dist/core/matching/matching.js +43 -11
  14. package/dist/core/perception/bio-inspired-engine.d.ts +130 -0
  15. package/dist/core/perception/bio-inspired-engine.js +232 -0
  16. package/dist/core/perception/foveal-attention.d.ts +142 -0
  17. package/dist/core/perception/foveal-attention.js +280 -0
  18. package/dist/core/perception/index.d.ts +6 -0
  19. package/dist/core/perception/index.js +17 -0
  20. package/dist/core/perception/predictive-coding.d.ts +92 -0
  21. package/dist/core/perception/predictive-coding.js +278 -0
  22. package/dist/core/perception/saccadic-controller.d.ts +126 -0
  23. package/dist/core/perception/saccadic-controller.js +269 -0
  24. package/dist/core/perception/saliency-map.d.ts +74 -0
  25. package/dist/core/perception/saliency-map.js +254 -0
  26. package/dist/core/perception/scale-orchestrator.d.ts +28 -0
  27. package/dist/core/perception/scale-orchestrator.js +68 -0
  28. package/dist/core/protocol.d.ts +14 -1
  29. package/dist/core/protocol.js +33 -1
  30. package/dist/runtime/bio-inspired-controller.d.ts +135 -0
  31. package/dist/runtime/bio-inspired-controller.js +358 -0
  32. package/dist/runtime/controller.d.ts +11 -2
  33. package/dist/runtime/controller.js +20 -8
  34. package/dist/runtime/controller.worker.js +2 -2
  35. package/package.json +1 -1
  36. package/src/compiler/offline-compiler.ts +56 -36
  37. package/src/core/constants.ts +5 -1
  38. package/src/core/detector/detector-lite.js +46 -16
  39. package/src/core/image-list.js +4 -4
  40. package/src/core/matching/matcher.js +8 -4
  41. package/src/core/matching/matching.js +51 -12
  42. package/src/core/perception/bio-inspired-engine.js +275 -0
  43. package/src/core/perception/foveal-attention.js +306 -0
  44. package/src/core/perception/index.js +18 -0
  45. package/src/core/perception/predictive-coding.js +327 -0
  46. package/src/core/perception/saccadic-controller.js +303 -0
  47. package/src/core/perception/saliency-map.js +296 -0
  48. package/src/core/perception/scale-orchestrator.js +80 -0
  49. package/src/core/protocol.ts +38 -1
  50. package/src/runtime/bio-inspired-controller.ts +448 -0
  51. package/src/runtime/controller.ts +22 -7
  52. package/src/runtime/controller.worker.js +2 -1
@@ -0,0 +1,126 @@
1
+ /**
2
+ * A saccade target representing where attention should be directed
3
+ */
4
+ export type SaccadeTarget = {
5
+ /**
6
+ * - X coordinate
7
+ */
8
+ x: number;
9
+ /**
10
+ * - Y coordinate
11
+ */
12
+ y: number;
13
+ /**
14
+ * - Priority (0 = highest)
15
+ */
16
+ priority: number;
17
+ /**
18
+ * - Why this target was selected
19
+ */
20
+ reason: string;
21
+ /**
22
+ * - Saliency score at this location
23
+ */
24
+ saliency: number;
25
+ };
26
+ /**
27
+ * Saccadic Controller
28
+ *
29
+ * Mimics human eye saccades - rapid movements that redirect foveal attention
30
+ * to areas of interest. The human eye makes 3-4 saccades per second to
31
+ * build a complete picture of the visual scene.
32
+ *
33
+ * Strategy:
34
+ * 1. Compute saliency map to find "interesting" regions
35
+ * 2. Use tracking state to predict where features should be
36
+ * 3. Generate priority-ordered list of "glance" targets
37
+ * 4. Limit saccades per frame to balance coverage vs. efficiency
38
+ */
39
+ /**
40
+ * A saccade target representing where attention should be directed
41
+ * @typedef {Object} SaccadeTarget
42
+ * @property {number} x - X coordinate
43
+ * @property {number} y - Y coordinate
44
+ * @property {number} priority - Priority (0 = highest)
45
+ * @property {string} reason - Why this target was selected
46
+ * @property {number} saliency - Saliency score at this location
47
+ */
48
+ export class SaccadicController {
49
+ /**
50
+ * @param {number} width - Image width
51
+ * @param {number} height - Image height
52
+ * @param {Object} config - Configuration
53
+ */
54
+ constructor(width: number, height: number, config: Object);
55
+ width: number;
56
+ height: number;
57
+ config: Object;
58
+ recentTargets: any[];
59
+ inhibitionRadius: number;
60
+ velocityHistory: any[];
61
+ lastCenter: {
62
+ x: number;
63
+ y: number;
64
+ };
65
+ gridCells: {
66
+ x: number;
67
+ y: number;
68
+ index: number;
69
+ lastVisit: number;
70
+ }[];
71
+ lastVisitedCell: number;
72
+ lastSaccadeTime: number;
73
+ saccadeCount: number;
74
+ /**
75
+ * Build a grid for systematic coverage during tracking loss
76
+ * @private
77
+ */
78
+ private _buildCoverageGrid;
79
+ /**
80
+ * Compute saccade targets based on current state
81
+ *
82
+ * @param {Object} saliency - Saliency map result
83
+ * @param {Object} currentFovea - Current fovea center {x, y}
84
+ * @param {Object} trackingState - Current tracking state (optional)
85
+ * @returns {SaccadeTarget[]} Priority-ordered list of targets
86
+ */
87
+ computeTargets(saliency: Object, currentFovea: Object, trackingState?: Object): SaccadeTarget[];
88
+ /**
89
+ * Predict center of tracking based on current state and velocity
90
+ * @private
91
+ */
92
+ private _predictTrackingCenter;
93
+ /**
94
+ * Compute average velocity from history
95
+ * @private
96
+ */
97
+ private _computeAverageVelocity;
98
+ /**
99
+ * Check if a location is inhibited (too close to recent targets)
100
+ * @private
101
+ */
102
+ private _isInhibited;
103
+ /**
104
+ * Get next grid cell for systematic search
105
+ * @private
106
+ */
107
+ private _getNextGridCell;
108
+ /**
109
+ * Update history with new targets
110
+ * @private
111
+ */
112
+ private _updateHistory;
113
+ /**
114
+ * Get the most likely location of interest based on history
115
+ * @returns {Object} {x, y} of predicted location
116
+ */
117
+ getPredictedLocation(): Object;
118
+ /**
119
+ * Reset controller state
120
+ */
121
+ reset(): void;
122
+ /**
123
+ * Update configuration
124
+ */
125
+ configure(config: any): void;
126
+ }
@@ -0,0 +1,269 @@
1
+ /**
2
+ * Saccadic Controller
3
+ *
4
+ * Mimics human eye saccades - rapid movements that redirect foveal attention
5
+ * to areas of interest. The human eye makes 3-4 saccades per second to
6
+ * build a complete picture of the visual scene.
7
+ *
8
+ * Strategy:
9
+ * 1. Compute saliency map to find "interesting" regions
10
+ * 2. Use tracking state to predict where features should be
11
+ * 3. Generate priority-ordered list of "glance" targets
12
+ * 4. Limit saccades per frame to balance coverage vs. efficiency
13
+ */
14
+ /**
15
+ * A saccade target representing where attention should be directed
16
+ * @typedef {Object} SaccadeTarget
17
+ * @property {number} x - X coordinate
18
+ * @property {number} y - Y coordinate
19
+ * @property {number} priority - Priority (0 = highest)
20
+ * @property {string} reason - Why this target was selected
21
+ * @property {number} saliency - Saliency score at this location
22
+ */
23
+ class SaccadicController {
24
+ /**
25
+ * @param {number} width - Image width
26
+ * @param {number} height - Image height
27
+ * @param {Object} config - Configuration
28
+ */
29
+ constructor(width, height, config) {
30
+ this.width = width;
31
+ this.height = height;
32
+ this.config = config;
33
+ // Saccade history for inhibition of return
34
+ this.recentTargets = [];
35
+ this.inhibitionRadius = Math.min(width, height) * 0.1;
36
+ // Movement prediction
37
+ this.velocityHistory = [];
38
+ this.lastCenter = { x: width / 2, y: height / 2 };
39
+ // Grid for systematic coverage
40
+ this.gridCells = this._buildCoverageGrid(3, 3);
41
+ this.lastVisitedCell = 4; // Center
42
+ // State
43
+ this.lastSaccadeTime = 0;
44
+ this.saccadeCount = 0;
45
+ }
46
+ /**
47
+ * Build a grid for systematic coverage during tracking loss
48
+ * @private
49
+ */
50
+ _buildCoverageGrid(rows, cols) {
51
+ const cells = [];
52
+ const cellW = this.width / cols;
53
+ const cellH = this.height / rows;
54
+ for (let r = 0; r < rows; r++) {
55
+ for (let c = 0; c < cols; c++) {
56
+ cells.push({
57
+ x: cellW * (c + 0.5),
58
+ y: cellH * (r + 0.5),
59
+ index: r * cols + c,
60
+ lastVisit: 0,
61
+ });
62
+ }
63
+ }
64
+ return cells;
65
+ }
66
+ /**
67
+ * Compute saccade targets based on current state
68
+ *
69
+ * @param {Object} saliency - Saliency map result
70
+ * @param {Object} currentFovea - Current fovea center {x, y}
71
+ * @param {Object} trackingState - Current tracking state (optional)
72
+ * @returns {SaccadeTarget[]} Priority-ordered list of targets
73
+ */
74
+ computeTargets(saliency, currentFovea, trackingState = null) {
75
+ const targets = [];
76
+ const maxTargets = this.config.MAX_SACCADES_PER_FRAME;
77
+ // Strategy 1: Follow tracking prediction (highest priority)
78
+ if (trackingState && trackingState.isTracking) {
79
+ const predicted = this._predictTrackingCenter(trackingState);
80
+ if (predicted) {
81
+ targets.push({
82
+ x: predicted.x,
83
+ y: predicted.y,
84
+ priority: 0,
85
+ reason: 'tracking_prediction',
86
+ saliency: 1.0,
87
+ });
88
+ }
89
+ }
90
+ // Strategy 2: High saliency regions
91
+ if (saliency && saliency.peaks) {
92
+ for (const peak of saliency.peaks) {
93
+ if (targets.length >= maxTargets)
94
+ break;
95
+ // Skip if too close to existing targets (inhibition of return)
96
+ if (this._isInhibited(peak.x, peak.y, targets))
97
+ continue;
98
+ if (peak.value > this.config.SALIENCY_THRESHOLD) {
99
+ targets.push({
100
+ x: peak.x,
101
+ y: peak.y,
102
+ priority: targets.length,
103
+ reason: 'saliency_peak',
104
+ saliency: peak.value,
105
+ });
106
+ }
107
+ }
108
+ }
109
+ // Strategy 3: Systematic grid search (when not tracking)
110
+ if (!trackingState?.isTracking && targets.length < maxTargets) {
111
+ const gridTarget = this._getNextGridCell();
112
+ if (gridTarget && !this._isInhibited(gridTarget.x, gridTarget.y, targets)) {
113
+ targets.push({
114
+ x: gridTarget.x,
115
+ y: gridTarget.y,
116
+ priority: targets.length,
117
+ reason: 'grid_search',
118
+ saliency: 0.5,
119
+ });
120
+ }
121
+ }
122
+ // Strategy 4: Stay at current center if no better options
123
+ if (targets.length === 0) {
124
+ targets.push({
125
+ x: currentFovea.x,
126
+ y: currentFovea.y,
127
+ priority: 0,
128
+ reason: 'maintain_position',
129
+ saliency: 0.3,
130
+ });
131
+ }
132
+ // Update history
133
+ this._updateHistory(targets);
134
+ return targets;
135
+ }
136
+ /**
137
+ * Predict center of tracking based on current state and velocity
138
+ * @private
139
+ */
140
+ _predictTrackingCenter(trackingState) {
141
+ if (!trackingState.worldMatrix)
142
+ return null;
143
+ // Extract center from world matrix
144
+ const matrix = trackingState.worldMatrix;
145
+ const cx = matrix[12] || this.width / 2;
146
+ const cy = matrix[13] || this.height / 2;
147
+ // Apply velocity-based prediction
148
+ if (this.velocityHistory.length >= 2) {
149
+ const vx = this._computeAverageVelocity('x');
150
+ const vy = this._computeAverageVelocity('y');
151
+ // Predict 1 frame ahead
152
+ return {
153
+ x: Math.max(0, Math.min(this.width - 1, cx + vx)),
154
+ y: Math.max(0, Math.min(this.height - 1, cy + vy)),
155
+ };
156
+ }
157
+ return { x: cx, y: cy };
158
+ }
159
+ /**
160
+ * Compute average velocity from history
161
+ * @private
162
+ */
163
+ _computeAverageVelocity(axis) {
164
+ if (this.velocityHistory.length < 2)
165
+ return 0;
166
+ let sum = 0;
167
+ for (let i = 1; i < this.velocityHistory.length; i++) {
168
+ sum += this.velocityHistory[i][axis] - this.velocityHistory[i - 1][axis];
169
+ }
170
+ return sum / (this.velocityHistory.length - 1);
171
+ }
172
+ /**
173
+ * Check if a location is inhibited (too close to recent targets)
174
+ * @private
175
+ */
176
+ _isInhibited(x, y, currentTargets) {
177
+ const r2 = this.inhibitionRadius ** 2;
178
+ // Check against current frame targets
179
+ for (const t of currentTargets) {
180
+ const dx = x - t.x;
181
+ const dy = y - t.y;
182
+ if (dx * dx + dy * dy < r2)
183
+ return true;
184
+ }
185
+ // Check against recent history
186
+ for (const t of this.recentTargets) {
187
+ const dx = x - t.x;
188
+ const dy = y - t.y;
189
+ if (dx * dx + dy * dy < r2)
190
+ return true;
191
+ }
192
+ return false;
193
+ }
194
+ /**
195
+ * Get next grid cell for systematic search
196
+ * @private
197
+ */
198
+ _getNextGridCell() {
199
+ // Find least recently visited cell
200
+ let oldest = this.gridCells[0];
201
+ let oldestTime = Infinity;
202
+ for (const cell of this.gridCells) {
203
+ if (cell.lastVisit < oldestTime) {
204
+ oldestTime = cell.lastVisit;
205
+ oldest = cell;
206
+ }
207
+ }
208
+ oldest.lastVisit = Date.now();
209
+ return oldest;
210
+ }
211
+ /**
212
+ * Update history with new targets
213
+ * @private
214
+ */
215
+ _updateHistory(targets) {
216
+ // Add to recent targets for inhibition of return
217
+ this.recentTargets.push(...targets);
218
+ // Keep only last N targets
219
+ const maxHistory = this.config.MOTION_HISTORY_FRAMES * this.config.MAX_SACCADES_PER_FRAME;
220
+ while (this.recentTargets.length > maxHistory) {
221
+ this.recentTargets.shift();
222
+ }
223
+ // Update velocity history
224
+ if (targets.length > 0) {
225
+ this.velocityHistory.push({ x: targets[0].x, y: targets[0].y });
226
+ while (this.velocityHistory.length > this.config.MOTION_HISTORY_FRAMES) {
227
+ this.velocityHistory.shift();
228
+ }
229
+ this.lastCenter = { x: targets[0].x, y: targets[0].y };
230
+ }
231
+ this.saccadeCount += targets.length;
232
+ this.lastSaccadeTime = Date.now();
233
+ }
234
+ /**
235
+ * Get the most likely location of interest based on history
236
+ * @returns {Object} {x, y} of predicted location
237
+ */
238
+ getPredictedLocation() {
239
+ if (this.velocityHistory.length >= 2) {
240
+ const vx = this._computeAverageVelocity('x');
241
+ const vy = this._computeAverageVelocity('y');
242
+ return {
243
+ x: Math.max(0, Math.min(this.width - 1, this.lastCenter.x + vx)),
244
+ y: Math.max(0, Math.min(this.height - 1, this.lastCenter.y + vy)),
245
+ };
246
+ }
247
+ return this.lastCenter;
248
+ }
249
+ /**
250
+ * Reset controller state
251
+ */
252
+ reset() {
253
+ this.recentTargets = [];
254
+ this.velocityHistory = [];
255
+ this.lastCenter = { x: this.width / 2, y: this.height / 2 };
256
+ this.saccadeCount = 0;
257
+ for (const cell of this.gridCells) {
258
+ cell.lastVisit = 0;
259
+ }
260
+ }
261
+ /**
262
+ * Update configuration
263
+ */
264
+ configure(config) {
265
+ this.config = { ...this.config, ...config };
266
+ this.inhibitionRadius = Math.min(this.width, this.height) * 0.1;
267
+ }
268
+ }
269
+ export { SaccadicController };
@@ -0,0 +1,74 @@
1
+ /**
2
+ * Saliency Map Computation
3
+ *
4
+ * Computes visual saliency - regions that "pop out" and attract attention.
5
+ * Used to guide saccadic attention to visually important areas.
6
+ *
7
+ * Implements a simplified Itti-Koch saliency model:
8
+ * - Intensity contrast
9
+ * - Edge density
10
+ * - Local complexity
11
+ *
12
+ * For AR tracking, high-saliency regions often contain:
13
+ * - Corners and edges (good for feature detection)
14
+ * - High-contrast areas (robust to lighting changes)
15
+ * - Texture-rich regions (distinctive for matching)
16
+ */
17
+ export class SaliencyMap {
18
+ /**
19
+ * @param {number} width - Image width
20
+ * @param {number} height - Image height
21
+ */
22
+ constructor(width: number, height: number);
23
+ width: number;
24
+ height: number;
25
+ scale: number;
26
+ scaledW: number;
27
+ scaledH: number;
28
+ intensityMap: Float32Array<ArrayBuffer>;
29
+ contrastMap: Float32Array<ArrayBuffer>;
30
+ edgeMap: Float32Array<ArrayBuffer>;
31
+ saliencyBuffer: Float32Array<ArrayBuffer>;
32
+ maxPeaks: number;
33
+ suppressionRadius: number;
34
+ /**
35
+ * Compute saliency map for input image
36
+ *
37
+ * @param {Uint8Array} inputData - Grayscale input image
38
+ * @returns {Object} Saliency result with peaks
39
+ */
40
+ compute(inputData: Uint8Array): Object;
41
+ /**
42
+ * Downsample input to working resolution
43
+ * @private
44
+ */
45
+ private _downsample;
46
+ /**
47
+ * Compute local contrast map
48
+ * @private
49
+ */
50
+ private _computeContrast;
51
+ /**
52
+ * Compute edge density map using Sobel-like operator
53
+ * @private
54
+ */
55
+ private _computeEdges;
56
+ /**
57
+ * Combine features into final saliency map
58
+ * @private
59
+ */
60
+ private _combineSaliency;
61
+ /**
62
+ * Find peaks in saliency map using non-maximum suppression
63
+ * @private
64
+ */
65
+ private _findPeaks;
66
+ /**
67
+ * Get saliency value at a specific location
68
+ *
69
+ * @param {number} x - X coordinate in original image
70
+ * @param {number} y - Y coordinate in original image
71
+ * @returns {number} Saliency value (0-1)
72
+ */
73
+ getSaliencyAt(x: number, y: number): number;
74
+ }