13 KiB
13 KiB
Arc Flutter 插件使用指南
简介
Arc 是一个封装虹软 (ArcSoft) Face SDK 的 Flutter 插件,提供 Android 平台的人脸检测、人脸识别、活体检测功能。本插件支持 1:1 人脸比对和 1:N 人脸搜索两种模式。
安装
1. 添加依赖
在您的 Flutter 项目 pubspec.yaml 中添加依赖:
dependencies:
arc:
path: ../arc # 本地引用,或使用 git/path 方式
2. Android 配置
在 android/app/build.gradle 中确保最小 SDK 版本:
android {
defaultConfig {
minSdkVersion 21 // 虹软 SDK 要求最低 Android 5.0
}
}
3. 获取虹软 SDK 密钥
访问 虹软开放平台 注册账号,创建应用获取:
appId: 应用 IDsdkKey: SDK 密钥activeKey: 激活密钥
快速开始
基础流程
激活 SDK → 初始化引擎 → 人脸检测 → 特征提取 → 特征比对/注册
示例代码
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,必须在使用其他功能前完成。
Future<Map<String, dynamic>?> activeOnline({
required String appId, // 虹软应用 ID
required String sdkKey, // SDK 密钥
required String activeKey, // 激活密钥
})
返回值:
| 字段 | 类型 | 说明 |
|---|---|---|
success |
bool | 是否成功 |
errorCode |
int | 错误码(0=成功) |
message |
String | 结果描述 |
init - 初始化引擎
初始化人脸识别引擎,配置检测模式和功能。
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 活体检测 |
推荐组合:
combinedMask: 0x9D // 人脸检测 + 识别 + 年龄 + 性别 + 活体
// 计算方式: 0x01 | 0x04 | 0x08 | 0x10 | 0x80 = 0x9D
detectFaces - 人脸检测
检测图像中的人脸,同时进行 RGB 活体检测。
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 | 检测到的人脸列表 |
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 字节的特征数据。
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)
比对两个人脸特征的相似度。
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 搜索。
Future<Map<String, dynamic>?> registerFaceFeature({
required int searchId, // 唯一标识符(建议使用用户 ID)
required Uint8List featureData, // 特征数据
String? faceTag, // 附属信息(可选)
})
registerFaceFeatureBatch - 批量注册
批量注册多张人脸特征。
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 数据:
// 配置摄像头使用 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 人脸验证
// 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 人脸搜索
// 注册阶段
// 提取特征(注册模式)
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 返回统一的错误格式:
{
'success': false,
'errorCode': 81929, // 具体错误码
'message': '特征提取失败',
}
常见错误码:
0: 成功81929: 特征提取失败(通常是因为未传递 faceData)其他: 参考android/src/.../FaceErrorCode.java中的 586 个错误码定义
注意事项
- 必须先激活再初始化:使用顺序为
activeOnline→init→ 其他功能 - faceData 必须传递:
extractFaceFeature的faceData参数是从detectFaces获取的关键数据,不传递会导致特征提取失败 - 图像尺寸限制:宽度必须为 4 的倍数,高度必须为 2 的倍数
- 单设备激活:虹软 SDK 激活与设备绑定,同一 AppId 在不同设备上需要重新激活
- 特征存储:特征数据为 512 字节,建议使用 Base64 编码后存储
依赖插件推荐
实现完整人脸识别功能通常需要配合:
dependencies:
arc: ^0.0.1 # 人脸识别
camera: ^0.11.0 # 摄像头访问
shared_preferences: ^2.0.0 # 特征存储
参考资源
- 虹软开放平台
- 虹软人脸识别 SDK 文档
- 本插件示例代码:
example/lib/main.dart - 虹软接口文档:
docs/虹软人脸识别接口文档.md