1
This commit is contained in:
498
docs/arc_plugins.md
Normal file
498
docs/arc_plugins.md
Normal file
@@ -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<Map<String, dynamic>?> activeOnline({
|
||||
required String appId, // 虹软应用 ID
|
||||
required String sdkKey, // SDK 密钥
|
||||
required String activeKey, // 激活密钥
|
||||
})
|
||||
```
|
||||
|
||||
**返回值:**
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| `success` | bool | 是否成功 |
|
||||
| `errorCode` | int | 错误码(0=成功) |
|
||||
| `message` | String | 结果描述 |
|
||||
|
||||
---
|
||||
|
||||
### init - 初始化引擎
|
||||
|
||||
初始化人脸识别引擎,配置检测模式和功能。
|
||||
|
||||
```dart
|
||||
Future<Map<String, dynamic>?> 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<Map<String, dynamic>?> detectFaces({
|
||||
required Uint8List data, // NV21 图像数据
|
||||
required int width, // 图像宽度
|
||||
required int height, // 图像高度
|
||||
int format = 2050, // 图像格式(默认 NV21)
|
||||
})
|
||||
```
|
||||
|
||||
**返回值:**
|
||||
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| `success` | bool | 是否检测成功 |
|
||||
| `errorCode` | int | 错误码 |
|
||||
| `faceList` | List<Map> | 检测到的人脸列表 |
|
||||
| `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<Map<String, dynamic>?> 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<Map<String, dynamic>?> 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<Map<String, dynamic>?> registerFaceFeature({
|
||||
required int searchId, // 唯一标识符(建议使用用户 ID)
|
||||
required Uint8List featureData, // 特征数据
|
||||
String? faceTag, // 附属信息(可选)
|
||||
})
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### registerFaceFeatureBatch - 批量注册
|
||||
|
||||
批量注册多张人脸特征。
|
||||
|
||||
```dart
|
||||
Future<Map<String, dynamic>?> registerFaceFeatureBatch({
|
||||
required List<Map<String, dynamic>> 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`
|
||||
Reference in New Issue
Block a user