Verarbeitungsantwort verarbeiten

Die Antwort auf eine Verarbeitungsanfrage enthält ein Document-Objekt mit allen bekannten Informationen zum verarbeiteten Dokument, einschließlich aller strukturierten Informationen, die Document AI extrahieren konnte.

Auf dieser Seite wird das Layout des Document-Objekts erläutert. Dazu werden Beispieldokumente bereitgestellt und Aspekte der OCR-Ergebnisse den spezifischen Elementen des Document-Objekt-JSON zugeordnet. Außerdem finden Sie hier Codebeispiele für Clientbibliotheken und das Document AI Toolbox SDK. In diesen Codebeispielen wird die Onlineverarbeitung verwendet, aber das Parsen des Document-Objekts funktioniert für die Batchverarbeitung genauso.

handle-response-1

Die orangefarbenen und blauen Rechtecke und Pfeile stehen dafür, dass mindestens ein Feld der verbundenen Objekte .layout bzw. detectedLanguage ist. Im Diagramm wird die Krähenfußnotation verwendet.

Verwenden Sie ein JSON-Anzeige- oder Bearbeitungstool, das speziell für das Ein- und Ausblenden von Elementen entwickelt wurde. Die Überprüfung von unformatiertem JSON in einem Texteditor ist ineffizient.

Text, Layout und Qualitätsfaktoren

Hier ein Beispiel für ein Textdokument:

handle-response-2

Hier ist das vollständige Dokumentobjekt, das vom Prozessor Enterprise Document OCR zurückgegeben wird:

JSON herunterladen

Diese OCR-Ausgabe ist auch immer in der Ausgabe des Document AI-Prozessors enthalten, da die OCR von den Prozessoren ausgeführt wird. Dabei werden die vorhandenen OCR-Daten verwendet. Deshalb können Sie solche JSON-Daten mit der Inline-Dokumentoption in Document AI-Prozessoren eingeben.

  image=None, # all our samples pass this var
  mime_type="application/json",
  inline_document=document_response # pass OCR output to CDE input - undocumented

Hier sind einige der wichtigen Felder:

Rohtext

Das Feld text enthält den Text, der von Document AI erkannt wird. Dieser Text enthält keine Layoutstruktur außer Leerzeichen, Tabulatoren und Zeilenumbrüchen. In diesem Feld werden die Textinformationen eines Dokuments gespeichert. Es dient als zentrale Informationsquelle für den Text des Dokuments. Andere Felder können sich anhand der Position (startIndex und endIndex) auf Teile des Textfelds beziehen.

  {
    text: "Sample Document\nHeading 1\nLorem ipsum dolor sit amet, ..."
  }

Seitengröße und Sprachen

Jedes page im Dokumentobjekt entspricht einer physischen Seite aus dem Beispieldokument. Die JSON-Beispielausgabe enthält eine Seite, da es sich um ein einzelnes PNG-Bild handelt.

  {
    "pages:" [
      {
        "pageNumber": 1,
        "dimension": {
          "width": 679.0,
          "height": 460.0,
          "unit": "pixels"
        },
      }
    ]
  }
{
  "pages": [
    {
      "detectedLanguages": [
        {
          "confidence": 0.98009938,
          "languageCode": "en"
        },
        {
          "confidence": 0.01990064,
          "languageCode": "und"
        }
      ]
    }
  ]
}

OCR-Daten

Mit Document AI OCR wird Text mit unterschiedlicher Granularität oder Organisation auf der Seite erkannt, z. B. Textblöcke, Absätze, Tokens und Symbole (die Symbolebene ist optional, wenn die Ausgabe von Daten auf Symbolebene konfiguriert ist). Das sind alles Mitglieder des Seitenobjekts.

Jedes Element hat ein entsprechendes layout, das seine Position und seinen Text beschreibt. Nicht textbasierte visuelle Elemente (z. B. Kästchen) sind ebenfalls auf Seitenebene.

{
  "pages": [
    {
      "paragraphs": [
        {
          "layout": {
            "textAnchor": {
              "textSegments": [
                {
                  "endIndex": "16"
                }
              ]
            },
            "confidence": 0.9939527,
            "boundingPoly": {
              "vertices": [ ... ],
              "normalizedVertices": [ ... ]
            },
            "orientation": "PAGE_UP"
          }
        }
      ]
    }
  ]
}

Der Roh-Text wird im textAnchor-Objekt referenziert, das mit startIndex und endIndex in den Haupttextstring indexiert wird.

  • Bei boundingPoly ist die obere linke Ecke der Seite der Ursprung (0,0). Positive X-Werte befinden sich rechts und positive Y-Werte unten.

  • Das vertices-Objekt verwendet dieselben Koordinaten wie das Originalbild, während normalizedVertices im Bereich [0,1] liegt. Es gibt eine Transformationsmatrix, die die Entzerrung der Messwerte und andere Attribute der Normalisierung des Bildes angibt.

  • Um das boundingPoly zu zeichnen, zeichnen Sie Liniensegmente von einem Eckpunkt zum nächsten. Schließen Sie das Polygon, indem Sie ein Liniensegment vom letzten zum ersten Eckpunkt zeichnen. Das orientation-Element des Layouts gibt an, ob der Text relativ zur Seite gedreht wurde.

Die folgenden Bilder zeigen Begrenzungspolygone für page.paragraphs, page.lines und page.tokens, um die Struktur des Dokuments zu veranschaulichen.

Absätze

handle-response-3

Linien

handle-response-4

Tokens

handle-response-5

Blöcke

handle-response-6

Der Prozessor Enterprise Document OCR kann die Qualität eines Dokuments anhand seiner Lesbarkeit bewerten.

Diese Qualitätsbewertung ist ein Qualitätsfaktor in [0, 1], wobei 1 für perfekte Qualität steht. Der Qualitätsfaktor wird im Feld Page.imageQualityScores zurückgegeben. Alle erkannten Fehler werden als quality/defect_* aufgeführt und absteigend nach Konfidenzwert sortiert.

Hier sehen Sie ein PDF, das zu dunkel und verschwommen ist, um es bequem lesen zu können:

PDF herunterladen

Hier sind die Informationen zur Dokumentqualität, die vom Prozessor Enterprise Document OCR zurückgegeben werden:

  {
    "pages": [
      {
        "imageQualityScores": {
          "qualityScore": 0.7811847,
          "detectedDefects": [
            {
              "type": "quality/defect_document_cutoff",
              "confidence": 1.0
            },
            {
              "type": "quality/defect_glare",
              "confidence": 0.97849524
            },
            {
              "type": "quality/defect_text_cutoff",
              "confidence": 0.5
            }
          ]
        }
      }
    ]
  }

Codebeispiele

Die folgenden Codebeispiele zeigen, wie Sie eine Verarbeitungsanfrage senden und dann die Felder lesen und im Terminal ausgeben:

Java

Weitere Informationen finden Sie in der Referenzdokumentation zur Document AI Java API.

Richten Sie zur Authentifizierung bei Document AI Standardanmeldedaten für Anwendungen ein. Weitere Informationen finden Sie unter Authentifizierung für eine lokale Entwicklungsumgebung einrichten.


import com.google.cloud.documentai.v1beta3.Document;
import com.google.cloud.documentai.v1beta3.DocumentProcessorServiceClient;
import com.google.cloud.documentai.v1beta3.DocumentProcessorServiceSettings;
import com.google.cloud.documentai.v1beta3.ProcessRequest;
import com.google.cloud.documentai.v1beta3.ProcessResponse;
import com.google.cloud.documentai.v1beta3.RawDocument;
import com.google.protobuf.ByteString;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeoutException;

public class ProcessOcrDocument {
  public static void processOcrDocument()
      throws IOException, InterruptedException, ExecutionException, TimeoutException {
    // TODO(developer): Replace these variables before running the sample.
    String projectId = "your-project-id";
    String location = "your-project-location"; // Format is "us" or "eu".
    String processerId = "your-processor-id";
    String filePath = "path/to/input/file.pdf";
    processOcrDocument(projectId, location, processerId, filePath);
  }

  public static void processOcrDocument(
      String projectId, String location, String processorId, String filePath)
      throws IOException, InterruptedException, ExecutionException, TimeoutException {
    // Initialize client that will be used to send requests. This client only needs
    // to be created
    // once, and can be reused for multiple requests. After completing all of your
    // requests, call
    // the "close" method on the client to safely clean up any remaining background
    // resources.
    String endpoint = String.format("%s-documentai.googleapis.com:443", location);
    DocumentProcessorServiceSettings settings =
        DocumentProcessorServiceSettings.newBuilder().setEndpoint(endpoint).build();
    try (DocumentProcessorServiceClient client = DocumentProcessorServiceClient.create(settings)) {
      // The full resource name of the processor, e.g.:
      // projects/project-id/locations/location/processor/processor-id
      // You must create new processors in the Cloud Console first
      String name =
          String.format("projects/%s/locations/%s/processors/%s", projectId, location, processorId);

      // Read the file.
      byte[] imageFileData = Files.readAllBytes(Paths.get(filePath));

      // Convert the image data to a Buffer and base64 encode it.
      ByteString content = ByteString.copyFrom(imageFileData);

      RawDocument document =
          RawDocument.newBuilder().setContent(content).setMimeType("application/pdf").build();

      // Configure the process request.
      ProcessRequest request =
          ProcessRequest.newBuilder().setName(name).setRawDocument(document).build();

      // Recognizes text entities in the PDF document
      ProcessResponse result = client.processDocument(request);
      Document documentResponse = result.getDocument();

      System.out.println("Document processing complete.");

      // Read the text recognition output from the processor
      // For a full list of Document object attributes,
      // please reference this page:
      // https://googleapis.dev/java/google-cloud-document-ai/latest/index.html

      // Get all of the document text as one big string
      String text = documentResponse.getText();
      System.out.printf("Full document text: '%s'\n", escapeNewlines(text));

      // Read the text recognition output from the processor
      List<Document.Page> pages = documentResponse.getPagesList();
      System.out.printf("There are %s page(s) in this document.\n", pages.size());

      for (Document.Page page : pages) {
        System.out.printf("Page %d:\n", page.getPageNumber());
        printPageDimensions(page.getDimension());
        printDetectedLanguages(page.getDetectedLanguagesList());
        printParagraphs(page.getParagraphsList(), text);
        printBlocks(page.getBlocksList(), text);
        printLines(page.getLinesList(), text);
        printTokens(page.getTokensList(), text);
      }
    }
  }

  private static void printPageDimensions(Document.Page.Dimension dimension) {
    String unit = dimension.getUnit();
    System.out.printf("    Width: %.1f %s\n", dimension.getWidth(), unit);
    System.out.printf("    Height: %.1f %s\n", dimension.getHeight(), unit);
  }

  private static void printDetectedLanguages(
      List<Document.Page.DetectedLanguage> detectedLangauges) {
    System.out.println("    Detected languages:");
    for (Document.Page.DetectedLanguage detectedLanguage : detectedLangauges) {
      String languageCode = detectedLanguage.getLanguageCode();
      float confidence = detectedLanguage.getConfidence();
      System.out.printf("        %s (%.2f%%)\n", languageCode, confidence * 100.0);
    }
  }

  private static void printParagraphs(List<Document.Page.Paragraph> paragraphs, String text) {
    System.out.printf("    %d paragraphs detected:\n", paragraphs.size());
    Document.Page.Paragraph firstParagraph = paragraphs.get(0);
    String firstParagraphText = getLayoutText(firstParagraph.getLayout().getTextAnchor(), text);
    System.out.printf("        First paragraph text: %s\n", escapeNewlines(firstParagraphText));
    Document.Page.Paragraph lastParagraph = paragraphs.get(paragraphs.size() - 1);
    String lastParagraphText = getLayoutText(lastParagraph.getLayout().getTextAnchor(), text);
    System.out.printf("        Last paragraph text: %s\n", escapeNewlines(lastParagraphText));
  }

  private static void printBlocks(List<Document.Page.Block> blocks, String text) {
    System.out.printf("    %d blocks detected:\n", blocks.size());
    Document.Page.Block firstBlock = blocks.get(0);
    String firstBlockText = getLayoutText(firstBlock.getLayout().getTextAnchor(), text);
    System.out.printf("        First block text: %s\n", escapeNewlines(firstBlockText));
    Document.Page.Block lastBlock = blocks.get(blocks.size() - 1);
    String lastBlockText = getLayoutText(lastBlock.getLayout().getTextAnchor(), text);
    System.out.printf("        Last block text: %s\n", escapeNewlines(lastBlockText));
  }

  private static void printLines(List<Document.Page.Line> lines, String text) {
    System.out.printf("    %d lines detected:\n", lines.size());
    Document.Page.Line firstLine = lines.get(0);
    String firstLineText = getLayoutText(firstLine.getLayout().getTextAnchor(), text);
    System.out.printf("        First line text: %s\n", escapeNewlines(firstLineText));
    Document.Page.Line lastLine = lines.get(lines.size() - 1);
    String lastLineText = getLayoutText(lastLine.getLayout().getTextAnchor(), text);
    System.out.printf("        Last line text: %s\n", escapeNewlines(lastLineText));
  }

  private static void printTokens(List<Document.Page.Token> tokens, String text) {
    System.out.printf("    %d tokens detected:\n", tokens.size());
    Document.Page.Token firstToken = tokens.get(0);
    String firstTokenText = getLayoutText(firstToken.getLayout().getTextAnchor(), text);
    System.out.printf("        First token text: %s\n", escapeNewlines(firstTokenText));
    Document.Page.Token lastToken = tokens.get(tokens.size() - 1);
    String lastTokenText = getLayoutText(lastToken.getLayout().getTextAnchor(), text);
    System.out.printf("        Last token text: %s\n", escapeNewlines(lastTokenText));
  }

  // Extract shards from the text field
  private static String getLayoutText(Document.TextAnchor textAnchor, String text) {
    if (textAnchor.getTextSegmentsList().size() > 0) {
      int startIdx = (int) textAnchor.getTextSegments(0).getStartIndex();
      int endIdx = (int) textAnchor.getTextSegments(0).getEndIndex();
      return text.substring(startIdx, endIdx);
    }
    return "[NO TEXT]";
  }

  private static String escapeNewlines(String s) {
    return s.replace("\n", "\\n").replace("\r", "\\r");
  }
}

Node.js

Weitere Informationen finden Sie in der Referenzdokumentation zur Document AI Node.js API.

Richten Sie zur Authentifizierung bei Document AI Standardanmeldedaten für Anwendungen ein. Weitere Informationen finden Sie unter Authentifizierung für eine lokale Entwicklungsumgebung einrichten.

/**
 * TODO(developer): Uncomment these variables before running the sample.
 */
// const projectId = 'YOUR_PROJECT_ID';
// const location = 'YOUR_PROJECT_LOCATION'; // Format is 'us' or 'eu'
// const processorId = 'YOUR_PROCESSOR_ID'; // Create processor in Cloud Console
// const filePath = '/path/to/local/pdf';

const {DocumentProcessorServiceClient} =
  require('@google-cloud/documentai').v1beta3;

// Instantiates a client
const client = new DocumentProcessorServiceClient();

async function processDocument() {
  // The full resource name of the processor, e.g.:
  // projects/project-id/locations/location/processor/processor-id
  // You must create new processors in the Cloud Console first
  const name = `projects/${projectId}/locations/${location}/processors/${processorId}`;

  // Read the file into memory.
  const fs = require('fs').promises;
  const imageFile = await fs.readFile(filePath);

  // Convert the image data to a Buffer and base64 encode it.
  const encodedImage = Buffer.from(imageFile).toString('base64');

  const request = {
    name,
    rawDocument: {
      content: encodedImage,
      mimeType: 'application/pdf',
    },
  };

  // Recognizes text entities in the PDF document
  const [result] = await client.processDocument(request);

  console.log('Document processing complete.');

  // Read the text recognition output from the processor
  // For a full list of Document object attributes,
  // please reference this page: https://googleapis.dev/nodejs/documentai/latest/index.html
  const {document} = result;
  const {text} = document;

  // Read the text recognition output from the processor
  console.log(`Full document text: ${JSON.stringify(text)}`);
  console.log(`There are ${document.pages.length} page(s) in this document.`);
  for (const page of document.pages) {
    console.log(`Page ${page.pageNumber}`);
    printPageDimensions(page.dimension);
    printDetectedLanguages(page.detectedLanguages);
    printParagraphs(page.paragraphs, text);
    printBlocks(page.blocks, text);
    printLines(page.lines, text