@srsergio/taptapp-ar 1.0.0

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 (207) hide show
  1. package/README.md +62 -0
  2. package/dist/compiler/aframe.d.ts +1 -0
  3. package/dist/compiler/aframe.js +275 -0
  4. package/dist/compiler/compiler-base.d.ts +12 -0
  5. package/dist/compiler/compiler-base.js +165 -0
  6. package/dist/compiler/compiler.d.ts +9 -0
  7. package/dist/compiler/compiler.js +24 -0
  8. package/dist/compiler/compiler.worker.d.ts +1 -0
  9. package/dist/compiler/compiler.worker.js +28 -0
  10. package/dist/compiler/controller.d.ts +101 -0
  11. package/dist/compiler/controller.js +400 -0
  12. package/dist/compiler/controller.worker.d.ts +1 -0
  13. package/dist/compiler/controller.worker.js +61 -0
  14. package/dist/compiler/detector/crop-detector.d.ts +65 -0
  15. package/dist/compiler/detector/crop-detector.js +59 -0
  16. package/dist/compiler/detector/detector.d.ts +98 -0
  17. package/dist/compiler/detector/detector.js +1049 -0
  18. package/dist/compiler/detector/freak.d.ts +1 -0
  19. package/dist/compiler/detector/freak.js +89 -0
  20. package/dist/compiler/detector/kernels/cpu/binomialFilter.d.ts +6 -0
  21. package/dist/compiler/detector/kernels/cpu/binomialFilter.js +51 -0
  22. package/dist/compiler/detector/kernels/cpu/buildExtremas.d.ts +6 -0
  23. package/dist/compiler/detector/kernels/cpu/buildExtremas.js +89 -0
  24. package/dist/compiler/detector/kernels/cpu/computeExtremaAngles.d.ts +7 -0
  25. package/dist/compiler/detector/kernels/cpu/computeExtremaAngles.js +79 -0
  26. package/dist/compiler/detector/kernels/cpu/computeExtremaFreak.d.ts +6 -0
  27. package/dist/compiler/detector/kernels/cpu/computeExtremaFreak.js +68 -0
  28. package/dist/compiler/detector/kernels/cpu/computeFreakDescriptors.d.ts +6 -0
  29. package/dist/compiler/detector/kernels/cpu/computeFreakDescriptors.js +57 -0
  30. package/dist/compiler/detector/kernels/cpu/computeLocalization.d.ts +6 -0
  31. package/dist/compiler/detector/kernels/cpu/computeLocalization.js +54 -0
  32. package/dist/compiler/detector/kernels/cpu/computeOrientationHistograms.d.ts +6 -0
  33. package/dist/compiler/detector/kernels/cpu/computeOrientationHistograms.js +118 -0
  34. package/dist/compiler/detector/kernels/cpu/downsampleBilinear.d.ts +6 -0
  35. package/dist/compiler/detector/kernels/cpu/downsampleBilinear.js +29 -0
  36. package/dist/compiler/detector/kernels/cpu/extremaReduction.d.ts +6 -0
  37. package/dist/compiler/detector/kernels/cpu/extremaReduction.js +50 -0
  38. package/dist/compiler/detector/kernels/cpu/fakeShader.d.ts +20 -0
  39. package/dist/compiler/detector/kernels/cpu/fakeShader.js +80 -0
  40. package/dist/compiler/detector/kernels/cpu/index.d.ts +1 -0
  41. package/dist/compiler/detector/kernels/cpu/index.js +25 -0
  42. package/dist/compiler/detector/kernels/cpu/prune.d.ts +1 -0
  43. package/dist/compiler/detector/kernels/cpu/prune.js +103 -0
  44. package/dist/compiler/detector/kernels/cpu/smoothHistograms.d.ts +6 -0
  45. package/dist/compiler/detector/kernels/cpu/smoothHistograms.js +47 -0
  46. package/dist/compiler/detector/kernels/cpu/upsampleBilinear.d.ts +6 -0
  47. package/dist/compiler/detector/kernels/cpu/upsampleBilinear.js +43 -0
  48. package/dist/compiler/detector/kernels/index.d.ts +1 -0
  49. package/dist/compiler/detector/kernels/index.js +2 -0
  50. package/dist/compiler/detector/kernels/webgl/binomialFilter.d.ts +6 -0
  51. package/dist/compiler/detector/kernels/webgl/binomialFilter.js +67 -0
  52. package/dist/compiler/detector/kernels/webgl/buildExtremas.d.ts +6 -0
  53. package/dist/compiler/detector/kernels/webgl/buildExtremas.js +101 -0
  54. package/dist/compiler/detector/kernels/webgl/computeExtremaAngles.d.ts +6 -0
  55. package/dist/compiler/detector/kernels/webgl/computeExtremaAngles.js +78 -0
  56. package/dist/compiler/detector/kernels/webgl/computeExtremaFreak.d.ts +6 -0
  57. package/dist/compiler/detector/kernels/webgl/computeExtremaFreak.js +86 -0
  58. package/dist/compiler/detector/kernels/webgl/computeFreakDescriptors.d.ts +6 -0
  59. package/dist/compiler/detector/kernels/webgl/computeFreakDescriptors.js +52 -0
  60. package/dist/compiler/detector/kernels/webgl/computeLocalization.d.ts +6 -0
  61. package/dist/compiler/detector/kernels/webgl/computeLocalization.js +58 -0
  62. package/dist/compiler/detector/kernels/webgl/computeOrientationHistograms.d.ts +6 -0
  63. package/dist/compiler/detector/kernels/webgl/computeOrientationHistograms.js +116 -0
  64. package/dist/compiler/detector/kernels/webgl/downsampleBilinear.d.ts +6 -0
  65. package/dist/compiler/detector/kernels/webgl/downsampleBilinear.js +46 -0
  66. package/dist/compiler/detector/kernels/webgl/extremaReduction.d.ts +6 -0
  67. package/dist/compiler/detector/kernels/webgl/extremaReduction.js +48 -0
  68. package/dist/compiler/detector/kernels/webgl/index.d.ts +1 -0
  69. package/dist/compiler/detector/kernels/webgl/index.js +25 -0
  70. package/dist/compiler/detector/kernels/webgl/smoothHistograms.d.ts +6 -0
  71. package/dist/compiler/detector/kernels/webgl/smoothHistograms.js +49 -0
  72. package/dist/compiler/detector/kernels/webgl/upsampleBilinear.d.ts +6 -0
  73. package/dist/compiler/detector/kernels/webgl/upsampleBilinear.js +56 -0
  74. package/dist/compiler/estimation/esimate-experiment.d.ts +5 -0
  75. package/dist/compiler/estimation/esimate-experiment.js +267 -0
  76. package/dist/compiler/estimation/estimate.d.ts +5 -0
  77. package/dist/compiler/estimation/estimate.js +51 -0
  78. package/dist/compiler/estimation/estimator.d.ts +13 -0
  79. package/dist/compiler/estimation/estimator.js +30 -0
  80. package/dist/compiler/estimation/refine-estimate-experiment.d.ts +6 -0
  81. package/dist/compiler/estimation/refine-estimate-experiment.js +429 -0
  82. package/dist/compiler/estimation/refine-estimate.d.ts +6 -0
  83. package/dist/compiler/estimation/refine-estimate.js +299 -0
  84. package/dist/compiler/estimation/utils.d.ts +10 -0
  85. package/dist/compiler/estimation/utils.js +80 -0
  86. package/dist/compiler/image-list.d.ts +13 -0
  87. package/dist/compiler/image-list.js +52 -0
  88. package/dist/compiler/index.d.ts +3 -0
  89. package/dist/compiler/index.js +10 -0
  90. package/dist/compiler/input-loader.d.ts +23 -0
  91. package/dist/compiler/input-loader.js +88 -0
  92. package/dist/compiler/matching/hamming-distance.d.ts +1 -0
  93. package/dist/compiler/matching/hamming-distance.js +20 -0
  94. package/dist/compiler/matching/hierarchical-clustering.d.ts +7 -0
  95. package/dist/compiler/matching/hierarchical-clustering.js +109 -0
  96. package/dist/compiler/matching/hough.d.ts +1 -0
  97. package/dist/compiler/matching/hough.js +169 -0
  98. package/dist/compiler/matching/matcher.d.ts +28 -0
  99. package/dist/compiler/matching/matcher.js +48 -0
  100. package/dist/compiler/matching/matching.d.ts +41 -0
  101. package/dist/compiler/matching/matching.js +197 -0
  102. package/dist/compiler/matching/ransacHomography.d.ts +1 -0
  103. package/dist/compiler/matching/ransacHomography.js +136 -0
  104. package/dist/compiler/offline-compiler.d.ts +10 -0
  105. package/dist/compiler/offline-compiler.js +450 -0
  106. package/dist/compiler/tensorflow-setup.d.ts +7 -0
  107. package/dist/compiler/tensorflow-setup.js +73 -0
  108. package/dist/compiler/three.d.ts +66 -0
  109. package/dist/compiler/three.js +310 -0
  110. package/dist/compiler/tracker/extract-utils.d.ts +1 -0
  111. package/dist/compiler/tracker/extract-utils.js +29 -0
  112. package/dist/compiler/tracker/extract.d.ts +4 -0
  113. package/dist/compiler/tracker/extract.js +349 -0
  114. package/dist/compiler/tracker/tracker.d.ts +38 -0
  115. package/dist/compiler/tracker/tracker.js +327 -0
  116. package/dist/compiler/utils/cumsum.d.ts +5 -0
  117. package/dist/compiler/utils/cumsum.js +39 -0
  118. package/dist/compiler/utils/geometry.d.ts +8 -0
  119. package/dist/compiler/utils/geometry.js +101 -0
  120. package/dist/compiler/utils/homography.d.ts +1 -0
  121. package/dist/compiler/utils/homography.js +138 -0
  122. package/dist/compiler/utils/images.d.ts +24 -0
  123. package/dist/compiler/utils/images.js +99 -0
  124. package/dist/compiler/utils/randomizer.d.ts +5 -0
  125. package/dist/compiler/utils/randomizer.js +25 -0
  126. package/dist/index.d.ts +6 -0
  127. package/dist/index.js +7 -0
  128. package/dist/react/AREditor.d.ts +5 -0
  129. package/dist/react/AREditor.js +159 -0
  130. package/dist/react/ProgressDialog.d.ts +13 -0
  131. package/dist/react/ProgressDialog.js +57 -0
  132. package/dist/react/types.d.ts +22 -0
  133. package/dist/react/types.js +14 -0
  134. package/package.json +53 -0
  135. package/src/astro/ARScene.astro +59 -0
  136. package/src/astro/ARVideoTrigger.astro +73 -0
  137. package/src/astro/overlays/ErrorOverlay.astro +40 -0
  138. package/src/astro/overlays/LoadingOverlay.astro +28 -0
  139. package/src/astro/overlays/ScanningOverlay.astro +119 -0
  140. package/src/astro/scripts/ARScripts.astro +118 -0
  141. package/src/astro/styles/ARStyles.astro +147 -0
  142. package/src/compiler/aframe.js +343 -0
  143. package/src/compiler/compiler-base.js +195 -0
  144. package/src/compiler/compiler.js +25 -0
  145. package/src/compiler/compiler.worker.js +30 -0
  146. package/src/compiler/controller.js +473 -0
  147. package/src/compiler/controller.worker.js +77 -0
  148. package/src/compiler/detector/crop-detector.js +68 -0
  149. package/src/compiler/detector/detector.js +1130 -0
  150. package/src/compiler/detector/freak.js +91 -0
  151. package/src/compiler/detector/kernels/cpu/binomialFilter.js +59 -0
  152. package/src/compiler/detector/kernels/cpu/buildExtremas.js +108 -0
  153. package/src/compiler/detector/kernels/cpu/computeExtremaAngles.js +91 -0
  154. package/src/compiler/detector/kernels/cpu/computeExtremaFreak.js +92 -0
  155. package/src/compiler/detector/kernels/cpu/computeFreakDescriptors.js +68 -0
  156. package/src/compiler/detector/kernels/cpu/computeLocalization.js +71 -0
  157. package/src/compiler/detector/kernels/cpu/computeOrientationHistograms.js +141 -0
  158. package/src/compiler/detector/kernels/cpu/downsampleBilinear.js +33 -0
  159. package/src/compiler/detector/kernels/cpu/extremaReduction.js +53 -0
  160. package/src/compiler/detector/kernels/cpu/fakeShader.js +88 -0
  161. package/src/compiler/detector/kernels/cpu/index.js +26 -0
  162. package/src/compiler/detector/kernels/cpu/prune.js +114 -0
  163. package/src/compiler/detector/kernels/cpu/smoothHistograms.js +57 -0
  164. package/src/compiler/detector/kernels/cpu/upsampleBilinear.js +51 -0
  165. package/src/compiler/detector/kernels/index.js +2 -0
  166. package/src/compiler/detector/kernels/webgl/binomialFilter.js +72 -0
  167. package/src/compiler/detector/kernels/webgl/buildExtremas.js +109 -0
  168. package/src/compiler/detector/kernels/webgl/computeExtremaAngles.js +82 -0
  169. package/src/compiler/detector/kernels/webgl/computeExtremaFreak.js +105 -0
  170. package/src/compiler/detector/kernels/webgl/computeFreakDescriptors.js +56 -0
  171. package/src/compiler/detector/kernels/webgl/computeLocalization.js +70 -0
  172. package/src/compiler/detector/kernels/webgl/computeOrientationHistograms.js +129 -0
  173. package/src/compiler/detector/kernels/webgl/downsampleBilinear.js +50 -0
  174. package/src/compiler/detector/kernels/webgl/extremaReduction.js +50 -0
  175. package/src/compiler/detector/kernels/webgl/index.js +26 -0
  176. package/src/compiler/detector/kernels/webgl/smoothHistograms.js +53 -0
  177. package/src/compiler/detector/kernels/webgl/upsampleBilinear.js +62 -0
  178. package/src/compiler/estimation/esimate-experiment.js +316 -0
  179. package/src/compiler/estimation/estimate.js +67 -0
  180. package/src/compiler/estimation/estimator.js +34 -0
  181. package/src/compiler/estimation/refine-estimate-experiment.js +512 -0
  182. package/src/compiler/estimation/refine-estimate.js +365 -0
  183. package/src/compiler/estimation/utils.js +97 -0
  184. package/src/compiler/image-list.js +62 -0
  185. package/src/compiler/index.js +13 -0
  186. package/src/compiler/input-loader.js +107 -0
  187. package/src/compiler/matching/hamming-distance.js +23 -0
  188. package/src/compiler/matching/hierarchical-clustering.js +131 -0
  189. package/src/compiler/matching/hough.js +206 -0
  190. package/src/compiler/matching/matcher.js +59 -0
  191. package/src/compiler/matching/matching.js +237 -0
  192. package/src/compiler/matching/ransacHomography.js +192 -0
  193. package/src/compiler/offline-compiler.js +553 -0
  194. package/src/compiler/tensorflow-setup.js +88 -0
  195. package/src/compiler/three.js +368 -0
  196. package/src/compiler/tracker/extract-utils.js +34 -0
  197. package/src/compiler/tracker/extract.js +419 -0
  198. package/src/compiler/tracker/tracker.js +397 -0
  199. package/src/compiler/utils/cumsum.js +40 -0
  200. package/src/compiler/utils/geometry.js +114 -0
  201. package/src/compiler/utils/homography.js +150 -0
  202. package/src/compiler/utils/images.js +111 -0
  203. package/src/compiler/utils/randomizer.js +29 -0
  204. package/src/index.ts +8 -0
  205. package/src/react/AREditor.tsx +394 -0
  206. package/src/react/ProgressDialog.tsx +185 -0
  207. package/src/react/types.ts +35 -0
@@ -0,0 +1,553 @@
1
+ /**
2
+ * @fileoverview Compilador Offline para Procesamiento de Imágenes con TensorFlow.js
3
+ *
4
+ * Este módulo implementa un sistema avanzado de compilación de imágenes para tracking
5
+ * utilizando TensorFlow.js, optimizado especialmente para entornos backend con alto rendimiento.
6
+ *
7
+ * Arquitectura y Componentes Principales:
8
+ *
9
+ * 1. Sistema de Inicialización:
10
+ * - Implementa un patrón Singleton para TensorFlow con inicialización temprana
11
+ * - Carga asíncrona y paralela de backends (CPU/WebGL/Node)
12
+ * - Detección automática de entorno (serverless/navegador/backend dedicado)
13
+ * - Precalentamiento agresivo para reducir cold starts
14
+ *
15
+ * 2. Gestión de Memoria:
16
+ * - Sistema de liberación ultra-agresiva de memoria con umbrales dinámicos
17
+ * - Monitoreo continuo del uso de tensores con cleanup automático
18
+ * - Estrategias de scope anidados para control preciso de recursos
19
+ * - Liberación proactiva entre operaciones intensivas
20
+ *
21
+ * 3. Optimizaciones de Rendimiento:
22
+ * - Precalentamiento estratégico del backend para eliminar latencia inicial
23
+ * - Ajustes específicos por backend con configuraciones óptimas por plataforma
24
+ * - Configuraciones especializadas para entornos backend de alto rendimiento
25
+ * - Reducción de precisión selectiva para operaciones no críticas
26
+ *
27
+ * 4. Procesamiento por Lotes:
28
+ * - Sistema adaptativo de tamaño de lotes basado en capacidad de hardware
29
+ * - Paralelización multinivel con control de concurrencia
30
+ * - Control de progreso granular con retroalimentación en tiempo real
31
+ * - Estrategias de división de trabajo para CPUs multi-núcleo
32
+ *
33
+ * 5. Gestión de Recursos:
34
+ * - Timeouts inteligentes con recuperación automática
35
+ * - Liberación proactiva de recursos con GC forzado estratégico
36
+ * - Manejo de errores robusto con recuperación de fallos
37
+ * - Monitoreo de rendimiento en tiempo real
38
+ *
39
+ * @requires tensorflow/tfjs
40
+ * @requires ./compiler-base.js
41
+ * @requires ./image-list.js
42
+ * @requires ./tracker/extract-utils.js
43
+ * @requires ./tensorflow-setup.js
44
+ */
45
+
46
+ import { CompilerBase } from "./compiler-base.js";
47
+ import { buildTrackingImageList } from "./image-list.js";
48
+ import { extractTrackingFeatures } from "./tracker/extract-utils.js";
49
+ import { setupTensorFlow } from "./tensorflow-setup.js";
50
+ import { tf } from "./tensorflow-setup.js";
51
+ import os from "os";
52
+ // OPTIMIZACIÓN CORE DEL PROCESO DE COMPILACIÓN
53
+ // 1. Inicialización temprana y paralela de TensorFlow
54
+ // 2. Optimizaciones de memoria y procesamiento agresivas
55
+ // 3. Estrategias de paralelización avanzadas
56
+ // 4. Ajustes para entornos serverless (Vercel, AWS Lambda, etc)
57
+
58
+ // Detector de entorno serverless
59
+ const isServerlessEnvironment = () => {
60
+ return process.env.VERCEL || process.env.AWS_LAMBDA_FUNCTION_NAME || process.env.NETLIFY;
61
+ };
62
+
63
+ // Configurar TensorFlow lo antes posible con un Singleton
64
+ let tensorflowBackend = null;
65
+ let setupPromise = null;
66
+
67
+ const setupTensorFlowAsync = async () => {
68
+ // Si ya hay una configuración en curso, reutilizarla
69
+ if (setupPromise) return setupPromise;
70
+
71
+ // Iniciar configuración y guardar la promesa
72
+ setupPromise = (async () => {
73
+ try {
74
+ console.time("⏱️ Configuración de TensorFlow");
75
+ const backend = await setupTensorFlow();
76
+ tensorflowBackend = backend;
77
+ console.timeEnd("⏱️ Configuración de TensorFlow");
78
+ return backend;
79
+ } catch (error) {
80
+ console.error("Error crítico al configurar TensorFlow:", error);
81
+ return null;
82
+ }
83
+ })();
84
+
85
+ return setupPromise;
86
+ };
87
+
88
+ // Iniciar la configuración inmediatamente al importar el módulo
89
+ const tensorflowSetupPromise = setupTensorFlowAsync();
90
+
91
+ // Registrar los kernels necesarios para CPU (carga temprana)
92
+ import "./detector/kernels/cpu/index.js";
93
+
94
+ // Registrar los backends básicos
95
+ import "@tensorflow/tfjs-backend-cpu";
96
+
97
+ // Configuraciones avanzadas para maximizar rendimiento en backend
98
+ const enablePerformanceOptimizations = async () => {
99
+ try {
100
+ // Esperar a que TensorFlow esté configurado
101
+ await tensorflowSetupPromise;
102
+
103
+ // Optimizaciones específicas según el backend
104
+ const backend = tf.getBackend();
105
+ console.log(`⚙️ Optimizando agresivamente para backend: ${backend}`);
106
+
107
+ // Entorno serverless necesita configuraciones especiales
108
+ const isServerless = isServerlessEnvironment();
109
+ const isBackendDedicated = !isServerless && process.env.NODE_ENV === "production";
110
+
111
+ if (isBackendDedicated) {
112
+ console.log(
113
+ "🚀🚀 Entorno backend dedicado detectado, aplicando configuraciones de alto rendimiento",
114
+ );
115
+
116
+ // Configuraciones agresivas para backend dedicado
117
+ tf.ENV.set("CPU_HANDOFF_SIZE_THRESHOLD", 1024 * 1024 * 16); // 16MB - más memoria disponible
118
+ tf.ENV.set("WEBGL_SIZE_UPLOAD_UNIFORM", 16); // Mayor capacidad de transferencia
119
+ tf.ENV.set("WEBGL_DELETE_TEXTURE_THRESHOLD", 64); // Más texturas en memoria
120
+
121
+ // Configuraciones para maximizar throughput
122
+ tf.ENV.set("WEBGL_FLUSH_THRESHOLD", 10); // Menos flushes para mejor rendimiento
123
+ tf.ENV.set("KEEP_INTERMEDIATE_TENSORS", false); // Liberar intermedios agresivamente
124
+ tf.ENV.set("WEBGL_PACK_BINARY_OPERATIONS", true); // Empaquetar operaciones binarias
125
+ } else if (isServerless) {
126
+ console.log(
127
+ "🚀 Entorno serverless detectado, aplicando configuraciones de memoria restrictivas",
128
+ );
129
+
130
+ // En serverless aplicamos configuraciones más conservadoras para memoria
131
+ tf.ENV.set("CPU_HANDOFF_SIZE_THRESHOLD", 1024 * 1024 * 4); // 4MB
132
+ tf.ENV.set("WEBGL_SIZE_UPLOAD_UNIFORM", 4);
133
+ tf.ENV.set("WEBGL_DELETE_TEXTURE_THRESHOLD", 10);
134
+
135
+ // Menor precisión para mejor rendimiento
136
+ tf.ENV.set("WEBGL_RENDER_FLOAT32_ENABLED", false);
137
+ }
138
+
139
+ // Optimizaciones generales para todos los backends
140
+ tf.ENV.set("WEBGL_CPU_FORWARD", false);
141
+ tf.ENV.set("DEBUG", false);
142
+ tf.ENV.set("CHECK_COMPUTATION_FOR_ERRORS", false); // Deshabilitar verificaciones para mayor velocidad
143
+
144
+ // Optimizar el uso de memoria con límites más altos
145
+ if (backend === "node") {
146
+ console.log("🔧 Aplicando optimizaciones avanzadas para Node.js backend");
147
+ } else if (backend === "webgl") {
148
+ // Optimizaciones específicas para WebGL
149
+ console.log("🔧 Aplicando optimizaciones avanzadas para WebGL backend");
150
+ tf.ENV.set("WEBGL_FORCE_F16_TEXTURES", true);
151
+ tf.ENV.set("WEBGL_PACK", true);
152
+ tf.ENV.set("WEBGL_PACK_DEPTHWISECONV", true);
153
+ tf.ENV.set("WEBGL_PACK_BINARY_OPERATIONS", true);
154
+ tf.ENV.set("WEBGL_PACK_ARRAY_OPERATIONS", true);
155
+ tf.ENV.set("WEBGL_PACK_IMAGE_OPERATIONS", true);
156
+ tf.ENV.set("WEBGL_PACK_REDUCE", true);
157
+
158
+ // Configuraciones de textura según entorno
159
+ if (isBackendDedicated) {
160
+ // En backend dedicado, usar valores más agresivos
161
+ tf.ENV.set("WEBGL_MAX_TEXTURE_SIZE", 8192); // Texturas más grandes
162
+ tf.ENV.set("WEBGL_MAX_TEXTURES_IN_SHADER", 16); // Más texturas por shader
163
+ } else if (isServerless) {
164
+ // En serverless, usamos valores más conservadores
165
+ tf.ENV.set("WEBGL_MAX_TEXTURE_SIZE", 2048);
166
+ tf.ENV.set("WEBGL_MAX_TEXTURES_IN_SHADER", 8);
167
+ } else {
168
+ // Entorno normal
169
+ tf.ENV.set("WEBGL_MAX_TEXTURE_SIZE", 4096);
170
+ tf.ENV.set("WEBGL_MAX_TEXTURES_IN_SHADER", 12);
171
+ }
172
+ } else if (backend === "cpu") {
173
+ // Optimizaciones específicas para CPU
174
+ console.log("🔧 Aplicando optimizaciones para CPU backend");
175
+
176
+ // Intentar usar SIMD si está disponible
177
+ try {
178
+ if (
179
+ typeof WebAssembly.validate === "function" &&
180
+ WebAssembly.validate(
181
+ new Uint8Array([
182
+ 0, 97, 115, 109, 1, 0, 0, 0, 1, 5, 1, 96, 0, 1, 123, 3, 2, 1, 0, 10, 10, 1, 8, 0, 65,
183
+ 0, 253, 15, 253, 98, 11,
184
+ ]),
185
+ )
186
+ ) {
187
+ console.log("🚀 SIMD disponible, habilitando aceleración vectorial");
188
+ tf.ENV.set("WASM_HAS_SIMD_SUPPORT", true);
189
+ tf.ENV.set("WASM_HAS_MULTITHREAD_SUPPORT", true);
190
+ }
191
+ } catch (e) {
192
+ console.warn("⚠️ No se pudo detectar soporte SIMD", e);
193
+ }
194
+ }
195
+
196
+ // Precalentamiento estratégico del backend para eliminar retrasos en la primera ejecución
197
+ // Implementamos un precalentamiento adaptativo según el entorno
198
+ console.time("🔥 Precalentamiento estratégico");
199
+ console.log("🔥 Precalentando TensorFlow con operaciones específicas...");
200
+
201
+ await tf.ready();
202
+
203
+ // Detectar si estamos en un entorno de backend dedicado
204
+
205
+ // Estrategia de precalentamiento adaptativa según entorno
206
+ const warmupStrategy = isBackendDedicated
207
+ ? "aggressive"
208
+ : isServerless
209
+ ? "minimal"
210
+ : "balanced";
211
+ console.log(`🔥 Aplicando estrategia de precalentamiento: ${warmupStrategy}`);
212
+
213
+ // Función para ejecutar y esperar operaciones tensores
214
+ const executeAndWait = async (tensors) => {
215
+ // Esperar a que todas las operaciones se completen
216
+ await Promise.all(tensors.map((t) => t.data()));
217
+ // Liberar memoria inmediatamente
218
+ tf.dispose(tensors);
219
+ };
220
+
221
+ // Precalentamiento básico para todos los entornos
222
+ await tf.tidy(async () => {
223
+ // Operaciones básicas de álgebra tensorial
224
+ const a = tf.tensor([1, 2, 3, 4]);
225
+ const b = tf.tensor([2, 2, 2, 2]);
226
+ const result = a.add(b);
227
+ const mult = a.mul(b);
228
+ const div = a.div(b);
229
+ await executeAndWait([result, mult, div]);
230
+ });
231
+
232
+ // Tamaño de imagen adaptativo según entorno
233
+ const size = isBackendDedicated ? 224 : isServerless ? 64 : 128;
234
+ console.log(`🖼️ Precalentando con imagen de tamaño ${size}x${size}`);
235
+
236
+ // Precalentamiento de operaciones de procesamiento de imágenes
237
+ await tf.tidy(async () => {
238
+ // Crear imagen sintética para precalentamiento
239
+ const image = tf.ones([size, size, 3]);
240
+
241
+ // Precalentar operaciones de preprocesamiento comunes
242
+ const normalized = image.div(tf.scalar(255));
243
+ const grayscale = image.mean(2, true); // Reducción de canal para escala de grises
244
+ await executeAndWait([normalized, grayscale]);
245
+
246
+ // Precalentar operaciones de convolución con diferentes configuraciones
247
+ // Estas operaciones son críticas para la extracción de características
248
+ const kernelSizes = warmupStrategy === "aggressive" ? [3, 5, 7] : [3];
249
+ const filterCounts = warmupStrategy === "aggressive" ? [8, 16] : [4];
250
+
251
+ for (const kernelSize of kernelSizes) {
252
+ for (const filters of filterCounts) {
253
+ // Crear kernel aleatorio para convolución
254
+ const kernel = tf.randomNormal([kernelSize, kernelSize, 3, filters]);
255
+
256
+ // Aplicar convolución - operación clave en detección de características
257
+ const convResult = tf.conv2d(image, kernel, 1, "same");
258
+
259
+ // Operaciones de pooling - también críticas en redes de detección
260
+ const maxPooled = tf.maxPool(convResult, [2, 2], 2, "same");
261
+ const avgPooled = tf.avgPool(convResult, [2, 2], 2, "same");
262
+
263
+ // Activaciones comunes
264
+ const activated = tf.relu(convResult);
265
+
266
+ await executeAndWait([convResult, maxPooled, avgPooled, activated]);
267
+ }
268
+ }
269
+
270
+ // En modo agresivo, precalentar operaciones más avanzadas
271
+ if (warmupStrategy === "aggressive") {
272
+ // Operaciones de transformación espacial comunes en tracking
273
+ const resized = tf.image.resizeBilinear(image, [size / 2, size / 2]);
274
+ const cropped = tf.slice(image, [0, 0, 0], [size / 2, size / 2, 3]);
275
+ await executeAndWait([resized, cropped]);
276
+
277
+ // Operaciones de detección de bordes (aproximación)
278
+ const sobelX = tf.conv2d(
279
+ grayscale,
280
+ tf.tensor4d(
281
+ [
282
+ [-1, 0, 1],
283
+ [-2, 0, 2],
284
+ [-1, 0, 1],
285
+ ],
286
+ [3, 3, 1, 1],
287
+ ),
288
+ 1,
289
+ "same",
290
+ );
291
+ const sobelY = tf.conv2d(
292
+ grayscale,
293
+ tf.tensor4d(
294
+ [
295
+ [-1, -2, -1],
296
+ [0, 0, 0],
297
+ [1, 2, 1],
298
+ ],
299
+ [3, 3, 1, 1],
300
+ ),
301
+ 1,
302
+ "same",
303
+ );
304
+ const edges = tf.sqrt(tf.add(tf.square(sobelX), tf.square(sobelY)));
305
+ await executeAndWait([sobelX, sobelY, edges]);
306
+ }
307
+ });
308
+
309
+ // Forzar recolección de basura para limpiar completamente
310
+ if (global.gc) {
311
+ try {
312
+ global.gc();
313
+ console.log("♻️ Recolección de basura manual ejecutada");
314
+ } catch (e) {
315
+ // Ignorar errores si no está disponible
316
+ }
317
+ }
318
+
319
+ // Verificar estado de memoria después del precalentamiento
320
+ const memInfo = tf.memory();
321
+ console.log(
322
+ `📊 Estado de memoria post-precalentamiento: ${memInfo.numTensors} tensores, ${(memInfo.numBytes / (1024 * 1024)).toFixed(2)}MB`,
323
+ );
324
+
325
+ console.timeEnd("🔥 Precalentamiento estratégico");
326
+ } catch (error) {
327
+ console.warn("⚠️ No se pudieron aplicar todas las optimizaciones:", error);
328
+ }
329
+ };
330
+
331
+ // Aplicar optimizaciones de manera asíncrona para no bloquear
332
+ enablePerformanceOptimizations();
333
+
334
+ // Versión optimizada del compilador
335
+ export class OfflineCompiler extends CompilerBase {
336
+ constructor() {
337
+ super();
338
+
339
+ // Detección de entorno
340
+ this.isServerless = isServerlessEnvironment();
341
+ if (this.isServerless) {
342
+ console.log("🚀 Compilador optimizado para entorno serverless");
343
+ }
344
+
345
+ // Inicializar inmediatamente para evitar arranque frío
346
+ this._ensureTensorflowReady();
347
+ }
348
+
349
+ // Método privado para asegurar que TensorFlow esté listo
350
+ async _ensureTensorflowReady() {
351
+ if (!tensorflowBackend) {
352
+ await tensorflowSetupPromise;
353
+ }
354
+ return tensorflowBackend;
355
+ }
356
+
357
+ // Versión optimizada del método principal de compilación
358
+ compileTrack({ progressCallback, targetImages, basePercent }) {
359
+ return new Promise(async (resolve, reject) => {
360
+ // Prevenir errores de timeout en entornos serverless
361
+ let compilationTimeout;
362
+
363
+ // En serverless, establecer un límite estricto de tiempo para evitar timeouts
364
+ if (this.isServerless) {
365
+ const timeoutSeconds = 25; // Tiempo límite para compilación en serverless
366
+ compilationTimeout = setTimeout(() => {
367
+ reject(
368
+ new Error(
369
+ `Tiempo límite de compilación excedido (${timeoutSeconds}s). La imagen puede ser demasiado compleja para procesamiento serverless.`,
370
+ ),
371
+ );
372
+ }, timeoutSeconds * 1000);
373
+ }
374
+
375
+ try {
376
+ // Asegurar que TensorFlow esté configurado
377
+ await this._ensureTensorflowReady();
378
+
379
+ console.time("⏱️ Tiempo de compilación de tracking");
380
+
381
+ const backend = tf.getBackend();
382
+ const percentPerImage = (100 - basePercent) / targetImages.length;
383
+ let percent = 0;
384
+ const list = [];
385
+
386
+ console.log(`🧮 Compilando con backend: ${backend}`);
387
+
388
+ // Optimizar el tamaño de lote según el backend disponible
389
+ // En serverless, siempre usar lotes más pequeños
390
+ // Estrategia adaptativa para tamaño de lote (CPU/GPU)
391
+ let batchSize = 1;
392
+ if (backend === "node") {
393
+ // Calcular tamaño óptimo basado en recursos
394
+ try {
395
+ const cpus = os.cpus().length;
396
+ const freeMem = os.freemem() / 1024 / 1024 / 1024; // GB libres
397
+
398
+ // Lógica de batch dinámico:
399
+ // - 1 núcleo: batch 1 (evitar sobrecarga)
400
+ // - 2-4 núcleos: batch 2-4 (balance carga/paralelismo)
401
+ // - >4 núcleos: batch escalable con memoria
402
+ batchSize =
403
+ cpus > 4
404
+ ? Math.min(Math.floor(freeMem * 0.5), 8) // 0.5GB por batch
405
+ : Math.min(cpus, 4);
406
+
407
+ console.log(
408
+ `🧠 Batch size calculado: ${batchSize} (${cpus} cores, ${freeMem.toFixed(1)}GB libres)`,
409
+ );
410
+ } catch (e) {
411
+ console.warn("⚠️ Error cálculo batch size:", e);
412
+ batchSize = 2; // Fallback: equilibrio seguridad/performance
413
+ }
414
+ } else if (this.isServerless) {
415
+ batchSize = 1; // Priorizar seguridad sobre performance
416
+ }
417
+
418
+ // Garantizar límites operativos seguros:
419
+ // - Mínimo: Evitar underflow en procesamiento
420
+ // - Máximo: Prevenir OOM (Out Of Memory)
421
+ batchSize = Math.max(1, Math.min(batchSize, 8));
422
+
423
+ console.log(`📊 Procesando imágenes en lotes de ${batchSize}`);
424
+
425
+ // Solicitar memoria mínima antes de empezar procesamiento intensivo
426
+ if (global.gc) {
427
+ try {
428
+ global.gc();
429
+ } catch (e) {
430
+ // Ignorar errores
431
+ }
432
+ }
433
+
434
+ // Paralelismo para el procesamiento en lotes
435
+ for (let i = 0; i < targetImages.length; i += batchSize) {
436
+ // Procesar un lote de imágenes
437
+ const batch = targetImages.slice(i, Math.min(i + batchSize, targetImages.length));
438
+
439
+ // Imprimir información sobre el procesamiento por lotes
440
+ if (batch.length > 1) {
441
+ console.log(
442
+ `🔄 Procesando lote ${Math.floor(i / batchSize) + 1}: ${batch.length} imágenes`,
443
+ );
444
+ }
445
+
446
+ // Usar tf.engine().startScope() para mejor control de memoria por lote
447
+ tf.engine().startScope();
448
+
449
+ try {
450
+ // Procesamiento paralelo de imágenes en el lote
451
+ const batchResults = await Promise.all(
452
+ batch.map(async (targetImage) => {
453
+ const imageList = buildTrackingImageList(targetImage);
454
+ const percentPerAction = percentPerImage / imageList.length;
455
+
456
+ // Usar tf.tidy para liberar memoria automáticamente en cada imagen
457
+ return await tf.tidy(() => {
458
+ // Extraer características con monitoreo de progreso
459
+ const trackingData = extractTrackingFeatures(imageList, (index) => {
460
+ percent += percentPerAction;
461
+ progressCallback(basePercent + percent);
462
+ });
463
+
464
+ return trackingData;
465
+ });
466
+ }),
467
+ );
468
+
469
+ // Agregar resultados a la lista final
470
+ list.push(...batchResults);
471
+ } finally {
472
+ // Asegurar que siempre se cierre el scope para evitar fugas de memoria
473
+ tf.engine().endScope();
474
+ }
475
+
476
+ // Liberar memoria entre lotes grandes o al final
477
+ // En serverless, liberar más agresivamente
478
+ if (i % (this.isServerless ? 2 : 5) === 0 || i === targetImages.length - 1) {
479
+ await tf.nextFrame(); // Permitir que el recolector de basura libere memoria
480
+
481
+ // Cálculo de presión de memoria adaptativa
482
+ const memoryInfo = tf.memory();
483
+ const totalMem = os.totalmem();
484
+ const freeMem = os.freemem();
485
+ const memPressure = 1 - freeMem / totalMem;
486
+
487
+ // Umbrales dinámicos basados en:
488
+ // 1. Tipo de backend (mayor tolerancia en GPU)
489
+ // 2. Presión de memoria actual
490
+ // 3. Entorno de ejecución (serverless vs dedicado)
491
+ const baseThreshold = backend === "webgl" ? 50 : 30;
492
+ const adaptiveThreshold = Math.floor(
493
+ baseThreshold *
494
+ (1 - Math.min(memPressure, 0.5)) *
495
+ (this.isServerless ? 0.6 : 1) *
496
+ (this.isBackendDedicated ? 1.2 : 1),
497
+ );
498
+
499
+ console.log(
500
+ `🧠 Memoria: ${(freeMem / 1024 / 1024).toFixed(1)}MB libres | ` +
501
+ `Presión: ${(memPressure * 100).toFixed(1)}% | ` +
502
+ `Umbral: ${adaptiveThreshold} tensores`,
503
+ );
504
+
505
+ if (memoryInfo.numTensors > adaptiveThreshold) {
506
+ // Estrategia de limpieza diferenciada
507
+ console.log(
508
+ `🧹 Limpieza ${this.isServerless ? "conservadora" : "agresiva"}: ` +
509
+ `${memoryInfo.numTensors} tensores, ${(memoryInfo.numBytes / 1024 / 1024).toFixed(2)}MB`,
510
+ );
511
+
512
+ // Estrategia de limpieza diferenciada:
513
+ // - Serverless: Liberación temprana preventiva
514
+ // - Dedicado: Postergar GC para mejor throughput
515
+ tf.disposeVariables();
516
+ tf.dispose();
517
+
518
+ // Forzar recolección de basura en Node.js si está disponible
519
+ if (global.gc) {
520
+ try {
521
+ global.gc();
522
+ } catch (e) {
523
+ // Ignorar errores si no está disponible
524
+ }
525
+ }
526
+ }
527
+ }
528
+ }
529
+
530
+ // Terminar medición de tiempo
531
+ console.timeEnd("⏱️ Tiempo de compilación de tracking");
532
+
533
+ // Liberar toda la memoria restante antes de finalizar
534
+ tf.dispose();
535
+
536
+ // Limpiar timeout si existía
537
+ if (compilationTimeout) {
538
+ clearTimeout(compilationTimeout);
539
+ }
540
+
541
+ resolve(list);
542
+ } catch (error) {
543
+ // Limpiar timeout si existía
544
+ if (compilationTimeout) {
545
+ clearTimeout(compilationTimeout);
546
+ }
547
+
548
+ console.error("❌ Error en compilación:", error);
549
+ reject(error);
550
+ }
551
+ });
552
+ }
553
+ }
@@ -0,0 +1,88 @@
1
+ import * as tf from "@tensorflow/tfjs";
2
+
3
+ // Registrar backends básicos
4
+ import "@tensorflow/tfjs-backend-cpu";
5
+ import "@tensorflow/tfjs-backend-webgl";
6
+
7
+ // Registrar kernels personalizados
8
+ import "./detector/kernels/cpu/index.js";
9
+ import "./detector/kernels/webgl/index.js";
10
+
11
+ /**
12
+ * Configuración optimizada de TensorFlow para diferentes entornos
13
+ * @returns {Promise<string>} El backend activo ('webgl', 'cpu')
14
+ */
15
+ export async function setupTensorFlow() {
16
+ console.log("🔧 Iniciando configuración optimizada de TensorFlow.js...");
17
+
18
+ try {
19
+ // Optimizaciones base para todos los backends
20
+ tf.ENV.set("DEBUG", false);
21
+ tf.ENV.set("WEBGL_CPU_FORWARD", false);
22
+ tf.ENV.set("WEBGL_FORCE_F16_TEXTURES", true);
23
+
24
+ // Configuración adaptativa de memoria según el entorno
25
+ const isServerless = typeof window === "undefined";
26
+ const memoryThreshold = isServerless ? 1024 * 1024 * 4 : 1024 * 1024 * 8; // 4MB en serverless, 8MB en cliente
27
+ tf.ENV.set("CPU_HANDOFF_SIZE_THRESHOLD", memoryThreshold);
28
+
29
+ // Configuración específica para entorno serverless
30
+ if (isServerless) {
31
+ try {
32
+ await tf.setBackend("cpu");
33
+ console.log("🚀 Backend CPU optimizado para entorno serverless");
34
+
35
+ // Optimizaciones específicas para CPU en serverless
36
+ tf.ENV.set("CPU_HANDOFF_SIZE_THRESHOLD", 1024 * 1024 * 2); // 2MB
37
+ tf.ENV.set("WEBGL_DELETE_TEXTURE_THRESHOLD", 0);
38
+
39
+ // Precalentar el backend
40
+ await tf.ready();
41
+ return "cpu";
42
+ } catch (cpuError) {
43
+ console.error("❌ Error crítico en configuración CPU:", cpuError);
44
+ throw new Error("No se pudo inicializar TensorFlow.js en modo serverless");
45
+ }
46
+ }
47
+
48
+ // Configuración optimizada para navegador (WebGL)
49
+ try {
50
+ // Optimizaciones avanzadas para WebGL
51
+ tf.ENV.set("WEBGL_PACK", true);
52
+ tf.ENV.set("WEBGL_PACK_DEPTHWISECONV", true);
53
+ tf.ENV.set("WEBGL_MAX_TEXTURE_SIZE", 4096);
54
+ tf.ENV.set("WEBGL_USE_SHAPES_UNIFORMS", true);
55
+ tf.ENV.set("WEBGL_CONV_IM2COL", true);
56
+
57
+ await tf.setBackend("webgl");
58
+ console.log("🎮 Backend WebGL activado con optimizaciones avanzadas");
59
+
60
+ // Precalentar el backend
61
+ await tf.ready();
62
+ return "webgl";
63
+ } catch (webglError) {
64
+ console.warn(
65
+ `No se pudo activar WebGL: ${webglError.message}, usando CPU como último recurso`,
66
+ );
67
+ }
68
+
69
+ // CPU Backend (más lento, último recurso)
70
+ await tf.setBackend("cpu");
71
+ console.log("⚠️ Backend CPU activado (rendimiento sub-óptimo)");
72
+
73
+ // Optimizaciones específicas para CPU
74
+ tf.ENV.set("CPU_HANDOFF_SIZE_THRESHOLD", 1024 * 1024 * 2); // 2MB
75
+ } catch (error) {
76
+ console.error("Error crítico configurando backends de TensorFlow:", error);
77
+ throw new Error("No se pudo inicializar TensorFlow.js con ningún backend");
78
+ }
79
+
80
+ // Registrar kernels específicos para el backend activo
81
+ const backend = tf.getBackend();
82
+ console.log(`Backend activo: ${backend}`);
83
+
84
+ return backend;
85
+ }
86
+
87
+ // Exportamos tf para poder usarlo en otros archivos
88
+ export { tf };