1
0
mirror of https://github.com/immich-app/immich.git synced 2025-07-16 07:24:40 +02:00

feat: facial recognition (#2180)

This commit is contained in:
Jason Rasmussen
2023-05-17 13:07:17 -04:00
committed by GitHub
parent 115a47d4c6
commit 93863b0629
107 changed files with 3943 additions and 133 deletions

View File

@ -21,6 +21,7 @@ class AllJobStatusResponseDto {
required this.storageTemplateMigrationQueue,
required this.backgroundTaskQueue,
required this.searchQueue,
required this.recognizeFacesQueue,
});
JobStatusDto thumbnailGenerationQueue;
@ -39,6 +40,8 @@ class AllJobStatusResponseDto {
JobStatusDto searchQueue;
JobStatusDto recognizeFacesQueue;
@override
bool operator ==(Object other) => identical(this, other) || other is AllJobStatusResponseDto &&
other.thumbnailGenerationQueue == thumbnailGenerationQueue &&
@ -48,7 +51,8 @@ class AllJobStatusResponseDto {
other.clipEncodingQueue == clipEncodingQueue &&
other.storageTemplateMigrationQueue == storageTemplateMigrationQueue &&
other.backgroundTaskQueue == backgroundTaskQueue &&
other.searchQueue == searchQueue;
other.searchQueue == searchQueue &&
other.recognizeFacesQueue == recognizeFacesQueue;
@override
int get hashCode =>
@ -60,10 +64,11 @@ class AllJobStatusResponseDto {
(clipEncodingQueue.hashCode) +
(storageTemplateMigrationQueue.hashCode) +
(backgroundTaskQueue.hashCode) +
(searchQueue.hashCode);
(searchQueue.hashCode) +
(recognizeFacesQueue.hashCode);
@override
String toString() => 'AllJobStatusResponseDto[thumbnailGenerationQueue=$thumbnailGenerationQueue, metadataExtractionQueue=$metadataExtractionQueue, videoConversionQueue=$videoConversionQueue, objectTaggingQueue=$objectTaggingQueue, clipEncodingQueue=$clipEncodingQueue, storageTemplateMigrationQueue=$storageTemplateMigrationQueue, backgroundTaskQueue=$backgroundTaskQueue, searchQueue=$searchQueue]';
String toString() => 'AllJobStatusResponseDto[thumbnailGenerationQueue=$thumbnailGenerationQueue, metadataExtractionQueue=$metadataExtractionQueue, videoConversionQueue=$videoConversionQueue, objectTaggingQueue=$objectTaggingQueue, clipEncodingQueue=$clipEncodingQueue, storageTemplateMigrationQueue=$storageTemplateMigrationQueue, backgroundTaskQueue=$backgroundTaskQueue, searchQueue=$searchQueue, recognizeFacesQueue=$recognizeFacesQueue]';
Map<String, dynamic> toJson() {
final json = <String, dynamic>{};
@ -75,6 +80,7 @@ class AllJobStatusResponseDto {
json[r'storage-template-migration-queue'] = this.storageTemplateMigrationQueue;
json[r'background-task-queue'] = this.backgroundTaskQueue;
json[r'search-queue'] = this.searchQueue;
json[r'recognize-faces-queue'] = this.recognizeFacesQueue;
return json;
}
@ -105,6 +111,7 @@ class AllJobStatusResponseDto {
storageTemplateMigrationQueue: JobStatusDto.fromJson(json[r'storage-template-migration-queue'])!,
backgroundTaskQueue: JobStatusDto.fromJson(json[r'background-task-queue'])!,
searchQueue: JobStatusDto.fromJson(json[r'search-queue'])!,
recognizeFacesQueue: JobStatusDto.fromJson(json[r'recognize-faces-queue'])!,
);
}
return null;
@ -160,6 +167,7 @@ class AllJobStatusResponseDto {
'storage-template-migration-queue',
'background-task-queue',
'search-queue',
'recognize-faces-queue',
};
}

View File

@ -34,6 +34,7 @@ class AssetResponseDto {
this.smartInfo,
this.livePhotoVideoId,
this.tags = const [],
this.people = const [],
});
AssetTypeEnum type;
@ -90,6 +91,8 @@ class AssetResponseDto {
List<TagResponseDto> tags;
List<PersonResponseDto> people;
@override
bool operator ==(Object other) => identical(this, other) || other is AssetResponseDto &&
other.type == type &&
@ -112,7 +115,8 @@ class AssetResponseDto {
other.exifInfo == exifInfo &&
other.smartInfo == smartInfo &&
other.livePhotoVideoId == livePhotoVideoId &&
other.tags == tags;
other.tags == tags &&
other.people == people;
@override
int get hashCode =>
@ -137,10 +141,11 @@ class AssetResponseDto {
(exifInfo == null ? 0 : exifInfo!.hashCode) +
(smartInfo == null ? 0 : smartInfo!.hashCode) +
(livePhotoVideoId == null ? 0 : livePhotoVideoId!.hashCode) +
(tags.hashCode);
(tags.hashCode) +
(people.hashCode);
@override
String toString() => 'AssetResponseDto[type=$type, id=$id, deviceAssetId=$deviceAssetId, ownerId=$ownerId, deviceId=$deviceId, originalPath=$originalPath, originalFileName=$originalFileName, resizePath=$resizePath, fileCreatedAt=$fileCreatedAt, fileModifiedAt=$fileModifiedAt, updatedAt=$updatedAt, isFavorite=$isFavorite, isArchived=$isArchived, mimeType=$mimeType, duration=$duration, webpPath=$webpPath, encodedVideoPath=$encodedVideoPath, exifInfo=$exifInfo, smartInfo=$smartInfo, livePhotoVideoId=$livePhotoVideoId, tags=$tags]';
String toString() => 'AssetResponseDto[type=$type, id=$id, deviceAssetId=$deviceAssetId, ownerId=$ownerId, deviceId=$deviceId, originalPath=$originalPath, originalFileName=$originalFileName, resizePath=$resizePath, fileCreatedAt=$fileCreatedAt, fileModifiedAt=$fileModifiedAt, updatedAt=$updatedAt, isFavorite=$isFavorite, isArchived=$isArchived, mimeType=$mimeType, duration=$duration, webpPath=$webpPath, encodedVideoPath=$encodedVideoPath, exifInfo=$exifInfo, smartInfo=$smartInfo, livePhotoVideoId=$livePhotoVideoId, tags=$tags, people=$people]';
Map<String, dynamic> toJson() {
final json = <String, dynamic>{};
@ -193,6 +198,7 @@ class AssetResponseDto {
// json[r'livePhotoVideoId'] = null;
}
json[r'tags'] = this.tags;
json[r'people'] = this.people;
return json;
}
@ -236,6 +242,7 @@ class AssetResponseDto {
smartInfo: SmartInfoResponseDto.fromJson(json[r'smartInfo']),
livePhotoVideoId: mapValueOfType<String>(json, r'livePhotoVideoId'),
tags: TagResponseDto.listFromJson(json[r'tags']),
people: PersonResponseDto.listFromJson(json[r'people']),
);
}
return null;

View File

@ -27,6 +27,7 @@ class JobName {
static const metadataExtractionQueue = JobName._(r'metadata-extraction-queue');
static const videoConversionQueue = JobName._(r'video-conversion-queue');
static const objectTaggingQueue = JobName._(r'object-tagging-queue');
static const recognizeFacesQueue = JobName._(r'recognize-faces-queue');
static const clipEncodingQueue = JobName._(r'clip-encoding-queue');
static const backgroundTaskQueue = JobName._(r'background-task-queue');
static const storageTemplateMigrationQueue = JobName._(r'storage-template-migration-queue');
@ -38,6 +39,7 @@ class JobName {
metadataExtractionQueue,
videoConversionQueue,
objectTaggingQueue,
recognizeFacesQueue,
clipEncodingQueue,
backgroundTaskQueue,
storageTemplateMigrationQueue,
@ -84,6 +86,7 @@ class JobNameTypeTransformer {
case r'metadata-extraction-queue': return JobName.metadataExtractionQueue;
case r'video-conversion-queue': return JobName.videoConversionQueue;
case r'object-tagging-queue': return JobName.objectTaggingQueue;
case r'recognize-faces-queue': return JobName.recognizeFacesQueue;
case r'clip-encoding-queue': return JobName.clipEncodingQueue;
case r'background-task-queue': return JobName.backgroundTaskQueue;
case r'storage-template-migration-queue': return JobName.storageTemplateMigrationQueue;

View File

@ -0,0 +1,125 @@
//
// AUTO-GENERATED FILE, DO NOT MODIFY!
//
// @dart=2.12
// ignore_for_file: unused_element, unused_import
// ignore_for_file: always_put_required_named_parameters_first
// ignore_for_file: constant_identifier_names
// ignore_for_file: lines_longer_than_80_chars
part of openapi.api;
class PersonResponseDto {
/// Returns a new [PersonResponseDto] instance.
PersonResponseDto({
required this.id,
required this.name,
required this.thumbnailPath,
});
String id;
String name;
String thumbnailPath;
@override
bool operator ==(Object other) => identical(this, other) || other is PersonResponseDto &&
other.id == id &&
other.name == name &&
other.thumbnailPath == thumbnailPath;
@override
int get hashCode =>
// ignore: unnecessary_parenthesis
(id.hashCode) +
(name.hashCode) +
(thumbnailPath.hashCode);
@override
String toString() => 'PersonResponseDto[id=$id, name=$name, thumbnailPath=$thumbnailPath]';
Map<String, dynamic> toJson() {
final json = <String, dynamic>{};
json[r'id'] = this.id;
json[r'name'] = this.name;
json[r'thumbnailPath'] = this.thumbnailPath;
return json;
}
/// Returns a new [PersonResponseDto] instance and imports its values from
/// [value] if it's a [Map], null otherwise.
// ignore: prefer_constructors_over_static_methods
static PersonResponseDto? fromJson(dynamic value) {
if (value is Map) {
final json = value.cast<String, dynamic>();
// Ensure that the map contains the required keys.
// Note 1: the values aren't checked for validity beyond being non-null.
// Note 2: this code is stripped in release mode!
assert(() {
requiredKeys.forEach((key) {
assert(json.containsKey(key), 'Required key "PersonResponseDto[$key]" is missing from JSON.');
assert(json[key] != null, 'Required key "PersonResponseDto[$key]" has a null value in JSON.');
});
return true;
}());
return PersonResponseDto(
id: mapValueOfType<String>(json, r'id')!,
name: mapValueOfType<String>(json, r'name')!,
thumbnailPath: mapValueOfType<String>(json, r'thumbnailPath')!,
);
}
return null;
}
static List<PersonResponseDto> listFromJson(dynamic json, {bool growable = false,}) {
final result = <PersonResponseDto>[];
if (json is List && json.isNotEmpty) {
for (final row in json) {
final value = PersonResponseDto.fromJson(row);
if (value != null) {
result.add(value);
}
}
}
return result.toList(growable: growable);
}
static Map<String, PersonResponseDto> mapFromJson(dynamic json) {
final map = <String, PersonResponseDto>{};
if (json is Map && json.isNotEmpty) {
json = json.cast<String, dynamic>(); // ignore: parameter_assignments
for (final entry in json.entries) {
final value = PersonResponseDto.fromJson(entry.value);
if (value != null) {
map[entry.key] = value;
}
}
}
return map;
}
// maps a json object with a list of PersonResponseDto-objects as value to a dart map
static Map<String, List<PersonResponseDto>> mapListFromJson(dynamic json, {bool growable = false,}) {
final map = <String, List<PersonResponseDto>>{};
if (json is Map && json.isNotEmpty) {
// ignore: parameter_assignments
json = json.cast<String, dynamic>();
for (final entry in json.entries) {
map[entry.key] = PersonResponseDto.listFromJson(entry.value, growable: growable,);
}
}
return map;
}
/// The list of required keys that must be present in a JSON.
static const requiredKeys = <String>{
'id',
'name',
'thumbnailPath',
};
}

View File

@ -0,0 +1,109 @@
//
// AUTO-GENERATED FILE, DO NOT MODIFY!
//
// @dart=2.12
// ignore_for_file: unused_element, unused_import
// ignore_for_file: always_put_required_named_parameters_first
// ignore_for_file: constant_identifier_names
// ignore_for_file: lines_longer_than_80_chars
part of openapi.api;
class PersonUpdateDto {
/// Returns a new [PersonUpdateDto] instance.
PersonUpdateDto({
required this.name,
});
String name;
@override
bool operator ==(Object other) => identical(this, other) || other is PersonUpdateDto &&
other.name == name;
@override
int get hashCode =>
// ignore: unnecessary_parenthesis
(name.hashCode);
@override
String toString() => 'PersonUpdateDto[name=$name]';
Map<String, dynamic> toJson() {
final json = <String, dynamic>{};
json[r'name'] = this.name;
return json;
}
/// Returns a new [PersonUpdateDto] instance and imports its values from
/// [value] if it's a [Map], null otherwise.
// ignore: prefer_constructors_over_static_methods
static PersonUpdateDto? fromJson(dynamic value) {
if (value is Map) {
final json = value.cast<String, dynamic>();
// Ensure that the map contains the required keys.
// Note 1: the values aren't checked for validity beyond being non-null.
// Note 2: this code is stripped in release mode!
assert(() {
requiredKeys.forEach((key) {
assert(json.containsKey(key), 'Required key "PersonUpdateDto[$key]" is missing from JSON.');
assert(json[key] != null, 'Required key "PersonUpdateDto[$key]" has a null value in JSON.');
});
return true;
}());
return PersonUpdateDto(
name: mapValueOfType<String>(json, r'name')!,
);
}
return null;
}
static List<PersonUpdateDto> listFromJson(dynamic json, {bool growable = false,}) {
final result = <PersonUpdateDto>[];
if (json is List && json.isNotEmpty) {
for (final row in json) {
final value = PersonUpdateDto.fromJson(row);
if (value != null) {
result.add(value);
}
}
}
return result.toList(growable: growable);
}
static Map<String, PersonUpdateDto> mapFromJson(dynamic json) {
final map = <String, PersonUpdateDto>{};
if (json is Map && json.isNotEmpty) {
json = json.cast<String, dynamic>(); // ignore: parameter_assignments
for (final entry in json.entries) {
final value = PersonUpdateDto.fromJson(entry.value);
if (value != null) {
map[entry.key] = value;
}
}
}
return map;
}
// maps a json object with a list of PersonUpdateDto-objects as value to a dart map
static Map<String, List<PersonUpdateDto>> mapListFromJson(dynamic json, {bool growable = false,}) {
final map = <String, List<PersonUpdateDto>>{};
if (json is Map && json.isNotEmpty) {
// ignore: parameter_assignments
json = json.cast<String, dynamic>();
for (final entry in json.entries) {
map[entry.key] = PersonUpdateDto.listFromJson(entry.value, growable: growable,);
}
}
return map;
}
/// The list of required keys that must be present in a JSON.
static const requiredKeys = <String>{
'name',
};
}