@sssxyd/face-liveness-detector 0.2.21 → 0.2.23
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/index.esm.js +118 -135
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +118 -134
- package/dist/index.js.map +1 -1
- package/dist/types/index.d.ts +1 -1
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/library-loader.d.ts +10 -3
- package/dist/types/library-loader.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -311,6 +311,7 @@
|
|
|
311
311
|
}
|
|
312
312
|
let webglAvailableCache = null;
|
|
313
313
|
let opencvInitPromise = null;
|
|
314
|
+
let opencvInitialized = false; // 标记是否已初始化完成
|
|
314
315
|
function _isWebGLAvailable() {
|
|
315
316
|
if (webglAvailableCache !== null) {
|
|
316
317
|
return webglAvailableCache;
|
|
@@ -354,8 +355,8 @@
|
|
|
354
355
|
// 复用 loadOpenCV 的初始化逻辑
|
|
355
356
|
opencvInitPromise = _initializeOpenCV(timeout);
|
|
356
357
|
try {
|
|
357
|
-
await opencvInitPromise;
|
|
358
|
-
console.log('[OpenCV] Preload completed successfully');
|
|
358
|
+
const initTime = await opencvInitPromise;
|
|
359
|
+
console.log('[OpenCV] Preload completed successfully, cost:', initTime.toFixed(0), 'ms');
|
|
359
360
|
}
|
|
360
361
|
catch (error) {
|
|
361
362
|
console.error('[OpenCV] Preload failed:', error);
|
|
@@ -372,16 +373,16 @@
|
|
|
372
373
|
*/
|
|
373
374
|
async function _initializeOpenCV(timeout) {
|
|
374
375
|
const initStartTime = performance.now();
|
|
375
|
-
console.log('
|
|
376
|
+
console.log('Waiting for OpenCV WASM initialization...');
|
|
376
377
|
// 快速路径:检查是否已经初始化
|
|
377
378
|
if (cvModule.Mat) {
|
|
378
379
|
const initTime = performance.now() - initStartTime;
|
|
379
|
-
console.log(`
|
|
380
|
+
console.log(`OpenCV.js already initialized, took ${initTime.toFixed(2)}ms`);
|
|
380
381
|
return cvModule;
|
|
381
382
|
}
|
|
382
383
|
if (typeof globalThis !== 'undefined' && globalThis.cv && globalThis.cv.Mat) {
|
|
383
384
|
const initTime = performance.now() - initStartTime;
|
|
384
|
-
console.log(`
|
|
385
|
+
console.log(`OpenCV.js already initialized (from global), took ${initTime.toFixed(2)}ms`);
|
|
385
386
|
cvModule = globalThis.cv;
|
|
386
387
|
return cvModule;
|
|
387
388
|
}
|
|
@@ -389,10 +390,10 @@
|
|
|
389
390
|
if (typeof globalThis !== 'undefined' && !globalThis.cv) {
|
|
390
391
|
if (cvModule && Object.isExtensible(cvModule)) {
|
|
391
392
|
globalThis.cv = cvModule;
|
|
392
|
-
console.log('
|
|
393
|
+
console.log('cvModule assigned to globalThis.cv');
|
|
393
394
|
}
|
|
394
395
|
else {
|
|
395
|
-
console.log('
|
|
396
|
+
console.log('cvModule is not extensible or globalThis already has cv');
|
|
396
397
|
}
|
|
397
398
|
}
|
|
398
399
|
return new Promise((resolve, reject) => {
|
|
@@ -401,7 +402,7 @@
|
|
|
401
402
|
// 防止多次调用 resolve/reject
|
|
402
403
|
let finished = false;
|
|
403
404
|
const timeoutId = setTimeout(() => {
|
|
404
|
-
console.error('
|
|
405
|
+
console.error('OpenCV.js initialization timeout after ' + timeout + 'ms');
|
|
405
406
|
finished = true;
|
|
406
407
|
if (pollInterval) {
|
|
407
408
|
clearInterval(pollInterval);
|
|
@@ -410,70 +411,65 @@
|
|
|
410
411
|
}, timeout);
|
|
411
412
|
const resolveOnce = (source) => {
|
|
412
413
|
if (finished) {
|
|
413
|
-
console.log('[
|
|
414
|
+
console.log('[resolveOnce] Already finished, ignoring call from:', source);
|
|
414
415
|
return;
|
|
415
416
|
}
|
|
416
417
|
finished = true;
|
|
417
|
-
console.log('[
|
|
418
|
+
console.log('[resolveOnce] Marking as finished');
|
|
418
419
|
// 立即停止所有定时器和轮询
|
|
419
420
|
clearTimeout(timeoutId);
|
|
420
421
|
if (pollInterval !== null) {
|
|
421
422
|
clearInterval(pollInterval);
|
|
422
423
|
pollInterval = null;
|
|
423
|
-
console.log('[
|
|
424
|
-
}
|
|
425
|
-
// 确保返回有效的 cv 对象
|
|
426
|
-
let validCv = cvModule;
|
|
427
|
-
if (typeof globalThis !== 'undefined' && globalThis.cv && globalThis.cv.Mat) {
|
|
428
|
-
validCv = globalThis.cv;
|
|
424
|
+
console.log('[resolveOnce] Poll interval cleared');
|
|
429
425
|
}
|
|
430
426
|
const initTime = performance.now() - initStartTime;
|
|
431
|
-
console.log(`
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
resolve(
|
|
437
|
-
console.log('[
|
|
427
|
+
console.log(`OpenCV.js initialized (${source}), took ${initTime.toFixed(2)}ms`);
|
|
428
|
+
// 标记初始化完成
|
|
429
|
+
opencvInitialized = true;
|
|
430
|
+
// 返回简单的标记,实际的 cv 对象已经在 globalThis.cv 上了
|
|
431
|
+
// 通过 getCvSync() 获取
|
|
432
|
+
resolve(initTime);
|
|
433
|
+
console.log('[resolveOnce] Promise resolved');
|
|
438
434
|
};
|
|
439
435
|
// 尝试设置回调(只有在 cvModule 可扩展时才尝试)
|
|
440
436
|
const canSetCallback = cvModule && Object.isExtensible(cvModule);
|
|
441
437
|
if (canSetCallback) {
|
|
442
438
|
try {
|
|
443
439
|
const originalOnRuntimeInitialized = cvModule.onRuntimeInitialized(cvModule).onRuntimeInitialized = () => {
|
|
444
|
-
console.log('[
|
|
440
|
+
console.log('[onRuntimeInitialized] callback triggered');
|
|
445
441
|
// 调用原始回调(如果存在)
|
|
446
442
|
if (originalOnRuntimeInitialized && typeof originalOnRuntimeInitialized === 'function') {
|
|
447
443
|
try {
|
|
448
444
|
originalOnRuntimeInitialized();
|
|
449
445
|
}
|
|
450
446
|
catch (e) {
|
|
451
|
-
console.warn('[
|
|
447
|
+
console.warn('[onRuntimeInitialized] callback failed:', e);
|
|
452
448
|
}
|
|
453
449
|
}
|
|
454
450
|
resolveOnce('callback');
|
|
455
451
|
};
|
|
456
|
-
console.log('[
|
|
452
|
+
console.log('[onRuntimeInitialized] callback set successfully');
|
|
457
453
|
}
|
|
458
454
|
catch (e) {
|
|
459
|
-
console.warn('[
|
|
455
|
+
console.warn('[onRuntimeInitialized] Failed to set callback, will use polling:', e);
|
|
460
456
|
}
|
|
461
457
|
}
|
|
462
458
|
else {
|
|
463
|
-
console.log('[
|
|
459
|
+
console.log('[polling] cvModule is not extensible, using polling mode');
|
|
464
460
|
}
|
|
465
461
|
// 启动轮询作为备用方案或主要方案
|
|
466
462
|
pollInterval = setInterval(() => {
|
|
467
|
-
console.log('[
|
|
463
|
+
console.log('[polling] Checking for Mat class...');
|
|
468
464
|
// 优先检查 cvModule 中是否有 Mat
|
|
469
465
|
if (cvModule.Mat) {
|
|
470
|
-
console.log('[
|
|
466
|
+
console.log('[polling] Found Mat in cvModule');
|
|
471
467
|
resolveOnce('cvModule polling');
|
|
472
468
|
return;
|
|
473
469
|
}
|
|
474
470
|
// 其次检查 globalThis.cv 中是否有 Mat
|
|
475
471
|
if (typeof globalThis !== 'undefined' && globalThis.cv && globalThis.cv.Mat) {
|
|
476
|
-
console.log('[
|
|
472
|
+
console.log('[polling] Found Mat in globalThis.cv');
|
|
477
473
|
cvModule = globalThis.cv;
|
|
478
474
|
resolveOnce('globalThis.cv polling');
|
|
479
475
|
return;
|
|
@@ -487,81 +483,40 @@
|
|
|
487
483
|
* @returns Promise that resolves with cv module
|
|
488
484
|
*/
|
|
489
485
|
async function loadOpenCV(timeout = 30000) {
|
|
490
|
-
let cv;
|
|
491
|
-
console.log('[FaceDetectionEngine] Loading OpenCV.js...');
|
|
492
486
|
try {
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
cv = await opencvInitPromise;
|
|
500
|
-
console.log('[FaceDetectionEngine] [loadOpenCV] AFTER AWAIT - OpenCV promise resolved, got cv module:', { hasMat: !!(cv && cv.Mat), type: typeof cv });
|
|
501
|
-
}
|
|
502
|
-
catch (awaitError) {
|
|
503
|
-
console.error('[FaceDetectionEngine] [loadOpenCV] AWAIT ERROR:', awaitError);
|
|
504
|
-
throw awaitError;
|
|
487
|
+
// 快速检查是否已经初始化完成
|
|
488
|
+
if (opencvInitialized) {
|
|
489
|
+
console.log('[loadOpenCV] Already initialized, returning immediately');
|
|
490
|
+
const cv = getCvSync();
|
|
491
|
+
if (cv) {
|
|
492
|
+
return { cv };
|
|
505
493
|
}
|
|
506
|
-
// 完成后清除 Promise 标记
|
|
507
|
-
console.log('[FaceDetectionEngine] [loadOpenCV] Clearing opencvInitPromise');
|
|
508
|
-
opencvInitPromise = null;
|
|
509
|
-
console.log('[FaceDetectionEngine] [loadOpenCV] opencvInitPromise cleared');
|
|
510
|
-
}
|
|
511
|
-
else if (cvModule.Mat) {
|
|
512
|
-
// 检查 cvModule 是否已经初始化
|
|
513
|
-
console.log('[FaceDetectionEngine] [loadOpenCV] OpenCV.js already initialized in cvModule');
|
|
514
|
-
cv = cvModule;
|
|
515
|
-
}
|
|
516
|
-
else if (typeof globalThis !== 'undefined' && globalThis.cv && globalThis.cv.Mat) {
|
|
517
|
-
// 检查全局 cv 是否已经初始化
|
|
518
|
-
console.log('[FaceDetectionEngine] [loadOpenCV] OpenCV.js already initialized in globalThis.cv');
|
|
519
|
-
cvModule = globalThis.cv;
|
|
520
|
-
cv = cvModule;
|
|
521
494
|
}
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
495
|
+
// 等待初始化
|
|
496
|
+
console.log('[loadOpenCV] Waiting for initialization...');
|
|
497
|
+
if (!opencvInitPromise) {
|
|
498
|
+
console.log('[loadOpenCV] Starting new initialization');
|
|
525
499
|
opencvInitPromise = _initializeOpenCV(timeout);
|
|
526
|
-
try {
|
|
527
|
-
console.log('[FaceDetectionEngine] [loadOpenCV] Awaiting _initializeOpenCV...');
|
|
528
|
-
cv = await opencvInitPromise;
|
|
529
|
-
console.log('[FaceDetectionEngine] [loadOpenCV] OpenCV initialization completed, got cv module:', { hasMat: !!(cv && cv.Mat), type: typeof cv });
|
|
530
|
-
// 完成后清除 Promise 标记
|
|
531
|
-
opencvInitPromise = null;
|
|
532
|
-
}
|
|
533
|
-
catch (error) {
|
|
534
|
-
// 失败后也要清除 Promise
|
|
535
|
-
console.error('[FaceDetectionEngine] [loadOpenCV] _initializeOpenCV threw error:', error);
|
|
536
|
-
opencvInitPromise = null;
|
|
537
|
-
throw error;
|
|
538
|
-
}
|
|
539
500
|
}
|
|
540
|
-
console.log('[
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
console.error('[FaceDetectionEngine] [loadOpenCV] OpenCV module is invalid:', {
|
|
550
|
-
hasMat: cv && cv.Mat,
|
|
551
|
-
type: typeof cv,
|
|
552
|
-
keys: cv ? Object.keys(cv).slice(0, 10) : 'N/A',
|
|
553
|
-
globalCvAvailable: !!(typeof globalThis !== 'undefined' && globalThis.cv)
|
|
554
|
-
});
|
|
555
|
-
throw new Error('OpenCV.js loaded but module is invalid (no Mat class found)');
|
|
556
|
-
}
|
|
501
|
+
console.log('[loadOpenCV] Awaiting opencvInitPromise');
|
|
502
|
+
const initTime = await opencvInitPromise;
|
|
503
|
+
// 清除 Promise 缓存
|
|
504
|
+
opencvInitPromise = null;
|
|
505
|
+
// 获取初始化后的 cv 对象
|
|
506
|
+
const cv = getCvSync();
|
|
507
|
+
if (!cv) {
|
|
508
|
+
console.error('[loadOpenCV] getCvSync returned null');
|
|
509
|
+
throw new Error('OpenCV module is invalid');
|
|
557
510
|
}
|
|
558
|
-
console.log('[
|
|
559
|
-
|
|
560
|
-
|
|
511
|
+
console.log('[loadOpenCV] OpenCV.js load successfully', {
|
|
512
|
+
initTime: `${initTime.toFixed(2)}ms`,
|
|
513
|
+
version: getOpenCVVersion()
|
|
514
|
+
});
|
|
515
|
+
return cv;
|
|
561
516
|
}
|
|
562
517
|
catch (error) {
|
|
563
|
-
console.error('[
|
|
564
|
-
|
|
518
|
+
console.error('[loadOpenCV] OpenCV.js load failed', error);
|
|
519
|
+
opencvInitPromise = null;
|
|
565
520
|
throw error;
|
|
566
521
|
}
|
|
567
522
|
}
|
|
@@ -580,6 +535,35 @@
|
|
|
580
535
|
}
|
|
581
536
|
return null;
|
|
582
537
|
}
|
|
538
|
+
/**
|
|
539
|
+
* Extract OpenCV version from getBuildInformation
|
|
540
|
+
* @returns version string like "4.12.0"
|
|
541
|
+
*/
|
|
542
|
+
function getOpenCVVersion() {
|
|
543
|
+
try {
|
|
544
|
+
const cv = getCvSync();
|
|
545
|
+
if (!cv || !cv.getBuildInformation) {
|
|
546
|
+
return 'unknown';
|
|
547
|
+
}
|
|
548
|
+
const buildInfo = cv.getBuildInformation();
|
|
549
|
+
// 查找 "Version control:" 或 "OpenCV" 开头的行
|
|
550
|
+
// 格式: "Version control: 4.12.0"
|
|
551
|
+
const versionMatch = buildInfo.match(/Version\s+control:\s+(\d+\.\d+\.\d+)/i);
|
|
552
|
+
if (versionMatch && versionMatch[1]) {
|
|
553
|
+
return versionMatch[1];
|
|
554
|
+
}
|
|
555
|
+
// 备用方案:查找 "OpenCV X.X.X" 格式
|
|
556
|
+
const opencvMatch = buildInfo.match(/OpenCV\s+(\d+\.\d+\.\d+)/i);
|
|
557
|
+
if (opencvMatch && opencvMatch[1]) {
|
|
558
|
+
return opencvMatch[1];
|
|
559
|
+
}
|
|
560
|
+
return 'unknown';
|
|
561
|
+
}
|
|
562
|
+
catch (error) {
|
|
563
|
+
console.error('[getOpenCVVersion] Failed to get version:', error);
|
|
564
|
+
return 'unknown';
|
|
565
|
+
}
|
|
566
|
+
}
|
|
583
567
|
/**
|
|
584
568
|
* Load Human.js
|
|
585
569
|
* @param modelPath - Path to model files (optional)
|
|
@@ -609,24 +593,17 @@
|
|
|
609
593
|
if (wasmPath) {
|
|
610
594
|
config.wasmPath = wasmPath;
|
|
611
595
|
}
|
|
612
|
-
console.log('[
|
|
596
|
+
console.log('[loadHuman] Config:', {
|
|
613
597
|
backend: config.backend,
|
|
614
598
|
modelBasePath: config.modelBasePath || '(using default)',
|
|
615
599
|
wasmPath: config.wasmPath || '(using default)'
|
|
616
600
|
});
|
|
617
601
|
const initStartTime = performance.now();
|
|
618
|
-
console.log('[FaceDetectionEngine] Creating Human instance...');
|
|
619
602
|
const human = new Human(config);
|
|
620
|
-
const instanceCreateTime = performance.now() - initStartTime;
|
|
621
|
-
console.log(`[FaceDetectionEngine] Human instance created, took ${instanceCreateTime.toFixed(2)}ms`);
|
|
622
|
-
console.log('[FaceDetectionEngine] Loading Human.js models...');
|
|
623
|
-
const modelLoadStartTime = performance.now();
|
|
624
603
|
try {
|
|
625
604
|
await human.load();
|
|
626
|
-
const loadTime = performance.now() - modelLoadStartTime;
|
|
627
605
|
const totalTime = performance.now() - initStartTime;
|
|
628
|
-
console.log('[
|
|
629
|
-
modelLoadTime: `${loadTime.toFixed(2)}ms`,
|
|
606
|
+
console.log('[loadHuman] Loaded successfully', {
|
|
630
607
|
totalInitTime: `${totalTime.toFixed(2)}ms`,
|
|
631
608
|
version: human.version
|
|
632
609
|
});
|
|
@@ -634,7 +611,32 @@
|
|
|
634
611
|
}
|
|
635
612
|
catch (error) {
|
|
636
613
|
const errorMsg = error instanceof Error ? error.message : 'Unknown error';
|
|
637
|
-
console.error('[
|
|
614
|
+
console.error('[loadHuman] Load failed:', errorMsg);
|
|
615
|
+
throw error;
|
|
616
|
+
}
|
|
617
|
+
}
|
|
618
|
+
async function loadLibraries(modelPath, wasmPath, timeout) {
|
|
619
|
+
console.log('[loadLibraries] Starting parallel load of OpenCV and Human...');
|
|
620
|
+
const startTime = performance.now();
|
|
621
|
+
if (timeout == undefined) {
|
|
622
|
+
timeout = 30000;
|
|
623
|
+
}
|
|
624
|
+
try {
|
|
625
|
+
// 并行加载 OpenCV 和 Human
|
|
626
|
+
const [cv, human] = await Promise.all([
|
|
627
|
+
loadOpenCV(timeout),
|
|
628
|
+
loadHuman(modelPath, wasmPath)
|
|
629
|
+
]);
|
|
630
|
+
const totalTime = performance.now() - startTime;
|
|
631
|
+
console.log('[loadLibraries] Both libraries loaded successfully in', totalTime.toFixed(2), 'ms');
|
|
632
|
+
return {
|
|
633
|
+
cv,
|
|
634
|
+
human
|
|
635
|
+
};
|
|
636
|
+
}
|
|
637
|
+
catch (error) {
|
|
638
|
+
const errorMsg = error instanceof Error ? error.message : 'Unknown error';
|
|
639
|
+
console.error('[loadLibraries] Failed to load libraries:', errorMsg);
|
|
638
640
|
throw error;
|
|
639
641
|
}
|
|
640
642
|
}
|
|
@@ -1616,12 +1618,13 @@
|
|
|
1616
1618
|
this.isInitializing = true;
|
|
1617
1619
|
this.emitDebug('initialization', 'Starting to load detection libraries...');
|
|
1618
1620
|
try {
|
|
1619
|
-
// Load
|
|
1620
|
-
this.emitDebug('initialization', 'Loading
|
|
1621
|
-
const
|
|
1621
|
+
// Load Libraries
|
|
1622
|
+
this.emitDebug('initialization', 'Loading Libraries...');
|
|
1623
|
+
const startLoadTime = performance.now();
|
|
1624
|
+
const { cv, human } = await loadLibraries(this.config.human_model_path, this.config.tensorflow_wasm_path, 30000);
|
|
1622
1625
|
if (!cv || !cv.Mat) {
|
|
1623
1626
|
console.log('[FaceDetectionEngine] Failed to load OpenCV.js: module is null or invalid');
|
|
1624
|
-
this.emit('detector-
|
|
1627
|
+
this.emit('detector-loaded', {
|
|
1625
1628
|
success: false,
|
|
1626
1629
|
error: 'Failed to load OpenCV.js: module is null or invalid'
|
|
1627
1630
|
});
|
|
@@ -1631,22 +1634,9 @@
|
|
|
1631
1634
|
});
|
|
1632
1635
|
return;
|
|
1633
1636
|
}
|
|
1634
|
-
this.emitDebug('initialization', 'OpenCV loaded successfully', {
|
|
1635
|
-
version: cv?.getBuildInformation?.() || 'unknown'
|
|
1636
|
-
});
|
|
1637
|
-
console.log('[FaceDetectionEngine] OpenCV loaded successfully', {
|
|
1638
|
-
version: cv?.getBuildInformation?.() || 'unknown'
|
|
1639
|
-
});
|
|
1640
|
-
// Load Human.js
|
|
1641
|
-
console.log('[FaceDetectionEngine] Loading Human.js models...');
|
|
1642
|
-
this.emitDebug('initialization', 'Loading Human.js...');
|
|
1643
|
-
const humanStartTime = performance.now();
|
|
1644
|
-
this.human = await loadHuman(this.config.human_model_path, this.config.tensorflow_wasm_path);
|
|
1645
|
-
const humanLoadTime = performance.now() - humanStartTime;
|
|
1646
1637
|
if (!this.human) {
|
|
1647
1638
|
const errorMsg = 'Failed to load Human.js: instance is null';
|
|
1648
1639
|
console.log('[FaceDetectionEngine] ' + errorMsg);
|
|
1649
|
-
this.emitDebug('initialization', errorMsg, { loadTime: humanLoadTime }, 'error');
|
|
1650
1640
|
this.emit('detector-loaded', {
|
|
1651
1641
|
success: false,
|
|
1652
1642
|
error: errorMsg
|
|
@@ -1657,21 +1647,14 @@
|
|
|
1657
1647
|
});
|
|
1658
1648
|
return;
|
|
1659
1649
|
}
|
|
1660
|
-
this.emitDebug('initialization', 'Human.js loaded successfully', {
|
|
1661
|
-
loadTime: `${humanLoadTime.toFixed(2)}ms`,
|
|
1662
|
-
version: this.human.version
|
|
1663
|
-
});
|
|
1664
|
-
console.log('[FaceDetectionEngine] Human.js loaded successfully', {
|
|
1665
|
-
loadTime: `${humanLoadTime.toFixed(2)}ms`,
|
|
1666
|
-
version: this.human.version
|
|
1667
|
-
});
|
|
1668
1650
|
this.isReady = true;
|
|
1669
1651
|
const loadedData = {
|
|
1670
1652
|
success: true,
|
|
1671
|
-
opencv_version:
|
|
1653
|
+
opencv_version: getOpenCVVersion(),
|
|
1672
1654
|
human_version: this.human.version
|
|
1673
1655
|
};
|
|
1674
1656
|
console.log('[FaceDetectionEngine] Engine initialized and ready', {
|
|
1657
|
+
initCostTime: (performance.now() - startLoadTime).toFixed(2),
|
|
1675
1658
|
opencv_version: loadedData.opencv_version,
|
|
1676
1659
|
human_version: loadedData.human_version
|
|
1677
1660
|
});
|
|
@@ -2444,6 +2427,7 @@
|
|
|
2444
2427
|
exports.FaceDetectionEngine = FaceDetectionEngine;
|
|
2445
2428
|
exports.default = FaceDetectionEngine;
|
|
2446
2429
|
exports.getCvSync = getCvSync;
|
|
2430
|
+
exports.getOpenCVVersion = getOpenCVVersion;
|
|
2447
2431
|
exports.loadOpenCV = loadOpenCV;
|
|
2448
2432
|
exports.preloadOpenCV = preloadOpenCV;
|
|
2449
2433
|
|