From 6eee922b7e265ed1b6ddbf5f5790206a59d718a3 Mon Sep 17 00:00:00 2001 From: leon <916117771@qq.com> Date: Mon, 13 Apr 2026 15:02:57 +0800 Subject: [PATCH] 1 --- docs/arc_plugins.md | 498 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 498 insertions(+) create mode 100644 docs/arc_plugins.md diff --git a/docs/arc_plugins.md b/docs/arc_plugins.md new file mode 100644 index 0000000..f09ad3b --- /dev/null +++ b/docs/arc_plugins.md @@ -0,0 +1,498 @@ +# Arc Flutter 插件使用指南 + +## 简介 + +Arc 是一个封装虹软 (ArcSoft) Face SDK 的 Flutter 插件,提供 Android 平台的人脸检测、人脸识别、活体检测功能。本插件支持 1:1 人脸比对和 1:N 人脸搜索两种模式。 + +## 安装 + +### 1. 添加依赖 + +在您的 Flutter 项目 `pubspec.yaml` 中添加依赖: + +```yaml +dependencies: + arc: + path: ../arc # 本地引用,或使用 git/path 方式 +``` + +### 2. Android 配置 + +在 `android/app/build.gradle` 中确保最小 SDK 版本: + +```gradle +android { + defaultConfig { + minSdkVersion 21 // 虹软 SDK 要求最低 Android 5.0 + } +} +``` + +### 3. 获取虹软 SDK 密钥 + +访问 [虹软开放平台](https://ai.arcsoft.com.cn/) 注册账号,创建应用获取: +- `appId`: 应用 ID +- `sdkKey`: SDK 密钥 +- `activeKey`: 激活密钥 + +## 快速开始 + +### 基础流程 + +``` +激活 SDK → 初始化引擎 → 人脸检测 → 特征提取 → 特征比对/注册 +``` + +### 示例代码 + +```dart +import 'package:arc/arc.dart'; + +final _arc = Arc(); + +// 1. 激活 SDK(必须首先执行) +await _arc.activeOnline( + appId: '您的AppId', + sdkKey: '您的SdkKey', + activeKey: '您的ActiveKey', +); + +// 2. 初始化引擎 +await _arc.init( + detectMode: 0, // 0=视频流模式, 1=图像模式 + orient: 0, // 检测角度 + maxFaceNum: 1, // 最大检测人脸数 + combinedMask: 0x9D, // 功能组合掩码 +); + +// 3. 人脸检测(需要摄像头 NV21 数据) +final result = await _arc.detectFaces( + data: nv21Data, + width: width, + height: height, +); + +// 4. 提取特征 +final featureResult = await _arc.extractFaceFeature( + data: nv21Data, + width: width, + height: height, + rectLeft: faceInfo['rectLeft'], + rectTop: faceInfo['rectTop'], + rectRight: faceInfo['rectRight'], + rectBottom: faceInfo['rectBottom'], + faceData: faceInfo['faceData'], // 重要!必须传递 +); + +// 5. 比对特征 +final compareResult = await _arc.compareFaceFeature( + featureData1: feature1, + featureData2: feature2, +); +``` + +## API 详细说明 + +### activeOnline - SDK 激活 + +在线激活虹软 SDK,必须在使用其他功能前完成。 + +```dart +Future?> activeOnline({ + required String appId, // 虹软应用 ID + required String sdkKey, // SDK 密钥 + required String activeKey, // 激活密钥 +}) +``` + +**返回值:** +| 字段 | 类型 | 说明 | +|------|------|------| +| `success` | bool | 是否成功 | +| `errorCode` | int | 错误码(0=成功) | +| `message` | String | 结果描述 | + +--- + +### init - 初始化引擎 + +初始化人脸识别引擎,配置检测模式和功能。 + +```dart +Future?> init({ + int? detectMode, // 检测模式 + int? orient, // 检测角度 + int? maxFaceNum, // 最大人脸数 + int? combinedMask, // 功能掩码组合 +}) +``` + +**参数说明:** + +| 参数 | 值 | 说明 | +|------|------|------| +| detectMode | 0 | VIDEO 模式(视频流,适合实时检测) | +| detectMode | 1 | IMAGE 模式(单张图片) | +| orient | 0/90/180/270/360 | 检测角度优先级 | +| maxFaceNum | 1-50 | 同时检测的最大人脸数量 | + +**功能掩码组合:** + +| 功能 | 值 | 说明 | +|------|------|------| +| ASF_FACE_DETECT | 0x00000001 | 人脸检测 | +| ASF_FACE_RECOGNITION | 0x00000004 | 人脸识别 | +| ASF_AGE | 0x00000008 | 年龄检测 | +| ASF_GENDER | 0x00000010 | 性别检测 | +| ASF_LIVENESS | 0x00000080 | RGB 活体检测 | + +**推荐组合:** +```dart +combinedMask: 0x9D // 人脸检测 + 识别 + 年龄 + 性别 + 活体 +// 计算方式: 0x01 | 0x04 | 0x08 | 0x10 | 0x80 = 0x9D +``` + +--- + +### detectFaces - 人脸检测 + +检测图像中的人脸,同时进行 RGB 活体检测。 + +```dart +Future?> detectFaces({ + required Uint8List data, // NV21 图像数据 + required int width, // 图像宽度 + required int height, // 图像高度 + int format = 2050, // 图像格式(默认 NV21) +}) +``` + +**返回值:** + +| 字段 | 类型 | 说明 | +|------|------|------| +| `success` | bool | 是否检测成功 | +| `errorCode` | int | 错误码 | +| `faceList` | List | 检测到的人脸列表 | +| `rgbLiveness` | int | RGB 活体结果(-1=未知, 0=非真人, 1=真人) | +| `isRgbAlive` | bool | 是否真人 | + +**faceList 每项包含:** + +| 字段 | 类型 | 说明 | +|------|------|------| +| `rectLeft` | int | 人脸框左边界 | +| `rectTop` | int | 人脸框上边界 | +| `rectRight` | int | 人脸框右边界 | +| `rectBottom` | int | 人脸框下边界 | +| `faceOrientation` | int | 人脸角度 | +| `faceId` | int | 人脸 ID | +| `faceData` | Uint8List | **重要!特征提取必需的数据** | + +--- + +### extractFaceFeature - 特征提取 + +从检测到的人脸中提取 512 字节的特征数据。 + +```dart +Future?> extractFaceFeature({ + required Uint8List data, // NV21 图像数据 + required int width, // 图像宽度 + required int height, // 图像高度 + required int rectLeft, // 人脸框左边界(从 detectFaces 获取) + required int rectTop, // 人脸框上边界 + required int rectRight, // 人脸框右边界 + required int rectBottom, // 人脸框下边界 + int format = 2050, // 图像格式 + int faceOrientation = 0, // 人脸角度(从 detectFaces 获取) + int faceId = -1, // 人脸 ID + Uint8List? faceData, // **关键:人脸数据(从 detectFaces 获取)** + int extractType = 1, // 0=注册模式, 1=识别模式 + int mask = 0, // 口罩状态 +}) +``` + +**参数说明:** + +| 参数 | 值 | 说明 | +|------|------|------| +| extractType | 0 | REGISTER 模式(用于注册到人脸库) | +| extractType | 1 | RECOGNIZE 模式(用于比对验证) | +| mask | 0 | 未佩戴口罩 | +| mask | 1 | 已佩戴口罩 | + +**返回值:** + +| 字段 | 类型 | 说明 | +|------|------|------| +| `success` | bool | 是否成功 | +| `errorCode` | int | 错误码 | +| `featureData` | Uint8List | 512 字节特征数据 | + +--- + +### compareFaceFeature - 特征比对 (1:1) + +比对两个人脸特征的相似度。 + +```dart +Future?> compareFaceFeature({ + required Uint8List featureData1, // 第一个特征 + required Uint8List featureData2, // 第二个特征 + int compareModel = 0, // 比对模型 +}) +``` + +**compareModel 参数:** + +| 值 | 说明 | 推荐阈值 | +|------|------|------| +| 0 | 生活照模型 | 0.8 | +| 1 | 证件照模型 | 0.82 | + +**返回值:** + +| 字段 | 类型 | 说明 | +|------|------|------| +| `success` | bool | 是否成功 | +| `similarity` | double | 相似度(0-1) | + +--- + +### registerFaceFeature - 注册到人脸库 (1:N) + +将人脸特征注册到本地人脸库,用于后续 1:N 搜索。 + +```dart +Future?> registerFaceFeature({ + required int searchId, // 唯一标识符(建议使用用户 ID) + required Uint8List featureData, // 特征数据 + String? faceTag, // 附属信息(可选) +}) +``` + +--- + +### registerFaceFeatureBatch - 批量注册 + +批量注册多张人脸特征。 + +```dart +Future?> registerFaceFeatureBatch({ + required List> faceList, +}) + +// 示例: +await _arc.registerFaceFeatureBatch( + faceList: [ + {'searchId': 1, 'featureData': feature1, 'faceTag': '张三'}, + {'searchId': 2, 'featureData': feature2, 'faceTag': '李四'}, + ], +); +``` + +## 图像格式要求 + +### NV21 格式 + +- 虹软 SDK 使用 NV21 格式(Android 摄像头默认格式) +- 格式代码:`2050` +- 宽度必须是 **4 的倍数** +- 高度必须是 **2 的倍数** + +### 从 Camera 提取 NV21 + +使用 `camera` 插件获取 NV21 数据: + +```dart +// 配置摄像头使用 NV21 格式 +_cameraController = CameraController( + camera, + ResolutionPreset.medium, + enableAudio: false, + imageFormatGroup: ImageFormatGroup.nv21, // 关键配置 +); + +// 处理图像流 +void _onImageAvailable(CameraImage image) { + final nv21Data = _extractNV21(image, image.width, image.height); + + // 人脸检测 + final result = await _arc.detectFaces( + data: nv21Data, + width: image.width, + height: image.height, + ); +} + +// NV21 数据提取函数 +Uint8List _extractNV21(CameraImage image, int width, int height) { + final ySize = width * height; + final nv21Size = ySize * 3 ~/ 2; + + // ... 根据 planes 结构提取数据 + // 参考 example/lib/main.dart 中的完整实现 +} +``` + +## 推荐阈值 + +| 功能 | 阈值 | 说明 | +|------|------|------| +| 人脸比对(生活照) | 0.8 | 相似度 >= 0.8 认为匹配 | +| 人脸比对(证件照) | 0.82 | 相似度 >= 0.82 认为匹配 | +| RGB 活体检测 | 0.5 | 活体分数 >= 0.5 认为真人 | +| IR 活体检测 | 0.5 | 活体分数 >= 0.5 认为真人 | + +## 完整使用流程示例 + +### 1:1 人脸验证 + +```dart +// 1. 激活 SDK +final activeResult = await _arc.activeOnline( + appId: appId, + sdkKey: sdkKey, + activeKey: activeKey, +); +if (activeResult?['success'] != true) { + print('激活失败'); + return; +} + +// 2. 初始化引擎 +final initResult = await _arc.init( + detectMode: 0, + orient: 0, + maxFaceNum: 1, + combinedMask: 0x9D, +); + +// 3. 摄像头获取图像 +// 使用 camera 插件获取 NV21 数据... + +// 4. 人脸检测 +final detectResult = await _arc.detectFaces( + data: nv21Data, + width: width, + height: height, +); + +if (detectResult?['success'] == true) { + final faceList = detectResult!['faceList'] as List; + + if (faceList.isNotEmpty) { + final faceInfo = faceList[0] as Map; + final rgbLiveness = detectResult['rgbLiveness'] as int; + + // 检查活体 + if (rgbLiveness != 1) { + print('非真人'); + return; + } + + // 5. 提取特征 + final featureResult = await _arc.extractFaceFeature( + data: nv21Data, + width: width, + height: height, + rectLeft: faceInfo['rectLeft'], + rectTop: faceInfo['rectTop'], + rectRight: faceInfo['rectRight'], + rectBottom: faceInfo['rectBottom'], + faceData: faceInfo['faceData'], // 重要! + extractType: 1, // 识别模式 + ); + + if (featureResult?['success'] == true) { + final currentFeature = featureResult!['featureData'] as Uint8List; + + // 6. 比对(与已存储的特征) + final compareResult = await _arc.compareFaceFeature( + featureData1: currentFeature, + featureData2: storedFeature, + compareModel: 0, + ); + + final similarity = compareResult?['similarity'] as double ?? 0.0; + if (similarity >= 0.8) { + print('验证通过,相似度: ${similarity}'); + } else { + print('验证失败,相似度: ${similarity}'); + } + } + } +} +``` + +### 1:N 人脸搜索 + +```dart +// 注册阶段 +// 提取特征(注册模式) +final registerFeature = await _arc.extractFaceFeature( + data: nv21Data, + width: width, + height: height, + rectLeft: faceInfo['rectLeft'], + rectTop: faceInfo['rectTop'], + rectRight: faceInfo['rectRight'], + rectBottom: faceInfo['rectBottom'], + faceData: faceInfo['faceData'], + extractType: 0, // 注册模式 +); + +// 注册到人脸库 +await _arc.registerFaceFeature( + searchId: userId, // 如: 10001 + featureData: registerFeature!['featureData'], + faceTag: '张三', +); + +// 搜索阶段(SDK 会自动搜索匹配) +// 使用 extractType=1 提取特征后,SDK 会自动进行 1:N 搜索 +``` + +## 错误处理 + +所有 API 返回统一的错误格式: + +```dart +{ + 'success': false, + 'errorCode': 81929, // 具体错误码 + 'message': '特征提取失败', +} +``` + +常见错误码: +- `0`: 成功 +- `81929`: 特征提取失败(通常是因为未传递 faceData) +- `其他`: 参考 `android/src/.../FaceErrorCode.java` 中的 586 个错误码定义 + +## 注意事项 + +1. **必须先激活再初始化**:使用顺序为 `activeOnline` → `init` → 其他功能 +2. **faceData 必须传递**:`extractFaceFeature` 的 `faceData` 参数是从 `detectFaces` 获取的关键数据,不传递会导致特征提取失败 +3. **图像尺寸限制**:宽度必须为 4 的倍数,高度必须为 2 的倍数 +4. **单设备激活**:虹软 SDK 激活与设备绑定,同一 AppId 在不同设备上需要重新激活 +5. **特征存储**:特征数据为 512 字节,建议使用 Base64 编码后存储 + +## 依赖插件推荐 + +实现完整人脸识别功能通常需要配合: + +```yaml +dependencies: + arc: ^0.0.1 # 人脸识别 + camera: ^0.11.0 # 摄像头访问 + shared_preferences: ^2.0.0 # 特征存储 +``` + +## 参考资源 + +- [虹软开放平台](https://ai.arcsoft.com.cn/) +- [虹软人脸识别 SDK 文档](https://ai.arcsoft.com.cn/manual/) +- 本插件示例代码:`example/lib/main.dart` +- 虹软接口文档:`docs/虹软人脸识别接口文档.md` \ No newline at end of file