Passed
Push — self-contained-model ( 97ee28...ab4f7c )
by Matias
04:06
created

DlibCnn5Model::getModelName()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 2
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 2
ccs 0
cts 2
cp 0
crap 2
rs 10
c 0
b 0
f 0
1
<?php
2
/**
3
 * @copyright Copyright (c) 2020, Matias De lellis <[email protected]>
4
 * @copyright Copyright (c) 2018, Branko Kokanovic <[email protected]>
5
 *
6
 * @author Branko Kokanovic <[email protected]>
7
 *
8
 * @license GNU AGPL version 3 or any later version
9
 *
10
 * This program is free software: you can redistribute it and/or modify
11
 * it under the terms of the GNU Affero General Public License as
12
 * published by the Free Software Foundation, either version 3 of the
13
 * License, or (at your option) any later version.
14
 *
15
 * This program is distributed in the hope that it will be useful,
16
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18
 * GNU Affero General Public License for more details.
19
 *
20
 * You should have received a copy of the GNU Affero General Public License
21
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
22
 *
23
 */
24
25
namespace OCA\FaceRecognition\Model;
26
27
use OCP\IDBConnection;
28
29
use OCA\FaceRecognition\Helper\Requirements;
30
31
use OCA\FaceRecognition\Service\FileService;
32
use OCA\FaceRecognition\Service\ModelService;
33
use OCA\FaceRecognition\Service\SettingsService;
34
35
use OCA\FaceRecognition\Model\IModel;
36
37
38
class DlibCnn5Model implements IModel {
39
40
	/** Defines ID for default face model */
41
	const FACE_MODEL_ID = 1;
42
43
	/** Defines name for default face model */
44
	const FACE_MODEL_NAME = 'Default';
45
46
	/** Defines description for default face model */
47
	const FACE_MODEL_DESC = 'Main model, using dlib defaults: mmod_human_face_detector.dat, shape_predictor_5_face_landmarks.dat and dlib_face_recognition_resnet_model_v1.dat';
48
49
	/*
50
	 * Model files.
51
	 */
52
	const MODEL_DETECTOR = 0;
53
	const MODEL_PREDICTOR = 1;
54
	const MODEL_RESNET = 2;
55
56
	const FACE_MODEL_BZ2_URLS = [
57
		'https://github.com/davisking/dlib-models/raw/94cdb1e40b1c29c0bfcaf7355614bfe6da19460e/mmod_human_face_detector.dat.bz2',
58
		'https://github.com/davisking/dlib-models/raw/4af9b776281dd7d6e2e30d4a2d40458b1e254e40/shape_predictor_5_face_landmarks.dat.bz2',
59
		'https://github.com/davisking/dlib-models/raw/2a61575dd45d818271c085ff8cd747613a48f20d/dlib_face_recognition_resnet_model_v1.dat.bz2'
60
	];
61
62
	const FACE_MODEL_FILES = [
63
		'mmod_human_face_detector.dat',
64
		'shape_predictor_5_face_landmarks.dat',
65
		'dlib_face_recognition_resnet_model_v1.dat'
66
	];
67
68
	/** @var \CnnFaceDetection */
0 ignored issues
show
Bug introduced by
The type CnnFaceDetection was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
69
	private $cfd;
70
71
	/** @var \FaceLandmarkDetection */
0 ignored issues
show
Bug introduced by
The type FaceLandmarkDetection was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
72
	private $fld;
73
74
	/** @var \FaceRecognition */
0 ignored issues
show
Bug introduced by
The type FaceRecognition was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
75
	private $fr;
76
77
	/** @var IDBConnection */
78
	private $connection;
79
80
	/** @var FileService */
81
	private $fileService;
82
83
	/** @var ModelService */
84
	private $modelService;
85
86
	/** @var SettingsService */
87
	private $settingsService;
88
89
90
	/**
91
	 * DlibCnn5Model __construct.
92
	 *
93
	 * @param IDBConnection $connection
94
	 * @param FileService $fileService
95
	 * @param ModelService $modelService
96
	 * @param SettingsService $settingsService
97
	 */
98 1
	public function __construct(IDBConnection   $connection,
99
	                            FileService     $fileService,
100
	                            ModelService    $modelService,
101
	                            SettingsService $settingsService)
102
	{
103 1
		$this->connection       = $connection;
104 1
		$this->fileService      = $fileService;
105 1
		$this->modelService     = $modelService;
106 1
		$this->settingsService  = $settingsService;
107 1
	}
108
109
110
	public function getModelId(): int {
111
		return self::FACE_MODEL_ID;
112
	}
113
114
	public function getModelName(): string {
115
		return self::FACE_MODEL_NAME;
116
	}
117
118
	public function getModelDescription(): string {
119
		return self::FACE_MODEL_DESC;
120
	}
121
122
	public function isInstalled(): bool {
123
		$requirements = new Requirements($this->modelService, self::FACE_MODEL_ID);
124
		return $requirements->modelFilesPresent();
125
	}
126
127
	public function meetDependencies(): bool {
128
		$model = $this->settingsService->getCurrentFaceModel();
129
		$requirements = new Requirements($this->modelService, $model);
130
		return extension_loaded('pdlib') && $requirements->modelFilesPresent();
131
	}
132
133
	public function install() {
134
		if ($this->isInstalled()) {
135
			return;
136
		}
137
138
		/* Still not installed but it is necessary to get the model folders */
139
		$this->modelService->useModelVersion(self::FACE_MODEL_ID);
140
141
		/* Download and install models */
142
		$detectorModelBz2 = $this->fileService->downloaldFile(self::FACE_MODEL_BZ2_URLS[self::MODEL_DETECTOR]);
143
		$this->fileService->bunzip2($detectorModelBz2, $this->modelService->getModelPath(self::FACE_MODEL_FILES[self::MODEL_DETECTOR]));
144
145
		$predictorModelBz2 = $this->fileService->downloaldFile(self::FACE_MODEL_BZ2_URLS[self::MODEL_PREDICTOR]);
146
		$this->fileService->bunzip2($predictorModelBz2, $this->modelService->getModelPath(self::FACE_MODEL_FILES[self::MODEL_PREDICTOR]));
147
148
		$resnetModelBz2 = $this->fileService->downloaldFile(self::FACE_MODEL_BZ2_URLS[self::MODEL_RESNET]);
149
		$this->fileService->bunzip2($resnetModelBz2, $this->modelService->getModelPath(self::FACE_MODEL_FILES[self::MODEL_RESNET]));
150
151
		/* Clean temporary files */
152
		$this->fileService->clean();
153
154
		// Insert on database and enable it
155
		$qb = $this->connection->getQueryBuilder();
156
		$query = $qb->select($qb->createFunction('COUNT(' . $qb->getColumnName('id') . ')'))
157
			->from('facerecog_models')
158
			->where($qb->expr()->eq('id', $qb->createParameter('id')))
159
			->setParameter('id', self::FACE_MODEL_ID);
160
		$resultStatement = $query->execute();
161
		$data = $resultStatement->fetch(\PDO::FETCH_NUM);
162
		$resultStatement->closeCursor();
163
164
		if ((int)$data[0] <= 0) {
165
			$query = $this->connection->getQueryBuilder();
166
			$query->insert('facerecog_models')
167
			->values([
168
				'id' => $query->createNamedParameter(self::FACE_MODEL_ID),
169
				'name' => $query->createNamedParameter(self::DEFAULT_FACE_MODEL_NAME),
0 ignored issues
show
Bug introduced by
The constant OCA\FaceRecognition\Mode...DEFAULT_FACE_MODEL_NAME was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
170
				'description' => $query->createNamedParameter(self::DEFAULT_FACE_MODEL_DESC)
0 ignored issues
show
Bug introduced by
The constant OCA\FaceRecognition\Mode...DEFAULT_FACE_MODEL_DESC was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
171
			])
172
			->execute();
173
		}
174
	}
175
176
	public function setDefault() {
177
		// Use default model, if it is not set already.
178
		if ($this->settingsService->getCurrentFaceModel() !== self::FACE_MODEL_ID) {
179
			$this->settingsService->setCurrentFaceModel(self::FACE_MODEL_ID);
180
		}
181
	}
182
183 4
	public function open() {
184 4
		$this->modelService->useModelVersion(self::FACE_MODEL_ID);
185
186 4
		$this->cfd = new \CnnFaceDetection($this->modelService->getModelPath(self::FACE_MODEL_FILES[self::MODEL_DETECTOR]));
187 4
		$this->fld = new \FaceLandmarkDetection($this->modelService->getModelPath(self::FACE_MODEL_FILES[self::MODEL_PREDICTOR]));
188 4
		$this->fr = new \FaceRecognition($this->modelService->getModelPath(self::FACE_MODEL_FILES[self::MODEL_RESNET]));
189 4
	}
190
191 2
	public function detectFaces(string $imagePath): array {
192 2
		return $this->cfd->detect($imagePath);
193
	}
194
195 1
	public function detectLandmarks(string $imagePath, array $rect): array {
196 1
		return $this->fld->detect($imagePath, $rect);
197
	}
198
199 1
	public function computeDescriptor(string $imagePath, array $landmarks): array {
200 1
		return $this->fr->computeDescriptor($imagePath, $landmarks);
201
	}
202
203
}
204