id-scanner-lib 1.6.7 → 2.0.0

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.
Files changed (48) hide show
  1. package/dist/id-scanner-lib.esm.js +994 -1139
  2. package/dist/id-scanner-lib.esm.js.map +1 -1
  3. package/dist/id-scanner-lib.js +995 -1144
  4. package/dist/id-scanner-lib.js.map +1 -1
  5. package/package.json +1 -1
  6. package/src/compat/index.ts +7 -0
  7. package/src/compat/v1-adapter.ts +84 -0
  8. package/src/core/camera-manager.ts +43 -76
  9. package/src/core/camera-stream-manager.ts +318 -0
  10. package/src/core/config.ts +113 -267
  11. package/src/core/errors.ts +68 -117
  12. package/src/core/logger.ts +158 -81
  13. package/src/core/resource-manager.ts +150 -0
  14. package/src/core/scanner.ts +109 -0
  15. package/src/core/utils/browser.ts +7 -0
  16. package/src/core/utils/canvas-pool.ts +171 -0
  17. package/src/core/utils/canvas.ts +7 -0
  18. package/src/core/utils/image.ts +7 -0
  19. package/src/core/utils/index.ts +9 -0
  20. package/src/core/utils/resource-manager.ts +155 -0
  21. package/src/core/utils/validate.ts +7 -0
  22. package/src/core/utils/worker.ts +130 -0
  23. package/src/modules/face/comparator/comparator.ts +45 -0
  24. package/src/modules/face/comparator/index.ts +1 -0
  25. package/src/modules/face/detector/detector.ts +83 -0
  26. package/src/modules/face/detector/index.ts +2 -0
  27. package/src/modules/face/detector/types.ts +80 -0
  28. package/src/modules/face/face-comparator.ts +150 -0
  29. package/src/modules/face/face-detector-options.ts +104 -0
  30. package/src/modules/face/face-detector.ts +121 -376
  31. package/src/modules/face/face-detector.ts.bak +991 -0
  32. package/src/modules/face/face-model-loader.ts +222 -0
  33. package/src/modules/face/face-result-converter.ts +225 -0
  34. package/src/modules/face/face-tracker.ts +207 -0
  35. package/src/modules/face/liveness/index.ts +7 -0
  36. package/src/modules/face/liveness-detector.ts +2 -2
  37. package/src/modules/face/tracker/index.ts +7 -0
  38. package/src/modules/id-card/anti-fake/index.ts +7 -0
  39. package/src/modules/id-card/detector/index.ts +7 -0
  40. package/src/modules/id-card/id-card-text-parser.ts +151 -0
  41. package/src/modules/id-card/ocr-processor.ts +20 -257
  42. package/src/modules/id-card/ocr-worker.ts +2 -183
  43. package/src/modules/id-card/parser/index.ts +7 -0
  44. package/src/modules/qr/scanner/index.ts +7 -0
  45. package/src/utils/canvas-pool.ts +273 -0
  46. package/src/utils/edge-detector.ts +232 -0
  47. package/src/utils/image-processing.ts +92 -419
  48. package/src/utils/index.ts +1 -0
@@ -0,0 +1,150 @@
1
+ /**
2
+ * @file 人脸比对器
3
+ * @description 提供人脸特征向量比对功能
4
+ * @module modules/face/face-comparator
5
+ */
6
+
7
+ import { FaceDetectionResult } from '../../interfaces/face-detection';
8
+ import { Result } from '../../core/result';
9
+ import { FaceComparisonError } from '../../core/errors';
10
+ import { Logger } from '../../core/logger';
11
+
12
+ /**
13
+ * 人脸比对结果
14
+ */
15
+ export interface ComparisonResult {
16
+ /** 相似度 (0-1) */
17
+ similarity: number;
18
+ /** 是否匹配(基于阈值) */
19
+ isMatch: boolean;
20
+ /** 使用的阈值 */
21
+ threshold: number;
22
+ }
23
+
24
+ /**
25
+ * 人脸比对器配置
26
+ */
27
+ export interface FaceComparatorConfig {
28
+ /** 人脸匹配阈值 (0-1) */
29
+ matchThreshold?: number;
30
+ }
31
+
32
+ /**
33
+ * 人脸比对器
34
+ *
35
+ * 负责计算两个人脸特征向量的相似度
36
+ */
37
+ export class FaceComparator {
38
+ /** 日志记录器 */
39
+ private logger: Logger;
40
+
41
+ /** 匹配阈值 */
42
+ private matchThreshold: number;
43
+
44
+ /**
45
+ * 构造函数
46
+ * @param config 比对器配置
47
+ */
48
+ constructor(config: FaceComparatorConfig = {}) {
49
+ this.logger = Logger.getInstance();
50
+ this.matchThreshold = config.matchThreshold ?? 0.6;
51
+ }
52
+
53
+ /**
54
+ * 计算两个特征向量的余弦相似度
55
+ *
56
+ * @param v1 特征向量1
57
+ * @param v2 特征向量2
58
+ * @returns 相似度 (0-1)
59
+ */
60
+ computeSimilarity(v1: number[], v2: number[]): number {
61
+ if (v1.length !== v2.length) {
62
+ throw new Error('特征向量维度不匹配');
63
+ }
64
+
65
+ let dotProduct = 0;
66
+ let norm1 = 0;
67
+ let norm2 = 0;
68
+
69
+ for (let i = 0; i < v1.length; i++) {
70
+ dotProduct += v1[i] * v2[i];
71
+ norm1 += v1[i] * v1[i];
72
+ norm2 += v2[i] * v2[i];
73
+ }
74
+
75
+ // 确保长度非零
76
+ if (norm1 === 0 || norm2 === 0) {
77
+ return 0;
78
+ }
79
+
80
+ return dotProduct / (Math.sqrt(norm1) * Math.sqrt(norm2));
81
+ }
82
+
83
+ /**
84
+ * 比对两个人脸
85
+ *
86
+ * @param source 源人脸(特征向量或检测结果)
87
+ * @param target 目标人脸(特征向量或检测结果)
88
+ * @returns 比对结果
89
+ */
90
+ compare(
91
+ source: number[] | FaceDetectionResult,
92
+ target: number[] | FaceDetectionResult
93
+ ): Result<ComparisonResult> {
94
+ try {
95
+ // 提取特征向量
96
+ const sourceEmbedding = this.extractEmbedding(source);
97
+ const targetEmbedding = this.extractEmbedding(target);
98
+
99
+ if (!sourceEmbedding || !targetEmbedding) {
100
+ return Result.failure(new FaceComparisonError('无法获取特征向量'));
101
+ }
102
+
103
+ // 计算相似度
104
+ const similarity = this.computeSimilarity(sourceEmbedding, targetEmbedding);
105
+ const isMatch = similarity >= this.matchThreshold;
106
+
107
+ return Result.success({
108
+ similarity,
109
+ isMatch,
110
+ threshold: this.matchThreshold
111
+ });
112
+ } catch (error) {
113
+ const errorMessage = error instanceof Error ? error.message : String(error);
114
+ this.logger.error('FaceComparator', `人脸比对失败: ${errorMessage}`, error as Error);
115
+ return Result.failure(new FaceComparisonError(`人脸比对失败: ${errorMessage}`));
116
+ }
117
+ }
118
+
119
+ /**
120
+ * 从输入中提取特征向量
121
+ */
122
+ private extractEmbedding(input: number[] | FaceDetectionResult): number[] | null {
123
+ if (Array.isArray(input)) {
124
+ return input;
125
+ }
126
+
127
+ if (input.embedding?.vector) {
128
+ return input.embedding.vector;
129
+ }
130
+
131
+ return null;
132
+ }
133
+
134
+ /**
135
+ * 设置匹配阈值
136
+ */
137
+ setThreshold(threshold: number): void {
138
+ if (threshold < 0 || threshold > 1) {
139
+ throw new Error('阈值必须在 0-1 范围内');
140
+ }
141
+ this.matchThreshold = threshold;
142
+ }
143
+
144
+ /**
145
+ * 获取当前阈值
146
+ */
147
+ getThreshold(): number {
148
+ return this.matchThreshold;
149
+ }
150
+ }
@@ -0,0 +1,104 @@
1
+ /**
2
+ * @file 人脸检测选项工厂
3
+ * @description 创建 face-api 检测选项和处理选项
4
+ * @module modules/face/face-detector-options
5
+ */
6
+
7
+ import * as faceapi from '@vladmandic/face-api';
8
+ import { FaceDetectionOptions } from '../../interfaces/face-detection';
9
+ import { FaceModelType, FaceDetectorConfig } from './face-detector';
10
+
11
+ /**
12
+ * 人脸检测选项工厂
13
+ *
14
+ * 负责创建 face-api 兼容的检测选项和处理选项
15
+ */
16
+ export class FaceDetectorOptionsFactory {
17
+ /**
18
+ * 创建 face-api 检测选项
19
+ * @param detectionModel 检测模型类型
20
+ * @param minConfidence 最小置信度
21
+ * @returns face-api 检测选项
22
+ */
23
+ static createFaceAPIOptions(
24
+ detectionModel: FaceModelType,
25
+ minConfidence: number
26
+ ): faceapi.SsdMobilenetv1Options | faceapi.TinyFaceDetectorOptions | faceapi.MtcnnOptions {
27
+ switch (detectionModel) {
28
+ case FaceModelType.SSD_MOBILENET:
29
+ return new faceapi.SsdMobilenetv1Options({ minConfidence });
30
+ case FaceModelType.TINY_FACE:
31
+ return new faceapi.TinyFaceDetectorOptions({ scoreThreshold: minConfidence });
32
+ case FaceModelType.MTCNN:
33
+ return new faceapi.MtcnnOptions({ minConfidence });
34
+ default:
35
+ return new faceapi.SsdMobilenetv1Options({ minConfidence });
36
+ }
37
+ }
38
+
39
+ /**
40
+ * 合并检测选项和配置
41
+ * @param config 人脸检测器配置
42
+ * @param options 用户提供的选项
43
+ * @returns 合并后的检测选项
44
+ */
45
+ static mergeOptions(
46
+ config: FaceDetectorConfig,
47
+ options: FaceDetectionOptions = {}
48
+ ): FaceDetectionOptions {
49
+ return {
50
+ minConfidence: config.minConfidence,
51
+ maxFaces: config.maxFaces,
52
+ withLandmarks: config.detectLandmarks,
53
+ withAttributes: config.detectExpressions || config.detectAgeGender,
54
+ withEmbedding: config.extractEmbeddings,
55
+ enableTracking: config.enableTracking,
56
+ ...options
57
+ };
58
+ }
59
+
60
+ /**
61
+ * 执行人脸检测
62
+ * @param input 输入图像/视频/画布
63
+ * @param faceapiOptions face-api 检测选项
64
+ * @param detectOptions 检测选项
65
+ * @param landmarksModel 关键点模型类型
66
+ * @returns face-api 检测结果
67
+ */
68
+ static async detect(
69
+ input: HTMLImageElement | HTMLCanvasElement | HTMLVideoElement,
70
+ faceapiOptions: faceapi.SsdMobilenetv1Options | faceapi.TinyFaceDetectorOptions | faceapi.MtcnnOptions,
71
+ detectOptions: FaceDetectionOptions,
72
+ landmarksModel: 'tiny' | '68_points'
73
+ ): Promise<any> {
74
+ const withLandmarks = detectOptions.withLandmarks;
75
+ const withAttributes = detectOptions.withAttributes;
76
+ const withEmbedding = detectOptions.withEmbedding;
77
+
78
+ // 根据选项组合选择检测方法链
79
+ if (withLandmarks && withAttributes && withEmbedding) {
80
+ // 全功能检测
81
+ return await faceapi
82
+ .detectAllFaces(input, faceapiOptions)
83
+ .withFaceLandmarks(landmarksModel === 'tiny')
84
+ .withFaceExpressions()
85
+ .withAgeAndGender()
86
+ .withFaceDescriptors();
87
+ } else if (withLandmarks && withAttributes) {
88
+ // 检测带关键点和属性
89
+ return await faceapi
90
+ .detectAllFaces(input, faceapiOptions)
91
+ .withFaceLandmarks(landmarksModel === 'tiny')
92
+ .withFaceExpressions()
93
+ .withAgeAndGender();
94
+ } else if (withLandmarks) {
95
+ // 检测带关键点
96
+ return await faceapi
97
+ .detectAllFaces(input, faceapiOptions)
98
+ .withFaceLandmarks(landmarksModel === 'tiny');
99
+ } else {
100
+ // 仅检测
101
+ return await faceapi.detectAllFaces(input, faceapiOptions);
102
+ }
103
+ }
104
+ }