Files
biz_xfj_cloud/lib/common/models/plugs/face_discern_models.dart
T
2026-07-24 20:41:17 +08:00

474 lines
15 KiB
Dart

import 'package:json_annotation/json_annotation.dart';
part 'face_discern_models.g.dart';
@JsonSerializable()
class FaceStream {
// 相似度
double similar;
// 识别时间
int cost;
// 人脸id
int? faceId;
// 人脸样本id
int? sampleId;
// 样本id
String? userId;
// 用户名
String? userName;
FaceStream({
required this.similar,
required this.cost,
this.faceId,
this.sampleId,
this.userId,
this.userName,
});
factory FaceStream.fromJson(Map<String, dynamic> json) =>
_$FaceStreamFromJson(json);
Map<String, dynamic> toJson() => _$FaceStreamToJson(this);
}
@JsonSerializable()
class FaceConfig {
String? appId;
String? sdkKey;
String? activeKey;
// 是否激活
bool isActive = false;
FaceConfig({
this.appId,
this.sdkKey,
this.activeKey,
this.isActive = false,
});
factory FaceConfig.fromJson(Map<String, dynamic> json) =>
_$FaceConfigFromJson(json);
Map<String, dynamic> toJson() => _$FaceConfigToJson(this);
}
/// 终端本机的人脸识别策略,对应 Android `RecognizeConfiguration` 的可调白名单。
class FaceRecognitionConfiguration {
const FaceRecognitionConfiguration({
required this.enableLiveness,
required this.similarThreshold,
required this.rgbLivenessThreshold,
required this.enableImageQuality,
required this.imageQualityNoMaskRecognizeThreshold,
required this.imageQualityMaskRecognizeThreshold,
required this.keepMaxFace,
required this.maxDetectFaces,
required this.extractRetryCount,
required this.livenessRetryCount,
required this.recognizeFailedRetryInterval,
required this.livenessFailedRetryInterval,
required this.livenessType,
});
const FaceRecognitionConfiguration.defaults()
: enableLiveness = false,
similarThreshold = 0.8,
rgbLivenessThreshold = 0.5,
enableImageQuality = true,
imageQualityNoMaskRecognizeThreshold = 0.49,
imageQualityMaskRecognizeThreshold = 0.29,
keepMaxFace = true,
maxDetectFaces = 1,
extractRetryCount = 3,
livenessRetryCount = 3,
recognizeFailedRetryInterval = 0,
livenessFailedRetryInterval = 0,
livenessType = 'RGB';
final bool enableLiveness;
final double similarThreshold;
final double rgbLivenessThreshold;
final bool enableImageQuality;
final double imageQualityNoMaskRecognizeThreshold;
final double imageQualityMaskRecognizeThreshold;
final bool keepMaxFace;
final int maxDetectFaces;
final int extractRetryCount;
final int livenessRetryCount;
final int recognizeFailedRetryInterval;
final int livenessFailedRetryInterval;
final String livenessType;
factory FaceRecognitionConfiguration.fromMap(Map<dynamic, dynamic> map) {
const defaults = FaceRecognitionConfiguration.defaults();
return FaceRecognitionConfiguration(
enableLiveness: _asBoolOr(map['enableLiveness'], defaults.enableLiveness),
similarThreshold:
_asDouble(map['similarThreshold'], defaults.similarThreshold),
rgbLivenessThreshold: _asDouble(
map['rgbLivenessThreshold'],
defaults.rgbLivenessThreshold,
),
enableImageQuality:
_asBoolOr(map['enableImageQuality'], defaults.enableImageQuality),
imageQualityNoMaskRecognizeThreshold: _asDouble(
map['imageQualityNoMaskRecognizeThreshold'],
defaults.imageQualityNoMaskRecognizeThreshold,
),
imageQualityMaskRecognizeThreshold: _asDouble(
map['imageQualityMaskRecognizeThreshold'],
defaults.imageQualityMaskRecognizeThreshold,
),
keepMaxFace: _asBoolOr(map['keepMaxFace'], defaults.keepMaxFace),
maxDetectFaces: _asIntOr(map['maxDetectFaces'], defaults.maxDetectFaces),
extractRetryCount:
_asIntOr(map['extractRetryCount'], defaults.extractRetryCount),
livenessRetryCount:
_asIntOr(map['livenessRetryCount'], defaults.livenessRetryCount),
recognizeFailedRetryInterval: _asIntOr(
map['recognizeFailedRetryInterval'],
defaults.recognizeFailedRetryInterval,
),
livenessFailedRetryInterval: _asIntOr(
map['livenessFailedRetryInterval'],
defaults.livenessFailedRetryInterval,
),
livenessType: map['livenessType']?.toString() ?? defaults.livenessType,
);
}
Map<String, dynamic> toMap() => {
'enableLiveness': enableLiveness,
'similarThreshold': similarThreshold,
'rgbLivenessThreshold': rgbLivenessThreshold,
'enableImageQuality': enableImageQuality,
'imageQualityNoMaskRecognizeThreshold':
imageQualityNoMaskRecognizeThreshold,
'imageQualityMaskRecognizeThreshold':
imageQualityMaskRecognizeThreshold,
'keepMaxFace': keepMaxFace,
'maxDetectFaces': maxDetectFaces,
'extractRetryCount': extractRetryCount,
'livenessRetryCount': livenessRetryCount,
'recognizeFailedRetryInterval': recognizeFailedRetryInterval,
'livenessFailedRetryInterval': livenessFailedRetryInterval,
};
bool get usesDefaults =>
this == const FaceRecognitionConfiguration.defaults();
FaceRecognitionConfiguration copyWith({
bool? enableLiveness,
double? similarThreshold,
double? rgbLivenessThreshold,
bool? enableImageQuality,
double? imageQualityNoMaskRecognizeThreshold,
double? imageQualityMaskRecognizeThreshold,
bool? keepMaxFace,
int? maxDetectFaces,
int? extractRetryCount,
int? livenessRetryCount,
int? recognizeFailedRetryInterval,
int? livenessFailedRetryInterval,
}) {
return FaceRecognitionConfiguration(
enableLiveness: enableLiveness ?? this.enableLiveness,
similarThreshold: similarThreshold ?? this.similarThreshold,
rgbLivenessThreshold: rgbLivenessThreshold ?? this.rgbLivenessThreshold,
enableImageQuality: enableImageQuality ?? this.enableImageQuality,
imageQualityNoMaskRecognizeThreshold:
imageQualityNoMaskRecognizeThreshold ??
this.imageQualityNoMaskRecognizeThreshold,
imageQualityMaskRecognizeThreshold: imageQualityMaskRecognizeThreshold ??
this.imageQualityMaskRecognizeThreshold,
keepMaxFace: keepMaxFace ?? this.keepMaxFace,
maxDetectFaces: maxDetectFaces ?? this.maxDetectFaces,
extractRetryCount: extractRetryCount ?? this.extractRetryCount,
livenessRetryCount: livenessRetryCount ?? this.livenessRetryCount,
recognizeFailedRetryInterval:
recognizeFailedRetryInterval ?? this.recognizeFailedRetryInterval,
livenessFailedRetryInterval:
livenessFailedRetryInterval ?? this.livenessFailedRetryInterval,
livenessType: livenessType,
);
}
@override
bool operator ==(Object other) =>
identical(this, other) ||
other is FaceRecognitionConfiguration &&
enableLiveness == other.enableLiveness &&
similarThreshold == other.similarThreshold &&
rgbLivenessThreshold == other.rgbLivenessThreshold &&
enableImageQuality == other.enableImageQuality &&
imageQualityNoMaskRecognizeThreshold ==
other.imageQualityNoMaskRecognizeThreshold &&
imageQualityMaskRecognizeThreshold ==
other.imageQualityMaskRecognizeThreshold &&
keepMaxFace == other.keepMaxFace &&
maxDetectFaces == other.maxDetectFaces &&
extractRetryCount == other.extractRetryCount &&
livenessRetryCount == other.livenessRetryCount &&
recognizeFailedRetryInterval == other.recognizeFailedRetryInterval &&
livenessFailedRetryInterval == other.livenessFailedRetryInterval &&
livenessType == other.livenessType;
@override
int get hashCode => Object.hash(
enableLiveness,
similarThreshold,
rgbLivenessThreshold,
enableImageQuality,
imageQualityNoMaskRecognizeThreshold,
imageQualityMaskRecognizeThreshold,
keepMaxFace,
maxDetectFaces,
extractRetryCount,
livenessRetryCount,
recognizeFailedRetryInterval,
livenessFailedRetryInterval,
livenessType,
);
}
@JsonSerializable()
class RegisterAllStorageFaceRes {
// 注册成功数量
int successCount;
// 注册失败数量
int failedCount;
// 注册数量
int registerCount;
// 本地文件数量
int fileCount;
RegisterAllStorageFaceRes({
required this.successCount,
required this.failedCount,
required this.registerCount,
required this.fileCount,
});
factory RegisterAllStorageFaceRes.fromJson(Map<String, dynamic> json) =>
_$RegisterAllStorageFaceResFromJson(json);
Map<String, dynamic> toJson() => _$RegisterAllStorageFaceResToJson(this);
}
@JsonSerializable()
class FaceRes {
int searchId;
List<int> featureData;
String faceTag;
FaceRes({
required this.searchId,
required this.featureData,
required this.faceTag,
});
factory FaceRes.fromJson(Map<String, dynamic> json) =>
_$FaceResFromJson(json);
Map<String, dynamic> toJson() => _$FaceResToJson(this);
}
/// 原生人脸插件、授权文件和内存人脸库的实时状态。
class FacePluginStatus {
const FacePluginStatus({
required this.activated,
required this.activationCode,
required this.parametersComplete,
required this.engineReady,
required this.engineCode,
required this.databaseCount,
required this.memoryCount,
required this.registrationInProgress,
required this.libraryConsistent,
this.activationStartTime,
this.activationEndTime,
this.registrationProgress,
this.lastRegistrationResult,
});
final bool activated;
final int activationCode;
final bool parametersComplete;
final bool engineReady;
final int engineCode;
final int databaseCount;
final int memoryCount;
final bool registrationInProgress;
final bool libraryConsistent;
final String? activationStartTime;
final String? activationEndTime;
final FaceRegistrationProgress? registrationProgress;
final FaceRegistrationResult? lastRegistrationResult;
bool get ready =>
activated && engineReady && !registrationInProgress && libraryConsistent;
factory FacePluginStatus.fromMap(Map<dynamic, dynamic> map) {
return FacePluginStatus(
activated: _asBool(map['activated']),
activationCode: _asInt(map['activationCode']),
parametersComplete: _asBool(map['parametersComplete']),
engineReady: _asBool(map['engineReady']),
engineCode: _asInt(map['engineCode']),
databaseCount: _asInt(map['databaseCount']),
memoryCount: _asInt(map['memoryCount']),
registrationInProgress: _asBool(map['registrationInProgress']),
libraryConsistent: _asBool(map['libraryConsistent']),
activationStartTime: _asNullableString(map['activationStartTime']),
activationEndTime: _asNullableString(map['activationEndTime']),
registrationProgress: map['registrationProgress'] is Map
? FaceRegistrationProgress.fromMap(
map['registrationProgress'] as Map,
)
: null,
lastRegistrationResult: map['lastRegistrationResult'] is Map
? FaceRegistrationResult.fromMap(
map['lastRegistrationResult'] as Map,
)
: null,
);
}
}
class FaceActivationResult {
const FaceActivationResult({
required this.success,
required this.code,
required this.message,
required this.requiresPermission,
required this.canOpenSettings,
});
final bool success;
final int code;
final String message;
final bool requiresPermission;
final bool canOpenSettings;
factory FaceActivationResult.fromMap(Map<dynamic, dynamic> map) {
return FaceActivationResult(
success: _asBool(map['success']),
code: _asInt(map['code']),
message: _asString(map['message'], '人脸插件激活失败'),
requiresPermission: _asBool(map['requiresPermission']),
canOpenSettings: _asBool(map['canOpenSettings']),
);
}
}
class FaceRegistrationProgress {
const FaceRegistrationProgress({
required this.phase,
required this.message,
required this.processed,
required this.total,
required this.successCount,
required this.failedCount,
required this.inProgress,
this.currentSampleId,
});
final String phase;
final String message;
final int processed;
final int total;
final int successCount;
final int failedCount;
final bool inProgress;
final int? currentSampleId;
double get fraction => total <= 0 ? 0 : (processed / total).clamp(0, 1);
factory FaceRegistrationProgress.fromMap(Map<dynamic, dynamic> map) {
return FaceRegistrationProgress(
phase: _asString(map['phase'], 'idle'),
message: _asString(map['message'], '尚未执行人脸库注册'),
processed: _asInt(map['processed']),
total: _asInt(map['total']),
successCount: _asInt(map['successCount']),
failedCount: _asInt(map['failedCount']),
inProgress: _asBool(map['inProgress']),
currentSampleId: map['currentSampleId'] == null
? null
: _asInt(map['currentSampleId']),
);
}
}
class FaceRegistrationResult {
const FaceRegistrationResult({
required this.success,
required this.message,
required this.total,
required this.successCount,
required this.failedCount,
required this.failedSampleIds,
required this.durationMs,
});
final bool success;
final String message;
final int total;
final int successCount;
final int failedCount;
final List<int> failedSampleIds;
final int durationMs;
factory FaceRegistrationResult.fromMap(Map<dynamic, dynamic> map) {
final failedSampleIds = map['failedSampleIds'];
return FaceRegistrationResult(
success: _asBool(map['success']),
message: _asString(map['message'], '人脸库注册失败'),
total: _asInt(map['total']),
successCount: _asInt(map['successCount']),
failedCount: _asInt(map['failedCount']),
failedSampleIds: failedSampleIds is List
? failedSampleIds.map(_asInt).toList(growable: false)
: const [],
durationMs: _asInt(map['durationMs']),
);
}
}
bool _asBool(dynamic value) => value == true;
int _asInt(dynamic value) => value is num ? value.toInt() : 0;
int _asIntOr(dynamic value, int fallback) =>
value is num ? value.toInt() : fallback;
double _asDouble(dynamic value, double fallback) =>
value is num ? value.toDouble() : fallback;
bool _asBoolOr(dynamic value, bool fallback) =>
value is bool ? value : fallback;
String _asString(dynamic value, String fallback) {
final result = value?.toString();
return result == null || result.isEmpty ? fallback : result;
}
String? _asNullableString(dynamic value) {
final result = value?.toString();
return result == null || result.isEmpty ? null : result;
}