@srsergio/taptapp-ar 1.0.59 → 1.0.60

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.
@@ -103,13 +103,76 @@ export class OfflineCompiler {
103
103
  });
104
104
  return Promise.all(wrappedPromises);
105
105
  }
106
- // Fallback or non-worker implementation: run match and track sequentially
107
- const matchingResults = await this._compileMatch(targetImages, (p) => progressCallback(p * 0.5));
108
- const trackingResults = await this._compileTrack(targetImages, (p) => progressCallback(50 + p * 0.5));
109
- return targetImages.map((_, i) => ({
110
- matchingData: matchingResults[i],
111
- trackingData: trackingResults[i]
112
- }));
106
+ // 🚀 MOONSHOT BROWSER FALLBACK:
107
+ // Combined detection to avoid redundant pyramid processing
108
+ const results = [];
109
+ for (let i = 0; i < targetImages.length; i++) {
110
+ const targetImage = targetImages[i];
111
+ // 1. Single Pass Detection + Pyramid Generation
112
+ const detector = new DetectorLite(targetImage.width, targetImage.height, { useLSH: true });
113
+ progressCallback((i / targetImages.length) * 100 + 10);
114
+ const { featurePoints, pyramid } = detector.detect(targetImage.data);
115
+ progressCallback((i / targetImages.length) * 100 + 40);
116
+ // 2. Extract Tracking Data using the ALREADY BLURRED pyramid
117
+ const trackingImageList = [];
118
+ const targetSizes = [256, 128];
119
+ for (const targetSize of targetSizes) {
120
+ let bestLevel = 0;
121
+ let minDiff = Math.abs(Math.min(targetImage.width, targetImage.height) - targetSize);
122
+ for (let l = 1; l < pyramid.length; l++) {
123
+ const img = pyramid[l][0];
124
+ const diff = Math.abs(Math.min(img.width, img.height) - targetSize);
125
+ if (diff < minDiff) {
126
+ minDiff = diff;
127
+ bestLevel = l;
128
+ }
129
+ }
130
+ const levelImg = pyramid[bestLevel][0];
131
+ trackingImageList.push({
132
+ data: levelImg.data,
133
+ width: levelImg.width,
134
+ height: levelImg.height,
135
+ scale: levelImg.width / targetImage.width
136
+ });
137
+ }
138
+ const trackingData = extractTrackingFeatures(trackingImageList, () => { });
139
+ progressCallback((i / targetImages.length) * 100 + 60);
140
+ // 3. Build Keyframes for Matching (Group by scale)
141
+ const scalesMap = new Map();
142
+ for (const p of featurePoints) {
143
+ const s = p.scale;
144
+ let list = scalesMap.get(s);
145
+ if (!list) {
146
+ list = [];
147
+ scalesMap.set(s, list);
148
+ }
149
+ list.push({ ...p, x: p.x / s, y: p.y / s, scale: 1.0 });
150
+ }
151
+ const keyframes = [];
152
+ const sortedScales = Array.from(scalesMap.keys()).sort((a, b) => a - b);
153
+ for (const s of sortedScales) {
154
+ const ps = scalesMap.get(s);
155
+ const maximaPoints = ps.filter((p) => p.maxima);
156
+ const minimaPoints = ps.filter((p) => !p.maxima);
157
+ const maximaPointsCluster = hierarchicalClusteringBuild({ points: maximaPoints });
158
+ const minimaPointsCluster = hierarchicalClusteringBuild({ points: minimaPoints });
159
+ keyframes.push({
160
+ maximaPoints,
161
+ minimaPoints,
162
+ maximaPointsCluster,
163
+ minimaPointsCluster,
164
+ width: Math.round(targetImage.width / s),
165
+ height: Math.round(targetImage.height / s),
166
+ scale: 1.0 / s,
167
+ });
168
+ }
169
+ results.push({
170
+ matchingData: keyframes,
171
+ trackingData: trackingData
172
+ });
173
+ progressCallback(((i + 1) / targetImages.length) * 100);
174
+ }
175
+ return results;
113
176
  }
114
177
  async _compileMatch(targetImages, progressCallback) {
115
178
  const percentPerImage = 100 / targetImages.length;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@srsergio/taptapp-ar",
3
- "version": "1.0.59",
3
+ "version": "1.0.60",
4
4
  "author": "Sergio Lazaro <srsergiolazaro@gmail.com>",
5
5
  "license": "GPL-3.0",
6
6
  "description": "Ultra-fast, lightweight Augmented Reality Image Tracking SDK for the web. Features an optimized offline compiler, React components, and compatibility with Three.js/A-Frame. No heavy ML frameworks required.",
@@ -126,14 +126,87 @@ export class OfflineCompiler {
126
126
  return Promise.all(wrappedPromises);
127
127
  }
128
128
 
129
- // Fallback or non-worker implementation: run match and track sequentially
130
- const matchingResults = await this._compileMatch(targetImages, (p) => progressCallback(p * 0.5));
131
- const trackingResults = await this._compileTrack(targetImages, (p) => progressCallback(50 + p * 0.5));
129
+ // 🚀 MOONSHOT BROWSER FALLBACK:
130
+ // Combined detection to avoid redundant pyramid processing
131
+ const results = [];
132
+ for (let i = 0; i < targetImages.length; i++) {
133
+ const targetImage = targetImages[i];
132
134
 
133
- return targetImages.map((_, i) => ({
134
- matchingData: matchingResults[i],
135
- trackingData: trackingResults[i]
136
- }));
135
+ // 1. Single Pass Detection + Pyramid Generation
136
+ const detector = new DetectorLite(targetImage.width, targetImage.height, { useLSH: true });
137
+ progressCallback((i / targetImages.length) * 100 + 10);
138
+
139
+ const { featurePoints, pyramid }: any = detector.detect(targetImage.data);
140
+ progressCallback((i / targetImages.length) * 100 + 40);
141
+
142
+ // 2. Extract Tracking Data using the ALREADY BLURRED pyramid
143
+ const trackingImageList: any[] = [];
144
+ const targetSizes = [256, 128];
145
+ for (const targetSize of targetSizes) {
146
+ let bestLevel = 0;
147
+ let minDiff = Math.abs(Math.min(targetImage.width, targetImage.height) - targetSize);
148
+
149
+ for (let l = 1; l < pyramid.length; l++) {
150
+ const img = pyramid[l][0];
151
+ const diff = Math.abs(Math.min(img.width, img.height) - targetSize);
152
+ if (diff < minDiff) {
153
+ minDiff = diff;
154
+ bestLevel = l;
155
+ }
156
+ }
157
+
158
+ const levelImg = pyramid[bestLevel][0];
159
+ trackingImageList.push({
160
+ data: levelImg.data,
161
+ width: levelImg.width,
162
+ height: levelImg.height,
163
+ scale: levelImg.width / targetImage.width
164
+ });
165
+ }
166
+
167
+ const trackingData = extractTrackingFeatures(trackingImageList, () => { });
168
+ progressCallback((i / targetImages.length) * 100 + 60);
169
+
170
+ // 3. Build Keyframes for Matching (Group by scale)
171
+ const scalesMap = new Map();
172
+ for (const p of featurePoints) {
173
+ const s = p.scale;
174
+ let list = scalesMap.get(s);
175
+ if (!list) {
176
+ list = [];
177
+ scalesMap.set(s, list);
178
+ }
179
+ list.push({ ...p, x: p.x / s, y: p.y / s, scale: 1.0 });
180
+ }
181
+
182
+ const keyframes = [];
183
+ const sortedScales = Array.from(scalesMap.keys()).sort((a, b) => a - b);
184
+ for (const s of sortedScales) {
185
+ const ps = scalesMap.get(s);
186
+ const maximaPoints = ps.filter((p: any) => p.maxima);
187
+ const minimaPoints = ps.filter((p: any) => !p.maxima);
188
+ const maximaPointsCluster = hierarchicalClusteringBuild({ points: maximaPoints });
189
+ const minimaPointsCluster = hierarchicalClusteringBuild({ points: minimaPoints });
190
+
191
+ keyframes.push({
192
+ maximaPoints,
193
+ minimaPoints,
194
+ maximaPointsCluster,
195
+ minimaPointsCluster,
196
+ width: Math.round(targetImage.width / s),
197
+ height: Math.round(targetImage.height / s),
198
+ scale: 1.0 / s,
199
+ });
200
+ }
201
+
202
+ results.push({
203
+ matchingData: keyframes,
204
+ trackingData: trackingData
205
+ });
206
+ progressCallback(((i + 1) / targetImages.length) * 100);
207
+ }
208
+
209
+ return results;
137
210
  }
138
211
 
139
212
  async _compileMatch(targetImages: any[], progressCallback: (p: number) => void) {