Passed
Push — modelV4 ( 5e5644...36865d )
by Matias
16:22 queued 16s
created

DlibCnnHogModel::getOverlayPercent()   A

Complexity

Conditions 5
Paths 3

Size

Total Lines 34
Code Lines 20

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 30

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 5
eloc 20
c 1
b 0
f 0
nc 3
nop 2
dl 0
loc 34
ccs 0
cts 21
cp 0
crap 30
rs 9.2888
1
<?php
2
/**
3
 * @copyright Copyright (c) 2020, 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\DlibCnnHogModel;
25
26
use OCP\IDBConnection;
27
28
use OCA\FaceRecognition\Helper\FaceRect;
29
30
use OCA\FaceRecognition\Model\IModel;
31
32
use OCA\FaceRecognition\Model\DlibCnnModel\DlibCnn5Model;
33
use OCA\FaceRecognition\Model\DlibHogModel\DlibHogModel;
34
35
class DlibCnnHogModel implements IModel {
36
37
	/*
38
	 * Model files.
39
	 */
40
	const FACE_MODEL_ID = 4;
41
	const FACE_MODEL_NAME = "CnnHog5";
42
	const FACE_MODEL_DESC = "Default Cnn model with Hog validation, and 5 point landmarks preprictor";
43
	const FACE_MODEL_DOC = "";
44
45
	/** @var IDBConnection */
46
	private $connection;
47
48
	/** @var DlibCnn5Model */
49
	private $dlibCnn5Model;
50
51
	/** @var DlibHogModel */
52
	private $dlibHogModel;
53
54
	/**
55
	 * DlibCnnHogModel __construct.
56
	 *
57
	 * @param IDBConnection $connection
58
	 * @param DlibCnn5Model $dlibCnn5Model
59
	 * @param DlibHogModel $dlibHogModel
60
	 */
61 1
	public function __construct(IDBConnection   $connection,
62
	                            DlibCnn5Model   $dlibCnn5Model,
63
	                            DlibHogModel    $dlibHogModel)
64
	{
65 1
		$this->connection       = $connection;
66 1
		$this->dlibCnn5Model    = $dlibCnn5Model;
67 1
		$this->dlibHogModel     = $dlibHogModel;
68 1
	}
69
70
	public function getId(): int {
71
		return static::FACE_MODEL_ID;
72
	}
73
74
	public function getName(): string {
75
		return static::FACE_MODEL_NAME;
76
	}
77
78
	public function getDescription(): string {
79
		return static::FACE_MODEL_DESC;
80
	}
81
82
	public function getDocumentation(): string {
83
		return static::FACE_MODEL_DOC;
84
	}
85
86
	public function isInstalled(): bool {
87
		if (!$this->dlibCnn5Model->isInstalled())
88
			return false;
89
		if (!$this->dlibHogModel->isInstalled())
90
			return false;
91
		return true;
92
	}
93
94
	public function meetDependencies(string &$error_message): bool {
95
		if (!$this->dlibCnn5Model->meetDependencies($error_message)) {
96
			$error_message .= " This Model depend on Model 1 and must install it.";
97
			return false;
98
		}
99
		if (!$this->dlibHogModel->meetDependencies($error_message)) {
100
			$error_message .= " This Model depend on Model 3 and must install it.";
101
			return false;
102
		}
103
		return true;
104
	}
105
106
	public function getMaximumArea(): int {
107
		return $this->dlibCnn5Model->getMaximumArea();
108
	}
109
110
	public function getPreferredMimeType(): string {
111
		return $this->dlibCnn5Model->getPreferredMimeType();
112
	}
113
114
	public function install() {
115
		if ($this->isInstalled()) {
116
			return;
117
		}
118
119
		// Insert on database and enable it
120
		$qb = $this->connection->getQueryBuilder();
121
		$query = $qb->select($qb->createFunction('COUNT(' . $qb->getColumnName('id') . ')'))
122
			->from('facerecog_models')
123
			->where($qb->expr()->eq('id', $qb->createParameter('id')))
124
			->setParameter('id', $this->getId());
125
		$resultStatement = $query->execute();
126
		$data = $resultStatement->fetch(\PDO::FETCH_NUM);
127
		$resultStatement->closeCursor();
128
129
		if ((int)$data[0] <= 0) {
130
			$query = $this->connection->getQueryBuilder();
131
			$query->insert('facerecog_models')
132
			->values([
133
				'id' => $query->createNamedParameter($this->getId()),
134
				'name' => $query->createNamedParameter($this->getName()),
135
				'description' => $query->createNamedParameter($this->getDescription())
136
			])
137
			->execute();
138
		}
139
	}
140
141
	public function open() {
142
		return $this->dlibCnn5Model->open();
0 ignored issues
show
Bug introduced by
Are you sure the usage of $this->dlibCnn5Model->open() targeting OCA\FaceRecognition\Mode...el\DlibCnnModel::open() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
143
	}
144
145
	public function detectFaces(string $imagePath): array {
146
		$detectedFaces = [];
147
148
		$cnnFaces = $this->dlibCnn5Model->detectFaces($imagePath);
149
		$hogFaces = $this->dlibHogModel->detectFaces($imagePath);
150
151
		foreach ($cnnFaces as $proposedFace) {
152
			$detectedFaces[] = $this->validateFace($proposedFace, $hogFaces);
153
		}
154
155
		return $detectedFaces;
156
	}
157
158
	public function detectLandmarks(string $imagePath, array $rect): array {
159
		return $this->dlibCnn5Model->detectLandmarks($imagePath, $rect);
160
	}
161
162
	public function computeDescriptor(string $imagePath, array $landmarks): array {
163
		return $this->dlibCnn5Model->computeDescriptor($imagePath, $landmarks);
164
	}
165
166
	private function validateFace($proposedFace, $validateFaces) {
167
		foreach ($validateFaces as $validateFace) {
168
			$overlayPercent = FaceRect::getOverlayPercent($proposedFace, $validateFace);
169
			/**
170
			 * The weak link in our default model is the landmark detector that
171
			 * can't align profile faces correctly.
172
			 * The Hog detector also fails and cannot detect these faces.
173
			 *
174
			 * So, if Hog detects it (Overlay > 80%), we know that the landmark
175
			 * detector will do it too.
176
			 * Just return it.
177
			 */
178
			if ($overlayPercent > 0.8) {
179
				return $proposedFace;
180
			}
181
		}
182
183
		/**
184
		 * If Hog don't detect this face, they are probably in profile or rotated.
185
		 * These are bad to compare, so we lower the confidence, to avoid clustering.
186
		 */
187
		$confidence = $proposedFace['detection_confidence'];
188
		$proposedFace['detection_confidence'] = $confidence * 0.9;
189
190
		return $proposedFace;
191
	}
192
193
}
194