Passed
Pull Request — master (#751)
by Matias
07:33 queued 04:51
created

DlibTaguchiHogModel::detectFaces()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 15
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 12

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 3
eloc 8
c 1
b 0
f 0
nc 3
nop 2
dl 0
loc 15
ccs 0
cts 9
cp 0
crap 12
rs 10
1
<?php
2
/**
3
 * @copyright Copyright (c) 2020-2024, Matias De lellis <[email protected]>
4
 *
5
 * @author Matias De lellis <[email protected]>
6
 *
7
 * @license GNU AGPL version 3 or any later version
8
 *
9
 * This program is free software: you can redistribute it and/or modify
10
 * it under the terms of the GNU Affero General Public License as
11
 * published by the Free Software Foundation, either version 3 of the
12
 * License, or (at your option) any later version.
13
 *
14
 * This program is distributed in the hope that it will be useful,
15
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
 * GNU Affero General Public License for more details.
18
 *
19
 * You should have received a copy of the GNU Affero General Public License
20
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
21
 *
22
 */
23
24
namespace OCA\FaceRecognition\Model\DlibTaguchiHogModel;
25
26
use OCA\FaceRecognition\Helper\FaceRect;
27
28
use OCA\FaceRecognition\Model\DlibCnnModel\DlibCnnModel;
29
use OCA\FaceRecognition\Model\IModel;
30
31
class DlibTaguchiHogModel extends DlibCnnModel implements IModel {
32
33
	/*
34
	 * Model files.
35
	 */
36
	const FACE_MODEL_ID = 6;
37
	const FACE_MODEL_NAME = "DlibTaguchiHog";
38
	const FACE_MODEL_DESC = "Extends the Taguchi model, doing a face validation with the Hog detector";
39
	const FACE_MODEL_DOC = "https://github.com/matiasdelellis/facerecognition/wiki/Models#model-6";
40
41
	/** Relationship between image size and memory consumed */
42
	const MEMORY_AREA_RELATIONSHIP = 1 * 1024;
43
	const MINIMUM_MEMORY_REQUIREMENTS = 1 * 1024 * 1024 * 1024;
44
45
	/*
46
	 * Model files.
47
	 */
48
	const FACE_MODEL_FILES = [
49
		'detector' => [
50
			'url' => 'https://github.com/davisking/dlib-models/raw/94cdb1e40b1c29c0bfcaf7355614bfe6da19460e/mmod_human_face_detector.dat.bz2',
51
			'filename' => 'mmod_human_face_detector.dat'
52
		],
53
		'predictor' => [
54
			'url' => 'https://github.com/davisking/dlib-models/raw/4af9b776281dd7d6e2e30d4a2d40458b1e254e40/shape_predictor_5_face_landmarks.dat.bz2',
55
			'filename' => 'shape_predictor_5_face_landmarks.dat',
56
		],
57
		'resnet' => [
58
			'url' => 'https://github.com/TaguchiModels/dlibModels/raw/main/taguchi_face_recognition_resnet_model_v1.7z',
59
			'filename' => 'taguchi_face_recognition_resnet_model_v1.dat'
60
		]
61
	];
62
63
	public function detectFaces(string $imagePath, bool $compute = true): array {
64
		$detectedFaces = [];
65
66
		$cnnFaces = parent::detectFaces($imagePath);
67
		if (count($cnnFaces) === 0) {
68
			return $detectedFaces;
69
		}
70
71
		$hogFaces = dlib_face_detection($imagePath);
0 ignored issues
show
Bug introduced by
The function dlib_face_detection was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

71
		$hogFaces = /** @scrutinizer ignore-call */ dlib_face_detection($imagePath);
Loading history...
72
73
		foreach ($cnnFaces as $proposedFace) {
74
			$detectedFaces[] = $this->validateFace($proposedFace, $hogFaces);
75
		}
76
77
		return $detectedFaces;
78
	}
79
80
	private function validateFace($proposedFace, array $validateFaces) {
81
		foreach ($validateFaces as $validateFace) {
82
			$overlapPercent = FaceRect::overlapPercent($proposedFace, $validateFace);
83
			/**
84
			 * The weak link in our default model is the landmark detector that
85
			 * can't align profile or rotate faces correctly.
86
			 *
87
			 * The Hog detector also fails and cannot detect these faces. So, we
88
			 * consider if Hog detector can detect it, to infer when the predictor
89
			 * will give good results.
90
			 *
91
			 * If Hog detects it (Overlap > 35%), we can assume that landmark
92
			 * detector will do it too. In this case, we consider the face valid,
93
			 * and just return it.
94
			 */
95
			if ($overlapPercent >= 0.35) {
96
				return $proposedFace;
97
			}
98
		}
99
100
		/**
101
		 * If Hog don't detect this face, they are probably in profile or rotated.
102
		 * These are bad to compare, so we lower the confidence, to avoid clustering.
103
		 */
104
		$confidence = $proposedFace['detection_confidence'];
105
		$proposedFace['detection_confidence'] = $confidence * 0.6;
106
107
		return $proposedFace;
108
	}
109
110
}
111