id-scanner-lib 1.3.0 → 1.3.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/README.md +223 -25
- package/dist/id-scanner-ocr.esm.js +17 -14
- package/dist/id-scanner-ocr.js +17 -14
- package/dist/id-scanner.js +385 -25
- package/dist/id-scanner.min.js +1 -1
- package/package.json +5 -3
- package/src/id-recognition/anti-fake-detector.ts +317 -0
- package/src/id-recognition/ocr-worker.ts +82 -72
- package/src/index.ts +189 -15
package/README.md
CHANGED
|
@@ -3,6 +3,8 @@
|
|
|
3
3
|
纯前端实现的TypeScript身份证与二维码识别库,无需后端支持,所有处理均在浏览器端完成。结合高性能图像处理与OCR技术,提供完整的识别解决方案。
|
|
4
4
|
|
|
5
5
|
[](https://www.npmjs.com/package/id-scanner-lib)
|
|
6
|
+
[](https://github.com/agions/id-scanner-lib)
|
|
7
|
+
[](https://bundlephobia.com/package/id-scanner-lib)
|
|
6
8
|
[](https://github.com/agions/id-scanner-lib/blob/master/LICENSE)
|
|
7
9
|
|
|
8
10
|
## 技术特性
|
|
@@ -11,6 +13,7 @@
|
|
|
11
13
|
- **二维码扫描**:基于jsQR实现高精度二维码识别与解码
|
|
12
14
|
- **条形码识别**:支持EAN-13、CODE-128等常见一维码格式
|
|
13
15
|
- **身份证OCR**:基于Tesseract.js的优化OCR引擎,精确提取身份证信息
|
|
16
|
+
- **身份证防伪检测**:检测多种防伪特征,有效识别伪造证件
|
|
14
17
|
- **图像处理优化**:内置多种图像预处理算法,提高识别率
|
|
15
18
|
- **支持多种数据源**:摄像头实时视频流、图片文件、URL、Base64等
|
|
16
19
|
- **高效缓存机制**:内置LRU缓存,避免重复识别,提升性能
|
|
@@ -25,9 +28,10 @@
|
|
|
25
28
|
| 二维码识别 | 50-150ms | >98% | 取决于图像质量 |
|
|
26
29
|
| 条形码识别 | 70-200ms | >95% | 支持多种格式 |
|
|
27
30
|
| 身份证OCR | 300-800ms | >90% | 优化后的识别速度 |
|
|
31
|
+
| 防伪检测 | 100-200ms | >85% | 多特征综合分析 |
|
|
28
32
|
| 图像处理 | 20-100ms | - | 视处理操作而定 |
|
|
29
33
|
|
|
30
|
-
## 最新版本 (v1.3.
|
|
34
|
+
## 最新版本 (v1.3.2)
|
|
31
35
|
|
|
32
36
|
- **图像处理引擎升级**:
|
|
33
37
|
- 增强的图像锐化算法,提高低光照环境下的识别率
|
|
@@ -41,30 +45,129 @@
|
|
|
41
45
|
- 批量图像处理API
|
|
42
46
|
- 内置图像压缩功能
|
|
43
47
|
- 一体化演示组件
|
|
48
|
+
- **身份证防伪检测**:识别多种防伪特征,检测伪造证件
|
|
49
|
+
- 支持荧光油墨、微缩文字、光变图案等5种防伪特征检测
|
|
50
|
+
- 基于多特征综合评分,提供置信度评估
|
|
51
|
+
- 缓存机制提高重复检测性能
|
|
44
52
|
- **架构改进**:
|
|
45
53
|
- 资源自动释放机制
|
|
46
54
|
- 更精细的模块划分
|
|
47
55
|
- 增强的错误处理
|
|
48
56
|
|
|
57
|
+
## 版本路线图
|
|
58
|
+
|
|
59
|
+
### v1.4.0:人脸比对与活体检测
|
|
60
|
+
|
|
61
|
+
- **人脸比对模块**:
|
|
62
|
+
- 身份证照片与现场采集照片的比对功能
|
|
63
|
+
- 基于深度学习的人脸特征提取与分析
|
|
64
|
+
- 提供相似度评分与置信度
|
|
65
|
+
- **活体检测**:
|
|
66
|
+
- 眨眼、张嘴等动作检测防止照片欺骗
|
|
67
|
+
- 基于光线反射的3D检测技术
|
|
68
|
+
- 多帧分析提高检测准确率
|
|
69
|
+
- **安全增强**:
|
|
70
|
+
- 本地处理所有数据,保护隐私
|
|
71
|
+
- 结果加密存储选项
|
|
72
|
+
- 合规性验证工具
|
|
73
|
+
|
|
74
|
+
### v1.5.0:多证件类型支持
|
|
75
|
+
|
|
76
|
+
- **护照识别**:
|
|
77
|
+
- MRZ码(机读区)解析
|
|
78
|
+
- 多国护照模板适配
|
|
79
|
+
- 芯片信息读取(ePassport支持)
|
|
80
|
+
- **驾驶证识别**:
|
|
81
|
+
- 驾驶证OCR识别
|
|
82
|
+
- 驾驶资格与限制条件解析
|
|
83
|
+
- 国际驾照支持
|
|
84
|
+
- **营业执照识别**:
|
|
85
|
+
- 企业信息提取
|
|
86
|
+
- 统一社会信用代码验证
|
|
87
|
+
- 经营范围解析
|
|
88
|
+
- **银行卡识别**:
|
|
89
|
+
- 卡号、有效期识别
|
|
90
|
+
- 银行标识解析
|
|
91
|
+
- BIN码验证
|
|
92
|
+
|
|
93
|
+
### v1.6.0:UI/UX改进与组件库升级
|
|
94
|
+
|
|
95
|
+
- **现代化UI框架**:
|
|
96
|
+
- 基于Web Components的组件系统
|
|
97
|
+
- 自适应扫描界面
|
|
98
|
+
- 多主题支持(含暗色模式)
|
|
99
|
+
- **交互体验优化**:
|
|
100
|
+
- 实时扫描引导框
|
|
101
|
+
- 智能对焦与取景提示
|
|
102
|
+
- 证件边缘自动检测与校正
|
|
103
|
+
- **可访问性支持**:
|
|
104
|
+
- 屏幕阅读器兼容
|
|
105
|
+
- 键盘导航
|
|
106
|
+
- 多语言本地化
|
|
107
|
+
- **动效与反馈**:
|
|
108
|
+
- 平滑过渡动画
|
|
109
|
+
- 触觉反馈(移动设备)
|
|
110
|
+
- 声音反馈与语音提示
|
|
111
|
+
|
|
112
|
+
### v1.7.0:性能与架构优化
|
|
113
|
+
|
|
114
|
+
- **WebAssembly实现**:
|
|
115
|
+
- 核心图像处理算法WASM化
|
|
116
|
+
- 性能提升3-5倍
|
|
117
|
+
- 更低的CPU占用
|
|
118
|
+
- **离线支持**:
|
|
119
|
+
- 完整离线运行能力
|
|
120
|
+
- 基于IndexedDB的本地缓存
|
|
121
|
+
- Service Worker支持
|
|
122
|
+
- **微前端集成**:
|
|
123
|
+
- React/Vue/Angular专用组件
|
|
124
|
+
- 更简单的集成API
|
|
125
|
+
- TypeScript类型增强
|
|
126
|
+
- **渐进式加载**:
|
|
127
|
+
- 核心功能快速加载
|
|
128
|
+
- 按需延迟加载附加模块
|
|
129
|
+
- 预测性加载提高响应速度
|
|
130
|
+
|
|
131
|
+
### v2.0.0:企业级解决方案
|
|
132
|
+
|
|
133
|
+
- **云端协同验证**:
|
|
134
|
+
- 可选云端验证API
|
|
135
|
+
- 本地与云端结果比对
|
|
136
|
+
- 多级安全验证
|
|
137
|
+
- **高级分析功能**:
|
|
138
|
+
- 证件使用统计与分析
|
|
139
|
+
- 风险评估模型
|
|
140
|
+
- 异常检测系统
|
|
141
|
+
- **行业解决方案包**:
|
|
142
|
+
- 金融行业KYC流程集成
|
|
143
|
+
- 酒店/零售快速登记系统
|
|
144
|
+
- 政务/安防高安全性验证
|
|
145
|
+
- **企业级管理功能**:
|
|
146
|
+
- 多租户支持
|
|
147
|
+
- 批量处理队列
|
|
148
|
+
- 完整审计日志
|
|
149
|
+
|
|
49
150
|
## 系统架构
|
|
50
151
|
|
|
51
152
|
```
|
|
52
|
-
|
|
153
|
+
┌────────────────────────────────────────────────────────────┐
|
|
53
154
|
│ IDScanner 主模块 │
|
|
54
155
|
├─────────────┬─────────────────┬────────────────────────────┤
|
|
55
156
|
│ QRScanner │ BarcodeScanner │ IDCardDetector │
|
|
56
157
|
├─────────────┴─────────────────┴────────────────────────────┤
|
|
57
|
-
│ Camera (视频流捕获与处理)
|
|
58
|
-
|
|
158
|
+
│ Camera (视频流捕获与处理) │
|
|
159
|
+
└────────────────────────────────────────────────────────────┘
|
|
59
160
|
▲
|
|
60
161
|
│
|
|
61
162
|
▼
|
|
62
|
-
|
|
163
|
+
┌────────────────────────────────────────────────────────────┐
|
|
63
164
|
│ 核心处理引擎 │
|
|
64
165
|
├─────────────────┬─────────────────┬────────────────────────┤
|
|
65
166
|
│ OCRProcessor │ DataExtractor │ ImageProcessor │
|
|
66
|
-
│ (文字识别) │ (数据提取验证)
|
|
67
|
-
|
|
167
|
+
│ (文字识别) │ (数据提取验证) │ (图像预处理) │
|
|
168
|
+
├─────────────────┴─────────────────┴────────────────────────┤
|
|
169
|
+
│ AntiFakeDetector (身份证防伪检测) │
|
|
170
|
+
└────────────────────────────────────────────────────────────┘
|
|
68
171
|
```
|
|
69
172
|
|
|
70
173
|
## 安装与使用
|
|
@@ -79,22 +182,22 @@ npm install id-scanner-lib --save
|
|
|
79
182
|
|
|
80
183
|
```html
|
|
81
184
|
<!-- 生产环境 (压缩版) -->
|
|
82
|
-
<script src="https://cdn.jsdelivr.net/npm/id-scanner-lib@1.3.
|
|
185
|
+
<script src="https://cdn.jsdelivr.net/npm/id-scanner-lib@1.3.1/dist/id-scanner.min.js"></script>
|
|
83
186
|
|
|
84
187
|
<!-- 开发环境 (未压缩) -->
|
|
85
|
-
<script src="https://cdn.jsdelivr.net/npm/id-scanner-lib@1.3.
|
|
188
|
+
<script src="https://cdn.jsdelivr.net/npm/id-scanner-lib@1.3.1/dist/id-scanner.js"></script>
|
|
86
189
|
```
|
|
87
190
|
|
|
88
191
|
## 包体积优化
|
|
89
192
|
|
|
90
|
-
v1.3.
|
|
193
|
+
v1.3.1版本通过代码分割和Tree-shaking极大地优化了包体积:
|
|
91
194
|
|
|
92
195
|
| 模块 | 大小 (gzip) | 说明 |
|
|
93
196
|
| --------------- | ----------- | ---------------- |
|
|
94
|
-
| 完整包(min.js) |
|
|
95
|
-
| 核心包(min.js) |
|
|
96
|
-
| OCR模块(min.js) |
|
|
97
|
-
| QR模块(min.js) |
|
|
197
|
+
| 完整包(min.js) | 93KB | 包含所有功能 |
|
|
198
|
+
| 核心包(min.js) | 186KB | 基础功能,无OCR |
|
|
199
|
+
| OCR模块(min.js) | 70KB | 仅文字识别 |
|
|
200
|
+
| QR模块(min.js) | 60KB | 仅二维码识别 |
|
|
98
201
|
| ESM模块 | 各模块更小 | 支持Tree-shaking |
|
|
99
202
|
|
|
100
203
|
## 最佳实践:按需引入
|
|
@@ -107,7 +210,8 @@ import { IDScanner } from 'id-scanner-lib';
|
|
|
107
210
|
|
|
108
211
|
const scanner = new IDScanner({
|
|
109
212
|
onQRCodeScanned: (result) => console.log('扫描结果:', result),
|
|
110
|
-
onIDCardScanned: (info) => console.log('身份证信息:', info)
|
|
213
|
+
onIDCardScanned: (info) => console.log('身份证信息:', info),
|
|
214
|
+
onAntiFakeDetected: (result) => console.log('防伪检测结果:', result)
|
|
111
215
|
});
|
|
112
216
|
```
|
|
113
217
|
|
|
@@ -176,12 +280,57 @@ document.getElementById('fileInput').addEventListener('change', async (e) => {
|
|
|
176
280
|
// 处理身份证图像
|
|
177
281
|
const idInfo = await scanner.processIDCardImage(compressed);
|
|
178
282
|
console.log('身份证信息:', idInfo);
|
|
283
|
+
|
|
284
|
+
// 检查防伪检测结果
|
|
285
|
+
if (idInfo.antiFakeResult) {
|
|
286
|
+
console.log('防伪检测结果:', idInfo.antiFakeResult);
|
|
287
|
+
if (idInfo.antiFakeResult.isAuthentic) {
|
|
288
|
+
console.log('证件验证通过');
|
|
289
|
+
} else {
|
|
290
|
+
console.log('警告:可能为伪造证件');
|
|
291
|
+
}
|
|
292
|
+
}
|
|
179
293
|
} catch (error) {
|
|
180
294
|
console.error('处理失败:', error);
|
|
181
295
|
}
|
|
182
296
|
});
|
|
183
297
|
```
|
|
184
298
|
|
|
299
|
+
### 身份证防伪检测
|
|
300
|
+
|
|
301
|
+
```javascript
|
|
302
|
+
import { IDScanner } from 'id-scanner-lib';
|
|
303
|
+
|
|
304
|
+
const scanner = new IDScanner({
|
|
305
|
+
// 防伪检测结果回调
|
|
306
|
+
onAntiFakeDetected: (result) => {
|
|
307
|
+
if (result.isAuthentic) {
|
|
308
|
+
console.log('身份证验证通过,检测到的防伪特征:', result.detectedFeatures);
|
|
309
|
+
} else {
|
|
310
|
+
console.log('警告:可能是伪造证件!', result.message);
|
|
311
|
+
// 显示安全提示
|
|
312
|
+
document.getElementById('warning').style.display = 'block';
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
});
|
|
316
|
+
|
|
317
|
+
await scanner.initialize();
|
|
318
|
+
|
|
319
|
+
// 方法1:单独进行防伪检测
|
|
320
|
+
const antiFakeResult = await scanner.detectIDCardAntiFake(idCardImage);
|
|
321
|
+
console.log('防伪检测结果:', antiFakeResult);
|
|
322
|
+
console.log('检测置信度:', antiFakeResult.confidence);
|
|
323
|
+
|
|
324
|
+
// 方法2:身份证识别时自动进行防伪检测
|
|
325
|
+
const idInfo = await scanner.processIDCardImage(idCardImage);
|
|
326
|
+
// 防伪检测结果包含在返回的信息中
|
|
327
|
+
if (idInfo.antiFakeResult && idInfo.antiFakeResult.isAuthentic) {
|
|
328
|
+
// 身份证真实,继续处理
|
|
329
|
+
} else {
|
|
330
|
+
// 提示可能为伪造证件
|
|
331
|
+
}
|
|
332
|
+
```
|
|
333
|
+
|
|
185
334
|
### 使用内置演示组件
|
|
186
335
|
|
|
187
336
|
```javascript
|
|
@@ -243,6 +392,23 @@ OCR引擎基于Tesseract.js进行了一系列优化:
|
|
|
243
392
|
3. **多线程处理**:使用Web Worker避免主线程阻塞
|
|
244
393
|
4. **结果缓存**:相同图像指纹不重复计算,提高响应速度
|
|
245
394
|
|
|
395
|
+
### 身份证防伪检测技术
|
|
396
|
+
|
|
397
|
+
防伪检测模块能识别身份证中的多种防伪特征:
|
|
398
|
+
|
|
399
|
+
1. **荧光油墨特征**:检测特定区域的荧光反应模式
|
|
400
|
+
2. **微缩文字**:识别证件上的微小文字,伪造证件难以复制
|
|
401
|
+
3. **光变图案**:检测特定角度下的光变效果
|
|
402
|
+
4. **雕刻凹印**:通过纹理检测特定的凹印模式
|
|
403
|
+
5. **隐形图案**:识别证件上的幽灵图像和隐形水印
|
|
404
|
+
|
|
405
|
+
算法结合多种图像处理技术:
|
|
406
|
+
|
|
407
|
+
- 特定光谱通道提取与分析
|
|
408
|
+
- 边缘检测与微文字模式识别
|
|
409
|
+
- 对比度与光照调整突出隐形特征
|
|
410
|
+
- 自适应阈值处理增强识别准确度
|
|
411
|
+
|
|
246
412
|
### 图像增强算法
|
|
247
413
|
|
|
248
414
|
针对不同场景提供最佳图像处理策略:
|
|
@@ -276,24 +442,55 @@ OCR引擎基于Tesseract.js进行了一系列优化:
|
|
|
276
442
|
|
|
277
443
|
## 应用场景
|
|
278
444
|
|
|
279
|
-
-
|
|
280
|
-
-
|
|
445
|
+
- **网上银行身份验证**:快速验证用户身份信息,检测伪造证件
|
|
446
|
+
- **酒店登记系统**:自动录入住客信息并验证证件真伪
|
|
281
447
|
- **自助服务终端**:无需人工,自动处理证件信息
|
|
282
|
-
-
|
|
448
|
+
- **企业内部系统**:员工证件信息采集与验证
|
|
283
449
|
- **活动签到系统**:快速扫码签到与证件登记
|
|
284
450
|
|
|
285
|
-
##
|
|
451
|
+
## 发布指南
|
|
452
|
+
|
|
453
|
+
### 发布到NPM
|
|
454
|
+
|
|
455
|
+
```bash
|
|
456
|
+
# 1. 确保版本号正确
|
|
457
|
+
npm version [patch|minor|major]
|
|
458
|
+
|
|
459
|
+
# 2. 构建生产版本
|
|
460
|
+
npm run build:prod
|
|
461
|
+
|
|
462
|
+
# 3. 发布到NPM
|
|
463
|
+
npm publish
|
|
286
464
|
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
465
|
+
# 4. 生成标签
|
|
466
|
+
git push origin --tags
|
|
467
|
+
```
|
|
468
|
+
|
|
469
|
+
### 发布到GitHub
|
|
470
|
+
|
|
471
|
+
```bash
|
|
472
|
+
# 1. 提交代码变更
|
|
473
|
+
git add .
|
|
474
|
+
git commit -m "发布 v1.x.x"
|
|
475
|
+
|
|
476
|
+
# 2. 推送到GitHub
|
|
477
|
+
git push origin main
|
|
478
|
+
|
|
479
|
+
# 3. 创建Release
|
|
480
|
+
# 访问 https://github.com/agions/id-scanner-lib/releases/new
|
|
481
|
+
# 选择对应的标签,填写Release说明
|
|
482
|
+
```
|
|
292
483
|
|
|
293
484
|
## 贡献指南
|
|
294
485
|
|
|
295
486
|
欢迎贡献代码、报告问题或提出新功能建议。请通过GitHub Issues或Pull Requests参与项目。
|
|
296
487
|
|
|
488
|
+
1. Fork项目仓库
|
|
489
|
+
2. 创建你的特性分支 (`git checkout -b feature/amazing-feature`)
|
|
490
|
+
3. 提交你的更改 (`git commit -m '添加一些很棒的功能'`)
|
|
491
|
+
4. 推送到分支 (`git push origin feature/amazing-feature`)
|
|
492
|
+
5. 打开Pull Request
|
|
493
|
+
|
|
297
494
|
## 许可证
|
|
298
495
|
|
|
299
496
|
本项目采用MIT许可证。详见[LICENSE](LICENSE)文件。
|
|
@@ -303,5 +500,6 @@ OCR引擎基于Tesseract.js进行了一系列优化:
|
|
|
303
500
|
<p align="center">
|
|
304
501
|
<a href="https://github.com/agions/id-scanner-lib">GitHub</a> •
|
|
305
502
|
<a href="https://www.npmjs.com/package/id-scanner-lib">NPM</a> •
|
|
306
|
-
<a href="https://github.com/agions/id-scanner-lib/issues">Issues</a>
|
|
503
|
+
<a href="https://github.com/agions/id-scanner-lib/issues">Issues</a> •
|
|
504
|
+
<a href="https://github.com/agions/id-scanner-lib/releases">Releases</a>
|
|
307
505
|
</p>
|
|
@@ -1081,16 +1081,16 @@ async function processOCRInWorker(input) {
|
|
|
1081
1081
|
// 加载Tesseract.js (Worker 环境下动态导入)
|
|
1082
1082
|
const { createWorker } = await import('tesseract.js');
|
|
1083
1083
|
// 创建OCR Worker
|
|
1084
|
-
const worker = await createWorker(input.tessWorkerOptions || {
|
|
1085
|
-
logger: (m) => console.log(m)
|
|
1086
|
-
}); // 添加类型断言,避免TypeScript错误
|
|
1084
|
+
const worker = (await createWorker(input.tessWorkerOptions || {
|
|
1085
|
+
logger: (m) => console.log(m),
|
|
1086
|
+
})); // 添加类型断言,避免TypeScript错误
|
|
1087
1087
|
try {
|
|
1088
1088
|
// 初始化OCR引擎
|
|
1089
1089
|
await worker.load();
|
|
1090
|
-
await worker.loadLanguage(
|
|
1091
|
-
await worker.initialize(
|
|
1090
|
+
await worker.loadLanguage("chi_sim");
|
|
1091
|
+
await worker.initialize("chi_sim");
|
|
1092
1092
|
await worker.setParameters({
|
|
1093
|
-
tessedit_char_whitelist:
|
|
1093
|
+
tessedit_char_whitelist: "0123456789X-年月日一二三四五六七八九十零壹贰叁肆伍陆柒捌玖拾ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz民族汉族满族回族维吾尔族藏族苗族彝族壮族朝鲜族侗族瑶族白族土家族哈尼族哈萨克族傣族黎族傈僳族佤族高山族拉祜族水族东乡族钠西族景颇族柯尔克孜族士族达斡尔族仫佬族羌族布朗族撒拉族毛南族仡佬族锡伯族阿昌族普米族塔吉克族怒族乌孜别克族俄罗斯族鄂温克族德昂族保安族裕固族京族塔塔尔族独龙族鄂伦春族赫哲族门巴族珞巴族基诺族男女性别住址出生公民身份号码签发机关有效期",
|
|
1094
1094
|
});
|
|
1095
1095
|
// 识别图像
|
|
1096
1096
|
const { data } = await worker.recognize(input.imageBase64);
|
|
@@ -1103,7 +1103,7 @@ async function processOCRInWorker(input) {
|
|
|
1103
1103
|
// 返回处理结果
|
|
1104
1104
|
return {
|
|
1105
1105
|
idCardInfo,
|
|
1106
|
-
processingTime
|
|
1106
|
+
processingTime,
|
|
1107
1107
|
};
|
|
1108
1108
|
}
|
|
1109
1109
|
catch (error) {
|
|
@@ -1124,7 +1124,7 @@ async function processOCRInWorker(input) {
|
|
|
1124
1124
|
function parseIDCardText(text) {
|
|
1125
1125
|
const info = {};
|
|
1126
1126
|
// 拆分为行
|
|
1127
|
-
const lines = text.split(
|
|
1127
|
+
const lines = text.split("\n").filter((line) => line.trim());
|
|
1128
1128
|
// 解析身份证号码(最容易识别的部分)
|
|
1129
1129
|
const idNumberRegex = /(\d{17}[\dX])/;
|
|
1130
1130
|
const idNumberMatch = text.match(idNumberRegex);
|
|
@@ -1133,8 +1133,9 @@ function parseIDCardText(text) {
|
|
|
1133
1133
|
}
|
|
1134
1134
|
// 解析姓名
|
|
1135
1135
|
for (const line of lines) {
|
|
1136
|
-
if (line.includes(
|
|
1137
|
-
|
|
1136
|
+
if (line.includes("姓名") ||
|
|
1137
|
+
(line.length < 10 && line.length > 1 && !/\d/.test(line))) {
|
|
1138
|
+
info.name = line.replace("姓名", "").trim();
|
|
1138
1139
|
break;
|
|
1139
1140
|
}
|
|
1140
1141
|
}
|
|
@@ -1144,7 +1145,9 @@ function parseIDCardText(text) {
|
|
|
1144
1145
|
if (genderMatch) {
|
|
1145
1146
|
info.gender = genderMatch[1];
|
|
1146
1147
|
const nationalityText = genderMatch[0];
|
|
1147
|
-
info.nationality = nationalityText
|
|
1148
|
+
info.nationality = nationalityText
|
|
1149
|
+
.substring(nationalityText.indexOf(genderMatch[1]) + 1)
|
|
1150
|
+
.trim();
|
|
1148
1151
|
}
|
|
1149
1152
|
// 解析出生日期
|
|
1150
1153
|
const birthDateRegex = /(\d{4})年(\d{1,2})月(\d{1,2})日/;
|
|
@@ -1156,19 +1159,19 @@ function parseIDCardText(text) {
|
|
|
1156
1159
|
const addressRegex = /住址([\s\S]*?)公民身份号码/;
|
|
1157
1160
|
const addressMatch = text.match(addressRegex);
|
|
1158
1161
|
if (addressMatch) {
|
|
1159
|
-
info.address = addressMatch[1].replace(/\n/g,
|
|
1162
|
+
info.address = addressMatch[1].replace(/\n/g, "").trim();
|
|
1160
1163
|
}
|
|
1161
1164
|
// 解析签发机关
|
|
1162
1165
|
const authorityRegex = /签发机关([\s\S]*?)有效期/;
|
|
1163
1166
|
const authorityMatch = text.match(authorityRegex);
|
|
1164
1167
|
if (authorityMatch) {
|
|
1165
|
-
info.issuingAuthority = authorityMatch[1].replace(/\n/g,
|
|
1168
|
+
info.issuingAuthority = authorityMatch[1].replace(/\n/g, "").trim();
|
|
1166
1169
|
}
|
|
1167
1170
|
// 解析有效期限
|
|
1168
1171
|
const validPeriodRegex = /有效期限([\s\S]*?)(-|至)/;
|
|
1169
1172
|
const validPeriodMatch = text.match(validPeriodRegex);
|
|
1170
1173
|
if (validPeriodMatch) {
|
|
1171
|
-
info.validPeriod = validPeriodMatch[0].replace(
|
|
1174
|
+
info.validPeriod = validPeriodMatch[0].replace("有效期限", "").trim();
|
|
1172
1175
|
}
|
|
1173
1176
|
return info;
|
|
1174
1177
|
}
|
package/dist/id-scanner-ocr.js
CHANGED
|
@@ -1085,16 +1085,16 @@
|
|
|
1085
1085
|
// 加载Tesseract.js (Worker 环境下动态导入)
|
|
1086
1086
|
const { createWorker } = await import('tesseract.js');
|
|
1087
1087
|
// 创建OCR Worker
|
|
1088
|
-
const worker = await createWorker(input.tessWorkerOptions || {
|
|
1089
|
-
logger: (m) => console.log(m)
|
|
1090
|
-
}); // 添加类型断言,避免TypeScript错误
|
|
1088
|
+
const worker = (await createWorker(input.tessWorkerOptions || {
|
|
1089
|
+
logger: (m) => console.log(m),
|
|
1090
|
+
})); // 添加类型断言,避免TypeScript错误
|
|
1091
1091
|
try {
|
|
1092
1092
|
// 初始化OCR引擎
|
|
1093
1093
|
await worker.load();
|
|
1094
|
-
await worker.loadLanguage(
|
|
1095
|
-
await worker.initialize(
|
|
1094
|
+
await worker.loadLanguage("chi_sim");
|
|
1095
|
+
await worker.initialize("chi_sim");
|
|
1096
1096
|
await worker.setParameters({
|
|
1097
|
-
tessedit_char_whitelist:
|
|
1097
|
+
tessedit_char_whitelist: "0123456789X-年月日一二三四五六七八九十零壹贰叁肆伍陆柒捌玖拾ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz民族汉族满族回族维吾尔族藏族苗族彝族壮族朝鲜族侗族瑶族白族土家族哈尼族哈萨克族傣族黎族傈僳族佤族高山族拉祜族水族东乡族钠西族景颇族柯尔克孜族士族达斡尔族仫佬族羌族布朗族撒拉族毛南族仡佬族锡伯族阿昌族普米族塔吉克族怒族乌孜别克族俄罗斯族鄂温克族德昂族保安族裕固族京族塔塔尔族独龙族鄂伦春族赫哲族门巴族珞巴族基诺族男女性别住址出生公民身份号码签发机关有效期",
|
|
1098
1098
|
});
|
|
1099
1099
|
// 识别图像
|
|
1100
1100
|
const { data } = await worker.recognize(input.imageBase64);
|
|
@@ -1107,7 +1107,7 @@
|
|
|
1107
1107
|
// 返回处理结果
|
|
1108
1108
|
return {
|
|
1109
1109
|
idCardInfo,
|
|
1110
|
-
processingTime
|
|
1110
|
+
processingTime,
|
|
1111
1111
|
};
|
|
1112
1112
|
}
|
|
1113
1113
|
catch (error) {
|
|
@@ -1128,7 +1128,7 @@
|
|
|
1128
1128
|
function parseIDCardText(text) {
|
|
1129
1129
|
const info = {};
|
|
1130
1130
|
// 拆分为行
|
|
1131
|
-
const lines = text.split(
|
|
1131
|
+
const lines = text.split("\n").filter((line) => line.trim());
|
|
1132
1132
|
// 解析身份证号码(最容易识别的部分)
|
|
1133
1133
|
const idNumberRegex = /(\d{17}[\dX])/;
|
|
1134
1134
|
const idNumberMatch = text.match(idNumberRegex);
|
|
@@ -1137,8 +1137,9 @@
|
|
|
1137
1137
|
}
|
|
1138
1138
|
// 解析姓名
|
|
1139
1139
|
for (const line of lines) {
|
|
1140
|
-
if (line.includes(
|
|
1141
|
-
|
|
1140
|
+
if (line.includes("姓名") ||
|
|
1141
|
+
(line.length < 10 && line.length > 1 && !/\d/.test(line))) {
|
|
1142
|
+
info.name = line.replace("姓名", "").trim();
|
|
1142
1143
|
break;
|
|
1143
1144
|
}
|
|
1144
1145
|
}
|
|
@@ -1148,7 +1149,9 @@
|
|
|
1148
1149
|
if (genderMatch) {
|
|
1149
1150
|
info.gender = genderMatch[1];
|
|
1150
1151
|
const nationalityText = genderMatch[0];
|
|
1151
|
-
info.nationality = nationalityText
|
|
1152
|
+
info.nationality = nationalityText
|
|
1153
|
+
.substring(nationalityText.indexOf(genderMatch[1]) + 1)
|
|
1154
|
+
.trim();
|
|
1152
1155
|
}
|
|
1153
1156
|
// 解析出生日期
|
|
1154
1157
|
const birthDateRegex = /(\d{4})年(\d{1,2})月(\d{1,2})日/;
|
|
@@ -1160,19 +1163,19 @@
|
|
|
1160
1163
|
const addressRegex = /住址([\s\S]*?)公民身份号码/;
|
|
1161
1164
|
const addressMatch = text.match(addressRegex);
|
|
1162
1165
|
if (addressMatch) {
|
|
1163
|
-
info.address = addressMatch[1].replace(/\n/g,
|
|
1166
|
+
info.address = addressMatch[1].replace(/\n/g, "").trim();
|
|
1164
1167
|
}
|
|
1165
1168
|
// 解析签发机关
|
|
1166
1169
|
const authorityRegex = /签发机关([\s\S]*?)有效期/;
|
|
1167
1170
|
const authorityMatch = text.match(authorityRegex);
|
|
1168
1171
|
if (authorityMatch) {
|
|
1169
|
-
info.issuingAuthority = authorityMatch[1].replace(/\n/g,
|
|
1172
|
+
info.issuingAuthority = authorityMatch[1].replace(/\n/g, "").trim();
|
|
1170
1173
|
}
|
|
1171
1174
|
// 解析有效期限
|
|
1172
1175
|
const validPeriodRegex = /有效期限([\s\S]*?)(-|至)/;
|
|
1173
1176
|
const validPeriodMatch = text.match(validPeriodRegex);
|
|
1174
1177
|
if (validPeriodMatch) {
|
|
1175
|
-
info.validPeriod = validPeriodMatch[0].replace(
|
|
1178
|
+
info.validPeriod = validPeriodMatch[0].replace("有效期限", "").trim();
|
|
1176
1179
|
}
|
|
1177
1180
|
return info;
|
|
1178
1181
|
}
|