id-scanner-lib 1.3.3 → 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 (101) 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 -75
  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/{id-recognition → modules/id-card}/anti-fake-detector.ts +273 -239
  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/{id-recognition → modules/id-card}/ocr-processor.ts +149 -92
  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/tesseract.d.ts +265 -22
  73. package/src/utils/image-processing.ts +68 -49
  74. package/src/utils/index.ts +426 -0
  75. package/src/utils/performance.ts +168 -131
  76. package/src/utils/resource-manager.ts +65 -146
  77. package/src/utils/types.ts +90 -2
  78. package/src/utils/worker.ts +123 -84
  79. package/src/version.ts +11 -0
  80. package/tools/scaffold.js +543 -0
  81. package/dist/id-scanner-core.esm.js +0 -11349
  82. package/dist/id-scanner-core.js +0 -11361
  83. package/dist/id-scanner-core.min.js +0 -1
  84. package/dist/id-scanner-ocr.esm.js +0 -2319
  85. package/dist/id-scanner-ocr.js +0 -2328
  86. package/dist/id-scanner-ocr.min.js +0 -1
  87. package/dist/id-scanner-qr.esm.js +0 -1296
  88. package/dist/id-scanner-qr.js +0 -1305
  89. package/dist/id-scanner-qr.min.js +0 -1
  90. package/dist/id-scanner.js +0 -4561
  91. package/dist/id-scanner.min.js +0 -1
  92. package/src/core.ts +0 -138
  93. package/src/demo/demo.ts +0 -204
  94. package/src/id-recognition/data-extractor.ts +0 -262
  95. package/src/id-recognition/id-detector.ts +0 -510
  96. package/src/id-recognition/ocr-worker.ts +0 -156
  97. package/src/index-umd.ts +0 -477
  98. package/src/ocr-module.ts +0 -187
  99. package/src/qr-module.ts +0 -179
  100. package/src/scanner/barcode-scanner.ts +0 -251
  101. package/src/scanner/qr-scanner.ts +0 -167
@@ -0,0 +1,178 @@
1
+ /**
2
+ * @file 身份证模块类型定义
3
+ * @description 身份证模块相关的类型和接口定义
4
+ * @module modules/id-card/types
5
+ */
6
+
7
+ /**
8
+ * 身份证类型枚举
9
+ */
10
+ export enum IDCardType {
11
+ /** 第二代居民身份证正面 */
12
+ FRONT = 'front',
13
+ /** 第二代居民身份证背面 */
14
+ BACK = 'back',
15
+ /** 第一代居民身份证 */
16
+ FIRST_GENERATION = 'first_generation',
17
+ /** 临时身份证 */
18
+ TEMPORARY = 'temporary',
19
+ /** 外国人永久居留证 */
20
+ FOREIGN_PERMANENT = 'foreign_permanent',
21
+ /** 港澳台居民居住证 */
22
+ HMT_RESIDENT = 'hmt_resident',
23
+ /** 未知类型 */
24
+ UNKNOWN = 'unknown'
25
+ }
26
+
27
+ /**
28
+ * 证件边缘信息
29
+ */
30
+ export interface IDCardEdge {
31
+ /** 左上角坐标 */
32
+ topLeft: { x: number; y: number };
33
+ /** 右上角坐标 */
34
+ topRight: { x: number; y: number };
35
+ /** 右下角坐标 */
36
+ bottomRight: { x: number; y: number };
37
+ /** 左下角坐标 */
38
+ bottomLeft: { x: number; y: number };
39
+ }
40
+
41
+ /**
42
+ * 身份证信息
43
+ */
44
+ export interface IDCardInfo {
45
+ nationality?: string;
46
+ issuingAuthority?: string;
47
+ validPeriod?: string;
48
+ /** 身份证类型 */
49
+ type?: IDCardType;
50
+ /** 身份证边缘信息 */
51
+ edge?: IDCardEdge;
52
+ /** 姓名 */
53
+ name?: string;
54
+ /** 性别 */
55
+ gender?: string;
56
+ /** 民族 */
57
+ ethnicity?: string;
58
+ /** 出生日期,格式: YYYY-MM-DD */
59
+ birthDate?: string;
60
+ /** 地址 */
61
+ address?: string;
62
+ /** 身份证号码 */
63
+ idNumber?: string;
64
+ /** 签发机关 */
65
+ issueAuthority?: string;
66
+ /** 有效期起始日期,格式: YYYY-MM-DD */
67
+ validFrom?: string;
68
+ /** 有效期截止日期,格式: YYYY-MM-DD */
69
+ validTo?: string;
70
+ /** 相片区域坐标 */
71
+ photoRegion?: {
72
+ x: number;
73
+ y: number;
74
+ width: number;
75
+ height: number;
76
+ };
77
+ /** 原始身份证图像 */
78
+ image?: ImageData;
79
+ /** 置信度 */
80
+ confidence?: number;
81
+ /** 防伪检测结果 */
82
+ antiFake?: {
83
+ /** 是否通过防伪检测 */
84
+ passed: boolean;
85
+ /** 防伪检测分数 */
86
+ score: number;
87
+ /** 防伪特征检测结果 */
88
+ features?: {
89
+ /** 荧光油墨 */
90
+ fluorescent?: boolean;
91
+ /** 微缩文字 */
92
+ microtext?: boolean;
93
+ /** 光变图案 */
94
+ opticalVariable?: boolean;
95
+ /** 纹理 */
96
+ texture?: boolean;
97
+ /** 暗记 */
98
+ watermark?: boolean;
99
+ };
100
+ };
101
+ }
102
+
103
+ /**
104
+ * 身份证模块配置选项
105
+ */
106
+ export interface IDCardModuleOptions {
107
+ /** 是否启用模块 */
108
+ enabled?: boolean;
109
+
110
+ /** 检测器配置 */
111
+ detector?: {
112
+ /** 最小置信度 */
113
+ minConfidence?: number;
114
+ /** 是否启用OCR识别 */
115
+ enableOCR?: boolean;
116
+ /** 是否启用防伪检测 */
117
+ enableAntiFake?: boolean;
118
+ };
119
+
120
+ /** OCR处理器配置 */
121
+ ocr?: {
122
+ /** 是否使用Web Worker处理OCR */
123
+ useWorker?: boolean;
124
+ /** 最大图像尺寸 */
125
+ maxImageDimension?: number;
126
+ /** 亮度调整 */
127
+ brightness?: number;
128
+ /** 对比度调整 */
129
+ contrast?: number;
130
+ };
131
+
132
+ /** 防伪检测配置 */
133
+ antiFake?: {
134
+ /** 防伪检测灵敏度 */
135
+ sensitivity?: number;
136
+ /** 最小置信度 */
137
+ minConfidence?: number;
138
+ };
139
+ }
140
+
141
+ /**
142
+ * 身份证验证结果
143
+ */
144
+ export interface IDCardVerificationResult {
145
+ /** 是否验证通过 */
146
+ isValid: boolean;
147
+ /** 验证分数 */
148
+ score: number;
149
+ /** 失败原因 */
150
+ failureReason?: string;
151
+ /** 验证详情 */
152
+ details?: {
153
+ /** 身份证号码是否有效 */
154
+ idNumberValid?: boolean;
155
+ /** 签发日期是否有效 */
156
+ issueDateValid?: boolean;
157
+ /** 有效期是否过期 */
158
+ isExpired?: boolean;
159
+ /** 防伪检测是否通过 */
160
+ antiFakePassed?: boolean;
161
+ };
162
+ }
163
+
164
+ /**
165
+ * 图像处理配置选项
166
+ */
167
+ export interface ImageProcessOptions {
168
+ /** 是否进行预处理 */
169
+ preprocess?: boolean;
170
+ /** 是否校正图像 */
171
+ correctPerspective?: boolean;
172
+ /** 是否增强图像 */
173
+ enhance?: boolean;
174
+ /** 是否去噪 */
175
+ denoise?: boolean;
176
+ /** 是否二值化 */
177
+ binarize?: boolean;
178
+ }
@@ -0,0 +1,175 @@
1
+ /**
2
+ * @file 二维码模块入口
3
+ * @description 提供二维码识别和解析功能的模块入口
4
+ * @module modules/qrcode
5
+ */
6
+
7
+ import { BaseModule } from '../../core/base-module';
8
+ import { QRCodeResult, QRCodeModuleOptions } from './types';
9
+ import { QRCodeScanner } from './qr-code-scanner';
10
+
11
+ /**
12
+ * 二维码模块
13
+ * 提供二维码检测和解析功能
14
+ */
15
+ export class QRCodeModule extends BaseModule {
16
+ /** 模块名称 */
17
+ public readonly name: string = 'qrcode';
18
+
19
+ /** 模块配置 */
20
+ private options: QRCodeModuleOptions;
21
+
22
+ /** 二维码扫描器 */
23
+ private scanner: QRCodeScanner;
24
+
25
+ /** 最后一次扫描结果 */
26
+ private lastScanResult?: QRCodeResult;
27
+
28
+ /**
29
+ * 构造函数
30
+ * @param options 模块配置选项
31
+ */
32
+ constructor(options: QRCodeModuleOptions = {}) {
33
+ super();
34
+
35
+ this.options = {
36
+ enabled: true,
37
+ scanner: {
38
+ minConfidence: 0.6,
39
+ tryMultipleScan: true,
40
+ returnImage: false,
41
+ ...options.scanner
42
+ },
43
+ imageProcess: {
44
+ preprocess: true,
45
+ enhanceContrast: true,
46
+ threshold: 128,
47
+ ...options.imageProcess
48
+ },
49
+ ...options
50
+ };
51
+
52
+ // 创建扫描器
53
+ this.scanner = new QRCodeScanner({
54
+ minConfidence: this.options.scanner?.minConfidence,
55
+ returnImage: this.options.scanner?.returnImage,
56
+ imageProcess: this.options.imageProcess
57
+ });
58
+ }
59
+
60
+ /**
61
+ * 初始化模块
62
+ */
63
+ public async initialize(): Promise<void> {
64
+ if (this._isInitialized) {
65
+ return;
66
+ }
67
+
68
+ this.logger.debug(this.name, '初始化二维码模块');
69
+
70
+ try {
71
+ // 初始化扫描器
72
+ await this.scanner.initialize();
73
+
74
+ this._isInitialized = true;
75
+ this.emit('initialized');
76
+ this.logger.debug(this.name, '二维码模块初始化完成');
77
+ } catch (error) {
78
+ this.logger.error(this.name, '二维码模块初始化失败', error as Error);
79
+ throw new Error(`二维码模块初始化失败: ${error instanceof Error ? error.message : String(error)}`);
80
+ }
81
+ }
82
+
83
+ /**
84
+ * 扫描图像中的二维码
85
+ * @param image 图像源
86
+ * @returns 二维码扫描结果
87
+ */
88
+ public async scan(
89
+ image: ImageData | HTMLImageElement | HTMLCanvasElement
90
+ ): Promise<QRCodeResult | undefined> {
91
+ this.ensureInitialized();
92
+
93
+ try {
94
+ // 扫描二维码
95
+ const scanResult = await this.scanner.scan(image);
96
+
97
+ if (scanResult) {
98
+ // 保存最后一次扫描结果
99
+ this.lastScanResult = scanResult;
100
+
101
+ // 触发事件
102
+ this.emit('qrcode:scanned', { result: scanResult });
103
+ }
104
+
105
+ return scanResult;
106
+ } catch (error) {
107
+ this.logger.error(this.name, '二维码扫描失败', error as Error);
108
+ throw new Error(`二维码扫描失败: ${error instanceof Error ? error.message : String(error)}`);
109
+ }
110
+ }
111
+
112
+ /**
113
+ * 获取最后一次扫描结果
114
+ */
115
+ public getLastScanResult(): QRCodeResult | undefined {
116
+ return this.lastScanResult;
117
+ }
118
+
119
+ /**
120
+ * 解析二维码数据
121
+ * @param data 二维码数据
122
+ * @returns 解析后的数据对象
123
+ */
124
+ public parseQRCodeData(data: string): Record<string, any> | string {
125
+ try {
126
+ // 尝试解析为JSON
127
+ return JSON.parse(data);
128
+ } catch {
129
+ // 不是JSON,尝试解析为URL参数
130
+ if (data.includes('=')) {
131
+ try {
132
+ const params: Record<string, string> = {};
133
+ const urlParams = new URLSearchParams(data.includes('?') ? data.split('?')[1] : data);
134
+
135
+ urlParams.forEach((value, key) => {
136
+ params[key] = value;
137
+ });
138
+
139
+ return params;
140
+ } catch {
141
+ // 解析URL参数失败,返回原始字符串
142
+ return data;
143
+ }
144
+ }
145
+
146
+ // 返回原始字符串
147
+ return data;
148
+ }
149
+ }
150
+
151
+ /**
152
+ * 释放模块资源
153
+ */
154
+ public async dispose(): Promise<void> {
155
+ if (!this._isInitialized) {
156
+ return;
157
+ }
158
+
159
+ this.logger.debug(this.name, '释放二维码模块资源');
160
+
161
+ try {
162
+ // 释放扫描器资源
163
+ await this.scanner.dispose();
164
+
165
+ // 调用基类的dispose方法
166
+ await super.dispose();
167
+ } catch (error) {
168
+ this.logger.error(this.name, '二维码模块资源释放失败', error as Error);
169
+ throw new Error(`二维码模块资源释放失败: ${error instanceof Error ? error.message : String(error)}`);
170
+ }
171
+ }
172
+ }
173
+
174
+ // 导出类型
175
+ export * from './types';
@@ -0,0 +1,230 @@
1
+ /**
2
+ * @file 二维码扫描器
3
+ * @description 提供二维码检测和解析功能
4
+ * @module modules/qrcode/qr-code-scanner
5
+ */
6
+
7
+ import { EventEmitter } from '../../core/event-emitter';
8
+ import { Logger } from '../../core/logger';
9
+ import { QRCodeResult } from './types';
10
+ import jsQR from 'jsqr';
11
+
12
+ /**
13
+ * 二维码扫描器配置选项
14
+ */
15
+ export interface QRCodeScannerOptions {
16
+ /** 最小置信度 */
17
+ minConfidence?: number;
18
+ /** 是否返回原始图像 */
19
+ returnImage?: boolean;
20
+ /** 图像处理配置 */
21
+ imageProcess?: {
22
+ /** 是否进行预处理 */
23
+ preprocess?: boolean;
24
+ /** 是否增强对比度 */
25
+ enhanceContrast?: boolean;
26
+ /** 二值化阈值 */
27
+ threshold?: number;
28
+ };
29
+ }
30
+
31
+ /**
32
+ * 二维码扫描器类
33
+ */
34
+ export class QRCodeScanner extends EventEmitter {
35
+ private options: QRCodeScannerOptions;
36
+ private logger: Logger;
37
+ private initialized: boolean = false;
38
+
39
+ /**
40
+ * 构造函数
41
+ * @param options 配置选项
42
+ */
43
+ constructor(options: QRCodeScannerOptions = {}) {
44
+ super();
45
+ this.options = {
46
+ minConfidence: 0.6,
47
+ returnImage: false,
48
+ imageProcess: {
49
+ preprocess: true,
50
+ enhanceContrast: true,
51
+ threshold: 128,
52
+ ...options.imageProcess
53
+ },
54
+ ...options
55
+ };
56
+ this.logger = Logger.getInstance();
57
+ }
58
+
59
+ /**
60
+ * 初始化扫描器
61
+ */
62
+ public async initialize(): Promise<void> {
63
+ if (this.initialized) {
64
+ return;
65
+ }
66
+
67
+ this.logger.debug('QRCodeScanner', '初始化二维码扫描器');
68
+
69
+ // 验证jsQR是否可用
70
+ if (typeof jsQR !== 'function') {
71
+ throw new Error('jsQR库未加载,请确保已安装jsqr依赖');
72
+ }
73
+
74
+ this.initialized = true;
75
+ this.logger.debug('QRCodeScanner', '二维码扫描器初始化完成');
76
+ }
77
+
78
+ /**
79
+ * 扫描图像中的二维码
80
+ * @param image 图像源
81
+ * @returns 二维码扫描结果
82
+ */
83
+ public async scan(
84
+ image: ImageData | HTMLImageElement | HTMLCanvasElement
85
+ ): Promise<QRCodeResult | undefined> {
86
+ if (!this.initialized) {
87
+ await this.initialize();
88
+ }
89
+
90
+ // 将输入转换为ImageData
91
+ const imageData = this.getImageData(image);
92
+
93
+ // 图像预处理
94
+ const processedImage = this.options.imageProcess?.preprocess
95
+ ? this.preprocessImage(imageData)
96
+ : imageData;
97
+
98
+ // 使用jsQR进行扫描
99
+ const code = jsQR(
100
+ processedImage.data,
101
+ processedImage.width,
102
+ processedImage.height,
103
+ {
104
+ inversionAttempts: 'dontInvert'
105
+ }
106
+ );
107
+
108
+ if (!code) {
109
+ return undefined;
110
+ }
111
+
112
+ // 构建结果
113
+ const result: QRCodeResult = {
114
+ data: code.data,
115
+ boundingBox: {
116
+ topLeft: code.location.topLeftCorner,
117
+ topRight: code.location.topRightCorner,
118
+ bottomRight: code.location.bottomRightCorner,
119
+ bottomLeft: code.location.bottomLeftCorner
120
+ },
121
+ center: {
122
+ x: Math.round((code.location.topLeftCorner.x + code.location.bottomRightCorner.x) / 2),
123
+ y: Math.round((code.location.topLeftCorner.y + code.location.bottomRightCorner.y) / 2)
124
+ },
125
+ confidence: 1.0 // jsQR不提供置信度,默认为1.0
126
+ };
127
+
128
+ // 如果需要返回原始图像
129
+ if (this.options.returnImage) {
130
+ result.image = imageData;
131
+ }
132
+
133
+ this.logger.debug('QRCodeScanner', `扫描到二维码: ${result.data.substring(0, 20)}${result.data.length > 20 ? '...' : ''}`);
134
+
135
+ return result;
136
+ }
137
+
138
+ /**
139
+ * 将各种图像源转换为ImageData
140
+ * @param image 图像源
141
+ * @returns ImageData
142
+ */
143
+ private getImageData(
144
+ image: ImageData | HTMLImageElement | HTMLCanvasElement
145
+ ): ImageData {
146
+ // 如果已经是ImageData,直接返回
147
+ if (image instanceof ImageData) {
148
+ return image;
149
+ }
150
+
151
+ // 创建canvas并获取2D上下文
152
+ const canvas = document.createElement('canvas');
153
+ const ctx = canvas.getContext('2d');
154
+
155
+ if (!ctx) {
156
+ throw new Error('无法创建Canvas上下文');
157
+ }
158
+
159
+ // 设置canvas尺寸
160
+ canvas.width = image.width;
161
+ canvas.height = image.height;
162
+
163
+ // 绘制图像
164
+ ctx.drawImage(image, 0, 0);
165
+
166
+ // 获取ImageData
167
+ return ctx.getImageData(0, 0, canvas.width, canvas.height);
168
+ }
169
+
170
+ /**
171
+ * 图像预处理
172
+ * @param imageData 原始图像数据
173
+ * @returns 处理后的图像数据
174
+ */
175
+ private preprocessImage(imageData: ImageData): ImageData {
176
+ // 创建canvas并获取2D上下文
177
+ const canvas = document.createElement('canvas');
178
+ const ctx = canvas.getContext('2d');
179
+
180
+ if (!ctx) {
181
+ return imageData;
182
+ }
183
+
184
+ // 设置canvas尺寸
185
+ canvas.width = imageData.width;
186
+ canvas.height = imageData.height;
187
+
188
+ // 绘制原始图像
189
+ ctx.putImageData(imageData, 0, 0);
190
+
191
+ // 增强对比度
192
+ if (this.options.imageProcess?.enhanceContrast) {
193
+ ctx.filter = 'contrast(150%)';
194
+ ctx.drawImage(canvas, 0, 0);
195
+ ctx.filter = 'none';
196
+ }
197
+
198
+ // 应用二值化
199
+ const threshold = this.options.imageProcess?.threshold || 128;
200
+ const processedData = ctx.getImageData(0, 0, canvas.width, canvas.height);
201
+ const data = processedData.data;
202
+
203
+ for (let i = 0; i < data.length; i += 4) {
204
+ // 计算灰度值
205
+ const gray = 0.299 * data[i] + 0.587 * data[i + 1] + 0.114 * data[i + 2];
206
+ // 二值化
207
+ const value = gray < threshold ? 0 : 255;
208
+ data[i] = data[i + 1] = data[i + 2] = value;
209
+ }
210
+
211
+ return processedData;
212
+ }
213
+
214
+ /**
215
+ * 释放资源
216
+ */
217
+ public async dispose(): Promise<void> {
218
+ if (!this.initialized) {
219
+ return;
220
+ }
221
+
222
+ this.logger.debug('QRCodeScanner', '释放二维码扫描器资源');
223
+
224
+ // 移除所有事件监听器
225
+ this.removeAllListeners();
226
+
227
+ this.initialized = false;
228
+ this.logger.debug('QRCodeScanner', '二维码扫描器资源已释放');
229
+ }
230
+ }
@@ -0,0 +1,65 @@
1
+ /**
2
+ * @file 二维码模块类型定义
3
+ * @description 二维码模块相关的类型和接口定义
4
+ * @module modules/qrcode/types
5
+ */
6
+
7
+ /**
8
+ * 二维码检测结果
9
+ */
10
+ export interface QRCodeResult {
11
+ /** 二维码内容 */
12
+ data: string;
13
+
14
+ /** 二维码类型 */
15
+ type?: string;
16
+
17
+ /** 二维码边界框 */
18
+ boundingBox: {
19
+ topLeft: { x: number; y: number };
20
+ topRight: { x: number; y: number };
21
+ bottomRight: { x: number; y: number };
22
+ bottomLeft: { x: number; y: number };
23
+ };
24
+
25
+ /** 二维码中心点 */
26
+ center: { x: number; y: number };
27
+
28
+ /** 原始图像 */
29
+ image?: ImageData;
30
+
31
+ /** 置信度 */
32
+ confidence?: number;
33
+ }
34
+
35
+ /**
36
+ * 二维码模块选项
37
+ */
38
+ export interface QRCodeModuleOptions {
39
+ /** 是否启用模块 */
40
+ enabled?: boolean;
41
+
42
+ /** 二维码扫描配置 */
43
+ scanner?: {
44
+ /** 最小置信度 */
45
+ minConfidence?: number;
46
+
47
+ /** 是否尝试多次扫描 */
48
+ tryMultipleScan?: boolean;
49
+
50
+ /** 是否返回原始图像 */
51
+ returnImage?: boolean;
52
+ };
53
+
54
+ /** 图像处理配置 */
55
+ imageProcess?: {
56
+ /** 是否进行预处理 */
57
+ preprocess?: boolean;
58
+
59
+ /** 是否增强对比度 */
60
+ enhanceContrast?: boolean;
61
+
62
+ /** 二值化阈值 */
63
+ threshold?: number;
64
+ };
65
+ }