@srsergio/taptapp-ar 1.0.9 → 1.0.10

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 (122) hide show
  1. package/dist/compiler/controller.d.ts +15 -22
  2. package/dist/compiler/controller.js +73 -92
  3. package/dist/compiler/detector/crop-detector.d.ts +20 -51
  4. package/dist/compiler/detector/crop-detector.js +21 -15
  5. package/dist/compiler/input-loader.d.ts +15 -17
  6. package/dist/compiler/input-loader.js +58 -76
  7. package/dist/compiler/matching/hamming-distance.js +4 -4
  8. package/dist/compiler/matching/matcher.js +2 -2
  9. package/dist/compiler/matching/matching.d.ts +2 -16
  10. package/dist/compiler/matching/matching.js +72 -60
  11. package/dist/compiler/offline-compiler.d.ts +9 -29
  12. package/dist/compiler/offline-compiler.js +38 -72
  13. package/dist/compiler/three.js +0 -4
  14. package/dist/compiler/tracker/tracker.d.ts +26 -12
  15. package/dist/compiler/tracker/tracker.js +158 -259
  16. package/package.json +1 -1
  17. package/src/compiler/controller.js +71 -93
  18. package/src/compiler/detector/crop-detector.js +26 -15
  19. package/src/compiler/input-loader.js +62 -88
  20. package/src/compiler/matching/hamming-distance.js +4 -4
  21. package/src/compiler/matching/hough.js +1 -1
  22. package/src/compiler/matching/matcher.js +2 -2
  23. package/src/compiler/matching/matching.js +80 -72
  24. package/src/compiler/offline-compiler.js +38 -75
  25. package/src/compiler/three.js +0 -4
  26. package/src/compiler/tracker/tracker.js +183 -283
  27. package/dist/compiler/compiler-base.d.ts +0 -8
  28. package/dist/compiler/compiler-base.js +0 -179
  29. package/dist/compiler/compiler.d.ts +0 -9
  30. package/dist/compiler/compiler.js +0 -24
  31. package/dist/compiler/compiler.worker.d.ts +0 -1
  32. package/dist/compiler/compiler.worker.js +0 -28
  33. package/dist/compiler/detector/detector.d.ts +0 -97
  34. package/dist/compiler/detector/detector.js +0 -1042
  35. package/dist/compiler/detector/kernels/cpu/binomialFilter.d.ts +0 -6
  36. package/dist/compiler/detector/kernels/cpu/binomialFilter.js +0 -50
  37. package/dist/compiler/detector/kernels/cpu/buildExtremas.d.ts +0 -6
  38. package/dist/compiler/detector/kernels/cpu/buildExtremas.js +0 -89
  39. package/dist/compiler/detector/kernels/cpu/computeExtremaAngles.d.ts +0 -7
  40. package/dist/compiler/detector/kernels/cpu/computeExtremaAngles.js +0 -79
  41. package/dist/compiler/detector/kernels/cpu/computeExtremaFreak.d.ts +0 -6
  42. package/dist/compiler/detector/kernels/cpu/computeExtremaFreak.js +0 -68
  43. package/dist/compiler/detector/kernels/cpu/computeFreakDescriptors.d.ts +0 -6
  44. package/dist/compiler/detector/kernels/cpu/computeFreakDescriptors.js +0 -57
  45. package/dist/compiler/detector/kernels/cpu/computeLocalization.d.ts +0 -6
  46. package/dist/compiler/detector/kernels/cpu/computeLocalization.js +0 -50
  47. package/dist/compiler/detector/kernels/cpu/computeOrientationHistograms.d.ts +0 -6
  48. package/dist/compiler/detector/kernels/cpu/computeOrientationHistograms.js +0 -100
  49. package/dist/compiler/detector/kernels/cpu/downsampleBilinear.d.ts +0 -6
  50. package/dist/compiler/detector/kernels/cpu/downsampleBilinear.js +0 -29
  51. package/dist/compiler/detector/kernels/cpu/extremaReduction.d.ts +0 -6
  52. package/dist/compiler/detector/kernels/cpu/extremaReduction.js +0 -50
  53. package/dist/compiler/detector/kernels/cpu/fakeShader.d.ts +0 -20
  54. package/dist/compiler/detector/kernels/cpu/fakeShader.js +0 -80
  55. package/dist/compiler/detector/kernels/cpu/index.d.ts +0 -1
  56. package/dist/compiler/detector/kernels/cpu/index.js +0 -25
  57. package/dist/compiler/detector/kernels/cpu/prune.d.ts +0 -7
  58. package/dist/compiler/detector/kernels/cpu/prune.js +0 -62
  59. package/dist/compiler/detector/kernels/cpu/smoothHistograms.d.ts +0 -6
  60. package/dist/compiler/detector/kernels/cpu/smoothHistograms.js +0 -47
  61. package/dist/compiler/detector/kernels/cpu/upsampleBilinear.d.ts +0 -6
  62. package/dist/compiler/detector/kernels/cpu/upsampleBilinear.js +0 -43
  63. package/dist/compiler/detector/kernels/index.d.ts +0 -1
  64. package/dist/compiler/detector/kernels/index.js +0 -2
  65. package/dist/compiler/detector/kernels/webgl/binomialFilter.d.ts +0 -6
  66. package/dist/compiler/detector/kernels/webgl/binomialFilter.js +0 -67
  67. package/dist/compiler/detector/kernels/webgl/buildExtremas.d.ts +0 -6
  68. package/dist/compiler/detector/kernels/webgl/buildExtremas.js +0 -101
  69. package/dist/compiler/detector/kernels/webgl/computeExtremaAngles.d.ts +0 -6
  70. package/dist/compiler/detector/kernels/webgl/computeExtremaAngles.js +0 -78
  71. package/dist/compiler/detector/kernels/webgl/computeExtremaFreak.d.ts +0 -6
  72. package/dist/compiler/detector/kernels/webgl/computeExtremaFreak.js +0 -86
  73. package/dist/compiler/detector/kernels/webgl/computeFreakDescriptors.d.ts +0 -6
  74. package/dist/compiler/detector/kernels/webgl/computeFreakDescriptors.js +0 -52
  75. package/dist/compiler/detector/kernels/webgl/computeLocalization.d.ts +0 -6
  76. package/dist/compiler/detector/kernels/webgl/computeLocalization.js +0 -58
  77. package/dist/compiler/detector/kernels/webgl/computeOrientationHistograms.d.ts +0 -6
  78. package/dist/compiler/detector/kernels/webgl/computeOrientationHistograms.js +0 -116
  79. package/dist/compiler/detector/kernels/webgl/downsampleBilinear.d.ts +0 -6
  80. package/dist/compiler/detector/kernels/webgl/downsampleBilinear.js +0 -46
  81. package/dist/compiler/detector/kernels/webgl/extremaReduction.d.ts +0 -6
  82. package/dist/compiler/detector/kernels/webgl/extremaReduction.js +0 -48
  83. package/dist/compiler/detector/kernels/webgl/index.d.ts +0 -1
  84. package/dist/compiler/detector/kernels/webgl/index.js +0 -25
  85. package/dist/compiler/detector/kernels/webgl/smoothHistograms.d.ts +0 -6
  86. package/dist/compiler/detector/kernels/webgl/smoothHistograms.js +0 -49
  87. package/dist/compiler/detector/kernels/webgl/upsampleBilinear.d.ts +0 -6
  88. package/dist/compiler/detector/kernels/webgl/upsampleBilinear.js +0 -56
  89. package/dist/compiler/tensorflow-setup.d.ts +0 -6
  90. package/dist/compiler/tensorflow-setup.js +0 -99
  91. package/src/compiler/compiler-base.js +0 -210
  92. package/src/compiler/compiler.js +0 -25
  93. package/src/compiler/compiler.worker.js +0 -30
  94. package/src/compiler/detector/detector.js +0 -1119
  95. package/src/compiler/detector/kernels/cpu/binomialFilter.js +0 -58
  96. package/src/compiler/detector/kernels/cpu/buildExtremas.js +0 -108
  97. package/src/compiler/detector/kernels/cpu/computeExtremaAngles.js +0 -91
  98. package/src/compiler/detector/kernels/cpu/computeExtremaFreak.js +0 -92
  99. package/src/compiler/detector/kernels/cpu/computeFreakDescriptors.js +0 -68
  100. package/src/compiler/detector/kernels/cpu/computeLocalization.js +0 -67
  101. package/src/compiler/detector/kernels/cpu/computeOrientationHistograms.js +0 -124
  102. package/src/compiler/detector/kernels/cpu/downsampleBilinear.js +0 -33
  103. package/src/compiler/detector/kernels/cpu/extremaReduction.js +0 -53
  104. package/src/compiler/detector/kernels/cpu/fakeShader.js +0 -88
  105. package/src/compiler/detector/kernels/cpu/index.js +0 -26
  106. package/src/compiler/detector/kernels/cpu/prune.js +0 -78
  107. package/src/compiler/detector/kernels/cpu/smoothHistograms.js +0 -57
  108. package/src/compiler/detector/kernels/cpu/upsampleBilinear.js +0 -51
  109. package/src/compiler/detector/kernels/index.js +0 -2
  110. package/src/compiler/detector/kernels/webgl/binomialFilter.js +0 -72
  111. package/src/compiler/detector/kernels/webgl/buildExtremas.js +0 -109
  112. package/src/compiler/detector/kernels/webgl/computeExtremaAngles.js +0 -82
  113. package/src/compiler/detector/kernels/webgl/computeExtremaFreak.js +0 -105
  114. package/src/compiler/detector/kernels/webgl/computeFreakDescriptors.js +0 -56
  115. package/src/compiler/detector/kernels/webgl/computeLocalization.js +0 -70
  116. package/src/compiler/detector/kernels/webgl/computeOrientationHistograms.js +0 -129
  117. package/src/compiler/detector/kernels/webgl/downsampleBilinear.js +0 -50
  118. package/src/compiler/detector/kernels/webgl/extremaReduction.js +0 -50
  119. package/src/compiler/detector/kernels/webgl/index.js +0 -26
  120. package/src/compiler/detector/kernels/webgl/smoothHistograms.js +0 -53
  121. package/src/compiler/detector/kernels/webgl/upsampleBilinear.js +0 -62
  122. package/src/compiler/tensorflow-setup.js +0 -116
@@ -1,88 +1,70 @@
1
- import * as tf from "@tensorflow/tfjs";
2
- // More efficient implementation for tf.browser.fromPixels
3
- // original implementation: /node_modules/@tensorflow/tfjs-backend-webgl/src/kernels/FromPixels.ts
4
- //
5
- // This implementation return grey scale instead of RGBA in the orignal implementation
1
+ /**
2
+ * InputLoader - Maneja la carga de imágenes y video sin TensorFlow
3
+ */
6
4
  class InputLoader {
7
5
  constructor(width, height) {
8
6
  this.width = width;
9
7
  this.height = height;
10
- this.texShape = [height, width];
11
- const context = document.createElement("canvas").getContext("2d");
12
- context.canvas.width = width;
13
- context.canvas.height = height;
14
- this.context = context;
15
- this.program = this.buildProgram(width, height);
16
- const backend = tf.backend();
17
- //this.tempPixelHandle = backend.makeTensorInfo(this.texShape, 'int32');
18
- this.tempPixelHandle = backend.makeTensorInfo(this.texShape, "float32");
19
- // warning!!!
20
- // usage type should be TextureUsage.PIXELS, but tfjs didn't export this enum type, so we hard-coded 2 here
21
- // i.e. backend.texData.get(tempPixelHandle.dataId).usage = TextureUsage.PIXELS;
22
- backend.texData.get(this.tempPixelHandle.dataId).usage = 2;
23
- }
24
- // old method
25
- _loadInput(input) {
26
- return tf.tidy(() => {
27
- let inputImage = tf.browser.fromPixels(input);
28
- inputImage = inputImage.mean(2);
29
- return inputImage;
30
- });
8
+ this.grayscaleBuffer = new Uint8Array(width * height);
9
+ if (typeof document !== "undefined") {
10
+ const canvas = document.createElement("canvas");
11
+ canvas.width = width;
12
+ canvas.height = height;
13
+ this.context = canvas.getContext("2d", { willReadFrequently: true, alpha: false });
14
+ }
31
15
  }
32
- // input is instance of HTMLVideoElement or HTMLImageElement
16
+ /**
17
+ * Carga una imagen o video y devuelve los datos en escala de grises
18
+ * @param {HTMLVideoElement|HTMLImageElement|ImageData|Uint8Array} input - La fuente de entrada
19
+ * @returns {Uint8Array} Datos de imagen en escala de grises (width * height)
20
+ */
33
21
  loadInput(input) {
34
- const context = this.context;
35
- context.clearRect(0, 0, this.context.canvas.width, this.context.canvas.height);
36
- const isInputRotated = input.width === this.height && input.height === this.width;
37
- if (isInputRotated) {
38
- // rotate 90 degree and draw
39
- let x = this.context.canvas.width / 2;
40
- let y = this.context.canvas.height / 2;
41
- let angleInDegrees = 90;
42
- context.save(); // save the current context state
43
- context.translate(x, y); // move the context origin to the center of the image
44
- context.rotate((angleInDegrees * Math.PI) / 180); // rotate the context
45
- // draw the image with its center at the origin
46
- context.drawImage(input, -input.width / 2, -input.height / 2);
47
- context.restore(); // restore the context to its original state
22
+ // Si ya es un Uint8Array de escala de grises, lo devolvemos
23
+ if (input instanceof Uint8Array && input.length === this.width * this.height) {
24
+ return input;
48
25
  }
49
- else {
50
- this.context.drawImage(input, 0, 0, input.width, input.height);
26
+ // Si es ImageData, convertimos a escala de grises directamente
27
+ if (typeof ImageData !== "undefined" && input instanceof ImageData) {
28
+ this._convertToGrayscale(input.data, input.width, input.height);
29
+ return this.grayscaleBuffer;
51
30
  }
52
- const backend = tf.backend();
53
- backend.gpgpu.uploadPixelDataToTexture(backend.getTexture(this.tempPixelHandle.dataId), this.context.canvas);
54
- //const res = backend.compileAndRun(this.program, [this.tempPixelHandle]);
55
- const res = this._compileAndRun(this.program, [this.tempPixelHandle]);
56
- //const res = this._runWebGLProgram(this.program, [this.tempPixelHandle], 'float32');
57
- //backend.disposeData(tempPixelHandle.dataId);
58
- return res;
59
- }
60
- buildProgram(width, height) {
61
- const textureMethod = tf.env().getNumber("WEBGL_VERSION") === 2 ? "texture" : "texture2D";
62
- const program = {
63
- variableNames: ["A"],
64
- outputShape: this.texShape,
65
- userCode: `
66
- void main() {
67
- ivec2 coords = getOutputCoords();
68
- int texR = coords[0];
69
- int texC = coords[1];
70
- vec2 uv = (vec2(texC, texR) + halfCR) / vec2(${width}.0, ${height}.0);
71
-
72
- vec4 values = ${textureMethod}(A, uv);
73
- setOutput((0.299 * values.r + 0.587 * values.g + 0.114 * values.b) * 255.0);
74
- }
75
- `,
76
- };
77
- return program;
78
- }
79
- _compileAndRun(program, inputs) {
80
- const outInfo = tf.backend().compileAndRun(program, inputs);
81
- return tf.engine().makeTensor(outInfo.dataId, outInfo.shape, outInfo.dtype);
31
+ // En el navegador, usamos canvas para procesar video/imágenes
32
+ if (this.context) {
33
+ this.context.clearRect(0, 0, this.width, this.height);
34
+ const isInputRotated = input.width === this.height && input.height === this.width;
35
+ if (isInputRotated) {
36
+ this.context.save();
37
+ this.context.translate(this.width / 2, this.height / 2);
38
+ this.context.rotate(Math.PI / 2);
39
+ this.context.drawImage(input, -input.width / 2, -input.height / 2);
40
+ this.context.restore();
41
+ }
42
+ else {
43
+ this.context.drawImage(input, 0, 0, this.width, this.height);
44
+ }
45
+ const imageData = this.context.getImageData(0, 0, this.width, this.height);
46
+ this._convertToGrayscale(imageData.data, this.width, this.height);
47
+ return this.grayscaleBuffer;
48
+ }
49
+ // Fallback para Node.js o entornos sin DOM
50
+ if (input.data && input.data instanceof Uint8Array) {
51
+ this._convertToGrayscale(input.data, input.width || this.width, input.height || this.height);
52
+ return this.grayscaleBuffer;
53
+ }
54
+ throw new Error("Input no soportado o entorno sin Canvas");
82
55
  }
83
- _runWebGLProgram(program, inputs, outputType) {
84
- const outInfo = tf.backend().runWebGLProgram(program, inputs, outputType);
85
- return tf.engine().makeTensor(outInfo.dataId, outInfo.shape, outInfo.dtype);
56
+ /**
57
+ * Convierte datos RGBA a escala de grises optimizada (reutilizando buffer)
58
+ */
59
+ _convertToGrayscale(rgbaData, width, height) {
60
+ const grayscale = this.grayscaleBuffer;
61
+ const len = (width * height);
62
+ // Optimized loop with bitwise ops
63
+ for (let i = 0; i < len; i++) {
64
+ const offset = i << 2;
65
+ // Formula de luminosidad estándar: 0.299R + 0.587G + 0.114B (scaled by 256)
66
+ grayscale[i] = (rgbaData[offset] * 77 + rgbaData[offset + 1] * 150 + rgbaData[offset + 2] * 29) >> 8;
67
+ }
86
68
  }
87
69
  }
88
70
  export { InputLoader };
@@ -9,11 +9,11 @@ for (let i = 0; i < 256; i++) {
9
9
  BIT_COUNT_8[i] = c;
10
10
  }
11
11
  const compute = (options) => {
12
- const { v1, v2 } = options;
12
+ const { v1, v2, v1Offset = 0, v2Offset = 0 } = options;
13
13
  let d = 0;
14
- const len = v1.length;
15
- for (let i = 0; i < len; i++) {
16
- d += BIT_COUNT_8[v1[i] ^ v2[i]];
14
+ // FREAK descriptors are 84 bytes
15
+ for (let i = 0; i < 84; i++) {
16
+ d += BIT_COUNT_8[v1[v1Offset + i] ^ v2[v2Offset + i]];
17
17
  }
18
18
  return d;
19
19
  };
@@ -37,8 +37,8 @@ class Matcher {
37
37
  y: querypoint.y,
38
38
  });
39
39
  worldCoords.push({
40
- x: (keypoint.x + 0.5) / keyframe.scale,
41
- y: (keypoint.y + 0.5) / keyframe.scale,
40
+ x: (keypoint.x + 0.5) / (keyframe.s || keyframe.scale || 1.0),
41
+ y: (keypoint.y + 0.5) / (keyframe.s || keyframe.scale || 1.0),
42
42
  z: 0,
43
43
  });
44
44
  }
@@ -6,14 +6,6 @@ export function match({ keyframe, querypoints, querywidth, queryheight, debugMod
6
6
  debugMode: any;
7
7
  }): {
8
8
  debugExtra: {
9
- matches: {
10
- querypoint: any;
11
- keypoint: {
12
- x: any;
13
- y: any;
14
- angle: any;
15
- };
16
- }[];
17
9
  houghMatches: any[];
18
10
  inlierMatches: any[];
19
11
  matches2: {
@@ -22,6 +14,7 @@ export function match({ keyframe, querypoints, querywidth, queryheight, debugMod
22
14
  x: any;
23
15
  y: any;
24
16
  angle: any;
17
+ scale: any;
25
18
  };
26
19
  }[];
27
20
  houghMatches2: any[];
@@ -33,14 +26,6 @@ export function match({ keyframe, querypoints, querywidth, queryheight, debugMod
33
26
  H: number[];
34
27
  matches: any[];
35
28
  debugExtra: {
36
- matches: {
37
- querypoint: any;
38
- keypoint: {
39
- x: any;
40
- y: any;
41
- angle: any;
42
- };
43
- }[];
44
29
  houghMatches: any[];
45
30
  inlierMatches: any[];
46
31
  matches2: {
@@ -49,6 +34,7 @@ export function match({ keyframe, querypoints, querywidth, queryheight, debugMod
49
34
  x: any;
50
35
  y: any;
51
36
  angle: any;
37
+ scale: any;
52
38
  };
53
39
  }[];
54
40
  houghMatches2: any[];
@@ -12,16 +12,17 @@ const HAMMING_THRESHOLD = 0.7;
12
12
  const match = ({ keyframe, querypoints, querywidth, queryheight, debugMode }) => {
13
13
  let debugExtra = {};
14
14
  const matches = [];
15
- for (let j = 0; j < querypoints.length; j++) {
15
+ const qlen = querypoints.length;
16
+ const kmax = keyframe.max;
17
+ const kmin = keyframe.min;
18
+ for (let j = 0; j < qlen; j++) {
16
19
  const querypoint = querypoints[j];
17
- const col = querypoint.maxima ? keyframe.max : keyframe.min;
20
+ const col = querypoint.maxima ? kmax : kmin;
18
21
  if (!col || col.x.length === 0)
19
22
  continue;
20
23
  const rootNode = col.t;
21
24
  const keypointIndexes = [];
22
- const queue = new TinyQueue([], (a1, a2) => {
23
- return a1.d - a2.d;
24
- });
25
+ const queue = new TinyQueue([], (a1, a2) => a1.d - a2.d);
25
26
  // query potential candidates from the columnar tree
26
27
  _query({
27
28
  node: rootNode,
@@ -34,11 +35,12 @@ const match = ({ keyframe, querypoints, querywidth, queryheight, debugMode }) =>
34
35
  let bestIndex = -1;
35
36
  let bestD1 = Number.MAX_SAFE_INTEGER;
36
37
  let bestD2 = Number.MAX_SAFE_INTEGER;
38
+ const qDesc = querypoint.descriptors;
39
+ const cDesc = col.d;
37
40
  for (let k = 0; k < keypointIndexes.length; k++) {
38
41
  const idx = keypointIndexes[k];
39
- // Access descriptor directly from binary buffer (Zero-copy)
40
- const keypointDescriptor = col.d.subarray(idx * 84, (idx + 1) * 84);
41
- const d = hammingCompute({ v1: keypointDescriptor, v2: querypoint.descriptors });
42
+ // Use offsets to avoid subarray allocation
43
+ const d = hammingCompute({ v1: cDesc, v1Offset: idx * 84, v2: qDesc });
42
44
  if (d < bestD1) {
43
45
  bestD2 = bestD1;
44
46
  bestD1 = d;
@@ -49,32 +51,29 @@ const match = ({ keyframe, querypoints, querywidth, queryheight, debugMode }) =>
49
51
  }
50
52
  }
51
53
  if (bestIndex !== -1 &&
52
- (bestD2 === Number.MAX_SAFE_INTEGER || (1.0 * bestD1) / bestD2 < HAMMING_THRESHOLD)) {
54
+ (bestD2 === Number.MAX_SAFE_INTEGER || (bestD1 / bestD2) < HAMMING_THRESHOLD)) {
53
55
  matches.push({
54
56
  querypoint,
55
57
  keypoint: {
56
58
  x: col.x[bestIndex],
57
59
  y: col.y[bestIndex],
58
- angle: col.a[bestIndex]
60
+ angle: col.a[bestIndex],
61
+ scale: col.s ? col.s[bestIndex] : keyframe.s
59
62
  }
60
63
  });
61
64
  }
62
65
  }
63
- if (debugMode) {
64
- debugExtra.matches = matches;
65
- }
66
66
  if (matches.length < MIN_NUM_INLIERS)
67
67
  return { debugExtra };
68
68
  const houghMatches = computeHoughMatches({
69
- keywidth: keyframe.w, // Protocol V3 uses .w, .h
69
+ keywidth: keyframe.w,
70
70
  keyheight: keyframe.h,
71
71
  querywidth,
72
72
  queryheight,
73
73
  matches,
74
74
  });
75
- if (debugMode) {
75
+ if (debugMode)
76
76
  debugExtra.houghMatches = houghMatches;
77
- }
78
77
  const H = computeHomography({
79
78
  srcPoints: houghMatches.map((m) => [m.keypoint.x, m.keypoint.y]),
80
79
  dstPoints: houghMatches.map((m) => [m.querypoint.x, m.querypoint.y]),
@@ -87,32 +86,40 @@ const match = ({ keyframe, querypoints, querywidth, queryheight, debugMode }) =>
87
86
  matches: houghMatches,
88
87
  threshold: INLIER_THRESHOLD,
89
88
  });
90
- if (debugMode) {
89
+ if (debugMode)
91
90
  debugExtra.inlierMatches = inlierMatches;
92
- }
93
91
  if (inlierMatches.length < MIN_NUM_INLIERS)
94
92
  return { debugExtra };
95
93
  // Second pass with homography guided matching
96
94
  const HInv = matrixInverse33(H, 0.00001);
97
- const dThreshold2 = 10 * 10;
95
+ const dThreshold2 = 100; // 10 * 10
98
96
  const matches2 = [];
99
- for (let j = 0; j < querypoints.length; j++) {
97
+ const hi00 = HInv[0], hi01 = HInv[1], hi02 = HInv[2];
98
+ const hi10 = HInv[3], hi11 = HInv[4], hi12 = HInv[5];
99
+ const hi20 = HInv[6], hi21 = HInv[7], hi22 = HInv[8];
100
+ for (let j = 0; j < qlen; j++) {
100
101
  const querypoint = querypoints[j];
101
- const mapquerypoint = multiplyPointHomographyInhomogenous([querypoint.x, querypoint.y], HInv);
102
+ const qx = querypoint.x, qy = querypoint.y;
103
+ // Inline multiplyPointHomographyInhomogenous
104
+ const uz = (qx * hi20) + (qy * hi21) + hi22;
105
+ const invZ = 1.0 / uz;
106
+ const mapX = ((qx * hi00) + (qy * hi01) + hi02) * invZ;
107
+ const mapY = ((qx * hi10) + (qy * hi11) + hi12) * invZ;
102
108
  let bestIndex = -1;
103
109
  let bestD1 = Number.MAX_SAFE_INTEGER;
104
110
  let bestD2 = Number.MAX_SAFE_INTEGER;
105
- const col = querypoint.maxima ? keyframe.max : keyframe.min;
111
+ const col = querypoint.maxima ? kmax : kmin;
106
112
  if (!col)
107
113
  continue;
108
- for (let k = 0; k < col.x.length; k++) {
109
- const dx = col.x[k] - mapquerypoint[0];
110
- const dy = col.y[k] - mapquerypoint[1];
114
+ const cx = col.x, cy = col.y, cd = col.d;
115
+ const qDesc = querypoint.descriptors;
116
+ for (let k = 0, clen = cx.length; k < clen; k++) {
117
+ const dx = cx[k] - mapX;
118
+ const dy = cy[k] - mapY;
111
119
  const d2 = dx * dx + dy * dy;
112
120
  if (d2 > dThreshold2)
113
121
  continue;
114
- const keypointDescriptor = col.d.subarray(k * 84, (k + 1) * 84);
115
- const d = hammingCompute({ v1: keypointDescriptor, v2: querypoint.descriptors });
122
+ const d = hammingCompute({ v1: cd, v1Offset: k * 84, v2: qDesc });
116
123
  if (d < bestD1) {
117
124
  bestD2 = bestD1;
118
125
  bestD1 = d;
@@ -123,20 +130,20 @@ const match = ({ keyframe, querypoints, querywidth, queryheight, debugMode }) =>
123
130
  }
124
131
  }
125
132
  if (bestIndex !== -1 &&
126
- (bestD2 === Number.MAX_SAFE_INTEGER || (1.0 * bestD1) / bestD2 < HAMMING_THRESHOLD)) {
133
+ (bestD2 === Number.MAX_SAFE_INTEGER || (bestD1 / bestD2) < HAMMING_THRESHOLD)) {
127
134
  matches2.push({
128
135
  querypoint,
129
136
  keypoint: {
130
137
  x: col.x[bestIndex],
131
138
  y: col.y[bestIndex],
132
- angle: col.a[bestIndex]
139
+ angle: col.a[bestIndex],
140
+ scale: col.s ? col.s[bestIndex] : keyframe.s
133
141
  }
134
142
  });
135
143
  }
136
144
  }
137
- if (debugMode) {
145
+ if (debugMode)
138
146
  debugExtra.matches2 = matches2;
139
- }
140
147
  const houghMatches2 = computeHoughMatches({
141
148
  keywidth: keyframe.w,
142
149
  keyheight: keyframe.h,
@@ -144,9 +151,8 @@ const match = ({ keyframe, querypoints, querywidth, queryheight, debugMode }) =>
144
151
  queryheight,
145
152
  matches: matches2,
146
153
  });
147
- if (debugMode) {
154
+ if (debugMode)
148
155
  debugExtra.houghMatches2 = houghMatches2;
149
- }
150
156
  const H2 = computeHomography({
151
157
  srcPoints: houghMatches2.map((m) => [m.keypoint.x, m.keypoint.y]),
152
158
  dstPoints: houghMatches2.map((m) => [m.querypoint.x, m.querypoint.y]),
@@ -159,14 +165,12 @@ const match = ({ keyframe, querypoints, querywidth, queryheight, debugMode }) =>
159
165
  matches: houghMatches2,
160
166
  threshold: INLIER_THRESHOLD,
161
167
  });
162
- if (debugMode) {
168
+ if (debugMode)
163
169
  debugExtra.inlierMatches2 = inlierMatches2;
164
- }
165
170
  return { H: H2, matches: inlierMatches2, debugExtra };
166
171
  };
167
172
  const _query = ({ node, descriptors, querypoint, queue, keypointIndexes, numPop }) => {
168
173
  const isLeaf = node[0] === 1;
169
- const centerIdx = node[1];
170
174
  const childrenOrIndices = node[2];
171
175
  if (isLeaf) {
172
176
  for (let i = 0; i < childrenOrIndices.length; i++) {
@@ -174,48 +178,56 @@ const _query = ({ node, descriptors, querypoint, queue, keypointIndexes, numPop
174
178
  }
175
179
  return;
176
180
  }
177
- const distances = [];
178
- for (let i = 0; i < childrenOrIndices.length; i++) {
181
+ const qDesc = querypoint.descriptors;
182
+ let minD = Number.MAX_SAFE_INTEGER;
183
+ const clen = childrenOrIndices.length;
184
+ const distances = new Int32Array(clen);
185
+ for (let i = 0; i < clen; i++) {
179
186
  const childNode = childrenOrIndices[i];
180
187
  const cIdx = childNode[1];
181
188
  const d = hammingCompute({
182
- v1: descriptors.subarray(cIdx * 84, (cIdx + 1) * 84),
183
- v2: querypoint.descriptors,
189
+ v1: descriptors,
190
+ v1Offset: cIdx * 84,
191
+ v2: qDesc,
184
192
  });
185
- distances.push(d);
193
+ distances[i] = d;
194
+ if (d < minD)
195
+ minD = d;
186
196
  }
187
- let minD = Number.MAX_SAFE_INTEGER;
188
- for (let i = 0; i < childrenOrIndices.length; i++) {
189
- minD = Math.min(minD, distances[i]);
190
- }
191
- for (let i = 0; i < childrenOrIndices.length; i++) {
192
- if (distances[i] !== minD) {
193
- queue.push({ node: childrenOrIndices[i], d: distances[i] });
197
+ for (let i = 0; i < clen; i++) {
198
+ const dist = distances[i];
199
+ if (dist !== minD) {
200
+ queue.push({ node: childrenOrIndices[i], d: dist });
194
201
  }
195
- }
196
- for (let i = 0; i < childrenOrIndices.length; i++) {
197
- if (distances[i] === minD) {
202
+ else {
198
203
  _query({ node: childrenOrIndices[i], descriptors, querypoint, queue, keypointIndexes, numPop });
199
204
  }
200
205
  }
201
206
  if (numPop < CLUSTER_MAX_POP && queue.length > 0) {
202
207
  const { node } = queue.pop();
203
- numPop += 1;
204
- _query({ node, descriptors, querypoint, queue, keypointIndexes, numPop });
208
+ _query({ node, descriptors, querypoint, queue, keypointIndexes, numPop: numPop + 1 });
205
209
  }
206
210
  };
207
211
  const _findInlierMatches = (options) => {
208
212
  const { H, matches, threshold } = options;
209
213
  const threshold2 = threshold * threshold;
214
+ const h00 = H[0], h01 = H[1], h02 = H[2];
215
+ const h10 = H[3], h11 = H[4], h12 = H[5];
216
+ const h20 = H[6], h21 = H[7], h22 = H[8];
210
217
  const goodMatches = [];
211
218
  for (let i = 0; i < matches.length; i++) {
212
- const querypoint = matches[i].querypoint;
213
- const keypoint = matches[i].keypoint;
214
- const mp = multiplyPointHomographyInhomogenous([keypoint.x, keypoint.y], H);
215
- const d2 = (mp[0] - querypoint.x) * (mp[0] - querypoint.x) +
216
- (mp[1] - querypoint.y) * (mp[1] - querypoint.y);
217
- if (d2 <= threshold2) {
218
- goodMatches.push(matches[i]);
219
+ const m = matches[i];
220
+ const qp = m.querypoint;
221
+ const kp = m.keypoint;
222
+ // Inline multiplyPointHomographyInhomogenous
223
+ const uz = (kp.x * h20) + (kp.y * h21) + h22;
224
+ const invZ = 1.0 / uz;
225
+ const mx = ((kp.x * h00) + (kp.y * h01) + h02) * invZ;
226
+ const my = ((kp.x * h10) + (kp.y * h11) + h12) * invZ;
227
+ const dx = mx - qp.x;
228
+ const dy = my - qp.y;
229
+ if (dx * dx + dy * dy <= threshold2) {
230
+ goodMatches.push(m);
219
231
  }
220
232
  }
221
233
  return goodMatches;
@@ -12,38 +12,18 @@ export class OfflineCompiler {
12
12
  * @returns {Promise<Array>} Datos compilados
13
13
  */
14
14
  compileImageTargets(images: any[], progressCallback: Function): Promise<any[]>;
15
- /**
16
- * Compila datos de matching usando DetectorLite (JS puro)
17
- */
18
15
  _compileMatch(targetImages: any, progressCallback: any): Promise<any[]>;
19
- /**
20
- * Compila datos de tracking usando extractTrackingFeatures (JS puro)
21
- */
22
16
  _compileTrack(targetImages: any, progressCallback: any): Promise<any[]>;
23
- /**
24
- * Método público para compilar tracking (compatibilidad con API anterior)
25
- * @param {Object} options - Opciones de compilación
26
- * @param {Function} options.progressCallback - Callback de progreso
27
- * @param {Array} options.targetImages - Lista de imágenes objetivo
28
- * @param {number} options.basePercent - Porcentaje base
29
- * @returns {Promise<Array>} Datos de tracking
30
- */
31
17
  compileTrack({ progressCallback, targetImages, basePercent }: {
32
- progressCallback: Function;
33
- targetImages: any[];
34
- basePercent: number;
18
+ progressCallback: any;
19
+ targetImages: any;
20
+ basePercent?: number | undefined;
35
21
  }): Promise<any[]>;
36
- /**
37
- * Método público para compilar matching (compatibilidad con API anterior)
38
- */
39
22
  compileMatch({ progressCallback, targetImages, basePercent }: {
40
23
  progressCallback: any;
41
24
  targetImages: any;
42
25
  basePercent?: number | undefined;
43
26
  }): Promise<any[]>;
44
- /**
45
- * Exporta datos compilados en formato binario columnar optimizado
46
- */
47
27
  exportData(): any;
48
28
  _packKeyframe(kf: any): {
49
29
  w: any;
@@ -53,6 +33,7 @@ export class OfflineCompiler {
53
33
  x: Float32Array<any>;
54
34
  y: Float32Array<any>;
55
35
  a: Float32Array<any>;
36
+ s: Float32Array<any>;
56
37
  d: Uint8Array<ArrayBuffer>;
57
38
  t: any[];
58
39
  };
@@ -60,6 +41,7 @@ export class OfflineCompiler {
60
41
  x: Float32Array<any>;
61
42
  y: Float32Array<any>;
62
43
  a: Float32Array<any>;
44
+ s: Float32Array<any>;
63
45
  d: Uint8Array<ArrayBuffer>;
64
46
  t: any[];
65
47
  };
@@ -68,13 +50,11 @@ export class OfflineCompiler {
68
50
  x: Float32Array<any>;
69
51
  y: Float32Array<any>;
70
52
  a: Float32Array<any>;
53
+ s: Float32Array<any>;
71
54
  d: Uint8Array<ArrayBuffer>;
72
55
  t: any[];
73
56
  };
74
57
  _compactTree(node: any): any[];
75
- /**
76
- * Importa datos - Mantiene el formato columnar para máximo rendimiento (Zero-copy)
77
- */
78
58
  importData(buffer: any): any;
79
59
  _unpackKeyframe(kf: any): {
80
60
  width: any;
@@ -84,12 +64,14 @@ export class OfflineCompiler {
84
64
  x: any;
85
65
  y: any;
86
66
  angle: any;
67
+ scale: any;
87
68
  descriptors: any;
88
69
  }[];
89
70
  minimaPoints: {
90
71
  x: any;
91
72
  y: any;
92
73
  angle: any;
74
+ scale: any;
93
75
  descriptors: any;
94
76
  }[];
95
77
  maximaPointsCluster: {
@@ -123,6 +105,7 @@ export class OfflineCompiler {
123
105
  x: any;
124
106
  y: any;
125
107
  angle: any;
108
+ scale: any;
126
109
  descriptors: any;
127
110
  }[];
128
111
  _expandTree(node: any): {
@@ -136,9 +119,6 @@ export class OfflineCompiler {
136
119
  children: any;
137
120
  pointIndexes?: undefined;
138
121
  };
139
- /**
140
- * Destruye el pool de workers
141
- */
142
122
  destroy(): Promise<void>;
143
123
  }
144
124
  import { WorkerPool } from "./utils/worker-pool.js";