@jaak.ai/stamps 1.0.0 → 2.0.0-beta.2
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/LICENSE +21 -0
- package/README.md +531 -457
- package/dist/cjs/index-DGM9-FNg.js +1402 -0
- package/dist/cjs/index-DGM9-FNg.js.map +1 -0
- package/dist/cjs/index.cjs.js +3 -0
- package/dist/cjs/index.cjs.js.map +1 -0
- package/dist/cjs/jaak-stamps-webcomponent.cjs.js +27 -0
- package/dist/cjs/jaak-stamps-webcomponent.cjs.js.map +1 -0
- package/dist/cjs/jaak-stamps.cjs.entry.js +1060 -0
- package/dist/cjs/jaak-stamps.cjs.entry.js.map +1 -0
- package/dist/cjs/jaak-stamps.entry.cjs.js.map +1 -0
- package/dist/cjs/loader.cjs.js +8 -15
- package/dist/cjs/loader.cjs.js.map +1 -0
- package/dist/collection/collection-manifest.json +3 -22
- package/dist/collection/components/my-component/my-component.css +530 -0
- package/dist/collection/components/my-component/my-component.js +1357 -0
- package/dist/collection/components/my-component/my-component.js.map +1 -0
- package/dist/collection/index.js +2 -1
- package/dist/collection/index.js.map +1 -0
- package/dist/collection/utils/utils.js +4 -0
- package/dist/collection/utils/utils.js.map +1 -0
- package/dist/components/index.d.ts +33 -0
- package/dist/components/index.js +1195 -0
- package/dist/components/index.js.map +1 -0
- package/dist/components/jaak-stamps.d.ts +11 -0
- package/dist/components/jaak-stamps.js +1109 -0
- package/dist/components/jaak-stamps.js.map +1 -0
- package/dist/esm/index-DqoVMnc7.js +1393 -0
- package/dist/esm/index-DqoVMnc7.js.map +1 -0
- package/dist/esm/index.js +3 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/jaak-stamps-webcomponent.js +23 -0
- package/dist/esm/jaak-stamps-webcomponent.js.map +1 -0
- package/dist/esm/jaak-stamps.entry.js +1058 -0
- package/dist/esm/jaak-stamps.entry.js.map +1 -0
- package/dist/esm/loader.js +9 -14
- package/dist/esm/loader.js.map +1 -0
- package/dist/jaak-stamps-webcomponent/index.esm.js +2 -0
- package/dist/jaak-stamps-webcomponent/index.esm.js.map +1 -0
- package/dist/jaak-stamps-webcomponent/jaak-stamps-webcomponent.esm.js +2 -0
- package/dist/jaak-stamps-webcomponent/jaak-stamps-webcomponent.esm.js.map +1 -0
- package/dist/jaak-stamps-webcomponent/jaak-stamps.entry.esm.js.map +1 -0
- package/dist/jaak-stamps-webcomponent/loader.esm.js.map +1 -0
- package/dist/jaak-stamps-webcomponent/p-DqoVMnc7.js +3 -0
- package/dist/jaak-stamps-webcomponent/p-DqoVMnc7.js.map +1 -0
- package/dist/jaak-stamps-webcomponent/p-f1172b06.entry.js +2 -0
- package/dist/jaak-stamps-webcomponent/p-f1172b06.entry.js.map +1 -0
- package/dist/types/components/my-component/my-component.d.ts +131 -0
- package/dist/types/components.d.ts +62 -1370
- package/dist/types/index.d.ts +10 -1
- package/dist/types/stencil-public-runtime.d.ts +93 -28
- package/dist/types/utils/utils.d.ts +1 -0
- package/loader/cdn.js +1 -3
- package/loader/index.cjs.js +1 -3
- package/loader/index.d.ts +5 -2
- package/loader/index.es2017.js +1 -3
- package/loader/index.js +1 -3
- package/package.json +22 -26
- package/dist/cjs/document-detector_19.cjs.entry.js +0 -8630
- package/dist/cjs/index-5e4e5e7d.js +0 -1685
- package/dist/cjs/mb-tooltip.cjs.entry.js +0 -26
- package/dist/cjs/stamps.cjs.js +0 -23
- package/dist/collection/components/document-detector/document-detector.css +0 -156
- package/dist/collection/components/document-detector/document-detector.js +0 -504
- package/dist/collection/components/shared/mb-api-process-status/mb-api-process-status.css +0 -360
- package/dist/collection/components/shared/mb-api-process-status/mb-api-process-status.js +0 -124
- package/dist/collection/components/shared/mb-button/mb-button.css +0 -95
- package/dist/collection/components/shared/mb-button/mb-button.js +0 -201
- package/dist/collection/components/shared/mb-button-classic/mb-button-classic.css +0 -100
- package/dist/collection/components/shared/mb-button-classic/mb-button-classic.js +0 -130
- package/dist/collection/components/shared/mb-camera-experience/mb-camera-experience.css +0 -740
- package/dist/collection/components/shared/mb-camera-experience/mb-camera-experience.js +0 -827
- package/dist/collection/components/shared/mb-camera-experience/mb-camera-experience.utils.js +0 -55
- package/dist/collection/components/shared/mb-camera-selection/mb-camera-selection.css +0 -124
- package/dist/collection/components/shared/mb-camera-selection/mb-camera-selection.js +0 -194
- package/dist/collection/components/shared/mb-camera-toolbar/mb-camera-toolbar.css +0 -80
- package/dist/collection/components/shared/mb-camera-toolbar/mb-camera-toolbar.js +0 -275
- package/dist/collection/components/shared/mb-completed/mb-completed.css +0 -17
- package/dist/collection/components/shared/mb-completed/mb-completed.js +0 -48
- package/dist/collection/components/shared/mb-component/mb-component.css +0 -321
- package/dist/collection/components/shared/mb-component/mb-component.js +0 -2294
- package/dist/collection/components/shared/mb-component/mb-component.utils.js +0 -14
- package/dist/collection/components/shared/mb-container/mb-container.css +0 -7
- package/dist/collection/components/shared/mb-container/mb-container.js +0 -23
- package/dist/collection/components/shared/mb-feedback/mb-feedback.css +0 -36
- package/dist/collection/components/shared/mb-feedback/mb-feedback.js +0 -91
- package/dist/collection/components/shared/mb-feedback/mb-feedback.utils.js +0 -11
- package/dist/collection/components/shared/mb-help/mb-help.css +0 -191
- package/dist/collection/components/shared/mb-help/mb-help.js +0 -409
- package/dist/collection/components/shared/mb-help/mb-help.model.js +0 -5
- package/dist/collection/components/shared/mb-image-box/mb-image-box.css +0 -78
- package/dist/collection/components/shared/mb-image-box/mb-image-box.js +0 -150
- package/dist/collection/components/shared/mb-modal/mb-modal.css +0 -106
- package/dist/collection/components/shared/mb-modal/mb-modal.js +0 -239
- package/dist/collection/components/shared/mb-overlay/mb-overlay.css +0 -46
- package/dist/collection/components/shared/mb-overlay/mb-overlay.js +0 -76
- package/dist/collection/components/shared/mb-progress-tracker/mb-progress-tracker.css +0 -24
- package/dist/collection/components/shared/mb-progress-tracker/mb-progress-tracker.js +0 -80
- package/dist/collection/components/shared/mb-screen/mb-screen.css +0 -19
- package/dist/collection/components/shared/mb-screen/mb-screen.js +0 -48
- package/dist/collection/components/shared/mb-spinner/mb-spinner.css +0 -30
- package/dist/collection/components/shared/mb-spinner/mb-spinner.js +0 -67
- package/dist/collection/components/shared/mb-tooltip/mb-tooltip.css +0 -62
- package/dist/collection/components/shared/mb-tooltip/mb-tooltip.js +0 -150
- package/dist/collection/components/shared/mb-tooltip-advanced/mb-tooltip-advanced.css +0 -91
- package/dist/collection/components/shared/mb-tooltip-advanced/mb-tooltip-advanced.js +0 -96
- package/dist/collection/utils/data-structures.js +0 -189
- package/dist/collection/utils/device.helpers.js +0 -37
- package/dist/collection/utils/error-structures.js +0 -47
- package/dist/collection/utils/generic.helpers.js +0 -82
- package/dist/collection/utils/sdk.service.js +0 -943
- package/dist/collection/utils/state-lifter.js +0 -3
- package/dist/collection/utils/status.document-detector.js +0 -15
- package/dist/collection/utils/translation.service.js +0 -97
- package/dist/esm/document-detector_19.entry.js +0 -8608
- package/dist/esm/index-dc740acb.js +0 -1656
- package/dist/esm/mb-tooltip.entry.js +0 -22
- package/dist/esm/polyfills/core-js.js +0 -11
- package/dist/esm/polyfills/css-shim.js +0 -1
- package/dist/esm/polyfills/dom.js +0 -79
- package/dist/esm/polyfills/es5-html-element.js +0 -1
- package/dist/esm/polyfills/index.js +0 -34
- package/dist/esm/polyfills/system.js +0 -6
- package/dist/esm/stamps.js +0 -18
- package/dist/stamps/index.esm.js +0 -0
- package/dist/stamps/p-7f07a434.js +0 -2
- package/dist/stamps/p-ae1d9117.entry.js +0 -9
- package/dist/stamps/p-ec3f5972.entry.js +0 -1
- package/dist/stamps/stamps.esm.js +0 -1
- package/dist/types/components/document-detector/document-detector.d.ts +0 -103
- package/dist/types/components/shared/mb-api-process-status/mb-api-process-status.d.ts +0 -30
- package/dist/types/components/shared/mb-button/mb-button.d.ts +0 -41
- package/dist/types/components/shared/mb-button-classic/mb-button-classic.d.ts +0 -27
- package/dist/types/components/shared/mb-camera-experience/mb-camera-experience.d.ts +0 -141
- package/dist/types/components/shared/mb-camera-experience/mb-camera-experience.utils.d.ts +0 -3
- package/dist/types/components/shared/mb-camera-selection/mb-camera-selection.d.ts +0 -33
- package/dist/types/components/shared/mb-camera-toolbar/mb-camera-toolbar.d.ts +0 -54
- package/dist/types/components/shared/mb-completed/mb-completed.d.ts +0 -12
- package/dist/types/components/shared/mb-component/mb-component.d.ts +0 -310
- package/dist/types/components/shared/mb-component/mb-component.utils.d.ts +0 -3
- package/dist/types/components/shared/mb-container/mb-container.d.ts +0 -8
- package/dist/types/components/shared/mb-feedback/mb-feedback.d.ts +0 -19
- package/dist/types/components/shared/mb-feedback/mb-feedback.utils.d.ts +0 -2
- package/dist/types/components/shared/mb-help/mb-help.d.ts +0 -66
- package/dist/types/components/shared/mb-help/mb-help.model.d.ts +0 -9
- package/dist/types/components/shared/mb-image-box/mb-image-box.d.ts +0 -35
- package/dist/types/components/shared/mb-modal/mb-modal.d.ts +0 -53
- package/dist/types/components/shared/mb-overlay/mb-overlay.d.ts +0 -17
- package/dist/types/components/shared/mb-progress-tracker/mb-progress-tracker.d.ts +0 -19
- package/dist/types/components/shared/mb-screen/mb-screen.d.ts +0 -12
- package/dist/types/components/shared/mb-spinner/mb-spinner.d.ts +0 -16
- package/dist/types/components/shared/mb-tooltip/mb-tooltip.d.ts +0 -10
- package/dist/types/components/shared/mb-tooltip-advanced/mb-tooltip-advanced.d.ts +0 -7
- package/dist/types/utils/data-structures.d.ts +0 -264
- package/dist/types/utils/device.helpers.d.ts +0 -7
- package/dist/types/utils/error-structures.d.ts +0 -44
- package/dist/types/utils/generic.helpers.d.ts +0 -21
- package/dist/types/utils/sdk.service.d.ts +0 -52
- package/dist/types/utils/state-lifter.d.ts +0 -3
- package/dist/types/utils/status.document-detector.d.ts +0 -14
- package/dist/types/utils/translation.service.d.ts +0 -77
- package/loader/package.json +0 -11
package/README.md
CHANGED
|
@@ -1,533 +1,607 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Jaak Stamps - Document Detector Web Component
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
Un componente web para la detección y captura automática de documentos de identificación usando visión artificial y redes neuronales.
|
|
4
|
+
|
|
5
|
+
## Características
|
|
6
|
+
|
|
7
|
+
- 📷 **Detección automática** de documentos de identificación en tiempo real
|
|
8
|
+
- 🎯 **Guía visual** para posicionamiento óptimo del documento
|
|
9
|
+
- 🤖 **Clasificación inteligente** de documentos para determinar si requieren reverso
|
|
10
|
+
- 📋 **Captura adaptativa** - automáticamente detecta si el documento tiene reverso
|
|
11
|
+
- 🖼 **Doble salida** para cada lado: imagen completa y recorte del documento
|
|
12
|
+
- ✂️ **Recorte configurable** con margen personalizable alrededor del documento
|
|
13
|
+
- 🔧 **API programática** para control total del proceso
|
|
14
|
+
- 📱 **Responsive** y compatible con dispositivos móviles
|
|
15
|
+
- ⚡ **Optimización automática** para mejor rendimiento
|
|
5
16
|
|
|
6
17
|
## Instalación
|
|
7
18
|
|
|
19
|
+
### NPM
|
|
8
20
|
```bash
|
|
9
21
|
npm install @jaak.ai/stamps
|
|
10
22
|
```
|
|
11
23
|
|
|
24
|
+
### Yarn
|
|
25
|
+
```bash
|
|
26
|
+
yarn add @jaak.ai/stamps
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
### CDN
|
|
30
|
+
```html
|
|
31
|
+
<script type="module" src="https://unpkg.com/@jaak.ai/stamps/dist/jaak-stamps-webcomponent/jaak-stamps-webcomponent.esm.js"></script>
|
|
32
|
+
```
|
|
33
|
+
|
|
12
34
|
## Uso Básico
|
|
13
35
|
|
|
14
|
-
### HTML
|
|
36
|
+
### HTML Vanilla
|
|
15
37
|
|
|
16
38
|
```html
|
|
17
39
|
<!DOCTYPE html>
|
|
18
40
|
<html>
|
|
19
41
|
<head>
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
<script type="module" src="https://cdn.jsdelivr.net/npm/@jaak.ai/stamps/dist/stamps/stamps.esm.js"></script>
|
|
23
|
-
<script nomodule src="https://cdn.jsdelivr.net/npm/@jaak.ai/stamps/dist/stamps/stamps.js"></script>
|
|
42
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
43
|
+
<script type="module" src="https://unpkg.com/@jaak.ai/stamps/dist/jaak-stamps-webcomponent/jaak-stamps-webcomponent.esm.js"></script>
|
|
24
44
|
</head>
|
|
25
45
|
<body>
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
46
|
+
<jaak-stamps id="detector" debug="false" mask-size="90" crop-margin="10" use-document-classification="false"></jaak-stamps>
|
|
47
|
+
|
|
48
|
+
<button onclick="startCapture()">Iniciar Captura</button>
|
|
49
|
+
<button onclick="stopCapture()">Detener</button>
|
|
50
|
+
<button onclick="resetCapture()">Reiniciar</button>
|
|
51
|
+
|
|
52
|
+
<script>
|
|
53
|
+
const detector = document.getElementById('detector');
|
|
54
|
+
|
|
55
|
+
// Escuchar evento de captura completada
|
|
56
|
+
detector.addEventListener('captureCompleted', (event) => {
|
|
57
|
+
console.log('Captura completada:', event.detail);
|
|
58
|
+
// event.detail contiene las imágenes capturadas
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
// Escuchar evento de componente listo
|
|
62
|
+
detector.addEventListener('isReady', (event) => {
|
|
63
|
+
console.log('Componente listo:', event.detail);
|
|
64
|
+
// event.detail indica si el componente está listo (true/false)
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
function startCapture() {
|
|
68
|
+
detector.startCapture();
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function stopCapture() {
|
|
72
|
+
detector.stopCapture();
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function resetCapture() {
|
|
76
|
+
detector.resetCapture();
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// Precargar el modelo (opcional - mejora el rendimiento)
|
|
80
|
+
async function preloadModel() {
|
|
81
|
+
try {
|
|
82
|
+
const result = await detector.preloadModel();
|
|
83
|
+
console.log('Modelo precargado:', result);
|
|
84
|
+
} catch (error) {
|
|
85
|
+
console.error('Error al precargar:', error);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// Obtener imágenes después de la captura
|
|
90
|
+
async function getImages() {
|
|
91
|
+
try {
|
|
92
|
+
const images = await detector.getCapturedImages();
|
|
93
|
+
console.log('Imágenes capturadas:', images);
|
|
94
|
+
} catch (error) {
|
|
95
|
+
console.error('Error:', error.message);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
</script>
|
|
47
99
|
</body>
|
|
48
100
|
</html>
|
|
49
101
|
```
|
|
50
102
|
|
|
51
|
-
###
|
|
52
|
-
|
|
53
|
-
```jsx
|
|
54
|
-
import React, { useEffect, useRef } from 'react';
|
|
55
|
-
import '@jaak.ai/stamps';
|
|
56
|
-
|
|
57
|
-
function DocumentDetectorComponent() {
|
|
58
|
-
const detectorRef = useRef(null);
|
|
59
|
-
|
|
60
|
-
useEffect(() => {
|
|
61
|
-
const detector = detectorRef.current;
|
|
62
|
-
|
|
63
|
-
// Escuchar los eventos emitidos directamente por el componente
|
|
64
|
-
const handleStatus = (ev) => {
|
|
65
|
-
console.log('Estado del detector:', ev.detail);
|
|
66
|
-
};
|
|
67
|
-
|
|
68
|
-
const handleResults = (ev) => {
|
|
69
|
-
console.log('Resultados del escaneo:', ev.detail);
|
|
70
|
-
};
|
|
71
|
-
|
|
72
|
-
detector.addEventListener('status', handleStatus);
|
|
73
|
-
detector.addEventListener('results', handleResults);
|
|
74
|
-
|
|
75
|
-
// Iniciar el escaneo por cámara cuando el componente esté listo
|
|
76
|
-
setTimeout(() => {
|
|
77
|
-
detector.startCameraScan();
|
|
78
|
-
}, 1000);
|
|
79
|
-
|
|
80
|
-
return () => {
|
|
81
|
-
detector.removeEventListener('status', handleStatus);
|
|
82
|
-
detector.removeEventListener('results', handleResults);
|
|
83
|
-
};
|
|
84
|
-
}, []);
|
|
85
|
-
|
|
86
|
-
return (
|
|
87
|
-
<document-detector
|
|
88
|
-
ref={detectorRef}
|
|
89
|
-
license-key="TU_CLAVE_DE_LICENCIA"
|
|
90
|
-
/>
|
|
91
|
-
);
|
|
92
|
-
}
|
|
103
|
+
### Angular
|
|
93
104
|
|
|
94
|
-
|
|
105
|
+
#### 1. Instalar el componente
|
|
106
|
+
```bash
|
|
107
|
+
npm install @jaak.ai/stamps
|
|
95
108
|
```
|
|
96
109
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
licenseKey: 'TU_CLAVE_DE_LICENCIA'
|
|
115
|
-
};
|
|
116
|
-
},
|
|
117
|
-
methods: {
|
|
118
|
-
// Métodos para manejar los eventos emitidos directamente por el componente
|
|
119
|
-
handleStatus(ev) {
|
|
120
|
-
console.log('Estado del detector:', ev.detail);
|
|
121
|
-
},
|
|
122
|
-
handleResults(ev) {
|
|
123
|
-
console.log('Resultados del escaneo:', ev.detail);
|
|
124
|
-
}
|
|
125
|
-
},
|
|
126
|
-
mounted() {
|
|
127
|
-
const detector = this.$refs.detector;
|
|
128
|
-
|
|
129
|
-
// Escuchar los eventos emitidos directamente por el componente
|
|
130
|
-
detector.addEventListener('status', this.handleStatus);
|
|
131
|
-
detector.addEventListener('results', this.handleResults);
|
|
132
|
-
|
|
133
|
-
// Iniciar el escaneo por cámara cuando el componente esté listo
|
|
134
|
-
setTimeout(() => {
|
|
135
|
-
detector.startCameraScan();
|
|
136
|
-
}, 1000);
|
|
137
|
-
},
|
|
138
|
-
beforeUnmount() {
|
|
139
|
-
const detector = this.$refs.detector;
|
|
140
|
-
|
|
141
|
-
// Eliminar los event listeners
|
|
142
|
-
detector.removeEventListener('status', this.handleStatus);
|
|
143
|
-
detector.removeEventListener('results', this.handleResults);
|
|
144
|
-
}
|
|
145
|
-
};
|
|
146
|
-
</script>
|
|
110
|
+
#### 2. Configurar el módulo (app.module.ts)
|
|
111
|
+
```typescript
|
|
112
|
+
import { NgModule, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
|
|
113
|
+
import { BrowserModule } from '@angular/platform-browser';
|
|
114
|
+
import { AppComponent } from './app.component';
|
|
115
|
+
|
|
116
|
+
// Importar el componente web
|
|
117
|
+
import '@jaak.ai/stamps/dist/jaak-stamps-webcomponent/jaak-stamps-webcomponent.esm.js';
|
|
118
|
+
|
|
119
|
+
@NgModule({
|
|
120
|
+
declarations: [AppComponent],
|
|
121
|
+
imports: [BrowserModule],
|
|
122
|
+
providers: [],
|
|
123
|
+
bootstrap: [AppComponent],
|
|
124
|
+
schemas: [CUSTOM_ELEMENTS_SCHEMA] // Permitir elementos personalizados
|
|
125
|
+
})
|
|
126
|
+
export class AppModule { }
|
|
147
127
|
```
|
|
148
128
|
|
|
149
|
-
|
|
150
|
-
|
|
129
|
+
#### 3. Usar en el componente
|
|
151
130
|
```typescript
|
|
152
|
-
//
|
|
153
|
-
import { Component,
|
|
154
|
-
import '@jaak.ai/stamps';
|
|
131
|
+
// app.component.ts
|
|
132
|
+
import { Component, ElementRef, ViewChild, OnInit } from '@angular/core';
|
|
155
133
|
|
|
156
134
|
@Component({
|
|
157
|
-
selector: 'app-
|
|
135
|
+
selector: 'app-root',
|
|
158
136
|
template: `
|
|
159
|
-
<
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
137
|
+
<div class="container">
|
|
138
|
+
<h1>Detector de Documentos</h1>
|
|
139
|
+
|
|
140
|
+
<jaak-stamps
|
|
141
|
+
#detector
|
|
142
|
+
[debug]="false"
|
|
143
|
+
[maskSize]="90"
|
|
144
|
+
[cropMargin]="10"
|
|
145
|
+
[useDocumentClassification]="false"
|
|
146
|
+
(captureCompleted)="onCaptureCompleted($event)"
|
|
147
|
+
(isReady)="onComponentReady($event)">
|
|
148
|
+
</jaak-stamps>
|
|
149
|
+
|
|
150
|
+
<div class="controls">
|
|
151
|
+
<button (click)="preloadModel()">Precargar Modelo</button>
|
|
152
|
+
<button (click)="startCapture()">Iniciar Captura</button>
|
|
153
|
+
<button (click)="stopCapture()">Detener</button>
|
|
154
|
+
<button (click)="resetCapture()">Reiniciar</button>
|
|
155
|
+
<button (click)="getImages()" [disabled]="!isCompleted">Obtener Imágenes</button>
|
|
156
|
+
</div>
|
|
157
|
+
|
|
158
|
+
<div *ngIf="capturedData" class="results">
|
|
159
|
+
<h3>Imágenes Capturadas:</h3>
|
|
160
|
+
<p>Total de imágenes: {{ capturedData.metadata.totalImages }}</p>
|
|
161
|
+
<img *ngIf="capturedData.front.cropped" [src]="capturedData.front.cropped" alt="Frente">
|
|
162
|
+
<img *ngIf="capturedData.back.cropped" [src]="capturedData.back.cropped" alt="Reverso">
|
|
163
|
+
</div>
|
|
164
|
+
</div>
|
|
165
|
+
`,
|
|
166
|
+
styles: [`
|
|
167
|
+
.container { max-width: 800px; margin: 0 auto; padding: 20px; }
|
|
168
|
+
.controls { margin: 20px 0; }
|
|
169
|
+
.controls button { margin: 0 10px; padding: 10px 20px; }
|
|
170
|
+
.results img { max-width: 300px; margin: 10px; border: 1px solid #ccc; }
|
|
171
|
+
`]
|
|
164
172
|
})
|
|
165
|
-
export class
|
|
166
|
-
@ViewChild('detector') detectorRef
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
173
|
+
export class AppComponent implements OnInit {
|
|
174
|
+
@ViewChild('detector', { static: true }) detectorRef!: ElementRef;
|
|
175
|
+
|
|
176
|
+
capturedData: any = null;
|
|
177
|
+
isCompleted = false;
|
|
178
|
+
|
|
179
|
+
ngOnInit() {
|
|
180
|
+
// El elemento ya está disponible después de la vista
|
|
172
181
|
}
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
182
|
+
|
|
183
|
+
async preloadModel() {
|
|
184
|
+
try {
|
|
185
|
+
const result = await this.detectorRef.nativeElement.preloadModel();
|
|
186
|
+
console.log('Modelo precargado:', result);
|
|
187
|
+
} catch (error) {
|
|
188
|
+
console.error('Error al precargar modelo:', error);
|
|
189
|
+
}
|
|
176
190
|
}
|
|
177
191
|
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
// Iniciar el escaneo por cámara cuando el componente esté listo
|
|
186
|
-
setTimeout(() => {
|
|
187
|
-
detector.startCameraScan();
|
|
188
|
-
}, 1000);
|
|
192
|
+
async startCapture() {
|
|
193
|
+
try {
|
|
194
|
+
await this.detectorRef.nativeElement.startCapture();
|
|
195
|
+
} catch (error) {
|
|
196
|
+
console.error('Error al iniciar captura:', error);
|
|
197
|
+
}
|
|
189
198
|
}
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
// Eliminar los event listeners
|
|
195
|
-
detector.removeEventListener('status', this.handleStatus.bind(this));
|
|
196
|
-
detector.removeEventListener('results', this.handleResults.bind(this));
|
|
199
|
+
|
|
200
|
+
async stopCapture() {
|
|
201
|
+
await this.detectorRef.nativeElement.stopCapture();
|
|
197
202
|
}
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
```tsx
|
|
204
|
-
import { Component, h, State, Listen, Element } from '@stencil/core';
|
|
205
|
-
import '@jaak.ai/stamps';
|
|
206
|
-
|
|
207
|
-
@Component({
|
|
208
|
-
tag: 'app-document-detector',
|
|
209
|
-
styleUrl: 'app-document-detector.css',
|
|
210
|
-
shadow: true
|
|
211
|
-
})
|
|
212
|
-
export class AppDocumentDetector {
|
|
213
|
-
@Element() el: HTMLElement;
|
|
214
|
-
@State() results: any = null;
|
|
215
|
-
@State() status: string = '';
|
|
216
|
-
|
|
217
|
-
// Escuchar los eventos emitidos directamente por el componente
|
|
218
|
-
@Listen('status')
|
|
219
|
-
handleStatus(ev: CustomEvent) {
|
|
220
|
-
this.status = ev.detail;
|
|
221
|
-
console.log('Estado del detector:', this.status);
|
|
203
|
+
|
|
204
|
+
async resetCapture() {
|
|
205
|
+
await this.detectorRef.nativeElement.resetCapture();
|
|
206
|
+
this.capturedData = null;
|
|
207
|
+
this.isCompleted = false;
|
|
222
208
|
}
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
209
|
+
|
|
210
|
+
async getImages() {
|
|
211
|
+
try {
|
|
212
|
+
const images = await this.detectorRef.nativeElement.getCapturedImages();
|
|
213
|
+
console.log('Imágenes obtenidas:', images);
|
|
214
|
+
} catch (error) {
|
|
215
|
+
console.error('Error al obtener imágenes:', error);
|
|
216
|
+
}
|
|
228
217
|
}
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
detector.startCameraScan();
|
|
235
|
-
}, 1000);
|
|
218
|
+
|
|
219
|
+
onCaptureCompleted(event: any) {
|
|
220
|
+
console.log('Captura completada en Angular:', event.detail);
|
|
221
|
+
this.capturedData = event.detail;
|
|
222
|
+
this.isCompleted = true;
|
|
236
223
|
}
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
<document-detector
|
|
242
|
-
license-key="TU_CLAVE_DE_LICENCIA"
|
|
243
|
-
/>
|
|
244
|
-
</div>
|
|
245
|
-
);
|
|
224
|
+
|
|
225
|
+
onComponentReady(event: any) {
|
|
226
|
+
console.log('Componente listo en Angular:', event.detail);
|
|
227
|
+
// El componente está listo para iniciar detección
|
|
246
228
|
}
|
|
247
229
|
}
|
|
248
230
|
```
|
|
249
231
|
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
El componente `document-detector` es el elemento principal de esta librería, diseñado para proporcionar una experiencia completa de escaneo e identificación de documentos en aplicaciones web.
|
|
253
|
-
|
|
254
|
-
### Descripción General
|
|
255
|
-
|
|
256
|
-
El `document-detector` es un componente web que utiliza tecnología de reconocimiento óptico avanzada para escanear y extraer información de documentos de identidad. Está construido sobre el SDK BlinkID y ofrece una interfaz fácil de usar para integrar capacidades de escaneo de documentos en cualquier aplicación web.
|
|
257
|
-
|
|
258
|
-
### Características Principales
|
|
259
|
-
|
|
260
|
-
- **Escaneo en tiempo real**: Captura documentos de identidad a través de la cámara del dispositivo.
|
|
261
|
-
- **Procesamiento de imágenes**: Permite cargar imágenes de documentos para su análisis.
|
|
262
|
-
- **Soporte para documentos de doble cara**: Puede procesar ambos lados de documentos como identificaciones o licencias de conducir.
|
|
263
|
-
- **Extracción de datos**: Obtiene automáticamente información como nombre, fecha de nacimiento, número de documento, etc.
|
|
264
|
-
- **Captura de imágenes**: Guarda imágenes del documento, rostro y firma cuando están disponibles.
|
|
265
|
-
- **Interfaz personalizable**: Permite adaptar la apariencia y comportamiento a las necesidades de tu aplicación.
|
|
266
|
-
- **Eventos detallados**: Proporciona eventos para cada etapa del proceso de escaneo.
|
|
267
|
-
- **Modo dinámico**: Optimiza automáticamente el rendimiento según el dispositivo (escritorio o móvil).
|
|
268
|
-
- **Filtros de calidad ajustables**: Controla la rigurosidad de los filtros de desenfoque y brillo.
|
|
269
|
-
- **Traducciones personalizables**: Permite personalizar todos los mensajes mostrados al usuario.
|
|
270
|
-
- **Capacidad de reinicio**: Facilita reiniciar el componente sin necesidad de recargarlo.
|
|
271
|
-
|
|
272
|
-
### Ciclo de Vida del Componente
|
|
273
|
-
|
|
274
|
-
1. **Inicialización**: El componente carga el SDK y prepara los reconocedores.
|
|
275
|
-
2. **Detección**: Busca un documento en el campo visual de la cámara o en la imagen proporcionada.
|
|
276
|
-
3. **Análisis**: Procesa el documento detectado para extraer la información.
|
|
277
|
-
4. **Resultados**: Emite los datos extraídos y las imágenes capturadas.
|
|
278
|
-
|
|
279
|
-
### Casos de Uso Comunes
|
|
280
|
-
|
|
281
|
-
- **Verificación de identidad**: Para procesos de onboarding digital o KYC (Know Your Customer).
|
|
282
|
-
- **Registro de usuarios**: Automatización de la captura de datos personales.
|
|
283
|
-
- **Check-in digital**: En hoteles, eventos o instalaciones que requieren identificación.
|
|
284
|
-
- **Servicios financieros**: Para apertura de cuentas o solicitudes de crédito.
|
|
285
|
-
- **Servicios de salud**: Registro de pacientes y verificación de seguros.
|
|
286
|
-
|
|
287
|
-
### Ejemplo de Implementación Básica
|
|
232
|
+
### React
|
|
288
233
|
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
</document-detector>
|
|
293
|
-
|
|
294
|
-
<!-- O usando la propiedad config con opciones avanzadas -->
|
|
295
|
-
<document-detector
|
|
296
|
-
config='{
|
|
297
|
-
"key": "TU_CLAVE_DE_LICENCIA",
|
|
298
|
-
"dynamicMode": true,
|
|
299
|
-
"strictMode": true,
|
|
300
|
-
"translation": {
|
|
301
|
-
"front": "Escanea el frente de tu documento",
|
|
302
|
-
"back": "Ahora escanea el reverso",
|
|
303
|
-
"changeSide": "Voltea el documento",
|
|
304
|
-
"cameraFeedbackBlur": "El documento está borroso",
|
|
305
|
-
"cameraFeedbackGlare": "Evita el reflejo en el documento"
|
|
306
|
-
}
|
|
307
|
-
}'>
|
|
308
|
-
</document-detector>
|
|
234
|
+
#### 1. Instalar el componente
|
|
235
|
+
```bash
|
|
236
|
+
npm install @jaak.ai/stamps
|
|
309
237
|
```
|
|
310
238
|
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
//
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
239
|
+
#### 2. Crear componente wrapper (opcional pero recomendado)
|
|
240
|
+
```jsx
|
|
241
|
+
// JaakStampsWrapper.jsx
|
|
242
|
+
import React, { useRef, useEffect, useImperativeHandle, forwardRef } from 'react';
|
|
243
|
+
|
|
244
|
+
// Importar el web component
|
|
245
|
+
import '@jaak.ai/stamps/dist/jaak-stamps-webcomponent/jaak-stamps-webcomponent.esm.js';
|
|
246
|
+
|
|
247
|
+
const JaakStampsWrapper = forwardRef(({ debug = false, maskSize = 90, cropMargin = 0, useDocumentClassification = false, onCaptureCompleted, onIsReady }, ref) => {
|
|
248
|
+
const elementRef = useRef(null);
|
|
249
|
+
|
|
250
|
+
useImperativeHandle(ref, () => ({
|
|
251
|
+
preloadModel: () => elementRef.current?.preloadModel(),
|
|
252
|
+
startCapture: () => elementRef.current?.startCapture(),
|
|
253
|
+
stopCapture: () => elementRef.current?.stopCapture(),
|
|
254
|
+
resetCapture: () => elementRef.current?.resetCapture(),
|
|
255
|
+
getCapturedImages: () => elementRef.current?.getCapturedImages(),
|
|
256
|
+
getStatus: () => elementRef.current?.getStatus(),
|
|
257
|
+
skipBackCapture: () => elementRef.current?.skipBackCapture(),
|
|
258
|
+
isProcessCompleted: () => elementRef.current?.isProcessCompleted()
|
|
259
|
+
}));
|
|
260
|
+
|
|
261
|
+
useEffect(() => {
|
|
262
|
+
const element = elementRef.current;
|
|
263
|
+
|
|
264
|
+
const handleCaptureCompleted = (event) => {
|
|
265
|
+
if (onCaptureCompleted) {
|
|
266
|
+
onCaptureCompleted(event.detail);
|
|
267
|
+
}
|
|
268
|
+
};
|
|
269
|
+
|
|
270
|
+
const handleIsReady = (event) => {
|
|
271
|
+
if (onIsReady) {
|
|
272
|
+
onIsReady(event.detail);
|
|
273
|
+
}
|
|
274
|
+
};
|
|
275
|
+
|
|
276
|
+
if (element) {
|
|
277
|
+
element.addEventListener('captureCompleted', handleCaptureCompleted);
|
|
278
|
+
element.addEventListener('isReady', handleIsReady);
|
|
279
|
+
|
|
280
|
+
return () => {
|
|
281
|
+
element.removeEventListener('captureCompleted', handleCaptureCompleted);
|
|
282
|
+
element.removeEventListener('isReady', handleIsReady);
|
|
283
|
+
};
|
|
284
|
+
}
|
|
285
|
+
}, [onCaptureCompleted, onIsReady]);
|
|
286
|
+
|
|
287
|
+
return (
|
|
288
|
+
<jaak-stamps
|
|
289
|
+
ref={elementRef}
|
|
290
|
+
debug={debug}
|
|
291
|
+
mask-size={maskSize}
|
|
292
|
+
crop-margin={cropMargin}
|
|
293
|
+
use-document-classification={useDocumentClassification}
|
|
294
|
+
/>
|
|
295
|
+
);
|
|
353
296
|
});
|
|
354
297
|
|
|
355
|
-
|
|
356
|
-
detector.addEventListener('results', (event) => {
|
|
357
|
-
const resultados = event.detail;
|
|
358
|
-
console.log('Datos del documento:', resultados);
|
|
359
|
-
|
|
360
|
-
// Acceder a imágenes del documento (si están disponibles)
|
|
361
|
-
if (resultados.generalData && resultados.generalData.documentImage) {
|
|
362
|
-
const imagenFrente = resultados.generalData.documentImage.front;
|
|
363
|
-
const imagenReverso = resultados.generalData.documentImage.back;
|
|
364
|
-
const imagenRostro = resultados.generalData.documentImage.face;
|
|
365
|
-
|
|
366
|
-
// Hacer algo con las imágenes...
|
|
367
|
-
}
|
|
368
|
-
});
|
|
298
|
+
export default JaakStampsWrapper;
|
|
369
299
|
```
|
|
370
300
|
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
// Iniciar escaneo por cámara
|
|
377
|
-
function iniciarEscaneoCamara() {
|
|
378
|
-
detector.startCameraScan();
|
|
379
|
-
}
|
|
380
|
-
|
|
381
|
-
// Iniciar escaneo desde archivo de imagen
|
|
382
|
-
function escanearDesdeImagen(archivo) {
|
|
383
|
-
detector.startImageScan(archivo);
|
|
384
|
-
}
|
|
301
|
+
#### 3. Usar en tu aplicación React
|
|
302
|
+
```jsx
|
|
303
|
+
// App.jsx
|
|
304
|
+
import React, { useRef, useState } from 'react';
|
|
305
|
+
import JaakStampsWrapper from './components/JaakStampsWrapper';
|
|
385
306
|
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
307
|
+
function App() {
|
|
308
|
+
const detectorRef = useRef(null);
|
|
309
|
+
const [capturedData, setCapturedData] = useState(null);
|
|
310
|
+
const [isCompleted, setIsCompleted] = useState(false);
|
|
311
|
+
const [status, setStatus] = useState(null);
|
|
312
|
+
|
|
313
|
+
const handleCaptureCompleted = (data) => {
|
|
314
|
+
console.log('Captura completada:', data);
|
|
315
|
+
setCapturedData(data);
|
|
316
|
+
setIsCompleted(true);
|
|
317
|
+
};
|
|
318
|
+
|
|
319
|
+
const handleIsReady = (isReady) => {
|
|
320
|
+
console.log('Componente listo:', isReady);
|
|
321
|
+
// El componente está listo para iniciar detección
|
|
322
|
+
};
|
|
323
|
+
|
|
324
|
+
const preloadModel = async () => {
|
|
325
|
+
try {
|
|
326
|
+
const result = await detectorRef.current?.preloadModel();
|
|
327
|
+
console.log('Modelo precargado:', result);
|
|
328
|
+
} catch (error) {
|
|
329
|
+
console.error('Error al precargar modelo:', error);
|
|
330
|
+
}
|
|
331
|
+
};
|
|
332
|
+
|
|
333
|
+
const startCapture = async () => {
|
|
334
|
+
try {
|
|
335
|
+
await detectorRef.current?.startCapture();
|
|
336
|
+
} catch (error) {
|
|
337
|
+
console.error('Error al iniciar captura:', error);
|
|
338
|
+
}
|
|
339
|
+
};
|
|
340
|
+
|
|
341
|
+
const stopCapture = async () => {
|
|
342
|
+
await detectorRef.current?.stopCapture();
|
|
343
|
+
};
|
|
344
|
+
|
|
345
|
+
const resetCapture = async () => {
|
|
346
|
+
await detectorRef.current?.resetCapture();
|
|
347
|
+
setCapturedData(null);
|
|
348
|
+
setIsCompleted(false);
|
|
349
|
+
};
|
|
350
|
+
|
|
351
|
+
const getImages = async () => {
|
|
352
|
+
try {
|
|
353
|
+
const images = await detectorRef.current?.getCapturedImages();
|
|
354
|
+
console.log('Imágenes obtenidas:', images);
|
|
355
|
+
} catch (error) {
|
|
356
|
+
console.error('Error al obtener imágenes:', error);
|
|
357
|
+
}
|
|
358
|
+
};
|
|
359
|
+
|
|
360
|
+
const checkStatus = async () => {
|
|
361
|
+
const currentStatus = await detectorRef.current?.getStatus();
|
|
362
|
+
setStatus(currentStatus);
|
|
363
|
+
};
|
|
364
|
+
|
|
365
|
+
return (
|
|
366
|
+
<div className="App">
|
|
367
|
+
<header className="App-header">
|
|
368
|
+
<h1>Detector de Documentos - React</h1>
|
|
369
|
+
|
|
370
|
+
<JaakStampsWrapper
|
|
371
|
+
ref={detectorRef}
|
|
372
|
+
debug={false}
|
|
373
|
+
maskSize={90}
|
|
374
|
+
cropMargin={10}
|
|
375
|
+
useDocumentClassification={false}
|
|
376
|
+
onCaptureCompleted={handleCaptureCompleted}
|
|
377
|
+
onIsReady={handleIsReady}
|
|
378
|
+
/>
|
|
379
|
+
|
|
380
|
+
<div className="controls">
|
|
381
|
+
<button onClick={preloadModel}>Precargar Modelo</button>
|
|
382
|
+
<button onClick={startCapture}>Iniciar Captura</button>
|
|
383
|
+
<button onClick={stopCapture}>Detener</button>
|
|
384
|
+
<button onClick={resetCapture}>Reiniciar</button>
|
|
385
|
+
<button onClick={getImages} disabled={!isCompleted}>
|
|
386
|
+
Obtener Imágenes
|
|
387
|
+
</button>
|
|
388
|
+
<button onClick={checkStatus}>Verificar Estado</button>
|
|
389
|
+
</div>
|
|
390
|
+
|
|
391
|
+
{status && (
|
|
392
|
+
<div className="status">
|
|
393
|
+
<h3>Estado Actual:</h3>
|
|
394
|
+
<p>Video activo: {status.isVideoActive ? 'Sí' : 'No'}</p>
|
|
395
|
+
<p>Paso: {status.captureStep}</p>
|
|
396
|
+
<p>Mensaje: {status.statusMessage}</p>
|
|
397
|
+
<p>Proceso completado: {status.isProcessCompleted ? 'Sí' : 'No'}</p>
|
|
398
|
+
<p>Modelo precargado: {status.isModelPreloaded ? 'Sí' : 'No'}</p>
|
|
399
|
+
</div>
|
|
400
|
+
)}
|
|
401
|
+
|
|
402
|
+
{capturedData && (
|
|
403
|
+
<div className="results">
|
|
404
|
+
<h3>Resultados de la Captura:</h3>
|
|
405
|
+
<p>Total de imágenes: {capturedData.metadata.totalImages}</p>
|
|
406
|
+
<p>Timestamp: {capturedData.timestamp}</p>
|
|
407
|
+
|
|
408
|
+
{capturedData.front.cropped && (
|
|
409
|
+
<div>
|
|
410
|
+
<h4>Frente del Documento:</h4>
|
|
411
|
+
<img
|
|
412
|
+
src={capturedData.front.cropped}
|
|
413
|
+
alt="Frente del documento"
|
|
414
|
+
style={{ maxWidth: '300px', border: '1px solid #ccc', margin: '10px' }}
|
|
415
|
+
/>
|
|
416
|
+
</div>
|
|
417
|
+
)}
|
|
418
|
+
|
|
419
|
+
{capturedData.back.cropped && (
|
|
420
|
+
<div>
|
|
421
|
+
<h4>Reverso del Documento:</h4>
|
|
422
|
+
<img
|
|
423
|
+
src={capturedData.back.cropped}
|
|
424
|
+
alt="Reverso del documento"
|
|
425
|
+
style={{ maxWidth: '300px', border: '1px solid #ccc', margin: '10px' }}
|
|
426
|
+
/>
|
|
427
|
+
</div>
|
|
428
|
+
)}
|
|
429
|
+
</div>
|
|
430
|
+
)}
|
|
431
|
+
</header>
|
|
432
|
+
</div>
|
|
433
|
+
);
|
|
391
434
|
}
|
|
392
435
|
|
|
393
|
-
|
|
394
|
-
document.getElementById('inputImagen').addEventListener('change', (event) => {
|
|
395
|
-
if (event.target.files && event.target.files[0]) {
|
|
396
|
-
escanearDesdeImagen(event.target.files[0]);
|
|
397
|
-
}
|
|
398
|
-
});
|
|
399
|
-
```
|
|
400
|
-
|
|
401
|
-
### Personalización de la Apariencia
|
|
402
|
-
|
|
403
|
-
El componente puede personalizarse mediante CSS utilizando las partes expuestas a través de Shadow DOM:
|
|
404
|
-
|
|
405
|
-
```css
|
|
406
|
-
document-detector::part(mb-camera-video) {
|
|
407
|
-
border-radius: 16px;
|
|
408
|
-
border: 2px solid #3498db;
|
|
409
|
-
}
|
|
436
|
+
export default App;
|
|
410
437
|
```
|
|
411
438
|
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
- **Permisos de cámara**: El navegador solicitará permiso para acceder a la cámara del dispositivo.
|
|
415
|
-
- **HTTPS**: Para usar la funcionalidad de cámara, tu aplicación debe servirse a través de HTTPS.
|
|
416
|
-
- **Compatibilidad**: Verifica la compatibilidad con navegadores móviles si tu aplicación está orientada a dispositivos móviles.
|
|
417
|
-
- **Licencia**: Se requiere una clave de licencia válida para el funcionamiento del componente.
|
|
418
|
-
|
|
419
|
-
## Referencia de API
|
|
439
|
+
## API Reference
|
|
420
440
|
|
|
421
|
-
###
|
|
441
|
+
### Props/Atributos
|
|
422
442
|
|
|
423
|
-
|
|
443
|
+
| Propiedad | Tipo | Predeterminado | Descripción |
|
|
444
|
+
|-----------|------|---------------|-------------|
|
|
445
|
+
| `debug` | `boolean` | `false` | Activa el modo debug para mostrar información de depuración |
|
|
446
|
+
| `alignmentTolerance` | `number` | `10` | Tolerancia en píxeles para considerar un lado alineado |
|
|
447
|
+
| `maskSize` | `number` | `90` | Porcentaje del video que ocupará la máscara de detección (50-100) |
|
|
448
|
+
| `cropMargin` | `number` | `0` | Margen en píxeles agregado al recorte del documento (0-100) |
|
|
449
|
+
| `useDocumentClassification` | `boolean` | `false` | Habilita la clasificación automática de documentos para determinar si solicitar reverso. Solo carga el modelo de clasificación cuando está habilitada. |
|
|
424
450
|
|
|
425
|
-
|
|
426
|
-
|--------------------------|-------------------------------------------|--------------------------------------------|
|
|
427
|
-
| `license-key` | string | Clave de licencia para el SDK |
|
|
428
|
-
| `config` | object | Configuración del componente (ver detalle abajo) |
|
|
451
|
+
### Métodos Públicos
|
|
429
452
|
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
|
433
|
-
|
|
434
|
-
| `
|
|
435
|
-
| `
|
|
436
|
-
| `
|
|
437
|
-
| `
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
| Propiedad | Tipo | Descripción |
|
|
442
|
-
|--------------------------------|-------------------------------------------|--------------------------------------------|
|
|
443
|
-
| `front` | string | Mensaje para escanear el frente del documento |
|
|
444
|
-
| `back` | string | Mensaje para escanear el reverso del documento |
|
|
445
|
-
| `changeSide` | string | Mensaje para voltear el documento |
|
|
446
|
-
| `adjustAngle` | string | Mensaje para ajustar el ángulo del documento |
|
|
447
|
-
| `cameraFeedbackBlur` | string | Mensaje cuando el documento está borroso |
|
|
448
|
-
| `cameraFeedbackFacePhotoCovered`| string | Mensaje cuando la foto de la cara está cubierta |
|
|
449
|
-
| `cameraFeedbackGlare` | string | Mensaje cuando hay deslumbramiento en el documento |
|
|
450
|
-
| `cameraFeedbackWrongSide` | string | Mensaje cuando se muestra el lado incorrecto del documento |
|
|
451
|
-
| `moveCloser` | string | Mensaje para acercar el documento |
|
|
452
|
-
| `moveFarther` | string | Mensaje para alejar el documento |
|
|
453
|
+
| Método | Retorna | Descripción |
|
|
454
|
+
|--------|---------|-------------|
|
|
455
|
+
| `startCapture()` | `Promise<void>` | Inicia el proceso de detección y captura |
|
|
456
|
+
| `stopCapture()` | `Promise<void>` | Detiene el proceso y libera la cámara |
|
|
457
|
+
| `resetCapture()` | `Promise<void>` | Reinicia el proceso de captura |
|
|
458
|
+
| `preloadModel()` | `Promise<{success: boolean, message?: string, error?: string}>` | Precarga el modelo de detección |
|
|
459
|
+
| `getCapturedImages()` | `Promise<CapturedImages>` | Obtiene las imágenes capturadas (solo después de completar) |
|
|
460
|
+
| `isProcessCompleted()` | `Promise<boolean>` | Verifica si el proceso ha sido completado |
|
|
461
|
+
| `getStatus()` | `Promise<Status>` | Obtiene el estado actual del detector |
|
|
462
|
+
| `skipBackCapture()` | `Promise<void>` | Omite la captura del reverso (solo disponible en paso 'back') |
|
|
453
463
|
|
|
454
464
|
### Eventos
|
|
455
465
|
|
|
456
|
-
|
|
466
|
+
| Evento | Payload | Descripción |
|
|
467
|
+
|--------|---------|-------------|
|
|
468
|
+
| `captureCompleted` | `CapturedImages` | Se emite cuando se completa el proceso de captura |
|
|
469
|
+
| `isReady` | `boolean` | Se emite cuando el componente está listo para comenzar la detección (modelos cargados) |
|
|
457
470
|
|
|
458
|
-
|
|
459
|
-
|----------------------|-------------------------------------------|--------------------------------------------|
|
|
460
|
-
| `status` | StatusDocumentDetector | Cambio de estado del detector |
|
|
461
|
-
| `results` | any | Resultados del escaneo |
|
|
471
|
+
### Tipos de Datos
|
|
462
472
|
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
473
|
+
```typescript
|
|
474
|
+
interface CapturedImages {
|
|
475
|
+
front: {
|
|
476
|
+
fullFrame: string | null; // Base64 de la imagen completa del frente
|
|
477
|
+
cropped: string | null; // Base64 del documento recortado del frente
|
|
478
|
+
};
|
|
479
|
+
back: {
|
|
480
|
+
fullFrame: string | null; // Base64 de la imagen completa del reverso
|
|
481
|
+
cropped: string | null; // Base64 del documento recortado del reverso
|
|
482
|
+
};
|
|
483
|
+
timestamp: string; // ISO timestamp de la captura
|
|
484
|
+
metadata: {
|
|
485
|
+
totalImages: number; // Número total de imágenes capturadas
|
|
486
|
+
processCompleted: boolean; // Si el proceso fue completado
|
|
487
|
+
backCaptureSkipped?: boolean; // Si se omitió la captura del reverso
|
|
488
|
+
};
|
|
489
|
+
}
|
|
466
490
|
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
491
|
+
interface Status {
|
|
492
|
+
isVideoActive: boolean; // Si la cámara está activa
|
|
493
|
+
captureStep: 'front' | 'back' | 'completed'; // Paso actual del proceso
|
|
494
|
+
statusMessage: string; // Mensaje de estado actual
|
|
495
|
+
hasImages: boolean; // Si hay imágenes capturadas
|
|
496
|
+
isProcessCompleted: boolean; // Si el proceso está completado
|
|
497
|
+
isModelPreloaded: boolean; // Si el modelo está precargado
|
|
498
|
+
}
|
|
499
|
+
```
|
|
476
500
|
|
|
477
|
-
##
|
|
501
|
+
## Flujo de Trabajo
|
|
502
|
+
|
|
503
|
+
### Flujo Estándar (useDocumentClassification = false)
|
|
504
|
+
1. **Inicialización**: El componente se prepara para la detección
|
|
505
|
+
2. **Inicio de captura**: Se carga automáticamente el modelo de detección
|
|
506
|
+
3. **Captura del frente**: El usuario posiciona el documento y se captura automáticamente
|
|
507
|
+
4. **Solicitud de reverso**: Siempre se solicita voltear el documento para capturar el reverso
|
|
508
|
+
5. **Botón "Saltar reverso"**: Disponible para omitir manualmente la captura del reverso
|
|
509
|
+
6. **Completado**: Se emite el evento `captureCompleted` con las imágenes correspondientes
|
|
510
|
+
|
|
511
|
+
### Flujo con Clasificación Inteligente (useDocumentClassification = true)
|
|
512
|
+
1. **Inicialización**: El componente se prepara para la detección
|
|
513
|
+
2. **Inicio de captura**: Se cargan automáticamente los modelos de detección y clasificación
|
|
514
|
+
3. **Captura del frente**: El usuario posiciona el documento y se captura automáticamente
|
|
515
|
+
4. **Clasificación automática**: El sistema determina si el documento requiere captura de reverso
|
|
516
|
+
5. **Flujo adaptativo**:
|
|
517
|
+
- **Si es pasaporte**: Se completa automáticamente el proceso (sin reverso)
|
|
518
|
+
- **Si es otro documento**: Se solicita voltear el documento para capturar el reverso
|
|
519
|
+
6. **Completado**: Se emite el evento `captureCompleted` con las imágenes correspondientes
|
|
520
|
+
|
|
521
|
+
### Flujo con Precarga (Recomendado)
|
|
522
|
+
1. **Precarga de modelos**: Se llama a `preloadModel()` para cargar ambos modelos en memoria
|
|
523
|
+
2. **Inicio optimizado**: Al iniciar la captura, se usan los modelos ya cargados
|
|
524
|
+
3. **Captura del frente**: Detección y clasificación más rápidas con modelos precargados
|
|
525
|
+
4. **Flujo inteligente**:
|
|
526
|
+
- **Documento sin reverso**: Proceso completado inmediatamente
|
|
527
|
+
- **Documento con reverso**: Se solicita captura del reverso
|
|
528
|
+
5. **Completado**: Se emite el evento `captureCompleted` con todas las imágenes
|
|
529
|
+
|
|
530
|
+
### Clasificación de Documentos
|
|
531
|
+
|
|
532
|
+
#### Modo con Clasificación Habilitada (`useDocumentClassification = true`)
|
|
533
|
+
Cuando la propiedad está habilitada, el sistema utiliza un modelo de inteligencia artificial especializado para determinar automáticamente si el documento requiere captura de reverso:
|
|
534
|
+
- **Pasaportes**: Se omite automáticamente la captura del reverso
|
|
535
|
+
- **Otros documentos**: Requieren captura de ambos lados (frente y reverso)
|
|
536
|
+
- **Botón "Saltar reverso"**: Siempre disponible para permitir flexibilidad manual
|
|
537
|
+
- **Carga optimizada**: El modelo de clasificación se descarga solo cuando es necesario
|
|
538
|
+
|
|
539
|
+
#### Modo Estándar (`useDocumentClassification = false`, por defecto)
|
|
540
|
+
Cuando está deshabilitada, el comportamiento es más liviano y directo:
|
|
541
|
+
- **Todos los documentos**: Siempre se solicita captura del reverso
|
|
542
|
+
- **Botón "Saltar reverso"**: Disponible para omitir manualmente la captura
|
|
543
|
+
- **Sin clasificación**: NO se carga el modelo de clasificación, solo el de detección
|
|
544
|
+
- **Menor uso de ancho de banda**: Solo descarga el modelo de detección (~5MB menos)
|
|
545
|
+
|
|
546
|
+
#### Consideraciones de Rendimiento
|
|
547
|
+
- **Con clasificación deshabilitada**: Carga más rápida y menor uso de datos
|
|
548
|
+
- **Con clasificación habilitada**: Experiencia más inteligente pero requiere descargar modelo adicional
|
|
549
|
+
- **Carga bajo demanda**: El modelo de clasificación se carga solo cuando se captura el primer documento
|
|
550
|
+
|
|
551
|
+
## Requisitos del Sistema
|
|
552
|
+
|
|
553
|
+
- **Navegadores**: Chrome/Edge 88+, Firefox 85+, Safari 14+
|
|
554
|
+
- **Cámara**: Acceso a cámara trasera (móvil) o webcam (escritorio)
|
|
555
|
+
- **Conexión**: Conexión a internet para cargar los modelos de IA
|
|
556
|
+
|
|
557
|
+
## Consideraciones de Privacidad y Rendimiento
|
|
558
|
+
|
|
559
|
+
### Privacidad
|
|
560
|
+
- Las imágenes se procesan localmente en el navegador
|
|
561
|
+
- No se envían datos a servidores externos
|
|
562
|
+
- Los modelos de IA (detección y clasificación) se ejecutan completamente en el cliente
|
|
563
|
+
- La clasificación de documentos se realiza de forma privada y local
|
|
564
|
+
- Las imágenes capturadas solo están disponibles en el contexto de tu aplicación
|
|
565
|
+
|
|
566
|
+
### Optimización de Recursos
|
|
567
|
+
- **Carga condicional**: Solo descarga modelos necesarios según configuración
|
|
568
|
+
- **Modelo de detección**: ~15MB (siempre requerido)
|
|
569
|
+
- **Modelo de clasificación**: ~5MB (solo si `useDocumentClassification = true`)
|
|
570
|
+
- **Lazy loading**: Los modelos se cargan cuando realmente se necesitan
|
|
571
|
+
- **Cache del navegador**: Los modelos se almacenan localmente después de la primera descarga
|
|
572
|
+
|
|
573
|
+
## Desarrollo
|
|
574
|
+
|
|
575
|
+
### Clonar el repositorio
|
|
576
|
+
```bash
|
|
577
|
+
git clone [repository-url]
|
|
578
|
+
cd jaak-stamps-webcomponent
|
|
579
|
+
```
|
|
478
580
|
|
|
479
|
-
|
|
581
|
+
### Instalar dependencias
|
|
582
|
+
```bash
|
|
583
|
+
npm install
|
|
584
|
+
```
|
|
480
585
|
|
|
481
|
-
###
|
|
586
|
+
### Desarrollo local
|
|
587
|
+
```bash
|
|
588
|
+
npm start
|
|
589
|
+
```
|
|
482
590
|
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
ERROR = "ERROR",
|
|
487
|
-
RUNNING = "RUNNING",
|
|
488
|
-
INITIALIZING = "INITIALIZING",
|
|
489
|
-
FRONT_SIDE_DETECTION = "FRONT_SIDE_DETECTION",
|
|
490
|
-
BACK_SIDE_DETECTION = "BACK_SIDE_DETECTION",
|
|
491
|
-
DOCUMENT_NOT_FOUND = "DOCUMENT_NOT_FOUND",
|
|
492
|
-
DOCUMENT_DETECTED = "DOCUMENT_DETECTED",
|
|
493
|
-
CHANGE_SIDE = "CHANGE_SIDE",
|
|
494
|
-
RESULTS_SUCCESS = "RESULTS_SUCCESS",
|
|
495
|
-
RESULTS_EMPTY = "RESULTS_EMPTY",
|
|
496
|
-
DETECTION_FAILED = "DETECTION_FAILED"
|
|
497
|
-
}
|
|
591
|
+
### Construir para producción
|
|
592
|
+
```bash
|
|
593
|
+
npm run build
|
|
498
594
|
```
|
|
499
595
|
|
|
500
|
-
###
|
|
596
|
+
### Ejecutar tests
|
|
597
|
+
```bash
|
|
598
|
+
npm test
|
|
599
|
+
```
|
|
501
600
|
|
|
502
|
-
|
|
601
|
+
## Soporte
|
|
503
602
|
|
|
504
|
-
|
|
505
|
-
interface DocumentData {
|
|
506
|
-
generalData: {
|
|
507
|
-
type: string;
|
|
508
|
-
nationality: string;
|
|
509
|
-
name: string;
|
|
510
|
-
surname: string;
|
|
511
|
-
address: string;
|
|
512
|
-
birthDate: string;
|
|
513
|
-
gender: string;
|
|
514
|
-
documentImage: {
|
|
515
|
-
frontFull: string; // Imagen base64
|
|
516
|
-
backFull: string; // Imagen base64
|
|
517
|
-
front: string; // Imagen base64
|
|
518
|
-
back: string; // Imagen base64
|
|
519
|
-
signature: string; // Imagen base64
|
|
520
|
-
face: string; // Imagen base64
|
|
521
|
-
}
|
|
522
|
-
};
|
|
523
|
-
mechanicalReadingZone: string;
|
|
524
|
-
specificData: Array<{
|
|
525
|
-
label: string;
|
|
526
|
-
value: string;
|
|
527
|
-
}>;
|
|
528
|
-
}
|
|
529
|
-
```
|
|
603
|
+
Para reportar bugs o solicitar características, por favor crea un issue en el repositorio del proyecto.
|
|
530
604
|
|
|
531
605
|
## Licencia
|
|
532
606
|
|
|
533
|
-
MIT
|
|
607
|
+
MIT License - ver archivo LICENSE para detalles.
|