id-scanner-lib 1.3.2 → 1.5.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 (115) hide show
  1. package/README.md +55 -460
  2. package/dist/id-scanner-lib.esm.js +4641 -0
  3. package/dist/id-scanner-lib.esm.js.map +1 -0
  4. package/dist/id-scanner-lib.js +14755 -0
  5. package/dist/id-scanner-lib.js.map +1 -0
  6. package/dist/types/core/base-module.d.ts +44 -0
  7. package/dist/types/core/camera-manager.d.ts +258 -0
  8. package/dist/types/core/config.d.ts +88 -0
  9. package/dist/types/core/errors.d.ts +111 -0
  10. package/dist/types/core/event-emitter.d.ts +55 -0
  11. package/dist/types/core/logger.d.ts +277 -0
  12. package/dist/types/core/module-manager.d.ts +78 -0
  13. package/dist/types/core/plugin-manager.d.ts +158 -0
  14. package/dist/types/core/resource-manager.d.ts +246 -0
  15. package/dist/types/core/result.d.ts +83 -0
  16. package/dist/types/core/scanner-factory.d.ts +93 -0
  17. package/dist/types/index.bundle.d.ts +1303 -0
  18. package/dist/types/index.d.ts +86 -0
  19. package/dist/types/interfaces/external-types.d.ts +174 -0
  20. package/dist/types/interfaces/face-detection.d.ts +293 -0
  21. package/dist/types/interfaces/scanner-module.d.ts +280 -0
  22. package/dist/types/modules/face/face-detector.d.ts +170 -0
  23. package/dist/types/modules/face/index.d.ts +56 -0
  24. package/dist/types/modules/face/liveness-detector.d.ts +177 -0
  25. package/dist/types/modules/face/types.d.ts +136 -0
  26. package/dist/types/modules/id-card/anti-fake-detector.d.ts +170 -0
  27. package/dist/types/modules/id-card/id-card-detector.d.ts +131 -0
  28. package/dist/types/modules/id-card/index.d.ts +89 -0
  29. package/dist/types/modules/id-card/ocr-processor.d.ts +110 -0
  30. package/dist/types/modules/id-card/ocr-worker.d.ts +31 -0
  31. package/dist/types/modules/id-card/types.d.ts +181 -0
  32. package/dist/types/modules/qrcode/index.d.ts +51 -0
  33. package/dist/types/modules/qrcode/qr-code-scanner.d.ts +64 -0
  34. package/dist/types/modules/qrcode/types.d.ts +67 -0
  35. package/dist/types/utils/camera.d.ts +81 -0
  36. package/dist/types/utils/image-processing.d.ts +176 -0
  37. package/dist/types/utils/index.d.ts +175 -0
  38. package/dist/types/utils/performance.d.ts +81 -0
  39. package/dist/types/utils/resource-manager.d.ts +53 -0
  40. package/dist/types/utils/types.d.ts +166 -0
  41. package/dist/types/utils/worker.d.ts +52 -0
  42. package/dist/types/version.d.ts +7 -0
  43. package/package.json +76 -77
  44. package/src/core/base-module.ts +78 -0
  45. package/src/core/camera-manager.ts +798 -0
  46. package/src/core/config.ts +268 -0
  47. package/src/core/errors.ts +174 -0
  48. package/src/core/event-emitter.ts +110 -0
  49. package/src/core/logger.ts +549 -0
  50. package/src/core/module-manager.ts +165 -0
  51. package/src/core/plugin-manager.ts +429 -0
  52. package/src/core/resource-manager.ts +762 -0
  53. package/src/core/result.ts +163 -0
  54. package/src/core/scanner-factory.ts +237 -0
  55. package/src/index.ts +113 -936
  56. package/src/interfaces/external-types.ts +200 -0
  57. package/src/interfaces/face-detection.ts +309 -0
  58. package/src/interfaces/scanner-module.ts +384 -0
  59. package/src/modules/face/face-detector.ts +931 -0
  60. package/src/modules/face/index.ts +208 -0
  61. package/src/modules/face/liveness-detector.ts +908 -0
  62. package/src/modules/face/types.ts +133 -0
  63. package/src/modules/id-card/anti-fake-detector.ts +732 -0
  64. package/src/modules/id-card/id-card-detector.ts +474 -0
  65. package/src/modules/id-card/index.ts +425 -0
  66. package/src/modules/id-card/ocr-processor.ts +538 -0
  67. package/src/modules/id-card/ocr-worker.ts +259 -0
  68. package/src/modules/id-card/types.ts +178 -0
  69. package/src/modules/qrcode/index.ts +175 -0
  70. package/src/modules/qrcode/qr-code-scanner.ts +230 -0
  71. package/src/modules/qrcode/types.ts +65 -0
  72. package/src/types/browser-image-compression.d.ts +19 -0
  73. package/src/types/tesseract.d.ts +280 -0
  74. package/src/utils/image-processing.ts +432 -49
  75. package/src/utils/index.ts +426 -0
  76. package/src/utils/performance.ts +168 -131
  77. package/src/utils/resource-manager.ts +65 -146
  78. package/src/utils/types.ts +90 -2
  79. package/src/utils/worker.ts +123 -84
  80. package/src/version.ts +11 -0
  81. package/tools/scaffold.js +543 -0
  82. package/dist/id-scanner-core.esm.js +0 -11076
  83. package/dist/id-scanner-core.esm.js.map +0 -1
  84. package/dist/id-scanner-core.js +0 -11088
  85. package/dist/id-scanner-core.js.map +0 -1
  86. package/dist/id-scanner-core.min.js +0 -1
  87. package/dist/id-scanner-core.min.js.map +0 -1
  88. package/dist/id-scanner-ocr.esm.js +0 -1802
  89. package/dist/id-scanner-ocr.esm.js.map +0 -1
  90. package/dist/id-scanner-ocr.js +0 -1811
  91. package/dist/id-scanner-ocr.js.map +0 -1
  92. package/dist/id-scanner-ocr.min.js +0 -1
  93. package/dist/id-scanner-ocr.min.js.map +0 -1
  94. package/dist/id-scanner-qr.esm.js +0 -1023
  95. package/dist/id-scanner-qr.esm.js.map +0 -1
  96. package/dist/id-scanner-qr.js +0 -1032
  97. package/dist/id-scanner-qr.js.map +0 -1
  98. package/dist/id-scanner-qr.min.js +0 -1
  99. package/dist/id-scanner-qr.min.js.map +0 -1
  100. package/dist/id-scanner.js +0 -3740
  101. package/dist/id-scanner.js.map +0 -1
  102. package/dist/id-scanner.min.js +0 -1
  103. package/dist/id-scanner.min.js.map +0 -1
  104. package/src/core.ts +0 -138
  105. package/src/demo/demo.ts +0 -204
  106. package/src/id-recognition/anti-fake-detector.ts +0 -317
  107. package/src/id-recognition/data-extractor.ts +0 -262
  108. package/src/id-recognition/id-detector.ts +0 -363
  109. package/src/id-recognition/ocr-processor.ts +0 -334
  110. package/src/id-recognition/ocr-worker.ts +0 -156
  111. package/src/index-umd.ts +0 -477
  112. package/src/ocr-module.ts +0 -187
  113. package/src/qr-module.ts +0 -179
  114. package/src/scanner/barcode-scanner.ts +0 -251
  115. package/src/scanner/qr-scanner.ts +0 -167
@@ -1,262 +0,0 @@
1
- /**
2
- * @file 数据提取工具类
3
- * @description 提供身份证信息的验证和格式化功能
4
- * @module DataExtractor
5
- */
6
-
7
- import { IDCardInfo } from '../utils/types';
8
-
9
- /**
10
- * 数据提取工具类
11
- *
12
- * 提供身份证信息的验证、提取和增强功能,可以从身份证号码中提取出生日期、性别等信息,
13
- * 并对OCR识别结果进行补充和验证
14
- *
15
- * @example
16
- * ```typescript
17
- * // 验证身份证号码
18
- * const isValid = DataExtractor.validateIDNumber('110101199001011234');
19
- *
20
- * // 从身份证号码提取出生日期
21
- * const birthDate = DataExtractor.extractBirthDateFromID('110101199001011234');
22
- * // 结果: '1990-01-01'
23
- *
24
- * // 增强OCR识别结果
25
- * const enhancedInfo = DataExtractor.enhanceIDCardInfo({
26
- * name: '张三',
27
- * idNumber: '110101199001011234'
28
- * });
29
- * // 结果会自动补充性别和出生日期
30
- * ```
31
- */
32
- export class DataExtractor {
33
- /**
34
- * 验证身份证号码格式
35
- *
36
- * 检查身份证号码的长度、格式和出生日期部分是否有效
37
- *
38
- * @param {string} idNumber - 要验证的身份证号码
39
- * @returns {boolean} 是否是有效的身份证号码
40
- */
41
- static validateIDNumber(idNumber: string): boolean {
42
- // 简单校验长度
43
- if (!idNumber || idNumber.length !== 18) {
44
- return false;
45
- }
46
-
47
- // 校验格式 (前17位必须是数字,最后一位可以是数字或X)
48
- const pattern = /^\d{17}[\dX]$/;
49
- if (!pattern.test(idNumber)) {
50
- return false;
51
- }
52
-
53
- // 校验出生日期
54
- const year = parseInt(idNumber.substr(6, 4));
55
- const month = parseInt(idNumber.substr(10, 2));
56
- const day = parseInt(idNumber.substr(12, 2));
57
-
58
- const date = new Date(year, month - 1, day);
59
- if (
60
- date.getFullYear() !== year ||
61
- date.getMonth() + 1 !== month ||
62
- date.getDate() !== day
63
- ) {
64
- return false;
65
- }
66
-
67
- // 简单的校验规则,实际项目中可以加入更完善的验证
68
- return true;
69
- }
70
-
71
- /**
72
- * 从身份证号码提取出生日期
73
- *
74
- * @param {string} idNumber - 身份证号码
75
- * @returns {string|null} 格式化的出生日期(YYYY-MM-DD),如果身份证号码无效则返回null
76
- */
77
- static extractBirthDateFromID(idNumber: string): string | null {
78
- if (!this.validateIDNumber(idNumber)) {
79
- return null;
80
- }
81
-
82
- const year = idNumber.substr(6, 4);
83
- const month = idNumber.substr(10, 2);
84
- const day = idNumber.substr(12, 2);
85
-
86
- return `${year}-${month}-${day}`;
87
- }
88
-
89
- /**
90
- * 从身份证号码提取性别
91
- *
92
- * 根据身份证号码第17位判断性别,奇数为男,偶数为女
93
- *
94
- * @param {string} idNumber - 身份证号码
95
- * @returns {string|null} '男'或'女',如果身份证号码无效则返回null
96
- */
97
- static extractGenderFromID(idNumber: string): string | null {
98
- if (!this.validateIDNumber(idNumber)) {
99
- return null;
100
- }
101
-
102
- // 第17位,奇数为男,偶数为女
103
- const genderCode = parseInt(idNumber.charAt(16));
104
- return genderCode % 2 === 1 ? '男' : '女';
105
- }
106
-
107
- /**
108
- * 从身份证号码提取地区编码
109
- *
110
- * @param {string} idNumber - 身份证号码
111
- * @returns {string|null} 地区编码(前6位),如果身份证号码无效则返回null
112
- */
113
- static extractRegionFromID(idNumber: string): string | null {
114
- if (!this.validateIDNumber(idNumber)) {
115
- return null;
116
- }
117
-
118
- return idNumber.substr(0, 6);
119
- }
120
-
121
- /**
122
- * 合并并优化身份证信息
123
- *
124
- * 使用多个来源的数据进行交叉验证和补充,如果OCR识别结果缺少某些信息,
125
- * 但有身份证号码,则可以从号码中提取出生日期和性别等信息
126
- *
127
- * @param {IDCardInfo} ocrInfo - OCR识别到的身份证信息
128
- * @param {string} [idNumber] - 可选的外部提供的身份证号码,优先级高于OCR识别结果
129
- * @returns {IDCardInfo} 增强后的身份证信息
130
- */
131
- static enhanceIDCardInfo(ocrInfo: IDCardInfo, idNumber?: string): IDCardInfo {
132
- const result = { ...ocrInfo };
133
-
134
- // 如果OCR识别出身份证号,但没有识别出生日期或性别,则从身份证号码提取
135
- if (result.idNumber && this.validateIDNumber(result.idNumber)) {
136
- // 从身份证号提取出生日期
137
- if (!result.birthDate) {
138
- result.birthDate = this.extractBirthDateFromID(result.idNumber) || undefined;
139
- }
140
-
141
- // 从身份证号提取性别
142
- if (!result.gender) {
143
- result.gender = this.extractGenderFromID(result.idNumber) || undefined;
144
- }
145
- }
146
-
147
- // 如果外部传入了身份证号,则优先使用它并提取信息
148
- if (idNumber && this.validateIDNumber(idNumber)) {
149
- result.idNumber = idNumber;
150
-
151
- // 使用身份证号码再次验证或补充信息
152
- const birthDate = this.extractBirthDateFromID(idNumber);
153
- if (birthDate) {
154
- result.birthDate = birthDate;
155
- }
156
-
157
- const gender = this.extractGenderFromID(idNumber);
158
- if (gender) {
159
- result.gender = gender;
160
- }
161
- }
162
-
163
- return result;
164
- }
165
-
166
- /**
167
- * 提取并验证身份证信息
168
- *
169
- * @param idCardInfo 初步提取的身份证信息
170
- * @returns 验证和增强后的身份证信息
171
- */
172
- extractAndValidate(idCardInfo: IDCardInfo): IDCardInfo {
173
- const enhancedInfo = {...idCardInfo};
174
-
175
- // 验证和规范化身份证号
176
- if (enhancedInfo.idNumber) {
177
- enhancedInfo.idNumber = this.normalizeIDNumber(enhancedInfo.idNumber);
178
-
179
- // 如果身份证号有效,推断出生日期
180
- if (this.validateIDNumber(enhancedInfo.idNumber)) {
181
- if (!enhancedInfo.birthDate) {
182
- enhancedInfo.birthDate = this.extractBirthDateFromID(enhancedInfo.idNumber);
183
- }
184
-
185
- // 推断性别
186
- if (!enhancedInfo.gender) {
187
- enhancedInfo.gender = this.extractGenderFromID(enhancedInfo.idNumber);
188
- }
189
- }
190
- }
191
-
192
- // 规范化日期格式
193
- if (enhancedInfo.birthDate) {
194
- enhancedInfo.birthDate = this.normalizeDate(enhancedInfo.birthDate);
195
- }
196
-
197
- // 规范化地址信息
198
- if (enhancedInfo.address) {
199
- enhancedInfo.address = this.normalizeAddress(enhancedInfo.address);
200
- }
201
-
202
- return enhancedInfo;
203
- }
204
-
205
- /**
206
- * 规范化身份证号码
207
- */
208
- private normalizeIDNumber(idNumber: string): string {
209
- // 移除空格和特殊字符
210
- return idNumber.replace(/[\s\-]/g, '').toUpperCase();
211
- }
212
-
213
- /**
214
- * 验证身份证号码是否有效
215
- */
216
- private validateIDNumber(idNumber: string): boolean {
217
- // 简单验证身份证号码长度和格式
218
- const idRegex = /(^\d{15}$)|(^\d{17}([0-9]|X)$)/;
219
- return idRegex.test(idNumber);
220
- }
221
-
222
- /**
223
- * 从身份证号中提取出生日期
224
- */
225
- private extractBirthDateFromID(idNumber: string): string {
226
- if (idNumber.length === 18) {
227
- return `${idNumber.substring(6, 10)}-${idNumber.substring(10, 12)}-${idNumber.substring(12, 14)}`;
228
- } else if (idNumber.length === 15) {
229
- return `19${idNumber.substring(6, 8)}-${idNumber.substring(8, 10)}-${idNumber.substring(10, 12)}`;
230
- }
231
- return '';
232
- }
233
-
234
- /**
235
- * 从身份证号中提取性别信息
236
- */
237
- private extractGenderFromID(idNumber: string): string {
238
- let sexCode: number;
239
- if (idNumber.length === 18) {
240
- sexCode = parseInt(idNumber.charAt(16));
241
- } else {
242
- sexCode = parseInt(idNumber.charAt(14));
243
- }
244
- return sexCode % 2 === 1 ? '男' : '女';
245
- }
246
-
247
- /**
248
- * 规范化日期格式
249
- */
250
- private normalizeDate(date: string): string {
251
- // 简单的日期格式化逻辑
252
- return date.replace(/(\d{4})(\d{2})(\d{2})/, '$1-$2-$3');
253
- }
254
-
255
- /**
256
- * 规范化地址信息
257
- */
258
- private normalizeAddress(address: string): string {
259
- // 地址格式化逻辑
260
- return address.trim();
261
- }
262
- }
@@ -1,363 +0,0 @@
1
- /**
2
- * @file 身份证检测模块
3
- * @description 提供自动检测和定位图像中的身份证功能
4
- * @module IDCardDetector
5
- */
6
-
7
- import { Camera } from "../utils/camera"
8
- import { ImageProcessor } from "../utils/image-processing"
9
- import { DetectionResult } from "../utils/types"
10
- import {
11
- throttle,
12
- LRUCache,
13
- calculateImageFingerprint,
14
- } from "../utils/performance"
15
- import { Disposable } from "../utils/resource-manager"
16
-
17
- /**
18
- * IDCardDetector配置选项
19
- */
20
- export interface IDCardDetectorOptions {
21
- onDetection?: (result: DetectionResult) => void
22
- onError?: (error: Error) => void
23
- detectionInterval?: number
24
- maxImageDimension?: number
25
- enableCache?: boolean
26
- cacheSize?: number
27
- logger?: (message: any) => void
28
- }
29
-
30
- /**
31
- * 身份证检测器类
32
- *
33
- * 通过图像处理和计算机视觉技术,实时检测视频流中的身份证,并提取身份证区域
34
- * 注意:当前实现是简化版,实际项目中建议使用OpenCV.js进行更精确的检测
35
- *
36
- * @example
37
- * ```typescript
38
- * // 创建身份证检测器
39
- * const detector = new IDCardDetector((result) => {
40
- * if (result.success && result.croppedImage) {
41
- * console.log('检测到身份证!');
42
- * // 对裁剪出的身份证图像进行处理
43
- * processIDCardImage(result.croppedImage);
44
- * }
45
- * });
46
- *
47
- * // 启动检测
48
- * const videoElement = document.getElementById('video') as HTMLVideoElement;
49
- * await detector.start(videoElement);
50
- *
51
- * // 停止检测
52
- * detector.stop();
53
- * ```
54
- */
55
- export class IDCardDetector implements Disposable {
56
- private camera: Camera
57
- private detecting = false
58
- private detectTimer: number | null = null
59
- private onDetected?: (result: DetectionResult) => void
60
- private onError?: (error: Error) => void
61
- private detectionInterval: number
62
- private maxImageDimension: number
63
- private resultCache: LRUCache<string, DetectionResult>
64
- private throttledDetect: ReturnType<typeof throttle>
65
- private frameCount: number = 0
66
- private lastDetectionTime: number = 0
67
- private options: IDCardDetectorOptions
68
-
69
- /**
70
- * 创建身份证检测器实例
71
- *
72
- * @param options 身份证检测器配置选项,或者检测回调函数
73
- */
74
- constructor(
75
- options?: IDCardDetectorOptions | ((result: DetectionResult) => void)
76
- ) {
77
- this.camera = new Camera()
78
-
79
- if (typeof options === "function") {
80
- // 兼容旧的构造函数方式
81
- this.onDetected = options
82
- this.options = {
83
- detectionInterval: 200,
84
- maxImageDimension: 800,
85
- enableCache: true,
86
- cacheSize: 20,
87
- logger: console.log,
88
- }
89
- } else if (options) {
90
- // 使用新的选项对象方式
91
- this.options = {
92
- detectionInterval: 200,
93
- maxImageDimension: 800,
94
- enableCache: true,
95
- cacheSize: 20,
96
- logger: console.log,
97
- ...options,
98
- }
99
- this.onDetected = options.onDetection
100
- this.onError = options.onError
101
- } else {
102
- this.options = {
103
- detectionInterval: 200,
104
- maxImageDimension: 800,
105
- enableCache: true,
106
- cacheSize: 20,
107
- logger: console.log,
108
- }
109
- }
110
-
111
- this.detectionInterval = this.options.detectionInterval!
112
- this.maxImageDimension = this.options.maxImageDimension!
113
-
114
- // 初始化结果缓存
115
- this.resultCache = new LRUCache<string, DetectionResult>(
116
- this.options.cacheSize
117
- )
118
-
119
- // 创建节流版本的检测函数
120
- this.throttledDetect = throttle(
121
- this.performDetection.bind(this),
122
- this.detectionInterval
123
- )
124
- }
125
-
126
- /**
127
- * 启动身份证检测
128
- *
129
- * 初始化相机并开始连续检测视频帧中的身份证
130
- *
131
- * @param {HTMLVideoElement} videoElement - 用于显示相机画面的video元素
132
- * @returns {Promise<void>} 启动完成的Promise
133
- */
134
- async start(videoElement: HTMLVideoElement): Promise<void> {
135
- await this.camera.initialize(videoElement)
136
- this.detecting = true
137
- this.frameCount = 0
138
- this.lastDetectionTime = 0
139
- this.detect()
140
- }
141
-
142
- /**
143
- * 停止身份证检测
144
- */
145
- stop(): void {
146
- this.detecting = false
147
- if (this.detectTimer !== null) {
148
- cancelAnimationFrame(this.detectTimer)
149
- this.detectTimer = null
150
- }
151
- }
152
-
153
- /**
154
- * 持续检测视频帧
155
- *
156
- * @private
157
- */
158
- private detect(): void {
159
- if (!this.detecting) return
160
-
161
- this.detectTimer = requestAnimationFrame(() => {
162
- try {
163
- this.frameCount++
164
- const now = performance.now()
165
-
166
- // 帧率控制 - 只有满足时间间隔的帧才进行检测
167
- // 这样可以显著减少CPU使用率,同时保持良好的用户体验
168
- if (
169
- this.frameCount % 3 === 0 ||
170
- now - this.lastDetectionTime >= this.detectionInterval
171
- ) {
172
- this.throttledDetect()
173
- this.lastDetectionTime = now
174
- }
175
-
176
- // 继续下一帧检测
177
- this.detect()
178
- } catch (error) {
179
- if (this.onError) {
180
- this.onError(error as Error)
181
- } else {
182
- console.error("身份证检测错误:", error)
183
- }
184
-
185
- // 出错后延迟重试
186
- setTimeout(() => {
187
- if (this.detecting) {
188
- this.detect()
189
- }
190
- }, 1000)
191
- }
192
- })
193
- }
194
-
195
- /**
196
- * 执行单帧检测
197
- *
198
- * @private
199
- */
200
- private async performDetection(): Promise<void> {
201
- if (!this.detecting || !this.camera) return
202
-
203
- // 获取当前视频帧
204
- const frame = this.camera.captureFrame()
205
- if (!frame) return
206
-
207
- // 检查缓存
208
- if (this.options.enableCache) {
209
- const fingerprint = calculateImageFingerprint(frame, 16) // 使用更大的尺寸提高特征区分度
210
- const cachedResult = this.resultCache.get(fingerprint)
211
-
212
- if (cachedResult) {
213
- this.options.logger?.("使用缓存的检测结果")
214
-
215
- // 使用缓存结果,但更新图像数据以确保最新
216
- const updatedResult = {
217
- ...cachedResult,
218
- imageData: frame,
219
- }
220
-
221
- if (this.onDetected) {
222
- this.onDetected(updatedResult)
223
- }
224
- return
225
- }
226
- }
227
-
228
- // 降低分辨率以提高性能
229
- const downsampledFrame = ImageProcessor.resizeImage(
230
- frame,
231
- this.maxImageDimension,
232
- this.maxImageDimension
233
- )
234
-
235
- try {
236
- // 检测身份证
237
- const result = await this.detectIDCard(downsampledFrame)
238
-
239
- // 如果检测成功,将原始图像添加到结果中
240
- if (result.success) {
241
- result.imageData = frame
242
-
243
- // 缓存结果
244
- if (this.options.enableCache) {
245
- const fingerprint = calculateImageFingerprint(frame, 16)
246
- this.resultCache.set(fingerprint, result)
247
- }
248
- }
249
-
250
- // 处理检测结果
251
- if (this.onDetected) {
252
- this.onDetected(result)
253
- }
254
- } catch (error) {
255
- if (this.onError) {
256
- this.onError(error as Error)
257
- } else {
258
- console.error("身份证检测错误:", error)
259
- }
260
- }
261
- }
262
-
263
- /**
264
- * 检测图像中的身份证
265
- *
266
- * @private
267
- * @param {ImageData} imageData - 要分析的图像数据
268
- * @returns {Promise<DetectionResult>} 检测结果
269
- */
270
- private async detectIDCard(imageData: ImageData): Promise<DetectionResult> {
271
- // 1. 图像预处理
272
- const grayscale = ImageProcessor.toGrayscale(imageData)
273
-
274
- // 2. 检测矩形和边缘(简化版实现)
275
- // 注意:实际应用中应使用OpenCV.js或其他计算机视觉库进行更精确的检测
276
- // 此处仅作为概念性实现,使用基本矩形检测逻辑
277
-
278
- // 模拟检测过程,随机判断是否找到身份证
279
- // 在实际应用中,此处应当实现实际的计算机视觉算法
280
- const detectionResult: DetectionResult = {
281
- success: Math.random() > 0.3, // 70%的概率成功检测到
282
- message: "身份证检测完成",
283
- }
284
-
285
- if (detectionResult.success) {
286
- // 模拟一个身份证矩形区域
287
- const width = imageData.width
288
- const height = imageData.height
289
-
290
- // 大致的身份证区域(按比例)
291
- const rectWidth = Math.round(width * 0.7)
292
- const rectHeight = Math.round(rectWidth * 0.618) // 身份证是黄金比例
293
- const rectX = Math.round((width - rectWidth) / 2)
294
- const rectY = Math.round((height - rectHeight) / 2)
295
-
296
- // 添加四个角点
297
- detectionResult.corners = [
298
- { x: rectX, y: rectY },
299
- { x: rectX + rectWidth, y: rectY },
300
- { x: rectX + rectWidth, y: rectY + rectHeight },
301
- { x: rectX, y: rectY + rectHeight },
302
- ]
303
-
304
- // 添加边界框
305
- detectionResult.boundingBox = {
306
- x: rectX,
307
- y: rectY,
308
- width: rectWidth,
309
- height: rectHeight,
310
- }
311
-
312
- // 裁剪身份证图像
313
- const canvas = document.createElement("canvas")
314
- canvas.width = rectWidth
315
- canvas.height = rectHeight
316
- const ctx = canvas.getContext("2d")
317
-
318
- if (ctx) {
319
- const tempCanvas = ImageProcessor.imageDataToCanvas(imageData)
320
- ctx.drawImage(
321
- tempCanvas,
322
- rectX,
323
- rectY,
324
- rectWidth,
325
- rectHeight,
326
- 0,
327
- 0,
328
- rectWidth,
329
- rectHeight
330
- )
331
-
332
- detectionResult.croppedImage = ctx.getImageData(
333
- 0,
334
- 0,
335
- rectWidth,
336
- rectHeight
337
- )
338
- }
339
-
340
- // 设置置信度
341
- detectionResult.confidence = 0.7 + Math.random() * 0.3
342
- }
343
-
344
- return detectionResult
345
- }
346
-
347
- /**
348
- * 清除检测结果缓存
349
- */
350
- clearCache(): void {
351
- this.resultCache.clear()
352
- this.options.logger?.("检测结果缓存已清除")
353
- }
354
-
355
- /**
356
- * 释放资源
357
- */
358
- dispose(): void {
359
- this.stop()
360
- this.camera.release()
361
- this.resultCache.clear()
362
- }
363
- }