Skip to content

Commit

Permalink
add annotation parsing
Browse files Browse the repository at this point in the history
  • Loading branch information
chbach committed Jul 25, 2024
1 parent af35796 commit a505bd8
Show file tree
Hide file tree
Showing 7 changed files with 1,736 additions and 145 deletions.
121 changes: 119 additions & 2 deletions src/Converter.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,18 @@
namespace Biigle\Modules\MetadataIfdo;

use Biigle\MediaType;
use Biigle\Services\MetadataParsing\Label;
use Biigle\Services\MetadataParsing\LabelAndUser;
use Biigle\Services\MetadataParsing\User;
use Biigle\Services\MetadataParsing\VolumeMetadata;
use Biigle\Shape;
use Illuminate\Support\Arr;

class Converter
{
private $acquisitionFormat = '';
private $annotators = [];
private $labels = [];

public function __construct($acquisitionFormat)
{
Expand All @@ -15,10 +22,13 @@ public function __construct($acquisitionFormat)

public function convert($ifdo)
{
$this->annotators = $this->extractIfdoAnnotators($ifdo->getImageSetHeader()['image-annotation-creators']);
$this->labels = $this->extractIfdoLabels($ifdo->getImageSetHeader()['image-annotation-labels']);

$data = new VolumeMetadata($this->mediaType());
foreach ($ifdo->getImageSetItems() as $name => $items)
{
if ( ! is_array($items))
if ( ! array_is_list($items))
{
$items = [$items];
}
Expand All @@ -39,12 +49,18 @@ public function convert($ifdo)

if ( ! is_null($fileData = $data->getFile($name)) && ! is_null($takenAt))
{
$fileData->addFrame(...$params);
$fileData->addFrame(...Arr::except($params, ['name']));
}
else
{
$class = $this->metadataClass();
$fileData = new $class(...$params);

if (isset($item['image-annotations']))
{
$this->addAnnotations($fileData, $item['image-annotations']);
}

$data->addFile($fileData);
}

Expand All @@ -62,6 +78,97 @@ protected function maybeCastToFloat(?string $value): ?float
return (is_null($value) || $value === '') ? null : floatval($value);
}

private function addAnnotations($fileData, $ifdoAnnotations)
{
foreach ($ifdoAnnotations as $ifdoAnnotation)
{
$fileData->addAnnotation($this->ifdoToBiigleAnnotation($ifdoAnnotation));
}
}

private function ifdoToBiigleAnnotation($ifdoAnnotation)
{
$class = $this->annotationClass();
$params = [
$this->ifdoShapeToBiigleShape($ifdoAnnotation['shape']),
$ifdoAnnotation['coordinates'],
$this->ifdoLabelsToBiigleLabelAndUsers($ifdoAnnotation['labels']),
];

if (isset($ifdoAnnotation['frames']))
{
$params[] = $ifdoAnnotation['frames'];
}

$annotation = new $class(...$params);

return $annotation;
}

private function ifdoLabelsToBiigleLabelAndUsers($ifdoLabels)
{
return array_map([$this, 'ifdoLabelToBiigleLabelAndUser'], $ifdoLabels);
}

private function ifdoLabelToBiigleLabelAndUser($ifdoLabel)
{
return new LabelAndUser(
$this->labelForId($ifdoLabel['label']),
$this->userForId($ifdoLabel['annotator'])
);
}

private function extractIfdoLabels($ifdoLabels)
{
$labels = [];
foreach ($ifdoLabels as $ifdoLabel)
{
$labels[$ifdoLabel['id']] = new Label($ifdoLabel['id'], $ifdoLabel['name']);
}
return $labels;
}

private function extractIfdoAnnotators($ifdoAnnotators)
{
$annotators = [];
foreach ($ifdoAnnotators as $ifdoAnnotator)
{
$annotators[$ifdoAnnotator['id']] = new User($ifdoAnnotator['id'], $ifdoAnnotator['name']);
}
return $annotators;
}

private function userForId($id)
{
return $this->annotators[$id];
}

private function labelForId($id)
{
return $this->labels[$id];
}

private function ifdoShapeToBiigleShape($shape)
{
switch ($shape)
{
case 'single-pixel':
return Shape::point();
case 'polyline':
return Shape::line();
case 'polygon':
return Shape::polygon();
case 'circle':
return Shape::circle();
case 'rectangle':
return Shape::rectangle();
case 'ellipse':
return Shape::ellipse();
case 'whole-frame':
return Shape::wholeFrame();
}
}

private function mediaType()
{
switch ($this->acquisitionFormat)
Expand All @@ -84,4 +191,14 @@ private function metadataClass()
}
}

private function annotationClass()
{
switch ($this->acquisitionFormat)
{
case 'photo':
return 'Biigle\Services\MetadataParsing\ImageAnnotation';
case 'video':
return 'Biigle\Services\MetadataParsing\VideoAnnotation';
}
}
}
2 changes: 1 addition & 1 deletion src/MetadataIfdoServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ public function boot(Modules $modules)
$this->loadViewsFrom(__DIR__ . '/resources/views', 'metadata-ifdo');

ParserFactory::extend(IfdoParser::class, 'image');
ParserFactory::extend(VideoIfdoParser::class, 'video');
ParserFactory::extend(IfdoParser::class, 'video');
$modules->register('metadata-ifdo', [
'viewMixins' => [
'metadataParsers',
Expand Down
6 changes: 0 additions & 6 deletions src/VideoIfdoParser.php

This file was deleted.

29 changes: 29 additions & 0 deletions tests/IfdoParserTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,5 +27,34 @@ public function testGetMetadata()
$this->assertEquals(2.1, $file->distanceToGround);
$this->assertEquals(5.1, $file->area);
$this->assertEquals(21, $file->yaw);

$this->assertCount(7, $file->getAnnotations());
$annotation = array_pop($file->annotations);

$this->assertEquals(3, $annotation->shape->id);
$this->assertEquals('Hans Wurst', $annotation->labels[0]->user->name);
}

public function testGetVideoMetadata()
{
$file = new File(__DIR__ . "/files/video-example-1.json");
$parser = new IfdoParser($file);
$data = $parser->getMetadata();
$this->assertEquals(MediaType::videoId(), $data->type->id);
$this->assertNull($data->name);
$this->assertNull($data->url);
$this->assertNull($data->handle);
$this->assertCount(1, $data->getFiles());
$file = $data->getFiles()->last();
$this->assertEquals('SO242_2_163-1_LowerHD.mp4', $file->name);
$this->assertEquals('2019-04-06 04:29:27.000000', $file->takenAt);
$this->assertEquals(-117.0214286, $file->lng);
$this->assertEquals(11.8582192, $file->lat);
$this->assertEquals(-4129.6, $file->gpsAltitude);
$this->assertEquals(2.1, $file->distanceToGround);
$this->assertEquals(5.1, $file->area);
$this->assertEquals(21, $file->yaw);

// var_dump($file);
}
}
6 changes: 3 additions & 3 deletions tests/MetadataIfdoServiceProviderTest.php
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
<?php

namespace Biigle\Tests\Modules\MetadataIfdo;

use Biigle\Modules\MetadataIfdo\ImageIfdoParser;
use Biigle\Modules\MetadataIfdo\MetadataIfdoServiceProvider;
use Biigle\Modules\MetadataIfdo\VideoIfdoParser;
use Biigle\Services\MetadataParsing\ParserFactory;
use Symfony\Component\HttpFoundation\File\File;
use TestCase;

class MetadataIfdoServiceProviderTest extends TestCase
Expand All @@ -19,7 +19,7 @@ public function testGetImageIfdo()
{
$this->markTestIncomplete('implement metadata parser');

$file = new File(__DIR__."/files/image-ifdo.json");
$file = new File(__DIR__ . "/files/image-ifdo.json");
$parser = ParserFactory::getParserForFile($file, 'image');
$this->assertInstanceOf(ImageIfdoParser::class, $parser);
}
Expand All @@ -28,7 +28,7 @@ public function testGetVideoIfdo()
{
$this->markTestIncomplete('implement metadata parser');

$file = new File(__DIR__."/files/video-ifdo.json");
$file = new File(__DIR__ . "/files/video-ifdo.json");
$parser = ParserFactory::getParserForFile($file, 'video');
$this->assertInstanceOf(VideoIfdoParser::class, $parser);
}
Expand Down
Loading

0 comments on commit a505bd8

Please sign in to comment.