@srsergio/taptapp-ar 1.0.85 → 1.0.87
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/node-worker.js +5 -18
- package/dist/compiler/offline-compiler.d.ts +0 -48
- package/dist/compiler/offline-compiler.js +12 -208
- package/dist/{compiler → core}/detector/detector-lite.d.ts +6 -0
- package/dist/{compiler → core}/detector/detector-lite.js +9 -9
- package/dist/{compiler → core}/matching/matching.js +3 -20
- package/dist/core/protocol.d.ts +43 -0
- package/dist/core/protocol.js +195 -0
- package/dist/{compiler → core}/tracker/tracker.js +3 -2
- package/dist/index.d.ts +3 -2
- package/dist/index.js +3 -2
- package/dist/react/use-ar.js +1 -1
- package/dist/{compiler → runtime}/controller.d.ts +10 -6
- package/dist/{compiler → runtime}/controller.js +76 -22
- package/dist/{compiler → runtime}/controller.worker.js +33 -3
- package/dist/runtime/index.d.ts +4 -0
- package/dist/runtime/index.js +4 -0
- package/dist/{compiler → runtime}/simple-ar.js +1 -1
- package/package.json +1 -1
- package/src/compiler/node-worker.js +5 -19
- package/src/compiler/offline-compiler.ts +12 -241
- package/src/{compiler → core}/detector/detector-lite.js +10 -10
- package/src/{compiler → core}/matching/matching.js +3 -22
- package/src/core/protocol.ts +223 -0
- package/src/{compiler → core}/tracker/tracker.js +3 -2
- package/src/index.ts +3 -2
- package/src/react/use-ar.ts +2 -2
- package/src/{compiler → runtime}/controller.ts +85 -24
- package/src/{compiler → runtime}/controller.worker.js +45 -3
- package/src/runtime/index.ts +4 -0
- package/src/{compiler → runtime}/simple-ar.ts +1 -1
- package/dist/compiler/utils/fourier-encoder.d.ts +0 -25
- package/dist/compiler/utils/fourier-encoder.js +0 -47
- package/src/compiler/utils/fourier-encoder.ts +0 -53
- /package/dist/compiler/{index.d.ts → offline-compiler-browsertest.d.ts} +0 -0
- /package/dist/compiler/{index.js → offline-compiler-browsertest.js} +0 -0
- /package/dist/{compiler → core}/detector/crop-detector.d.ts +0 -0
- /package/dist/{compiler → core}/detector/crop-detector.js +0 -0
- /package/dist/{compiler → core}/detector/freak.d.ts +0 -0
- /package/dist/{compiler → core}/detector/freak.js +0 -0
- /package/dist/{compiler → core}/estimation/estimate.d.ts +0 -0
- /package/dist/{compiler → core}/estimation/estimate.js +0 -0
- /package/dist/{compiler → core}/estimation/estimator.d.ts +0 -0
- /package/dist/{compiler → core}/estimation/estimator.js +0 -0
- /package/dist/{compiler → core}/estimation/refine-estimate.d.ts +0 -0
- /package/dist/{compiler → core}/estimation/refine-estimate.js +0 -0
- /package/dist/{compiler → core}/estimation/utils.d.ts +0 -0
- /package/dist/{compiler → core}/estimation/utils.js +0 -0
- /package/dist/{compiler → core}/features/auto-rotation-feature.d.ts +0 -0
- /package/dist/{compiler → core}/features/auto-rotation-feature.js +0 -0
- /package/dist/{compiler → core}/features/crop-detection-feature.d.ts +0 -0
- /package/dist/{compiler → core}/features/crop-detection-feature.js +0 -0
- /package/dist/{compiler → core}/features/feature-base.d.ts +0 -0
- /package/dist/{compiler → core}/features/feature-base.js +0 -0
- /package/dist/{compiler → core}/features/feature-manager.d.ts +0 -0
- /package/dist/{compiler → core}/features/feature-manager.js +0 -0
- /package/dist/{compiler → core}/features/one-euro-filter-feature.d.ts +0 -0
- /package/dist/{compiler → core}/features/one-euro-filter-feature.js +0 -0
- /package/dist/{compiler → core}/features/temporal-filter-feature.d.ts +0 -0
- /package/dist/{compiler → core}/features/temporal-filter-feature.js +0 -0
- /package/dist/{compiler → core}/image-list.d.ts +0 -0
- /package/dist/{compiler → core}/image-list.js +0 -0
- /package/dist/{compiler → core}/input-loader.d.ts +0 -0
- /package/dist/{compiler → core}/input-loader.js +0 -0
- /package/dist/{compiler → core}/matching/hamming-distance.d.ts +0 -0
- /package/dist/{compiler → core}/matching/hamming-distance.js +0 -0
- /package/dist/{compiler → core}/matching/hierarchical-clustering.d.ts +0 -0
- /package/dist/{compiler → core}/matching/hierarchical-clustering.js +0 -0
- /package/dist/{compiler → core}/matching/hough.d.ts +0 -0
- /package/dist/{compiler → core}/matching/hough.js +0 -0
- /package/dist/{compiler → core}/matching/matcher.d.ts +0 -0
- /package/dist/{compiler → core}/matching/matcher.js +0 -0
- /package/dist/{compiler → core}/matching/matching.d.ts +0 -0
- /package/dist/{compiler → core}/matching/ransacHomography.d.ts +0 -0
- /package/dist/{compiler → core}/matching/ransacHomography.js +0 -0
- /package/dist/{compiler → core}/tracker/extract-utils.d.ts +0 -0
- /package/dist/{compiler → core}/tracker/extract-utils.js +0 -0
- /package/dist/{compiler → core}/tracker/extract.d.ts +0 -0
- /package/dist/{compiler → core}/tracker/extract.js +0 -0
- /package/dist/{compiler → core}/tracker/tracker.d.ts +0 -0
- /package/dist/{compiler → core}/utils/cumsum.d.ts +0 -0
- /package/dist/{compiler → core}/utils/cumsum.js +0 -0
- /package/dist/{compiler → core}/utils/geometry.d.ts +0 -0
- /package/dist/{compiler → core}/utils/geometry.js +0 -0
- /package/dist/{compiler → core}/utils/gpu-compute.d.ts +0 -0
- /package/dist/{compiler → core}/utils/gpu-compute.js +0 -0
- /package/dist/{compiler → core}/utils/homography.d.ts +0 -0
- /package/dist/{compiler → core}/utils/homography.js +0 -0
- /package/dist/{compiler → core}/utils/images.d.ts +0 -0
- /package/dist/{compiler → core}/utils/images.js +0 -0
- /package/dist/{compiler → core}/utils/lsh-binarizer.d.ts +0 -0
- /package/dist/{compiler → core}/utils/lsh-binarizer.js +0 -0
- /package/dist/{compiler → core}/utils/lsh-direct.d.ts +0 -0
- /package/dist/{compiler → core}/utils/lsh-direct.js +0 -0
- /package/dist/{compiler → core}/utils/projection.d.ts +0 -0
- /package/dist/{compiler → core}/utils/projection.js +0 -0
- /package/dist/{compiler → core}/utils/randomizer.d.ts +0 -0
- /package/dist/{compiler → core}/utils/randomizer.js +0 -0
- /package/dist/{compiler → core}/utils/worker-pool.d.ts +0 -0
- /package/dist/{compiler → core}/utils/worker-pool.js +0 -0
- /package/dist/{compiler → runtime}/aframe.d.ts +0 -0
- /package/dist/{compiler → runtime}/aframe.js +0 -0
- /package/dist/{compiler → runtime}/controller.worker.d.ts +0 -0
- /package/dist/{compiler → runtime}/simple-ar.d.ts +0 -0
- /package/dist/{compiler → runtime}/three.d.ts +0 -0
- /package/dist/{compiler → runtime}/three.js +0 -0
- /package/src/compiler/{index.js → offline-compiler-browsertest.js} +0 -0
- /package/src/{compiler → core}/detector/crop-detector.js +0 -0
- /package/src/{compiler → core}/detector/freak.js +0 -0
- /package/src/{compiler → core}/estimation/estimate.js +0 -0
- /package/src/{compiler → core}/estimation/estimator.js +0 -0
- /package/src/{compiler → core}/estimation/refine-estimate.js +0 -0
- /package/src/{compiler → core}/estimation/utils.js +0 -0
- /package/src/{compiler → core}/features/auto-rotation-feature.ts +0 -0
- /package/src/{compiler → core}/features/crop-detection-feature.ts +0 -0
- /package/src/{compiler → core}/features/feature-base.ts +0 -0
- /package/src/{compiler → core}/features/feature-manager.ts +0 -0
- /package/src/{compiler → core}/features/one-euro-filter-feature.ts +0 -0
- /package/src/{compiler → core}/features/temporal-filter-feature.ts +0 -0
- /package/src/{compiler → core}/image-list.js +0 -0
- /package/src/{compiler → core}/input-loader.js +0 -0
- /package/src/{compiler → core}/matching/hamming-distance.js +0 -0
- /package/src/{compiler → core}/matching/hierarchical-clustering.js +0 -0
- /package/src/{compiler → core}/matching/hough.js +0 -0
- /package/src/{compiler → core}/matching/matcher.js +0 -0
- /package/src/{compiler → core}/matching/ransacHomography.js +0 -0
- /package/src/{compiler → core}/tracker/extract-utils.js +0 -0
- /package/src/{compiler → core}/tracker/extract.js +0 -0
- /package/src/{compiler → core}/utils/cumsum.js +0 -0
- /package/src/{compiler → core}/utils/geometry.js +0 -0
- /package/src/{compiler → core}/utils/gpu-compute.js +0 -0
- /package/src/{compiler → core}/utils/homography.js +0 -0
- /package/src/{compiler → core}/utils/images.js +0 -0
- /package/src/{compiler → core}/utils/lsh-binarizer.js +0 -0
- /package/src/{compiler → core}/utils/lsh-direct.js +0 -0
- /package/src/{compiler → core}/utils/projection.js +0 -0
- /package/src/{compiler → core}/utils/randomizer.js +0 -0
- /package/src/{compiler → core}/utils/worker-pool.js +0 -0
- /package/src/{compiler → runtime}/aframe.js +0 -0
- /package/src/{compiler → runtime}/three.js +0 -0
|
@@ -5,27 +5,14 @@
|
|
|
5
5
|
* Usa JavaScript puro para máxima velocidad.
|
|
6
6
|
*/
|
|
7
7
|
import { parentPort } from 'node:worker_threads';
|
|
8
|
-
import { extractTrackingFeatures } from '
|
|
9
|
-
import { buildTrackingImageList } from '
|
|
10
|
-
import { DetectorLite } from '
|
|
11
|
-
import { build as hierarchicalClusteringBuild } from '
|
|
8
|
+
import { extractTrackingFeatures } from '../core/tracker/extract-utils.js';
|
|
9
|
+
import { buildTrackingImageList } from '../core/image-list.js';
|
|
10
|
+
import { DetectorLite } from '../core/detector/detector-lite.js';
|
|
11
|
+
import { build as hierarchicalClusteringBuild } from '../core/matching/hierarchical-clustering.js';
|
|
12
|
+
import { getMorton } from '../core/protocol.js';
|
|
12
13
|
if (!parentPort) {
|
|
13
14
|
throw new Error('This file must be run as a worker thread.');
|
|
14
15
|
}
|
|
15
|
-
// Helper for Morton Order sorting inside worker
|
|
16
|
-
function getMorton(x, y) {
|
|
17
|
-
let x_int = x | 0;
|
|
18
|
-
let y_int = y | 0;
|
|
19
|
-
x_int = (x_int | (x_int << 8)) & 0x00FF00FF;
|
|
20
|
-
x_int = (x_int | (x_int << 4)) & 0x0F0F0F0F;
|
|
21
|
-
x_int = (x_int | (x_int << 2)) & 0x33333333;
|
|
22
|
-
x_int = (x_int | (x_int << 1)) & 0x55555555;
|
|
23
|
-
y_int = (y_int | (y_int << 8)) & 0x00FF00FF;
|
|
24
|
-
y_int = (y_int | (y_int << 4)) & 0x0F0F0F0F;
|
|
25
|
-
y_int = (y_int | (y_int << 2)) & 0x33333333;
|
|
26
|
-
y_int = (y_int | (y_int << 1)) & 0x55555555;
|
|
27
|
-
return x_int | (y_int << 1);
|
|
28
|
-
}
|
|
29
16
|
const mortonCache = new Int32Array(2048); // Cache for sorting stability
|
|
30
17
|
function sortPoints(points) {
|
|
31
18
|
if (points.length <= 1)
|
|
@@ -5,10 +5,8 @@
|
|
|
5
5
|
* que NO depende de TensorFlow, eliminando todos los problemas de
|
|
6
6
|
* inicialización, bloqueos y compatibilidad.
|
|
7
7
|
*/
|
|
8
|
-
import { FourierEncoder } from "./utils/fourier-encoder.js";
|
|
9
8
|
export declare class OfflineCompiler {
|
|
10
9
|
data: any;
|
|
11
|
-
fourierEncoder: FourierEncoder;
|
|
12
10
|
constructor();
|
|
13
11
|
compileImageTargets(images: any[], progressCallback: (p: number) => void): Promise<any>;
|
|
14
12
|
_compileTarget(targetImages: any[], progressCallback: (p: number) => void): Promise<{
|
|
@@ -112,55 +110,9 @@ export declare class OfflineCompiler {
|
|
|
112
110
|
scale: any;
|
|
113
111
|
}[][]>;
|
|
114
112
|
exportData(): Uint8Array<ArrayBuffer>;
|
|
115
|
-
_getMorton(x: number, y: number): number;
|
|
116
|
-
_columnarize(points: any[], tree: any, width: number, height: number): {
|
|
117
|
-
x: Uint16Array<ArrayBuffer>;
|
|
118
|
-
y: Uint16Array<ArrayBuffer>;
|
|
119
|
-
a: Int16Array<ArrayBuffer>;
|
|
120
|
-
s: Uint8Array<ArrayBuffer>;
|
|
121
|
-
d: Uint32Array<ArrayBuffer>;
|
|
122
|
-
f: Int8Array<ArrayBuffer>;
|
|
123
|
-
t: any;
|
|
124
|
-
};
|
|
125
|
-
_compactTree(node: any): any;
|
|
126
113
|
importData(buffer: ArrayBuffer | Uint8Array): {
|
|
127
114
|
version: any;
|
|
128
115
|
dataList: any;
|
|
129
116
|
};
|
|
130
|
-
_unpackKeyframe(kf: any): {
|
|
131
|
-
width: any;
|
|
132
|
-
height: any;
|
|
133
|
-
scale: any;
|
|
134
|
-
maximaPoints: {
|
|
135
|
-
x: number;
|
|
136
|
-
y: number;
|
|
137
|
-
angle: any;
|
|
138
|
-
scale: any;
|
|
139
|
-
descriptors: any;
|
|
140
|
-
}[];
|
|
141
|
-
minimaPoints: {
|
|
142
|
-
x: number;
|
|
143
|
-
y: number;
|
|
144
|
-
angle: any;
|
|
145
|
-
scale: any;
|
|
146
|
-
descriptors: any;
|
|
147
|
-
}[];
|
|
148
|
-
maximaPointsCluster: {
|
|
149
|
-
rootNode: any;
|
|
150
|
-
};
|
|
151
|
-
minimaPointsCluster: {
|
|
152
|
-
rootNode: any;
|
|
153
|
-
};
|
|
154
|
-
};
|
|
155
|
-
_decolumnarize(col: any, width: number, height: number): {
|
|
156
|
-
x: number;
|
|
157
|
-
y: number;
|
|
158
|
-
angle: any;
|
|
159
|
-
scale: any;
|
|
160
|
-
descriptors: any;
|
|
161
|
-
}[];
|
|
162
|
-
_expandTree(node: any): any;
|
|
163
117
|
destroy(): Promise<void>;
|
|
164
|
-
_pack4Bit(data: Uint8Array): Uint8Array<ArrayBufferLike>;
|
|
165
|
-
_unpack4Bit(packed: Uint8Array, width: number, height: number): Uint8Array<ArrayBuffer>;
|
|
166
118
|
}
|
|
@@ -5,20 +5,17 @@
|
|
|
5
5
|
* que NO depende de TensorFlow, eliminando todos los problemas de
|
|
6
6
|
* inicialización, bloqueos y compatibilidad.
|
|
7
7
|
*/
|
|
8
|
-
import { buildTrackingImageList, buildImageList } from "
|
|
9
|
-
import { extractTrackingFeatures } from "
|
|
10
|
-
import { DetectorLite } from "
|
|
11
|
-
import { build as hierarchicalClusteringBuild } from "
|
|
12
|
-
import
|
|
13
|
-
import * as msgpack from "@msgpack/msgpack";
|
|
8
|
+
import { buildTrackingImageList, buildImageList } from "../core/image-list.js";
|
|
9
|
+
import { extractTrackingFeatures } from "../core/tracker/extract-utils.js";
|
|
10
|
+
import { DetectorLite } from "../core/detector/detector-lite.js";
|
|
11
|
+
import { build as hierarchicalClusteringBuild } from "../core/matching/hierarchical-clustering.js";
|
|
12
|
+
import * as protocol from "../core/protocol.js";
|
|
14
13
|
// Detect environment
|
|
15
14
|
const isNode = typeof process !== "undefined" &&
|
|
16
15
|
process.versions != null &&
|
|
17
16
|
process.versions.node != null;
|
|
18
|
-
const CURRENT_VERSION = 7; // Protocol v7: Moonshot - 4-bit Packed Tracking Data
|
|
19
17
|
export class OfflineCompiler {
|
|
20
18
|
data = null;
|
|
21
|
-
fourierEncoder = new FourierEncoder(4);
|
|
22
19
|
constructor() {
|
|
23
20
|
console.log("⚡ OfflineCompiler: Main thread mode (no workers)");
|
|
24
21
|
}
|
|
@@ -78,7 +75,7 @@ export class OfflineCompiler {
|
|
|
78
75
|
const percentPerImageScale = percentPerImage / imageList.length;
|
|
79
76
|
const keyframes = [];
|
|
80
77
|
for (const image of imageList) {
|
|
81
|
-
const detector = new DetectorLite(image.width, image.height, { useLSH: true });
|
|
78
|
+
const detector = new DetectorLite(image.width, image.height, { useLSH: true, maxFeaturesPerBucket: 20 });
|
|
82
79
|
const { featurePoints: ps } = detector.detect(image.data);
|
|
83
80
|
const maximaPoints = ps.filter((p) => p.maxima);
|
|
84
81
|
const minimaPoints = ps.filter((p) => !p.maxima);
|
|
@@ -157,212 +154,19 @@ export class OfflineCompiler {
|
|
|
157
154
|
w: kf.width,
|
|
158
155
|
h: kf.height,
|
|
159
156
|
s: kf.scale,
|
|
160
|
-
max:
|
|
161
|
-
min:
|
|
157
|
+
max: protocol.columnarize(kf.maximaPoints, kf.maximaPointsCluster, kf.width, kf.height),
|
|
158
|
+
min: protocol.columnarize(kf.minimaPoints, kf.minimaPointsCluster, kf.width, kf.height),
|
|
162
159
|
})),
|
|
163
160
|
};
|
|
164
161
|
});
|
|
165
|
-
return
|
|
166
|
-
v: CURRENT_VERSION,
|
|
167
|
-
dataList,
|
|
168
|
-
});
|
|
169
|
-
}
|
|
170
|
-
_getMorton(x, y) {
|
|
171
|
-
let x_int = x | 0;
|
|
172
|
-
let y_int = y | 0;
|
|
173
|
-
x_int = (x_int | (x_int << 8)) & 0x00FF00FF;
|
|
174
|
-
x_int = (x_int | (x_int << 4)) & 0x0F0F0F0F;
|
|
175
|
-
x_int = (x_int | (x_int << 2)) & 0x33333333;
|
|
176
|
-
x_int = (x_int | (x_int << 1)) & 0x55555555;
|
|
177
|
-
y_int = (y_int | (y_int << 8)) & 0x00FF00FF;
|
|
178
|
-
y_int = (y_int | (y_int << 4)) & 0x0F0F0F0F;
|
|
179
|
-
y_int = (y_int | (y_int << 2)) & 0x33333333;
|
|
180
|
-
y_int = (y_int | (y_int << 1)) & 0x55555555;
|
|
181
|
-
return x_int | (y_int << 1);
|
|
182
|
-
}
|
|
183
|
-
// Keyframe packing is now minimal, most work moved to Workers
|
|
184
|
-
_columnarize(points, tree, width, height) {
|
|
185
|
-
const count = points.length;
|
|
186
|
-
const x = new Uint16Array(count);
|
|
187
|
-
const y = new Uint16Array(count);
|
|
188
|
-
const angle = new Int16Array(count);
|
|
189
|
-
const scale = new Uint8Array(count);
|
|
190
|
-
const descriptors = new Uint32Array(count * 2);
|
|
191
|
-
const fourier = new Int8Array(count * 16); // 4 frequencies * 4 components (sin/cos x/y)
|
|
192
|
-
for (let i = 0; i < count; i++) {
|
|
193
|
-
x[i] = Math.round((points[i].x / width) * 65535);
|
|
194
|
-
y[i] = Math.round((points[i].y / height) * 65535);
|
|
195
|
-
angle[i] = Math.round((points[i].angle / Math.PI) * 32767);
|
|
196
|
-
scale[i] = Math.round(Math.log2(points[i].scale || 1));
|
|
197
|
-
if (points[i].descriptors && points[i].descriptors.length >= 2) {
|
|
198
|
-
descriptors[i * 2] = points[i].descriptors[0];
|
|
199
|
-
descriptors[(i * 2) + 1] = points[i].descriptors[1];
|
|
200
|
-
}
|
|
201
|
-
// 🚀 MOONSHOT: Fourier Positional Encoding
|
|
202
|
-
const feat = this.fourierEncoder.encode(points[i].x / width, points[i].y / height);
|
|
203
|
-
for (let j = 0; j < 16; j++) {
|
|
204
|
-
fourier[i * 16 + j] = Math.round(feat[j] * 127);
|
|
205
|
-
}
|
|
206
|
-
}
|
|
207
|
-
return {
|
|
208
|
-
x,
|
|
209
|
-
y,
|
|
210
|
-
a: angle,
|
|
211
|
-
s: scale,
|
|
212
|
-
d: descriptors,
|
|
213
|
-
f: fourier,
|
|
214
|
-
t: this._compactTree(tree.rootNode),
|
|
215
|
-
};
|
|
216
|
-
}
|
|
217
|
-
_compactTree(node) {
|
|
218
|
-
if (node.leaf) {
|
|
219
|
-
return [1, node.centerPointIndex || 0, node.pointIndexes];
|
|
220
|
-
}
|
|
221
|
-
return [0, node.centerPointIndex || 0, node.children.map((c) => this._compactTree(c))];
|
|
162
|
+
return protocol.encodeTaar(dataList);
|
|
222
163
|
}
|
|
223
164
|
importData(buffer) {
|
|
224
|
-
const
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
console.error(`Incompatible .taar version: ${version}. This engine only supports Protocol V5/V6.`);
|
|
228
|
-
return { version, dataList: [] };
|
|
229
|
-
}
|
|
230
|
-
const dataList = content.dataList;
|
|
231
|
-
for (let i = 0; i < dataList.length; i++) {
|
|
232
|
-
const item = dataList[i];
|
|
233
|
-
for (const td of item.trackingData) {
|
|
234
|
-
let px = td.px;
|
|
235
|
-
let py = td.py;
|
|
236
|
-
if (px instanceof Uint8Array) {
|
|
237
|
-
px = new Float32Array(px.buffer.slice(px.byteOffset, px.byteOffset + px.byteLength));
|
|
238
|
-
}
|
|
239
|
-
if (py instanceof Uint8Array) {
|
|
240
|
-
py = new Float32Array(py.buffer.slice(py.byteOffset, py.byteOffset + py.byteLength));
|
|
241
|
-
}
|
|
242
|
-
td.px = px;
|
|
243
|
-
td.py = py;
|
|
244
|
-
// No longer unpacking 4-bit, keeping original data
|
|
245
|
-
if (td.data && td.data.length === (td.width * td.height) / 2) {
|
|
246
|
-
td.data = this._unpack4Bit(td.data, td.width, td.height);
|
|
247
|
-
}
|
|
248
|
-
if (td.d && td.d.length === (td.w * td.h) / 2) {
|
|
249
|
-
td.d = this._unpack4Bit(td.d, td.w, td.h);
|
|
250
|
-
}
|
|
251
|
-
}
|
|
252
|
-
for (const kf of item.matchingData) {
|
|
253
|
-
for (const col of [kf.max, kf.min]) {
|
|
254
|
-
let xRaw = col.x;
|
|
255
|
-
let yRaw = col.y;
|
|
256
|
-
if (xRaw instanceof Uint8Array) {
|
|
257
|
-
xRaw = new Uint16Array(xRaw.buffer.slice(xRaw.byteOffset, xRaw.byteOffset + xRaw.byteLength));
|
|
258
|
-
}
|
|
259
|
-
if (yRaw instanceof Uint8Array) {
|
|
260
|
-
yRaw = new Uint16Array(yRaw.buffer.slice(yRaw.byteOffset, yRaw.byteOffset + yRaw.byteLength));
|
|
261
|
-
}
|
|
262
|
-
const count = xRaw.length;
|
|
263
|
-
const x = new Float32Array(count);
|
|
264
|
-
const y = new Float32Array(count);
|
|
265
|
-
for (let k = 0; k < count; k++) {
|
|
266
|
-
x[k] = (xRaw[k] / 65535) * kf.w;
|
|
267
|
-
y[k] = (yRaw[k] / 65535) * kf.h;
|
|
268
|
-
}
|
|
269
|
-
col.x = x;
|
|
270
|
-
col.y = y;
|
|
271
|
-
if (col.a instanceof Uint8Array) {
|
|
272
|
-
const aRaw = new Int16Array(col.a.buffer.slice(col.a.byteOffset, col.a.byteOffset + col.a.byteLength));
|
|
273
|
-
const a = new Float32Array(count);
|
|
274
|
-
for (let k = 0; k < count; k++) {
|
|
275
|
-
a[k] = (aRaw[k] / 32767) * Math.PI;
|
|
276
|
-
}
|
|
277
|
-
col.a = a;
|
|
278
|
-
}
|
|
279
|
-
if (col.s instanceof Uint8Array) {
|
|
280
|
-
const sRaw = col.s;
|
|
281
|
-
const s = new Float32Array(count);
|
|
282
|
-
for (let k = 0; k < count; k++) {
|
|
283
|
-
s[k] = Math.pow(2, sRaw[k]);
|
|
284
|
-
}
|
|
285
|
-
col.s = s;
|
|
286
|
-
}
|
|
287
|
-
if (col.d instanceof Uint8Array) {
|
|
288
|
-
col.d = new Uint32Array(col.d.buffer.slice(col.d.byteOffset, col.d.byteOffset + col.d.byteLength));
|
|
289
|
-
}
|
|
290
|
-
if (col.f instanceof Uint8Array) {
|
|
291
|
-
col.f = new Int8Array(col.f.buffer.slice(col.f.byteOffset, col.f.byteOffset + col.f.byteLength));
|
|
292
|
-
}
|
|
293
|
-
}
|
|
294
|
-
}
|
|
295
|
-
}
|
|
296
|
-
this.data = dataList;
|
|
297
|
-
return { version, dataList };
|
|
298
|
-
}
|
|
299
|
-
_unpackKeyframe(kf) {
|
|
300
|
-
return {
|
|
301
|
-
width: kf.w,
|
|
302
|
-
height: kf.h,
|
|
303
|
-
scale: kf.s,
|
|
304
|
-
maximaPoints: this._decolumnarize(kf.max, kf.w, kf.h),
|
|
305
|
-
minimaPoints: this._decolumnarize(kf.min, kf.w, kf.h),
|
|
306
|
-
maximaPointsCluster: { rootNode: this._expandTree(kf.max.t) },
|
|
307
|
-
minimaPointsCluster: { rootNode: this._expandTree(kf.min.t) },
|
|
308
|
-
};
|
|
309
|
-
}
|
|
310
|
-
_decolumnarize(col, width, height) {
|
|
311
|
-
const points = [];
|
|
312
|
-
const count = col.x.length;
|
|
313
|
-
const descSize = col.d.length / count;
|
|
314
|
-
for (let i = 0; i < count; i++) {
|
|
315
|
-
points.push({
|
|
316
|
-
x: (col.x[i] / 65535) * width,
|
|
317
|
-
y: (col.y[i] / 65535) * height,
|
|
318
|
-
angle: col.a[i],
|
|
319
|
-
scale: col.s ? col.s[i] : 1.0,
|
|
320
|
-
descriptors: col.d.slice(i * descSize, (i + 1) * descSize),
|
|
321
|
-
});
|
|
322
|
-
}
|
|
323
|
-
return points;
|
|
324
|
-
}
|
|
325
|
-
_expandTree(node) {
|
|
326
|
-
const isLeaf = node[0] === 1;
|
|
327
|
-
if (isLeaf) {
|
|
328
|
-
return {
|
|
329
|
-
leaf: true,
|
|
330
|
-
centerPointIndex: node[1],
|
|
331
|
-
pointIndexes: node[2],
|
|
332
|
-
};
|
|
333
|
-
}
|
|
334
|
-
return {
|
|
335
|
-
leaf: false,
|
|
336
|
-
centerPointIndex: node[1],
|
|
337
|
-
children: node[2].map((c) => this._expandTree(c)),
|
|
338
|
-
};
|
|
165
|
+
const result = protocol.decodeTaar(buffer);
|
|
166
|
+
this.data = result.dataList;
|
|
167
|
+
return result;
|
|
339
168
|
}
|
|
340
169
|
async destroy() {
|
|
341
170
|
// No workers to destroy
|
|
342
171
|
}
|
|
343
|
-
_pack4Bit(data) {
|
|
344
|
-
const length = data.length;
|
|
345
|
-
if (length % 2 !== 0)
|
|
346
|
-
return data; // Only pack even lengths
|
|
347
|
-
const packed = new Uint8Array(length / 2);
|
|
348
|
-
for (let i = 0; i < length; i += 2) {
|
|
349
|
-
// Take top 4 bits of each byte
|
|
350
|
-
const p1 = (data[i] & 0xF0) >> 4;
|
|
351
|
-
const p2 = (data[i + 1] & 0xF0) >> 4;
|
|
352
|
-
packed[i / 2] = (p1 << 4) | p2;
|
|
353
|
-
}
|
|
354
|
-
return packed;
|
|
355
|
-
}
|
|
356
|
-
_unpack4Bit(packed, width, height) {
|
|
357
|
-
const length = width * height;
|
|
358
|
-
const data = new Uint8Array(length);
|
|
359
|
-
for (let i = 0; i < packed.length; i++) {
|
|
360
|
-
const byte = packed[i];
|
|
361
|
-
const p1 = (byte & 0xF0); // First pixel (already in high position)
|
|
362
|
-
const p2 = (byte & 0x0F) << 4; // Second pixel (move to high position)
|
|
363
|
-
data[i * 2] = p1;
|
|
364
|
-
data[i * 2 + 1] = p2;
|
|
365
|
-
}
|
|
366
|
-
return data;
|
|
367
|
-
}
|
|
368
172
|
}
|
|
@@ -8,6 +8,7 @@ export class DetectorLite {
|
|
|
8
8
|
height: any;
|
|
9
9
|
useGPU: any;
|
|
10
10
|
useLSH: any;
|
|
11
|
+
maxFeaturesPerBucket: any;
|
|
11
12
|
numOctaves: number;
|
|
12
13
|
/**
|
|
13
14
|
* Detecta características en una imagen en escala de grises
|
|
@@ -25,6 +26,11 @@ export class DetectorLite {
|
|
|
25
26
|
width: any;
|
|
26
27
|
height: any;
|
|
27
28
|
}[][];
|
|
29
|
+
_pyramidBuffers: {
|
|
30
|
+
width: any;
|
|
31
|
+
height: any;
|
|
32
|
+
temp: Float32Array<ArrayBuffer>;
|
|
33
|
+
} | undefined;
|
|
28
34
|
/**
|
|
29
35
|
* Aplica un filtro gaussiano binomial [1,4,6,4,1] - Optimizado
|
|
30
36
|
*/
|
|
@@ -15,7 +15,7 @@ import { computeLSH64, computeFullFREAK, packLSHIntoDescriptor } from "../utils/
|
|
|
15
15
|
const PYRAMID_MIN_SIZE = 4; // Restored to 4 for better small-scale detection
|
|
16
16
|
// PYRAMID_MAX_OCTAVE ya no es necesario, el límite lo da PYRAMID_MIN_SIZE
|
|
17
17
|
const NUM_BUCKETS_PER_DIMENSION = 10;
|
|
18
|
-
const
|
|
18
|
+
const DEFAULT_MAX_FEATURES_PER_BUCKET = 8;
|
|
19
19
|
const ORIENTATION_NUM_BINS = 36;
|
|
20
20
|
const FREAK_EXPANSION_FACTOR = 7.0;
|
|
21
21
|
// Global GPU mode flag
|
|
@@ -37,6 +37,7 @@ export class DetectorLite {
|
|
|
37
37
|
this.useGPU = options.useGPU !== undefined ? options.useGPU : globalUseGPU;
|
|
38
38
|
// Protocol V6 (Moonshot): 64-bit LSH is the standard descriptor format
|
|
39
39
|
this.useLSH = options.useLSH !== undefined ? options.useLSH : true;
|
|
40
|
+
this.maxFeaturesPerBucket = options.maxFeaturesPerBucket !== undefined ? options.maxFeaturesPerBucket : DEFAULT_MAX_FEATURES_PER_BUCKET;
|
|
40
41
|
let numOctaves = 0;
|
|
41
42
|
let w = width, h = height;
|
|
42
43
|
while (w >= PYRAMID_MIN_SIZE && h >= PYRAMID_MIN_SIZE) {
|
|
@@ -87,7 +88,7 @@ export class DetectorLite {
|
|
|
87
88
|
y: ext.y * scale + scale * 0.5 - 0.5,
|
|
88
89
|
scale: scale,
|
|
89
90
|
angle: ext.angle || 0,
|
|
90
|
-
descriptors: (this.useLSH && ext.lsh) ? ext.
|
|
91
|
+
descriptors: (this.useLSH && ext.lsh) ? ext.lsh : (ext.descriptors || [])
|
|
91
92
|
};
|
|
92
93
|
});
|
|
93
94
|
return { featurePoints, pyramid: pyramidImages };
|
|
@@ -118,22 +119,21 @@ export class DetectorLite {
|
|
|
118
119
|
console.warn("GPU pyramid failed, falling back to CPU:", e.message);
|
|
119
120
|
}
|
|
120
121
|
}
|
|
121
|
-
//
|
|
122
|
+
// Buffer management: Reuse arrays if dimensions match to reduce GC
|
|
123
|
+
if (!this._pyramidBuffers || this._pyramidBuffers.width !== width || this._pyramidBuffers.height !== height) {
|
|
124
|
+
this._pyramidBuffers = { width, height, temp: new Float32Array(width * height) };
|
|
125
|
+
}
|
|
122
126
|
const pyramid = [];
|
|
123
127
|
let currentData = data;
|
|
124
128
|
let currentWidth = width;
|
|
125
129
|
let currentHeight = height;
|
|
126
130
|
for (let i = 0; i < this.numOctaves; i++) {
|
|
127
131
|
const img1 = this._applyGaussianFilter(currentData, currentWidth, currentHeight);
|
|
128
|
-
// Only need the second blur if we are going to compute DoG with the NEXT layer
|
|
129
|
-
// or if we need it for this octave's DoG.
|
|
130
|
-
// Actually, for maxOctaves=1, we only need img1 and maybe img2 for one DoG layer.
|
|
131
132
|
const img2 = this._applyGaussianFilter(img1.data, currentWidth, currentHeight);
|
|
132
133
|
pyramid.push([
|
|
133
134
|
{ data: img1.data, width: currentWidth, height: currentHeight },
|
|
134
135
|
{ data: img2.data, width: currentWidth, height: currentHeight }
|
|
135
136
|
]);
|
|
136
|
-
// Downsample para siguiente octava - Only if we have more octaves to go
|
|
137
137
|
if (i < this.numOctaves - 1) {
|
|
138
138
|
const downsampled = this._downsample(img2.data, currentWidth, currentHeight);
|
|
139
139
|
currentData = downsampled.data;
|
|
@@ -148,7 +148,7 @@ export class DetectorLite {
|
|
|
148
148
|
*/
|
|
149
149
|
_applyGaussianFilter(data, width, height) {
|
|
150
150
|
const output = new Float32Array(width * height);
|
|
151
|
-
const temp = new Float32Array(width * height);
|
|
151
|
+
const temp = this._pyramidBuffers?.temp || new Float32Array(width * height);
|
|
152
152
|
const k0 = 0.0625, k1 = 0.25, k2 = 0.375; // 1/16, 4/16, 6/16
|
|
153
153
|
const w1 = width - 1;
|
|
154
154
|
// Horizontal pass - Speed optimized with manual border handling
|
|
@@ -305,7 +305,7 @@ export class DetectorLite {
|
|
|
305
305
|
*/
|
|
306
306
|
_applyPrune(extremas) {
|
|
307
307
|
const nBuckets = NUM_BUCKETS_PER_DIMENSION;
|
|
308
|
-
const nFeatures =
|
|
308
|
+
const nFeatures = this.maxFeaturesPerBucket;
|
|
309
309
|
// Agrupar por buckets
|
|
310
310
|
const buckets = [];
|
|
311
311
|
for (let i = 0; i < nBuckets * nBuckets; i++) {
|
|
@@ -3,12 +3,10 @@ import { compute as hammingCompute } from "./hamming-distance.js";
|
|
|
3
3
|
import { computeHoughMatches } from "./hough.js";
|
|
4
4
|
import { computeHomography } from "./ransacHomography.js";
|
|
5
5
|
import { multiplyPointHomographyInhomogenous, matrixInverse33 } from "../utils/geometry.js";
|
|
6
|
-
import { FourierEncoder } from "../utils/fourier-encoder.js";
|
|
7
|
-
const encoder = new FourierEncoder(4);
|
|
8
6
|
const INLIER_THRESHOLD = 5.0; // Tightened from 10 to 5 for better precision
|
|
9
7
|
const MIN_NUM_INLIERS = 8; // Restored to 8
|
|
10
8
|
const CLUSTER_MAX_POP = 20;
|
|
11
|
-
const HAMMING_THRESHOLD = 0.
|
|
9
|
+
const HAMMING_THRESHOLD = 0.85; // Relaxed from 0.8 back to 0.85
|
|
12
10
|
// match list of querpoints against pre-built list of keyframes
|
|
13
11
|
const match = ({ keyframe, querypoints, querywidth, queryheight, debugMode }) => {
|
|
14
12
|
let debugExtra = {};
|
|
@@ -96,7 +94,7 @@ const match = ({ keyframe, querypoints, querywidth, queryheight, debugMode }) =>
|
|
|
96
94
|
return { debugExtra };
|
|
97
95
|
// Second pass with homography guided matching
|
|
98
96
|
const HInv = matrixInverse33(H, 0.00001);
|
|
99
|
-
const dThreshold2 =
|
|
97
|
+
const dThreshold2 = 100; // 10 * 10
|
|
100
98
|
const matches2 = [];
|
|
101
99
|
const hi00 = HInv[0], hi01 = HInv[1], hi02 = HInv[2];
|
|
102
100
|
const hi10 = HInv[3], hi11 = HInv[4], hi12 = HInv[5];
|
|
@@ -115,29 +113,14 @@ const match = ({ keyframe, querypoints, querywidth, queryheight, debugMode }) =>
|
|
|
115
113
|
const col = querypoint.maxima ? kmax : kmin;
|
|
116
114
|
if (!col)
|
|
117
115
|
continue;
|
|
118
|
-
const cx = col.x, cy = col.y, cd = col.d
|
|
116
|
+
const cx = col.x, cy = col.y, cd = col.d;
|
|
119
117
|
const qDesc = querypoint.descriptors;
|
|
120
|
-
// Fourier encoding of the mapped point (where it SHOULD be in the keyframe)
|
|
121
|
-
const qFourier = encoder.encode(mapX / keyframe.w, mapY / keyframe.h);
|
|
122
118
|
for (let k = 0, clen = cx.length; k < clen; k++) {
|
|
123
119
|
const dx = cx[k] - mapX;
|
|
124
120
|
const dy = cy[k] - mapY;
|
|
125
121
|
const d2 = dx * dx + dy * dy;
|
|
126
122
|
if (d2 > dThreshold2)
|
|
127
123
|
continue;
|
|
128
|
-
// 🚀 MOONSHOT: Fourier Spatial Harmony Check
|
|
129
|
-
// We check if the stored point's Fourier signature matches its predicted position
|
|
130
|
-
let fourierSim = 0;
|
|
131
|
-
if (cf) {
|
|
132
|
-
for (let fidx = 0; fidx < 16; fidx++) {
|
|
133
|
-
fourierSim += (cf[k * 16 + fidx] / 127) * qFourier[fidx];
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
else {
|
|
137
|
-
fourierSim = 16; // Backward compatibility
|
|
138
|
-
}
|
|
139
|
-
if (fourierSim < 8)
|
|
140
|
-
continue; // Reject if spatially dissonant (low harmonic match)
|
|
141
124
|
const d = hammingCompute({ v1: cd, v1Offset: k * descSize, v2: qDesc });
|
|
142
125
|
if (d < bestD1) {
|
|
143
126
|
bestD2 = bestD1;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
export declare const CURRENT_VERSION = 7;
|
|
2
|
+
/**
|
|
3
|
+
* Morton Order calculation for spatial sorting
|
|
4
|
+
*/
|
|
5
|
+
export declare function getMorton(x: number, y: number): number;
|
|
6
|
+
/**
|
|
7
|
+
* Packs 8-bit image data into 4-bit packed data
|
|
8
|
+
*/
|
|
9
|
+
export declare function pack4Bit(data: Uint8Array): Uint8Array;
|
|
10
|
+
/**
|
|
11
|
+
* Unpacks 4-bit data back to 8-bit image data
|
|
12
|
+
*/
|
|
13
|
+
export declare function unpack4Bit(packed: Uint8Array, width: number, height: number): Uint8Array;
|
|
14
|
+
/**
|
|
15
|
+
* Columnarizes point data for efficient storage and transfer
|
|
16
|
+
*/
|
|
17
|
+
export declare function columnarize(points: any[], tree: any, width: number, height: number): {
|
|
18
|
+
x: Uint16Array<ArrayBuffer>;
|
|
19
|
+
y: Uint16Array<ArrayBuffer>;
|
|
20
|
+
a: Int16Array<ArrayBuffer>;
|
|
21
|
+
s: Uint8Array<ArrayBuffer>;
|
|
22
|
+
d: Uint32Array<ArrayBuffer>;
|
|
23
|
+
t: any;
|
|
24
|
+
};
|
|
25
|
+
/**
|
|
26
|
+
* Compacts hierarchical clustering tree into a minimal array structure
|
|
27
|
+
*/
|
|
28
|
+
export declare function compactTree(node: any): any;
|
|
29
|
+
/**
|
|
30
|
+
* Expands a compacted tree back into an object structure
|
|
31
|
+
*/
|
|
32
|
+
export declare function expandTree(node: any): any;
|
|
33
|
+
/**
|
|
34
|
+
* Deserializes and normalizes .taar data from a buffer
|
|
35
|
+
*/
|
|
36
|
+
export declare function decodeTaar(buffer: ArrayBuffer | Uint8Array): {
|
|
37
|
+
version: any;
|
|
38
|
+
dataList: any;
|
|
39
|
+
};
|
|
40
|
+
/**
|
|
41
|
+
* Serializes target data into a .taar binary buffer
|
|
42
|
+
*/
|
|
43
|
+
export declare function encodeTaar(dataList: any[]): Uint8Array<ArrayBuffer>;
|