TYPO3 Metadaten mit der Amazon Textract API befüllen

Ihr fragt euch sicherlich was das Bild mit TYPO3 zu tun hat? Dazu später mehr. In dem Blogartikel geht es um Bilder, in kleinen Teilen um Barrierefreiheit und um automatische Informationsanreicherung. Wer ein wenig mit machen möchte, der organisiert sich einen AWS Console Account und mit Credentials und dann kann es auch schon losgehen.


Was wollen wir erreichen?

Im ersten Schritt geht es darum, dass wir ein statisches lokales Bild mit der Amazon Textract API auslesen wollen. Amazon Textract gibt es zum automatischen Extrahieren von gedrucktem Text, Handschrift und Daten aus Dokumenten. Klassisch wie OCR, nur das es durchaus intelligenter sein kann, gerade bei komplexeren Dokumenten. Wir konzentrieren uns auf den Einstieg und eine einfache Anwendung.

Schauen wir uns doch das Beispielbild von der letzten Ostseetour einmal an. Man sieht den Zaun und die Infotafel der DWD Wetterstation in Pelzerhaken. Wir haben links ein Warnschild (Spoiler: Das wird nicht ausgelesen) und rechts das Informationsschild. In unserem simplen Beispiel möchte ich nur die Koordinaten von der Informationstafel auslesen, also einen Teilbereich.


Umsetzung


Erste Schritte mit AWS SDK

Damit ich lokal die API überhaupt ansprechen kann, müssen wir uns per Composer das AWS SDK für PHP installieren. Wir arbeiten mit AWS Profilen und legen uns im Home Verzeichnis einen .aws Ordner an, der zwei Textdateien beinhaltet: Die config und credentials Datei. Mehr dazu kann man hier finden. Achte bitte darauf, dass Profilname und Region später übereinstimmen. Gerade auch für andere Amazon APIs wichtig.


require '../vendor/autoload.php';

$options = [
    'profile' => 'DEIN_PROFILNAME',
    'region' => 'eu-central-1',
    'version' => 'latest'
];
$client = new TextractClient($options);
                                                

Man sollte wissen, dass Amazon für jeden Dienst einen eigenen Client hat, wir nutzen hier den TextractClient. Nachdem wir alles konfiguriert haben, feuern wir nun unseren ersten Request ab. Zuerst benötigen wir ein Testbild, dass als ByteStream verschickt wird. Ein Nutzen eines Bildes, welches im S3 Bucket liegt, geht natürlich auch.

Bild auslesen und analysieren


try {
    $imagePath = '/var/www/html/public/testbild.jpg';
    $fileHandlerImage = fopen($imagePath, 'rb');
    $image = fread($fileHandlerImage, filesize($imagePath));
    fclose($fileHandlerImage);

    $result = $client->detectDocumentText([
        'Document' => [
            'Bytes' => $image,
        ],
    ]);
} catch (AwsException $e) {
    echo '
Error: $e
'; }

Sofern alle Voraussetzungen gegeben sind, bekommt ihr von Amazon ein Ergebnis zurück. Das erste Ergebnis ist beeindruckend. Bis auf das Warnschild wurden alle Texte auf der Infotafel sauber erkannt. Amazon geht hier Zeile für Zeile vor, was uns das automatische Anreichern erschwert. Unterteilt werden Treffer in Page, Line und Word. So könnt ihr eine gewisse Struktur direkt mit den Daten herstellen.


[1] => Array
(
    [BlockType] => LINE
    [Confidence] => 99.396057128906
    [Text] => Deutscher Wetterdienst
    [Geometry] => Array
    (
        [BoundingBox] => Array
        (
            [Width] => 0.047028891742229
            [Height] => 0.0079845450818539
            [Left] => 0.59368813037872
            [Top] => 0.38027635216713
        )

        [Polygon] => Array
        (
            [0] => Array
            (
                [X] => 0.59368813037872
                [Y] => 0.38041678071022
            )
            [..]
        )
    )
    [...]
)
                                                

Im Ergebnis bekommen wir verschiedene Werte mit denen wir später arbeiten können:

  • Confidence - Treffsicherheit in Prozent
  • Den Type und dazugehörigen Text
  • Und man kann die Position des Treffers im Bild nachvollziehen

Unser Ziel muss es sein, neben dem Type "Line" nur die Treffer auszulesen, die in unserem gewählten Bereich sind.


Textbereich auswählen

Hier ist jetzt etwas Fantasie gefragt. Stellt euch vor, ihr habt im TYPO3 Backend das Croptool und definiert einen Bereich. Das könnte so aussehen:


In meinem Plain PHP Test wurden dieser Bereich und die Bildabmessungen fest definiert:


$imageWidth = 3226;
$imageHeight = 1814;

$xMin = 1280;
$xMax = 1495;

$yMin = 945;
$yMax = 1020;
                                        

Auch wenn wir nur einen Bereich als Text haben möchten, dann wird Amazon trotzdem das ganze Bild scannen. Wir müssen mit eigener Logik diese Filterung schaffen. Hierfür verwenden wir die Geometriewerte aus dem Amazon Ergebnis.


foreach ($result['Blocks'] as $phrase) {
    if ($phrase['BlockType'] === 'LINE') {
        $polygon = $phrase['Geometry']['Polygon'];
        $textIsInArea = true;
        foreach ($polygon as $point) {
            $xValue = round($point['X'] * $imageWidth);
            $yValue = round($point['Y'] * $imageHeight);

            $xCheck = ($xMin <= $xValue) && ($xValue <= $xMax);
            $yCheck = ($yMin <= $yValue) && ($yValue <= $yMax);

            if (!$xCheck || !$yCheck) {
                $textIsInArea = false;
                break;
            }
        }

        if ($textIsInArea) {
            [...]
        }
    }
}
                                        

Ausgabe

Wie man nun in der Ausgabe sehen kann, wurde nur der Teilbereich ausgelesen und die Werte sind auch mehr als zufriedenstellend.


Kosten

Die Kosten halten sich bei der Textverarbeitung in Grenzen. Auch hier kommt es wieder auf den Anwendungsfall und die Region an. Auf der Textract Pricing Seite kann man testweise alles einmal berechnen.


Ausblick


Spinnen wir die Idee mal im TYPO3 Kontext weiter

An dieser Stelle hat mein Plain PHP Test ein Ende gefunden. Wir haben nun die Möglichkeit automatisiert an Informationen in Bilder zu kommen. Das Verarbeiten und Zuordnen müssen wir aber dennoch selbst machen. Wir hätten jetzt die Möglichkeit diese Information in TYPO3 Metadaten zu speichern. Wenn man diesen Schritt auch noch automatisieren möchte, kann man sich hier einen EventListener für Uploads integrieren. Noch besser wäre ein Command, um die Verarbeitung im Backend asynchron zu halten.

Metadaten Beispiel im AfterFileAddedEventListener


public function setMetadata(AfterFileAddedEvent $event): AfterFileAddedEvent
{
    $file = $event->getFile();
    $metaData = $file->getMetaData();
    $metaData->offsetGet('description', $awsResult);
    $metaData->save();

    return $event;
}
                                            

Die ultimative Lösung wäre natürlich, wenn wir das TYPO3 Croptool direkt an den MetaDaten nutzen könnte. Man kann hier sicher mit einem RenderType arbeiten, ist aber natürlich nicht ganz so trivial.

Es gibt noch mehr Möglichkeiten bei Amazon, um Bilder und Videos automatisiert zu verarbeiten. Über den Einsatz sollte man durchaus diskutieren, aber je nach Kontext kann es sinnvoll sein. Und gerade auch das Anreichern von Medien ist im Sinne der Barrierefreiheit mehr als sinnvoll.