id-scanner-lib 1.2.2 → 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/LICENSE +1 -1
- package/README.md +375 -363
- package/dist/id-scanner-core.esm.js +427 -221
- package/dist/id-scanner-core.esm.js.map +1 -1
- package/dist/id-scanner-core.js +427 -221
- package/dist/id-scanner-core.js.map +1 -1
- package/dist/id-scanner-core.min.js +1 -9
- package/dist/id-scanner-core.min.js.map +1 -1
- package/dist/id-scanner-ocr.esm.js +451 -276
- package/dist/id-scanner-ocr.esm.js.map +1 -1
- package/dist/id-scanner-ocr.js +451 -276
- package/dist/id-scanner-ocr.js.map +1 -1
- package/dist/id-scanner-ocr.min.js +1 -9
- package/dist/id-scanner-ocr.min.js.map +1 -1
- package/dist/id-scanner-qr.esm.js +483 -233
- package/dist/id-scanner-qr.esm.js.map +1 -1
- package/dist/id-scanner-qr.js +482 -232
- package/dist/id-scanner-qr.js.map +1 -1
- package/dist/id-scanner-qr.min.js +1 -9
- package/dist/id-scanner-qr.min.js.map +1 -1
- package/dist/id-scanner.js +2138 -358
- package/dist/id-scanner.js.map +1 -1
- package/dist/id-scanner.min.js +1 -9
- package/dist/id-scanner.min.js.map +1 -1
- package/package.json +27 -7
- package/src/demo/demo.ts +178 -62
- package/src/id-recognition/anti-fake-detector.ts +317 -0
- package/src/id-recognition/id-detector.ts +184 -155
- package/src/id-recognition/ocr-processor.ts +193 -146
- package/src/id-recognition/ocr-worker.ts +82 -72
- package/src/index-umd.ts +347 -110
- package/src/index.ts +866 -91
- package/src/ocr-module.ts +108 -60
- package/src/qr-module.ts +104 -54
- package/src/scanner/barcode-scanner.ts +145 -58
- package/src/scanner/qr-scanner.ts +86 -47
- package/src/utils/image-processing.ts +479 -294
- package/dist/core.d.ts +0 -77
- package/dist/demo/demo.d.ts +0 -14
- package/dist/id-recognition/data-extractor.d.ts +0 -105
- package/dist/id-recognition/id-detector.d.ts +0 -100
- package/dist/id-recognition/ocr-processor.d.ts +0 -64
- package/dist/id-scanner.esm.js +0 -94656
- package/dist/id-scanner.esm.js.map +0 -1
- package/dist/index-umd.d.ts +0 -96
- package/dist/index.d.ts +0 -78
- package/dist/ocr-module.d.ts +0 -67
- package/dist/qr-module.d.ts +0 -68
- package/dist/scanner/barcode-scanner.d.ts +0 -90
- package/dist/scanner/qr-scanner.d.ts +0 -80
- package/dist/types/core.d.ts +0 -77
- package/dist/types/demo/demo.d.ts +0 -14
- package/dist/types/id-recognition/data-extractor.d.ts +0 -105
- package/dist/types/id-recognition/id-detector.d.ts +0 -100
- package/dist/types/id-recognition/ocr-processor.d.ts +0 -64
- package/dist/types/index-umd.d.ts +0 -96
- package/dist/types/index.d.ts +0 -78
- package/dist/types/ocr-module.d.ts +0 -67
- package/dist/types/qr-module.d.ts +0 -68
- package/dist/types/scanner/barcode-scanner.d.ts +0 -90
- package/dist/types/scanner/qr-scanner.d.ts +0 -80
- package/dist/types/utils/camera.d.ts +0 -81
- package/dist/types/utils/image-processing.d.ts +0 -75
- package/dist/types/utils/types.d.ts +0 -65
- package/dist/utils/camera.d.ts +0 -81
- package/dist/utils/image-processing.d.ts +0 -75
- package/dist/utils/types.d.ts +0 -65
|
@@ -4,31 +4,35 @@
|
|
|
4
4
|
* @module IDCardDetector
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import { Camera } from
|
|
8
|
-
import { ImageProcessor } from
|
|
9
|
-
import { DetectionResult } from
|
|
10
|
-
import {
|
|
11
|
-
|
|
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"
|
|
12
16
|
|
|
13
17
|
/**
|
|
14
18
|
* IDCardDetector配置选项
|
|
15
19
|
*/
|
|
16
20
|
export interface IDCardDetectorOptions {
|
|
17
|
-
onDetection?: (result: DetectionResult) => void
|
|
18
|
-
onError?: (error: Error) => void
|
|
19
|
-
detectionInterval?: number
|
|
20
|
-
maxImageDimension?: number
|
|
21
|
-
enableCache?: boolean
|
|
22
|
-
cacheSize?: number
|
|
23
|
-
logger?: (message: any) => void
|
|
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
|
|
24
28
|
}
|
|
25
29
|
|
|
26
30
|
/**
|
|
27
31
|
* 身份证检测器类
|
|
28
|
-
*
|
|
32
|
+
*
|
|
29
33
|
* 通过图像处理和计算机视觉技术,实时检测视频流中的身份证,并提取身份证区域
|
|
30
34
|
* 注意:当前实现是简化版,实际项目中建议使用OpenCV.js进行更精确的检测
|
|
31
|
-
*
|
|
35
|
+
*
|
|
32
36
|
* @example
|
|
33
37
|
* ```typescript
|
|
34
38
|
* // 创建身份证检测器
|
|
@@ -39,47 +43,49 @@ export interface IDCardDetectorOptions {
|
|
|
39
43
|
* processIDCardImage(result.croppedImage);
|
|
40
44
|
* }
|
|
41
45
|
* });
|
|
42
|
-
*
|
|
46
|
+
*
|
|
43
47
|
* // 启动检测
|
|
44
48
|
* const videoElement = document.getElementById('video') as HTMLVideoElement;
|
|
45
49
|
* await detector.start(videoElement);
|
|
46
|
-
*
|
|
50
|
+
*
|
|
47
51
|
* // 停止检测
|
|
48
52
|
* detector.stop();
|
|
49
53
|
* ```
|
|
50
54
|
*/
|
|
51
55
|
export class IDCardDetector implements Disposable {
|
|
52
|
-
private camera: Camera
|
|
53
|
-
private detecting = false
|
|
54
|
-
private detectTimer: number | null = null
|
|
55
|
-
private onDetected?: (result: DetectionResult) => void
|
|
56
|
-
private onError?: (error: Error) => void
|
|
57
|
-
private detectionInterval: number
|
|
58
|
-
private maxImageDimension: number
|
|
59
|
-
private resultCache: LRUCache<string, DetectionResult
|
|
60
|
-
private throttledDetect: ReturnType<typeof throttle
|
|
61
|
-
private frameCount: number = 0
|
|
62
|
-
private lastDetectionTime: number = 0
|
|
63
|
-
private options: IDCardDetectorOptions
|
|
64
|
-
|
|
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
|
+
|
|
65
69
|
/**
|
|
66
70
|
* 创建身份证检测器实例
|
|
67
|
-
*
|
|
71
|
+
*
|
|
68
72
|
* @param options 身份证检测器配置选项,或者检测回调函数
|
|
69
73
|
*/
|
|
70
|
-
constructor(
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
+
constructor(
|
|
75
|
+
options?: IDCardDetectorOptions | ((result: DetectionResult) => void)
|
|
76
|
+
) {
|
|
77
|
+
this.camera = new Camera()
|
|
78
|
+
|
|
79
|
+
if (typeof options === "function") {
|
|
74
80
|
// 兼容旧的构造函数方式
|
|
75
|
-
this.onDetected = options
|
|
81
|
+
this.onDetected = options
|
|
76
82
|
this.options = {
|
|
77
83
|
detectionInterval: 200,
|
|
78
84
|
maxImageDimension: 800,
|
|
79
85
|
enableCache: true,
|
|
80
86
|
cacheSize: 20,
|
|
81
|
-
logger: console.log
|
|
82
|
-
}
|
|
87
|
+
logger: console.log,
|
|
88
|
+
}
|
|
83
89
|
} else if (options) {
|
|
84
90
|
// 使用新的选项对象方式
|
|
85
91
|
this.options = {
|
|
@@ -88,247 +94,270 @@ export class IDCardDetector implements Disposable {
|
|
|
88
94
|
enableCache: true,
|
|
89
95
|
cacheSize: 20,
|
|
90
96
|
logger: console.log,
|
|
91
|
-
...options
|
|
92
|
-
}
|
|
93
|
-
this.onDetected = options.onDetection
|
|
94
|
-
this.onError = options.onError
|
|
97
|
+
...options,
|
|
98
|
+
}
|
|
99
|
+
this.onDetected = options.onDetection
|
|
100
|
+
this.onError = options.onError
|
|
95
101
|
} else {
|
|
96
102
|
this.options = {
|
|
97
103
|
detectionInterval: 200,
|
|
98
104
|
maxImageDimension: 800,
|
|
99
105
|
enableCache: true,
|
|
100
106
|
cacheSize: 20,
|
|
101
|
-
logger: console.log
|
|
102
|
-
}
|
|
107
|
+
logger: console.log,
|
|
108
|
+
}
|
|
103
109
|
}
|
|
104
|
-
|
|
105
|
-
this.detectionInterval = this.options.detectionInterval
|
|
106
|
-
this.maxImageDimension = this.options.maxImageDimension
|
|
107
|
-
|
|
110
|
+
|
|
111
|
+
this.detectionInterval = this.options.detectionInterval!
|
|
112
|
+
this.maxImageDimension = this.options.maxImageDimension!
|
|
113
|
+
|
|
108
114
|
// 初始化结果缓存
|
|
109
|
-
this.resultCache = new LRUCache<string, DetectionResult>(
|
|
110
|
-
|
|
115
|
+
this.resultCache = new LRUCache<string, DetectionResult>(
|
|
116
|
+
this.options.cacheSize
|
|
117
|
+
)
|
|
118
|
+
|
|
111
119
|
// 创建节流版本的检测函数
|
|
112
|
-
this.throttledDetect = throttle(
|
|
120
|
+
this.throttledDetect = throttle(
|
|
121
|
+
this.performDetection.bind(this),
|
|
122
|
+
this.detectionInterval
|
|
123
|
+
)
|
|
113
124
|
}
|
|
114
|
-
|
|
125
|
+
|
|
115
126
|
/**
|
|
116
127
|
* 启动身份证检测
|
|
117
|
-
*
|
|
128
|
+
*
|
|
118
129
|
* 初始化相机并开始连续检测视频帧中的身份证
|
|
119
|
-
*
|
|
130
|
+
*
|
|
120
131
|
* @param {HTMLVideoElement} videoElement - 用于显示相机画面的video元素
|
|
121
132
|
* @returns {Promise<void>} 启动完成的Promise
|
|
122
133
|
*/
|
|
123
134
|
async start(videoElement: HTMLVideoElement): Promise<void> {
|
|
124
|
-
await this.camera.initialize(videoElement)
|
|
125
|
-
this.detecting = true
|
|
126
|
-
this.frameCount = 0
|
|
127
|
-
this.lastDetectionTime = 0
|
|
128
|
-
this.detect()
|
|
135
|
+
await this.camera.initialize(videoElement)
|
|
136
|
+
this.detecting = true
|
|
137
|
+
this.frameCount = 0
|
|
138
|
+
this.lastDetectionTime = 0
|
|
139
|
+
this.detect()
|
|
129
140
|
}
|
|
130
|
-
|
|
141
|
+
|
|
131
142
|
/**
|
|
132
143
|
* 停止身份证检测
|
|
133
144
|
*/
|
|
134
145
|
stop(): void {
|
|
135
|
-
this.detecting = false
|
|
146
|
+
this.detecting = false
|
|
136
147
|
if (this.detectTimer !== null) {
|
|
137
|
-
cancelAnimationFrame(this.detectTimer)
|
|
138
|
-
this.detectTimer = null
|
|
148
|
+
cancelAnimationFrame(this.detectTimer)
|
|
149
|
+
this.detectTimer = null
|
|
139
150
|
}
|
|
140
151
|
}
|
|
141
|
-
|
|
152
|
+
|
|
142
153
|
/**
|
|
143
154
|
* 持续检测视频帧
|
|
144
|
-
*
|
|
155
|
+
*
|
|
145
156
|
* @private
|
|
146
157
|
*/
|
|
147
158
|
private detect(): void {
|
|
148
|
-
if (!this.detecting) return
|
|
149
|
-
|
|
159
|
+
if (!this.detecting) return
|
|
160
|
+
|
|
150
161
|
this.detectTimer = requestAnimationFrame(() => {
|
|
151
162
|
try {
|
|
152
|
-
this.frameCount
|
|
153
|
-
const now = performance.now()
|
|
154
|
-
|
|
163
|
+
this.frameCount++
|
|
164
|
+
const now = performance.now()
|
|
165
|
+
|
|
155
166
|
// 帧率控制 - 只有满足时间间隔的帧才进行检测
|
|
156
167
|
// 这样可以显著减少CPU使用率,同时保持良好的用户体验
|
|
157
|
-
if (
|
|
158
|
-
this.
|
|
159
|
-
this.lastDetectionTime
|
|
168
|
+
if (
|
|
169
|
+
this.frameCount % 3 === 0 ||
|
|
170
|
+
now - this.lastDetectionTime >= this.detectionInterval
|
|
171
|
+
) {
|
|
172
|
+
this.throttledDetect()
|
|
173
|
+
this.lastDetectionTime = now
|
|
160
174
|
}
|
|
161
|
-
|
|
175
|
+
|
|
162
176
|
// 继续下一帧检测
|
|
163
|
-
this.detect()
|
|
177
|
+
this.detect()
|
|
164
178
|
} catch (error) {
|
|
165
179
|
if (this.onError) {
|
|
166
|
-
this.onError(error as Error)
|
|
180
|
+
this.onError(error as Error)
|
|
167
181
|
} else {
|
|
168
|
-
console.error(
|
|
182
|
+
console.error("身份证检测错误:", error)
|
|
169
183
|
}
|
|
170
|
-
|
|
184
|
+
|
|
171
185
|
// 出错后延迟重试
|
|
172
186
|
setTimeout(() => {
|
|
173
187
|
if (this.detecting) {
|
|
174
|
-
this.detect()
|
|
188
|
+
this.detect()
|
|
175
189
|
}
|
|
176
|
-
}, 1000)
|
|
190
|
+
}, 1000)
|
|
177
191
|
}
|
|
178
|
-
})
|
|
192
|
+
})
|
|
179
193
|
}
|
|
180
|
-
|
|
194
|
+
|
|
181
195
|
/**
|
|
182
196
|
* 执行单帧检测
|
|
183
|
-
*
|
|
197
|
+
*
|
|
184
198
|
* @private
|
|
185
199
|
*/
|
|
186
200
|
private async performDetection(): Promise<void> {
|
|
187
|
-
if (!this.detecting || !this.camera) return
|
|
188
|
-
|
|
201
|
+
if (!this.detecting || !this.camera) return
|
|
202
|
+
|
|
189
203
|
// 获取当前视频帧
|
|
190
|
-
const frame = this.camera.captureFrame()
|
|
191
|
-
if (!frame) return
|
|
192
|
-
|
|
204
|
+
const frame = this.camera.captureFrame()
|
|
205
|
+
if (!frame) return
|
|
206
|
+
|
|
193
207
|
// 检查缓存
|
|
194
208
|
if (this.options.enableCache) {
|
|
195
|
-
const fingerprint = calculateImageFingerprint(frame, 16)
|
|
196
|
-
const cachedResult = this.resultCache.get(fingerprint)
|
|
197
|
-
|
|
209
|
+
const fingerprint = calculateImageFingerprint(frame, 16) // 使用更大的尺寸提高特征区分度
|
|
210
|
+
const cachedResult = this.resultCache.get(fingerprint)
|
|
211
|
+
|
|
198
212
|
if (cachedResult) {
|
|
199
|
-
this.options.logger?.(
|
|
200
|
-
|
|
213
|
+
this.options.logger?.("使用缓存的检测结果")
|
|
214
|
+
|
|
201
215
|
// 使用缓存结果,但更新图像数据以确保最新
|
|
202
216
|
const updatedResult = {
|
|
203
217
|
...cachedResult,
|
|
204
|
-
imageData: frame
|
|
205
|
-
}
|
|
206
|
-
|
|
218
|
+
imageData: frame,
|
|
219
|
+
}
|
|
220
|
+
|
|
207
221
|
if (this.onDetected) {
|
|
208
|
-
this.onDetected(updatedResult)
|
|
222
|
+
this.onDetected(updatedResult)
|
|
209
223
|
}
|
|
210
|
-
return
|
|
224
|
+
return
|
|
211
225
|
}
|
|
212
226
|
}
|
|
213
|
-
|
|
227
|
+
|
|
214
228
|
// 降低分辨率以提高性能
|
|
215
|
-
const downsampledFrame = ImageProcessor.
|
|
216
|
-
|
|
229
|
+
const downsampledFrame = ImageProcessor.resizeImage(
|
|
230
|
+
frame,
|
|
231
|
+
this.maxImageDimension,
|
|
232
|
+
this.maxImageDimension
|
|
233
|
+
)
|
|
234
|
+
|
|
217
235
|
try {
|
|
218
236
|
// 检测身份证
|
|
219
|
-
const result = await this.detectIDCard(downsampledFrame)
|
|
220
|
-
|
|
237
|
+
const result = await this.detectIDCard(downsampledFrame)
|
|
238
|
+
|
|
221
239
|
// 如果检测成功,将原始图像添加到结果中
|
|
222
240
|
if (result.success) {
|
|
223
|
-
result.imageData = frame
|
|
224
|
-
|
|
241
|
+
result.imageData = frame
|
|
242
|
+
|
|
225
243
|
// 缓存结果
|
|
226
244
|
if (this.options.enableCache) {
|
|
227
|
-
const fingerprint = calculateImageFingerprint(frame, 16)
|
|
228
|
-
this.resultCache.set(fingerprint, result)
|
|
245
|
+
const fingerprint = calculateImageFingerprint(frame, 16)
|
|
246
|
+
this.resultCache.set(fingerprint, result)
|
|
229
247
|
}
|
|
230
248
|
}
|
|
231
|
-
|
|
249
|
+
|
|
232
250
|
// 处理检测结果
|
|
233
251
|
if (this.onDetected) {
|
|
234
|
-
this.onDetected(result)
|
|
252
|
+
this.onDetected(result)
|
|
235
253
|
}
|
|
236
254
|
} catch (error) {
|
|
237
255
|
if (this.onError) {
|
|
238
|
-
this.onError(error as Error)
|
|
256
|
+
this.onError(error as Error)
|
|
239
257
|
} else {
|
|
240
|
-
console.error(
|
|
258
|
+
console.error("身份证检测错误:", error)
|
|
241
259
|
}
|
|
242
260
|
}
|
|
243
261
|
}
|
|
244
|
-
|
|
262
|
+
|
|
245
263
|
/**
|
|
246
264
|
* 检测图像中的身份证
|
|
247
|
-
*
|
|
265
|
+
*
|
|
248
266
|
* @private
|
|
249
267
|
* @param {ImageData} imageData - 要分析的图像数据
|
|
250
268
|
* @returns {Promise<DetectionResult>} 检测结果
|
|
251
269
|
*/
|
|
252
270
|
private async detectIDCard(imageData: ImageData): Promise<DetectionResult> {
|
|
253
271
|
// 1. 图像预处理
|
|
254
|
-
const grayscale = ImageProcessor.toGrayscale(imageData)
|
|
255
|
-
|
|
272
|
+
const grayscale = ImageProcessor.toGrayscale(imageData)
|
|
273
|
+
|
|
256
274
|
// 2. 检测矩形和边缘(简化版实现)
|
|
257
275
|
// 注意:实际应用中应使用OpenCV.js或其他计算机视觉库进行更精确的检测
|
|
258
276
|
// 此处仅作为概念性实现,使用基本矩形检测逻辑
|
|
259
|
-
|
|
277
|
+
|
|
260
278
|
// 模拟检测过程,随机判断是否找到身份证
|
|
261
279
|
// 在实际应用中,此处应当实现实际的计算机视觉算法
|
|
262
280
|
const detectionResult: DetectionResult = {
|
|
263
281
|
success: Math.random() > 0.3, // 70%的概率成功检测到
|
|
264
|
-
message:
|
|
265
|
-
}
|
|
266
|
-
|
|
282
|
+
message: "身份证检测完成",
|
|
283
|
+
}
|
|
284
|
+
|
|
267
285
|
if (detectionResult.success) {
|
|
268
286
|
// 模拟一个身份证矩形区域
|
|
269
|
-
const width = imageData.width
|
|
270
|
-
const height = imageData.height
|
|
271
|
-
|
|
287
|
+
const width = imageData.width
|
|
288
|
+
const height = imageData.height
|
|
289
|
+
|
|
272
290
|
// 大致的身份证区域(按比例)
|
|
273
|
-
const rectWidth = Math.round(width * 0.7)
|
|
274
|
-
const rectHeight = Math.round(rectWidth * 0.618)
|
|
275
|
-
const rectX = Math.round((width - rectWidth) / 2)
|
|
276
|
-
const rectY = Math.round((height - rectHeight) / 2)
|
|
277
|
-
|
|
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
|
+
|
|
278
296
|
// 添加四个角点
|
|
279
297
|
detectionResult.corners = [
|
|
280
298
|
{ x: rectX, y: rectY },
|
|
281
299
|
{ x: rectX + rectWidth, y: rectY },
|
|
282
300
|
{ x: rectX + rectWidth, y: rectY + rectHeight },
|
|
283
|
-
{ x: rectX, y: rectY + rectHeight }
|
|
284
|
-
]
|
|
285
|
-
|
|
301
|
+
{ x: rectX, y: rectY + rectHeight },
|
|
302
|
+
]
|
|
303
|
+
|
|
286
304
|
// 添加边界框
|
|
287
305
|
detectionResult.boundingBox = {
|
|
288
306
|
x: rectX,
|
|
289
307
|
y: rectY,
|
|
290
308
|
width: rectWidth,
|
|
291
|
-
height: rectHeight
|
|
292
|
-
}
|
|
293
|
-
|
|
309
|
+
height: rectHeight,
|
|
310
|
+
}
|
|
311
|
+
|
|
294
312
|
// 裁剪身份证图像
|
|
295
|
-
const canvas = document.createElement(
|
|
296
|
-
canvas.width = rectWidth
|
|
297
|
-
canvas.height = rectHeight
|
|
298
|
-
const ctx = canvas.getContext(
|
|
299
|
-
|
|
313
|
+
const canvas = document.createElement("canvas")
|
|
314
|
+
canvas.width = rectWidth
|
|
315
|
+
canvas.height = rectHeight
|
|
316
|
+
const ctx = canvas.getContext("2d")
|
|
317
|
+
|
|
300
318
|
if (ctx) {
|
|
301
|
-
const tempCanvas = ImageProcessor.imageDataToCanvas(imageData)
|
|
319
|
+
const tempCanvas = ImageProcessor.imageDataToCanvas(imageData)
|
|
302
320
|
ctx.drawImage(
|
|
303
321
|
tempCanvas,
|
|
304
|
-
rectX,
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
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
|
+
)
|
|
309
338
|
}
|
|
310
|
-
|
|
339
|
+
|
|
311
340
|
// 设置置信度
|
|
312
|
-
detectionResult.confidence = 0.7 + Math.random() * 0.3
|
|
341
|
+
detectionResult.confidence = 0.7 + Math.random() * 0.3
|
|
313
342
|
}
|
|
314
|
-
|
|
315
|
-
return detectionResult
|
|
343
|
+
|
|
344
|
+
return detectionResult
|
|
316
345
|
}
|
|
317
|
-
|
|
346
|
+
|
|
318
347
|
/**
|
|
319
348
|
* 清除检测结果缓存
|
|
320
349
|
*/
|
|
321
350
|
clearCache(): void {
|
|
322
|
-
this.resultCache.clear()
|
|
323
|
-
this.options.logger?.(
|
|
351
|
+
this.resultCache.clear()
|
|
352
|
+
this.options.logger?.("检测结果缓存已清除")
|
|
324
353
|
}
|
|
325
|
-
|
|
354
|
+
|
|
326
355
|
/**
|
|
327
356
|
* 释放资源
|
|
328
357
|
*/
|
|
329
358
|
dispose(): void {
|
|
330
|
-
this.stop()
|
|
331
|
-
this.camera.release()
|
|
332
|
-
this.resultCache.clear()
|
|
359
|
+
this.stop()
|
|
360
|
+
this.camera.release()
|
|
361
|
+
this.resultCache.clear()
|
|
333
362
|
}
|
|
334
|
-
}
|
|
363
|
+
}
|