dhvazquez commited on
Commit
fcbd81b
·
verified ·
1 Parent(s): f708f15

Delete model-inference.js

Browse files
Files changed (1) hide show
  1. model-inference.js +0 -472
model-inference.js DELETED
@@ -1,472 +0,0 @@
1
- /**
2
- * Model inference module using ONNX Runtime Web
3
- */
4
-
5
- class ModelInference {
6
- constructor() {
7
- this.session = null;
8
- this.isModelLoaded = false;
9
- this.isInferring = false;
10
- this.modelPath = 'models/card_segmentation.onnx';
11
-
12
- // Model specifications
13
- this.inputHeight = 320;
14
- this.inputWidth = 240;
15
- this.numClasses = 2;
16
-
17
- // GPU acceleration info
18
- this.accelerationInfo = {
19
- activeProvider: 'unknown',
20
- availableProviders: [],
21
- gpuInfo: null,
22
- supportsWebGL: false,
23
- supportsWebGPU: false
24
- };
25
-
26
- // Performance tracking
27
- this.inferenceStats = {
28
- totalInferences: 0,
29
- totalTime: 0,
30
- averageTime: 0,
31
- lastInferenceTime: 0
32
- };
33
- }
34
-
35
- /**
36
- * Initialize ONNX Runtime and load the model with GPU acceleration
37
- * @returns {Promise<boolean>}
38
- */
39
- async initialize() {
40
- try {
41
- console.log('Initializing ONNX Runtime with GPU acceleration...');
42
-
43
- // Configure ONNX Runtime
44
- ort.env.wasm.wasmPaths = 'https://cdn.jsdelivr.net/npm/onnxruntime-web@1.22.0/dist/';
45
- ort.env.wasm.numThreads = 1; // Single thread for stability
46
-
47
- // Detect GPU capabilities
48
- await this.detectGPUCapabilities();
49
-
50
- // Determine optimal execution providers
51
- const executionProviders = this.getOptimalExecutionProviders();
52
-
53
- console.log('Attempting to load model with providers:', executionProviders);
54
- console.log(`Loading model from: ${this.modelPath}`);
55
-
56
- // Try to load model with optimal providers
57
- this.session = await this.loadModelWithFallback(executionProviders);
58
-
59
- console.log(`Model loaded successfully with provider: ${this.accelerationInfo.activeProvider}`);
60
- this.isModelLoaded = true;
61
-
62
- // Log model and acceleration information
63
- this.logModelInfo();
64
- this.logAccelerationInfo();
65
-
66
- return true;
67
- } catch (error) {
68
- console.error('Failed to initialize model:', error);
69
- this.isModelLoaded = false;
70
- throw new Error(`Model initialization failed: ${error.message}`);
71
- }
72
- }
73
-
74
- /**
75
- * Detect GPU capabilities and available acceleration
76
- */
77
- async detectGPUCapabilities() {
78
- console.log('Detecting GPU capabilities...');
79
-
80
- // Check WebGL support
81
- this.accelerationInfo.supportsWebGL = this.checkWebGLSupport();
82
-
83
- // Check WebGPU support
84
- this.accelerationInfo.supportsWebGPU = await this.checkWebGPUSupport();
85
-
86
- // Get GPU info if available
87
- if (this.accelerationInfo.supportsWebGL) {
88
- this.accelerationInfo.gpuInfo = this.getWebGLInfo();
89
- }
90
-
91
- console.log('GPU Capabilities:', {
92
- WebGL: this.accelerationInfo.supportsWebGL,
93
- WebGPU: this.accelerationInfo.supportsWebGPU,
94
- GPU: this.accelerationInfo.gpuInfo
95
- });
96
- }
97
-
98
- /**
99
- * Check WebGL support
100
- * @returns {boolean}
101
- */
102
- checkWebGLSupport() {
103
- try {
104
- const canvas = document.createElement('canvas');
105
- const gl = canvas.getContext('webgl') || canvas.getContext('experimental-webgl');
106
- return !!gl;
107
- } catch (error) {
108
- console.warn('WebGL check failed:', error);
109
- return false;
110
- }
111
- }
112
-
113
- /**
114
- * Check WebGPU support
115
- * @returns {Promise<boolean>}
116
- */
117
- async checkWebGPUSupport() {
118
- try {
119
- if (!navigator.gpu) {
120
- return false;
121
- }
122
-
123
- const adapter = await navigator.gpu.requestAdapter();
124
- return !!adapter;
125
- } catch (error) {
126
- console.warn('WebGPU check failed:', error);
127
- return false;
128
- }
129
- }
130
-
131
- /**
132
- * Get WebGL renderer information
133
- * @returns {Object|null}
134
- */
135
- getWebGLInfo() {
136
- try {
137
- const canvas = document.createElement('canvas');
138
- const gl = canvas.getContext('webgl') || canvas.getContext('experimental-webgl');
139
-
140
- if (!gl) return null;
141
-
142
- const debugInfo = gl.getExtension('WEBGL_debug_renderer_info');
143
-
144
- return {
145
- vendor: debugInfo ? gl.getParameter(debugInfo.UNMASKED_VENDOR_WEBGL) : gl.getParameter(gl.VENDOR),
146
- renderer: debugInfo ? gl.getParameter(debugInfo.UNMASKED_RENDERER_WEBGL) : gl.getParameter(gl.RENDERER),
147
- version: gl.getParameter(gl.VERSION),
148
- shadingLanguageVersion: gl.getParameter(gl.SHADING_LANGUAGE_VERSION)
149
- };
150
- } catch (error) {
151
- console.warn('Failed to get WebGL info:', error);
152
- return null;
153
- }
154
- }
155
-
156
- /**
157
- * Determine optimal execution providers based on capabilities
158
- * @returns {Array<string>}
159
- */
160
- getOptimalExecutionProviders() {
161
- const providers = [];
162
-
163
- // Prioritize WebGPU first for best performance
164
- if (this.accelerationInfo.supportsWebGPU) {
165
- providers.push('webgpu');
166
- this.accelerationInfo.availableProviders.push('webgpu');
167
- }
168
-
169
- // Fall back to WebGL if WebGPU is not available or fails
170
- if (this.accelerationInfo.supportsWebGL) {
171
- providers.push('webgl');
172
- this.accelerationInfo.availableProviders.push('webgl');
173
- }
174
-
175
- // Always add WASM as final fallback
176
- providers.push('wasm');
177
- this.accelerationInfo.availableProviders.push('wasm');
178
-
179
- return providers;
180
- }
181
-
182
- /**
183
- * Load model with fallback mechanism
184
- * @param {Array<string>} executionProviders
185
- * @returns {Promise<InferenceSession>}
186
- */
187
- async loadModelWithFallback(executionProviders) {
188
- const baseOptions = {
189
- enableMemPattern: false,
190
- enableCpuMemArena: false,
191
- graphOptimizationLevel: 'all'
192
- };
193
-
194
- // Try each provider in order
195
- for (const provider of executionProviders) {
196
- try {
197
- console.log(`Attempting to load model with ${provider} provider...`);
198
-
199
- const options = {
200
- ...baseOptions,
201
- executionProviders: [provider]
202
- };
203
-
204
- const session = await ort.InferenceSession.create(this.modelPath, options);
205
- this.accelerationInfo.activeProvider = provider;
206
-
207
- console.log(`✓ Successfully loaded with ${provider} provider`);
208
- return session;
209
- } catch (error) {
210
- const errorMsg = error.message;
211
-
212
- // Log specific information for operator compatibility issues
213
- if (errorMsg.includes('cannot resolve operator')) {
214
- const operatorName = errorMsg.match(/operator '(\w+)'/)?.[1] || 'unknown';
215
- console.warn(`✗ ${provider.toUpperCase()} provider doesn't support operator '${operatorName}' - falling back to next provider`);
216
- } else {
217
- console.warn(`✗ Failed to load with ${provider} provider:`, errorMsg);
218
- }
219
-
220
- // Store failed provider info for reporting
221
- this.accelerationInfo[`${provider}Error`] = errorMsg;
222
- continue;
223
- }
224
- }
225
-
226
- throw new Error('Failed to load model with any execution provider');
227
- }
228
-
229
- /**
230
- * Log acceleration information
231
- */
232
- logAccelerationInfo() {
233
- console.log('=== Acceleration Information ===');
234
- console.log(`Active Provider: ${this.accelerationInfo.activeProvider}`);
235
- console.log(`Available Providers: ${this.accelerationInfo.availableProviders.join(', ')}`);
236
- console.log(`WebGL Support: ${this.accelerationInfo.supportsWebGL}`);
237
- console.log(`WebGPU Support: ${this.accelerationInfo.supportsWebGPU}`);
238
-
239
- if (this.accelerationInfo.gpuInfo) {
240
- console.log('GPU Information:');
241
- console.log(` Vendor: ${this.accelerationInfo.gpuInfo.vendor}`);
242
- console.log(` Renderer: ${this.accelerationInfo.gpuInfo.renderer}`);
243
- console.log(` Version: ${this.accelerationInfo.gpuInfo.version}`);
244
- }
245
- console.log('===============================');
246
- }
247
-
248
- /**
249
- * Get acceleration information
250
- * @returns {Object}
251
- */
252
- getAccelerationInfo() {
253
- return { ...this.accelerationInfo };
254
- }
255
-
256
- /**
257
- * Log model information for debugging
258
- */
259
- logModelInfo() {
260
- if (!this.session) return;
261
-
262
- console.log('=== Model Information ===');
263
- console.log('Input tensors:');
264
- this.session.inputNames.forEach((name, index) => {
265
- // Try to access input metadata safely
266
- try {
267
- if (this.session.inputs && this.session.inputs[index]) {
268
- const input = this.session.inputs[index];
269
- console.log(` ${name}: ${input.dims} (${input.type})`);
270
- } else {
271
- console.log(` ${name}: metadata not available`);
272
- }
273
- } catch (error) {
274
- console.log(` ${name}: metadata not available`);
275
- }
276
- });
277
-
278
- console.log('Output tensors:');
279
- this.session.outputNames.forEach((name, index) => {
280
- // Try to access output metadata safely
281
- try {
282
- if (this.session.outputs && this.session.outputs[index]) {
283
- const output = this.session.outputs[index];
284
- console.log(` ${name}: ${output.dims} (${output.type})`);
285
- } else {
286
- console.log(` ${name}: metadata not available`);
287
- }
288
- } catch (error) {
289
- console.log(` ${name}: metadata not available`);
290
- }
291
- });
292
- console.log('========================');
293
- }
294
-
295
- /**
296
- * Run inference on preprocessed image data
297
- * @param {Float32Array} inputData
298
- * @returns {Promise<Float32Array>}
299
- */
300
- async runInference(inputData) {
301
- if (!this.isModelLoaded || !this.session) {
302
- throw new Error('Model not loaded. Call initialize() first.');
303
- }
304
-
305
- if (this.isInferring) {
306
- console.warn('Inference already in progress, skipping...');
307
- return null;
308
- }
309
-
310
- try {
311
- this.isInferring = true;
312
- const startTime = performance.now();
313
-
314
- // Create input tensor
315
- const inputTensor = new ort.Tensor('float32', inputData, [1, 3, this.inputHeight, this.inputWidth]);
316
-
317
- // Get input name from model
318
- const inputName = this.session.inputNames[0];
319
-
320
- // Run inference
321
- const results = await this.session.run({ [inputName]: inputTensor });
322
-
323
- // Get output tensor
324
- const outputName = this.session.outputNames[0];
325
- const outputTensor = results[outputName];
326
-
327
- // Calculate inference time
328
- const endTime = performance.now();
329
- const inferenceTime = endTime - startTime;
330
-
331
- // Update statistics
332
- this.updateInferenceStats(inferenceTime);
333
-
334
- console.log(`Inference completed in ${inferenceTime.toFixed(2)}ms`);
335
-
336
- return outputTensor.data;
337
- } catch (error) {
338
- console.error('Inference failed:', error);
339
- throw new Error(`Inference failed: ${error.message}`);
340
- } finally {
341
- this.isInferring = false;
342
- }
343
- }
344
-
345
- /**
346
- * Process video frame and return segmentation mask
347
- * @param {HTMLVideoElement} video
348
- * @returns {Promise<Object>} - {mask: Uint8Array, stats: Object}
349
- */
350
- async processVideoFrame(video) {
351
- try {
352
- // Check if model is ready
353
- if (!this.isModelLoaded) {
354
- throw new Error('Model not initialized');
355
- }
356
-
357
- // Get video dimensions
358
- const videoWidth = video.videoWidth;
359
- const videoHeight = video.videoHeight;
360
-
361
- if (videoWidth === 0 || videoHeight === 0) {
362
- throw new Error('Video not ready');
363
- }
364
-
365
- // Determine if rotation is needed for model input
366
- const shouldRotateForModel = ImageUtils.shouldRotateForModel(videoWidth, videoHeight);
367
-
368
- // Preprocess video frame
369
- const preprocessedData = ImageUtils.preprocessVideoFrame(
370
- video,
371
- this.inputWidth,
372
- this.inputHeight,
373
- shouldRotateForModel
374
- );
375
-
376
- // Run inference
377
- const modelOutput = await this.runInference(preprocessedData);
378
-
379
- if (!modelOutput) {
380
- return null; // Inference skipped
381
- }
382
-
383
- // Process model output to create mask
384
- const mask = ImageUtils.processModelOutput(
385
- modelOutput,
386
- this.inputHeight,
387
- this.inputWidth
388
- );
389
-
390
- return {
391
- mask: mask,
392
- shouldRotateBack: shouldRotateForModel,
393
- stats: this.getInferenceStats()
394
- };
395
- } catch (error) {
396
- console.error('Error processing video frame:', error);
397
- throw error;
398
- }
399
- }
400
-
401
- /**
402
- * Update inference performance statistics
403
- * @param {number} inferenceTime
404
- */
405
- updateInferenceStats(inferenceTime) {
406
- this.inferenceStats.totalInferences++;
407
- this.inferenceStats.totalTime += inferenceTime;
408
- this.inferenceStats.averageTime = this.inferenceStats.totalTime / this.inferenceStats.totalInferences;
409
- this.inferenceStats.lastInferenceTime = inferenceTime;
410
- }
411
-
412
- /**
413
- * Get current inference statistics
414
- * @returns {Object}
415
- */
416
- getInferenceStats() {
417
- return {
418
- ...this.inferenceStats,
419
- fps: this.inferenceStats.lastInferenceTime > 0 ?
420
- 1000 / this.inferenceStats.lastInferenceTime : 0
421
- };
422
- }
423
-
424
- /**
425
- * Reset inference statistics
426
- */
427
- resetStats() {
428
- this.inferenceStats = {
429
- totalInferences: 0,
430
- totalTime: 0,
431
- averageTime: 0,
432
- lastInferenceTime: 0
433
- };
434
- }
435
-
436
- /**
437
- * Check if model is ready for inference
438
- * @returns {boolean}
439
- */
440
- isReady() {
441
- return this.isModelLoaded && !this.isInferring;
442
- }
443
-
444
- /**
445
- * Get model specifications
446
- * @returns {Object}
447
- */
448
- getModelSpecs() {
449
- return {
450
- inputHeight: this.inputHeight,
451
- inputWidth: this.inputWidth,
452
- numClasses: this.numClasses,
453
- isLoaded: this.isModelLoaded
454
- };
455
- }
456
-
457
- /**
458
- * Dispose of the model and free resources
459
- */
460
- dispose() {
461
- if (this.session) {
462
- this.session.release();
463
- this.session = null;
464
- }
465
- this.isModelLoaded = false;
466
- this.isInferring = false;
467
- console.log('Model resources disposed');
468
- }
469
- }
470
-
471
- // Export for use in other modules
472
- window.ModelInference = ModelInference;