Google Cloud Vision über gRPC in Delphi

· Komponenten

Google Cloud Vision analysiert Bilder und sagt Ihnen, was darauf zu sehen ist: Es liefert beschreibende Labels zurück, liest gedruckten und handgeschriebenen Text (OCR), erkennt Gesichter, identifiziert berühmte Sehenswürdigkeiten und Logos und mehr. sgcWebSockets Enterprise liefert einen typisierten Vision-gRPC-Client, der auf TsgcGRPCClient aufsetzt, sodass Sie ein Bild senden und seine Annotationen aus Delphi und C++Builder zurücklesen können, ohne externe Laufzeitumgebung oder handgeschriebene Protobufs.

Wie es funktioniert

Cloud Vision stellt einen ImageAnnotator-gRPC-Dienst bereit. Ein Request ist ein Stapel aus einem oder mehreren Bildern, jedes gepaart mit der Liste der Features, die Sie erkennen lassen möchten, und die Response ist ein passender Stapel von Annotationen. Der gesamte Austausch besteht aus Protocol-Buffers-Nachrichten, die über HTTP/2 gerahmt werden.

sgcWebSockets liefert bereits einen vollständigen HTTP/2-Stack, daher ist der Transport ein TsgcHTTP2Client, der auf vision.googleapis.com:443 über TLS verweist. TsgcGRPCClient setzt darauf auf und übernimmt das gRPC-Framing, die Header, die Timeouts und das Trailer-Parsing. Die Vision-Nachrichtenklassen in sgcGRPC_Google_Vision sind typisierte Protobuf-Helfer: Sie füllen das Request-Objekt, rufen ToBytes auf, um es zu serialisieren, senden es mit dem generischen Client und laden die Antwort-Bytes mit LoadFromBytes zurück in ein typisiertes Response-Objekt.

Die Authentifizierung ist der standardmäßige Google-Dienstkonto-Ablauf. Ein selbstsigniertes JWT wird gegen ein Bearer-Token ausgetauscht und bei jedem Aufruf als gRPC-Metadaten gesendet. Da das JWT audience-gebunden ist, wird das Token auf den Vision-Endpunkt ausgerichtet, damit vision.googleapis.com es akzeptiert.

Die Clients einrichten

Erstellen Sie den HTTP/2-Transport, hängen Sie den gRPC-Client daran an und weisen Sie den Channel an, den binären Protobuf-Content-Type zu verwenden. Vision spricht application/grpc+proto.

uses
  sgcHTTP2_Client, sgcGRPC_Types, sgcGRPC_Client,
  sgcGRPC_Google_Vision;

var
  HTTP2: TsgcHTTP2Client;
  GRPC: TsgcGRPCClient;
begin
  HTTP2 := TsgcHTTP2Client.Create(nil);
  HTTP2.Host := 'vision.googleapis.com';
  HTTP2.Port := 443;
  HTTP2.TLS  := True;

  GRPC := TsgcGRPCClient.Create(nil);
  GRPC.Client := HTTP2;
  GRPC.ChannelOptions.ContentType := grpcProto;
  GRPC.ChannelOptions.Compression := grpcNoCompression;
end;

Authentifizierung

Das Bearer-Token stammt aus Ihren Dienstkonto-Anmeldedaten. Konfigurieren Sie die JWT-Optionen mit den Werten aus dem heruntergeladenen JSON-Schlüssel, richten Sie die Audience auf den Vision-Endpunkt aus und fügen Sie das resultierende Token zu DefaultMetadata hinzu, sodass es bei jedem gRPC-Aufruf mitgesendet wird.

// configure the service-account JWT (values from the JSON key file)
CloudClient.GoogleCloudOptions.Authentication := gcaJWT;
CloudClient.GoogleCloudOptions.JWT.ClientEmail  := ClientEmail;
CloudClient.GoogleCloudOptions.JWT.PrivateKeyId := PrivateKeyId;
CloudClient.GoogleCloudOptions.JWT.PrivateKey.Text := PrivateKey;
CloudClient.GoogleCloudOptions.JWT.ProjectId := ProjectId;
// the self-signed JWT is audience-bound to the Vision endpoint
CloudClient.GoogleCloudOptions.JWT.API_Endpoint :=
  'https://vision.googleapis.com/';

// once the token is acquired, send it as gRPC metadata
GRPC.DefaultMetadata.Clear;
GRPC.DefaultMetadata.Add('authorization', 'Bearer ' + Token);

Ein Bild annotieren

Zum Analysieren eines Bildes erstellen Sie einen TsgcGRPCVisionBatchAnnotateImagesRequest, fügen einen Bild-Request hinzu, verweisen ihn auf das Bild (hier ein Google-Cloud-Storage-URI, aber Sie können auch Rohbytes senden) und fügen ein oder mehrere Features hinzu. Jedes Feature hat einen FeatureType und ein optionales MaxResults. Serialisieren Sie mit ToBytes und rufen Sie die Methode BatchAnnotateImages des ImageAnnotator-Dienstes auf.

var
  oRequest: TsgcGRPCVisionBatchAnnotateImagesRequest;
  oImgReq: TsgcGRPCVisionAnnotateImageRequest;
  oFeature: TsgcGRPCVisionFeature;
  oResponse: TsgcGRPCResponse;
begin
  oRequest := TsgcGRPCVisionBatchAnnotateImagesRequest.Create;
  try
    oImgReq := oRequest.AddRequest;
    oImgReq.Image.Source.GcsImageUri :=
      'gs://cloud-samples-data/vision/demo-image.jpg';

    oFeature := oImgReq.AddFeature;
    oFeature.FeatureType := 4;   // LABEL_DETECTION
    oFeature.MaxResults := 10;

    oResponse := GRPC.Call('google.cloud.vision.v1.ImageAnnotator',
      'BatchAnnotateImages', oRequest.ToBytes);
  finally
    oRequest.Free;
  end;
end;

Die FeatureType-Werte folgen dem Enum der Vision-API: 1 FACE_DETECTION, 2 LANDMARK_DETECTION, 3 LOGO_DETECTION, 4 LABEL_DETECTION, 5 TEXT_DETECTION, 6 DOCUMENT_TEXT_DETECTION und die übrigen. Um mehrere Erkennungen am selben Bild in einem Roundtrip auszuführen, fügen Sie mehr als ein Feature hinzu.

Die Annotationen auslesen

Die Antwort-Bytes laden direkt in eine typisierte Batch-Response. Jedes Bild im Stapel trägt separate Listen für Label-, Landmarken-, Logo- und Text-Annotationen. Jeder Eintrag ist ein TsgcGRPCVisionEntityAnnotation mit einer Description und, bei Labels, einem Konfidenz-Score.

var
  oResponse: TsgcGRPCVisionBatchAnnotateImagesResponse;
  oImgResp: TsgcGRPCVisionAnnotateImageResponse;
  i, j: Integer;
begin
  oResponse := TsgcGRPCVisionBatchAnnotateImagesResponse.Create;
  try
    oResponse.LoadFromBytes(aData);
    for i := 0 to oResponse.ResponseCount - 1 do
    begin
      oImgResp := oResponse.Response(i);

      for j := 0 to oImgResp.LabelAnnotationCount - 1 do
        Memo1.Lines.Add('Label: ' + oImgResp.LabelAnnotation(j).Description +
          ' (score: ' + FloatToStr(oImgResp.LabelAnnotation(j).Score) + ')');

      for j := 0 to oImgResp.TextAnnotationCount - 1 do
        Memo1.Lines.Add('Text: ' + oImgResp.TextAnnotation(j).Description);

      for j := 0 to oImgResp.LandmarkAnnotationCount - 1 do
        Memo1.Lines.Add('Landmark: ' + oImgResp.LandmarkAnnotation(j).Description);
    end;
  finally
    oResponse.Free;
  end;
end;

Bilder aus Speicher oder aus Bytes

Die Bildquelle ist flexibel. Setzen Sie Image.Source.GcsImageUri für ein Objekt in Google Cloud Storage oder Image.Source.ImageUri für eine öffentliche HTTP(S)-URL. Um eine lokale Datei zu annotieren, lesen Sie sie in ein TBytes und weisen es stattdessen Image.Content zu, sodass das Bild inline im Request reist. Dieselben Request- und Response-Klassen verarbeiten jede Quelle.

Synchron oder asynchron

Das obige Beispiel verwendet das blockierende Call, das ein TsgcGRPCResponse mit dem StatusCode, den rohen Data-Bytes und den Trailern zurückgibt. Um die Benutzeroberfläche reaktionsfähig zu halten, verwenden Sie CallAsync und behandeln die Antwort im OnGRPCResponse-Ereignis, wo Sie aResponse.Data genau auf dieselbe Weise parsen. Ein Nicht-OK-Status erscheint über OnGRPCError und ein Transportfehler über OnGRPCException.

Verfügbarkeit

Der typisierte Vision-gRPC-Client ist Teil der sgcWebSockets Enterprise Edition und läuft unter Windows, macOS, Linux, iOS und Android. Ein sofort lauffähiges Beispiel befindet sich in Demos\21.GRPC\13.Vision, und die vollständige Referenz finden Sie auf der gRPC-Client-Produktseite.

Fragen oder Feedback? Nehmen Sie Kontakt auf. Sie erhalten eine Antwort von den Leuten, die den Code geschrieben haben.