Passed
Push — self-contained-model ( d29518...24c026 )
by Matias
04:02
created

DlibCnn5Model::open()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 4
c 1
b 0
f 0
nc 1
nop 0
dl 0
loc 6
ccs 0
cts 5
cp 0
crap 2
rs 10
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
36
class DlibCnn5Model {
37
38
	/** Defines ID for default face model */
39
	const DEFAULT_FACE_MODEL_ID = 1;
40
41
	/** Defines name for default face model */
42
	const DEFAULT_FACE_MODEL_NAME = 'Default';
43
44
	/** Defines description for default face model */
45
	const DEFAULT_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';
46
47
	/*
48
	 * Model files.
49
	 */
50
	const MODEL_DETECTOR = 0;
51
	const MODEL_PREDICTOR = 1;
52
	const MODEL_RESNET = 2;
53
54
	const FACE_MODEL_BZ2_URLS = [
55
		'https://github.com/davisking/dlib-models/raw/94cdb1e40b1c29c0bfcaf7355614bfe6da19460e/mmod_human_face_detector.dat.bz2',
56
		'https://github.com/davisking/dlib-models/raw/4af9b776281dd7d6e2e30d4a2d40458b1e254e40/shape_predictor_5_face_landmarks.dat.bz2',
57
		'https://github.com/davisking/dlib-models/raw/2a61575dd45d818271c085ff8cd747613a48f20d/dlib_face_recognition_resnet_model_v1.dat.bz2'
58
	];
59
60
	const FACE_MODEL_FILES = [
61
		'mmod_human_face_detector.dat',
62
		'shape_predictor_5_face_landmarks.dat',
63
		'dlib_face_recognition_resnet_model_v1.dat'
64
	];
65
66
	/** @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...
67
	private $cfd;
68
69
	/** @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...
70
	private $fld;
71
72
	/** @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...
73
	private $fr;
74
75
	/** @var IDBConnection */
76
	private $connection;
77
78
	/** @var FileService */
79
	private $fileService;
80
81
	/** @var ModelService */
82
	private $modelService;
83
84
	/** @var SettingsService */
85
	private $settingsService;
86
87
88
	/**
89
	 * DlibCnn5Model __construct.
90
	 *
91
	 * @param IDBConnection $connection
92
	 * @param FileService $fileService
93
	 * @param ModelService $modelService
94
	 * @param SettingsService $settingsService
95
	 */
96
	public function __construct(IDBConnection   $connection,
97
	                            FileService     $fileService,
98
	                            ModelService    $modelService,
99
	                            SettingsService $settingsService) {
100
		$this->connection       = $connection;
101
		$this->fileService      = $fileService;
102
		$this->modelService     = $modelService;
103
		$this->settingsService  = $settingsService;
104
	}
105
106
	public function isInstalled(): bool {
107
		$requirements = new Requirements($this->modelService, self::DEFAULT_FACE_MODEL_ID);
108
		return $requirements->modelFilesPresent();
109
	}
110
111
	public function meetDependencies(): bool {
112
		$model = $this->settingsService->getCurrentFaceModel();
113
		$requirements = new Requirements($this->modelService, $model);
114
		return extension_loaded('pdlib') && $requirements->modelFilesPresent();
115
	}
116
117
	public function install() {
118
		if ($this->isInstalled()) {
119
			return;
120
		}
121
122
		/* Still not installed but it is necessary to get the model folders */
123
		$this->modelService->useModelVersion(self::DEFAULT_FACE_MODEL_ID);
124
125
		/* Download and install models */
126
		$detectorModelBz2 = $this->fileService->downloaldFile(self::FACE_MODEL_BZ2_URLS[self::MODEL_DETECTOR]);
127
		$this->fileService->bunzip2($detectorModelBz2, $this->modelService->getModelPath(self::FACE_MODEL_FILES[self::MODEL_DETECTOR]));
128
129
		$predictorModelBz2 = $this->fileService->downloaldFile(self::FACE_MODEL_BZ2_URLS[self::MODEL_PREDICTOR]);
130
		$this->fileService->bunzip2($predictorModelBz2, $this->modelService->getModelPath(self::FACE_MODEL_FILES[self::MODEL_PREDICTOR]));
131
132
		$resnetModelBz2 = $this->fileService->downloaldFile(self::FACE_MODEL_BZ2_URLS[self::MODEL_RESNET]);
133
		$this->fileService->bunzip2($resnetModelBz2, $this->modelService->getModelPath(self::FACE_MODEL_FILES[self::MODEL_RESNET]));
134
135
		/* Clean temporary files */
136
		$this->fileService->clean();
137
138
		// Insert on database and enable it
139
		$qb = $this->connection->getQueryBuilder();
140
		$query = $qb->select($qb->createFunction('COUNT(' . $qb->getColumnName('id') . ')'))
141
			->from('facerecog_models')
142
			->where($qb->expr()->eq('id', $qb->createParameter('id')))
143
			->setParameter('id', self::DEFAULT_FACE_MODEL_ID);
144
		$resultStatement = $query->execute();
145
		$data = $resultStatement->fetch(\PDO::FETCH_NUM);
146
		$resultStatement->closeCursor();
147
148
		if ((int)$data[0] <= 0) {
149
			$query = $this->connection->getQueryBuilder();
150
			$query->insert('facerecog_models')
151
			->values([
152
				'id' => $query->createNamedParameter(self::DEFAULT_FACE_MODEL_ID),
153
				'name' => $query->createNamedParameter(self::DEFAULT_FACE_MODEL_NAME),
154
				'description' => $query->createNamedParameter(self::DEFAULT_FACE_MODEL_DESC)
155
			])
156
			->execute();
157
		}
158
	}
159
160
	public function setDefault() {
161
		// Use default model, if it is not set already.
162
		if ($this->settingsService->getCurrentFaceModel() !== self::DEFAULT_FACE_MODEL_ID) {
163
			$this->settingsService->setCurrentFaceModel(self::DEFAULT_FACE_MODEL_ID);
164
		}
165
	}
166
167
	public function open() {
168
		$this->modelService->useModelVersion(self::DEFAULT_FACE_MODEL_ID);
169
170
		$this->cfd = new \CnnFaceDetection($this->modelService->getModelPath(self::FACE_MODEL_FILES[self::MODEL_DETECTOR]));
171
		$this->fld = new \FaceLandmarkDetection($this->modelService->getModelPath(self::FACE_MODEL_FILES[self::MODEL_PREDICTOR]));
172
		$this->fr = new \FaceRecognition($this->modelService->getModelPath(self::FACE_MODEL_FILES[self::MODEL_RESNET]));
173
	}
174
175
	public function detectFaces(string $imagePath): array {
176
		return $this->cfd->detect($imagePath);
177
	}
178
179
	public function detectLandmarks(string $imagePath, array $rect): array {
180
		return $this->fld->detect($imagePath, $rect);
181
	}
182
183
	public function computeDescriptor(string $imagePath, array $landmarks): array {
184
		return $this->fr->computeDescriptor($imagePath, $landmarks);
185
	}
186
187
}
188