@jaak.ai/stamps 2.0.0-dev.31 → 2.0.0-dev.33
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/jaak-stamps-webcomponent.cjs.js +1 -1
- package/dist/cjs/jaak-stamps.cjs.entry.js +212 -19
- package/dist/cjs/jaak-stamps.cjs.entry.js.map +1 -1
- package/dist/cjs/jaak-stamps.entry.cjs.js.map +1 -1
- package/dist/cjs/loader.cjs.js +1 -1
- package/dist/collection/components/my-component/my-component.css +248 -115
- package/dist/collection/components/my-component/my-component.js +205 -15
- package/dist/collection/components/my-component/my-component.js.map +1 -1
- package/dist/collection/services/DetectionService.js +10 -4
- package/dist/collection/services/DetectionService.js.map +1 -1
- package/dist/components/jaak-stamps.js +215 -19
- package/dist/components/jaak-stamps.js.map +1 -1
- package/dist/esm/jaak-stamps-webcomponent.js +1 -1
- package/dist/esm/jaak-stamps.entry.js +212 -19
- package/dist/esm/jaak-stamps.entry.js.map +1 -1
- package/dist/esm/loader.js +1 -1
- package/dist/jaak-stamps-webcomponent/jaak-stamps-webcomponent.esm.js +1 -1
- package/dist/jaak-stamps-webcomponent/jaak-stamps.entry.esm.js.map +1 -1
- package/dist/jaak-stamps-webcomponent/p-9d1c45a9.entry.js +2 -0
- package/dist/jaak-stamps-webcomponent/p-9d1c45a9.entry.js.map +1 -0
- package/dist/types/components/my-component/my-component.d.ts +22 -0
- package/package.json +3 -3
- package/dist/jaak-stamps-webcomponent/p-5051b84e.entry.js +0 -2
- package/dist/jaak-stamps-webcomponent/p-5051b84e.entry.js.map +0 -1
|
@@ -18,12 +18,24 @@ export class JaakStamps {
|
|
|
18
18
|
isMaskReady = false;
|
|
19
19
|
shouldMirrorVideo = true;
|
|
20
20
|
showCameraSelector = false;
|
|
21
|
+
isSwitchingCamera = false;
|
|
21
22
|
currentStatus = {
|
|
22
23
|
message: 'Inicializando componente...',
|
|
23
24
|
description: 'Configurando servicios y cargando recursos',
|
|
24
25
|
type: 'initializing',
|
|
25
26
|
isInitialized: false
|
|
26
27
|
};
|
|
28
|
+
performanceData = {
|
|
29
|
+
fps: 0,
|
|
30
|
+
inferenceTime: 0,
|
|
31
|
+
memoryUsage: 0,
|
|
32
|
+
onnxLoadTime: 0,
|
|
33
|
+
frameProcessingTime: 0,
|
|
34
|
+
totalDetections: 0,
|
|
35
|
+
successfulDetections: 0,
|
|
36
|
+
detectionRate: 0
|
|
37
|
+
};
|
|
38
|
+
isPerformanceMonitorMinimized = false;
|
|
27
39
|
// Services
|
|
28
40
|
serviceContainer;
|
|
29
41
|
logger;
|
|
@@ -40,6 +52,22 @@ export class JaakStamps {
|
|
|
40
52
|
lastDetectedBox;
|
|
41
53
|
startTime;
|
|
42
54
|
hasScreenshotTaken = false;
|
|
55
|
+
alignmentStartTime;
|
|
56
|
+
alignmentTimer;
|
|
57
|
+
// Performance monitoring
|
|
58
|
+
performanceMetrics = {
|
|
59
|
+
fps: 0,
|
|
60
|
+
inferenceTime: 0,
|
|
61
|
+
memoryUsage: 0,
|
|
62
|
+
cpuUsage: 0,
|
|
63
|
+
onnxLoadTime: 0,
|
|
64
|
+
frameProcessingTime: 0,
|
|
65
|
+
totalDetections: 0,
|
|
66
|
+
successfulDetections: 0,
|
|
67
|
+
detectionRate: 0,
|
|
68
|
+
lastUpdateTime: 0
|
|
69
|
+
};
|
|
70
|
+
performanceUpdateInterval;
|
|
43
71
|
// Performance optimization
|
|
44
72
|
frameSkipCounter = 0;
|
|
45
73
|
FRAME_SKIP = 2;
|
|
@@ -54,6 +82,9 @@ export class JaakStamps {
|
|
|
54
82
|
await this.setupEventListeners();
|
|
55
83
|
this.updateStatus('Inicializando cámara...', 'Detectando dispositivos disponibles', 'initializing');
|
|
56
84
|
await this.initializeComponent();
|
|
85
|
+
if (this.debug) {
|
|
86
|
+
this.initializePerformanceMonitor();
|
|
87
|
+
}
|
|
57
88
|
}
|
|
58
89
|
async initializeServices() {
|
|
59
90
|
const config = {
|
|
@@ -294,17 +325,24 @@ export class JaakStamps {
|
|
|
294
325
|
return { success: true, message: 'Model already loaded' };
|
|
295
326
|
}
|
|
296
327
|
try {
|
|
328
|
+
const loadStartTime = performance.now();
|
|
297
329
|
this.updateStatus('Descargando modelo de detección...', 'Obteniendo red neuronal para reconocimiento de documentos', 'loading');
|
|
298
330
|
this.stateManager.updateCaptureState({ isLoading: true });
|
|
299
331
|
await this.detectionService.loadModel();
|
|
300
332
|
this.updateStatus('Cargando clasificador...', 'Preparando modelo de clasificación de tipos de documento', 'loading');
|
|
301
333
|
await this.detectionService.loadClassificationModel();
|
|
334
|
+
const loadEndTime = performance.now();
|
|
335
|
+
const loadTime = loadEndTime - loadStartTime;
|
|
336
|
+
// Record ONNX load time
|
|
337
|
+
if (this.debug) {
|
|
338
|
+
this.recordOnnxPerformance(loadTime, 0);
|
|
339
|
+
}
|
|
302
340
|
this.updateStatus('Optimizando modelos...', 'Configurando parámetros de rendimiento', 'loading');
|
|
303
341
|
await new Promise(resolve => setTimeout(resolve, 300));
|
|
304
342
|
this.updateStatus('Modelos precargados', '', 'ready');
|
|
305
343
|
this.stateManager.updateCaptureState({ isLoading: false });
|
|
306
344
|
this.emitReadyEvent();
|
|
307
|
-
this.logger.state('MODELOS_PRECARGADOS_EXITOSAMENTE');
|
|
345
|
+
this.logger.state('MODELOS_PRECARGADOS_EXITOSAMENTE', { loadTime: Math.round(loadTime) });
|
|
308
346
|
return { success: true, message: 'Models preloaded successfully' };
|
|
309
347
|
}
|
|
310
348
|
catch (error) {
|
|
@@ -340,11 +378,19 @@ export class JaakStamps {
|
|
|
340
378
|
try {
|
|
341
379
|
// Paso 1: Verificar y cargar modelos si es necesario
|
|
342
380
|
if (!this.detectionService.isModelLoaded()) {
|
|
381
|
+
const loadStartTime = performance.now();
|
|
343
382
|
this.updateStatus('Cargando modelo de detección...', 'Descargando red neuronal para reconocimiento', 'loading');
|
|
344
383
|
this.stateManager.updateCaptureState({ isLoading: true });
|
|
345
384
|
await this.detectionService.loadModel();
|
|
346
385
|
this.updateStatus('Cargando clasificador...', 'Preparando modelo de clasificación de documentos', 'loading');
|
|
347
386
|
await this.detectionService.loadClassificationModel();
|
|
387
|
+
const loadEndTime = performance.now();
|
|
388
|
+
const loadTime = loadEndTime - loadStartTime;
|
|
389
|
+
// Record ONNX load time
|
|
390
|
+
if (this.debug) {
|
|
391
|
+
this.recordOnnxPerformance(loadTime, 0);
|
|
392
|
+
}
|
|
393
|
+
this.logger.state('MODELOS_CARGADOS_EN_DETECCION', { loadTime: Math.round(loadTime) });
|
|
348
394
|
}
|
|
349
395
|
// Paso 2: Detectar y configurar dispositivos
|
|
350
396
|
this.updateStatus('Detectando cámaras...', 'Buscando dispositivos de captura disponibles', 'loading');
|
|
@@ -396,6 +442,7 @@ export class JaakStamps {
|
|
|
396
442
|
}
|
|
397
443
|
async detectFrame() {
|
|
398
444
|
try {
|
|
445
|
+
const frameStartTime = performance.now();
|
|
399
446
|
const captureState = this.stateManager.getCaptureState();
|
|
400
447
|
if (!this.videoRef || !this.detectionContainer || !this.detectionService.isModelLoaded())
|
|
401
448
|
return;
|
|
@@ -423,8 +470,15 @@ export class JaakStamps {
|
|
|
423
470
|
return;
|
|
424
471
|
}
|
|
425
472
|
this.lastInferenceTime = currentTime;
|
|
473
|
+
// Measure preprocessing and inference time
|
|
474
|
+
const inferenceStartTime = performance.now();
|
|
426
475
|
const inputTensor = this.detectionService.preprocess(this.videoRef);
|
|
427
476
|
const detections = await this.detectionService.runInference(inputTensor);
|
|
477
|
+
const inferenceTime = performance.now() - inferenceStartTime;
|
|
478
|
+
// Record ONNX performance metrics
|
|
479
|
+
if (this.debug) {
|
|
480
|
+
this.recordOnnxPerformance(0, inferenceTime);
|
|
481
|
+
}
|
|
428
482
|
// Update best score logic
|
|
429
483
|
if (this.startTime && Date.now() - this.startTime < 5000) {
|
|
430
484
|
detections.forEach(detection => {
|
|
@@ -450,6 +504,12 @@ export class JaakStamps {
|
|
|
450
504
|
this.detectionBoxes = [];
|
|
451
505
|
}
|
|
452
506
|
this.updateMaskColor(detections);
|
|
507
|
+
// Record frame processing metrics
|
|
508
|
+
if (this.debug) {
|
|
509
|
+
const frameEndTime = performance.now();
|
|
510
|
+
const totalFrameTime = frameEndTime - frameStartTime;
|
|
511
|
+
this.recordFrameProcessing(totalFrameTime, detections.length);
|
|
512
|
+
}
|
|
453
513
|
// Continue detection loop
|
|
454
514
|
if (captureState.step !== 'completed') {
|
|
455
515
|
if (this.consecutiveFailures > this.MAX_FAILURES) {
|
|
@@ -480,7 +540,16 @@ export class JaakStamps {
|
|
|
480
540
|
if (this.videoStream) {
|
|
481
541
|
this.videoStream.getTracks().forEach(track => track.stop());
|
|
482
542
|
}
|
|
543
|
+
if (this.alignmentTimer) {
|
|
544
|
+
clearTimeout(this.alignmentTimer);
|
|
545
|
+
this.alignmentTimer = undefined;
|
|
546
|
+
}
|
|
547
|
+
if (this.performanceUpdateInterval) {
|
|
548
|
+
clearInterval(this.performanceUpdateInterval);
|
|
549
|
+
this.performanceUpdateInterval = undefined;
|
|
550
|
+
}
|
|
483
551
|
this.detectionBoxes = [];
|
|
552
|
+
this.alignmentStartTime = undefined;
|
|
484
553
|
this.serviceContainer?.cleanup();
|
|
485
554
|
}
|
|
486
555
|
render() {
|
|
@@ -499,7 +568,7 @@ export class JaakStamps {
|
|
|
499
568
|
deviceType: 'desktop',
|
|
500
569
|
preferredFacing: null
|
|
501
570
|
};
|
|
502
|
-
return (h("div", { key: '
|
|
571
|
+
return (h("div", { key: '6d83055c7dcfc6c6f77e99d8439866aaca31f323', class: "detector-container" }, h("div", { key: '89d95da0fbee2bf03a455da911103d13f2d55a64', class: "video-container" }, h("video", { key: 'a06b3df2a0c2de21c4c3113ca5357a0518168214', ref: el => this.videoRef = el, autoplay: true, muted: true, playsinline: true, class: this.shouldMirrorVideo ? 'mirror' : '', style: { display: captureState.isVideoActive ? 'block' : 'none' } }), h("div", { key: 'a11ae04dd825208d069a02368708811a718a5b68', ref: el => this.detectionContainer = el, class: `detection-overlay ${this.shouldMirrorVideo ? 'mirror' : ''}` }, this.debug && this.detectionBoxes.map((box, index) => (h("div", { key: index, class: "detection-box", style: {
|
|
503
572
|
position: 'absolute',
|
|
504
573
|
left: `${box.x}px`,
|
|
505
574
|
top: `${box.y}px`,
|
|
@@ -508,10 +577,7 @@ export class JaakStamps {
|
|
|
508
577
|
border: '2px solid #32406C',
|
|
509
578
|
pointerEvents: 'none',
|
|
510
579
|
boxSizing: 'border-box'
|
|
511
|
-
} })))), this.isMaskReady && (h("div", { key: '
|
|
512
|
-
this.cameraService.switchCamera(camera.id);
|
|
513
|
-
this.toggleCameraSelector();
|
|
514
|
-
}, type: "button" }, h("span", { class: "camera-label" }, camera.label || `Cámara ${cameraInfo.availableCameras.indexOf(camera) + 1}`), cameraInfo.selectedCameraId === camera.id && (h("span", { class: "selected-indicator" }, "\u2713")))))), h("div", { key: 'afd0e161367e9dcf9105bef6fa3510a8fa25d221', class: "device-info" }, h("small", { key: 'fd57d4bfaba32b77d441d163491655468b0263d2' }, "Dispositivo: ", cameraInfo.deviceType)))))), captureState.isCapturing && (h("div", { key: 'dcb69cad03369a87e2834e1cd04cbab5dc052866', class: "capture-animation" })), captureState.showFlipAnimation && (h("div", { key: '899ef764d10497b023140b296c3fc72a7e762607', class: "flip-animation" }, h("div", { key: 'ec7449b92e28dcbd40d956e435c3a0ebc65d16ff', class: "id-card-icon" }), h("div", { key: 'f086a238ecc3b3fa91fc1010380676e9b3bc7429', class: "flip-text" }, "\u00A1Voltea tu identificaci\u00F3n!"))), captureState.showSuccessAnimation && (h("div", { key: '4d6f0030db7a14c403b4b6fd00714aa04fd5abed', class: "success-animation" }, h("div", { key: 'c08babe375bbc94c9403ef264739016bbfac13ae', class: "check-icon" }), h("div", { key: '24393d75b67dd27da6520dd2b7a223dc9dfa73e4', class: "success-text" }, "\u00A1Proceso completado!"))), this.currentStatus.type !== 'active' && (h("div", { key: '20820f96090471728b9ed654e0b92f0a503e2052', class: `component-status status-${this.currentStatus.type}` }, (this.currentStatus.type === 'loading' || this.currentStatus.type === 'initializing') && (h("div", { key: '0709abb333b47085e4c48ff162e58226e2204978', class: "status-spinner" })), h("div", { key: '5eb17314e376a5e0db32a6f00023d2f502c55fe4', class: "status-content" }, h("div", { key: 'fd98ef9b6889de7ca5cce0befd05285d7247795c', class: "status-message" }, this.currentStatus.message), this.currentStatus.description && (h("div", { key: '3aa93673546a06137f407aafd2933bf09d6814b0', class: "status-description" }, this.currentStatus.description))))), h("div", { key: '2247b9245bc8ecf265cb03c6c518583ae49a3e6d', class: "watermark" }, h("img", { key: '7a50ec51fe6c08a6d7907f5d4bda85b3d9a5b48b', src: "https://storage.googleapis.com/jaak-static/commons/powered-by-jaak.png", alt: "Powered by Jaak" })))));
|
|
580
|
+
} })))), this.isMaskReady && (h("div", { key: '58c0a0bdd8088835c677c9b455e01ffd8a28bcc0', class: "overlay-mask" }, h("div", { key: '52f87e8837f82a4ab6fd75bd22f8c178ff5670c4', class: "card-outline" }, h("div", { key: '0f503ec7ab610342e01d2b976fff0a5ff1b01845', class: "side side-top" }), h("div", { key: '305c980c5d638270c348ce2fc7bf762515557ea1', class: "side side-right" }), h("div", { key: '201531d41aa8fab1782bc3045bda313bfac14929', class: "side side-bottom" }), h("div", { key: 'acaa082133217e2b4aa807571d6f7f8e5f225530', class: "side side-left" }), !captureState.showFlipAnimation && !captureState.showSuccessAnimation && (h("div", { key: '17246f4264074dfae7fdef963120a2d3756b0f64', class: "guide-text" }, "Alinee su identificaci\u00F3n con el marco"))), captureState.step === 'back' && !captureState.showFlipAnimation && !captureState.showSuccessAnimation && (h("button", { key: '9f21b022b3601f2b8f9898f72683e33b86f433a6', class: "skip-button", onClick: () => this.skipBackCapture(), type: "button" }, "Saltar reverso")), captureState.isVideoActive && (h("div", { key: '3c9d8e3b2135dd14414463a6ada636b425385583', class: "camera-controls" }, h("button", { key: 'b287e1dab5a98f2eb6e05e924b1af9bb6616f947', class: `camera-selector-button ${this.isSwitchingCamera ? 'loading' : ''}`, onClick: () => this.toggleCameraSelector(), type: "button", title: "Seleccionar c\u00E1mara", disabled: this.isSwitchingCamera }, this.isSwitchingCamera ? (h("div", { class: "button-spinner" })) : ('Cámaras')))), this.showCameraSelector && cameraInfo.availableCameras.length > 0 && (h("div", { key: 'd8dca3049cbdf827d03cd432ac183a1651f77ab6', class: "camera-selector-dropdown" }, h("div", { key: '3a4200b5624f5d96de4ae8acb821a47d31a34c93', class: "camera-selector-header" }, h("span", { key: '14f8e8618d9404cdfd3f9cc150e54b510507c977' }, "Seleccionar C\u00E1mara"), h("button", { key: '98367e182d227093742e0fc9118f81db32352bdd', class: "close-selector", onClick: () => this.toggleCameraSelector(), type: "button" }, "\u00D7")), h("div", { key: '172471ef3c0d55cb619a061eafe37205c3a0bee4', class: "camera-list" }, cameraInfo.availableCameras.map((camera) => (h("button", { key: camera.id, class: `camera-option ${cameraInfo.selectedCameraId === camera.id ? 'selected' : ''}`, onClick: () => this.handleCameraSwitch(camera.id), type: "button" }, h("span", { class: "camera-label" }, camera.label || `Cámara ${cameraInfo.availableCameras.indexOf(camera) + 1}`), cameraInfo.selectedCameraId === camera.id && (h("span", { class: "selected-indicator" }, "\u2713")))))), h("div", { key: 'e08ced0c02b5662be31c60b2ba35c83fac46bb80', class: "device-info" }, h("small", { key: '8489f10c13a0a528abc878cc66d71dc769890b90' }, "Dispositivo: ", cameraInfo.deviceType)))))), captureState.isCapturing && (h("div", { key: '89f6c5a9bc1efb9bd8af190ae0821dabe992a2be', class: "capture-animation" })), captureState.showFlipAnimation && (h("div", { key: 'ead4d0cf0751097220572a4946bf4dcb3d7f4f33', class: "flip-animation" }, h("div", { key: '357e981fd9b2f616e9b1b90c8454555dceac6fbd', class: "id-card-icon" }), h("div", { key: '4abfecbb5ee0165b720d6ad8398984b25ecec7a1', class: "flip-text" }, "\u00A1Voltea tu identificaci\u00F3n!"))), captureState.showSuccessAnimation && (h("div", { key: 'cdeedd36903c8467e7ebb406e3414ecd92abf47c', class: "success-animation" }, h("div", { key: '8731f318d490ff67fa7f68edf264acb762632604', class: "check-icon" }), h("div", { key: '2e21ce0921fedfaa0b90c56ec44d289426ea7708', class: "success-text" }, "\u00A1Proceso completado!"))), h("div", { key: '6cf678c79f8e57fde12202a932fe855905ae770f', class: `component-status status-${this.currentStatus.type}` }, (this.currentStatus.type === 'loading' || this.currentStatus.type === 'initializing') && (h("div", { key: 'f9e888616736c26624bd3de7c2f1eee297d0a2f5', class: "status-spinner" })), h("div", { key: 'b849c5187ed8e66b4cf62113d2f93c006cf9f836', class: "status-content" }, h("div", { key: '64a2dac4cb5e4c17fc2aa161c8faa389c64a0458', class: "status-message" }, this.currentStatus.message), this.currentStatus.description && (h("div", { key: '64e85a98129f791d6784a98129f2411607360fff', class: "status-description" }, this.currentStatus.description)))), this.debug && (h("div", { key: '1d41d3139d7d486bdf9225f584d6de250faeddf7', class: "performance-monitor" }, h("div", { key: '75bf3d45d869c4b0365f994444292de2245d391c', class: "performance-expanded" }, h("div", { key: '762c977e7125202103aba84c568c0fefee43d6b2', class: "metrics-row" }, h("div", { key: '51b03d882f84e835664af11d409fc01a5363c0ce', class: "metric-compact" }, h("span", { key: '21767c803c2fda9fe8653881cb8dfdcaa992fe3b', class: "metric-label" }, "FPS"), h("span", { key: '5467ba22adb75668a0acadd4ffcbaa25117fd8ae', class: `metric-value ${this.performanceData.fps < 15 ? 'warning' : this.performanceData.fps < 10 ? 'danger' : 'good'}` }, this.performanceData.fps)), h("div", { key: 'a6c020d500a72f330a7cbb01cfdddc1fff63f1bb', class: "metric-compact" }, h("span", { key: '5034e33c12ad454368e4fa32567c307bce6ffe0e', class: "metric-label" }, "MEM"), h("span", { key: '19f691984f9e6aac29067fc983561b701b9080de', class: `metric-value ${this.performanceData.memoryUsage > 100 ? 'warning' : this.performanceData.memoryUsage > 200 ? 'danger' : 'good'}` }, this.performanceData.memoryUsage, "MB"))), h("div", { key: 'c2a11b8dc156b90a4ba18020e5a62ff87c29f624', class: "metrics-row" }, h("div", { key: '7af9c2c1286bb32d6c166d3487c8ea4a02f14490', class: "metric-compact" }, h("span", { key: 'b34e54ac6b4e387ee8155176f999dd2b721a8617', class: "metric-label" }, "INF"), h("span", { key: 'ada2f913ac6c97661a054f9bf596f4ac52eb918e', class: `metric-value ${this.performanceData.inferenceTime > 100 ? 'warning' : this.performanceData.inferenceTime > 200 ? 'danger' : 'good'}` }, this.performanceData.inferenceTime, "ms")), h("div", { key: 'cc2d819a7e75af4e03d2521756c23110785076ad', class: "metric-compact" }, h("span", { key: 'b2f7e528be88eafcc66d801e8f547b4d274e0cf8', class: "metric-label" }, "FRAME"), h("span", { key: '1bcddf221b960018fb5505553e9f8cfd3717c349', class: `metric-value ${this.performanceData.frameProcessingTime > 50 ? 'warning' : this.performanceData.frameProcessingTime > 100 ? 'danger' : 'good'}` }, this.performanceData.frameProcessingTime, "ms"))), h("div", { key: 'cb80b6198f621fab68b13c4992578ef2e548ae99', class: "metrics-row" }, h("div", { key: 'b752b65906c92eff86cad2d0ffdc1420f03a8932', class: "metric-compact" }, h("span", { key: '96af746b42a101c6bfe4c197b652837ecc66fc06', class: "metric-label" }, "DET"), h("span", { key: 'f2038ae4943ebd9ae2ec1d8b907ae23f04c8fd90', class: "metric-value good" }, this.performanceData.successfulDetections, "/", this.performanceData.totalDetections)), h("div", { key: 'c2e6b9380928b30b1a879a6abc43eb7053da9ac1', class: "metric-compact" }, h("span", { key: '096268d19a7ac7471c5dafd5adc3103d30433a55', class: "metric-label" }, "RATE"), h("span", { key: '7f9e9e49c68da719fe43391518514af3cdab004d', class: `metric-value ${this.performanceData.detectionRate < 30 ? 'danger' : this.performanceData.detectionRate < 60 ? 'warning' : 'good'}` }, this.performanceData.detectionRate, "%")))))), h("div", { key: 'c6546f8ec722c56fa369da6d5d732f29d3afc65f', class: "watermark" }, h("img", { key: 'd195a395051a4c436dec33d7835c565e748cf60a', src: "https://storage.googleapis.com/jaak-static/commons/powered-by-jaak.png", alt: "Powered by Jaak" })))));
|
|
515
581
|
}
|
|
516
582
|
// Utility methods
|
|
517
583
|
updateDetectionBoxes(boxes) {
|
|
@@ -584,19 +650,37 @@ export class JaakStamps {
|
|
|
584
650
|
cardOutline?.classList.add('perfect-match');
|
|
585
651
|
corners?.forEach(corner => corner.classList.add('perfect-match'));
|
|
586
652
|
if (!this.hasScreenshotTaken) {
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
653
|
+
const currentTime = Date.now();
|
|
654
|
+
// Initialize alignment start time if not set
|
|
655
|
+
if (!this.alignmentStartTime) {
|
|
656
|
+
this.alignmentStartTime = currentTime;
|
|
657
|
+
}
|
|
658
|
+
// Check if document has been aligned for 1 second
|
|
659
|
+
const alignmentDuration = currentTime - this.alignmentStartTime;
|
|
660
|
+
if (alignmentDuration >= 1000) {
|
|
661
|
+
this.lastDetectedBox = bestBox;
|
|
662
|
+
this.takeScreenshot().catch(error => {
|
|
663
|
+
this.logger.error('Error al tomar captura de pantalla:', error);
|
|
664
|
+
});
|
|
665
|
+
this.hasScreenshotTaken = true;
|
|
666
|
+
this.alignmentStartTime = undefined;
|
|
667
|
+
setTimeout(() => {
|
|
668
|
+
this.hasScreenshotTaken = false;
|
|
669
|
+
}, 2000);
|
|
670
|
+
}
|
|
595
671
|
}
|
|
596
672
|
}
|
|
597
673
|
else {
|
|
598
674
|
cardOutline?.classList.remove('perfect-match');
|
|
599
675
|
corners?.forEach(corner => corner.classList.remove('perfect-match'));
|
|
676
|
+
// Reset alignment timer when document moves out of position
|
|
677
|
+
if (this.alignmentStartTime) {
|
|
678
|
+
this.alignmentStartTime = undefined;
|
|
679
|
+
}
|
|
680
|
+
if (this.alignmentTimer) {
|
|
681
|
+
clearTimeout(this.alignmentTimer);
|
|
682
|
+
this.alignmentTimer = undefined;
|
|
683
|
+
}
|
|
600
684
|
}
|
|
601
685
|
}
|
|
602
686
|
async takeScreenshot() {
|
|
@@ -713,8 +797,52 @@ export class JaakStamps {
|
|
|
713
797
|
this.logger.state('DETECTOR_DETENIDO', { timestamp: Date.now() });
|
|
714
798
|
}
|
|
715
799
|
toggleCameraSelector() {
|
|
800
|
+
if (this.isSwitchingCamera)
|
|
801
|
+
return; // Don't toggle if switching camera
|
|
716
802
|
this.showCameraSelector = !this.showCameraSelector;
|
|
717
803
|
}
|
|
804
|
+
async handleCameraSwitch(cameraId) {
|
|
805
|
+
if (this.isSwitchingCamera)
|
|
806
|
+
return; // Prevent multiple simultaneous switches
|
|
807
|
+
try {
|
|
808
|
+
// Close the selector immediately when user selects a camera
|
|
809
|
+
this.showCameraSelector = false;
|
|
810
|
+
this.isSwitchingCamera = true;
|
|
811
|
+
this.logger.state('INICIANDO_CAMBIO_CAMARA', {
|
|
812
|
+
from: this.cameraService.getSelectedCameraId(),
|
|
813
|
+
to: cameraId
|
|
814
|
+
});
|
|
815
|
+
// Stop current video stream
|
|
816
|
+
if (this.videoStream) {
|
|
817
|
+
this.videoStream.getTracks().forEach(track => track.stop());
|
|
818
|
+
}
|
|
819
|
+
// Switch camera in service
|
|
820
|
+
await this.cameraService.switchCamera(cameraId);
|
|
821
|
+
// Setup new camera stream
|
|
822
|
+
const newStream = await this.cameraService.setupCamera();
|
|
823
|
+
// Update video element
|
|
824
|
+
await this.initializeVideoStream(newStream);
|
|
825
|
+
this.logger.state('CAMBIO_CAMARA_EXITOSO', {
|
|
826
|
+
newCameraId: cameraId,
|
|
827
|
+
isRearCamera: this.cameraService.isRearCamera(newStream)
|
|
828
|
+
});
|
|
829
|
+
}
|
|
830
|
+
catch (error) {
|
|
831
|
+
this.logger.error('Error al cambiar cámara:', error);
|
|
832
|
+
// Try to restore previous camera if switch failed
|
|
833
|
+
try {
|
|
834
|
+
const fallbackStream = await this.cameraService.setupCamera();
|
|
835
|
+
await this.initializeVideoStream(fallbackStream);
|
|
836
|
+
}
|
|
837
|
+
catch (fallbackError) {
|
|
838
|
+
this.logger.error('Error al restaurar cámara anterior:', fallbackError);
|
|
839
|
+
this.updateStatus('Error al cambiar cámara', 'No se pudo completar el cambio de dispositivo', 'error');
|
|
840
|
+
}
|
|
841
|
+
}
|
|
842
|
+
finally {
|
|
843
|
+
this.isSwitchingCamera = false;
|
|
844
|
+
}
|
|
845
|
+
}
|
|
718
846
|
resetDetection() {
|
|
719
847
|
this.stateManager.reset();
|
|
720
848
|
this.hasScreenshotTaken = false;
|
|
@@ -723,6 +851,11 @@ export class JaakStamps {
|
|
|
723
851
|
this.consecutiveFailures = 0;
|
|
724
852
|
this.lastInferenceTime = 0;
|
|
725
853
|
this.detectionBoxes = [];
|
|
854
|
+
this.alignmentStartTime = undefined;
|
|
855
|
+
if (this.alignmentTimer) {
|
|
856
|
+
clearTimeout(this.alignmentTimer);
|
|
857
|
+
this.alignmentTimer = undefined;
|
|
858
|
+
}
|
|
726
859
|
const captureState = this.stateManager.getCaptureState();
|
|
727
860
|
if (captureState.isVideoActive && this.detectionService.isModelLoaded()) {
|
|
728
861
|
this.updateStatus('Captura reiniciada', 'Buscando documento en el marco de captura', 'active');
|
|
@@ -742,6 +875,60 @@ export class JaakStamps {
|
|
|
742
875
|
this.detectionBoxes = [];
|
|
743
876
|
this.cleanup();
|
|
744
877
|
}
|
|
878
|
+
// PERFORMANCE MONITORING METHODS
|
|
879
|
+
initializePerformanceMonitor() {
|
|
880
|
+
this.performanceMetrics.lastUpdateTime = performance.now();
|
|
881
|
+
// Update performance metrics every 500ms
|
|
882
|
+
this.performanceUpdateInterval = window.setInterval(() => {
|
|
883
|
+
this.updatePerformanceMetrics();
|
|
884
|
+
}, 500);
|
|
885
|
+
this.logger.debug('Monitor de performance inicializado');
|
|
886
|
+
}
|
|
887
|
+
updatePerformanceMetrics() {
|
|
888
|
+
const currentTime = performance.now();
|
|
889
|
+
const deltaTime = currentTime - this.performanceMetrics.lastUpdateTime;
|
|
890
|
+
// Calculate FPS
|
|
891
|
+
if (deltaTime > 0) {
|
|
892
|
+
this.performanceMetrics.fps = Math.round(1000 / (deltaTime / this.frameSkipCounter || 1));
|
|
893
|
+
}
|
|
894
|
+
// Get memory usage if available
|
|
895
|
+
if ('memory' in performance) {
|
|
896
|
+
const memInfo = performance.memory;
|
|
897
|
+
this.performanceMetrics.memoryUsage = Math.round(memInfo.usedJSHeapSize / 1048576); // MB
|
|
898
|
+
}
|
|
899
|
+
// Calculate detection success rate
|
|
900
|
+
if (this.performanceMetrics.totalDetections > 0) {
|
|
901
|
+
this.performanceMetrics.successfulDetections = this.performanceMetrics.successfulDetections;
|
|
902
|
+
const detectionRate = (this.performanceMetrics.successfulDetections / this.performanceMetrics.totalDetections) * 100;
|
|
903
|
+
this.performanceMetrics.detectionRate = Math.round(detectionRate);
|
|
904
|
+
}
|
|
905
|
+
// Update state for rendering
|
|
906
|
+
this.performanceData = {
|
|
907
|
+
fps: this.performanceMetrics.fps,
|
|
908
|
+
inferenceTime: this.performanceMetrics.inferenceTime,
|
|
909
|
+
memoryUsage: this.performanceMetrics.memoryUsage,
|
|
910
|
+
onnxLoadTime: this.performanceMetrics.onnxLoadTime,
|
|
911
|
+
frameProcessingTime: this.performanceMetrics.frameProcessingTime,
|
|
912
|
+
totalDetections: this.performanceMetrics.totalDetections,
|
|
913
|
+
successfulDetections: this.performanceMetrics.successfulDetections,
|
|
914
|
+
detectionRate: this.performanceMetrics.detectionRate
|
|
915
|
+
};
|
|
916
|
+
this.performanceMetrics.lastUpdateTime = currentTime;
|
|
917
|
+
}
|
|
918
|
+
recordOnnxPerformance(loadTime, inferenceTime) {
|
|
919
|
+
this.performanceMetrics.onnxLoadTime = Math.round(loadTime);
|
|
920
|
+
this.performanceMetrics.inferenceTime = Math.round(inferenceTime);
|
|
921
|
+
}
|
|
922
|
+
recordFrameProcessing(processingTime, detectionsFound) {
|
|
923
|
+
this.performanceMetrics.frameProcessingTime = Math.round(processingTime);
|
|
924
|
+
this.performanceMetrics.totalDetections++;
|
|
925
|
+
if (detectionsFound > 0) {
|
|
926
|
+
this.performanceMetrics.successfulDetections++;
|
|
927
|
+
}
|
|
928
|
+
}
|
|
929
|
+
togglePerformanceMonitor() {
|
|
930
|
+
this.isPerformanceMonitorMinimized = !this.isPerformanceMonitorMinimized;
|
|
931
|
+
}
|
|
745
932
|
static get is() { return "jaak-stamps"; }
|
|
746
933
|
static get encapsulation() { return "shadow"; }
|
|
747
934
|
static get originalStyleUrls() {
|
|
@@ -885,7 +1072,10 @@ export class JaakStamps {
|
|
|
885
1072
|
"isMaskReady": {},
|
|
886
1073
|
"shouldMirrorVideo": {},
|
|
887
1074
|
"showCameraSelector": {},
|
|
888
|
-
"
|
|
1075
|
+
"isSwitchingCamera": {},
|
|
1076
|
+
"currentStatus": {},
|
|
1077
|
+
"performanceData": {},
|
|
1078
|
+
"isPerformanceMonitorMinimized": {}
|
|
889
1079
|
};
|
|
890
1080
|
}
|
|
891
1081
|
static get events() {
|