nextcloud-custom-apps-face-.../git_facerecognition/tests/Unit/MergeClustersTest.php
2024-09-03 09:12:12 +05:00

166 lines
6.4 KiB
PHP

<?php
/**
* @copyright Copyright (c) 2017, Matias De lellis <mati86dl@gmail.com>
* @copyright Copyright (c) 2018, Branko Kokanovic <branko@kokanovic.org>
*
* @author Branko Kokanovic <branko@kokanovic.org>
*
* @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\Tests\Unit;
use Test\TestCase;
use OCA\FaceRecognition\Db\PersonMapper;
use OCA\FaceRecognition\Db\ImageMapper;
use OCA\FaceRecognition\Db\FaceMapper;
use OCA\FaceRecognition\Service\SettingsService;
use OCA\FaceRecognition\BackgroundJob\Tasks\CreateClustersTask;
class MergeClustersTest extends TestCase {
/** @var CreateClustersTask Create cluster task */
private $createClusterTask;
/**
* {@inheritDoc}
*/
public function setUp(): void {
$personMapper = $this->getMockBuilder(PersonMapper::class)
->disableOriginalConstructor()
->getMock();
$imageMapper = $this->getMockBuilder(ImageMapper::class)
->disableOriginalConstructor()
->getMock();
$faceMapper = $this->getMockBuilder(FaceMapper::class)
->disableOriginalConstructor()
->getMock();
$settingsService = $this->getMockBuilder(SettingsService::class)
->disableOriginalConstructor()
->getMock();
$this->createClusterTask = new CreateClustersTask($personMapper, $imageMapper, $faceMapper, $settingsService);
}
/**
* Tests cluster merging. Starts with simple cases and go to more complex ones. IDs that are used
* do not have any significance, they are mostly random, except that ID<100 are for person IDs,
* and IDs>100 are reserved for face IDs (this is just convention in test, to make reading easier).
*/
public function testMergeClustersSimple() {
// Case when old cluster is empty and we get some new clusters
//
$result = $this->createClusterTask->mergeClusters(array(), array(1=>[101,102], 2=>[103,104]));
$this->assertEquals(count($result), 2);
$this->assertEquals($result[1], [101, 102]);
$this->assertEquals($result[2], [103, 104]);
// Case when old and new cluster are completely same
//
$c = array(3=>[101,103], 4=>[105,107]);
$result = $this->createClusterTask->mergeClusters($c, $c);
$this->assertEquals(count($result), 2);
$this->assertEquals($result[3], [101, 103]);
$this->assertEquals($result[4], [105, 107]);
// Case when cluster are the same, but person ID differ
//
$old = array(5=>[102,103], 6=>[105,106]);
$new = array(1=>[102,103], 2=>[105,106]);
$result = $this->createClusterTask->mergeClusters($old, $new);
$this->assertEquals(count($result), 2);
$this->assertEquals($result[5], [102, 103]);
$this->assertEquals($result[6], [105, 106]);
// Case when new faces are added to existing cluster
//
$old = array(7=>[102,103], 8=>[105,106]);
$new = array(1=>[102,103], 2=>[105,106, 107]);
$result = $this->createClusterTask->mergeClusters($old, $new);
$this->assertEquals(count($result), 2);
$this->assertEquals($result[7], [102, 103]);
$this->assertEquals($result[8], [105, 106, 107]);
// Case when new faces are added to new cluster
//
$old = array(3=>[110,111], 4=>[112,113]);
$new = array(1=>[110,111], 2=>[112,113], 3=>[114, 115, 116]);
$result = $this->createClusterTask->mergeClusters($old, $new);
$this->assertEquals(count($result), 3);
$this->assertEquals($result[3], [110, 111]);
$this->assertEquals($result[4], [112, 113]);
$this->assertEquals($result[5], [114, 115, 116]);
// Case when existing face "pops" to new cluster (cluster split)
//
$old = array(5=>[110,111,112], 6=>[113,114]);
$new = array(1=>[110,111], 2=>[113,114], 3=>[112]);
$result = $this->createClusterTask->mergeClusters($old, $new);
$this->assertEquals(count($result), 3);
$this->assertEquals($result[5], [110,111]);
$this->assertEquals($result[6], [113, 114]);
$this->assertEquals($result[7], [112]);
// Case when existing face is removed
//
$old = array(7=>[110,111], 8=>[113,114]);
$new = array(1=>[110], 2=>[113,114]);
$result = $this->createClusterTask->mergeClusters($old, $new);
$this->assertEquals(count($result), 2);
$this->assertEquals($result[7], [110]);
$this->assertEquals($result[8], [113, 114]);
// Case when all faces in cluster are removed (cluster dissapear)
//
$old = array(3=>[110,111], 4=>[113,114]);
$new = array(1=>[110,111]);
$result = $this->createClusterTask->mergeClusters($old, $new);
$this->assertEquals(count($result), 1);
$this->assertEquals($result[3], [110, 111]);
// Case when existing faces move to other cluster (cluster spil)
//
$old = array(5=>[110,111], 6=>[112,113,114]);
$new = array(1=>[110,111,112,113], 2=>[114]);
$result = $this->createClusterTask->mergeClusters($old, $new);
$this->assertEquals(count($result), 2);
$this->assertEquals($result[5], [110, 111,112,113]);
$this->assertEquals($result[6], [114]);
}
/**
* More complex case demostrating various use cases
*/
public function testMergeClustersComplex() {
// Case when old cluster is empty and we get some new clusters
//
$old = array(
10=>[100,101,102,103],
11=>[104,105,106,107],
12=>[108,109,110,111],
13=>[112,113,114,115]
);
$new = array(
1=>[100,101,102,103], // not touched
2=>[104,105,106,107,130], // new face added to this one
3=>[108,109,110], // one face removed
4=>[112,113,114], // one face moved to separate cluster
5=>[115,116], // face from cluster 4 (12) plus new face in this
6=>[117,118,119] // completely new cluster with new faces
);
$result = $this->createClusterTask->mergeClusters($old, $new);
$this->assertEquals(count($result), 6);
$this->assertEquals($result[10], [100, 101, 102, 103]);
$this->assertEquals($result[11], [104, 105, 106, 107, 130]);
$this->assertEquals($result[12], [108, 109, 110]);
$this->assertEquals($result[13], [112, 113, 114]);
$this->assertEquals($result[14], [115, 116]);
$this->assertEquals($result[15], [117, 118, 119]);
}
}