nextcloud-custom-apps-face-.../facerecognition/lib/Helper/PhotoAlbums.php
2024-09-03 09:12:12 +05:00

261 lines
8.6 KiB
PHP

<?php
/**
* @copyright Copyright (c) 2022 Matias De lellis <mati86dl@gmail.com>
*
* @author Matias De lellis <mati86dl@gmail.com>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
namespace OCA\FaceRecognition\Helper;
use OCP\IUser;
use Symfony\Component\Console\Output\OutputInterface;
use OCA\FaceRecognition\Db\ImageMapper;
use OCA\FaceRecognition\Db\PersonMapper;
use OCA\FaceRecognition\Album\AlbumMapper;
use OCA\FaceRecognition\Service\SettingsService;
class PhotoAlbums {
/** @var PersonMapper Person mapper*/
private $personMapper;
/** @var ImageMapper Image mapper*/
private $imageMapper;
/** @var AlbumMapper Album mapper */
private $albumMapper;
/** @var SettingsService Settings service*/
private $settingsService;
/**
* @param PersonMapper $personMapper
* @param ImageMapper $imageMapper
* @param AlbumMapper $albumMapper
* @param SettingsService $settingsService
*/
public function __construct(PersonMapper $personMapper,
ImageMapper $imageMapper,
AlbumMapper $albumMapper,
SettingsService $settingsService)
{
$this->personMapper = $personMapper;
$this->imageMapper = $imageMapper;
$this->albumMapper = $albumMapper;
$this->settingsService = $settingsService;
}
/**
* @return void
*/
public function syncUser (string $userId) {
$modelId = $this->settingsService->getCurrentFaceModel();
/* Get current albums and persons to sync */
$personNames = $this->getPersonsNames($userId, $modelId);
$albumNames = $this->albumMapper->getAll($userId);
/* Create albums for new persons */
$albumsToCreate = array_diff ($personNames, $albumNames);
foreach ($albumsToCreate as $albumToCreate) {
$this->albumMapper->create($userId, $albumToCreate);
}
/* Remove albums for old persons */
$albumsToDelete = array_diff ($albumNames, $personNames);
foreach ($albumsToDelete as $albumToDelete) {
$albumId = $this->albumMapper->get($userId, $albumToDelete);
$this->albumMapper->delete($albumId);
}
/* Find person's images and sync */
foreach ($personNames as $albumName) {
$albumId = $this->albumMapper->get($userId, $albumName);
/* Get images within albums and person's to compare and sync */
$albumImages = $this->albumMapper->getFiles($albumId);
$personImages = $this->getPersonsImages($userId, $modelId, $albumName);
/* Delete old photos. Maybe corrections. */
$imagesToDelete = array_diff ($albumImages, $personImages);
foreach ($imagesToDelete as $image) {
$this->albumMapper->removeFile($albumId, $image);
}
/* Add new photos to the person's album */
$imagesToAdd = array_diff ($personImages, $albumImages);
foreach ($imagesToAdd as $image) {
$this->albumMapper->addFile($albumId, $image, $userId);
}
}
}
/**
* @return void
*/
public function syncUserPersonNamesSelected (string $userId, string $personNames, OutputInterface $output) {
$modelId = $this->settingsService->getCurrentFaceModel();
/* Get current albums and persons to sync */
$personsNames = $this->getPersonsNamesSelected($userId, $modelId, $personNames);
if ( count($personsNames) === 0 ){
$output->writeln("Person name $personNames invalid - skipping");
return;
}
$albumNames = $this->albumMapper->getAll($userId);
/* Create albums for new persons */
$albumsToCreate = array_diff ($personsNames, $albumNames);
foreach ($albumsToCreate as $albumToCreate) {
$this->albumMapper->create($userId, $albumToCreate);
}
/* Find person's images and sync */
foreach ($personsNames as $albumName) {
$albumId = $this->albumMapper->get($userId, $albumName);
/* Get images within albums and person's to compare and sync */
$albumImages = $this->albumMapper->getFiles($albumId);
$personImages = $this->getPersonsImages($userId, $modelId, $albumName);
/* Delete old photos. Maybe corrections. */
$imagesToDelete = array_diff ($albumImages, $personImages);
foreach ($imagesToDelete as $image) {
$this->albumMapper->removeFile($albumId, $image);
}
/* Add new photos to the person's album */
$imagesToAdd = array_diff ($personImages, $albumImages);
foreach ($imagesToAdd as $image) {
$this->albumMapper->addFile($albumId, $image, $userId);
}
}
}
/**
* @return void
*/
public function syncUserPersonNamesCombinedAlbum (string $userId, array $personList, OutputInterface $output) {
$modelId = $this->settingsService->getCurrentFaceModel();
/* Get current albums and persons to sync */
$albumToCreateCombined = "";
$albumTodo = array();
$personNames = array();
foreach ($personList as $person) {
$personName = $this->getPersonsNamesSelected($userId, $modelId, $person);
if ( $personName[0] === $person ){
array_push($personNames, $personName[0]);
$albumToCreateCombined .= $personName[0] . "+";
}else{
$output->writeln("Person name $person invalid - exit without creating combined album");
return;
}
}
$albumToCreateCombined = rtrim($albumToCreateCombined, "+");
array_push($albumTodo, $albumToCreateCombined);
$albumNames = $this->albumMapper->getAll($userId);
/* Create albums for new persons */
$albumsToCreate = array_diff ($albumTodo, $albumNames);
$countAlbumsToCreate = count($albumsToCreate);
if ($countAlbumsToCreate === 1) {
$albumToCreate = $albumsToCreate[0];
$this->albumMapper->create($userId, $albumToCreate);
}
if ($countAlbumsToCreate === 1) {
$albumToCreate = $albumsToCreate[0];
$albumId = $this->albumMapper->get($userId, $albumToCreate);
} else {
$albumToCreate = $albumTodo[0];
$albumId = $this->albumMapper->get($userId, $albumToCreate);
}
/* Get images within albums and person's to compare and sync */
$albumImages = $this->albumMapper->getFiles($albumId);
$personImages = $this->getMultiPersonsImages($userId, $modelId, $personNames);
/* Delete old photos. Maybe corrections. */
$imagesToDelete = array_diff ($albumImages, $personImages);
foreach ($imagesToDelete as $image) {
$this->albumMapper->removeFile($albumId, $image);
}
/* Add new photos to the person's album */
$imagesToAdd = array_diff ($personImages, $albumImages);
foreach ($imagesToAdd as $image) {
$this->albumMapper->addFile($albumId, $image, $userId);
}
}
private function getPersonsNames(string $userId, int $modelId): array {
$distintNames = $this->personMapper->findDistinctNames($userId, $modelId);
$names = [];
foreach ($distintNames as $distintName) {
$names[] = $distintName->getName();
}
return $names;
}
private function getPersonsNamesSelected(string $userId, int $modelId, string $faceNames): array {
$distintNames = $this->personMapper->findDistinctNamesSelected($userId, $modelId, $faceNames);
$names = [];
foreach ($distintNames as $distintName) {
$names[] = $distintName->getName();
}
return $names;
}
private function getPersonsImages(string $userId, int $modelId, string $personName): array {
$personImages = $this->imageMapper->findFromPerson($userId, $modelId, $personName);
$images = [];
foreach ($personImages as $image) {
$images[] = $image->getFile();
}
return array_unique($images);
}
private function getMultiPersonsImages(string $userId, int $modelId, array $personNames): array {
$multiPersonImages = array();
foreach ($personNames as $personName){
$personImages = $this->imageMapper->findFromPerson($userId, $modelId, $personName);
$images = [];
foreach ($personImages as $image) {
$images[] = $image->getFile();
}
array_push($multiPersonImages, $images);
}
$noPersons = count($multiPersonImages);
$multiPersonMatchingImages = array();
for ($i = 1 ; $i < $noPersons ; ++$i) {
if ($i === 1) {
$multiPersonMatchingImages = array_intersect($multiPersonImages[$i-1], $multiPersonImages[$i]);
} else {
$multiPersonMatchingImages = array_intersect($multiPersonMatchingImages, $multiPersonImages[$i]);
}
}
return array_unique($multiPersonMatchingImages);
}
}