@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.
- package/README.md +62 -0
- package/dist/compiler/aframe.d.ts +1 -0
- package/dist/compiler/aframe.js +275 -0
- package/dist/compiler/compiler-base.d.ts +12 -0
- package/dist/compiler/compiler-base.js +165 -0
- package/dist/compiler/compiler.d.ts +9 -0
- package/dist/compiler/compiler.js +24 -0
- package/dist/compiler/compiler.worker.d.ts +1 -0
- package/dist/compiler/compiler.worker.js +28 -0
- package/dist/compiler/controller.d.ts +101 -0
- package/dist/compiler/controller.js +400 -0
- package/dist/compiler/controller.worker.d.ts +1 -0
- package/dist/compiler/controller.worker.js +61 -0
- package/dist/compiler/detector/crop-detector.d.ts +65 -0
- package/dist/compiler/detector/crop-detector.js +59 -0
- package/dist/compiler/detector/detector.d.ts +98 -0
- package/dist/compiler/detector/detector.js +1049 -0
- package/dist/compiler/detector/freak.d.ts +1 -0
- package/dist/compiler/detector/freak.js +89 -0
- package/dist/compiler/detector/kernels/cpu/binomialFilter.d.ts +6 -0
- package/dist/compiler/detector/kernels/cpu/binomialFilter.js +51 -0
- package/dist/compiler/detector/kernels/cpu/buildExtremas.d.ts +6 -0
- package/dist/compiler/detector/kernels/cpu/buildExtremas.js +89 -0
- package/dist/compiler/detector/kernels/cpu/computeExtremaAngles.d.ts +7 -0
- package/dist/compiler/detector/kernels/cpu/computeExtremaAngles.js +79 -0
- package/dist/compiler/detector/kernels/cpu/computeExtremaFreak.d.ts +6 -0
- package/dist/compiler/detector/kernels/cpu/computeExtremaFreak.js +68 -0
- package/dist/compiler/detector/kernels/cpu/computeFreakDescriptors.d.ts +6 -0
- package/dist/compiler/detector/kernels/cpu/computeFreakDescriptors.js +57 -0
- package/dist/compiler/detector/kernels/cpu/computeLocalization.d.ts +6 -0
- package/dist/compiler/detector/kernels/cpu/computeLocalization.js +54 -0
- package/dist/compiler/detector/kernels/cpu/computeOrientationHistograms.d.ts +6 -0
- package/dist/compiler/detector/kernels/cpu/computeOrientationHistograms.js +118 -0
- package/dist/compiler/detector/kernels/cpu/downsampleBilinear.d.ts +6 -0
- package/dist/compiler/detector/kernels/cpu/downsampleBilinear.js +29 -0
- package/dist/compiler/detector/kernels/cpu/extremaReduction.d.ts +6 -0
- package/dist/compiler/detector/kernels/cpu/extremaReduction.js +50 -0
- package/dist/compiler/detector/kernels/cpu/fakeShader.d.ts +20 -0
- package/dist/compiler/detector/kernels/cpu/fakeShader.js +80 -0
- package/dist/compiler/detector/kernels/cpu/index.d.ts +1 -0
- package/dist/compiler/detector/kernels/cpu/index.js +25 -0
- package/dist/compiler/detector/kernels/cpu/prune.d.ts +1 -0
- package/dist/compiler/detector/kernels/cpu/prune.js +103 -0
- package/dist/compiler/detector/kernels/cpu/smoothHistograms.d.ts +6 -0
- package/dist/compiler/detector/kernels/cpu/smoothHistograms.js +47 -0
- package/dist/compiler/detector/kernels/cpu/upsampleBilinear.d.ts +6 -0
- package/dist/compiler/detector/kernels/cpu/upsampleBilinear.js +43 -0
- package/dist/compiler/detector/kernels/index.d.ts +1 -0
- package/dist/compiler/detector/kernels/index.js +2 -0
- package/dist/compiler/detector/kernels/webgl/binomialFilter.d.ts +6 -0
- package/dist/compiler/detector/kernels/webgl/binomialFilter.js +67 -0
- package/dist/compiler/detector/kernels/webgl/buildExtremas.d.ts +6 -0
- package/dist/compiler/detector/kernels/webgl/buildExtremas.js +101 -0
- package/dist/compiler/detector/kernels/webgl/computeExtremaAngles.d.ts +6 -0
- package/dist/compiler/detector/kernels/webgl/computeExtremaAngles.js +78 -0
- package/dist/compiler/detector/kernels/webgl/computeExtremaFreak.d.ts +6 -0
- package/dist/compiler/detector/kernels/webgl/computeExtremaFreak.js +86 -0
- package/dist/compiler/detector/kernels/webgl/computeFreakDescriptors.d.ts +6 -0
- package/dist/compiler/detector/kernels/webgl/computeFreakDescriptors.js +52 -0
- package/dist/compiler/detector/kernels/webgl/computeLocalization.d.ts +6 -0
- package/dist/compiler/detector/kernels/webgl/computeLocalization.js +58 -0
- package/dist/compiler/detector/kernels/webgl/computeOrientationHistograms.d.ts +6 -0
- package/dist/compiler/detector/kernels/webgl/computeOrientationHistograms.js +116 -0
- package/dist/compiler/detector/kernels/webgl/downsampleBilinear.d.ts +6 -0
- package/dist/compiler/detector/kernels/webgl/downsampleBilinear.js +46 -0
- package/dist/compiler/detector/kernels/webgl/extremaReduction.d.ts +6 -0
- package/dist/compiler/detector/kernels/webgl/extremaReduction.js +48 -0
- package/dist/compiler/detector/kernels/webgl/index.d.ts +1 -0
- package/dist/compiler/detector/kernels/webgl/index.js +25 -0
- package/dist/compiler/detector/kernels/webgl/smoothHistograms.d.ts +6 -0
- package/dist/compiler/detector/kernels/webgl/smoothHistograms.js +49 -0
- package/dist/compiler/detector/kernels/webgl/upsampleBilinear.d.ts +6 -0
- package/dist/compiler/detector/kernels/webgl/upsampleBilinear.js +56 -0
- package/dist/compiler/estimation/esimate-experiment.d.ts +5 -0
- package/dist/compiler/estimation/esimate-experiment.js +267 -0
- package/dist/compiler/estimation/estimate.d.ts +5 -0
- package/dist/compiler/estimation/estimate.js +51 -0
- package/dist/compiler/estimation/estimator.d.ts +13 -0
- package/dist/compiler/estimation/estimator.js +30 -0
- package/dist/compiler/estimation/refine-estimate-experiment.d.ts +6 -0
- package/dist/compiler/estimation/refine-estimate-experiment.js +429 -0
- package/dist/compiler/estimation/refine-estimate.d.ts +6 -0
- package/dist/compiler/estimation/refine-estimate.js +299 -0
- package/dist/compiler/estimation/utils.d.ts +10 -0
- package/dist/compiler/estimation/utils.js +80 -0
- package/dist/compiler/image-list.d.ts +13 -0
- package/dist/compiler/image-list.js +52 -0
- package/dist/compiler/index.d.ts +3 -0
- package/dist/compiler/index.js +10 -0
- package/dist/compiler/input-loader.d.ts +23 -0
- package/dist/compiler/input-loader.js +88 -0
- package/dist/compiler/matching/hamming-distance.d.ts +1 -0
- package/dist/compiler/matching/hamming-distance.js +20 -0
- package/dist/compiler/matching/hierarchical-clustering.d.ts +7 -0
- package/dist/compiler/matching/hierarchical-clustering.js +109 -0
- package/dist/compiler/matching/hough.d.ts +1 -0
- package/dist/compiler/matching/hough.js +169 -0
- package/dist/compiler/matching/matcher.d.ts +28 -0
- package/dist/compiler/matching/matcher.js +48 -0
- package/dist/compiler/matching/matching.d.ts +41 -0
- package/dist/compiler/matching/matching.js +197 -0
- package/dist/compiler/matching/ransacHomography.d.ts +1 -0
- package/dist/compiler/matching/ransacHomography.js +136 -0
- package/dist/compiler/offline-compiler.d.ts +10 -0
- package/dist/compiler/offline-compiler.js +450 -0
- package/dist/compiler/tensorflow-setup.d.ts +7 -0
- package/dist/compiler/tensorflow-setup.js +73 -0
- package/dist/compiler/three.d.ts +66 -0
- package/dist/compiler/three.js +310 -0
- package/dist/compiler/tracker/extract-utils.d.ts +1 -0
- package/dist/compiler/tracker/extract-utils.js +29 -0
- package/dist/compiler/tracker/extract.d.ts +4 -0
- package/dist/compiler/tracker/extract.js +349 -0
- package/dist/compiler/tracker/tracker.d.ts +38 -0
- package/dist/compiler/tracker/tracker.js +327 -0
- package/dist/compiler/utils/cumsum.d.ts +5 -0
- package/dist/compiler/utils/cumsum.js +39 -0
- package/dist/compiler/utils/geometry.d.ts +8 -0
- package/dist/compiler/utils/geometry.js +101 -0
- package/dist/compiler/utils/homography.d.ts +1 -0
- package/dist/compiler/utils/homography.js +138 -0
- package/dist/compiler/utils/images.d.ts +24 -0
- package/dist/compiler/utils/images.js +99 -0
- package/dist/compiler/utils/randomizer.d.ts +5 -0
- package/dist/compiler/utils/randomizer.js +25 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +7 -0
- package/dist/react/AREditor.d.ts +5 -0
- package/dist/react/AREditor.js +159 -0
- package/dist/react/ProgressDialog.d.ts +13 -0
- package/dist/react/ProgressDialog.js +57 -0
- package/dist/react/types.d.ts +22 -0
- package/dist/react/types.js +14 -0
- package/package.json +53 -0
- package/src/astro/ARScene.astro +59 -0
- package/src/astro/ARVideoTrigger.astro +73 -0
- package/src/astro/overlays/ErrorOverlay.astro +40 -0
- package/src/astro/overlays/LoadingOverlay.astro +28 -0
- package/src/astro/overlays/ScanningOverlay.astro +119 -0
- package/src/astro/scripts/ARScripts.astro +118 -0
- package/src/astro/styles/ARStyles.astro +147 -0
- package/src/compiler/aframe.js +343 -0
- package/src/compiler/compiler-base.js +195 -0
- package/src/compiler/compiler.js +25 -0
- package/src/compiler/compiler.worker.js +30 -0
- package/src/compiler/controller.js +473 -0
- package/src/compiler/controller.worker.js +77 -0
- package/src/compiler/detector/crop-detector.js +68 -0
- package/src/compiler/detector/detector.js +1130 -0
- package/src/compiler/detector/freak.js +91 -0
- package/src/compiler/detector/kernels/cpu/binomialFilter.js +59 -0
- package/src/compiler/detector/kernels/cpu/buildExtremas.js +108 -0
- package/src/compiler/detector/kernels/cpu/computeExtremaAngles.js +91 -0
- package/src/compiler/detector/kernels/cpu/computeExtremaFreak.js +92 -0
- package/src/compiler/detector/kernels/cpu/computeFreakDescriptors.js +68 -0
- package/src/compiler/detector/kernels/cpu/computeLocalization.js +71 -0
- package/src/compiler/detector/kernels/cpu/computeOrientationHistograms.js +141 -0
- package/src/compiler/detector/kernels/cpu/downsampleBilinear.js +33 -0
- package/src/compiler/detector/kernels/cpu/extremaReduction.js +53 -0
- package/src/compiler/detector/kernels/cpu/fakeShader.js +88 -0
- package/src/compiler/detector/kernels/cpu/index.js +26 -0
- package/src/compiler/detector/kernels/cpu/prune.js +114 -0
- package/src/compiler/detector/kernels/cpu/smoothHistograms.js +57 -0
- package/src/compiler/detector/kernels/cpu/upsampleBilinear.js +51 -0
- package/src/compiler/detector/kernels/index.js +2 -0
- package/src/compiler/detector/kernels/webgl/binomialFilter.js +72 -0
- package/src/compiler/detector/kernels/webgl/buildExtremas.js +109 -0
- package/src/compiler/detector/kernels/webgl/computeExtremaAngles.js +82 -0
- package/src/compiler/detector/kernels/webgl/computeExtremaFreak.js +105 -0
- package/src/compiler/detector/kernels/webgl/computeFreakDescriptors.js +56 -0
- package/src/compiler/detector/kernels/webgl/computeLocalization.js +70 -0
- package/src/compiler/detector/kernels/webgl/computeOrientationHistograms.js +129 -0
- package/src/compiler/detector/kernels/webgl/downsampleBilinear.js +50 -0
- package/src/compiler/detector/kernels/webgl/extremaReduction.js +50 -0
- package/src/compiler/detector/kernels/webgl/index.js +26 -0
- package/src/compiler/detector/kernels/webgl/smoothHistograms.js +53 -0
- package/src/compiler/detector/kernels/webgl/upsampleBilinear.js +62 -0
- package/src/compiler/estimation/esimate-experiment.js +316 -0
- package/src/compiler/estimation/estimate.js +67 -0
- package/src/compiler/estimation/estimator.js +34 -0
- package/src/compiler/estimation/refine-estimate-experiment.js +512 -0
- package/src/compiler/estimation/refine-estimate.js +365 -0
- package/src/compiler/estimation/utils.js +97 -0
- package/src/compiler/image-list.js +62 -0
- package/src/compiler/index.js +13 -0
- package/src/compiler/input-loader.js +107 -0
- package/src/compiler/matching/hamming-distance.js +23 -0
- package/src/compiler/matching/hierarchical-clustering.js +131 -0
- package/src/compiler/matching/hough.js +206 -0
- package/src/compiler/matching/matcher.js +59 -0
- package/src/compiler/matching/matching.js +237 -0
- package/src/compiler/matching/ransacHomography.js +192 -0
- package/src/compiler/offline-compiler.js +553 -0
- package/src/compiler/tensorflow-setup.js +88 -0
- package/src/compiler/three.js +368 -0
- package/src/compiler/tracker/extract-utils.js +34 -0
- package/src/compiler/tracker/extract.js +419 -0
- package/src/compiler/tracker/tracker.js +397 -0
- package/src/compiler/utils/cumsum.js +40 -0
- package/src/compiler/utils/geometry.js +114 -0
- package/src/compiler/utils/homography.js +150 -0
- package/src/compiler/utils/images.js +111 -0
- package/src/compiler/utils/randomizer.js +29 -0
- package/src/index.ts +8 -0
- package/src/react/AREditor.tsx +394 -0
- package/src/react/ProgressDialog.tsx +185 -0
- 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 };
|