Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Polish admin settings #323

Merged
merged 12 commits into from
Sep 23, 2022
6 changes: 2 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,14 @@

This app goes through your media collection and adds fitting tags, automatically categorizing your photos and music.

* 📷 👪 Recognizes faces from contact photos
* 📷 👪 Recognizes faces and groups photos by face
* 📷 🏔 Recognizes animals, landscapes, food, vehicles, buildings and other objects
* 📷 🗼 Recognizes landmarks and monuments
* 👂 🎵 Recognizes music genres
* ⚡ Tagging works via Nextcloud's Collaborative Tags, allowing access by any of your apps
* 👂 listen to your tagged music with the audioplayer app
* 📷 view your tagged photos with the photos app

Note: This project is quite young and thus still a bit rough around the edges.

### Examples

![](https://github.com/marcelklehr/recognize/raw/master/screenshots/imagenet_examples.jpg)
Expand Down Expand Up @@ -54,7 +52,7 @@ Recognize uses

### One click

Go to "Apps" in your nextcloud, search for "recognize" and click install (currently only works on Nextcloud v22+. If you're below that, you'll need to install manually).
Go to "Apps" in your nextcloud, search for "recognize" and click install.

### Configuration

Expand Down
4 changes: 3 additions & 1 deletion appinfo/routes.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,12 @@
['name' => 'admin#reset', 'url' => '/admin/reset', 'verb' => 'GET'],
['name' => 'admin#recrawl', 'url' => '/admin/recrawl', 'verb' => 'GET'],
['name' => 'admin#count', 'url' => '/admin/count', 'verb' => 'GET'],
['name' => 'admin#countQueued', 'url' => '/admin/countQueued', 'verb' => 'GET'],
['name' => 'admin#count_missed', 'url' => '/admin/countMissed', 'verb' => 'GET'],
['name' => 'admin#avx', 'url' => '/admin/avx', 'verb' => 'GET'],
['name' => 'admin#platform', 'url' => '/admin/platform', 'verb' => 'GET'],
['name' => 'admin#musl', 'url' => '/admin/musl', 'verb' => 'GET'],
['name' => 'user#update_cluster', 'url' => '/user/cluster/{id}', 'verb' => 'POST'],
['name' => 'admin#get_setting', 'url' => '/admin/settings/{setting}', 'verb' => 'GET'],
['name' => 'admin#set_setting', 'url' => '/admin/settings/{setting}', 'verb' => 'PUT'],
],
];
21 changes: 17 additions & 4 deletions lib/BackgroundJobs/ClassifierJob.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,26 @@
use OCP\DB\Exception;
use OCP\Files\Config\ICachedMountInfo;
use OCP\Files\Config\IUserMountCache;
use OCP\IConfig;
use Psr\Log\LoggerInterface;

abstract class ClassifierJob extends Job {
private LoggerInterface $logger;
private QueueService $queue;
private IUserMountCache $userMountCache;
private IJobList $jobList;
/**
* @var \OCP\IConfig
*/
private IConfig $config;

public function __construct(ITimeFactory $time, LoggerInterface $logger, QueueService $queue, IUserMountCache $userMountCache, IJobList $jobList) {
public function __construct(ITimeFactory $time, LoggerInterface $logger, QueueService $queue, IUserMountCache $userMountCache, IJobList $jobList, IConfig $config) {
parent::__construct($time);
$this->logger = $logger;
$this->queue = $queue;
$this->userMountCache = $userMountCache;
$this->jobList = $jobList;
$this->config = $config;
}

protected function runClassifier(string $model, $argument) {
Expand All @@ -32,7 +38,8 @@ protected function runClassifier(string $model, $argument) {
try {
$files = $this->queue->getFromQueue($model, $storageId, $rootId, $this->getBatchSize());
} catch (Exception $e) {
$this->logger->error('Cannot retrieve items from imagenet queue', ['exception' => $e]);
$this->config->setAppValue('recognize', $model.'.status', 'false');
$this->logger->error('Cannot retrieve items from '.$model.' queue', ['exception' => $e]);
return;
}

Expand All @@ -44,7 +51,12 @@ protected function runClassifier(string $model, $argument) {
\OC_Util::setupFS($mounts[0]->getUser()->getUID());
}

$this->classify($files);
try {
$this->classify($files);
} catch(\Throwable $e) {
$this->config->setAppValue('recognize', $model.'.status', 'false');
throw $e;
}

try {
// If there is at least one file left in the queue, reschedule this job
Expand All @@ -54,7 +66,8 @@ protected function runClassifier(string $model, $argument) {
$this->jobList->remove(static::class, $argument);
}
} catch (Exception $e) {
$this->logger->error('Cannot retrieve items from imagenet queue', ['exception' => $e]);
$this->config->setAppValue('recognize', $model.'.status', 'false');
$this->logger->error('Cannot retrieve items from '.$model.' queue', ['exception' => $e]);
return;
}
}
Expand Down
2 changes: 1 addition & 1 deletion lib/BackgroundJobs/ClassifyFacesJob.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ class ClassifyFacesJob extends ClassifierJob {
private ClusteringFaceClassifier $faces;

public function __construct(ITimeFactory $time, LoggerInterface $logger, QueueService $queue, IConfig $config, ClusteringFaceClassifier $faceClassifier, IUserMountCache $mountCache, IJobList $jobList) {
parent::__construct($time, $logger, $queue, $mountCache, $jobList);
parent::__construct($time, $logger, $queue, $mountCache, $jobList, $config);
$this->config = $config;
$this->faces = $faceClassifier;
}
Expand Down
2 changes: 1 addition & 1 deletion lib/BackgroundJobs/ClassifyImagenetJob.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ class ClassifyImagenetJob extends ClassifierJob {
private ImagenetClassifier $imagenet;

public function __construct(ITimeFactory $time, LoggerInterface $logger, QueueService $queue, IConfig $config, ImagenetClassifier $imagenet, IUserMountCache $mountCache, IJobList $jobList) {
parent::__construct($time, $logger, $queue, $mountCache, $jobList);
parent::__construct($time, $logger, $queue, $mountCache, $jobList, $config);
$this->config = $config;
$this->imagenet = $imagenet;
}
Expand Down
2 changes: 1 addition & 1 deletion lib/BackgroundJobs/ClassifyLandmarksJob.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ class ClassifyLandmarksJob extends ClassifierJob {
private LandmarksClassifier $landmarks;

public function __construct(ITimeFactory $time, LoggerInterface $logger, QueueService $queue, IConfig $config, LandmarksClassifier $landmarks, IUserMountCache $mountCache, IJobList $jobList) {
parent::__construct($time, $logger, $queue, $mountCache, $jobList);
parent::__construct($time, $logger, $queue, $mountCache, $jobList, $config);
$this->config = $config;
$this->landmarks = $landmarks;
}
Expand Down
2 changes: 1 addition & 1 deletion lib/BackgroundJobs/ClassifyMovinetJob.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ class ClassifyMovinetJob extends ClassifierJob {
private MovinetClassifier $movinet;

public function __construct(ITimeFactory $time, LoggerInterface $logger, QueueService $queue, IConfig $config, MovinetClassifier $movinet, IUserMountCache $mountCache, IJobList $jobList) {
parent::__construct($time, $logger, $queue, $mountCache, $jobList);
parent::__construct($time, $logger, $queue, $mountCache, $jobList, $config);
$this->config = $config;
$this->movinet = $movinet;
}
Expand Down
2 changes: 1 addition & 1 deletion lib/BackgroundJobs/ClassifyMusicnnJob.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ class ClassifyMusicnnJob extends ClassifierJob {
private MusicnnClassifier $musicnn;

public function __construct(ITimeFactory $time, LoggerInterface $logger, QueueService $queue, IConfig $config, MusicnnClassifier $musicnn, IUserMountCache $mountCache, IJobList $jobList) {
parent::__construct($time, $logger, $queue, $mountCache, $jobList);
parent::__construct($time, $logger, $queue, $mountCache, $jobList, $config);
$this->config = $config;
$this->musicnn = $musicnn;
}
Expand Down
14 changes: 14 additions & 0 deletions lib/BackgroundJobs/SchedulerJob.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@

use OC\Files\Cache\CacheQueryBuilder;
use OC\SystemConfig;
use OCA\Recognize\Classifiers\Audio\MusicnnClassifier;
use OCA\Recognize\Classifiers\Images\ClusteringFaceClassifier;
use OCA\Recognize\Classifiers\Images\ImagenetClassifier;
use OCA\Recognize\Classifiers\Images\LandmarksClassifier;
use OCA\Recognize\Classifiers\Video\MovinetClassifier;
use OCA\Recognize\Service\Logger;
use OCP\AppFramework\Utility\ITimeFactory;
use OCP\BackgroundJob\IJobList;
Expand Down Expand Up @@ -49,6 +54,14 @@ public function __construct(ITimeFactory $timeFactory, Logger $logger, IDBConnec
}

protected function run($argument): void {
$models = $argument['models'] ?? [
ClusteringFaceClassifier::MODEL_NAME,
ImagenetClassifier::MODEL_NAME,
LandmarksClassifier::MODEL_NAME,
MovinetClassifier::MODEL_NAME,
MusicnnClassifier::MODEL_NAME,
];

$qb = $this->db->getQueryBuilder();
$qb->select('root_id', 'storage_id', 'mount_provider_class')
->from('mounts')
Expand Down Expand Up @@ -80,6 +93,7 @@ protected function run($argument): void {
'root_id' => $rootId,
'override_root' => $overrideRoot,
'last_file_id' => 0,
'models' => $models,
]);
}

Expand Down
56 changes: 51 additions & 5 deletions lib/BackgroundJobs/StorageCrawlJob.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,13 @@
use OCA\Recognize\Classifiers\Audio\MusicnnClassifier;
use OCA\Recognize\Classifiers\Images\ClusteringFaceClassifier;
use OCA\Recognize\Classifiers\Images\ImagenetClassifier;
use OCA\Recognize\Classifiers\Images\LandmarksClassifier;
use OCA\Recognize\Classifiers\Video\MovinetClassifier;
use OCA\Recognize\Constants;
use OCA\Recognize\Db\QueueFile;
use OCA\Recognize\Service\Logger;
use OCA\Recognize\Service\QueueService;
use OCA\Recognize\Service\TagManager;
use OCP\AppFramework\Utility\ITimeFactory;
use OCP\BackgroundJob\IJobList;
use OCP\BackgroundJob\QueuedJob;
Expand All @@ -33,22 +35,32 @@ class StorageCrawlJob extends QueuedJob {
private IJobList $jobList;
private IDBConnection $db;
private SystemConfig $systemConfig;
private TagManager $tagManager;

public function __construct(ITimeFactory $timeFactory, Logger $logger, IMimeTypeLoader $mimeTypes, QueueService $queue, IJobList $jobList, IDBConnection $db, SystemConfig $systemConfig) {
public function __construct(ITimeFactory $timeFactory, Logger $logger, IMimeTypeLoader $mimeTypes, QueueService $queue, IJobList $jobList, IDBConnection $db, SystemConfig $systemConfig, TagManager $tagManager) {
parent::__construct($timeFactory);
$this->logger = $logger;
$this->mimeTypes = $mimeTypes;
$this->queue = $queue;
$this->jobList = $jobList;
$this->db = $db;
$this->systemConfig = $systemConfig;
$this->tagManager = $tagManager;
}

protected function run($argument): void {
$storageId = $argument['storage_id'];
$rootId = $argument['root_id'];
$overrideRoot = $argument['override_root'];
$lastFileId = $argument['last_file_id'];
$models = $argument['models'] ?? [
ClusteringFaceClassifier::MODEL_NAME,
ImagenetClassifier::MODEL_NAME,
LandmarksClassifier::MODEL_NAME,
MovinetClassifier::MODEL_NAME,
MusicnnClassifier::MODEL_NAME,
];

$qb = new CacheQueryBuilder($this->db, $this->systemConfig, $this->logger);
try {
$root = $qb->selectFileCache()
Expand All @@ -63,13 +75,31 @@ protected function run($argument): void {
$videoTypes = array_map(fn ($mimeType) => $this->mimeTypes->getId($mimeType), Constants::VIDEO_FORMATS);
$audioTypes = array_map(fn ($mimeType) => $this->mimeTypes->getId($mimeType), Constants::AUDIO_FORMATS);

$mimeTypes = [];
if (in_array(ClusteringFaceClassifier::MODEL_NAME, $models) ||
in_array(ImagenetClassifier::MODEL_NAME, $models) ||
in_array(LandmarksClassifier::MODEL_NAME, $models)) {
$mimeTypes = array_merge($imageTypes, $mimeTypes);
}
if (in_array(MovinetClassifier::MODEL_NAME, $models)) {
$mimeTypes = array_merge($videoTypes, $mimeTypes);
}
if (in_array(MusicnnClassifier::MODEL_NAME, $models)) {
$mimeTypes = array_merge($audioTypes, $mimeTypes);
}
marcelklehr marked this conversation as resolved.
Show resolved Hide resolved
if (count($mimeTypes) === 0) {
// Remove current iteration
$this->jobList->remove(self::class, $argument);
return;
}

try {
$qb = new CacheQueryBuilder($this->db, $this->systemConfig, $this->logger);
$files = $qb->selectFileCache()
->whereStorageId($storageId)
->andWhere($qb->expr()->like('path', $qb->createNamedParameter($root['path'] . '/%')))
->andWhere($qb->expr()->eq('storage', $qb->createNamedParameter($storageId)))
->andWhere($qb->expr()->in('mimetype', $qb->createNamedParameter(array_merge($imageTypes, $videoTypes, $audioTypes), IQueryBuilder::PARAM_INT_ARRAY)))
->andWhere($qb->expr()->in('mimetype', $qb->createNamedParameter($mimeTypes, IQueryBuilder::PARAM_INT_ARRAY)))
->andWhere($qb->expr()->gt('filecache.fileid', $qb->createNamedParameter($lastFileId)))
->orderBy('filecache.fileid', 'ASC')
->setMaxResults(100)
Expand All @@ -92,8 +122,23 @@ protected function run($argument): void {
$queueFile->setUpdate(false);
try {
if (in_array($file['mimetype'], $imageTypes)) {
$this->queue->insertIntoQueue(ImagenetClassifier::MODEL_NAME, $queueFile);
$this->queue->insertIntoQueue(ClusteringFaceClassifier::MODEL_NAME, $queueFile);
if (in_array(ImagenetClassifier::class, $models)) {
$this->queue->insertIntoQueue(ImagenetClassifier::MODEL_NAME, $queueFile);
}
if (!in_array(ImagenetClassifier::class, $models) && in_array(LandmarksClassifier::class, $models)) {
$tags = $this->tagManager->getTagsForFiles([$queueFile->getFileId()]);
/** @var \OCP\SystemTag\ISystemTag[] $fileTags */
$fileTags = $tags[$queueFile->getFileId()];
$landmarkTags = array_filter($fileTags, function ($tag) {
return in_array($tag->getName(), LandmarksClassifier::PRECONDITION_TAGS);
});
if (count($landmarkTags) > 0) {
$this->queue->insertIntoQueue(LandmarksClassifier::MODEL_NAME, $queueFile);
}
}
if (in_array(ClusteringFaceClassifier::class, $models)) {
$this->queue->insertIntoQueue(ClusteringFaceClassifier::MODEL_NAME, $queueFile);
}
}
if (in_array($file['mimetype'], $videoTypes)) {
$this->queue->insertIntoQueue(MovinetClassifier::MODEL_NAME, $queueFile);
Expand All @@ -113,7 +158,8 @@ protected function run($argument): void {
'storage_id' => $storageId,
'root_id' => $rootId,
'override_root' => $overrideRoot,
'last_file_id' => $queueFile->getFileId()
'last_file_id' => $queueFile->getFileId(),
'models' => $models,
]);
}
}
Expand Down
1 change: 1 addition & 0 deletions lib/Classifiers/Audio/MusicnnClassifier.php
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ public function classify(array $queueFiles): void {

foreach ($classifierProcess as $queueFile => $results) {
$this->tagManager->assignTags($queueFile->getFileId(), $results);
$this->config->setAppValue('recognize', self::MODEL_NAME.'.status', 'true');
}
}
}
1 change: 1 addition & 0 deletions lib/Classifiers/Images/ClusteringFaceClassifier.php
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ public function classify(array $queueFiles): void {
}
$usersToCluster[] = $userId;
}
$this->config->setAppValue('recognize', self::MODEL_NAME.'.status', 'true');
}
}

Expand Down
1 change: 1 addition & 0 deletions lib/Classifiers/Images/ImagenetClassifier.php
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ public function classify(array $queueFiles): void {
$landmarkTags = array_filter($results, function ($tagName) {
return in_array($tagName, LandmarksClassifier::PRECONDITION_TAGS);
});
$this->config->setAppValue('recognize', self::MODEL_NAME.'.status', 'true');
if (count($landmarkTags) > 0) {
try {
$this->queue->insertIntoQueue(LandmarksClassifier::MODEL_NAME, $queueFile);
Expand Down
1 change: 1 addition & 0 deletions lib/Classifiers/Images/LandmarksClassifier.php
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ public function classify(array $queueFiles): void {

foreach ($classifierProcess as $queueFile => $results) {
$this->tagManager->assignTags($queueFile->getFileId(), $results);
$this->config->setAppValue('recognize', self::MODEL_NAME.'.status', 'true');
}
}
}
1 change: 1 addition & 0 deletions lib/Classifiers/Video/MovinetClassifier.php
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ public function classify(array $queueFiles): void {

foreach ($classifierProcess as $queueFile => $results) {
$this->tagManager->assignTags($queueFile->getFileId(), $results);
$this->config->setAppValue('recognize', self::MODEL_NAME.'.status', 'false');
marcelklehr marked this conversation as resolved.
Show resolved Hide resolved
}
}
}
Loading