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

Crashes with TypeError: OCA\FaceRecognition\Helper\Euclidean::distance(): Argument #1 ($vector1) must be of type array, string given, called in #780

Open
wojciechczyz opened this issue Oct 17, 2024 · 25 comments

Comments

@wojciechczyz
Copy link

Hey, Thanks for reporting issues back to Nextcloud Face Recognition. Please, try to complete this report in detail so we can help you easier. 😄

Make sure you read all the documentation, and the FAQ, and that the issue has not been reported before. 😉

Expected behaviour

when running:

php occ face:background_job --cluster-mode

It starts clustering and then crashes:
1/3 - Executing task CheckRequirementsTask (Check all requirements)
2/3 - Executing task CheckCronTask (Check that service is started from either cron or from command)
3/3 - Executing task CreateClustersTask (Create new persons or update existing persons)
Face clustering will be created for the first time.
There are 47 faces for clustering
An unhandled exception has been thrown:

Actual behaviour

Crashes with error:
42b5095134e3:/var/www/html$ php occ face:background_job --cluster-mode
1/3 - Executing task CheckRequirementsTask (Check all requirements)
2/3 - Executing task CheckCronTask (Check that service is started from either cron or from command)
3/3 - Executing task CreateClustersTask (Create new persons or update existing persons)
Face clustering will be created for the first time.
There are 47 faces for clustering
An unhandled exception has been thrown:
TypeError: OCA\FaceRecognition\Helper\Euclidean::distance(): Argument #1 ($vector1) must be of type array, string given, called in /var/www/html/custom_apps/facerecognition/lib/BackgroundJob/Tasks/CreateClustersTask.php on line 336 and defined in /var/www/html/custom_apps/facerecognition/lib/Helper/Euclidean.php:24
Stack trace:
#0 /var/www/html/custom_apps/facerecognition/lib/BackgroundJob/Tasks/CreateClustersTask.php(336): OCA\FaceRecognition\Helper\Euclidean::distance('[-0.08935702592...', '[-0.08935702592...')
#1 /var/www/html/custom_apps/facerecognition/lib/BackgroundJob/Tasks/CreateClustersTask.php(177): OCA\FaceRecognition\BackgroundJob\Tasks\CreateClustersTask->getNewClusters(Array)
#2 /var/www/html/custom_apps/facerecognition/lib/BackgroundJob/Tasks/CreateClustersTask.php(90): OCA\FaceRecognition\BackgroundJob\Tasks\CreateClustersTask->createClusterIfNeeded('admin')
#3 /var/www/html/custom_apps/facerecognition/lib/BackgroundJob/BackgroundService.php(150): OCA\FaceRecognition\BackgroundJob\Tasks\CreateClustersTask->execute(Object(OCA\FaceRecognition\BackgroundJob\FaceRecognitionContext))
#4 /var/www/html/custom_apps/facerecognition/lib/Command/BackgroundCommand.php(192): OCA\FaceRecognition\BackgroundJob\BackgroundService->execute(0, false, NULL, NULL, 'cluster-mode')
#5 /var/www/html/3rdparty/symfony/console/Command/Command.php(298): OCA\FaceRecognition\Command\BackgroundCommand->execute(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#6 /var/www/html/3rdparty/symfony/console/Application.php(1040): Symfony\Component\Console\Command\Command->run(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#7 /var/www/html/3rdparty/symfony/console/Application.php(301): Symfony\Component\Console\Application->doRunCommand(Object(OCA\FaceRecognition\Command\BackgroundCommand), Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#8 /var/www/html/3rdparty/symfony/console/Application.php(171): Symfony\Component\Console\Application->doRun(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#9 /var/www/html/lib/private/Console/Application.php(213): Symfony\Component\Console\Application->run(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#10 /var/www/html/console.php(102): OC\Console\Application->run()
#11 /var/www/html/occ(11): require_once('/var/www/html/c...')
#12 {main}42b5095134e3:/var/www/html$

Server configuration

  • Operating system:

docker setup with external container

  • Pdlib version:

  • How is DLib installed: Make sure it is working correctly with this tool

docker setup with external container

  • How is PDlib installed: Make sure it is working correctly with this tool

  • PHP version:

  • Web server:

  • Database:

  • Nextcloud version:

29.0.8

Client configuration

  • Browser:

Chrome

  • Operating system:

Docker under Proxmox

Logs

Background task log with debug.

sudo -u apache php occ -vvv face:background_job
1/8 - Executing task CheckRequirementsTask (Check all requirements)        System: Linux
        System memory: 33227206656        PHP Memory Limit: 2147483648        Clustering backend: PHP (Not recommended.)
        Image Backend: Imaginary        Imaginary version: dev
2/8 - Executing task CheckCronTask (Check that service is started from either cron or from command)
3/8 - Executing task DisabledUserRemovalTask (Purge all the information of a user when disable the analysis.)
yielding
yielding
4/8 - Executing task StaleImagesRemovalTask (Crawl for stale images (either missing in filesystem or under .nomedia) and remove them from DB)
        Skipping stale images removal for user admin as there is no need for it
        Skipping stale images removal for user wojtek as there is no need for it
5/8 - Executing task CreateClustersTask (Create new persons or update existing persons)
        Face clustering will be created for the first time.
        There are 47 faces for clustering
        We will cluster with 1 batch(es) of 47 faces
An unhandled exception has been thrown:
TypeError: OCA\FaceRecognition\Helper\Euclidean::distance(): Argument #1 ($vector1) must be of type array, string given, called in /var/www/html/custom_apps/facerecognition/lib/BackgroundJob/Tasks/CreateClustersTask.php on line 336 and defined in /var/www/html/custom_apps/facerecognition/lib/Helper/Euclidean.php:24
Stack trace:
#0 /var/www/html/custom_apps/facerecognition/lib/BackgroundJob/Tasks/CreateClustersTask.php(336): OCA\FaceRecognition\Helper\Euclidean::distance('[-0.08935702592...', '[-0.08935702592...')
#1 /var/www/html/custom_apps/facerecognition/lib/BackgroundJob/Tasks/CreateClustersTask.php(177): OCA\FaceRecognition\BackgroundJob\Tasks\CreateClustersTask->getNewClusters(Array)
#2 /var/www/html/custom_apps/facerecognition/lib/BackgroundJob/Tasks/CreateClustersTask.php(90): OCA\FaceRecognition\BackgroundJob\Tasks\CreateClustersTask->createClusterIfNeeded('admin')
#3 /var/www/html/custom_apps/facerecognition/lib/BackgroundJob/BackgroundService.php(150): OCA\FaceRecognition\BackgroundJob\Tasks\CreateClustersTask->execute(Object(OCA\FaceRecognition\BackgroundJob\FaceRecognitionContext))
#4 /var/www/html/custom_apps/facerecognition/lib/Command/BackgroundCommand.php(192): OCA\FaceRecognition\BackgroundJob\BackgroundService->execute(0, true, NULL, NULL, 'default-mode')
#5 /var/www/html/3rdparty/symfony/console/Command/Command.php(298): OCA\FaceRecognition\Command\BackgroundCommand->execute(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#6 /var/www/html/3rdparty/symfony/console/Application.php(1040): Symfony\Component\Console\Command\Command->run(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#7 /var/www/html/3rdparty/symfony/console/Application.php(301): Symfony\Component\Console\Application->doRunCommand(Object(OCA\FaceRecognition\Command\BackgroundCommand), Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#8 /var/www/html/3rdparty/symfony/console/Application.php(171): Symfony\Component\Console\Application->doRun(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#9 /var/www/html/lib/private/Console/Application.php(213): Symfony\Component\Console\Application->run(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#10 /var/www/html/console.php(102): OC\Console\Application->run()
#11 /var/www/html/occ(11): require_once('/var/www/html/c...')
42b

Web server error log

Web server error log
Insert your webserver log here

Nextcloud log (data/nextcloud.log)

Nextcloud log
Insert your Nextcloud log here

Browser log

Browser log
Insert your browser log here, this could for example include:

a) The javascript console log
b) The network log
c) ...
@ewok2
Copy link

ewok2 commented Oct 19, 2024

Hello, I get the same behaviour
Face recognation 0.9.51
NC 29.0.8
Pdlib tested Ok

When launching :
sudo -u www-data php /var/www/nextcloud/occ face:background_job
after a
sudo -u www-data php /var/www/nextcloud/occ face:reset --all
it start analyse the picture and stop after all picture has been analysed
With the stat command :

sudo -u www-data php /var/www/nextcloud/occ face:stats
+----------------+--------+-----------+-------+----------+---------+
| User           | Images | Processed | Faces | Clusters | Persons |
+----------------+--------+-----------+-------+----------+---------+
| user1           | 224    | 224       | 263   | 0        | 0       |
+----------------+--------+-----------+-------+----------+---------+

but when launching again
sudo -u www-data php /var/www/nextcloud/occ face:background_job
I get

1/8 - Executing task CheckRequirementsTask (Check all requirements)
2/8 - Executing task CheckCronTask (Check that service is started from either cron or from command)
3/8 - Executing task DisabledUserRemovalTask (Purge all the information of a user when disable the analysis.)
4/8 - Executing task StaleImagesRemovalTask (Crawl for stale images (either missing in filesystem or under .nomedia) and remove them from DB)
5/8 - Executing task CreateClustersTask (Create new persons or update existing persons)
	Skipping cluster creation, not enough data (yet) collected. For cluster creation, you need either one of the following:
	* have 1000 faces already processed
	* or you need to have 95% of you images processed
	Use stats command to track progress
	Skipping cluster creation, not enough data (yet) collected. For cluster creation, you need either one of the following:
	* have 1000 faces already processed
	* or you need to have 95% of you images processed
	Use stats command to track progress
	Skipping cluster creation, not enough data (yet) collected. For cluster creation, you need either one of the following:
	* have 1000 faces already processed
	* or you need to have 95% of you images processed
	Use stats command to track progress
	Skipping cluster creation, not enough data (yet) collected. For cluster creation, you need either one of the following:
	* have 1000 faces already processed
	* or you need to have 95% of you images processed
	Use stats command to track progress
	Face clustering will be created for the first time.
	There are 263 faces for clustering
An unhandled exception has been thrown:
TypeError: dlib_vector_length(): Argument #1 ($x_arg) must be of type array, string given in /var/www/nextcloud/apps/facerecognition/lib/BackgroundJob/Tasks/CreateClustersTask.php:311
Stack trace:
#0 /var/www/nextcloud/apps/facerecognition/lib/BackgroundJob/Tasks/CreateClustersTask.php(311): dlib_vector_length()
#1 /var/www/nextcloud/apps/facerecognition/lib/BackgroundJob/Tasks/CreateClustersTask.php(177): OCA\FaceRecognition\BackgroundJob\Tasks\CreateClustersTask->getNewClusters()
#2 /var/www/nextcloud/apps/facerecognition/lib/BackgroundJob/Tasks/CreateClustersTask.php(90): OCA\FaceRecognition\BackgroundJob\Tasks\CreateClustersTask->createClusterIfNeeded()
#3 /var/www/nextcloud/apps/facerecognition/lib/BackgroundJob/BackgroundService.php(150): OCA\FaceRecognition\BackgroundJob\Tasks\CreateClustersTask->execute()
#4 /var/www/nextcloud/apps/facerecognition/lib/Command/BackgroundCommand.php(192): OCA\FaceRecognition\BackgroundJob\BackgroundService->execute()
#5 /var/www/nextcloud/3rdparty/symfony/console/Command/Command.php(298): OCA\FaceRecognition\Command\BackgroundCommand->execute()
#6 /var/www/nextcloud/3rdparty/symfony/console/Application.php(1040): Symfony\Component\Console\Command\Command->run()
#7 /var/www/nextcloud/3rdparty/symfony/console/Application.php(301): Symfony\Component\Console\Application->doRunCommand()
#8 /var/www/nextcloud/3rdparty/symfony/console/Application.php(171): Symfony\Component\Console\Application->doRun()
#9 /var/www/nextcloud/lib/private/Console/Application.php(213): Symfony\Component\Console\Application->run()
#10 /var/www/nextcloud/console.php(102): OC\Console\Application->run()
#11 /var/www/nextcloud/occ(11): require_once('...')

The first time I had installed Face recognation it has worked, but after changing the setting on the face detection in NC interface and perform a reset it does not works anymore?

Any idea why?

@ewok2
Copy link

ewok2 commented Oct 19, 2024

PS : I initialy test it with a higher number of picture (more than 20 000 picture) but for the last test I perform it on a small number :-)

@nordscan
Copy link

nordscan commented Oct 20, 2024

hi, the same (i tried it maybe a year ago and it was working)

tried external model installed on wsl2 and through Nextcloud AIO (Computing container for facerecognition container) too.

Nextcloud AIO v9.7.0
Nextcloud Hub 8 (29.0.8)
Face recognation 0.9.51

1/8 - Executing task CheckRequirementsTask (Check all requirements)
2/8 - Executing task CheckCronTask (Check that service is started from either cron or from command)
3/8 - Executing task DisabledUserRemovalTask (Purge all the information of a user when disable the analysis.)
4/8 - Executing task StaleImagesRemovalTask (Crawl for stale images (either missing in filesystem or under .nomedia) and remove them from DB)
5/8 - Executing task CreateClustersTask (Create new persons or update existing persons)
        Face clustering will be recreated with new information or changes
        There are 7635 faces for clustering
An unhandled exception has been thrown:
TypeError: OCA\FaceRecognition\Helper\Euclidean::distance(): Argument #1 ($vector1) must be of type array, string given, called in /var/www/html/custom_apps/facerecognition/lib/BackgroundJob/Tasks/CreateClustersTask.php on line 336 and defined in /var/www/html/custom_apps/facerecognition/lib/Helper/Euclidean.php:24
Stack trace:
#0 /var/www/html/custom_apps/facerecognition/lib/BackgroundJob/Tasks/CreateClustersTask.php(336): OCA\FaceRecognition\Helper\Euclidean::distance('[-0.10269370675...', '[-0.10269370675...')
#1 /var/www/html/custom_apps/facerecognition/lib/BackgroundJob/Tasks/CreateClustersTask.php(177): OCA\FaceRecognition\BackgroundJob\Tasks\CreateClustersTask->getNewClusters(Array)
#2 /var/www/html/custom_apps/facerecognition/lib/BackgroundJob/Tasks/CreateClustersTask.php(90): OCA\FaceRecognition\BackgroundJob\Tasks\CreateClustersTask->createClusterIfNeeded('nordscan')
#3 /var/www/html/custom_apps/facerecognition/lib/BackgroundJob/BackgroundService.php(150): OCA\FaceRecognition\BackgroundJob\Tasks\CreateClustersTask->execute(Object(OCA\FaceRecognition\BackgroundJob\FaceRecognitionContext))
#4 /var/www/html/custom_apps/facerecognition/lib/Command/BackgroundCommand.php(192): OCA\FaceRecognition\BackgroundJob\BackgroundService->execute(0, false, Object(OC\User\User), NULL, 'default-mode')
#5 /var/www/html/3rdparty/symfony/console/Command/Command.php(298): OCA\FaceRecognition\Command\BackgroundCommand->execute(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#6 /var/www/html/3rdparty/symfony/console/Application.php(1040): Symfony\Component\Console\Command\Command->run(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#7 /var/www/html/3rdparty/symfony/console/Application.php(301): Symfony\Component\Console\Application->doRunCommand(Object(OCA\FaceRecognition\Command\BackgroundCommand), Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#8 /var/www/html/3rdparty/symfony/console/Application.php(171): Symfony\Component\Console\Application->doRun(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#9 /var/www/html/lib/private/Console/Application.php(213): Symfony\Component\Console\Application->run(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#10 /var/www/html/console.php(102): OC\Console\Application->run()
#11 /var/www/html/occ(11): require_once('/var/www/html/c...')

@Oski19831
Copy link

I can confirm this Bug also. It is a WorkArround to manuel convert the json_string to an array.

I don´t know if this is a Problem with PHP. I use PHP8.2 and run it on a RPI4 with ARM64-CPU.

for me it work to edit the CreateClusterTaks.php on Line 311

$distance = dlib_vector_length($face1->descriptor, $face2->descriptor); to

if(!is_array($face1->descriptor)) { $face1->descriptor = json_decode($face1->descriptor, true); } if(!is_array($face2->descriptor)) { $face2->descriptor = json_decode($face2->descriptor, true); } $distance = dlib_vector_length($face1->descriptor, $face2->descriptor);

I hope this help temporaly...

@ewok2
Copy link

ewok2 commented Oct 21, 2024

If related to php I am using php8.3

@ewok2
Copy link

ewok2 commented Oct 21, 2024

@Oski19831 thanks your workaroud seem's to works for me !

@vwbusguy
Copy link

I can confirm this Bug also. It is a WorkArround to manuel convert the json_string to an array.

I don´t know if this is a Problem with PHP. I use PHP8.2 and run it on a RPI4 with ARM64-CPU.

for me it work to edit the CreateClusterTaks.php on Line 311

$distance = dlib_vector_length($face1->descriptor, $face2->descriptor); to

if(!is_array($face1->descriptor)) { $face1->descriptor = json_decode($face1->descriptor, true); } if(!is_array($face2->descriptor)) { $face2->descriptor = json_decode($face2->descriptor, true); } $distance = dlib_vector_length($face1->descriptor, $face2->descriptor);

I hope this help temporaly...

Heck yes! Maybe submit a Pull Request for this?

@Oski19831
Copy link

I never wrote Code for NC. So i think it is better Solution to change Code in DB-Object. But i don´t know the relation between NC and Entity - Class in NC. I think this Code is better in /lib/Db/Face.php. Or a function there... and call the function in CreateClusterTask.php ... But if it is helfull for you i will change the code...

@warriorcookie
Copy link

Same issue here.

Noticed Face Recognition was hung at Analyzing images - 31779 images detected - 339 images in queue - Ends approximately in 26 minutes.

went to CLI and executed the following:

:~$ sudo docker exec --user www-data -it nextcloud-aio-nextcloud php occ face:background_job
1/8 - Executing task CheckRequirementsTask (Check all requirements)
2/8 - Executing task CheckCronTask (Check that service is started from either cron or from command)
3/8 - Executing task DisabledUserRemovalTask (Purge all the information of a user when disable the analysis.)
4/8 - Executing task StaleImagesRemovalTask (Crawl for stale images (either missing in filesystem or under .nomedia) and remove them from DB)
5/8 - Executing task CreateClustersTask (Create new persons or update existing persons)
	Face clustering will be created for the first time.
	There are 2 faces for clustering
An unhandled exception has been thrown:
TypeError: OCA\FaceRecognition\Helper\Euclidean::distance(): Argument #1 ($vector1) must be of type array, string given, called in /var/www/html/custom_apps/facerecognition/lib/BackgroundJob/Tasks/CreateClustersTask.php on line 336 and defined in /var/www/html/custom_apps/facerecognition/lib/Helper/Euclidean.php:24
Stack trace:
#0 /var/www/html/custom_apps/facerecognition/lib/BackgroundJob/Tasks/CreateClustersTask.php(336): OCA\FaceRecognition\Helper\Euclidean::distance('[-0.04276097938...', '[-0.04276097938...')
#1 /var/www/html/custom_apps/facerecognition/lib/BackgroundJob/Tasks/CreateClustersTask.php(177): OCA\FaceRecognition\BackgroundJob\Tasks\CreateClustersTask->getNewClusters(Array)
#2 /var/www/html/custom_apps/facerecognition/lib/BackgroundJob/Tasks/CreateClustersTask.php(90): OCA\FaceRecognition\BackgroundJob\Tasks\CreateClustersTask->createClusterIfNeeded('admin')
#3 /var/www/html/custom_apps/facerecognition/lib/BackgroundJob/BackgroundService.php(150): OCA\FaceRecognition\BackgroundJob\Tasks\CreateClustersTask->execute(Object(OCA\FaceRecognition\BackgroundJob\FaceRecognitionContext))
#4 /var/www/html/custom_apps/facerecognition/lib/Command/BackgroundCommand.php(192): OCA\FaceRecognition\BackgroundJob\BackgroundService->execute(0, false, NULL, NULL, 'default-mode')
#5 /var/www/html/3rdparty/symfony/console/Command/Command.php(298): OCA\FaceRecognition\Command\BackgroundCommand->execute(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#6 /var/www/html/3rdparty/symfony/console/Application.php(1040): Symfony\Component\Console\Command\Command->run(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#7 /var/www/html/3rdparty/symfony/console/Application.php(301): Symfony\Component\Console\Application->doRunCommand(Object(OCA\FaceRecognition\Command\BackgroundCommand), Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#8 /var/www/html/3rdparty/symfony/console/Application.php(171): Symfony\Component\Console\Application->doRun(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#9 /var/www/html/lib/private/Console/Application.php(183): Symfony\Component\Console\Application->run(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#10 /var/www/html/console.php(87): OC\Console\Application->run(Object(Symfony\Component\Console\Input\ArgvInput))
#11 /var/www/html/occ(11): require_once('/var/www/html/c...')
#12 {main}

@Oski19831
Copy link

Same here. $faces returns a String instead of an array.

So for WorkArround add a function in /lib/Db/Face.php
function getDescriptorArray(): array { if(is_array($this->descriptor)) { return $this->descriptor; } else { return jsond_decode($this->descriptor, true); } }

and change each $face1['descriptor'] and $face2['descriptor'] to $face1->getDescriptorArray() and $face2->getDescriptorArray() in /lib/BackgroundJob/Tasks/CreateClusterTask.php

Or change my Solution above to your Code in CreateClusterTask.php

This is my Solutiion for this Issue.

This schould work as WorkArround or Wait until the Issue is fixed... I hope i could help you.

@tuxArg
Copy link

tuxArg commented Oct 22, 2024

Probably related I've got this error:

An unhandled exception has been thrown:
Error: Call to a member function getTimestamp() on string in /var/www/nextcloud/apps/facerecognition/lib/BackgroundJob/Tasks/CreateClustersTask.php:232

@nordscan
Copy link

#781

@mrmipo
Copy link

mrmipo commented Oct 23, 2024

Same here. $faces returns a String instead of an array.

So for WorkArround add a function in /lib/Db/Face.php function getDescriptorArray(): array { if(is_array($this->descriptor)) { return $this->descriptor; } else { return jsond_decode($this->descriptor, true); } }

and change each $face1['descriptor'] and $face2['descriptor'] to $face1->getDescriptorArray() and $face2->getDescriptorArray() in /lib/BackgroundJob/Tasks/CreateClusterTask.php

Or change my Solution above to your Code in CreateClusterTask.php

This is my Solutiion for this Issue.

This schould work as WorkArround or Wait until the Issue is fixed... I hope i could help you.

Hi

sorry but I not know what to do ...

I add function to lib/Db/Face.php

        public function setCreationTime($creationTime): void {
                if (is_a($creationTime, 'DateTime')) {
                        $this->creationTime = $creationTime;
                } else {
                        $this->creationTime = new \DateTime($creationTime);
                }
                $this->markFieldUpdated('creationTime');
        }
        public function getDescriptorArray(): array {
                if (is_array($this->descriptor)) {
                        return $this->descriptor;
                } else {
                        return jsond_decode($this->descriptor, true);
                }
        }

But not know what do you mean change each $face1['descriptor'] and $face2['descriptor'] to $face1->getDescriptorArray() as I don't see $face1['descriptor'] in file:

$grep "face1" /var/www/html/custom_apps/facerecognition/lib/BackgroundJob/Tasks/CreateClustersTask.php
                                $face1 = $faces[$i];
                                if (!isset($face1->descriptor)) {
                                        if (!is_array($face1->descriptor)) {
                                                $face1->descriptor = json_decode($face1->descriptor, true);
                                        $distance = dlib_vector_length($face1->descriptor, $face2->descriptor);
                                $face1 = $faces[$i];
                                if (!isset($face1->descriptor)) {
                                        $distance = Euclidean::distance($face1->descriptor, $face2->descriptor);

Can you attach corrected files ?

@Oski19831
Copy link

Oski19831 commented Oct 23, 2024

hello @mrmipo .

change $face1->descriptor to $face1->getDescriptorArray(). that should call the function in Class Face.php and returned an array and not the String from the DB. Try it.

EDIT:

And you don´t proof again in CreateTaskCluster.php if $facex->descriptor is an array. you proof it also in the function getDescriptorArray() in Face.php.

@tuxArg

For you the WorkArround ist like the Same. You get the TimeString instead a DateTime-Object. So it must be converted before call getTimestamp().

@tuxArg
Copy link

tuxArg commented Oct 23, 2024

For you the WorkArround ist like the Same. You get the TimeString instead a DateTime-Object. So it must be converted before call getTimestamp().

I did it this way: #781 (comment)

@mrmipo
Copy link

mrmipo commented Oct 23, 2024

hello @mrmipo .

change $face1->descriptor to $face1->getDescriptorArray(). that should call the function in Class Face.php and returned an array and not the String from the DB. Try it.

EDIT:

And you don´t proof again in CreateTaskCluster.php if $facex->descriptor is an array. you proof it also in the function getDescriptorArray() in Face.php.

@tuxArg

For you the WorkArround ist like the Same. You get the TimeString instead a DateTime-Object. So it must be converted before call getTimestamp().

Hi Oski19831

Ok I finally fix this issue and it's look like no it's working fine (manage new image/face and creating clustering) but without getDescriptorArray() as I was not able to understand how it's should be done. But I use your solution from beginning and from issue that I create. So I only modify one file CreateClustersTask.php . Output from diff:

$ diff CreateClustersTask.php_org CreateClustersTask.php
--- CreateClustersTask.php_org
+++ CreateClustersTask.php
@@ -229,10 +229,16 @@

                // We have some faces, but not that many, let's see when oldest one is generated.
                $oldestFace = $this->faceMapper->getOldestCreatedFaceWithoutPerson($userId, $modelId);
-               $oldestFaceTimestamp = $oldestFace->creationTime->getTimestamp();
+               if (is_string($oldestFace->creationTime)) {
+                       $oldestFaceTimestamp = strtotime($oldestFace->creationTime);
+                       $oldestFaceFormat=$oldestFace->creationTime;
+               } else {
+                       $oldestFaceTimestamp = $oldestFace->creationTime->getTimestamp();
+                       $oldestFaceFormat=$oldestFace->creationTime->format('Y-m-d H:i:s');
+               }
                $currentTimestamp = (new \DateTime())->getTimestamp();
                $this->logDebug(sprintf('Oldest face without persons for user %s and model %d is from %s',
-                               $userId, $modelId, $oldestFace->creationTime->format('Y-m-d H:i:s')));
+                               $userId, $modelId, $oldestFaceFormat));

                // todo: get rid of magic numbers (move to config)
                if ($currentTimestamp - $oldestFaceTimestamp > 2 * 60 * 60)
@@ -308,6 +314,12 @@
                                        if (!isset($face2->descriptor)) {
                                                continue;
                                        }
+                                       if (!is_array($face1->descriptor)) {
+                                               $face1->descriptor = json_decode($face1->descriptor, true);
+                                       }
+                                       if (!is_array($face2->descriptor)) {
+                                               $face2->descriptor = json_decode($face2->descriptor, true);
+                                       }
                                        $distance = dlib_vector_length($face1->descriptor, $face2->descriptor);
                                        if ($distance < $sensitivity) {
                                                $edges[] = array($i, $j);
@@ -333,6 +345,12 @@
                                        if (!isset($face2->descriptor)) {
                                                continue;
                                        }
+                                       if (!is_array($face1->descriptor)) {
+                                                $face1->descriptor = json_decode($face1->descriptor, true);
+                                        }
+                                        if (!is_array($face2->descriptor)) {
+                                                $face2->descriptor = json_decode($face2->descriptor, true);
+                                        }
                                        $distance = Euclidean::distance($face1->descriptor, $face2->descriptor);
                                        if ($distance < $sensitivity) {
                                                $edges[] = array($i, $j);

Really thanks for your help

@Oski19831
Copy link

Top no thanks. I test a modification which is easyer... i post an update if it pass the test....

@Oski19831
Copy link

Oski19831 commented Oct 23, 2024

it is also enough to change /lib/Db/face.php and add two Lines in function __construct()

public function __construct() {
          $this->addType('id', 'integer');
          $this->addType('image', 'integer');
          $this->addType('person', 'integer');
          $this->addType('isGroupable', 'bool');

          //This Lines fix the Isue
          $this->addType('descriptor', 'json');
          $this->addType('creationTime', 'datetime');
}

Then nothing else is to do.

Testet on NC HUB 8 (29.0.8)

@tocopaxi
Copy link

tocopaxi commented Nov 1, 2024

I can confirm this Bug also. It is a WorkArround to manuel convert the json_string to an array.

I don´t know if this is a Problem with PHP. I use PHP8.2 and run it on a RPI4 with ARM64-CPU.

for me it work to edit the CreateClusterTaks.php on Line 311

$distance = dlib_vector_length($face1->descriptor, $face2->descriptor); to

if(!is_array($face1->descriptor)) { $face1->descriptor = json_decode($face1->descriptor, true); } if(!is_array($face2->descriptor)) { $face2->descriptor = json_decode($face2->descriptor, true); } $distance = dlib_vector_length($face1->descriptor, $face2->descriptor);

I hope this help temporaly...

I had the same issue and can confirm that this solution by @Oski19831 works for me as well - thanks :)

@matiasdelellis
Copy link
Owner

Hi everyone,
I will soon release a version compatible with NC30, and I was thinking of deprecating NC29 since I can't test it. However, I see that some Nextcloud update is causing problems in NC29 with this application as well.. 😞

As I said, I couldn't reproduce this problem in my installations or in testing. However, I am trying the fix suggested by Oski19831, and in my case it does not cause any problems.

Here I leave you a tarball with all the changes introduced for nexctloud 30 and still compatible with nc29 plus this patch.

If you test it and confirm that it works, I will add it and release the update this week.. 😉

@benneti
Copy link

benneti commented Nov 7, 2024

I already had the change #780 (comment) on nc29 but installing the tar.gz did not seem to have broken anything.

@Oski19831
Copy link

Oski19831 commented Nov 8, 2024

Hi everyone, I will soon release a version compatible with NC30, and I was thinking of deprecating NC29 since I can't test it. However, I see that some Nextcloud update is causing problems in NC29 with this application as well.. 😞

As I said, I couldn't reproduce this problem in my installations or in testing. However, I am trying the fix suggested by Oski19831, and in my case it does not cause any problems.

Here I leave you a tarball with all the changes introduced for nexctloud 30 and still compatible with nc29 plus this patch.

If you test it and confirm that it works, I will add it and release the update this week.. 😉

I can confirm that this Version run on NC 29.

After installation i reseted all Photos in my Instance and rescan and all runs fine.

@priyankub
Copy link

Hi everyone, I will soon release a version compatible with NC30, and I was thinking of deprecating NC29 since I can't test it. However, I see that some Nextcloud update is causing problems in NC29 with this application as well.. 😞

As I said, I couldn't reproduce this problem in my installations or in testing. However, I am trying the fix suggested by Oski19831, and in my case it does not cause any problems.

Here I leave you a tarball with all the changes introduced for nexctloud 30 and still compatible with nc29 plus this patch.

If you test it and confirm that it works, I will add it and release the update this week.. 😉

Here is an error with the updated release in this attachment that showed up in my instance this morning:

{"reqId":"uezf2meFJydwiPrTwIDg","level":3,"time":"2024-11-20T13:05:58+00:00","remoteAddr":"192.168.1.48","user":"priyanku","app":"index","method":"GET","url":"/apps/facerecognition/face/7089/thumb/50","message":"OCP\\AppFramework\\Http\\DataDisplayResponse::__construct(): Argument #1 ($data) must be of type string, null given, called in /var/www/html/custom_apps/facerecognition/lib/Controller/FaceController.php on line 130 in file '/var/www/html/lib/public/AppFramework/Http/DataDisplayResponse.php' line 34","userAgent":"Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Mobile Safari/537.36","version":"30.0.2.2","exception":{"Exception":"Exception","Message":"OCP\\AppFramework\\Http\\DataDisplayResponse::__construct(): Argument #1 ($data) must be of type string, null given, called in /var/www/html/custom_apps/facerecognition/lib/Controller/FaceController.php on line 130 in file '/var/www/html/lib/public/AppFramework/Http/DataDisplayResponse.php' line 34","Code":0,"Trace":[{"file":"/var/www/html/lib/private/AppFramework/App.php","line":161,"function":"dispatch","class":"OC\\AppFramework\\Http\\Dispatcher","type":"->","args":[{"__class__":"OCA\\FaceRecognition\\Controller\\FaceController"},"getThumb"]},{"file":"/var/www/html/lib/private/Route/Router.php","line":302,"function":"main","class":"OC\\AppFramework\\App","type":"::","args":["OCA\\FaceRecognition\\Controller\\FaceController","getThumb",{"__class__":"OC\\AppFramework\\DependencyInjection\\DIContainer"},{"id":"7089","size":"50","_route":"facerecognition.face.getthumb"}]},{"file":"/var/www/html/lib/base.php","line":1001,"function":"match","class":"OC\\Route\\Router","type":"->","args":["/apps/facerecognition/face/7089/thumb/50"]},{"file":"/var/www/html/index.php","line":24,"function":"handleRequest","class":"OC","type":"::","args":[]}],"File":"/var/www/html/lib/private/AppFramework/Http/Dispatcher.php","Line":146,"Previous":{"Exception":"TypeError","Message":"OCP\\AppFramework\\Http\\DataDisplayResponse::__construct(): Argument #1 ($data) must be of type string, null given, called in /var/www/html/custom_apps/facerecognition/lib/Controller/FaceController.php on line 130","Code":0,"Trace":[{"file":"/var/www/html/custom_apps/facerecognition/lib/Controller/FaceController.php","line":130,"function":"__construct","class":"OCP\\AppFramework\\Http\\DataDisplayResponse","type":"->","args":[null,200,{"Content-Type":null}]},{"file":"/var/www/html/lib/private/AppFramework/Http/Dispatcher.php","line":208,"function":"getThumb","class":"OCA\\FaceRecognition\\Controller\\FaceController","type":"->","args":["7089","50"]},{"file":"/var/www/html/lib/private/AppFramework/Http/Dispatcher.php","line":114,"function":"executeController","class":"OC\\AppFramework\\Http\\Dispatcher","type":"->","args":[{"__class__":"OCA\\FaceRecognition\\Controller\\FaceController"},"getThumb"]},{"file":"/var/www/html/lib/private/AppFramework/App.php","line":161,"function":"dispatch","class":"OC\\AppFramework\\Http\\Dispatcher","type":"->","args":[{"__class__":"OCA\\FaceRecognition\\Controller\\FaceController"},"getThumb"]},{"file":"/var/www/html/lib/private/Route/Router.php","line":302,"function":"main","class":"OC\\AppFramework\\App","type":"::","args":["OCA\\FaceRecognition\\Controller\\FaceController","getThumb",{"__class__":"OC\\AppFramework\\DependencyInjection\\DIContainer"},{"id":"7089","size":"50","_route":"facerecognition.face.getthumb"}]},{"file":"/var/www/html/lib/base.php","line":1001,"function":"match","class":"OC\\Route\\Router","type":"->","args":["/apps/facerecognition/face/7089/thumb/50"]},{"file":"/var/www/html/index.php","line":24,"function":"handleRequest","class":"OC","type":"::","args":[]}],"File":"/var/www/html/lib/public/AppFramework/Http/DataDisplayResponse.php","Line":34},"message":"OCP\\AppFramework\\Http\\DataDisplayResponse::__construct(): Argument #1 ($data) must be of type string, null given, called in /var/www/html/custom_apps/facerecognition/lib/Controller/FaceController.php on line 130 in file '/var/www/html/lib/public/AppFramework/Http/DataDisplayResponse.php' line 34","exception":[],"CustomMessage":"OCP\\AppFramework\\Http\\DataDisplayResponse::__construct(): Argument #1 ($data) must be of type string, null given, called in /var/www/html/custom_apps/facerecognition/lib/Controller/FaceController.php on line 130 in file '/var/www/html/lib/public/AppFramework/Http/DataDisplayResponse.php' line 34"},"id":"673e0997317a4"}

@Oski19831
Copy link

Hi @priyankub. This error is not related to this App it think. Nextcloud cannot load the Data of one of your pictures and it retrunted null.

you can proof against null and return null. But i don´t know what does it with the response. But you can try it with a Line in 129 in /var/www/html/custom_apps/facerecognition/lib/Controller/FaceController.php
you will miss a Thumb than i think.
if($img->data === null) return;

@priyankub
Copy link

priyankub commented Nov 20, 2024

I rewrote that entire function to:

	public function getThumb ($id, $size) {
		$face = $this->faceMapper->find($id);
		if ($face === null) {			
			return new JSONResponse([], Http::STATUS_NOT_FOUND);
		}
	
		$image = $this->imageMapper->find($this->userId, $face->getImage());
		if ($image === null) {
			return new JSONResponse([], Http::STATUS_NOT_FOUND);
		}
	
		$fileId = $image->getFile();
		
		$userFolder = $this->rootFolder->getUserFolder($this->userId);
		$nodes = $userFolder->getById($fileId);
	
		if (empty($nodes)) {
			return new DataDisplayResponse('', Http::STATUS_OK, ['Content-Type' => 'text/plain']);
		}
	
		$file = $nodes[0];

		$ownerView = new \OC\Files\View('/'. $this->userId . '/files');
		$path = $userFolder->getRelativePath($file->getPath());
	
		$img = new OCP_Image();
		$fileName = $ownerView->getLocalFile($path);
	
		// Attempt to load and process the image
		if (!$img->loadFromFile($fileName)) {
			return new DataDisplayResponse('', Http::STATUS_OK, ['Content-Type' => 'text/plain']);
		}
	
		$img->fixOrientation();
	
		$x = $face->getX();
		$y = $face->getY();
		$w = $face->getWidth();
		$h = $face->getHeight();
	
		$padding = $h*0.35;
		$x -= $padding;
		$y -= $padding;
		$w += $padding*2;
		$h += $padding*2;
	
		if ($this->settingsService->getObfuscateFaces()) {
			$this->hipsterize($img, $face);
		}
	
		$img->crop($x, $y, $w, $h);
		$img->scaleDownToFit($size, $size);
	
		// Attempt to fetch processed image data	
		if ($img->data() === null) {
			return new DataDisplayResponse('', Http::STATUS_OK, ['Content-Type' => 'text/plain']);
		}
	
		$resp = new DataDisplayResponse($img->data(), Http::STATUS_OK, ['Content-Type' => $img->mimeType()]);
		$resp->setETag((string)crc32($img->data()));
		$resp->cacheFor(7 * 24 * 60 * 60);
		$resp->setLastModified(new \DateTime('now', new \DateTimeZone('GMT')));
	
		return $resp;
	}	

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests