@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
|
-
//
|
|
107
|
-
|
|
108
|
-
const
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
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.
|
|
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
|
-
//
|
|
130
|
-
|
|
131
|
-
const
|
|
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
|
-
|
|
134
|
-
|
|
135
|
-
|
|
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) {
|