File size: 3,503 Bytes
9c2551a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
import threading
from typing import Any, Optional, List
import insightface
import numpy

import DeepFakeAI.globals
from DeepFakeAI.typing import Frame, Face, FaceAnalyserDirection, FaceAnalyserAge, FaceAnalyserGender

FACE_ANALYSER = None
THREAD_LOCK = threading.Lock()


def get_face_analyser() -> Any:
	global FACE_ANALYSER

	with THREAD_LOCK:
		if FACE_ANALYSER is None:
			FACE_ANALYSER = insightface.app.FaceAnalysis(name = 'buffalo_l', providers = DeepFakeAI.globals.execution_providers)
			FACE_ANALYSER.prepare(ctx_id = 0)
	return FACE_ANALYSER


def clear_face_analyser() -> Any:
	global FACE_ANALYSER

	FACE_ANALYSER = None


def get_one_face(frame : Frame, position : int = 0) -> Optional[Face]:
	many_faces = get_many_faces(frame)
	if many_faces:
		try:
			return many_faces[position]
		except IndexError:
			return many_faces[-1]
	return None


def get_many_faces(frame : Frame) -> List[Face]:
	try:
		faces = get_face_analyser().get(frame)
		if DeepFakeAI.globals.face_analyser_direction:
			faces = sort_by_direction(faces, DeepFakeAI.globals.face_analyser_direction)
		if DeepFakeAI.globals.face_analyser_age:
			faces = filter_by_age(faces, DeepFakeAI.globals.face_analyser_age)
		if DeepFakeAI.globals.face_analyser_gender:
			faces = filter_by_gender(faces, DeepFakeAI.globals.face_analyser_gender)
		return faces
	except (AttributeError, ValueError):
		return []


def find_similar_faces(frame : Frame, reference_face : Face, face_distance : float) -> List[Face]:
	many_faces = get_many_faces(frame)
	similar_faces = []
	if many_faces:
		for face in many_faces:
			if hasattr(face, 'normed_embedding') and hasattr(reference_face, 'normed_embedding'):
				current_face_distance = numpy.sum(numpy.square(face.normed_embedding - reference_face.normed_embedding))
				if current_face_distance < face_distance:
					similar_faces.append(face)
	return similar_faces


def sort_by_direction(faces : List[Face], direction : FaceAnalyserDirection) -> List[Face]:
	if direction == 'left-right':
		return sorted(faces, key = lambda face: face['bbox'][0])
	if direction == 'right-left':
		return sorted(faces, key = lambda face: face['bbox'][0], reverse = True)
	if direction == 'top-bottom':
		return sorted(faces, key = lambda face: face['bbox'][1])
	if direction == 'bottom-top':
		return sorted(faces, key = lambda face: face['bbox'][1], reverse = True)
	if direction == 'small-large':
		return sorted(faces, key = lambda face: (face['bbox'][2] - face['bbox'][0]) * (face['bbox'][3] - face['bbox'][1]))
	if direction == 'large-small':
		return sorted(faces, key = lambda face: (face['bbox'][2] - face['bbox'][0]) * (face['bbox'][3] - face['bbox'][1]), reverse = True)
	return faces


def filter_by_age(faces : List[Face], age : FaceAnalyserAge) -> List[Face]:
	filter_faces = []
	for face in faces:
		if face['age'] < 13 and age == 'child':
			filter_faces.append(face)
		elif face['age'] < 19 and age == 'teen':
			filter_faces.append(face)
		elif face['age'] < 60 and age == 'adult':
			filter_faces.append(face)
		elif face['age'] > 59 and age == 'senior':
			filter_faces.append(face)
	return filter_faces


def filter_by_gender(faces : List[Face], gender : FaceAnalyserGender) -> List[Face]:
	filter_faces = []
	for face in faces:
		if face['gender'] == 1 and gender == 'male':
			filter_faces.append(face)
		if face['gender'] == 0 and gender == 'female':
			filter_faces.append(face)
	return filter_faces


def get_faces_total(frame : Frame) -> int:
	return len(get_many_faces(frame))