fix: 修复特征提取失败(错误码81929)

问题: extractFaceFeature 返回错误码 81929 (MERR_FSDK_FACEFEATURE_FACEDATA)

根本原因: detectFaces 返回的人脸信息缺少 faceData 字段,
而虹软 SDK 的 extractFaceFeature 必须要有这个字段才能提取特征

修复:
- FaceEngineManager.convertFaceInfoToList: 添加返回 faceData
- ArcPlugin.handleExtractFaceFeature: 接收并传递 faceData 参数
- Dart API: extractFaceFeature 添加 faceData 参数
- example: 传递 faceData 到特征提取调用

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-30 16:58:12 +08:00
parent c9d57d160c
commit 86e268ae1c
7 changed files with 1611 additions and 3 deletions

135
lib/arc_method_channel.dart Normal file
View File

@@ -0,0 +1,135 @@
import 'package:flutter/foundation.dart';
import 'package:flutter/services.dart';
import 'arc_platform_interface.dart';
/// An implementation of [ArcPlatform] that uses method channels.
class MethodChannelArc extends ArcPlatform {
/// The method channel used to interact with the native platform.
@visibleForTesting
final methodChannel = const MethodChannel('arc');
@override
Future<String?> getPlatformVersion() async {
final version = await methodChannel.invokeMethod<String>('getPlatformVersion');
return version;
}
@override
Future<Map<String, dynamic>?> activeOnline({
required String appId,
required String sdkKey,
required String activeKey,
}) async {
final result = await methodChannel.invokeMethod<Map<dynamic, dynamic>>('activeOnline', {
'appId': appId,
'sdkKey': sdkKey,
'activeKey': activeKey,
});
return result?.cast<String, dynamic>();
}
@override
Future<Map<String, dynamic>?> init({
int? detectMode,
int? orient,
int? maxFaceNum,
int? combinedMask,
}) async {
final result = await methodChannel.invokeMethod<Map<dynamic, dynamic>>('init', {
'detectMode': detectMode,
'orient': orient,
'maxFaceNum': maxFaceNum,
'combinedMask': combinedMask,
});
return result?.cast<String, dynamic>();
}
@override
Future<Map<String, dynamic>?> detectFaces({
required Uint8List data,
required int width,
required int height,
int format = 2050,
}) async {
final result = await methodChannel.invokeMethod<Map<dynamic, dynamic>>('detectFaces', {
'data': data,
'width': width,
'height': height,
'format': format,
});
return result?.cast<String, dynamic>();
}
@override
Future<Map<String, dynamic>?> extractFaceFeature({
required Uint8List data,
required int width,
required int height,
required int rectLeft,
required int rectTop,
required int rectRight,
required int rectBottom,
int format = 2050,
int faceOrientation = 0,
int faceId = -1,
Uint8List? faceData,
int extractType = 1,
int mask = 0,
}) async {
final result = await methodChannel.invokeMethod<Map<dynamic, dynamic>>('extractFaceFeature', {
'data': data,
'width': width,
'height': height,
'format': format,
'rectLeft': rectLeft,
'rectTop': rectTop,
'rectRight': rectRight,
'rectBottom': rectBottom,
'faceOrientation': faceOrientation,
'faceId': faceId,
'faceData': faceData, // 关键:传递 faceData这是虹软 SDK 特征提取必需的数据
'extractType': extractType,
'mask': mask,
});
return result?.cast<String, dynamic>();
}
@override
Future<Map<String, dynamic>?> compareFaceFeature({
required Uint8List featureData1,
required Uint8List featureData2,
int compareModel = 0,
}) async {
final result = await methodChannel.invokeMethod<Map<dynamic, dynamic>>('compareFaceFeature', {
'featureData1': featureData1,
'featureData2': featureData2,
'compareModel': compareModel,
});
return result?.cast<String, dynamic>();
}
@override
Future<Map<String, dynamic>?> registerFaceFeature({
required int searchId,
required Uint8List featureData,
String? faceTag,
}) async {
final result = await methodChannel.invokeMethod<Map<dynamic, dynamic>>('registerFaceFeature', {
'searchId': searchId,
'featureData': featureData,
'faceTag': faceTag,
});
return result?.cast<String, dynamic>();
}
@override
Future<Map<String, dynamic>?> registerFaceFeatureBatch({
required List<Map<String, dynamic>> faceList,
}) async {
final result = await methodChannel.invokeMethod<Map<dynamic, dynamic>>('registerFaceFeatureBatch', {
'faceList': faceList,
});
return result?.cast<String, dynamic>();
}
}