id-scanner-lib
Version:
一款纯前端实现的TypeScript身份证&二维码识别库,无需后端支持,所有处理在浏览器端完成,新增图像批处理与优化
318 lines (276 loc) • 9.04 kB
text/typescript
/**
* @file 身份证防伪检测模块
* @description 提供身份证防伪特征识别功能,区分真假身份证
* @module AntiFakeDetector
*/
import { ImageProcessor } from "../utils/image-processing"
import { LRUCache, calculateImageFingerprint } from "../utils/performance"
import { Disposable } from "../utils/resource-manager"
/**
* 防伪检测结果
*/
export interface AntiFakeDetectionResult {
isAuthentic: boolean // 是否为真实身份证
confidence: number // 置信度(0-1)
detectedFeatures: string[] // 检测到的防伪特征
message: string // 结果描述
processingTime?: number // 处理时间(ms)
}
/**
* 防伪检测器配置选项
*/
export interface AntiFakeDetectorOptions {
sensitivity?: number // 敏感度 (0-1),值越高越严格
enableCache?: boolean // 是否启用缓存
cacheSize?: number // 缓存大小
logger?: (message: any) => void // 日志记录器
}
/**
* 身份证防伪特征检测器
*
* 基于图像分析技术检测身份证中的多种防伪特征,包括:
* 1. 荧光油墨特征
* 2. 微缩文字
* 3. 光变图案
* 4. 雕刻凹印
* 5. 隐形图案
*
* @example
* ```typescript
* // 创建防伪检测器
* const antiFakeDetector = new AntiFakeDetector({
* sensitivity: 0.8,
* enableCache: true
* });
*
* // 分析身份证图像
* const imageData = await ImageProcessor.createImageDataFromFile(idCardFile);
* const result = await antiFakeDetector.detect(imageData);
*
* if (result.isAuthentic) {
* console.log('身份证真实,检测到防伪特征:', result.detectedFeatures);
* } else {
* console.log('警告!', result.message);
* }
* ```
*/
export class AntiFakeDetector implements Disposable {
private options: Required<AntiFakeDetectorOptions>
private resultCache: LRUCache<string, AntiFakeDetectionResult>
/**
* 创建身份证防伪检测器实例
*
* @param options 防伪检测器配置
*/
constructor(options: AntiFakeDetectorOptions = {}) {
this.options = {
sensitivity: 0.7,
enableCache: true,
cacheSize: 50,
logger: console.log,
...options,
}
// 初始化缓存
this.resultCache = new LRUCache<string, AntiFakeDetectionResult>(
this.options.cacheSize
)
}
/**
* 检测身份证图像的防伪特征
*
* @param imageData 身份证图像数据
* @returns 防伪检测结果
*/
async detect(imageData: ImageData): Promise<AntiFakeDetectionResult> {
const startTime = performance.now()
// 检查缓存
if (this.options.enableCache) {
const fingerprint = calculateImageFingerprint(imageData)
const cachedResult = this.resultCache.get(fingerprint)
if (cachedResult) {
this.options.logger("使用缓存的防伪检测结果")
return cachedResult
}
}
// 图像预处理增强防伪特征
const enhancedImage = this.enhanceAntiFakeFeatures(imageData)
// 执行多种防伪特征检测
const featureResults = await Promise.all([
this.detectUVInkFeatures(enhancedImage),
this.detectMicroText(enhancedImage),
this.detectOpticalVariable(enhancedImage),
this.detectIntaglioPrinting(enhancedImage),
this.detectGhostImage(enhancedImage),
])
// 汇总检测结果
const detectedFeatures: string[] = []
let totalConfidence = 0
for (const [feature, detected, confidence] of featureResults) {
if (detected && confidence > 0.5) {
detectedFeatures.push(feature)
totalConfidence += confidence
}
}
// 计算最终结果
const normalizedConfidence =
featureResults.length > 0 ? totalConfidence / featureResults.length : 0
// 根据敏感度和检测到的特征决定是否通过验证
const isAuthentic =
normalizedConfidence >= this.options.sensitivity &&
detectedFeatures.length >= 2
// 生成结果消息
let message = isAuthentic
? `身份证真实,检测到${detectedFeatures.length}个防伪特征`
: detectedFeatures.length > 0
? `可疑身份证,仅检测到${detectedFeatures.length}个防伪特征,置信度不足`
: "未检测到有效防伪特征,可能为伪造证件"
const result: AntiFakeDetectionResult = {
isAuthentic,
confidence: normalizedConfidence,
detectedFeatures,
message,
processingTime: performance.now() - startTime,
}
// 缓存结果
if (this.options.enableCache) {
const fingerprint = calculateImageFingerprint(imageData)
this.resultCache.set(fingerprint, result)
}
return result
}
/**
* 增强身份证图像中的防伪特征
*
* @param imageData 原始图像数据
* @returns 增强后的图像数据
* @private
*/
private enhanceAntiFakeFeatures(imageData: ImageData): ImageData {
// 应用特定的图像处理增强防伪特征
return ImageProcessor.batchProcess(imageData, {
contrast: 30, // 增强对比度
brightness: 10, // 轻微提高亮度
sharpen: true, // 锐化图像突出细节
})
}
/**
* 检测荧光油墨特征
*
* @param imageData 图像数据
* @returns [特征名称, 是否检测到, 置信度]
* @private
*/
private async detectUVInkFeatures(
imageData: ImageData
): Promise<[string, boolean, number]> {
// 提取蓝色通道增强UV油墨可见度
const canvas = document.createElement("canvas")
canvas.width = imageData.width
canvas.height = imageData.height
const ctx = canvas.getContext("2d")
if (!ctx) {
return ["荧光油墨", false, 0]
}
ctx.putImageData(imageData, 0, 0)
// 分析蓝色通道中的特定模式
// 实际实现中应使用更复杂的算法提取UV特征
// 这里使用模拟实现
// 模拟检测: 70%的概率检测到,置信度0.65-0.95
const detected = Math.random() > 0.3
const confidence = detected ? 0.65 + Math.random() * 0.3 : 0
return ["荧光油墨", detected, confidence]
}
/**
* 检测微缩文字
*
* @param imageData 图像数据
* @returns [特征名称, 是否检测到, 置信度]
* @private
*/
private async detectMicroText(
imageData: ImageData
): Promise<[string, boolean, number]> {
// 应用边缘检测突出微缩文字
const grayscale = ImageProcessor.toGrayscale(
new ImageData(
new Uint8ClampedArray(imageData.data),
imageData.width,
imageData.height
)
)
// 寻找特定的微缩文字模式
// 实际实现中应使用计算机视觉算法寻找微小规则文字模式
// 这里使用模拟实现
// 模拟检测: 80%的概率检测到,置信度0.7-0.95
const detected = Math.random() > 0.2
const confidence = detected ? 0.7 + Math.random() * 0.25 : 0
return ["微缩文字", detected, confidence]
}
/**
* 检测光变图案
*
* @param imageData 图像数据
* @returns [特征名称, 是否检测到, 置信度]
* @private
*/
private async detectOpticalVariable(
imageData: ImageData
): Promise<[string, boolean, number]> {
// 提取特定区域并分析颜色变化
// 在实际实现中需要定位光变图案区域并分析其特征
// 这里使用模拟实现
// 模拟检测: 65%的概率检测到,置信度0.6-0.9
const detected = Math.random() > 0.35
const confidence = detected ? 0.6 + Math.random() * 0.3 : 0
return ["光变图案", detected, confidence]
}
/**
* 检测凹印雕刻特征
*
* @param imageData 图像数据
* @returns [特征名称, 是否检测到, 置信度]
* @private
*/
private async detectIntaglioPrinting(
imageData: ImageData
): Promise<[string, boolean, number]> {
// 使用特定滤镜增强凹印效果
// 在实际实现中应分析阴影和纹理模式
// 这里使用模拟实现
// 模拟检测: 75%的概率检测到,置信度0.65-0.9
const detected = Math.random() > 0.25
const confidence = detected ? 0.65 + Math.random() * 0.25 : 0
return ["雕刻凹印", detected, confidence]
}
/**
* 检测隐形图案(幽灵图像)
*
* @param imageData 图像数据
* @returns [特征名称, 是否检测到, 置信度]
* @private
*/
private async detectGhostImage(
imageData: ImageData
): Promise<[string, boolean, number]> {
// 调整对比度和亮度显现隐形图案
// 在实际实现中应使用特定滤镜和图像处理算法
// 这里使用模拟实现
// 模拟检测: 60%的概率检测到,置信度0.55-0.85
const detected = Math.random() > 0.4
const confidence = detected ? 0.55 + Math.random() * 0.3 : 0
return ["隐形图案", detected, confidence]
}
/**
* 清除结果缓存
*/
clearCache(): void {
this.resultCache.clear()
this.options.logger("防伪检测结果缓存已清除")
}
/**
* 释放资源
*/
dispose(): void {
this.resultCache.clear()
}
}