@jaak.ai/stamps 2.0.0-dev.23 → 2.0.0-dev.24
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +22 -9
- package/dist/cjs/jaak-stamps.cjs.entry.js +116 -16
- package/dist/cjs/jaak-stamps.cjs.entry.js.map +1 -1
- package/dist/cjs/jaak-stamps.entry.cjs.js.map +1 -1
- package/dist/collection/components/my-component/my-component.js +116 -16
- package/dist/collection/components/my-component/my-component.js.map +1 -1
- package/dist/components/jaak-stamps.js +116 -16
- package/dist/components/jaak-stamps.js.map +1 -1
- package/dist/esm/jaak-stamps.entry.js +116 -16
- package/dist/esm/jaak-stamps.entry.js.map +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-0521d8f5.entry.js +2 -0
- package/dist/jaak-stamps-webcomponent/p-0521d8f5.entry.js.map +1 -0
- package/dist/types/components/my-component/my-component.d.ts +7 -0
- package/package.json +1 -1
- package/dist/jaak-stamps-webcomponent/p-380b1ebe.entry.js +0 -2
- package/dist/jaak-stamps-webcomponent/p-380b1ebe.entry.js.map +0 -1
|
@@ -48,6 +48,8 @@ const JaakStamps$1 = /*@__PURE__*/ proxyCustomElement(class JaakStamps extends H
|
|
|
48
48
|
animationId;
|
|
49
49
|
hasScreenshotTaken = false;
|
|
50
50
|
lastDetectedBox;
|
|
51
|
+
mobileNetSession;
|
|
52
|
+
mobileNetClassMap;
|
|
51
53
|
// Performance optimization properties
|
|
52
54
|
frameSkipCounter = 0;
|
|
53
55
|
FRAME_SKIP = 2; // Process every 3rd frame (reduces CPU by ~66%)
|
|
@@ -60,7 +62,9 @@ const JaakStamps$1 = /*@__PURE__*/ proxyCustomElement(class JaakStamps extends H
|
|
|
60
62
|
preprocessCtx;
|
|
61
63
|
captureCanvas;
|
|
62
64
|
captureCtx;
|
|
63
|
-
MODEL_PATH = "https://storage.googleapis.com/jaak-static/web/component/stamps/
|
|
65
|
+
MODEL_PATH = "https://storage.googleapis.com/jaak-static/web/component/stamps/ddmyp-v1.onnx";
|
|
66
|
+
MOBILENET_MODEL_PATH = "https://storage.googleapis.com/jaak-static/web/component/stamps/cdmmp-v1.onnx";
|
|
67
|
+
MOBILENET_CLASSES_PATH = "https://storage.googleapis.com/jaak-static/web/component/stamps/cdmmp-v1.json";
|
|
64
68
|
INPUT_SIZE = 320;
|
|
65
69
|
CONFIDENCE_THRESHOLD = 0.6;
|
|
66
70
|
// ISO/IEC 7810 ID-1 standard dimensions (85.60mm x 53.98mm)
|
|
@@ -266,25 +270,27 @@ const JaakStamps$1 = /*@__PURE__*/ proxyCustomElement(class JaakStamps extends H
|
|
|
266
270
|
}
|
|
267
271
|
try {
|
|
268
272
|
this.isLoading = true;
|
|
269
|
-
this.statusMessage = "Precargando
|
|
273
|
+
this.statusMessage = "Precargando modelos...";
|
|
270
274
|
this.statusColor = "#007bff";
|
|
271
275
|
const modelPath = this.MODEL_PATH;
|
|
272
|
-
this.debugLog('🤖 Preloading model:', modelPath);
|
|
276
|
+
this.debugLog('🤖 Preloading detection model:', modelPath);
|
|
273
277
|
// Configure ONNX Runtime with device-specific optimizations
|
|
274
278
|
const sessionOptions = this.getSessionOptions();
|
|
275
279
|
this.session = await window.ort.InferenceSession.create(modelPath, sessionOptions);
|
|
280
|
+
// Preload MobileNet model and classes
|
|
281
|
+
await this.loadMobileNetModel();
|
|
276
282
|
this.isModelPreloaded = true;
|
|
277
283
|
this.isLoading = false;
|
|
278
|
-
this.statusMessage = "
|
|
284
|
+
this.statusMessage = "Modelos precargados. Listo para comenzar detección";
|
|
279
285
|
this.statusColor = "#28a745";
|
|
280
286
|
this.emitReadyEvent();
|
|
281
|
-
this.debugLog('✅
|
|
282
|
-
return { success: true, message: '
|
|
287
|
+
this.debugLog('✅ Models preloaded successfully');
|
|
288
|
+
return { success: true, message: 'Models preloaded successfully' };
|
|
283
289
|
}
|
|
284
290
|
catch (error) {
|
|
285
|
-
this.debugLog('❌ Error preloading
|
|
291
|
+
this.debugLog('❌ Error preloading models:', error);
|
|
286
292
|
this.isLoading = false;
|
|
287
|
-
this.statusMessage = "Error al precargar
|
|
293
|
+
this.statusMessage = "Error al precargar los modelos";
|
|
288
294
|
this.statusColor = "#ff6b6b";
|
|
289
295
|
return { success: false, error: error.message };
|
|
290
296
|
}
|
|
@@ -294,6 +300,80 @@ const JaakStamps$1 = /*@__PURE__*/ proxyCustomElement(class JaakStamps extends H
|
|
|
294
300
|
this.completeProcess(true);
|
|
295
301
|
}
|
|
296
302
|
}
|
|
303
|
+
async loadMobileNetModel() {
|
|
304
|
+
try {
|
|
305
|
+
this.debugLog('🤖 Loading MobileNet model...');
|
|
306
|
+
// Load class map
|
|
307
|
+
const classResponse = await fetch(this.MOBILENET_CLASSES_PATH);
|
|
308
|
+
if (!classResponse.ok) {
|
|
309
|
+
throw new Error(`Failed to load class map: ${this.MOBILENET_CLASSES_PATH}`);
|
|
310
|
+
}
|
|
311
|
+
this.mobileNetClassMap = await classResponse.json();
|
|
312
|
+
this.debugLog('📋 MobileNet classes loaded:', this.mobileNetClassMap);
|
|
313
|
+
// Load model
|
|
314
|
+
const sessionOptions = this.getSessionOptions();
|
|
315
|
+
this.mobileNetSession = await window.ort.InferenceSession.create(this.MOBILENET_MODEL_PATH, sessionOptions);
|
|
316
|
+
this.debugLog('✅ MobileNet model loaded successfully');
|
|
317
|
+
}
|
|
318
|
+
catch (error) {
|
|
319
|
+
this.debugLog('❌ Error loading MobileNet model:', error);
|
|
320
|
+
throw error;
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
preprocessMobileNet(canvas) {
|
|
324
|
+
// Create a temporary canvas for MobileNet preprocessing (224x224)
|
|
325
|
+
const tempCanvas = document.createElement('canvas');
|
|
326
|
+
tempCanvas.width = 224;
|
|
327
|
+
tempCanvas.height = 224;
|
|
328
|
+
const tempCtx = tempCanvas.getContext('2d');
|
|
329
|
+
// Draw the cropped image onto the 224x224 canvas
|
|
330
|
+
tempCtx.drawImage(canvas, 0, 0, 224, 224);
|
|
331
|
+
// Get image data and preprocess for MobileNet
|
|
332
|
+
const imageData = tempCtx.getImageData(0, 0, 224, 224);
|
|
333
|
+
const data = imageData.data;
|
|
334
|
+
const hw = 224 * 224;
|
|
335
|
+
const arr = new Float32Array(3 * hw);
|
|
336
|
+
// Normalize pixels: (pixel/255 - 0.5) / 0.5 = (pixel - 127.5) / 127.5
|
|
337
|
+
for (let i = 0; i < hw; i++) {
|
|
338
|
+
arr[i] = (data[i * 4 + 0] / 255 - 0.5) / 0.5; // R
|
|
339
|
+
arr[hw + i] = (data[i * 4 + 1] / 255 - 0.5) / 0.5; // G
|
|
340
|
+
arr[2 * hw + i] = (data[i * 4 + 2] / 255 - 0.5) / 0.5; // B
|
|
341
|
+
}
|
|
342
|
+
return new window.ort.Tensor('float32', arr, [1, 3, 224, 224]);
|
|
343
|
+
}
|
|
344
|
+
async classifyDocument(canvas) {
|
|
345
|
+
if (!this.mobileNetSession || !this.mobileNetClassMap) {
|
|
346
|
+
this.debugLog('⚠️ MobileNet model not loaded');
|
|
347
|
+
return null;
|
|
348
|
+
}
|
|
349
|
+
try {
|
|
350
|
+
this.debugLog('🔍 Classifying document...');
|
|
351
|
+
// Preprocess image for MobileNet
|
|
352
|
+
const inputTensor = this.preprocessMobileNet(canvas);
|
|
353
|
+
// Run inference
|
|
354
|
+
const feeds = { input: inputTensor };
|
|
355
|
+
const results = await this.mobileNetSession.run(feeds);
|
|
356
|
+
const output = results[Object.keys(results)[0]].data;
|
|
357
|
+
// Find the class with highest confidence
|
|
358
|
+
const maxIdx = output.reduce((bestIdx, val, idx, arr) => val > arr[bestIdx] ? idx : bestIdx, 0);
|
|
359
|
+
const confidence = output[maxIdx];
|
|
360
|
+
const className = this.mobileNetClassMap[maxIdx.toString()] || "unknown";
|
|
361
|
+
this.debugLog('📄 Document classification result:', {
|
|
362
|
+
class: className,
|
|
363
|
+
confidence: confidence.toFixed(3),
|
|
364
|
+
classIndex: maxIdx
|
|
365
|
+
});
|
|
366
|
+
return {
|
|
367
|
+
class: className,
|
|
368
|
+
confidence: confidence,
|
|
369
|
+
classIndex: maxIdx
|
|
370
|
+
};
|
|
371
|
+
}
|
|
372
|
+
catch (error) {
|
|
373
|
+
this.debugLog('❌ Error classifying document:', error);
|
|
374
|
+
return null;
|
|
375
|
+
}
|
|
376
|
+
}
|
|
297
377
|
cleanup() {
|
|
298
378
|
if (this.animationId) {
|
|
299
379
|
cancelAnimationFrame(this.animationId);
|
|
@@ -321,11 +401,16 @@ const JaakStamps$1 = /*@__PURE__*/ proxyCustomElement(class JaakStamps extends H
|
|
|
321
401
|
this.captureCtx = undefined;
|
|
322
402
|
this.captureCanvas = undefined;
|
|
323
403
|
}
|
|
324
|
-
// Disposed ONNX
|
|
404
|
+
// Disposed ONNX sessions
|
|
325
405
|
if (this.session) {
|
|
326
406
|
this.session.release?.();
|
|
327
407
|
this.session = undefined;
|
|
328
408
|
}
|
|
409
|
+
if (this.mobileNetSession) {
|
|
410
|
+
this.mobileNetSession.release?.();
|
|
411
|
+
this.mobileNetSession = undefined;
|
|
412
|
+
}
|
|
413
|
+
this.mobileNetClassMap = undefined;
|
|
329
414
|
this.isModelPreloaded = false;
|
|
330
415
|
this.debugLog('🧹 Canvas pool cleaned up');
|
|
331
416
|
}
|
|
@@ -456,18 +541,22 @@ const JaakStamps$1 = /*@__PURE__*/ proxyCustomElement(class JaakStamps extends H
|
|
|
456
541
|
// Check if model is already preloaded
|
|
457
542
|
if (!this.session) {
|
|
458
543
|
this.isLoading = true;
|
|
459
|
-
this.statusMessage = "Cargando
|
|
544
|
+
this.statusMessage = "Cargando modelos...";
|
|
460
545
|
this.statusColor = "#007bff";
|
|
461
546
|
const modelPath = this.MODEL_PATH;
|
|
462
|
-
this.debugLog('🤖 Loading model:', modelPath);
|
|
547
|
+
this.debugLog('🤖 Loading detection model:', modelPath);
|
|
463
548
|
const sessionOptions = this.getSessionOptions();
|
|
464
549
|
this.session = await window.ort.InferenceSession.create(modelPath, sessionOptions);
|
|
550
|
+
// Load MobileNet model if not already loaded
|
|
551
|
+
if (!this.mobileNetSession) {
|
|
552
|
+
await this.loadMobileNetModel();
|
|
553
|
+
}
|
|
465
554
|
this.isModelPreloaded = true;
|
|
466
555
|
this.emitReadyEvent();
|
|
467
556
|
}
|
|
468
557
|
else {
|
|
469
|
-
this.debugLog('🚀 Using preloaded
|
|
470
|
-
this.statusMessage = "Usando
|
|
558
|
+
this.debugLog('🚀 Using preloaded models');
|
|
559
|
+
this.statusMessage = "Usando modelos precargados...";
|
|
471
560
|
this.statusColor = "#007bff";
|
|
472
561
|
}
|
|
473
562
|
this.statusMessage = "Configurando cámara...";
|
|
@@ -686,7 +775,9 @@ const JaakStamps$1 = /*@__PURE__*/ proxyCustomElement(class JaakStamps extends H
|
|
|
686
775
|
corners?.forEach(corner => corner.classList.add('perfect-match'));
|
|
687
776
|
if (!this.hasScreenshotTaken) {
|
|
688
777
|
this.lastDetectedBox = bestBox;
|
|
689
|
-
this.takeScreenshot()
|
|
778
|
+
this.takeScreenshot().catch(error => {
|
|
779
|
+
this.debugLog('❌ Error taking screenshot:', error);
|
|
780
|
+
});
|
|
690
781
|
this.hasScreenshotTaken = true;
|
|
691
782
|
// Reset para permitir segunda captura
|
|
692
783
|
setTimeout(() => {
|
|
@@ -769,7 +860,7 @@ const JaakStamps$1 = /*@__PURE__*/ proxyCustomElement(class JaakStamps extends H
|
|
|
769
860
|
ctx.strokeRect(x, y, w, h);
|
|
770
861
|
});
|
|
771
862
|
}
|
|
772
|
-
takeScreenshot() {
|
|
863
|
+
async takeScreenshot() {
|
|
773
864
|
if (!this.videoRef || !this.lastDetectedBox)
|
|
774
865
|
return;
|
|
775
866
|
// Activar animación
|
|
@@ -803,6 +894,15 @@ const JaakStamps$1 = /*@__PURE__*/ proxyCustomElement(class JaakStamps extends H
|
|
|
803
894
|
// Captura del frente usando canvas reutilizado
|
|
804
895
|
this.capturedFullFrame = this.captureCanvas.toDataURL('image/png');
|
|
805
896
|
this.capturedCroppedId = croppedCanvas.toDataURL('image/png');
|
|
897
|
+
// Classify the cropped document
|
|
898
|
+
const classification = await this.classifyDocument(croppedCanvas);
|
|
899
|
+
if (classification && classification.class === 'passport') {
|
|
900
|
+
// If it's a passport, skip back capture since passports don't have a back side
|
|
901
|
+
this.debugLog('📄 Passport detected - skipping back capture');
|
|
902
|
+
this.completeProcess(true);
|
|
903
|
+
return;
|
|
904
|
+
}
|
|
905
|
+
// For other IDs, continue with normal flow (back capture)
|
|
806
906
|
this.captureStep = 'back';
|
|
807
907
|
this.statusMessage = "Voltee la identificación y muestre la parte trasera";
|
|
808
908
|
this.statusColor = "#007bff";
|
|
@@ -932,7 +1032,7 @@ const JaakStamps$1 = /*@__PURE__*/ proxyCustomElement(class JaakStamps extends H
|
|
|
932
1032
|
this.cleanup();
|
|
933
1033
|
}
|
|
934
1034
|
render() {
|
|
935
|
-
return (h("div", { key: '
|
|
1035
|
+
return (h("div", { key: 'd6cd4225500c44e5c7fb4f2b3dc453a055467066', class: "detector-container" }, h("div", { key: '6bd49b0bcd686648aeffb8fb95203dc0779f1d8a', class: "video-container" }, h("video", { key: 'd2666ce9d1f5b84703ac86fd4eb901f4298ed7d5', ref: el => this.videoRef = el, autoplay: true, muted: true, playsinline: true, class: this.shouldMirrorVideo ? 'mirror' : '', style: { display: this.isVideoActive ? 'block' : 'none' } }), h("canvas", { key: 'e997f063450d81d2a15398f0761c9d06c28a85c9', ref: el => this.canvasRef = el, class: this.shouldMirrorVideo ? 'mirror' : '' }), this.isMaskReady && (h("div", { key: '4ccb8bf05091a7173255181eae1a8699fe512b56', class: "overlay-mask" }, h("div", { key: 'b35defa8c207b05e41d64c8e1eefc905d31fad55', class: "card-outline" }, h("div", { key: '6ed8dad63d6d79c1bb4a64f0b28467f5b29d778a', class: "side side-top" }), h("div", { key: '403d4a5ba681a58ad1870a4339e19b4f037a8795', class: "side side-right" }), h("div", { key: '3cb3276bb184a4b76419b4cb0b4fcb151a4df631', class: "side side-bottom" }), h("div", { key: 'ed7c9bec0e708ab282ba8b24a08d21b8126af27e', class: "side side-left" }), h("div", { key: '157be211355bf9260dc7a73d03831dbb1a2945e3', class: "corner corner-tl" }), h("div", { key: 'b19af5f319333ff05f981063af939d2c4cfc9b5f', class: "corner corner-tr" }), h("div", { key: '6fcd3e2c8842261dcd32c36e6df5b2f3dd0c8fc8', class: "corner corner-bl" }), h("div", { key: '7caab5eaee62f3f9039075b3748083c89c8127e0', class: "corner corner-br" }), !this.showFlipAnimation && !this.showSuccessAnimation && (h("div", { key: 'e3dd42ddb75b22aeef438d8651955f3dc039f00c', class: "guide-text" }, this.statusMessage))), this.captureStep === 'back' && !this.showFlipAnimation && !this.showSuccessAnimation && (h("button", { key: '54b8651817cd52bad2f34ac1413a4b1e21166cee', class: "skip-button", onClick: () => this.skipBackCapture(), type: "button" }, "Saltar reverso")))), this.isCapturing && (h("div", { key: '853707a4fa71eeacbee7985e619fca80d6522cbd', class: "capture-animation" })), this.showFlipAnimation && (h("div", { key: '246ed3f5dc57ee57345105cdebe5f950d5ff4c90', class: "flip-animation" }, h("div", { key: 'f03c6c87c8f5e98a32176cca061d369a521da2e8', class: "id-card-icon" }), h("div", { key: 'e357785b076a9e41ea4f9b3d9c14e847bacc9604', class: "flip-text" }, "\u00A1Voltea tu identificaci\u00F3n!"))), this.showSuccessAnimation && (h("div", { key: 'df3adaaecd3d547938638c58ccc0e89f8325fc23', class: "success-animation" }, h("div", { key: 'a023985b8afd6ed72f9e1c2ee63e2c7ba9fb960b', class: "check-icon" }), h("div", { key: '739ff7f329f2131061a6860529c07c8819800aab', class: "success-text" }, "\u00A1Proceso completado!"))), this.isLoading && (h("div", { key: '9b02df640528a19cb15e5dbabf9ecb43afbceffa', class: "loading-overlay" }, h("div", { key: '3652c8e355ea7fe623c478229bf548bdf30e399a', class: "loading-spinner" }), h("div", { key: '334f4469b5672f6af78b8679c15ed8c59ecefa85', class: "loading-text" }, this.statusMessage))), h("div", { key: 'a0b7c9b92771cff96e97bd67da2fd3090b080f8a', class: "watermark" }, h("img", { key: 'b5c8f0de1d8138d4a0c80526fd33b2daefa86b16', src: "https://storage.googleapis.com/jaak-static/commons/powered-by-jaak.png", alt: "Powered by Jaak" })))));
|
|
936
1036
|
}
|
|
937
1037
|
static get style() { return myComponentCss; }
|
|
938
1038
|
}, [1, "jaak-stamps", {
|