此內容適用於:v2.1 | 最新版本:
v4.0 (GA)
在本指南中,瞭解如何將檔智慧模型新增至您的應用程式和工作流程。 使用您選擇的程式設計語言 SDK 或 REST API。
Azure AI 檔智慧是雲端式 Azure AI 服務,使用機器學習從檔中擷取主要文字和結構元素。 建議您在了解技術時使用免費服務。 請記住,免費的頁數限制為每個月 500 頁。
從下列檔智慧模型中選擇,並從表單和檔中分析及擷取資料和值:
預建的讀取 模型是所有文檔智能模型的核心,並且可以偵測行、文字、位置和語言。 版面配置、一般檔、預先建置和自定義模型全都使用
read
模型作為從檔擷取文字的基礎。prebuilt-layout 模型會從文件和影像中擷取文字和文字位置、表格、選取標記和結構資訊。 您可以使用布局模型並啟用可選的查詢字串參數
features=keyValuePairs
擷取索引鍵/值組。預先設計的合約 模型會從合約中提取關鍵資訊。
prebuilt-healthInsuranceCard.us 模型會從美國醫療保險卡擷取重要資訊。
預先建置的稅務檔模型 模型會擷取美國稅務表格上報告的資訊。
預設發票 模型會從各種格式和品質的銷售發票中擷取關鍵欄位和明細項目。 欄位包括手機擷取的影像、掃描的檔和數位 PDF。
預建收據 模型會從印刷和手寫的銷售收據中擷取重要資訊。
預建的idDocument 模型會從美國駕駛執照、國際護照傳記頁面、美國州標識碼、社會保障卡和永久居民卡中擷取重要資訊。
- 預建的businessCard 模型會從名片影像擷取重要資訊和聯繫人詳細數據。
用戶端連結庫 |REST API 參考 | 套件| 範例|支援的 REST API 版本
先決條件
Azure 訂用帳戶 - 免費建立一個訂用帳戶。
Azure AI 服務或文件智慧服務資源。 建立 單一服務 或 多服務。 您可以使用免費定價層 (
F0
) 來試用服務,之後可升級至付費層以用於實際執行環境。從您所建立資源的金鑰和端點,將應用程式連線至 Azure 文件智慧服務。
- 部署資源之後,請選取 [前往資源]。
- 在左側導覽功能表中,選取 [金鑰和端點]。
- 複製其中一個金鑰和 端點,以供本文稍後使用。
位於 URL 位置的文件檔案。 針對此專案,您可以使用下表中針對每項功能的範例表單:
特徵 / 功能 modelID document-url Read 模型 prebuilt-read 範例手冊 版面配置模型 預設佈局 範例預約確認 W-2 表單模型 prebuilt-tax.us.w2 範例 W-2 表單 發票模型 prebuilt-invoice 範例發票 收據模型 prebuilt-receipt 範例收據 識別碼文件模型 prebuilt-idDocument 範例身份文件
設定環境變數
若要與此文件智慧服務互動,您必須建立 DocumentAnalysisClient
類別的執行個體。 若要這樣做,請使用 Azure 入口網站中的 key
和 endpoint
具現化用戶端。 針對此專案,請使用環境變數來儲存和存取認證。
這很重要
請謹慎使用 API 金鑰。 請勿在程式碼中直接包含 API 金鑰,且切勿公開張貼金鑰。 如果您使用 API 金鑰,請安全地將其儲存在 Azure 金鑰保存庫。 如需在應用程式中安全地使用 API 金鑰的詳細資訊,請參閱搭配 Azure 金鑰保存庫 的 API 金鑰。
如需 AI 服務安全性的詳細資訊,請參閱驗證對 Azure AI 服務的要求。
若要設定 Document Intelligence 資源金鑰的環境變數,請開啟主控台視窗,並遵循作系統和開發環境的指示。 將 <yourKey> 和 <yourEndpoint> 取代為 Azure 入口網站中資源的值。
Windows 中的環境變數不會區分大小寫。 它們通常會以大寫方式宣告,單字之間以底線連結。 在命令提示字元中,執行下列命令:
設定您的金鑰變數:
setx DI_KEY <yourKey>
設定您的端點變數
setx DI_ENDPOINT <yourEndpoint>
設定環境變數之後,請關閉 [命令提示字元] 視窗。 值會維持不變,直到您再次變更這些值為止。
重新啟動讀取環境變數的任何執行中程式。 例如,如果您使用 Visual Studio 或 Visual Studio Code 作為編輯器,請在執行範例程式代碼之前重新啟動。
以下是搭配環境變數使用的一些更實用的命令:
命令 | 動作 | 範例 |
---|---|---|
setx VARIABLE_NAME= |
將值設定為空字串,以刪除環境變數。 | setx DI_KEY= |
setx VARIABLE_NAME=value |
設定或變更環境變數的值。 | setx DI_KEY=<yourKey> |
set VARIABLE_NAME |
顯示特定環境變數的值。 | set DI_KEY |
set |
顯示所有環境變數。 | set |
設定程式設計環境
啟動 Visual Studio。
在起始頁面上,選擇 [建立新專案。
在 [建立新專案] 頁面上,在搜尋方塊中輸入主控台。 選取 主控台應用程式 範本,然後按一下 [下一步]。
在 [設定新專案] 頁面中,於 [專案 名稱] 底下輸入 docIntelligence_app。 然後選取下一步。
在 [其他資訊] 頁面中,選取 [.NET 8.0 (長期支援)],然後選取 [建立 ]。
使用 NuGet 安裝用戶端程式庫
以滑鼠右鍵按下您的 docIntelligence_app 項目,然後選取 [管理 NuGet 套件... ]。
選取 [流覽] 索引標籤,然後輸入 Azure.AI.DocumentIntelligence。
從下拉式功能表中選擇版本,並在專案中安裝套件。
建置您的 應用程式
備註
從 .NET 6 開始,使用 console
範本的新專案會產生與舊版不同的新程式樣式。 新輸出會使用最新的 C# 功能,以簡化您需要撰寫的程式碼。
當您使用較新版本時,只需要撰寫 Main
方法的主體。 您不需要包含最上層陳述式、全域 using 指示詞或隱含 using 指示詞。 如需詳細資訊,請參閱 C# 主控台應用程式範本會產生最上層陳述式 (部分內容可能是機器或 AI 翻譯)。
開啟 Program.cs 檔案。
刪除現有的程式代碼,包括行
Console.Writeline("Hello World!")
。選取下列其中一個程式代碼範例,並將/貼到應用程式的 Program.cs 檔案中:
將程式代碼範例新增至應用程式之後,請選擇專案名稱旁的綠色 [開始] 按鈕,以建置和執行程式,或按 F5。
使用 Read 模型
using Azure;
using Azure.AI.DocumentIntelligence;
//use your `key` and `endpoint` environment variables to create your `AzureKeyCredential` and `DocumentIntelligenceClient` instances
string key = Environment.GetEnvironmentVariable("DI_KEY");
string endpoint = Environment.GetEnvironmentVariable("DI_ENDPOINT");
AzureKeyCredential credential = new AzureKeyCredential(key);
DocumentIntelligenceClient client = new DocumentIntelligenceClient(new Uri(endpoint), credential);
//sample document
Uri fileUri = new Uri("https://raw.githubusercontent.com/Azure-Samples/cognitive-services-REST-api-samples/master/curl/form-recognizer/rest-api/read.png");
Operation<AnalyzeResult> operation = await client.AnalyzeDocumentAsync(WaitUntil.Completed, "prebuilt-read", fileUri);
AnalyzeResult result = operation.Value;
foreach (DocumentPage page in result.Pages)
{
Console.WriteLine($"Document Page {page.PageNumber} has {page.Lines.Count} line(s), {page.Words.Count} word(s),");
Console.WriteLine($"and {page.SelectionMarks.Count} selection mark(s).");
for (int i = 0; i < page.Lines.Count; i++)
{
DocumentLine line = page.Lines[i];
Console.WriteLine($" Line {i} has content: '{line.Content}'.");
Console.WriteLine($" Its bounding polygon (points ordered clockwise):");
for (int j = 0; j < line.Polygon.Count; j++)
{
Console.WriteLine($" Point {j} => X: {line.Polygon[j].X}, Y: {line.Polygon[j].Y}");
}
}
}
foreach (DocumentStyle style in result.Styles)
{
// Check the style and style confidence to see if text is handwritten.
// Note that value '0.8' is used as an example.
bool isHandwritten = style.IsHandwritten.HasValue && style.IsHandwritten == true;
if (isHandwritten && style.Confidence > 0.8)
{
Console.WriteLine($"Handwritten content found:");
foreach (DocumentSpan span in style.Spans)
{
Console.WriteLine($" Content: {result.Content.Substring(span.Index, span.Length)}");
}
}
}
Console.WriteLine("Detected languages:");
foreach (DocumentLanguage language in result.Languages)
{
Console.WriteLine($" Found language with locale'{language.Locale}' with confidence {language.Confidence}.");
}
請瀏覽 GitHub 上的 Azure 範例存放庫,並檢視 read
模型輸出。
使用 Layout 模型
using Azure;
using Azure.AI.DocumentIntelligence;
//use your `key` and `endpoint` environment variables to create your `AzureKeyCredential` and `DocumentIntelligenceClient` instances
string key = Environment.GetEnvironmentVariable("DI_KEY");
string endpoint = Environment.GetEnvironmentVariable("DI_ENDPOINT");
AzureKeyCredential credential = new AzureKeyCredential(key);
DocumentIntelligenceClient client = new DocumentIntelligenceClient(new Uri(endpoint), credential);
// sample document document
Uri fileUri = new Uri ("https://raw.githubusercontent.com/Azure-Samples/cognitive-services-REST-api-samples/master/curl/form-recognizer/rest-api/layout.png");
Operation<AnalyzeResult> operation = await client.AnalyzeDocumentAsync(WaitUntil.Completed, "prebuilt-layout", fileUri);
AnalyzeResult result = operation.Value;
foreach (DocumentPage page in result.Pages)
{
Console.WriteLine($"Document Page {page.PageNumber} has {page.Lines.Count} line(s), {page.Words.Count} word(s),");
Console.WriteLine($"and {page.SelectionMarks.Count} selection mark(s).");
for (int i = 0; i < page.Lines.Count; i++)
{
DocumentLine line = page.Lines[i];
Console.WriteLine($" Line {i} has content: '{line.Content}'.");
Console.WriteLine($" Its bounding polygon (points ordered clockwise):");
for (int j = 0; j < line.Polygon.Count; j++)
{
Console.WriteLine($" Point {j} => X: {line.Polygon[j].X}, Y: {line.Polygon[j].Y}");
}
}
for (int i = 0; i < page.SelectionMarks.Count; i++)
{
DocumentSelectionMark selectionMark = page.SelectionMarks[i];
Console.WriteLine($" Selection Mark {i} is {selectionMark.State}.");
Console.WriteLine($" Its bounding polygon (points ordered clockwise):");
for (int j = 0; j < selectionMark.Polygon.Count; j++)
{
Console.WriteLine($" Point {j} => X: {selectionMark.Polygon[j].X}, Y: {selectionMark.Polygon[j].Y}");
}
}
}
Console.WriteLine("Paragraphs:");
foreach (DocumentParagraph paragraph in result.Paragraphs)
{
Console.WriteLine($" Paragraph content: {paragraph.Content}");
if (paragraph.Role != null)
{
Console.WriteLine($" Role: {paragraph.Role}");
}
}
foreach (DocumentStyle style in result.Styles)
{
// Check the style and style confidence to see if text is handwritten.
// Note that value '0.8' is used as an example.
bool isHandwritten = style.IsHandwritten.HasValue && style.IsHandwritten == true;
if (isHandwritten && style.Confidence > 0.8)
{
Console.WriteLine($"Handwritten content found:");
foreach (DocumentSpan span in style.Spans)
{
Console.WriteLine($" Content: {result.Content.Substring(span.Index, span.Length)}");
}
}
}
Console.WriteLine("The following tables were extracted:");
for (int i = 0; i < result.Tables.Count; i++)
{
DocumentTable table = result.Tables[i];
Console.WriteLine($" Table {i} has {table.RowCount} rows and {table.ColumnCount} columns.");
foreach (DocumentTableCell cell in table.Cells)
{
Console.WriteLine($" Cell ({cell.RowIndex}, {cell.ColumnIndex}) has kind '{cell.Kind}' and content: '{cell.Content}'.");
}
}
請瀏覽 GitHub 上的 Azure 範例存放庫,並檢視 版面配置模型輸出。
使用通用文件模型
using Azure;
using Azure.AI.DocumentIntelligence;
//use your `key` and `endpoint` environment variables to create your `AzureKeyCredential` and `DocumentIntelligenceClient` instances
string key = Environment.GetEnvironmentVariable("DI_KEY");
string endpoint = Environment.GetEnvironmentVariable("DI_ENDPOINT");
AzureKeyCredential credential = new AzureKeyCredential(key);
DocumentIntelligenceClient client = new DocumentIntelligenceClient(new Uri(endpoint), credential);
// sample document document
Uri fileUri = new Uri("https://raw.githubusercontent.com/Azure-Samples/cognitive-services-REST-api-samples/master/curl/form-recognizer/sample-layout.pdf");
Operation<AnalyzeResult> operation = await client.AnalyzeDocumentAsync(WaitUntil.Completed, "prebuilt-document", fileUri);
AnalyzeResult result = operation.Value;
Console.WriteLine("Detected key-value pairs:");
foreach (DocumentKeyValuePair kvp in result.KeyValuePairs)
{
if (kvp.Value == null)
{
Console.WriteLine($" Found key with no value: '{kvp.Key.Content}'");
}
else
{
Console.WriteLine($" Found key-value pair: '{kvp.Key.Content}' and '{kvp.Value.Content}'");
}
}
foreach (DocumentPage page in result.Pages)
{
Console.WriteLine($"Document Page {page.PageNumber} has {page.Lines.Count} line(s), {page.Words.Count} word(s),");
Console.WriteLine($"and {page.SelectionMarks.Count} selection mark(s).");
for (int i = 0; i < page.Lines.Count; i++)
{
DocumentLine line = page.Lines[i];
Console.WriteLine($" Line {i} has content: '{line.Content}'.");
Console.WriteLine($" Its bounding polygon (points ordered clockwise):");
for (int j = 0; j < line.Polygon.Count; j++)
{
Console.WriteLine($" Point {j} => X: {line.Polygon[j].X}, Y: {line.Polygon[j].Y}");
}
}
for (int i = 0; i < page.SelectionMarks.Count; i++)
{
DocumentSelectionMark selectionMark = page.SelectionMarks[i];
Console.WriteLine($" Selection Mark {i} is {selectionMark.State}.");
Console.WriteLine($" Its bounding polygon (points ordered clockwise):");
for (int j = 0; j < selectionMark.Polygon.Count; j++)
{
Console.WriteLine($" Point {j} => X: {selectionMark.Polygon[j].X}, Y: {selectionMark.Polygon[j].Y}");
}
}
}
foreach (DocumentStyle style in result.Styles)
{
// Check the style and style confidence to see if text is handwritten.
// Note that value '0.8' is used as an example.
bool isHandwritten = style.IsHandwritten.HasValue && style.IsHandwritten == true;
if (isHandwritten && style.Confidence > 0.8)
{
Console.WriteLine($"Handwritten content found:");
foreach (DocumentSpan span in style.Spans)
{
Console.WriteLine($" Content: {result.Content.Substring(span.Index, span.Length)}");
}
}
}
Console.WriteLine("The following tables were extracted:");
for (int i = 0; i < result.Tables.Count; i++)
{
DocumentTable table = result.Tables[i];
Console.WriteLine($" Table {i} has {table.RowCount} rows and {table.ColumnCount} columns.");
foreach (DocumentTableCell cell in table.Cells)
{
Console.WriteLine($" Cell ({cell.RowIndex}, {cell.ColumnIndex}) has kind '{cell.Kind}' and content: '{cell.Content}'.");
}
}
請瀏覽 GitHub 上的 Azure 範例存放庫,並檢視 一般檔案模型輸出。
使用 W-2 稅務模型
using Azure;
using Azure.AI.DocumentIntelligence;
//use your `key` and `endpoint` environment variables to create your `AzureKeyCredential` and `DocumentIntelligenceClient` instances
string key = Environment.GetEnvironmentVariable("DI_KEY");
string endpoint = Environment.GetEnvironmentVariable("DI_ENDPOINT");
AzureKeyCredential credential = new AzureKeyCredential(key);
DocumentIntelligenceClient client = new DocumentIntelligenceClient(new Uri(endpoint), credential);
// sample document document
Uri w2Uri = new Uri("https://raw.githubusercontent.com/Azure-Samples/cognitive-services-REST-api-samples/master/curl/form-recognizer/rest-api/w2.png");
Operation<AnalyzeResult> operation = await client.AnalyzeDocumentAsync(WaitUntil.Completed, "prebuilt-tax.us.w2", w2Uri);
AnalyzeResult result = operation.Value;
for (int i = 0; i < result.Documents.Count; i++)
{
Console.WriteLine($"Document {i}:");
AnalyzedDocument document = result.Documents[i];
if (document.Fields.TryGetValue("AdditionalInfo", out DocumentField? additionalInfoField))
{
if (additionalInfoField.FieldType == DocumentFieldType.List)
{
foreach (DocumentField infoField in additionalInfoField.Value.AsList())
{
Console.WriteLine("AdditionalInfo:");
if (infoField.FieldType == DocumentFieldType.Dictionary)
{
IReadOnlyDictionary<string, DocumentField> infoFields = infoField.Value.AsDictionary();
if (infoFields.TryGetValue("Amount", out DocumentField? amountField))
{
if (amountField.FieldType == DocumentFieldType.Double)
{
double amount = amountField.Value.AsDouble();
Console.WriteLine($" Amount: '{amount}', with confidence {amountField.Confidence}");
}
}
if (infoFields.TryGetValue("LetterCode", out DocumentField? letterCodeField))
{
if (letterCodeField.FieldType == DocumentFieldType.String)
{
string letterCode = letterCodeField.Value.AsString();
Console.WriteLine($" LetterCode: '{letterCode}', with confidence {letterCodeField.Confidence}");
}
}
}
}
}
}
if (document.Fields.TryGetValue("AllocatedTips", out DocumentField? allocatedTipsField))
{
if (allocatedTipsField.FieldType == DocumentFieldType.Double)
{
double allocatedTips = allocatedTipsField.Value.AsDouble();
Console.WriteLine($"Allocated Tips: '{allocatedTips}', with confidence {allocatedTipsField.Confidence}");
}
}
if (document.Fields.TryGetValue("Employer", out DocumentField? employerField))
{
if (employerField.FieldType == DocumentFieldType.Dictionary)
{
IReadOnlyDictionary<string, DocumentField> employerFields = employerField.Value.AsDictionary();
if (employerFields.TryGetValue("Name", out DocumentField? employerNameField))
{
if (employerNameField.FieldType == DocumentFieldType.String)
{
string name = employerNameField.Value.AsString();
Console.WriteLine($"Employer Name: '{name}', with confidence {employerNameField.Confidence}");
}
}
if (employerFields.TryGetValue("IdNumber", out DocumentField? idNumberField))
{
if (idNumberField.FieldType == DocumentFieldType.String)
{
string id = idNumberField.Value.AsString();
Console.WriteLine($"Employer ID Number: '{id}', with confidence {idNumberField.Confidence}");
}
}
if (employerFields.TryGetValue("Address", out DocumentField? addressField))
{
if (addressField.FieldType == DocumentFieldType.Address)
{
Console.WriteLine($"Employer Address: '{addressField.Content}', with confidence {addressField.Confidence}");
}
}
}
}
}
請瀏覽 GitHub 上的 Azure 範例存放庫,並檢視 W-2 稅務模型輸出。
使用發票模型
using Azure;
using Azure.AI.DocumentIntelligence;
//use your `key` and `endpoint` environment variables to create your `AzureKeyCredential` and `DocumentIntelligenceClient` instances
string key = Environment.GetEnvironmentVariable("DI_KEY");
string endpoint = Environment.GetEnvironmentVariable("DI_ENDPOINT");
AzureKeyCredential credential = new AzureKeyCredential(key);
DocumentIntelligenceClient client = new DocumentIntelligenceClient(new Uri(endpoint), credential);
// sample document document
Uri invoiceUri = new Uri("https://github.com/Azure-Samples/cognitive-services-REST-api-samples/raw/master/curl/form-recognizer/rest-api/invoice.pdf");
Operation<AnalyzeResult> operation = await client.AnalyzeDocumentAsync(WaitUntil.Completed, "prebuilt-invoice", invoiceUri);
AnalyzeResult result = operation.Value;
for (int i = 0; i < result.Documents.Count; i++)
{
Console.WriteLine($"Document {i}:");
AnalyzedDocument document = result.Documents[i];
if (document.Fields.TryGetValue("VendorName", out DocumentField vendorNameField))
{
if (vendorNameField.FieldType == DocumentFieldType.String)
{
string vendorName = vendorNameField.Value.AsString();
Console.WriteLine($"Vendor Name: '{vendorName}', with confidence {vendorNameField.Confidence}");
}
}
if (document.Fields.TryGetValue("CustomerName", out DocumentField customerNameField))
{
if (customerNameField.FieldType == DocumentFieldType.String)
{
string customerName = customerNameField.Value.AsString();
Console.WriteLine($"Customer Name: '{customerName}', with confidence {customerNameField.Confidence}");
}
}
if (document.Fields.TryGetValue("Items", out DocumentField itemsField))
{
if (itemsField.FieldType == DocumentFieldType.List)
{
foreach (DocumentField itemField in itemsField.Value.AsList())
{
Console.WriteLine("Item:");
if (itemField.FieldType == DocumentFieldType.Dictionary)
{
IReadOnlyDictionary<string, DocumentField> itemFields = itemField.Value.AsDictionary();
if (itemFields.TryGetValue("Description", out DocumentField itemDescriptionField))
{
if (itemDescriptionField.FieldType == DocumentFieldType.String)
{
string itemDescription = itemDescriptionField.Value.AsString();
Console.WriteLine($" Description: '{itemDescription}', with confidence {itemDescriptionField.Confidence}");
}
}
if (itemFields.TryGetValue("Amount", out DocumentField itemAmountField))
{
if (itemAmountField.FieldType == DocumentFieldType.Currency)
{
CurrencyValue itemAmount = itemAmountField.Value.AsCurrency();
Console.WriteLine($" Amount: '{itemAmount.Symbol}{itemAmount.Amount}', with confidence {itemAmountField.Confidence}");
}
}
}
}
}
}
if (document.Fields.TryGetValue("SubTotal", out DocumentField subTotalField))
{
if (subTotalField.FieldType == DocumentFieldType.Currency)
{
CurrencyValue subTotal = subTotalField.Value.AsCurrency();
Console.WriteLine($"Sub Total: '{subTotal.Symbol}{subTotal.Amount}', with confidence {subTotalField.Confidence}");
}
}
if (document.Fields.TryGetValue("TotalTax", out DocumentField totalTaxField))
{
if (totalTaxField.FieldType == DocumentFieldType.Currency)
{
CurrencyValue totalTax = totalTaxField.Value.AsCurrency();
Console.WriteLine($"Total Tax: '{totalTax.Symbol}{totalTax.Amount}', with confidence {totalTaxField.Confidence}");
}
}
if (document.Fields.TryGetValue("InvoiceTotal", out DocumentField invoiceTotalField))
{
if (invoiceTotalField.FieldType == DocumentFieldType.Currency)
{
CurrencyValue invoiceTotal = invoiceTotalField.Value.AsCurrency();
Console.WriteLine($"Invoice Total: '{invoiceTotal.Symbol}{invoiceTotal.Amount}', with confidence {invoiceTotalField.Confidence}");
}
}
}
請瀏覽 GitHub 上的 Azure 範例存放庫,並檢視 發票模型輸出。
使用收據模型
using Azure;
using Azure.AI.DocumentIntelligence;
//use your `key` and `endpoint` environment variables to create your `AzureKeyCredential` and `DocumentIntelligenceClient` instances
string key = Environment.GetEnvironmentVariable("DI_KEY");
string endpoint = Environment.GetEnvironmentVariable("DI_ENDPOINT");
AzureKeyCredential credential = new AzureKeyCredential(key);
DocumentIntelligenceClient client = new DocumentIntelligenceClient(new Uri(endpoint), credential);
// sample document document
Uri receiptUri = new Uri("https://raw.githubusercontent.com/Azure-Samples/cognitive-services-REST-api-samples/master/curl/form-recognizer/rest-api/receipt.png");
Operation<AnalyzeResult> operation = await client.AnalyzeDocumentAsync(WaitUntil.Completed, "prebuilt-receipt", receiptUri);
AnalyzeResult receipts = operation.Value;
foreach (AnalyzedDocument receipt in receipts.Documents)
{
if (receipt.Fields.TryGetValue("MerchantName", out DocumentField merchantNameField))
{
if (merchantNameField.FieldType == DocumentFieldType.String)
{
string merchantName = merchantNameField.Value.AsString();
Console.WriteLine($"Merchant Name: '{merchantName}', with confidence {merchantNameField.Confidence}");
}
}
if (receipt.Fields.TryGetValue("TransactionDate", out DocumentField transactionDateField))
{
if (transactionDateField.FieldType == DocumentFieldType.Date)
{
DateTimeOffset transactionDate = transactionDateField.Value.AsDate();
Console.WriteLine($"Transaction Date: '{transactionDate}', with confidence {transactionDateField.Confidence}");
}
}
if (receipt.Fields.TryGetValue("Items", out DocumentField itemsField))
{
if (itemsField.FieldType == DocumentFieldType.List)
{
foreach (DocumentField itemField in itemsField.Value.AsList())
{
Console.WriteLine("Item:");
if (itemField.FieldType == DocumentFieldType.Dictionary)
{
IReadOnlyDictionary<string, DocumentField> itemFields = itemField.Value.AsDictionary();
if (itemFields.TryGetValue("Description", out DocumentField itemDescriptionField))
{
if (itemDescriptionField.FieldType == DocumentFieldType.String)
{
string itemDescription = itemDescriptionField.Value.AsString();
Console.WriteLine($" Description: '{itemDescription}', with confidence {itemDescriptionField.Confidence}");
}
}
if (itemFields.TryGetValue("TotalPrice", out DocumentField itemTotalPriceField))
{
if (itemTotalPriceField.FieldType == DocumentFieldType.Double)
{
double itemTotalPrice = itemTotalPriceField.Value.AsDouble();
Console.WriteLine($" Total Price: '{itemTotalPrice}', with confidence {itemTotalPriceField.Confidence}");
}
}
}
}
}
}
if (receipt.Fields.TryGetValue("Total", out DocumentField totalField))
{
if (totalField.FieldType == DocumentFieldType.Double)
{
double total = totalField.Value.AsDouble();
Console.WriteLine($"Total: '{total}', with confidence '{totalField.Confidence}'");
}
}
}
請瀏覽 GitHub 上的 Azure 範例存放庫,並檢視 收據模型輸出。
使用身分證件模型
using Azure;
using Azure.AI.DocumentIntelligence;
//use your `key` and `endpoint` environment variables to create your `AzureKeyCredential` and `DocumentIntelligenceClient` instances
string key = Environment.GetEnvironmentVariable("DI_KEY");
string endpoint = Environment.GetEnvironmentVariable("DI_ENDPOINT");
AzureKeyCredential credential = new AzureKeyCredential(key);
DocumentIntelligenceClient client = new DocumentIntelligenceClient(new Uri(endpoint), credential);
// sample document document
Uri idDocumentUri = new Uri("https://raw.githubusercontent.com/Azure-Samples/cognitive-services-REST-api-samples/master/curl/form-recognizer/rest-api/identity_documents.png");
Operation<AnalyzeResult> operation = await client.AnalyzeDocumentAsync(WaitUntil.Completed, "prebuilt-idDocument", idDocumentUri);
AnalyzeResult identityDocuments = operation.Value;
AnalyzedDocument identityDocument = identityDocuments.Documents.Single();
if (identityDocument.Fields.TryGetValue("Address", out DocumentField addressField))
{
if (addressField.FieldType == DocumentFieldType.String)
{
string address = addressField.Value. AsString();
Console.WriteLine($"Address: '{address}', with confidence {addressField.Confidence}");
}
}
if (identityDocument.Fields.TryGetValue("CountryRegion", out DocumentField countryRegionField))
{
if (countryRegionField.FieldType == DocumentFieldType.CountryRegion)
{
string countryRegion = countryRegionField.Value.AsCountryRegion();
Console.WriteLine($"CountryRegion: '{countryRegion}', with confidence {countryRegionField.Confidence}");
}
}
if (identityDocument.Fields.TryGetValue("DateOfBirth", out DocumentField dateOfBirthField))
{
if (dateOfBirthField.FieldType == DocumentFieldType.Date)
{
DateTimeOffset dateOfBirth = dateOfBirthField.Value.AsDate();
Console.WriteLine($"Date Of Birth: '{dateOfBirth}', with confidence {dateOfBirthField.Confidence}");
}
}
if (identityDocument.Fields.TryGetValue("DateOfExpiration", out DocumentField dateOfExpirationField))
{
if (dateOfExpirationField.FieldType == DocumentFieldType.Date)
{
DateTimeOffset dateOfExpiration = dateOfExpirationField.Value.AsDate();
Console.WriteLine($"Date Of Expiration: '{dateOfExpiration}', with confidence {dateOfExpirationField.Confidence}");
}
}
if (identityDocument.Fields.TryGetValue("DocumentNumber", out DocumentField documentNumberField))
{
if (documentNumberField.FieldType == DocumentFieldType.String)
{
string documentNumber = documentNumberField.Value.AsString();
Console.WriteLine($"Document Number: '{documentNumber}', with confidence {documentNumberField.Confidence}");
}
}
if (identityDocument.Fields.TryGetValue("FirstName", out DocumentField firstNameField))
{
if (firstNameField.FieldType == DocumentFieldType.String)
{
string firstName = firstNameField.Value.AsString();
Console.WriteLine($"First Name: '{firstName}', with confidence {firstNameField.Confidence}");
}
}
if (identityDocument.Fields.TryGetValue("LastName", out DocumentField lastNameField))
{
if (lastNameField.FieldType == DocumentFieldType.String)
{
string lastName = lastNameField.Value.AsString();
Console.WriteLine($"Last Name: '{lastName}', with confidence {lastNameField.Confidence}");
}
}
if (identityDocument.Fields.TryGetValue("Region", out DocumentField regionfield))
{
if (regionfield.FieldType == DocumentFieldType.String)
{
string region = regionfield.Value.AsString();
Console.WriteLine($"Region: '{region}', with confidence {regionfield.Confidence}");
}
}
if (identityDocument.Fields.TryGetValue("Sex", out DocumentField sexfield))
{
if (sexfield.FieldType == DocumentFieldType.String)
{
string sex = sexfield.Value.AsString();
Console.WriteLine($"Sex: '{sex}', with confidence {sexfield.Confidence}");
}
}
請瀏覽 GitHub 上的 Azure 範例存放庫,並檢視 識別碼檔案模型輸出。
用戶端連結庫 |API 參考 | 套件 (NuGet) | 範例 | 支援的 REST API 版本
用戶端連結庫 | REST API 參考 | 套件 | 範例 |支援的 REST API 版本
先決條件
Azure 訂用帳戶 - 免費建立一個訂用帳戶。
Azure AI 服務或文件智慧服務資源。 建立 單一服務 或 多服務。 您可以使用免費定價層 (
F0
) 來試用服務,之後可升級至付費層以用於實際執行環境。從您所建立資源的金鑰和端點,將應用程式連線至 Azure 文件智慧服務。
- 部署資源之後,請選取 [前往資源]。
- 在左側導覽功能表中,選取 [金鑰和端點]。
- 複製其中一個金鑰和 端點,以供本文稍後使用。
位於 URL 位置的文件檔案。 針對此專案,您可以使用下表中針對每項功能的範例表單:
特徵 / 功能 modelID document-url Read 模型 prebuilt-read 範例手冊 版面配置模型 預設佈局 範例預約確認 W-2 表單模型 prebuilt-tax.us.w2 範例 W-2 表單 發票模型 prebuilt-invoice 範例發票 收據模型 prebuilt-receipt 範例收據 識別碼文件模型 prebuilt-idDocument 範例身份文件 名片模型 prebuilt-businessCard 範例名片
設定環境變數
若要與此文件智慧服務互動,您必須建立 DocumentAnalysisClient
類別的執行個體。 若要這樣做,請使用 Azure 入口網站中的 key
和 endpoint
具現化用戶端。 針對此專案,請使用環境變數來儲存和存取認證。
這很重要
請謹慎使用 API 金鑰。 請勿在程式碼中直接包含 API 金鑰,且切勿公開張貼金鑰。 如果您使用 API 金鑰,請安全地將其儲存在 Azure 金鑰保存庫。 如需在應用程式中安全地使用 API 金鑰的詳細資訊,請參閱搭配 Azure 金鑰保存庫 的 API 金鑰。
如需 AI 服務安全性的詳細資訊,請參閱驗證對 Azure AI 服務的要求。
若要設定 Document Intelligence 資源金鑰的環境變數,請開啟主控台視窗,並遵循作系統和開發環境的指示。 將 <yourKey> 和 <yourEndpoint> 取代為 Azure 入口網站中資源的值。
Windows 中的環境變數不會區分大小寫。 它們通常會以大寫方式宣告,單字之間以底線連結。 在命令提示字元中,執行下列命令:
設定您的金鑰變數:
setx DI_KEY <yourKey>
設定您的端點變數
setx DI_ENDPOINT <yourEndpoint>
設定環境變數之後,請關閉 [命令提示字元] 視窗。 值會維持不變,直到您再次變更這些值為止。
重新啟動讀取環境變數的任何執行中程式。 例如,如果您使用 Visual Studio 或 Visual Studio Code 作為編輯器,請在執行範例程式代碼之前重新啟動。
以下是搭配環境變數使用的一些更實用的命令:
命令 | 動作 | 範例 |
---|---|---|
setx VARIABLE_NAME= |
將值設定為空字串,以刪除環境變數。 | setx DI_KEY= |
setx VARIABLE_NAME=value |
設定或變更環境變數的值。 | setx DI_KEY=<yourKey> |
set VARIABLE_NAME |
顯示特定環境變數的值。 | set DI_KEY |
set |
顯示所有環境變數。 | set |
設定程式設計環境
啟動 Visual Studio。
在起始頁面上,選擇 [建立新專案。
在 [建立新專案] 頁面上,在搜尋方塊中輸入主控台。 選取 主控台應用程式 範本,然後按一下 [下一步]。
在 [設定新專案] 頁面中,於 [專案 名稱] 底下輸入 docIntelligence_app。 然後選取下一步。
在 [其他資訊] 頁面中,選取 [.NET 8.0 (長期支援)],然後選取 [建立 ]。
使用 NuGet 安裝用戶端程式庫
以滑鼠右鍵按下您的 docIntelligence_app 項目,然後選取 [管理 NuGet 套件... ]。
選取 瀏覽 索引標籤,然後輸入 Azure.AI.FormRecognizer。
從下拉功能表中選取版本,並在專案中安裝套件。
建置您的 應用程式
備註
從 .NET 6 開始,使用 console
範本的新專案會產生與舊版不同的新程式樣式。 新輸出會使用最新的 C# 功能,以簡化您需要撰寫的程式碼。
當您使用較新版本時,只需要撰寫 Main
方法的主體。 您不需要包含最上層陳述式、全域 using 指示詞或隱含 using 指示詞。 如需詳細資訊,請參閱 C# 主控台應用程式範本會產生最上層陳述式 (部分內容可能是機器或 AI 翻譯)。
開啟 Program.cs 檔案。
刪除現有的程式代碼,包括行
Console.Writeline("Hello World!")
。選取下列其中一個程式代碼範例,並將/貼到應用程式的 Program.cs 檔案中:
將程式代碼範例新增至應用程式之後,請選擇專案名稱旁的綠色 [開始] 按鈕,以建置和執行程式,或按 F5。
使用 Read 模型
using Azure;
using Azure.AI.FormRecognizer.DocumentAnalysis;
//use your `key` and `endpoint` environment variables to create your `AzureKeyCredential` and `DocumentAnalysisClient` instances
string key = Environment.GetEnvironmentVariable("DI_KEY");
string endpoint = Environment.GetEnvironmentVariable("DI_ENDPOINT");
AzureKeyCredential credential = new AzureKeyCredential(key);
DocumentAnalysisClient client = new DocumentAnalysisClient(new Uri(endpoint), credential);
//sample document
Uri fileUri = new Uri("https://raw.githubusercontent.com/Azure-Samples/cognitive-services-REST-api-samples/master/curl/form-recognizer/rest-api/read.png");
AnalyzeDocumentOperation operation = await client.AnalyzeDocumentFromUriAsync(WaitUntil.Completed, "prebuilt-read", fileUri);
AnalyzeResult result = operation.Value;
foreach (DocumentPage page in result.Pages)
{
Console.WriteLine($"Document Page {page.PageNumber} has {page.Lines.Count} line(s), {page.Words.Count} word(s),");
Console.WriteLine($"and {page.SelectionMarks.Count} selection mark(s).");
for (int i = 0; i < page.Lines.Count; i++)
{
DocumentLine line = page.Lines[i];
Console.WriteLine($" Line {i} has content: '{line.Content}'.");
Console.WriteLine($" Its bounding polygon (points ordered clockwise):");
for (int j = 0; j < line.BoundingPolygon.Count; j++)
{
Console.WriteLine($" Point {j} => X: {line.BoundingPolygon[j].X}, Y: {line.BoundingPolygon[j].Y}");
}
}
}
foreach (DocumentStyle style in result.Styles)
{
// Check the style and style confidence to see if text is handwritten.
// Note that value '0.8' is used as an example.
bool isHandwritten = style.IsHandwritten.HasValue && style.IsHandwritten == true;
if (isHandwritten && style.Confidence > 0.8)
{
Console.WriteLine($"Handwritten content found:");
foreach (DocumentSpan span in style.Spans)
{
Console.WriteLine($" Content: {result.Content.Substring(span.Index, span.Length)}");
}
}
}
Console.WriteLine("Detected languages:");
foreach (DocumentLanguage language in result.Languages)
{
Console.WriteLine($" Found language with locale'{language.Locale}' with confidence {language.Confidence}.");
}
請瀏覽 GitHub 上的 Azure 範例存放庫,並檢視 read
模型輸出。
使用 Layout 模型
using Azure;
using Azure.AI.FormRecognizer.DocumentAnalysis;
//use your `key` and `endpoint` environment variables to create your `AzureKeyCredential` and `DocumentAnalysisClient` instances
string key = Environment.GetEnvironmentVariable("DI_KEY");
string endpoint = Environment.GetEnvironmentVariable("DI_ENDPOINT");
AzureKeyCredential credential = new AzureKeyCredential(key);
DocumentAnalysisClient client = new DocumentAnalysisClient(new Uri(endpoint), credential);
// sample document document
Uri fileUri = new Uri ("https://raw.githubusercontent.com/Azure-Samples/cognitive-services-REST-api-samples/master/curl/form-recognizer/rest-api/layout.png");
AnalyzeDocumentOperation operation = await client.AnalyzeDocumentFromUriAsync(WaitUntil.Completed, "prebuilt-layout", fileUri);
AnalyzeResult result = operation.Value;
foreach (DocumentPage page in result.Pages)
{
Console.WriteLine($"Document Page {page.PageNumber} has {page.Lines.Count} line(s), {page.Words.Count} word(s),");
Console.WriteLine($"and {page.SelectionMarks.Count} selection mark(s).");
for (int i = 0; i < page.Lines.Count; i++)
{
DocumentLine line = page.Lines[i];
Console.WriteLine($" Line {i} has content: '{line.Content}'.");
Console.WriteLine($" Its bounding polygon (points ordered clockwise):");
for (int j = 0; j < line.BoundingPolygon.Count; j++)
{
Console.WriteLine($" Point {j} => X: {line.BoundingPolygon[j].X}, Y: {line.BoundingPolygon[j].Y}");
}
}
for (int i = 0; i < page.SelectionMarks.Count; i++)
{
DocumentSelectionMark selectionMark = page.SelectionMarks[i];
Console.WriteLine($" Selection Mark {i} is {selectionMark.State}.");
Console.WriteLine($" Its bounding polygon (points ordered clockwise):");
for (int j = 0; j < selectionMark.BoundingPolygon.Count; j++)
{
Console.WriteLine($" Point {j} => X: {selectionMark.BoundingPolygon[j].X}, Y: {selectionMark.BoundingPolygon[j].Y}");
}
}
}
Console.WriteLine("Paragraphs:");
foreach (DocumentParagraph paragraph in result.Paragraphs)
{
Console.WriteLine($" Paragraph content: {paragraph.Content}");
if (paragraph.Role != null)
{
Console.WriteLine($" Role: {paragraph.Role}");
}
}
foreach (DocumentStyle style in result.Styles)
{
// Check the style and style confidence to see if text is handwritten.
// Note that value '0.8' is used as an example.
bool isHandwritten = style.IsHandwritten.HasValue && style.IsHandwritten == true;
if (isHandwritten && style.Confidence > 0.8)
{
Console.WriteLine($"Handwritten content found:");
foreach (DocumentSpan span in style.Spans)
{
Console.WriteLine($" Content: {result.Content.Substring(span.Index, span.Length)}");
}
}
}
Console.WriteLine("The following tables were extracted:");
for (int i = 0; i < result.Tables.Count; i++)
{
DocumentTable table = result.Tables[i];
Console.WriteLine($" Table {i} has {table.RowCount} rows and {table.ColumnCount} columns.");
foreach (DocumentTableCell cell in table.Cells)
{
Console.WriteLine($" Cell ({cell.RowIndex}, {cell.ColumnIndex}) has kind '{cell.Kind}' and content: '{cell.Content}'.");
}
}
請瀏覽 GitHub 上的 Azure 範例存放庫,並檢視 版面配置模型輸出。
使用通用文件模型
using Azure;
using Azure.AI.FormRecognizer.DocumentAnalysis;
//use your `key` and `endpoint` environment variables to create your `AzureKeyCredential` and `DocumentAnalysisClient` instances
string key = Environment.GetEnvironmentVariable("DI_KEY");
string endpoint = Environment.GetEnvironmentVariable("DI_ENDPOINT");
AzureKeyCredential credential = new AzureKeyCredential(key);
DocumentAnalysisClient client = new DocumentAnalysisClient(new Uri(endpoint), credential);
// sample document document
Uri fileUri = new Uri("https://raw.githubusercontent.com/Azure-Samples/cognitive-services-REST-api-samples/master/curl/form-recognizer/sample-layout.pdf");
AnalyzeDocumentOperation operation = await client.AnalyzeDocumentFromUriAsync(WaitUntil.Completed, "prebuilt-document", fileUri);
AnalyzeResult result = operation.Value;
Console.WriteLine("Detected key-value pairs:");
foreach (DocumentKeyValuePair kvp in result.KeyValuePairs)
{
if (kvp.Value == null)
{
Console.WriteLine($" Found key with no value: '{kvp.Key.Content}'");
}
else
{
Console.WriteLine($" Found key-value pair: '{kvp.Key.Content}' and '{kvp.Value.Content}'");
}
}
foreach (DocumentPage page in result.Pages)
{
Console.WriteLine($"Document Page {page.PageNumber} has {page.Lines.Count} line(s), {page.Words.Count} word(s),");
Console.WriteLine($"and {page.SelectionMarks.Count} selection mark(s).");
for (int i = 0; i < page.Lines.Count; i++)
{
DocumentLine line = page.Lines[i];
Console.WriteLine($" Line {i} has content: '{line.Content}'.");
Console.WriteLine($" Its bounding polygon (points ordered clockwise):");
for (int j = 0; j < line.BoundingPolygon.Count; j++)
{
Console.WriteLine($" Point {j} => X: {line.BoundingPolygon[j].X}, Y: {line.BoundingPolygon[j].Y}");
}
}
for (int i = 0; i < page.SelectionMarks.Count; i++)
{
DocumentSelectionMark selectionMark = page.SelectionMarks[i];
Console.WriteLine($" Selection Mark {i} is {selectionMark.State}.");
Console.WriteLine($" Its bounding polygon (points ordered clockwise):");
for (int j = 0; j < selectionMark.BoundingPolygon.Count; j++)
{
Console.WriteLine($" Point {j} => X: {selectionMark.BoundingPolygon[j].X}, Y: {selectionMark.BoundingPolygon[j].Y}");
}
}
}
foreach (DocumentStyle style in result.Styles)
{
// Check the style and style confidence to see if text is handwritten.
// Note that value '0.8' is used as an example.
bool isHandwritten = style.IsHandwritten.HasValue && style.IsHandwritten == true;
if (isHandwritten && style.Confidence > 0.8)
{
Console.WriteLine($"Handwritten content found:");
foreach (DocumentSpan span in style.Spans)
{
Console.WriteLine($" Content: {result.Content.Substring(span.Index, span.Length)}");
}
}
}
Console.WriteLine("The following tables were extracted:");
for (int i = 0; i < result.Tables.Count; i++)
{
DocumentTable table = result.Tables[i];
Console.WriteLine($" Table {i} has {table.RowCount} rows and {table.ColumnCount} columns.");
foreach (DocumentTableCell cell in table.Cells)
{
Console.WriteLine($" Cell ({cell.RowIndex}, {cell.ColumnIndex}) has kind '{cell.Kind}' and content: '{cell.Content}'.");
}
}
請瀏覽 GitHub 上的 Azure 範例存放庫,並檢視 一般檔案模型輸出。
使用 W-2 稅務模型
using Azure;
using Azure.AI.FormRecognizer.DocumentAnalysis;
//use your `key` and `endpoint` environment variables to create your `AzureKeyCredential` and `DocumentAnalysisClient` instances
string key = Environment.GetEnvironmentVariable("DI_KEY");
string endpoint = Environment.GetEnvironmentVariable("DI_ENDPOINT");
AzureKeyCredential credential = new AzureKeyCredential(key);
DocumentAnalysisClient client = new DocumentAnalysisClient(new Uri(endpoint), credential);
// sample document document
Uri w2Uri = new Uri("https://raw.githubusercontent.com/Azure-Samples/cognitive-services-REST-api-samples/master/curl/form-recognizer/rest-api/w2.png");
AnalyzeDocumentOperation operation = await client.AnalyzeDocumentFromUriAsync(WaitUntil.Completed, "prebuilt-tax.us.w2", w2Uri);
AnalyzeResult result = operation.Value;
for (int i = 0; i < result.Documents.Count; i++)
{
Console.WriteLine($"Document {i}:");
AnalyzedDocument document = result.Documents[i];
if (document.Fields.TryGetValue("AdditionalInfo", out DocumentField? additionalInfoField))
{
if (additionalInfoField.FieldType == DocumentFieldType.List)
{
foreach (DocumentField infoField in additionalInfoField.Value.AsList())
{
Console.WriteLine("AdditionalInfo:");
if (infoField.FieldType == DocumentFieldType.Dictionary)
{
IReadOnlyDictionary<string, DocumentField> infoFields = infoField.Value.AsDictionary();
if (infoFields.TryGetValue("Amount", out DocumentField? amountField))
{
if (amountField.FieldType == DocumentFieldType.Double)
{
double amount = amountField.Value.AsDouble();
Console.WriteLine($" Amount: '{amount}', with confidence {amountField.Confidence}");
}
}
if (infoFields.TryGetValue("LetterCode", out DocumentField? letterCodeField))
{
if (letterCodeField.FieldType == DocumentFieldType.String)
{
string letterCode = letterCodeField.Value.AsString();
Console.WriteLine($" LetterCode: '{letterCode}', with confidence {letterCodeField.Confidence}");
}
}
}
}
}
}
if (document.Fields.TryGetValue("AllocatedTips", out DocumentField? allocatedTipsField))
{
if (allocatedTipsField.FieldType == DocumentFieldType.Double)
{
double allocatedTips = allocatedTipsField.Value.AsDouble();
Console.WriteLine($"Allocated Tips: '{allocatedTips}', with confidence {allocatedTipsField.Confidence}");
}
}
if (document.Fields.TryGetValue("Employer", out DocumentField? employerField))
{
if (employerField.FieldType == DocumentFieldType.Dictionary)
{
IReadOnlyDictionary<string, DocumentField> employerFields = employerField.Value.AsDictionary();
if (employerFields.TryGetValue("Name", out DocumentField? employerNameField))
{
if (employerNameField.FieldType == DocumentFieldType.String)
{
string name = employerNameField.Value.AsString();
Console.WriteLine($"Employer Name: '{name}', with confidence {employerNameField.Confidence}");
}
}
if (employerFields.TryGetValue("IdNumber", out DocumentField? idNumberField))
{
if (idNumberField.FieldType == DocumentFieldType.String)
{
string id = idNumberField.Value.AsString();
Console.WriteLine($"Employer ID Number: '{id}', with confidence {idNumberField.Confidence}");
}
}
if (employerFields.TryGetValue("Address", out DocumentField? addressField))
{
if (addressField.FieldType == DocumentFieldType.Address)
{
Console.WriteLine($"Employer Address: '{addressField.Content}', with confidence {addressField.Confidence}");
}
}
}
}
}
請瀏覽 GitHub 上的 Azure 範例存放庫,並檢視 W-2 稅務模型輸出。
使用發票模型
using Azure;
using Azure.AI.FormRecognizer.DocumentAnalysis;
//use your `key` and `endpoint` environment variables to create your `AzureKeyCredential` and `DocumentAnalysisClient` instances
string key = Environment.GetEnvironmentVariable("DI_KEY");
string endpoint = Environment.GetEnvironmentVariable("DI_ENDPOINT");
AzureKeyCredential credential = new AzureKeyCredential(key);
DocumentAnalysisClient client = new DocumentAnalysisClient(new Uri(endpoint), credential);
// sample document document
Uri invoiceUri = new Uri("https://github.com/Azure-Samples/cognitive-services-REST-api-samples/raw/master/curl/form-recognizer/rest-api/invoice.pdf");
AnalyzeDocumentOperation operation = await client.AnalyzeDocumentFromUriAsync(WaitUntil.Completed, "prebuilt-invoice", invoiceUri);
AnalyzeResult result = operation.Value;
for (int i = 0; i < result.Documents.Count; i++)
{
Console.WriteLine($"Document {i}:");
AnalyzedDocument document = result.Documents[i];
if (document.Fields.TryGetValue("VendorName", out DocumentField vendorNameField))
{
if (vendorNameField.FieldType == DocumentFieldType.String)
{
string vendorName = vendorNameField.Value.AsString();
Console.WriteLine($"Vendor Name: '{vendorName}', with confidence {vendorNameField.Confidence}");
}
}
if (document.Fields.TryGetValue("CustomerName", out DocumentField customerNameField))
{
if (customerNameField.FieldType == DocumentFieldType.String)
{
string customerName = customerNameField.Value.AsString();
Console.WriteLine($"Customer Name: '{customerName}', with confidence {customerNameField.Confidence}");
}
}
if (document.Fields.TryGetValue("Items", out DocumentField itemsField))
{
if (itemsField.FieldType == DocumentFieldType.List)
{
foreach (DocumentField itemField in itemsField.Value.AsList())
{
Console.WriteLine("Item:");
if (itemField.FieldType == DocumentFieldType.Dictionary)
{
IReadOnlyDictionary<string, DocumentField> itemFields = itemField.Value.AsDictionary();
if (itemFields.TryGetValue("Description", out DocumentField itemDescriptionField))
{
if (itemDescriptionField.FieldType == DocumentFieldType.String)
{
string itemDescription = itemDescriptionField.Value.AsString();
Console.WriteLine($" Description: '{itemDescription}', with confidence {itemDescriptionField.Confidence}");
}
}
if (itemFields.TryGetValue("Amount", out DocumentField itemAmountField))
{
if (itemAmountField.FieldType == DocumentFieldType.Currency)
{
CurrencyValue itemAmount = itemAmountField.Value.AsCurrency();
Console.WriteLine($" Amount: '{itemAmount.Symbol}{itemAmount.Amount}', with confidence {itemAmountField.Confidence}");
}
}
}
}
}
}
if (document.Fields.TryGetValue("SubTotal", out DocumentField subTotalField))
{
if (subTotalField.FieldType == DocumentFieldType.Currency)
{
CurrencyValue subTotal = subTotalField.Value.AsCurrency();
Console.WriteLine($"Sub Total: '{subTotal.Symbol}{subTotal.Amount}', with confidence {subTotalField.Confidence}");
}
}
if (document.Fields.TryGetValue("TotalTax", out DocumentField totalTaxField))
{
if (totalTaxField.FieldType == DocumentFieldType.Currency)
{
CurrencyValue totalTax = totalTaxField.Value.AsCurrency();
Console.WriteLine($"Total Tax: '{totalTax.Symbol}{totalTax.Amount}', with confidence {totalTaxField.Confidence}");
}
}
if (document.Fields.TryGetValue("InvoiceTotal", out DocumentField invoiceTotalField))
{
if (invoiceTotalField.FieldType == DocumentFieldType.Currency)
{
CurrencyValue invoiceTotal = invoiceTotalField.Value.AsCurrency();
Console.WriteLine($"Invoice Total: '{invoiceTotal.Symbol}{invoiceTotal.Amount}', with confidence {invoiceTotalField.Confidence}");
}
}
}
請瀏覽 GitHub 上的 Azure 範例存放庫,並檢視 發票模型輸出。
使用收據模型
using Azure;
using Azure.AI.FormRecognizer.DocumentAnalysis;
//use your `key` and `endpoint` environment variables to create your `AzureKeyCredential` and `DocumentAnalysisClient` instances
string key = Environment.GetEnvironmentVariable("DI_KEY");
string endpoint = Environment.GetEnvironmentVariable("DI_ENDPOINT");
AzureKeyCredential credential = new AzureKeyCredential(key);
DocumentAnalysisClient client = new DocumentAnalysisClient(new Uri(endpoint), credential);
// sample document document
Uri receiptUri = new Uri("https://raw.githubusercontent.com/Azure-Samples/cognitive-services-REST-api-samples/master/curl/form-recognizer/rest-api/receipt.png");
AnalyzeDocumentOperation operation = await client.AnalyzeDocumentFromUriAsync(WaitUntil.Completed, "prebuilt-receipt", receiptUri);
AnalyzeResult receipts = operation.Value;
foreach (AnalyzedDocument receipt in receipts.Documents)
{
if (receipt.Fields.TryGetValue("MerchantName", out DocumentField merchantNameField))
{
if (merchantNameField.FieldType == DocumentFieldType.String)
{
string merchantName = merchantNameField.Value.AsString();
Console.WriteLine($"Merchant Name: '{merchantName}', with confidence {merchantNameField.Confidence}");
}
}
if (receipt.Fields.TryGetValue("TransactionDate", out DocumentField transactionDateField))
{
if (transactionDateField.FieldType == DocumentFieldType.Date)
{
DateTimeOffset transactionDate = transactionDateField.Value.AsDate();
Console.WriteLine($"Transaction Date: '{transactionDate}', with confidence {transactionDateField.Confidence}");
}
}
if (receipt.Fields.TryGetValue("Items", out DocumentField itemsField))
{
if (itemsField.FieldType == DocumentFieldType.List)
{
foreach (DocumentField itemField in itemsField.Value.AsList())
{
Console.WriteLine("Item:");
if (itemField.FieldType == DocumentFieldType.Dictionary)
{
IReadOnlyDictionary<string, DocumentField> itemFields = itemField.Value.AsDictionary();
if (itemFields.TryGetValue("Description", out DocumentField itemDescriptionField))
{
if (itemDescriptionField.FieldType == DocumentFieldType.String)
{
string itemDescription = itemDescriptionField.Value.AsString();
Console.WriteLine($" Description: '{itemDescription}', with confidence {itemDescriptionField.Confidence}");
}
}
if (itemFields.TryGetValue("TotalPrice", out DocumentField itemTotalPriceField))
{
if (itemTotalPriceField.FieldType == DocumentFieldType.Double)
{
double itemTotalPrice = itemTotalPriceField.Value.AsDouble();
Console.WriteLine($" Total Price: '{itemTotalPrice}', with confidence {itemTotalPriceField.Confidence}");
}
}
}
}
}
}
if (receipt.Fields.TryGetValue("Total", out DocumentField totalField))
{
if (totalField.FieldType == DocumentFieldType.Double)
{
double total = totalField.Value.AsDouble();
Console.WriteLine($"Total: '{total}', with confidence '{totalField.Confidence}'");
}
}
}
請瀏覽 GitHub 上的 Azure 範例存放庫,並檢視 收據模型輸出。
身份證件模型
using Azure;
using Azure.AI.FormRecognizer.DocumentAnalysis;
//use your `key` and `endpoint` environment variables to create your `AzureKeyCredential` and `DocumentAnalysisClient` instances
string key = Environment.GetEnvironmentVariable("DI_KEY");
string endpoint = Environment.GetEnvironmentVariable("DI_ENDPOINT");
AzureKeyCredential credential = new AzureKeyCredential(key);
DocumentAnalysisClient client = new DocumentAnalysisClient(new Uri(endpoint), credential);
// sample document document
Uri idDocumentUri = new Uri("https://raw.githubusercontent.com/Azure-Samples/cognitive-services-REST-api-samples/master/curl/form-recognizer/rest-api/identity_documents.png");
AnalyzeDocumentOperation operation = await client.AnalyzeDocumentFromUriAsync(WaitUntil.Completed, "prebuilt-idDocument", idDocumentUri);
AnalyzeResult identityDocuments = operation.Value;
AnalyzedDocument identityDocument = identityDocuments.Documents.Single();
if (identityDocument.Fields.TryGetValue("Address", out DocumentField addressField))
{
if (addressField.FieldType == DocumentFieldType.String)
{
string address = addressField.Value. AsString();
Console.WriteLine($"Address: '{address}', with confidence {addressField.Confidence}");
}
}
if (identityDocument.Fields.TryGetValue("CountryRegion", out DocumentField countryRegionField))
{
if (countryRegionField.FieldType == DocumentFieldType.CountryRegion)
{
string countryRegion = countryRegionField.Value.AsCountryRegion();
Console.WriteLine($"CountryRegion: '{countryRegion}', with confidence {countryRegionField.Confidence}");
}
}
if (identityDocument.Fields.TryGetValue("DateOfBirth", out DocumentField dateOfBirthField))
{
if (dateOfBirthField.FieldType == DocumentFieldType.Date)
{
DateTimeOffset dateOfBirth = dateOfBirthField.Value.AsDate();
Console.WriteLine($"Date Of Birth: '{dateOfBirth}', with confidence {dateOfBirthField.Confidence}");
}
}
if (identityDocument.Fields.TryGetValue("DateOfExpiration", out DocumentField dateOfExpirationField))
{
if (dateOfExpirationField.FieldType == DocumentFieldType.Date)
{
DateTimeOffset dateOfExpiration = dateOfExpirationField.Value.AsDate();
Console.WriteLine($"Date Of Expiration: '{dateOfExpiration}', with confidence {dateOfExpirationField.Confidence}");
}
}
if (identityDocument.Fields.TryGetValue("DocumentNumber", out DocumentField documentNumberField))
{
if (documentNumberField.FieldType == DocumentFieldType.String)
{
string documentNumber = documentNumberField.Value.AsString();
Console.WriteLine($"Document Number: '{documentNumber}', with confidence {documentNumberField.Confidence}");
}
}
if (identityDocument.Fields.TryGetValue("FirstName", out DocumentField firstNameField))
{
if (firstNameField.FieldType == DocumentFieldType.String)
{
string firstName = firstNameField.Value.AsString();
Console.WriteLine($"First Name: '{firstName}', with confidence {firstNameField.Confidence}");
}
}
if (identityDocument.Fields.TryGetValue("LastName", out DocumentField lastNameField))
{
if (lastNameField.FieldType == DocumentFieldType.String)
{
string lastName = lastNameField.Value.AsString();
Console.WriteLine($"Last Name: '{lastName}', with confidence {lastNameField.Confidence}");
}
}
if (identityDocument.Fields.TryGetValue("Region", out DocumentField regionfield))
{
if (regionfield.FieldType == DocumentFieldType.String)
{
string region = regionfield.Value.AsString();
Console.WriteLine($"Region: '{region}', with confidence {regionfield.Confidence}");
}
}
if (identityDocument.Fields.TryGetValue("Sex", out DocumentField sexfield))
{
if (sexfield.FieldType == DocumentFieldType.String)
{
string sex = sexfield.Value.AsString();
Console.WriteLine($"Sex: '{sex}', with confidence {sexfield.Confidence}");
}
}
請瀏覽 GitHub 上的 Azure 範例存放庫,並檢視 識別碼檔案模型輸出。
使用名片模型
using Azure;
using Azure.AI.FormRecognizer.DocumentAnalysis;
//use your `key` and `endpoint` environment variables to create your `AzureKeyCredential` and `DocumentAnalysisClient` instances
string key = Environment.GetEnvironmentVariable("DI_KEY");
string endpoint = Environment.GetEnvironmentVariable("DI_ENDPOINT");
AzureKeyCredential credential = new AzureKeyCredential(key);
DocumentAnalysisClient client = new DocumentAnalysisClient(new Uri(endpoint), credential);
// sample document document
Uri businessCardUri = new Uri("https://raw.githubusercontent.com/Azure-Samples/cognitive-services-REST-api-samples/master/curl/form-recognizer/business-card-english.jpg");
AnalyzeDocumentOperation operation = await client.AnalyzeDocumentFromUriAsync(WaitUntil.Completed, "prebuilt-businessCard", businessCardUri);
AnalyzeResult businessCards = operation.Value;
foreach (AnalyzedDocument businessCard in businessCards.Documents)
{
if (businessCard.Fields.TryGetValue("ContactNames", out DocumentField ContactNamesField))
{
if (ContactNamesField.FieldType == DocumentFieldType.List)
{
foreach (DocumentField contactNameField in ContactNamesField.Value.AsList())
{
Console.WriteLine("Contact Name: ");
if (contactNameField.FieldType == DocumentFieldType.Dictionary)
{
IReadOnlyDictionary<string, DocumentField> contactNameFields = contactNameField.Value.AsDictionary();
if (contactNameFields.TryGetValue("FirstName", out DocumentField firstNameField))
{
if (firstNameField.FieldType == DocumentFieldType.String)
{
string firstName = firstNameField.Value.AsString();
Console.WriteLine($" First Name: '{firstName}', with confidence {firstNameField.Confidence}");
}
}
if (contactNameFields.TryGetValue("LastName", out DocumentField lastNameField))
{
if (lastNameField.FieldType == DocumentFieldType.String)
{
string lastName = lastNameField.Value.AsString();
Console.WriteLine($" Last Name: '{lastName}', with confidence {lastNameField.Confidence}");
}
}
}
}
}
}
if (businessCard.Fields.TryGetValue("JobTitles", out DocumentField jobTitlesFields))
{
if (jobTitlesFields.FieldType == DocumentFieldType.List)
{
foreach (DocumentField jobTitleField in jobTitlesFields.Value.AsList())
{
if (jobTitleField.FieldType == DocumentFieldType.String)
{
string jobTitle = jobTitleField.Value.AsString();
Console.WriteLine($"Job Title: '{jobTitle}', with confidence {jobTitleField.Confidence}");
}
}
}
}
if (businessCard.Fields.TryGetValue("Departments", out DocumentField departmentFields))
{
if (departmentFields.FieldType == DocumentFieldType.List)
{
foreach (DocumentField departmentField in departmentFields.Value.AsList())
{
if (departmentField.FieldType == DocumentFieldType.String)
{
string department = departmentField.Value.AsString();
Console.WriteLine($"Department: '{department}', with confidence {departmentField.Confidence}");
}
}
}
}
if (businessCard.Fields.TryGetValue("Emails", out DocumentField emailFields))
{
if (emailFields.FieldType == DocumentFieldType.List)
{
foreach (DocumentField emailField in emailFields.Value.AsList())
{
if (emailField.FieldType == DocumentFieldType.String)
{
string email = emailField.Value.AsString();
Console.WriteLine($"Email: '{email}', with confidence {emailField.Confidence}");
}
}
}
}
if (businessCard.Fields.TryGetValue("Websites", out DocumentField websiteFields))
{
if (websiteFields.FieldType == DocumentFieldType.List)
{
foreach (DocumentField websiteField in websiteFields.Value.AsList())
{
if (websiteField.FieldType == DocumentFieldType.String)
{
string website = websiteField.Value.AsString();
Console.WriteLine($"Website: '{website}', with confidence {websiteField.Confidence}");
}
}
}
}
if (businessCard.Fields.TryGetValue("MobilePhones", out DocumentField mobilePhonesFields))
{
if (mobilePhonesFields.FieldType == DocumentFieldType.List)
{
foreach (DocumentField mobilePhoneField in mobilePhonesFields.Value.AsList())
{
if (mobilePhoneField.FieldType == DocumentFieldType.PhoneNumber)
{
string mobilePhone = mobilePhoneField.Value.AsPhoneNumber();
Console.WriteLine($"Mobile phone number: '{mobilePhone}', with confidence {mobilePhoneField.Confidence}");
}
}
}
}
if (businessCard.Fields.TryGetValue("WorkPhones", out DocumentField workPhonesFields))
{
if (workPhonesFields.FieldType == DocumentFieldType.List)
{
foreach (DocumentField workPhoneField in workPhonesFields.Value.AsList())
{
if (workPhoneField.FieldType == DocumentFieldType.PhoneNumber)
{
string workPhone = workPhoneField.Value.AsPhoneNumber();
Console.WriteLine($"Work phone number: '{workPhone}', with confidence {workPhoneField.Confidence}");
}
}
}
}
if (businessCard.Fields.TryGetValue("Faxes", out DocumentField faxesFields))
{
if (faxesFields.FieldType == DocumentFieldType.List)
{
foreach (DocumentField faxField in faxesFields.Value.AsList())
{
if (faxField.FieldType == DocumentFieldType.PhoneNumber)
{
string fax = faxField.Value.AsPhoneNumber();
Console.WriteLine($"Fax phone number: '{fax}', with confidence {faxField.Confidence}");
}
}
}
}
if (businessCard.Fields.TryGetValue("Addresses", out DocumentField addressesFields))
{
if (addressesFields.FieldType == DocumentFieldType.List)
{
foreach (DocumentField addressField in addressesFields.Value.AsList())
{
if (addressField.FieldType == DocumentFieldType.String)
{
string address = addressField.Value.AsString();
Console.WriteLine($"Address: '{address}', with confidence {addressField.Confidence}");
}
}
}
}
if (businessCard.Fields.TryGetValue("CompanyNames", out DocumentField companyNamesFields))
{
if (companyNamesFields.FieldType == DocumentFieldType.List)
{
foreach (DocumentField companyNameField in companyNamesFields.Value.AsList())
{
if (companyNameField.FieldType == DocumentFieldType.String)
{
string companyName = companyNameField.Value.AsString();
Console.WriteLine($"Company name: '{companyName}', with confidence {companyNameField.Confidence}");
}
}
}
}
}
請瀏覽 GitHub 上的 Azure 範例存放庫,並檢視 名片模型輸出。
用戶端連結庫 | REST API 參考 | 套件 (Maven) | 範例 |支援的 REST API 版本
先決條件
Azure 訂用帳戶 - 免費建立一個訂用帳戶。
最新的 Visual Studio Code 版本或您慣用的 IDE。 請參閱 Visual Studio Code 中的Java。
- Visual Studio Code 為適用於 Windows 和 macOS 的 Java 提供 程式代碼套件。 程式代碼撰寫套件是一組
VS
Code、Java Development Kit (JDK),以及Microsoft所建議延伸模組的集合。 編碼套件也可以用於修正現有的開發環境。 - 如果您使用
VS
Code 和適用於 Java 的編碼套件,請安裝適用於 Java 的 Gradle 擴充功能。
如果您未使用 Visual Studio Code,請確保在開發環境中安裝下列項目:
- Java 開發套件 (JDK) 第 8 版或更新版本。 如需詳細資訊,請參閱 Microsoft Build of OpenJDK。
- Gradle,6.8 版或後續版本。
- Visual Studio Code 為適用於 Windows 和 macOS 的 Java 提供 程式代碼套件。 程式代碼撰寫套件是一組
Azure AI 服務或文件智慧服務資源。 建立 單一服務 或 多服務。 您可以使用免費定價層 (
F0
) 來試用服務,之後可升級至付費層以用於實際執行環境。小提示
如果您打算使用單一端點和密鑰來存取多個 Azure AI 服務,請建立 Azure AI 服務資源。 針對僅限文件智慧服務存取,請建立文件智慧服務資源。 如果您想要使用 Microsoft Entra 驗證,則需要使用單一服務資源。
從您所建立資源的金鑰和端點,將應用程式連線至 Azure 文件智慧服務。
- 部署資源之後,請選取 [前往資源]。
- 在左側導覽功能表中,選取 [金鑰和端點]。
- 複製其中一個金鑰和 端點,以供本文稍後使用。
URL 的文件檔案。 針對此專案,您可以使用下表中針對每項功能的範例表單:
特徵 / 功能 modelID document-url Read 模型 prebuilt-read 範例手冊 版面配置模型 預設佈局 範例預約確認 W-2 表單模型 prebuilt-tax.us.w2 範例 W-2 表單 發票模型 prebuilt-invoice 範例發票 收據模型 prebuilt-receipt 範例收據 識別碼文件模型 prebuilt-idDocument 範例身份文件
設定環境變數
若要與此文件智慧服務互動,您必須建立 DocumentAnalysisClient
類別的執行個體。 若要這樣做,請使用 Azure 入口網站中的 key
和 endpoint
具現化用戶端。 針對此專案,請使用環境變數來儲存和存取認證。
這很重要
請謹慎使用 API 金鑰。 請勿在程式碼中直接包含 API 金鑰,且切勿公開張貼金鑰。 如果您使用 API 金鑰,請安全地將其儲存在 Azure 金鑰保存庫。 如需在應用程式中安全地使用 API 金鑰的詳細資訊,請參閱搭配 Azure 金鑰保存庫 的 API 金鑰。
如需 AI 服務安全性的詳細資訊,請參閱驗證對 Azure AI 服務的要求。
若要設定 Document Intelligence 資源金鑰的環境變數,請開啟主控台視窗,並遵循作系統和開發環境的指示。 將 <yourKey> 和 <yourEndpoint> 取代為 Azure 入口網站中資源的值。
Windows 中的環境變數不會區分大小寫。 它們通常會以大寫方式宣告,單字之間以底線連結。 在命令提示字元中,執行下列命令:
設定您的金鑰變數:
setx DI_KEY <yourKey>
設定您的端點變數
setx DI_ENDPOINT <yourEndpoint>
設定環境變數之後,請關閉 [命令提示字元] 視窗。 值會維持不變,直到您再次變更這些值為止。
重新啟動讀取環境變數的任何執行中程式。 例如,如果您使用 Visual Studio 或 Visual Studio Code 作為編輯器,請在執行範例程式代碼之前重新啟動。
以下是搭配環境變數使用的一些更實用的命令:
命令 | 動作 | 範例 |
---|---|---|
setx VARIABLE_NAME= |
將值設定為空字串,以刪除環境變數。 | setx DI_KEY= |
setx VARIABLE_NAME=value |
設定或變更環境變數的值。 | setx DI_KEY=<yourKey> |
set VARIABLE_NAME |
顯示特定環境變數的值。 | set DI_KEY |
set |
顯示所有環境變數。 | set |
設定程式設計環境
若要設定程式設計環境,請建立 Gradle 專案並安裝用戶端連結庫。
建立 Gradle 專案
在主控台視窗中,為您的應用程式建立名為 doc-intelligence-app 的目錄,並流覽至該目錄。
mkdir doc-intelligence-app cd doc-intelligence-app
從您的工作目錄執行
gradle init
命令。 此命令會建立 Gradle 的基本組建檔案,包括 build.gradle.kts,將在執行階段使用 build.gradle.kts,來建立及設定應用程式。gradle init --type basic
出現選擇 DSL 的提示時,請選取 [Kotlin]。
選擇 ,然後輸入 以接受預設項目名稱 doc-intelligence-app。
安裝用戶端程式庫
本文使用 Gradle 相依性管理員。 您可以在 Maven 中央存放庫中找到用戶端程式庫和其他相依性管理員的資訊。
在 IDE 中開啟專案的 build.gradle.kts 檔案。 複製並貼上下列程式碼以將客戶端庫作為
implementation
陳述式包含在內,並新增所需的外掛程式和設定。plugins { java application } application { mainClass.set("DocIntelligence") } repositories { mavenCentral() } dependencies { implementation group: 'com.azure', name: 'azure-ai-documentintelligence', version: '1.0.0' }
建立 Java 應用程式
若要與 Document Intelligence 服務互動,請建立 DocumentIntelligenceClient
類別的實例。 若要這樣做,請使用 AzureKeyCredential
從 Azure 入口網站建立 key
,並使用 DocumentIntelligenceClient
和文件智慧服務 AzureKeyCredential
來建立 endpoint
執行個體。
從 doc-intelligence-app 目錄執行下列命令:
mkdir -p src/main/java
該指令會建立下列目錄結構:
流覽至
java
目錄,並建立名為 DocIntelligence.java的檔案。小提示
您可以使用 PowerShell 建立新的檔案。 按住 shift 鍵,並在資料夾上按鼠右鍵,然後在專案目錄中開啟 PowerShell 視窗,然後輸入下列命令:New-Item DocIntelligence.java。
開啟 DocIntelligence.java 檔案,然後選取下列其中一個程式代碼範例,然後將這些範例複製/貼到您的應用程式:
- 預建的讀取 模型是所有文檔智能模型的核心,並且可以偵測行、文字、位置和語言。 版面配置、一般檔、預先建置和自定義模型全都使用
read
模型作為從檔擷取文字的基礎。 - prebuilt-layout 模型會從文件和影像中擷取文字和文字位置、表格、選取標記和結構資訊。
- prebuilt-tax.us.w2 模型會擷取美國國稅局 (IRS) 稅務表單上所報告的資訊。
- 預設發票 模型會從各種格式的銷售發票中擷取關鍵欄位和明細項目。
- 預建收據 模型會從印刷和手寫的銷售收據中擷取重要資訊。
- 預建的 idDocument 模型會從美國駕駛執照、國際護照傳記頁面、美國州身份證、社會保障卡和永久居民卡中擷取重要資訊。
- 預建的讀取 模型是所有文檔智能模型的核心,並且可以偵測行、文字、位置和語言。 版面配置、一般檔、預先建置和自定義模型全都使用
輸入下列命令:
gradle build gradle run
使用 Read 模型
import com.azure.ai.documentintelligence;
import com.azure.ai.documentintelligence.models.AnalyzeDocumentRequest;
import com.azure.ai.documentintelligence.models.AnalyzeResult;
import com.azure.ai.documentintelligence.models.AnalyzeResultOperation;
import com.azure.ai.documentintelligence.models.Document;
import com.azure.ai.documentintelligence.models.DocumentField;
import com.azure.ai.documentintelligence.models.DocumentFieldType;
import com.azure.core.credential.AzureKeyCredential;
import com.azure.core.util.polling.SyncPoller;
import java.io.IOException;
import java.time.LocalDate;
import java.util.List;
import java.util.Map;
public class DocIntelligence {
//use your `key` and `endpoint` environment variables
private static final String key = System.getenv("FR_KEY");
private static final String endpoint = System.getenv("FR_ENDPOINT");
public static void main(final String[] args) {
// create your `DocumentIntelligenceClient` instance and `AzureKeyCredential` variable
DocumentIntelligenceClient client = new DocumentIntelligenceClientBuilder()
.credential(new AzureKeyCredential(key))
.endpoint(endpoint)
.buildClient();
//sample document
String documentUrl = "https://raw.githubusercontent.com/Azure-Samples/cognitive-services-REST-api-samples/master/curl/form-recognizer/rest-api/read.png";
String modelId = "prebuilt-read";
SyncPoller < OperationResult, AnalyzeResult > analyzeLayoutResultPoller =
client.beginAnalyzeDocument(modelId, invoiceUrl);
AnalyzeResult analyzeLayoutResult = analyzeLayoutResultPoller.getFinalResult().getAnalyzeResult();
// pages
analyzeLayoutResult.getPages().forEach(documentPage -> {
System.out.printf("Page has width: %.2f and height: %.2f, measured with unit: %s%n",
documentPage.getWidth(),
documentPage.getHeight(),
documentPage.getUnit());
// lines
documentPage.getLines().forEach(documentLine ->
System.out.printf("Line %s is within a bounding polygon %s.%n",
documentLine.getContent(),
documentLine.getPolygon().toString()));
// words
documentPage.getWords().forEach(documentWord ->
System.out.printf("Word '%s' has a confidence score of %.2f.%n",
documentWord.getContent(),
documentWord.getConfidence()));
});
}
}
請瀏覽 GitHub 上的 Azure 範例存放庫,並檢視 read
模型輸出。
使用 Layout 模型
import com.azure.ai.documentintelligence;
import com.azure.ai.documentintelligence.models.AnalyzeDocumentRequest;
import com.azure.ai.documentintelligence.models.AnalyzeResult;
import com.azure.ai.documentintelligence.models.AnalyzeResultOperation;
import com.azure.ai.documentintelligence.models.Document;
import com.azure.ai.documentintelligence.models.DocumentField;
import com.azure.ai.documentintelligence.models.DocumentFieldType;
import com.azure.core.credential.AzureKeyCredential;
import com.azure.core.util.polling.SyncPoller;
import java.io.IOException;
import java.time.LocalDate;
import java.util.List;
import java.util.Map;
public class DocIntelligence {
//use your `key` and `endpoint` environment variables
private static final String key = System.getenv("FR_KEY");
private static final String endpoint = System.getenv("FR_ENDPOINT");
public static void main(final String[] args) {
// create your `DocumentIntelligenceClient` instance and `AzureKeyCredential` variable
DocumentIntelligenceClient client = new DocumentIntelligenceClientBuilder()
.credential(new AzureKeyCredential(key))
.endpoint(endpoint)
.buildClient();
//sample document
String layoutDocumentUrl = "https://raw.githubusercontent.com/Azure-Samples/cognitive-services-REST-api-samples/master/curl/form-recognizer/rest-api/layout.png";
String modelId = "prebuilt-layout";
SyncPoller < OperationResult, AnalyzeResult > analyzeLayoutResultPoller =
client.beginAnalyzeDocument(modelId, layoutDocumentUrl);
AnalyzeResult analyzeLayoutResult = analyzeLayoutResultPoller.getFinalResult().getAnalyzeResult();
// pages
analyzeLayoutResult.getPages().forEach(documentPage -> {
System.out.printf("Page has width: %.2f and height: %.2f, measured with unit: %s%n",
documentPage.getWidth(),
documentPage.getHeight(),
documentPage.getUnit());
// lines
documentPage.getLines().forEach(documentLine ->
System.out.printf("Line %s is within a bounding polygon %s.%n",
documentLine.getContent(),
documentLine.getPolygon().toString()));
// words
documentPage.getWords().forEach(documentWord ->
System.out.printf("Word '%s' has a confidence score of %.2f%n",
documentWord.getContent(),
documentWord.getConfidence()));
// selection marks
documentPage.getSelectionMarks().forEach(documentSelectionMark ->
System.out.printf("Selection mark is '%s' and is within a bounding polygon %s with confidence %.2f.%n",
documentSelectionMark.getSelectionMarkState().toString(),
getBoundingCoordinates(documentSelectionMark.getPolygon()),
documentSelectionMark.getConfidence()));
});
// tables
List < DocumentTable > tables = analyzeLayoutResult.getTables();
for (int i = 0; i < tables.size(); i++) {
DocumentTable documentTables = tables.get(i);
System.out.printf("Table %d has %d rows and %d columns.%n", i, documentTables.getRowCount(),
documentTables.getColumnCount());
documentTables.getCells().forEach(documentTableCell -> {
System.out.printf("Cell '%s', has row index %d and column index %d.%n", documentTableCell.getContent(),
documentTableCell.getRowIndex(), documentTableCell.getColumnIndex());
});
System.out.println();
}
}
// Utility function to get the bounding polygon coordinates.
private static String getBoundingCoordinates(List < Point > Polygon) {
return Polygon.stream().map(point -> String.format("[%.2f, %.2f]", point.getX(),
point.getY())).collect(Collectors.joining(", "));
}
}
請瀏覽 GitHub 上的 Azure 範例存放庫,並檢視 版面配置模型輸出。
使用通用文件模型
import com.azure.ai.documentintelligence;
import com.azure.ai.documentintelligence.models.AnalyzeDocumentRequest;
import com.azure.ai.documentintelligence.models.AnalyzeResult;
import com.azure.ai.documentintelligence.models.AnalyzeResultOperation;
import com.azure.ai.documentintelligence.models.Document;
import com.azure.ai.documentintelligence.models.DocumentField;
import com.azure.ai.documentintelligence.models.DocumentFieldType;
import com.azure.core.credential.AzureKeyCredential;
import com.azure.core.util.polling.SyncPoller;
import java.io.IOException;
import java.time.LocalDate;
import java.util.List;
import java.util.Map;
public class DocIntelligence {
//use your `key` and `endpoint` environment variables
private static final String key = System.getenv("FR_KEY");
private static final String endpoint = System.getenv("FR_ENDPOINT");
public static void main(final String[] args) {
// create your `DocumentIntelligenceClient` instance and `AzureKeyCredential` variable
DocumentIntelligenceClient client = new DocumentIntelligenceClientBuilder()
.credential(new AzureKeyCredential(key))
.endpoint(endpoint)
.buildClient();
//sample document
String generalDocumentUrl = "https://raw.githubusercontent.com/Azure-Samples/cognitive-services-REST-api-samples/master/curl/form-recognizer/sample-layout.pdf";
String modelId = "prebuilt-document";
SyncPoller < OperationResult, AnalyzeResult > analyzeDocumentPoller =
client.beginAnalyzeDocument(modelId, generalDocumentUrl);
AnalyzeResult analyzeResult = analyzeDocumentPoller.getFinalResult().getAnalyzeResult();
// pages
analyzeResult.getPages().forEach(documentPage -> {
System.out.printf("Page has width: %.2f and height: %.2f, measured with unit: %s%n",
documentPage.getWidth(),
documentPage.getHeight(),
documentPage.getUnit());
// lines
documentPage.getLines().forEach(documentLine ->
System.out.printf("Line %s is within a bounding polygon %s.%n",
documentLine.getContent(),
documentLine.getPolygon().toString()));
// words
documentPage.getWords().forEach(documentWord ->
System.out.printf("Word %s has a confidence score of %.2f%n.",
documentWord.getContent(),
documentWord.getConfidence()));
});
// tables
List < DocumentTable > tab_les = analyzeResult.getTables();
for (int i = 0; i < tab_les.size(); i++) {
DocumentTable documentTable = tab_les.get(i);
System.out.printf("Table %d has %d rows and %d columns.%n", i, documentTable.getRowCount(),
documentTable.getColumnCount());
documentTable.getCells().forEach(documentTableCell -> {
System.out.printf("Cell '%s', has row index %d and column index %d.%n",
documentTableCell.getContent(),
documentTableCell.getRowIndex(), documentTableCell.getColumnIndex());
});
System.out.println();
}
// Key-value pairs
analyzeResult.getKeyValuePairs().forEach(documentKeyValuePair -> {
System.out.printf("Key content: %s%n", documentKeyValuePair.getKey().getContent());
System.out.printf("Key content bounding region: %s%n",
documentKeyValuePair.getKey().getBoundingRegions().toString());
if (documentKeyValuePair.getValue() != null) {
System.out.printf("Value content: %s%n", documentKeyValuePair.getValue().getContent());
System.out.printf("Value content bounding region: %s%n", documentKeyValuePair.getValue().getBoundingRegions().toString());
}
});
}
}
請瀏覽 GitHub 上的 Azure 範例存放庫,並檢視 一般檔案模型輸出。
使用 W-2 稅務模型
import com.azure.ai.documentintelligence;
import com.azure.ai.documentintelligence.models.AnalyzeDocumentRequest;
import com.azure.ai.documentintelligence.models.AnalyzeResult;
import com.azure.ai.documentintelligence.models.AnalyzeResultOperation;
import com.azure.ai.documentintelligence.models.Document;
import com.azure.ai.documentintelligence.models.DocumentField;
import com.azure.ai.documentintelligence.models.DocumentFieldType;
import com.azure.core.credential.AzureKeyCredential;
import com.azure.core.util.polling.SyncPoller;
import java.io.IOException;
import java.time.LocalDate;
import java.util.List;
import java.util.Map;
public class DocIntelligence {
//use your `key` and `endpoint` environment variables
private static final String key = System.getenv("FR_KEY");
private static final String endpoint = System.getenv("FR_ENDPOINT");
public static void main(final String[] args) {
// create your `DocumentIntelligenceClient` instance and `AzureKeyCredential` variable
DocumentIntelligenceClient client = new DocumentIntelligenceClientBuilder()
.credential(new AzureKeyCredential(key))
.endpoint(endpoint)
.buildClient();
// sample document
String w2Url = "https://raw.githubusercontent.com/Azure-Samples/cognitive-services-REST-api-samples/master/curl/form-recognizer/rest-api/w2.png";
String modelId = "prebuilt-tax.us.w2";
SyncPoller < OperationResult, AnalyzeResult > analyzeW2Poller =
client.beginAnalyzeDocument(modelId, w2Url);
AnalyzeResult analyzeTaxResult = analyzeW2Poller.getFinalResult().getAnalyzeResult();
for (int i = 0; i < analyzeTaxResult.getDocuments().size(); i++) {
AnalyzedDocument analyzedTaxDocument = analyzeTaxResult.getDocuments().get(i);
Map < String, DocumentField > taxFields = analyzedTaxDocument.getFields();
System.out.printf("----------- Analyzing Document %d -----------%n", i);
DocumentField w2FormVariantField = taxFields.get("W2FormVariant");
if (w2FormVariantField != null) {
if (DocumentFieldType.STRING == w2FormVariantField.getType()) {
String merchantName = w2FormVariantField.getValueAsString();
System.out.printf("Form variant: %s, confidence: %.2f%n",
merchantName, w2FormVariantField.getConfidence());
}
}
DocumentField employeeField = taxFields.get("Employee");
if (employeeField != null) {
System.out.println("Employee Data: ");
if (DocumentFieldType.MAP == employeeField.getType()) {
Map < String, DocumentField > employeeDataFieldMap = employeeField.getValueAsMap();
DocumentField employeeName = employeeDataFieldMap.get("Name");
if (employeeName != null) {
if (DocumentFieldType.STRING == employeeName.getType()) {
String employeesName = employeeName.getValueAsString();
System.out.printf("Employee Name: %s, confidence: %.2f%n",
employeesName, employeeName.getConfidence());
}
}
DocumentField employeeAddrField = employeeDataFieldMap.get("Address");
if (employeeAddrField != null) {
if (DocumentFieldType.STRING == employeeAddrField.getType()) {
String employeeAddress = employeeAddrField.getValueAsString();
System.out.printf("Employee Address: %s, confidence: %.2f%n",
employeeAddress, employeeAddrField.getConfidence());
}
}
}
}
DocumentField employerField = taxFields.get("Employer");
if (employerField != null) {
System.out.println("Employer Data: ");
if (DocumentFieldType.MAP == employerField.getType()) {
Map < String, DocumentField > employerDataFieldMap = employerField.getValueAsMap();
DocumentField employerNameField = employerDataFieldMap.get("Name");
if (employerNameField != null) {
if (DocumentFieldType.STRING == employerNameField.getType()) {
String employerName = employerNameField.getValueAsString();
System.out.printf("Employer Name: %s, confidence: %.2f%n",
employerName, employerNameField.getConfidence());
}
}
DocumentField employerIDNumberField = employerDataFieldMap.get("IdNumber");
if (employerIDNumberField != null) {
if (DocumentFieldType.STRING == employerIDNumberField.getType()) {
String employerIdNumber = employerIDNumberField.getValueAsString();
System.out.printf("Employee ID Number: %s, confidence: %.2f%n",
employerIdNumber, employerIDNumberField.getConfidence());
}
}
}
}
DocumentField taxYearField = taxFields.get("TaxYear");
if (taxYearField != null) {
if (DocumentFieldType.STRING == taxYearField.getType()) {
String taxYear = taxYearField.getValueAsString();
System.out.printf("Tax year: %s, confidence: %.2f%n",
taxYear, taxYearField.getConfidence());
}
}
DocumentField taxDateField = taxFields.get("TaxDate");
if (taxDateField != null) {
if (DocumentFieldType.DATE == taxDateField.getType()) {
LocalDate taxDate = taxDateField.getValueAsDate();
System.out.printf("Tax Date: %s, confidence: %.2f%n",
taxDate, taxDateField.getConfidence());
}
}
DocumentField socialSecurityTaxField = taxFields.get("SocialSecurityTaxWithheld");
if (socialSecurityTaxField != null) {
if (DocumentFieldType.DOUBLE == socialSecurityTaxField.getType()) {
Double socialSecurityTax = socialSecurityTaxField.getValueAsDouble();
System.out.printf("Social Security Tax withheld: %.2f, confidence: %.2f%n",
socialSecurityTax, socialSecurityTaxField.getConfidence());
}
}
}
}
}
請瀏覽 GitHub 上的 Azure 範例存放庫,並檢視 W-2 稅務模型輸出。
使用發票模型
import com.azure.ai.documentintelligence;
import com.azure.ai.documentintelligence.models.AnalyzeDocumentRequest;
import com.azure.ai.documentintelligence.models.AnalyzeResult;
import com.azure.ai.documentintelligence.models.AnalyzeResultOperation;
import com.azure.ai.documentintelligence.models.Document;
import com.azure.ai.documentintelligence.models.DocumentField;
import com.azure.ai.documentintelligence.models.DocumentFieldType;
import com.azure.core.credential.AzureKeyCredential;
import com.azure.core.util.polling.SyncPoller;
import java.io.IOException;
import java.time.LocalDate;
import java.util.List;
import java.util.Map;
public class DocIntelligence {
//use your `key` and `endpoint` environment variables
private static final String key = System.getenv("FR_KEY");
private static final String endpoint = System.getenv("FR_ENDPOINT");
public static void main(final String[] args) {
// create your `DocumentIntelligenceClient` instance and `AzureKeyCredential` variable
DocumentIntelligenceClient client = new DocumentIntelligenceClientBuilder()
.credential(new AzureKeyCredential(key))
.endpoint(endpoint)
.buildClient();
// sample document
String invoiceUrl = "https://github.com/Azure-Samples/cognitive-services-REST-api-samples/raw/master/curl/form-recognizer/rest-api/invoice.pdf";
String modelId = "prebuilt-invoice";
SyncPoller < OperationResult, AnalyzeResult > analyzeInvoicesPoller =
client.beginAnalyzeDocument(modelId, invoiceUrl);
AnalyzeResult analyzeInvoiceResult = analyzeInvoicesPoller.getFinalResult().getAnalyzeResult();
for (int i = 0; i < analyzeInvoiceResult.getDocuments().size(); i++) {
AnalyzedDocument analyzedInvoice = analyzeInvoiceResult.getDocuments().get(i);
Map < String, DocumentField > invoiceFields = analyzedInvoice.getFields();
System.out.printf("----------- Analyzing invoice %d -----------%n", i);
DocumentField vendorNameField = invoiceFields.get("VendorName");
if (vendorNameField != null) {
if (DocumentFieldType.STRING == vendorNameField.getType()) {
String merchantName = vendorNameField.getValueAsString();
System.out.printf("Vendor Name: %s, confidence: %.2f%n",
merchantName, vendorNameField.getConfidence());
}
}
DocumentField vendorAddressField = invoiceFields.get("VendorAddress");
if (vendorAddressField != null) {
if (DocumentFieldType.STRING == vendorAddressField.getType()) {
String merchantAddress = vendorAddressField.getValueAsString();
System.out.printf("Vendor address: %s, confidence: %.2f%n",
merchantAddress, vendorAddressField.getConfidence());
}
}
DocumentField customerNameField = invoiceFields.get("CustomerName");
if (customerNameField != null) {
if (DocumentFieldType.STRING == customerNameField.getType()) {
String merchantAddress = customerNameField.getValueAsString();
System.out.printf("Customer Name: %s, confidence: %.2f%n",
merchantAddress, customerNameField.getConfidence());
}
}
DocumentField customerAddressRecipientField = invoiceFields.get("CustomerAddressRecipient");
if (customerAddressRecipientField != null) {
if (DocumentFieldType.STRING == customerAddressRecipientField.getType()) {
String customerAddr = customerAddressRecipientField.getValueAsString();
System.out.printf("Customer Address Recipient: %s, confidence: %.2f%n",
customerAddr, customerAddressRecipientField.getConfidence());
}
}
DocumentField invoiceIdField = invoiceFields.get("InvoiceId");
if (invoiceIdField != null) {
if (DocumentFieldType.STRING == invoiceIdField.getType()) {
String invoiceId = invoiceIdField.getValueAsString();
System.out.printf("Invoice ID: %s, confidence: %.2f%n",
invoiceId, invoiceIdField.getConfidence());
}
}
DocumentField invoiceDateField = invoiceFields.get("InvoiceDate");
if (customerNameField != null) {
if (DocumentFieldType.DATE == invoiceDateField.getType()) {
LocalDate invoiceDate = invoiceDateField.getValueAsDate();
System.out.printf("Invoice Date: %s, confidence: %.2f%n",
invoiceDate, invoiceDateField.getConfidence());
}
}
DocumentField invoiceTotalField = invoiceFields.get("InvoiceTotal");
if (customerAddressRecipientField != null) {
if (DocumentFieldType.DOUBLE == invoiceTotalField.getType()) {
Double invoiceTotal = invoiceTotalField.getValueAsDouble();
System.out.printf("Invoice Total: %.2f, confidence: %.2f%n",
invoiceTotal, invoiceTotalField.getConfidence());
}
}
DocumentField invoiceItemsField = invoiceFields.get("Items");
if (invoiceItemsField != null) {
System.out.printf("Invoice Items: %n");
if (DocumentFieldType.LIST == invoiceItemsField.getType()) {
List < DocumentField > invoiceItems = invoiceItemsField.getValueAsList();
invoiceItems.stream()
.filter(invoiceItem -> DocumentFieldType.MAP == invoiceItem.getType())
.map(documentField -> documentField.getValueAsMap())
.forEach(documentFieldMap -> documentFieldMap.forEach((key, documentField) -> {
if ("Description".equals(key)) {
if (DocumentFieldType.STRING == documentField.getType()) {
String name = documentField.getValueAsString();
System.out.printf("Description: %s, confidence: %.2fs%n",
name, documentField.getConfidence());
}
}
if ("Quantity".equals(key)) {
if (DocumentFieldType.DOUBLE == documentField.getType()) {
Double quantity = documentField.getValueAsDouble();
System.out.printf("Quantity: %f, confidence: %.2f%n",
quantity, documentField.getConfidence());
}
}
if ("UnitPrice".equals(key)) {
if (DocumentFieldType.DOUBLE == documentField.getType()) {
Double unitPrice = documentField.getValueAsDouble();
System.out.printf("Unit Price: %f, confidence: %.2f%n",
unitPrice, documentField.getConfidence());
}
}
if ("ProductCode".equals(key)) {
if (DocumentFieldType.DOUBLE == documentField.getType()) {
Double productCode = documentField.getValueAsDouble();
System.out.printf("Product Code: %f, confidence: %.2f%n",
productCode, documentField.getConfidence());
}
}
}));
}
}
}
}
}
請瀏覽 GitHub 上的 Azure 範例存放庫,並檢視 發票模型輸出。
使用收據模型
import com.azure.ai.documentintelligence;
import com.azure.ai.documentintelligence.models.AnalyzeDocumentRequest;
import com.azure.ai.documentintelligence.models.AnalyzeResult;
import com.azure.ai.documentintelligence.models.AnalyzeResultOperation;
import com.azure.ai.documentintelligence.models.Document;
import com.azure.ai.documentintelligence.models.DocumentField;
import com.azure.ai.documentintelligence.models.DocumentFieldType;
import com.azure.core.credential.AzureKeyCredential;
import com.azure.core.util.polling.SyncPoller;
import java.io.IOException;
import java.time.LocalDate;
import java.util.List;
import java.util.Map;
public class DocIntelligence {
//use your `key` and `endpoint` environment variables
private static final String key = System.getenv("FR_KEY");
private static final String endpoint = System.getenv("FR_ENDPOINT");
public static void main(final String[] args) {
// create your `DocumentIntelligenceClient` instance and `AzureKeyCredential` variable
DocumentIntelligenceClient client = new DocumentIntelligenceClientBuilder()
.credential(new AzureKeyCredential(key))
.endpoint(endpoint)
.buildClient();
String receiptUrl = "https://raw.githubusercontent.com/Azure-Samples/cognitive-services-REST-api-samples/master/curl/form-recognizer/rest-api/receipt.png";
String modelId = "prebuilt-receipt";
SyncPoller < OperationResult, AnalyzeResult > analyzeReceiptPoller =
client.beginAnalyzeDocument(modelId, receiptUrl);
AnalyzeResult receiptResults = analyzeReceiptPoller.getFinalResult().getAnalyzeResult();
for (int i = 0; i < receiptResults.getDocuments().size(); i++) {
AnalyzedDocument analyzedReceipt = receiptResults.getDocuments().get(i);
Map < String, DocumentField > receiptFields = analyzedReceipt.getFields();
System.out.printf("----------- Analyzing receipt info %d -----------%n", i);
DocumentField merchantNameField = receiptFields.get("MerchantName");
if (merchantNameField != null) {
if (DocumentFieldType.STRING == merchantNameField.getType()) {
String merchantName = merchantNameField.getValueAsString();
System.out.printf("Merchant Name: %s, confidence: %.2f%n",
merchantName, merchantNameField.getConfidence());
}
}
DocumentField merchantPhoneNumberField = receiptFields.get("MerchantPhoneNumber");
if (merchantPhoneNumberField != null) {
if (DocumentFieldType.PHONE_NUMBER == merchantPhoneNumberField.getType()) {
String merchantAddress = merchantPhoneNumberField.getValueAsPhoneNumber();
System.out.printf("Merchant Phone number: %s, confidence: %.2f%n",
merchantAddress, merchantPhoneNumberField.getConfidence());
}
}
DocumentField merchantAddressField = receiptFields.get("MerchantAddress");
if (merchantAddressField != null) {
if (DocumentFieldType.STRING == merchantAddressField.getType()) {
String merchantAddress = merchantAddressField.getValueAsString();
System.out.printf("Merchant Address: %s, confidence: %.2f%n",
merchantAddress, merchantAddressField.getConfidence());
}
}
DocumentField transactionDateField = receiptFields.get("TransactionDate");
if (transactionDateField != null) {
if (DocumentFieldType.DATE == transactionDateField.getType()) {
LocalDate transactionDate = transactionDateField.getValueAsDate();
System.out.printf("Transaction Date: %s, confidence: %.2f%n",
transactionDate, transactionDateField.getConfidence());
}
}
DocumentField receiptItemsField = receiptFields.get("Items");
if (receiptItemsField != null) {
System.out.printf("Receipt Items: %n");
if (DocumentFieldType.LIST == receiptItemsField.getType()) {
List < DocumentField > receiptItems = receiptItemsField.getValueAsList();
receiptItems.stream()
.filter(receiptItem -> DocumentFieldType.MAP == receiptItem.getType())
.map(documentField -> documentField.getValueAsMap())
.forEach(documentFieldMap -> documentFieldMap.forEach((key, documentField) -> {
if ("Name".equals(key)) {
if (DocumentFieldType.STRING == documentField.getType()) {
String name = documentField.getValueAsString();
System.out.printf("Name: %s, confidence: %.2fs%n",
name, documentField.getConfidence());
}
}
if ("Quantity".equals(key)) {
if (DocumentFieldType.DOUBLE == documentField.getType()) {
Double quantity = documentField.getValueAsDouble();
System.out.printf("Quantity: %f, confidence: %.2f%n",
quantity, documentField.getConfidence());
}
}
if ("Price".equals(key)) {
if (DocumentFieldType.DOUBLE == documentField.getType()) {
Double price = documentField.getValueAsDouble();
System.out.printf("Price: %f, confidence: %.2f%n",
price, documentField.getConfidence());
}
}
if ("TotalPrice".equals(key)) {
if (DocumentFieldType.DOUBLE == documentField.getType()) {
Double totalPrice = documentField.getValueAsDouble();
System.out.printf("Total Price: %f, confidence: %.2f%n",
totalPrice, documentField.getConfidence());
}
}
}));
}
}
}
}
}
請瀏覽 GitHub 上的 Azure 範例存放庫,並檢視 收據模型輸出。
使用身分證件模型
import com.azure.ai.documentintelligence;
import com.azure.ai.documentintelligence.models.AnalyzeDocumentRequest;
import com.azure.ai.documentintelligence.models.AnalyzeResult;
import com.azure.ai.documentintelligence.models.AnalyzeResultOperation;
import com.azure.ai.documentintelligence.models.Document;
import com.azure.ai.documentintelligence.models.DocumentField;
import com.azure.ai.documentintelligence.models.DocumentFieldType;
import com.azure.core.credential.AzureKeyCredential;
import com.azure.core.util.polling.SyncPoller;
import java.io.IOException;
import java.time.LocalDate;
import java.util.List;
import java.util.Map;
public class DocIntelligence {
//use your `key` and `endpoint` environment variables
private static final String key = System.getenv("FR_KEY");
private static final String endpoint = System.getenv("FR_ENDPOINT");
public static void main(final String[] args) {
// create your `DocumentIntelligenceClient` instance and `AzureKeyCredential` variable
DocumentIntelligenceClient client = new DocumentIntelligenceClientBuilder()
.credential(new AzureKeyCredential(key))
.endpoint(endpoint)
.buildClient();
//sample document
String licenseUrl = "https://raw.githubusercontent.com/Azure-Samples/cognitive-services-REST-api-samples/master/curl/form-recognizer/rest-api/identity_documents.png";
String modelId = "prebuilt-idDocument";
SyncPoller < OperationResult, AnalyzeResult > analyzeIdentityDocumentPoller = client.beginAnalyzeDocument(modelId, licenseUrl);
AnalyzeResult identityDocumentResults = analyzeIdentityDocumentPoller.getFinalResult().getAnalyzeResult();
for (int i = 0; i < identityDocumentResults.getDocuments().size(); i++) {
AnalyzedDocument analyzedIDDocument = identityDocumentResults.getDocuments().get(i);
Map < String, DocumentField > licenseFields = analyzedIDDocument.getFields();
System.out.printf("----------- Analyzed license info for page %d -----------%n", i);
DocumentField addressField = licenseFields.get("Address");
if (addressField != null) {
if (DocumentFieldType.STRING == addressField.getType()) {
String address = addressField.getValueAsString();
System.out.printf("Address: %s, confidence: %.2f%n",
address, addressField.getConfidence());
}
}
DocumentField countryRegionDocumentField = licenseFields.get("CountryRegion");
if (countryRegionDocumentField != null) {
if (DocumentFieldType.STRING == countryRegionDocumentField.getType()) {
String countryRegion = countryRegionDocumentField.getValueAsCountry();
System.out.printf("Country or region: %s, confidence: %.2f%n",
countryRegion, countryRegionDocumentField.getConfidence());
}
}
DocumentField dateOfBirthField = licenseFields.get("DateOfBirth");
if (dateOfBirthField != null) {
if (DocumentFieldType.DATE == dateOfBirthField.getType()) {
LocalDate dateOfBirth = dateOfBirthField.getValueAsDate();
System.out.printf("Date of Birth: %s, confidence: %.2f%n",
dateOfBirth, dateOfBirthField.getConfidence());
}
}
DocumentField dateOfExpirationField = licenseFields.get("DateOfExpiration");
if (dateOfExpirationField != null) {
if (DocumentFieldType.DATE == dateOfExpirationField.getType()) {
LocalDate expirationDate = dateOfExpirationField.getValueAsDate();
System.out.printf("Document date of expiration: %s, confidence: %.2f%n",
expirationDate, dateOfExpirationField.getConfidence());
}
}
DocumentField documentNumberField = licenseFields.get("DocumentNumber");
if (documentNumberField != null) {
if (DocumentFieldType.STRING == documentNumberField.getType()) {
String documentNumber = documentNumberField.getValueAsString();
System.out.printf("Document number: %s, confidence: %.2f%n",
documentNumber, documentNumberField.getConfidence());
}
}
DocumentField firstNameField = licenseFields.get("FirstName");
if (firstNameField != null) {
if (DocumentFieldType.STRING == firstNameField.getType()) {
String firstName = firstNameField.getValueAsString();
System.out.printf("First Name: %s, confidence: %.2f%n",
firstName, documentNumberField.getConfidence());
}
}
DocumentField lastNameField = licenseFields.get("LastName");
if (lastNameField != null) {
if (DocumentFieldType.STRING == lastNameField.getType()) {
String lastName = lastNameField.getValueAsString();
System.out.printf("Last name: %s, confidence: %.2f%n",
lastName, lastNameField.getConfidence());
}
}
DocumentField regionField = licenseFields.get("Region");
if (regionField != null) {
if (DocumentFieldType.STRING == regionField.getType()) {
String region = regionField.getValueAsString();
System.out.printf("Region: %s, confidence: %.2f%n",
region, regionField.getConfidence());
}
}
}
}
}
請瀏覽 GitHub 上的 Azure 範例存放庫,並檢視 識別碼檔案模型輸出。
先決條件
Azure 訂用帳戶 - 免費建立一個訂用帳戶。
最新的 Visual Studio Code 版本或您慣用的 IDE。 請參閱 Visual Studio Code 中的Java。
- Visual Studio Code 為適用於 Windows 和 macOS 的 Java 提供 程式代碼套件。 程式代碼撰寫套件是一組
VS Code
、Java 開發工具包 (JDK),以及Microsoft建議的延伸模組集合。 編碼套件也可以用於修正現有的開發環境。 - 如果您使用
VS Code
和適用於 Java 的編碼套件,請安裝適用於 Java 的 Gradle 擴充功能。
如果您未使用 Visual Studio Code,請確保在開發環境中安裝下列項目:
- Java 開發套件 (JDK) 第 8 版或更新版本。 如需詳細資訊,請參閱 Microsoft Build of OpenJDK。
- Gradle,6.8 版或後續版本。
- Visual Studio Code 為適用於 Windows 和 macOS 的 Java 提供 程式代碼套件。 程式代碼撰寫套件是一組
Azure AI 服務或文件智慧服務資源。 建立 單一服務 或 多服務。 您可以使用免費定價層 (
F0
) 來試用服務,之後可升級至付費層以用於實際執行環境。小提示
如果您打算使用單一端點和密鑰來存取多個 Azure AI 服務,請建立 Azure AI 服務資源。 針對僅限文件智慧服務存取,請建立文件智慧服務資源。 如果您想要使用 Microsoft Entra 驗證,則需要使用單一服務資源。
從您所建立資源的金鑰和端點,將應用程式連線至 Azure 文件智慧服務。
- 部署資源之後,請選取 [前往資源]。
- 在左側導覽功能表中,選取 [金鑰和端點]。
- 複製其中一個金鑰和 端點,以供本文稍後使用。
URL 的文件檔案。 針對此專案,您可以使用下表中針對每項功能的範例表單:
特徵 / 功能 modelID document-url Read 模型 prebuilt-read 範例手冊 版面配置模型 預設佈局 範例預約確認 W-2 表單模型 prebuilt-tax.us.w2 範例 W-2 表單 發票模型 prebuilt-invoice 範例發票 收據模型 prebuilt-receipt 範例收據 識別碼文件模型 prebuilt-idDocument 範例身份文件 名片模型 prebuilt-businessCard 範例名片
設定環境變數
若要與此文件智慧服務互動,您必須建立 DocumentAnalysisClient
類別的執行個體。 若要這樣做,請使用 Azure 入口網站中的 key
和 endpoint
具現化用戶端。 針對此專案,請使用環境變數來儲存和存取認證。
這很重要
請謹慎使用 API 金鑰。 請勿在程式碼中直接包含 API 金鑰,且切勿公開張貼金鑰。 如果您使用 API 金鑰,請安全地將其儲存在 Azure 金鑰保存庫。 如需在應用程式中安全地使用 API 金鑰的詳細資訊,請參閱搭配 Azure 金鑰保存庫 的 API 金鑰。
如需 AI 服務安全性的詳細資訊,請參閱驗證對 Azure AI 服務的要求。
若要設定 Document Intelligence 資源金鑰的環境變數,請開啟主控台視窗,並遵循作系統和開發環境的指示。 將 <yourKey> 和 <yourEndpoint> 取代為 Azure 入口網站中資源的值。
Windows 中的環境變數不會區分大小寫。 它們通常會以大寫方式宣告,單字之間以底線連結。 在命令提示字元中,執行下列命令:
設定您的金鑰變數:
setx DI_KEY <yourKey>
設定您的端點變數
setx DI_ENDPOINT <yourEndpoint>
設定環境變數之後,請關閉 [命令提示字元] 視窗。 值會維持不變,直到您再次變更這些值為止。
重新啟動讀取環境變數的任何執行中程式。 例如,如果您使用 Visual Studio 或 Visual Studio Code 作為編輯器,請在執行範例程式代碼之前重新啟動。
以下是搭配環境變數使用的一些更實用的命令:
命令 | 動作 | 範例 |
---|---|---|
setx VARIABLE_NAME= |
將值設定為空字串,以刪除環境變數。 | setx DI_KEY= |
setx VARIABLE_NAME=value |
設定或變更環境變數的值。 | setx DI_KEY=<yourKey> |
set VARIABLE_NAME |
顯示特定環境變數的值。 | set DI_KEY |
set |
顯示所有環境變數。 | set |
設定程式設計環境
若要設定程式設計環境,請建立 Gradle 專案並安裝用戶端連結庫。
建立 Gradle 專案
在主控台視窗中,為名為 窗體辨識器應用程式 的應用程式建立目錄,並流覽至它。
mkdir form-recognizer-app cd form-recognizer-app
從您的工作目錄執行
gradle init
命令。 此命令會建立 Gradle 的基本組建檔案,包括 build.gradle.kts,將在執行階段使用 build.gradle.kts,來建立及設定應用程式。gradle init --type basic
出現選擇 DSL 的提示時,請選取 [Kotlin]。
選擇 [輸入 以接受預設項目名稱,表單辨識器-應用程式。
安裝用戶端程式庫
本文使用 Gradle 相依性管理員。 您可以在 Maven 中央存放庫中找到用戶端程式庫和其他相依性管理員的資訊。
在 IDE 中開啟專案的 build.gradle.kts 檔案。 複製並貼上下列程式碼以將客戶端庫作為
implementation
陳述式包含在內,並新增所需的外掛程式和設定。plugins { java application } application { mainClass.set("FormRecognizer") } repositories { mavenCentral() } dependencies { implementation(group = "com.azure", name = "azure-ai-formrecognizer", version = "4.0.0") }
建立 Java 應用程式
若要與 Document Intelligence 服務互動,請建立 DocumentAnalysisClient
類別的實例。 若要這樣做,請使用 AzureKeyCredential
從 Azure 入口網站建立 key
,並使用 DocumentAnalysisClient
和文件智慧服務 AzureKeyCredential
來建立 endpoint
執行個體。
從 form-recognizer-app 目錄中,執行下列命令:
mkdir -p src/main/java
您會建立下列目錄結構:
流覽至
java
目錄,並建立名為 FormRecognizer.java的檔案。小提示
您可以使用 PowerShell 建立新的檔案。 按住 Shift 鍵,並在資料夾上按下滑鼠右鍵,然後輸入下列命令,以開啟項目目錄中的 PowerShell 視窗:New-Item FormRecognizer.java。
開啟 FormRecognizer.java 檔案,然後選取下列其中一個程式代碼範例,然後將/貼到您的應用程式:
- 預建的讀取 模型是所有文檔智能模型的核心,並且可以偵測行、文字、位置和語言。 版面配置、一般檔、預先建置和自定義模型全都使用
read
模型作為從檔擷取文字的基礎。 - prebuilt-layout 模型會從文件和影像中擷取文字和文字位置、表格、選取標記和結構資訊。
- prebuilt-tax.us.w2 模型會擷取美國國稅局 (IRS) 稅務表單上所報告的資訊。
- 預設發票 模型會從各種格式的銷售發票中擷取關鍵欄位和明細項目。
- 預建收據 模型會從印刷和手寫的銷售收據中擷取重要資訊。
- 預建的 idDocument 模型會從美國駕駛執照、國際護照傳記頁面、美國州身份證、社會保障卡和永久居民卡中擷取重要資訊。
- 預建的讀取 模型是所有文檔智能模型的核心,並且可以偵測行、文字、位置和語言。 版面配置、一般檔、預先建置和自定義模型全都使用
輸入下列命令:
gradle build gradle -PmainClass=FormRecognizer run
使用 Read 模型
import com.azure.ai.formrecognizer.*;
import com.azure.ai.formrecognizer.documentanalysis.models.*;
import com.azure.ai.formrecognizer.documentanalysis.DocumentAnalysisClient;
import com.azure.ai.formrecognizer.documentanalysis.DocumentAnalysisClientBuilder;
import com.azure.core.credential.AzureKeyCredential;
import com.azure.core.util.polling.SyncPoller;
import java.io.IOException;
import java.util.List;
import java.util.Arrays;
import java.time.LocalDate;
import java.util.Map;
import java.util.stream.Collectors;
public class FormRecognizer {
//use your `key` and `endpoint` environment variables
private static final String key = System.getenv("FR_KEY");
private static final String endpoint = System.getenv("FR_ENDPOINT");
public static void main(final String[] args) {
// create your `DocumentAnalysisClient` instance and `AzureKeyCredential` variable
DocumentAnalysisClient client = new DocumentAnalysisClientBuilder()
.credential(new AzureKeyCredential(key))
.endpoint(endpoint)
.buildClient();
//sample document
String documentUrl = "https://raw.githubusercontent.com/Azure-Samples/cognitive-services-REST-api-samples/master/curl/form-recognizer/rest-api/read.png";
String modelId = "prebuilt-read";
SyncPoller < OperationResult, AnalyzeResult > analyzeLayoutResultPoller =
client.beginAnalyzeDocumentFromUrl(modelId, documentUrl);
AnalyzeResult analyzeLayoutResult = analyzeLayoutResultPoller.getFinalResult();
// pages
analyzeLayoutResult.getPages().forEach(documentPage -> {
System.out.printf("Page has width: %.2f and height: %.2f, measured with unit: %s%n",
documentPage.getWidth(),
documentPage.getHeight(),
documentPage.getUnit());
// lines
documentPage.getLines().forEach(documentLine ->
System.out.printf("Line %s is within a bounding polygon %s.%n",
documentLine.getContent(),
documentLine.getBoundingPolygon().toString()));
// words
documentPage.getWords().forEach(documentWord ->
System.out.printf("Word '%s' has a confidence score of %.2f.%n",
documentWord.getContent(),
documentWord.getConfidence()));
});
}
}
請瀏覽 GitHub 上的 Azure 範例存放庫,並檢視 read
模型輸出。
使用 Layout 模型
import com.azure.ai.formrecognizer.*;
import com.azure.ai.formrecognizer.documentanalysis.models.*;
import com.azure.ai.formrecognizer.documentanalysis.DocumentAnalysisClient;
import com.azure.ai.formrecognizer.documentanalysis.DocumentAnalysisClientBuilder;
import com.azure.core.credential.AzureKeyCredential;
import com.azure.core.util.polling.SyncPoller;
import java.io.IOException;
import java.util.List;
import java.util.Arrays;
import java.time.LocalDate;
import java.util.Map;
import java.util.stream.Collectors;
public class FormRecognizer {
//use your `key` and `endpoint` environment variables
private static final String key = System.getenv("FR_KEY");
private static final String endpoint = System.getenv("FR_ENDPOINT");
public static void main(final String[] args) {
// create your `DocumentAnalysisClient` instance and `AzureKeyCredential` variable
DocumentAnalysisClient client = new DocumentAnalysisClientBuilder()
.credential(new AzureKeyCredential(key))
.endpoint(endpoint)
.buildClient();
//sample document
String layoutDocumentUrl = "https://raw.githubusercontent.com/Azure-Samples/cognitive-services-REST-api-samples/master/curl/form-recognizer/rest-api/layout.png";
String modelId = "prebuilt-layout";
SyncPoller < OperationResult, AnalyzeResult > analyzeLayoutResultPoller =
client.beginAnalyzeDocumentFromUrl(modelId, layoutDocumentUrl);
AnalyzeResult analyzeLayoutResult = analyzeLayoutResultPoller.getFinalResult();
// pages
analyzeLayoutResult.getPages().forEach(documentPage -> {
System.out.printf("Page has width: %.2f and height: %.2f, measured with unit: %s%n",
documentPage.getWidth(),
documentPage.getHeight(),
documentPage.getUnit());
// lines
documentPage.getLines().forEach(documentLine ->
System.out.printf("Line %s is within a bounding polygon %s.%n",
documentLine.getContent(),
documentLine.getBoundingPolygon().toString()));
// words
documentPage.getWords().forEach(documentWord ->
System.out.printf("Word '%s' has a confidence score of %.2f%n",
documentWord.getContent(),
documentWord.getConfidence()));
// selection marks
documentPage.getSelectionMarks().forEach(documentSelectionMark ->
System.out.printf("Selection mark is '%s' and is within a bounding polygon %s with confidence %.2f.%n",
documentSelectionMark.getSelectionMarkState().toString(),
getBoundingCoordinates(documentSelectionMark.getBoundingPolygon()),
documentSelectionMark.getConfidence()));
});
// tables
List < DocumentTable > tables = analyzeLayoutResult.getTables();
for (int i = 0; i < tables.size(); i++) {
DocumentTable documentTables = tables.get(i);
System.out.printf("Table %d has %d rows and %d columns.%n", i, documentTables.getRowCount(),
documentTables.getColumnCount());
documentTables.getCells().forEach(documentTableCell -> {
System.out.printf("Cell '%s', has row index %d and column index %d.%n", documentTableCell.getContent(),
documentTableCell.getRowIndex(), documentTableCell.getColumnIndex());
});
System.out.println();
}
}
// Utility function to get the bounding polygon coordinates.
private static String getBoundingCoordinates(List < Point > boundingPolygon) {
return boundingPolygon.stream().map(point -> String.format("[%.2f, %.2f]", point.getX(),
point.getY())).collect(Collectors.joining(", "));
}
}
請瀏覽 GitHub 上的 Azure 範例存放庫,並檢視 版面配置模型輸出。
使用通用文件模型
import com.azure.ai.formrecognizer.*;
import com.azure.ai.formrecognizer.documentanalysis.models.*;
import com.azure.ai.formrecognizer.documentanalysis.DocumentAnalysisClient;
import com.azure.ai.formrecognizer.documentanalysis.DocumentAnalysisClientBuilder;
import com.azure.core.credential.AzureKeyCredential;
import com.azure.core.util.polling.SyncPoller;
import java.io.IOException;
import java.util.List;
import java.util.Arrays;
import java.time.LocalDate;
import java.util.Map;
import java.util.stream.Collectors;
public class FormRecognizer {
//use your `key` and `endpoint` environment variables
private static final String key = System.getenv("FR_KEY");
private static final String endpoint = System.getenv("FR_ENDPOINT");
public static void main(final String[] args) {
// create your `DocumentAnalysisClient` instance and `AzureKeyCredential` variable
DocumentAnalysisClient client = new DocumentAnalysisClientBuilder()
.credential(new AzureKeyCredential(key))
.endpoint(endpoint)
.buildClient();
//sample document
String generalDocumentUrl = "https://raw.githubusercontent.com/Azure-Samples/cognitive-services-REST-api-samples/master/curl/form-recognizer/sample-layout.pdf";
String modelId = "prebuilt-document";
SyncPoller < OperationResult, AnalyzeResult > analyzeDocumentPoller =
client.beginAnalyzeDocumentFromUrl(modelId, generalDocumentUrl);
AnalyzeResult analyzeResult = analyzeDocumentPoller.getFinalResult();
// pages
analyzeResult.getPages().forEach(documentPage -> {
System.out.printf("Page has width: %.2f and height: %.2f, measured with unit: %s%n",
documentPage.getWidth(),
documentPage.getHeight(),
documentPage.getUnit());
// lines
documentPage.getLines().forEach(documentLine ->
System.out.printf("Line %s is within a bounding polygon %s.%n",
documentLine.getContent(),
documentLine.getBoundingPolygon().toString()));
// words
documentPage.getWords().forEach(documentWord ->
System.out.printf("Word %s has a confidence score of %.2f%n.",
documentWord.getContent(),
documentWord.getConfidence()));
});
// tables
List < DocumentTable > tab_les = analyzeResult.getTables();
for (int i = 0; i < tab_les.size(); i++) {
DocumentTable documentTable = tab_les.get(i);
System.out.printf("Table %d has %d rows and %d columns.%n", i, documentTable.getRowCount(),
documentTable.getColumnCount());
documentTable.getCells().forEach(documentTableCell -> {
System.out.printf("Cell '%s', has row index %d and column index %d.%n",
documentTableCell.getContent(),
documentTableCell.getRowIndex(), documentTableCell.getColumnIndex());
});
System.out.println();
}
// Key-value pairs
analyzeResult.getKeyValuePairs().forEach(documentKeyValuePair -> {
System.out.printf("Key content: %s%n", documentKeyValuePair.getKey().getContent());
System.out.printf("Key content bounding region: %s%n",
documentKeyValuePair.getKey().getBoundingRegions().toString());
if (documentKeyValuePair.getValue() != null) {
System.out.printf("Value content: %s%n", documentKeyValuePair.getValue().getContent());
System.out.printf("Value content bounding region: %s%n", documentKeyValuePair.getValue().getBoundingRegions().toString());
}
});
}
}
請瀏覽 GitHub 上的 Azure 範例存放庫,並檢視 一般檔案模型輸出。
使用 W-2 稅務模型
import com.azure.ai.formrecognizer.*;
import com.azure.ai.formrecognizer.documentanalysis.models.*;
import com.azure.ai.formrecognizer.documentanalysis.DocumentAnalysisClient;
import com.azure.ai.formrecognizer.documentanalysis.DocumentAnalysisClientBuilder;
import com.azure.core.credential.AzureKeyCredential;
import com.azure.core.util.polling.SyncPoller;
import java.io.IOException;
import java.util.List;
import java.util.Arrays;
import java.time.LocalDate;
import java.util.Map;
import java.util.stream.Collectors;
public class FormRecognizer {
//use your `key` and `endpoint` environment variables
private static final String key = System.getenv("FR_KEY");
private static final String endpoint = System.getenv("FR_ENDPOINT");
public static void main(final String[] args) {
// create your `DocumentAnalysisClient` instance and `AzureKeyCredential` variable
DocumentAnalysisClient client = new DocumentAnalysisClientBuilder()
.credential(new AzureKeyCredential(key))
.endpoint(endpoint)
.buildClient();
// sample document
String w2Url = "https://raw.githubusercontent.com/Azure-Samples/cognitive-services-REST-api-samples/master/curl/form-recognizer/rest-api/w2.png";
String modelId = "prebuilt-tax.us.w2";
SyncPoller < OperationResult, AnalyzeResult > analyzeW2Poller =
client.beginAnalyzeDocumentFromUrl(modelId, w2Url);
AnalyzeResult analyzeTaxResult = analyzeW2Poller.getFinalResult();
for (int i = 0; i < analyzeTaxResult.getDocuments().size(); i++) {
AnalyzedDocument analyzedTaxDocument = analyzeTaxResult.getDocuments().get(i);
Map < String, DocumentField > taxFields = analyzedTaxDocument.getFields();
System.out.printf("----------- Analyzing Document %d -----------%n", i);
DocumentField w2FormVariantField = taxFields.get("W2FormVariant");
if (w2FormVariantField != null) {
if (DocumentFieldType.STRING == w2FormVariantField.getType()) {
String merchantName = w2FormVariantField.getValueAsString();
System.out.printf("Form variant: %s, confidence: %.2f%n",
merchantName, w2FormVariantField.getConfidence());
}
}
DocumentField employeeField = taxFields.get("Employee");
if (employeeField != null) {
System.out.println("Employee Data: ");
if (DocumentFieldType.MAP == employeeField.getType()) {
Map < String, DocumentField > employeeDataFieldMap = employeeField.getValueAsMap();
DocumentField employeeName = employeeDataFieldMap.get("Name");
if (employeeName != null) {
if (DocumentFieldType.STRING == employeeName.getType()) {
String employeesName = employeeName.getValueAsString();
System.out.printf("Employee Name: %s, confidence: %.2f%n",
employeesName, employeeName.getConfidence());
}
}
DocumentField employeeAddrField = employeeDataFieldMap.get("Address");
if (employeeAddrField != null) {
if (DocumentFieldType.STRING == employeeAddrField.getType()) {
String employeeAddress = employeeAddrField.getValueAsString();
System.out.printf("Employee Address: %s, confidence: %.2f%n",
employeeAddress, employeeAddrField.getConfidence());
}
}
}
}
DocumentField employerField = taxFields.get("Employer");
if (employerField != null) {
System.out.println("Employer Data: ");
if (DocumentFieldType.MAP == employerField.getType()) {
Map < String, DocumentField > employerDataFieldMap = employerField.getValueAsMap();
DocumentField employerNameField = employerDataFieldMap.get("Name");
if (employerNameField != null) {
if (DocumentFieldType.STRING == employerNameField.getType()) {
String employerName = employerNameField.getValueAsString();
System.out.printf("Employer Name: %s, confidence: %.2f%n",
employerName, employerNameField.getConfidence());
}
}
DocumentField employerIDNumberField = employerDataFieldMap.get("IdNumber");
if (employerIDNumberField != null) {
if (DocumentFieldType.STRING == employerIDNumberField.getType()) {
String employerIdNumber = employerIDNumberField.getValueAsString();
System.out.printf("Employee ID Number: %s, confidence: %.2f%n",
employerIdNumber, employerIDNumberField.getConfidence());
}
}
}
}
DocumentField taxYearField = taxFields.get("TaxYear");
if (taxYearField != null) {
if (DocumentFieldType.STRING == taxYearField.getType()) {
String taxYear = taxYearField.getValueAsString();
System.out.printf("Tax year: %s, confidence: %.2f%n",
taxYear, taxYearField.getConfidence());
}
}
DocumentField taxDateField = taxFields.get("TaxDate");
if (taxDateField != null) {
if (DocumentFieldType.DATE == taxDateField.getType()) {
LocalDate taxDate = taxDateField.getValueAsDate();
System.out.printf("Tax Date: %s, confidence: %.2f%n",
taxDate, taxDateField.getConfidence());
}
}
DocumentField socialSecurityTaxField = taxFields.get("SocialSecurityTaxWithheld");
if (socialSecurityTaxField != null) {
if (DocumentFieldType.DOUBLE == socialSecurityTaxField.getType()) {
Double socialSecurityTax = socialSecurityTaxField.getValueAsDouble();
System.out.printf("Social Security Tax withheld: %.2f, confidence: %.2f%n",
socialSecurityTax, socialSecurityTaxField.getConfidence());
}
}
}
}
}
請瀏覽 GitHub 上的 Azure 範例存放庫,並檢視 W-2 稅務模型輸出。
使用發票模型
import com.azure.ai.formrecognizer.*;
import com.azure.ai.formrecognizer.documentanalysis.models.*;
import com.azure.ai.formrecognizer.documentanalysis.DocumentAnalysisClient;
import com.azure.ai.formrecognizer.documentanalysis.DocumentAnalysisClientBuilder;
import com.azure.core.credential.AzureKeyCredential;
import com.azure.core.util.polling.SyncPoller;
import java.io.IOException;
import java.util.List;
import java.util.Arrays;
import java.time.LocalDate;
import java.util.Map;
import java.util.stream.Collectors;
public class FormRecognizer {
//use your `key` and `endpoint` environment variables
private static final String key = System.getenv("FR_KEY");
private static final String endpoint = System.getenv("FR_ENDPOINT");
public static void main(final String[] args) {
// create your `DocumentAnalysisClient` instance and `AzureKeyCredential` variable
DocumentAnalysisClient client = new DocumentAnalysisClientBuilder()
.credential(new AzureKeyCredential(key))
.endpoint(endpoint)
.buildClient();
// sample document
String invoiceUrl = "https://github.com/Azure-Samples/cognitive-services-REST-api-samples/raw/master/curl/form-recognizer/rest-api/invoice.pdf";
String modelId = "prebuilt-invoice";
SyncPoller < OperationResult, AnalyzeResult > analyzeInvoicesPoller =
client.beginAnalyzeDocumentFromUrl(modelId, invoiceUrl);
AnalyzeResult analyzeInvoiceResult = analyzeInvoicesPoller.getFinalResult();
for (int i = 0; i < analyzeInvoiceResult.getDocuments().size(); i++) {
AnalyzedDocument analyzedInvoice = analyzeInvoiceResult.getDocuments().get(i);
Map < String, DocumentField > invoiceFields = analyzedInvoice.getFields();
System.out.printf("----------- Analyzing invoice %d -----------%n", i);
DocumentField vendorNameField = invoiceFields.get("VendorName");
if (vendorNameField != null) {
if (DocumentFieldType.STRING == vendorNameField.getType()) {
String merchantName = vendorNameField.getValueAsString();
System.out.printf("Vendor Name: %s, confidence: %.2f%n",
merchantName, vendorNameField.getConfidence());
}
}
DocumentField vendorAddressField = invoiceFields.get("VendorAddress");
if (vendorAddressField != null) {
if (DocumentFieldType.STRING == vendorAddressField.getType()) {
String merchantAddress = vendorAddressField.getValueAsString();
System.out.printf("Vendor address: %s, confidence: %.2f%n",
merchantAddress, vendorAddressField.getConfidence());
}
}
DocumentField customerNameField = invoiceFields.get("CustomerName");
if (customerNameField != null) {
if (DocumentFieldType.STRING == customerNameField.getType()) {
String merchantAddress = customerNameField.getValueAsString();
System.out.printf("Customer Name: %s, confidence: %.2f%n",
merchantAddress, customerNameField.getConfidence());
}
}
DocumentField customerAddressRecipientField = invoiceFields.get("CustomerAddressRecipient");
if (customerAddressRecipientField != null) {
if (DocumentFieldType.STRING == customerAddressRecipientField.getType()) {
String customerAddr = customerAddressRecipientField.getValueAsString();
System.out.printf("Customer Address Recipient: %s, confidence: %.2f%n",
customerAddr, customerAddressRecipientField.getConfidence());
}
}
DocumentField invoiceIdField = invoiceFields.get("InvoiceId");
if (invoiceIdField != null) {
if (DocumentFieldType.STRING == invoiceIdField.getType()) {
String invoiceId = invoiceIdField.getValueAsString();
System.out.printf("Invoice ID: %s, confidence: %.2f%n",
invoiceId, invoiceIdField.getConfidence());
}
}
DocumentField invoiceDateField = invoiceFields.get("InvoiceDate");
if (customerNameField != null) {
if (DocumentFieldType.DATE == invoiceDateField.getType()) {
LocalDate invoiceDate = invoiceDateField.getValueAsDate();
System.out.printf("Invoice Date: %s, confidence: %.2f%n",
invoiceDate, invoiceDateField.getConfidence());
}
}
DocumentField invoiceTotalField = invoiceFields.get("InvoiceTotal");
if (customerAddressRecipientField != null) {
if (DocumentFieldType.DOUBLE == invoiceTotalField.getType()) {
Double invoiceTotal = invoiceTotalField.getValueAsDouble();
System.out.printf("Invoice Total: %.2f, confidence: %.2f%n",
invoiceTotal, invoiceTotalField.getConfidence());
}
}
DocumentField invoiceItemsField = invoiceFields.get("Items");
if (invoiceItemsField != null) {
System.out.printf("Invoice Items: %n");
if (DocumentFieldType.LIST == invoiceItemsField.getType()) {
List < DocumentField > invoiceItems = invoiceItemsField.getValueAsList();
invoiceItems.stream()
.filter(invoiceItem -> DocumentFieldType.MAP == invoiceItem.getType())
.map(documentField -> documentField.getValueAsMap())
.forEach(documentFieldMap -> documentFieldMap.forEach((key, documentField) -> {
if ("Description".equals(key)) {
if (DocumentFieldType.STRING == documentField.getType()) {
String name = documentField.getValueAsString();
System.out.printf("Description: %s, confidence: %.2fs%n",
name, documentField.getConfidence());
}
}
if ("Quantity".equals(key)) {
if (DocumentFieldType.DOUBLE == documentField.getType()) {
Double quantity = documentField.getValueAsDouble();
System.out.printf("Quantity: %f, confidence: %.2f%n",
quantity, documentField.getConfidence());
}
}
if ("UnitPrice".equals(key)) {
if (DocumentFieldType.DOUBLE == documentField.getType()) {
Double unitPrice = documentField.getValueAsDouble();
System.out.printf("Unit Price: %f, confidence: %.2f%n",
unitPrice, documentField.getConfidence());
}
}
if ("ProductCode".equals(key)) {
if (DocumentFieldType.DOUBLE == documentField.getType()) {
Double productCode = documentField.getValueAsDouble();
System.out.printf("Product Code: %f, confidence: %.2f%n",
productCode, documentField.getConfidence());
}
}
}));
}
}
}
}
}
請瀏覽 GitHub 上的 Azure 範例存放庫,並檢視 發票模型輸出。
使用收據模型
import com.azure.ai.formrecognizer.*;
import com.azure.ai.formrecognizer.documentanalysis.models.*;
import com.azure.ai.formrecognizer.documentanalysis.DocumentAnalysisClient;
import com.azure.ai.formrecognizer.documentanalysis.DocumentAnalysisClientBuilder;
import com.azure.core.credential.AzureKeyCredential;
import com.azure.core.util.polling.SyncPoller;
import java.io.IOException;
import java.util.List;
import java.util.Arrays;
import java.time.LocalDate;
import java.util.Map;
import java.util.stream.Collectors;
public class FormRecognizer {
//use your `key` and `endpoint` environment variables
private static final String key = System.getenv("FR_KEY");
private static final String endpoint = System.getenv("FR_ENDPOINT");
public static void main(final String[] args) {
// create your `DocumentAnalysisClient` instance and `AzureKeyCredential` variable
DocumentAnalysisClient client = new DocumentAnalysisClientBuilder()
.credential(new AzureKeyCredential(key))
.endpoint(endpoint)
.buildClient();
String receiptUrl = "https://raw.githubusercontent.com/Azure-Samples/cognitive-services-REST-api-samples/master/curl/form-recognizer/rest-api/receipt.png";
String modelId = "prebuilt-receipt";
SyncPoller < OperationResult, AnalyzeResult > analyzeReceiptPoller =
client.beginAnalyzeDocumentFromUrl(modelId, receiptUrl);
AnalyzeResult receiptResults = analyzeReceiptPoller.getFinalResult();
for (int i = 0; i < receiptResults.getDocuments().size(); i++) {
AnalyzedDocument analyzedReceipt = receiptResults.getDocuments().get(i);
Map < String, DocumentField > receiptFields = analyzedReceipt.getFields();
System.out.printf("----------- Analyzing receipt info %d -----------%n", i);
DocumentField merchantNameField = receiptFields.get("MerchantName");
if (merchantNameField != null) {
if (DocumentFieldType.STRING == merchantNameField.getType()) {
String merchantName = merchantNameField.getValueAsString();
System.out.printf("Merchant Name: %s, confidence: %.2f%n",
merchantName, merchantNameField.getConfidence());
}
}
DocumentField merchantPhoneNumberField = receiptFields.get("MerchantPhoneNumber");
if (merchantPhoneNumberField != null) {
if (DocumentFieldType.PHONE_NUMBER == merchantPhoneNumberField.getType()) {
String merchantAddress = merchantPhoneNumberField.getValueAsPhoneNumber();
System.out.printf("Merchant Phone number: %s, confidence: %.2f%n",
merchantAddress, merchantPhoneNumberField.getConfidence());
}
}
DocumentField merchantAddressField = receiptFields.get("MerchantAddress");
if (merchantAddressField != null) {
if (DocumentFieldType.STRING == merchantAddressField.getType()) {
String merchantAddress = merchantAddressField.getValueAsString();
System.out.printf("Merchant Address: %s, confidence: %.2f%n",
merchantAddress, merchantAddressField.getConfidence());
}
}
DocumentField transactionDateField = receiptFields.get("TransactionDate");
if (transactionDateField != null) {
if (DocumentFieldType.DATE == transactionDateField.getType()) {
LocalDate transactionDate = transactionDateField.getValueAsDate();
System.out.printf("Transaction Date: %s, confidence: %.2f%n",
transactionDate, transactionDateField.getConfidence());
}
}
DocumentField receiptItemsField = receiptFields.get("Items");
if (receiptItemsField != null) {
System.out.printf("Receipt Items: %n");
if (DocumentFieldType.LIST == receiptItemsField.getType()) {
List < DocumentField > receiptItems = receiptItemsField.getValueAsList();
receiptItems.stream()
.filter(receiptItem -> DocumentFieldType.MAP == receiptItem.getType())
.map(documentField -> documentField.getValueAsMap())
.forEach(documentFieldMap -> documentFieldMap.forEach((key, documentField) -> {
if ("Name".equals(key)) {
if (DocumentFieldType.STRING == documentField.getType()) {
String name = documentField.getValueAsString();
System.out.printf("Name: %s, confidence: %.2fs%n",
name, documentField.getConfidence());
}
}
if ("Quantity".equals(key)) {
if (DocumentFieldType.DOUBLE == documentField.getType()) {
Double quantity = documentField.getValueAsDouble();
System.out.printf("Quantity: %f, confidence: %.2f%n",
quantity, documentField.getConfidence());
}
}
if ("Price".equals(key)) {
if (DocumentFieldType.DOUBLE == documentField.getType()) {
Double price = documentField.getValueAsDouble();
System.out.printf("Price: %f, confidence: %.2f%n",
price, documentField.getConfidence());
}
}
if ("TotalPrice".equals(key)) {
if (DocumentFieldType.DOUBLE == documentField.getType()) {
Double totalPrice = documentField.getValueAsDouble();
System.out.printf("Total Price: %f, confidence: %.2f%n",
totalPrice, documentField.getConfidence());
}
}
}));
}
}
}
}
}
請瀏覽 GitHub 上的 Azure 範例存放庫,並檢視 收據模型輸出。
使用身分證件模型
import com.azure.ai.formrecognizer.*;
import com.azure.ai.formrecognizer.documentanalysis.models.*;
import com.azure.ai.formrecognizer.documentanalysis.DocumentAnalysisClient;
import com.azure.ai.formrecognizer.documentanalysis.DocumentAnalysisClientBuilder;
import com.azure.core.credential.AzureKeyCredential;
import com.azure.core.util.polling.SyncPoller;
import java.io.IOException;
import java.util.List;
import java.util.Arrays;
import java.time.LocalDate;
import java.util.Map;
import java.util.stream.Collectors;
public class FormRecognizer {
//use your `key` and `endpoint` environment variables
private static final String key = System.getenv("FR_KEY");
private static final String endpoint = System.getenv("FR_ENDPOINT");
public static void main(final String[] args) {
// create your `DocumentAnalysisClient` instance and `AzureKeyCredential` variable
DocumentAnalysisClient client = new DocumentAnalysisClientBuilder()
.credential(new AzureKeyCredential(key))
.endpoint(endpoint)
.buildClient();
//sample document
String licenseUrl = "https://raw.githubusercontent.com/Azure-Samples/cognitive-services-REST-api-samples/master/curl/form-recognizer/rest-api/identity_documents.png";
String modelId = "prebuilt-idDocument";
SyncPoller < OperationResult, AnalyzeResult > analyzeIdentityDocumentPoller = client.beginAnalyzeDocumentFromUrl(modelId, licenseUrl);
AnalyzeResult identityDocumentResults = analyzeIdentityDocumentPoller.getFinalResult();
for (int i = 0; i < identityDocumentResults.getDocuments().size(); i++) {
AnalyzedDocument analyzedIDDocument = identityDocumentResults.getDocuments().get(i);
Map < String, DocumentField > licenseFields = analyzedIDDocument.getFields();
System.out.printf("----------- Analyzed license info for page %d -----------%n", i);
DocumentField addressField = licenseFields.get("Address");
if (addressField != null) {
if (DocumentFieldType.STRING == addressField.getType()) {
String address = addressField.getValueAsString();
System.out.printf("Address: %s, confidence: %.2f%n",
address, addressField.getConfidence());
}
}
DocumentField countryRegionDocumentField = licenseFields.get("CountryRegion");
if (countryRegionDocumentField != null) {
if (DocumentFieldType.STRING == countryRegionDocumentField.getType()) {
String countryRegion = countryRegionDocumentField.getValueAsCountry();
System.out.printf("Country or region: %s, confidence: %.2f%n",
countryRegion, countryRegionDocumentField.getConfidence());
}
}
DocumentField dateOfBirthField = licenseFields.get("DateOfBirth");
if (dateOfBirthField != null) {
if (DocumentFieldType.DATE == dateOfBirthField.getType()) {
LocalDate dateOfBirth = dateOfBirthField.getValueAsDate();
System.out.printf("Date of Birth: %s, confidence: %.2f%n",
dateOfBirth, dateOfBirthField.getConfidence());
}
}
DocumentField dateOfExpirationField = licenseFields.get("DateOfExpiration");
if (dateOfExpirationField != null) {
if (DocumentFieldType.DATE == dateOfExpirationField.getType()) {
LocalDate expirationDate = dateOfExpirationField.getValueAsDate();
System.out.printf("Document date of expiration: %s, confidence: %.2f%n",
expirationDate, dateOfExpirationField.getConfidence());
}
}
DocumentField documentNumberField = licenseFields.get("DocumentNumber");
if (documentNumberField != null) {
if (DocumentFieldType.STRING == documentNumberField.getType()) {
String documentNumber = documentNumberField.getValueAsString();
System.out.printf("Document number: %s, confidence: %.2f%n",
documentNumber, documentNumberField.getConfidence());
}
}
DocumentField firstNameField = licenseFields.get("FirstName");
if (firstNameField != null) {
if (DocumentFieldType.STRING == firstNameField.getType()) {
String firstName = firstNameField.getValueAsString();
System.out.printf("First Name: %s, confidence: %.2f%n",
firstName, documentNumberField.getConfidence());
}
}
DocumentField lastNameField = licenseFields.get("LastName");
if (lastNameField != null) {
if (DocumentFieldType.STRING == lastNameField.getType()) {
String lastName = lastNameField.getValueAsString();
System.out.printf("Last name: %s, confidence: %.2f%n",
lastName, lastNameField.getConfidence());
}
}
DocumentField regionField = licenseFields.get("Region");
if (regionField != null) {
if (DocumentFieldType.STRING == regionField.getType()) {
String region = regionField.getValueAsString();
System.out.printf("Region: %s, confidence: %.2f%n",
region, regionField.getConfidence());
}
}
}
}
}
請瀏覽 GitHub 上的 Azure 範例存放庫,並檢視 識別碼檔案模型輸出。
使用名片模型
import com.azure.ai.formrecognizer.*;
import com.azure.ai.formrecognizer.documentanalysis.models.*;
import com.azure.ai.formrecognizer.documentanalysis.DocumentAnalysisClient;
import com.azure.ai.formrecognizer.documentanalysis.DocumentAnalysisClientBuilder;
import com.azure.core.credential.AzureKeyCredential;
import com.azure.core.util.polling.SyncPoller;
import java.io.IOException;
import java.util.List;
import java.util.Arrays;
import java.time.LocalDate;
import java.util.Map;
import java.util.stream.Collectors;
public class FormRecognizer {
//use your `key` and `endpoint` environment variables
private static final String key = System.getenv("FR_KEY");
private static final String endpoint = System.getenv("FR_ENDPOINT");
public static void main(final String[] args) {
// create your `DocumentAnalysisClient` instance and `AzureKeyCredential` variable
DocumentAnalysisClient client = new DocumentAnalysisClientBuilder()
.credential(new AzureKeyCredential(key))
.endpoint(endpoint)
.buildClient();
//sample document
String businessCardUrl = "https://raw.githubusercontent.com/Azure-Samples/cognitive-services-REST-api-samples/de5e0d8982ab754823c54de47a47e8e499351523/curl/form-recognizer/rest-api/business_card.jpg";
String modelId = "prebuilt-businessCard";
SyncPoller < OperationResult, AnalyzeResult > analyzeBusinessCardPoller = client.beginAnalyzeDocumentFromUrl(modelId, businessCardUrl);
AnalyzeResult businessCardPageResults = analyzeBusinessCardPoller.getFinalResult();
for (int i = 0; i < businessCardPageResults.getDocuments().size(); i++) {
System.out.printf("--------Analyzing business card %d -----------%n", i);
AnalyzedDocument analyzedBusinessCard = businessCardPageResults.getDocuments().get(i);
Map < String, DocumentField > businessCardFields = analyzedBusinessCard.getFields();
DocumentField contactNamesDocumentField = businessCardFields.get("ContactNames");
if (contactNamesDocumentField != null) {
if (DocumentFieldType.LIST == contactNamesDocumentField.getType()) {
List < DocumentField > contactNamesList = contactNamesDocumentField.getValueAsList();
contactNamesList.stream()
.filter(contactName -> DocumentFieldType.MAP == contactName.getType())
.map(contactName -> {
System.out.printf("Contact name: %s%n", contactName.getContent());
return contactName.getValueAsMap();
})
.forEach(contactNamesMap -> contactNamesMap.forEach((key, contactName) -> {
if ("FirstName".equals(key)) {
if (DocumentFieldType.STRING == contactName.getType()) {
String firstName = contactName.getValueAsString();
System.out.printf("\tFirst Name: %s, confidence: %.2f%n",
firstName, contactName.getConfidence());
}
}
if ("LastName".equals(key)) {
if (DocumentFieldType.STRING == contactName.getType()) {
String lastName = contactName.getValueAsString();
System.out.printf("\tLast Name: %s, confidence: %.2f%n",
lastName, contactName.getConfidence());
}
}
}));
}
}
DocumentField jobTitles = businessCardFields.get("JobTitles");
if (jobTitles != null) {
if (DocumentFieldType.LIST == jobTitles.getType()) {
List < DocumentField > jobTitlesItems = jobTitles.getValueAsList();
jobTitlesItems.forEach(jobTitlesItem -> {
if (DocumentFieldType.STRING == jobTitlesItem.getType()) {
String jobTitle = jobTitlesItem.getValueAsString();
System.out.printf("Job Title: %s, confidence: %.2f%n",
jobTitle, jobTitlesItem.getConfidence());
}
});
}
}
DocumentField departments = businessCardFields.get("Departments");
if (departments != null) {
if (DocumentFieldType.LIST == departments.getType()) {
List < DocumentField > departmentsItems = departments.getValueAsList();
departmentsItems.forEach(departmentsItem -> {
if (DocumentFieldType.STRING == departmentsItem.getType()) {
String department = departmentsItem.getValueAsString();
System.out.printf("Department: %s, confidence: %.2f%n",
department, departmentsItem.getConfidence());
}
});
}
}
DocumentField emails = businessCardFields.get("Emails");
if (emails != null) {
if (DocumentFieldType.LIST == emails.getType()) {
List < DocumentField > emailsItems = emails.getValueAsList();
emailsItems.forEach(emailsItem -> {
if (DocumentFieldType.STRING == emailsItem.getType()) {
String email = emailsItem.getValueAsString();
System.out.printf("Email: %s, confidence: %.2f%n", email, emailsItem.getConfidence());
}
});
}
}
DocumentField websites = businessCardFields.get("Websites");
if (websites != null) {
if (DocumentFieldType.LIST == websites.getType()) {
List < DocumentField > websitesItems = websites.getValueAsList();
websitesItems.forEach(websitesItem -> {
if (DocumentFieldType.STRING == websitesItem.getType()) {
String website = websitesItem.getValueAsString();
System.out.printf("Web site: %s, confidence: %.2f%n",
website, websitesItem.getConfidence());
}
});
}
}
DocumentField mobilePhones = businessCardFields.get("MobilePhones");
if (mobilePhones != null) {
if (DocumentFieldType.LIST == mobilePhones.getType()) {
List < DocumentField > mobilePhonesItems = mobilePhones.getValueAsList();
mobilePhonesItems.forEach(mobilePhonesItem -> {
if (DocumentFieldType.PHONE_NUMBER == mobilePhonesItem.getType()) {
String mobilePhoneNumber = mobilePhonesItem.getValueAsPhoneNumber();
System.out.printf("Mobile phone number: %s, confidence: %.2f%n",
mobilePhoneNumber, mobilePhonesItem.getConfidence());
}
});
}
}
DocumentField otherPhones = businessCardFields.get("OtherPhones");
if (otherPhones != null) {
if (DocumentFieldType.LIST == otherPhones.getType()) {
List < DocumentField > otherPhonesItems = otherPhones.getValueAsList();
otherPhonesItems.forEach(otherPhonesItem -> {
if (DocumentFieldType.PHONE_NUMBER == otherPhonesItem.getType()) {
String otherPhoneNumber = otherPhonesItem.getValueAsPhoneNumber();
System.out.printf("Other phone number: %s, confidence: %.2f%n",
otherPhoneNumber, otherPhonesItem.getConfidence());
}
});
}
}
DocumentField faxes = businessCardFields.get("Faxes");
if (faxes != null) {
if (DocumentFieldType.LIST == faxes.getType()) {
List < DocumentField > faxesItems = faxes.getValueAsList();
faxesItems.forEach(faxesItem -> {
if (DocumentFieldType.PHONE_NUMBER == faxesItem.getType()) {
String faxPhoneNumber = faxesItem.getValueAsPhoneNumber();
System.out.printf("Fax phone number: %s, confidence: %.2f%n",
faxPhoneNumber, faxesItem.getConfidence());
}
});
}
}
DocumentField addresses = businessCardFields.get("Addresses");
if (addresses != null) {
if (DocumentFieldType.LIST == addresses.getType()) {
List < DocumentField > addressesItems = addresses.getValueAsList();
addressesItems.forEach(addressesItem -> {
if (DocumentFieldType.STRING == addressesItem.getType()) {
String address = addressesItem.getValueAsString();
System.out
.printf("Address: %s, confidence: %.2f%n", address, addressesItem.getConfidence());
}
});
}
}
DocumentField companyName = businessCardFields.get("CompanyNames");
if (companyName != null) {
if (DocumentFieldType.LIST == companyName.getType()) {
List < DocumentField > companyNameItems = companyName.getValueAsList();
companyNameItems.forEach(companyNameItem -> {
if (DocumentFieldType.STRING == companyNameItem.getType()) {
String companyNameValue = companyNameItem.getValueAsString();
System.out.printf("Company name: %s, confidence: %.2f%n", companyNameValue,
companyNameItem.getConfidence());
}
});
}
}
}
}
}
請瀏覽 GitHub 上的 Azure 範例存放庫,並檢視 名片模型輸出。
用戶端程式庫 | REST API 參考 | 套件 (npm) | 範例 |支援的 REST API 版本
先決條件
Azure 訂用帳戶 - 免費建立一個訂用帳戶。
最新的 Visual Studio Code 版本或您慣用的 IDE。 如需詳細資訊,請參閱 Visual Studio Code 中的Node.js。
Azure AI 服務或文件智慧服務資源。 建立 單一服務 或 多服務。 您可以使用免費定價層 (
F0
) 來試用服務,之後可升級至付費層以用於實際執行環境。小提示
如果您打算使用單一端點和密鑰來存取多個 Azure AI 服務,請建立 Azure AI 服務資源。 針對僅限文件智慧服務存取,請建立文件智慧服務資源。 如果您想要使用 Microsoft Entra 驗證,則需要使用單一服務資源。
從您所建立資源的金鑰和端點,將應用程式連線至 Azure 文件智慧服務。
- 部署資源之後,請選取 [前往資源]。
- 在左側導覽功能表中,選取 [金鑰和端點]。
- 複製其中一個金鑰和 端點,以供本文稍後使用。
URL 的文件檔案。 針對此專案,您可以使用下表中針對每項功能的範例表單:
特徵 / 功能 modelID document-url Read 模型 prebuilt-read 範例手冊 版面配置模型 預設佈局 範例預約確認 W-2 表單模型 prebuilt-tax.us.w2 範例 W-2 表單 發票模型 prebuilt-invoice 範例發票 收據模型 prebuilt-receipt 範例收據 識別碼文件模型 prebuilt-idDocument 範例身份文件
設定環境變數
若要與此文件智慧服務互動,您必須建立 DocumentAnalysisClient
類別的執行個體。 若要這樣做,請使用 Azure 入口網站中的 key
和 endpoint
具現化用戶端。 針對此專案,請使用環境變數來儲存和存取認證。
這很重要
請謹慎使用 API 金鑰。 請勿在程式碼中直接包含 API 金鑰,且切勿公開張貼金鑰。 如果您使用 API 金鑰,請安全地將其儲存在 Azure 金鑰保存庫。 如需在應用程式中安全地使用 API 金鑰的詳細資訊,請參閱搭配 Azure 金鑰保存庫 的 API 金鑰。
如需 AI 服務安全性的詳細資訊,請參閱驗證對 Azure AI 服務的要求。
若要設定 Document Intelligence 資源金鑰的環境變數,請開啟主控台視窗,並遵循作系統和開發環境的指示。 將 <yourKey> 和 <yourEndpoint> 取代為 Azure 入口網站中資源的值。
Windows 中的環境變數不會區分大小寫。 它們通常會以大寫方式宣告,單字之間以底線連結。 在命令提示字元中,執行下列命令:
設定您的金鑰變數:
setx DI_KEY <yourKey>
設定您的端點變數
setx DI_ENDPOINT <yourEndpoint>
設定環境變數之後,請關閉 [命令提示字元] 視窗。 值會維持不變,直到您再次變更這些值為止。
重新啟動讀取環境變數的任何執行中程式。 例如,如果您使用 Visual Studio 或 Visual Studio Code 作為編輯器,請在執行範例程式代碼之前重新啟動。
以下是搭配環境變數使用的一些更實用的命令:
命令 | 動作 | 範例 |
---|---|---|
setx VARIABLE_NAME= |
將值設定為空字串,以刪除環境變數。 | setx DI_KEY= |
setx VARIABLE_NAME=value |
設定或變更環境變數的值。 | setx DI_KEY=<yourKey> |
set VARIABLE_NAME |
顯示特定環境變數的值。 | set DI_KEY |
set |
顯示所有環境變數。 | set |
設定程式設計環境
建立 Node.js Express 應用程式。
在主控台視窗中,為名為
doc-intel-app
的應用程式建立並流覽至新的目錄。mkdir doc-intel-app cd doc-intel-app
執行
npm init
命令來初始化應用程式,並建構您的專案。npm init
使用終端機中顯示的提示來指定專案的屬性。
- 名稱、版本號碼和進入點是最重要的屬性。
- 我們建議您將進入點的名稱保留為
index.js
。 描述、測試命令、GitHub 存放庫、關鍵詞、作者和授權資訊都是選擇性屬性。 在此專案中可以跳過它們。 - 選取 [輸入 以接受括弧中的建議。
完成提示之後,命令會在
package.json
目錄中建立 檔案。安裝
ai-document-intelligence
用戶端程式庫和azure/identity
npm 套件:npm i @azure-rest/ai-document-intelligence@1.0.0 @azure/identity
您應用程式的 package.json 檔案會隨著相依項目更新。
在應用程式目錄中建立名為 index.js 的檔案。
小提示
您可以使用 PowerShell 建立新的檔案。 按住 Shift 鍵,並在資料夾上按下滑鼠右鍵,然後輸入下列命令,以開啟項目目錄中的 PowerShell 視窗:New-Item index.js。
建置您的 應用程式
若要與此文件智慧服務互動,您必須建立 DocumentIntelligenceClient
類別的執行個體。 若要這樣做,您需要從 Azure 入口網站取得您的密鑰來建立 AzureKeyCredential
,並且使用 DocumentIntelligenceClient
和 Document Intelligence 端點建立 AzureKeyCredential
實例。
在 Visual Studio Code 或您慣用的 IDE 中開啟 index.js
檔案,然後選取下列其中一個程式代碼範例,然後將/貼到您的應用程式:
- 預建的讀取 模型是所有文檔智能模型的核心,並且可以偵測行、文字、位置和語言。 版面配置、一般檔、預先建置和自定義模型全都使用
read
模型作為從檔擷取文字的基礎。 - prebuilt-layout 模型會從文件和影像中擷取文字和文字位置、表格、選取標記和結構資訊。
- prebuilt-tax.us.w2 模型會擷取美國國稅局 (IRS) 稅務表單上所報告的資訊。
- 預建發票 模型會擷取美國國稅服務稅單上報告的資訊。
- 預建收據 模型會從印刷和手寫的銷售收據中擷取重要資訊。
- 預建的 idDocument 模型會從美國駕駛執照、國際護照傳記頁面、美國州身份證、社會保障卡和永久居民卡中擷取重要資訊。
使用 Read 模型
const { DocumentIntelligenceClient } = require("@azure-rest/ai-document-intelligence");
const { AzureKeyCredential } = require("@azure/core-auth");
//use your `key` and `endpoint` environment variables
const key = process.env['DI_KEY'];
const endpoint = process.env['DI_ENDPOINT'];
// sample document
const documentUrlRead = "https://raw.githubusercontent.com/Azure-Samples/cognitive-services-REST-api-samples/master/curl/form-recognizer/rest-api/read.png"
// helper function
function* getTextOfSpans(content, spans) {
for (const span of spans) {
yield content.slice(span.offset, span.offset + span.length);
}
}
async function main() {
// create your `DocumentIntelligenceClient` instance and `AzureKeyCredential` variable
const client = DocumentIntelligence(endpoint, new AzureKeyCredential(key));
const poller = await client.beginAnalyzeDocument("prebuilt-read", documentUrlRead);
const {
content,
pages,
languages,
styles
} = await poller.pollUntilDone();
if (pages.length <= 0) {
console.log("No pages were extracted from the document.");
} else {
console.log("Pages:");
for (const page of pages) {
console.log("- Page", page.pageNumber, `(unit: ${page.unit})`);
console.log(` ${page.width}x${page.height}, angle: ${page.angle}`);
console.log(` ${page.lines.length} lines, ${page.words.length} words`);
if (page.lines.length > 0) {
console.log(" Lines:");
for (const line of page.lines) {
console.log(` - "${line.content}"`);
// The words of the line can also be iterated independently. The words are computed based on their
// corresponding spans.
for (const word of line.words()) {
console.log(` - "${word.content}"`);
}
}
}
}
}
if (languages.length <= 0) {
console.log("No language spans were extracted from the document.");
} else {
console.log("Languages:");
for (const languageEntry of languages) {
console.log(
`- Found language: ${languageEntry.languageCode} (confidence: ${languageEntry.confidence})`
);
for (const text of getTextOfSpans(content, languageEntry.spans)) {
const escapedText = text.replace(/\r?\n/g, "\\n").replace(/"/g, '\\"');
console.log(` - "${escapedText}"`);
}
}
}
if (styles.length <= 0) {
console.log("No text styles were extracted from the document.");
} else {
console.log("Styles:");
for (const style of styles) {
console.log(
`- Handwritten: ${style.isHandwritten ? "yes" : "no"} (confidence=${style.confidence})`
);
for (const word of getTextOfSpans(content, style.spans)) {
console.log(` - "${word}"`);
}
}
}
}
main().catch((error) => {
console.error("An error occurred:", error);
process.exit(1);
});
請瀏覽 GitHub 上的 Azure 範例存放庫,並檢視 read
模型輸出。
使用 Layout 模型
const { DocumentIntelligenceClient } = require("@azure-rest/ai-document-intelligence");
const { AzureKeyCredential } = require("@azure/core-auth");
//use your `key` and `endpoint` environment variables
const key = process.env['DI_KEY'];
const endpoint = process.env['DI_ENDPOINT'];
// sample document
const layoutUrl = "https://raw.githubusercontent.com/Azure-Samples/cognitive-services-REST-api-samples/master/curl/form-recognizer/rest-api/layout.png"
async function main() {
const client = DocumentIntelligence(endpoint, new AzureKeyCredential(key));
const poller = await client.beginAnalyzeDocument(
"prebuilt-layout", layoutUrl);
// Layout extraction produces basic elements such as pages, words, lines, etc. as well as information about the
// appearance (styles) of textual elements.
const { pages, tables } = await poller.pollUntilDone();
if (!pages || pages.length <= 0) {
console.log("No pages were extracted from the document.");
} else {
console.log("Pages:");
for (const page of pages) {
console.log("- Page", page.pageNumber, `(unit: ${page.unit})`);
console.log(` ${page.width}x${page.height}, angle: ${page.angle}`);
console.log(
` ${page.lines && page.lines.length} lines, ${page.words && page.words.length} words`
);
if (page.lines && page.lines.length > 0) {
console.log(" Lines:");
for (const line of page.lines) {
console.log(` - "${line.content}"`);
// The words of the line can also be iterated independently. The words are computed based on their
// corresponding spans.
for (const word of line.words()) {
console.log(` - "${word.content}"`);
}
}
}
}
}
if (!tables || tables.length <= 0) {
console.log("No tables were extracted from the document.");
} else {
console.log("Tables:");
for (const table of tables) {
console.log(
`- Extracted table: ${table.columnCount} columns, ${table.rowCount} rows (${table.cells.length} cells)`
);
}
}
}
main().catch((error) => {
console.error("An error occurred:", error);
process.exit(1);
});
請瀏覽 GitHub 上的 Azure 範例存放庫,並檢視 版面配置模型輸出。
使用通用文件模型
const { DocumentIntelligenceClient } = require("@azure-rest/ai-document-intelligence");
const { AzureKeyCredential } = require("@azure/core-auth");
//use your `key` and `endpoint` environment variables
const key = process.env['DI_KEY'];
const endpoint = process.env['DI_ENDPOINT'];
// sample document
const documentUrl = "https://raw.githubusercontent.com/Azure-Samples/cognitive-services-REST-api-samples/master/curl/form-recognizer/sample-layout.pdf"
async function main() {
const client = DocumentIntelligence(endpoint, new AzureKeyCredential(key));
const poller = await client.beginAnalyzeDocument("prebuilt-document", documentUrl);
const {
keyValuePairs
} = await poller.pollUntilDone();
if (!keyValuePairs || keyValuePairs.length <= 0) {
console.log("No key-value pairs were extracted from the document.");
} else {
console.log("Key-Value Pairs:");
for (const {
key,
value,
confidence
} of keyValuePairs) {
console.log("- Key :", `"${key.content}"`);
console.log(" Value:", `"${(value && value.content) || "<undefined>"}" (${confidence})`);
}
}
}
main().catch((error) => {
console.error("An error occurred:", error);
process.exit(1);
});
請瀏覽 GitHub 上的 Azure 範例存放庫,並檢視 一般檔案模型輸出。
使用 W-2 稅務模型
const { DocumentIntelligenceClient } = require("@azure-rest/ai-document-intelligence");
const { AzureKeyCredential } = require("@azure/core-auth");
//use your `key` and `endpoint` environment variables
const key = process.env['DI_KEY'];
const endpoint = process.env['DI_ENDPOINT'];
const w2DocumentURL = "https://raw.githubusercontent.com/Azure-Samples/cognitive-services-REST-api-samples/master/curl/form-recognizer/rest-api/w2.png"
async function main() {
const client = DocumentIntelligence(endpoint, new AzureKeyCredential(key));
const poller = await client.beginAnalyzeDocument("prebuilt-tax.us.w2", w2DocumentURL);
const {
documents: [result]
} = await poller.pollUntilDone();
if (result) {
const { Employee, Employer, ControlNumber, TaxYear, AdditionalInfo } = result.fields;
if (Employee) {
const { Name, Address, SocialSecurityNumber } = Employee.properties;
console.log("Employee:");
console.log(" Name:", Name && Name.content);
console.log(" SSN/TIN:", SocialSecurityNumber && SocialSecurityNumber.content);
if (Address && Address.value) {
const { streetAddress, postalCode } = Address.value;
console.log(" Address:");
console.log(" Street Address:", streetAddress);
console.log(" Postal Code:", postalCode);
}
} else {
console.log("No employee information extracted.");
}
if (Employer) {
const { Name, Address, IdNumber } = Employer.properties;
console.log("Employer:");
console.log(" Name:", Name && Name.content);
console.log(" ID (EIN):", IdNumber && IdNumber.content);
if (Address && Address.value) {
const { streetAddress, postalCode } = Address.value;
console.log(" Address:");
console.log(" Street Address:", streetAddress);
console.log(" Postal Code:", postalCode);
}
} else {
console.log("No employer information extracted.");
}
console.log("Control Number:", ControlNumber && ControlNumber.content);
console.log("Tax Year:", TaxYear && TaxYear.content);
if (AdditionalInfo) {
console.log("Additional Info:");
for (const info of AdditionalInfo.values) {
const { LetterCode, Amount } = info.properties;
console.log(`- ${LetterCode && LetterCode.content}: ${Amount && Amount.content}`);
}
}
} else {
throw new Error("Expected at least one document in the result.");
}
}
main().catch((error) => {
console.error(error);
process.exit(1);
});
請瀏覽 GitHub 上的 Azure 範例存放庫,並檢視 W-2 稅務模型輸出。
使用發票模型
const { DocumentIntelligenceClient } = require("@azure-rest/ai-document-intelligence");
const { AzureKeyCredential } = require("@azure/core-auth");
//use your `key` and `endpoint` environment variables
const key = process.env['DI_KEY'];
const endpoint = process.env['DI_ENDPOINT'];
// sample url
const invoiceUrl = "https://github.com/Azure-Samples/cognitive-services-REST-api-samples/raw/master/curl/form-recognizer/rest-api/invoice.pdf";
async function main() {
const client = DocumentIntelligence(endpoint, new AzureKeyCredential(key));
const poller = await client.beginAnalyzeDocument("prebuilt-invoice", invoiceUrl);
const {
documents: [result]
} = await poller.pollUntilDone();
if (result) {
const invoice = result.fields;
console.log("Vendor Name:", invoice.VendorName?.content);
console.log("Customer Name:", invoice.CustomerName?.content);
console.log("Invoice Date:", invoice.InvoiceDate?.content);
console.log("Due Date:", invoice.DueDate?.content);
console.log("Items:");
for (const {
properties: item
} of invoice.Items?.values ?? []) {
console.log("-", item.ProductCode?.content ?? "<no product code>");
console.log(" Description:", item.Description?.content);
console.log(" Quantity:", item.Quantity?.content);
console.log(" Date:", item.Date?.content);
console.log(" Unit:", item.Unit?.content);
console.log(" Unit Price:", item.UnitPrice?.content);
console.log(" Tax:", item.Tax?.content);
console.log(" Amount:", item.Amount?.content);
}
console.log("Subtotal:", invoice.SubTotal?.content);
console.log("Previous Unpaid Balance:", invoice.PreviousUnpaidBalance?.content);
console.log("Tax:", invoice.TotalTax?.content);
console.log("Amount Due:", invoice.AmountDue?.content);
} else {
throw new Error("Expected at least one receipt in the result.");
}
}
main().catch((error) => {
console.error("An error occurred:", error);
process.exit(1);
});
請瀏覽 GitHub 上的 Azure 範例存放庫,並檢視 發票模型輸出。
使用收據模型
const { DocumentIntelligenceClient } = require("@azure-rest/ai-document-intelligence");
const { AzureKeyCredential } = require("@azure/core-auth");
//use your `key` and `endpoint` environment variables
const key = process.env['DI_KEY'];
const endpoint = process.env['DI_ENDPOINT'];
// sample url
const receiptUrl = "https://raw.githubusercontent.com/Azure-Samples/cognitive-services-REST-api-samples/master/curl/form-recognizer/rest-api/receipt.png";
async function main() {
const client = DocumentIntelligence(endpoint, new AzureKeyCredential(key));
const poller = await client.beginAnalyzeDocument("prebuilt-receipt", receiptUrl);
const {
documents: [result]
} = await poller.pollUntilDone();
if (result) {
const {
MerchantName,
Items,
Total
} = result.fields;
console.log("=== Receipt Information ===");
console.log("Type:", result.docType);
console.log("Merchant:", MerchantName && MerchantName.content);
console.log("Items:");
for (const item of (Items && Items.values) || []) {
const {
Description,
TotalPrice
} = item.properties;
console.log("- Description:", Description && Description.content);
console.log(" Total Price:", TotalPrice && TotalPrice.content);
}
console.log("Total:", Total && Total.content);
} else {
throw new Error("Expected at least one receipt in the result.");
}
}
main().catch((err) => {
console.error("The sample encountered an error:", err);
});
請瀏覽 GitHub 上的 Azure 範例存放庫,並檢視 收據模型輸出。
使用身分證件模型
const { DocumentIntelligenceClient } = require("@azure-rest/ai-document-intelligence");
const { AzureKeyCredential } = require("@azure/core-auth");
//use your `key` and `endpoint` environment variables
const key = process.env['DI_KEY'];
const endpoint = process.env['DI_ENDPOINT'];
// sample document
const idDocumentURL = "https://raw.githubusercontent.com/Azure-Samples/cognitive-services-REST-api-samples/master/curl/form-recognizer/rest-api/identity_documents.png"
async function main() {
const client = DocumentIntelligence(endpoint, new AzureKeyCredential(key));
const poller = await client.beginAnalyzeDocument("prebuilt-idDocument", idDocumentURL);
const {
documents: [result]
} = await poller.pollUntilDone();
if (result) {
// The identity document model has multiple document types, so we need to know which document type was actually
extracted.
if (result.docType === "idDocument.driverLicense") {
const { FirstName, LastName, DocumentNumber, DateOfBirth, DateOfExpiration, Height, Weight, EyeColor, Endorsements, Restrictions, VehicleClassifications} = result.fields;
// For the sake of the example, we'll only show a few of the fields that are produced.
console.log("Extracted a Driver License:");
console.log(" Name:", FirstName && FirstName.content, LastName && LastName.content);
console.log(" License No.:", DocumentNumber && DocumentNumber.content);
console.log(" Date of Birth:", DateOfBirth && DateOfBirth.content);
console.log(" Expiration:", DateOfExpiration && DateOfExpiration.content);
console.log(" Height:", Height && Height.content);
console.log(" Weight:", Weight && Weight.content);
console.log(" Eye color:", EyeColor && EyeColor.content);
console.log(" Restrictions:", Restrictions && Restrictions.content);
console.log(" Endorsements:", Endorsements && Endorsements.content);
console.log(" Class:", VehicleClassifications && VehicleClassifications.content);
} else if (result.docType === "idDocument.passport") {
// The passport document type extracts and parses the Passport's machine-readable zone
if (!result.fields.machineReadableZone) {
throw new Error("No Machine Readable Zone extracted from passport.");
}
const {
FirstName,
LastName,
DateOfBirth,
Nationality,
DocumentNumber,
CountryRegion,
DateOfExpiration,
} = result.fields.machineReadableZone.properties;
console.log("Extracted a Passport:");
console.log(" Name:", FirstName && FirstName.content, LastName && LastName.content);
console.log(" Date of Birth:", DateOfBirth && DateOfBirth.content);
console.log(" Nationality:", Nationality && Nationality.content);
console.log(" Passport No.:", DocumentNumber && DocumentNumber.content);
console.log(" Issuer:", CountryRegion && CountryRegion.content);
console.log(" Expiration Date:", DateOfExpiration && DateOfExpiration.content);
} else {
// The only reason this would happen is if the client library's schema for the prebuilt identity document model is
out of date, and a new document type has been introduced.
console.error("Unknown document type in result:", result);
}
} else {
throw new Error("Expected at least one receipt in the result.");
}
}
main().catch((error) => {
console.error("An error occurred:", error);
process.exit(1);
});
請瀏覽 GitHub 上的 Azure 範例存放庫,並檢視 識別碼檔案模型輸出。
用戶端連結庫 | REST API 參考 | 套件 (npm) | 範例 |支援的 REST API 版本
用戶端連結庫 | REST API 參考 | 套件 (npm) | 範例 |支援的 REST API 版本
先決條件
Azure 訂用帳戶 - 免費建立一個訂用帳戶。
最新的 Visual Studio Code 版本或您慣用的 IDE。 如需詳細資訊,請參閱 Visual Studio Code 中的Node.js。
Azure AI 服務或文件智慧服務資源。 建立 單一服務 或 多服務。 您可以使用免費定價層 (
F0
) 來試用服務,之後可升級至付費層以用於實際執行環境。小提示
如果您打算使用單一端點和密鑰來存取多個 Azure AI 服務,請建立 Azure AI 服務資源。 針對僅限文件智慧服務存取,請建立文件智慧服務資源。 如果您想要使用 Microsoft Entra 驗證,則需要使用單一服務資源。
從您所建立資源的金鑰和端點,將應用程式連線至 Azure 文件智慧服務。
- 部署資源之後,請選取 [前往資源]。
- 在左側導覽功能表中,選取 [金鑰和端點]。
- 複製其中一個金鑰和 端點,以供本文稍後使用。
URL 的文件檔案。 針對此專案,您可以使用下表中針對每項功能的範例表單:
特徵 / 功能 modelID document-url Read 模型 prebuilt-read 範例手冊 版面配置模型 預設佈局 範例預約確認 W-2 表單模型 prebuilt-tax.us.w2 範例 W-2 表單 發票模型 prebuilt-invoice 範例發票 收據模型 prebuilt-receipt 範例收據 識別碼文件模型 prebuilt-idDocument 範例身份文件 名片模型 prebuilt-businessCard 範例名片
設定環境變數
若要與此文件智慧服務互動,您必須建立 DocumentAnalysisClient
類別的執行個體。 若要這樣做,請使用 Azure 入口網站中的 key
和 endpoint
具現化用戶端。 針對此專案,請使用環境變數來儲存和存取認證。
這很重要
請謹慎使用 API 金鑰。 請勿在程式碼中直接包含 API 金鑰,且切勿公開張貼金鑰。 如果您使用 API 金鑰,請安全地將其儲存在 Azure 金鑰保存庫。 如需在應用程式中安全地使用 API 金鑰的詳細資訊,請參閱搭配 Azure 金鑰保存庫 的 API 金鑰。
如需 AI 服務安全性的詳細資訊,請參閱驗證對 Azure AI 服務的要求。
若要設定 Document Intelligence 資源金鑰的環境變數,請開啟主控台視窗,並遵循作系統和開發環境的指示。 將 <yourKey> 和 <yourEndpoint> 取代為 Azure 入口網站中資源的值。
Windows 中的環境變數不會區分大小寫。 它們通常會以大寫方式宣告,單字之間以底線連結。 在命令提示字元中,執行下列命令:
設定您的金鑰變數:
setx DI_KEY <yourKey>
設定您的端點變數
setx DI_ENDPOINT <yourEndpoint>
設定環境變數之後,請關閉 [命令提示字元] 視窗。 值會維持不變,直到您再次變更這些值為止。
重新啟動讀取環境變數的任何執行中程式。 例如,如果您使用 Visual Studio 或 Visual Studio Code 作為編輯器,請在執行範例程式代碼之前重新啟動。
以下是搭配環境變數使用的一些更實用的命令:
命令 | 動作 | 範例 |
---|---|---|
setx VARIABLE_NAME= |
將值設定為空字串,以刪除環境變數。 | setx DI_KEY= |
setx VARIABLE_NAME=value |
設定或變更環境變數的值。 | setx DI_KEY=<yourKey> |
set VARIABLE_NAME |
顯示特定環境變數的值。 | set DI_KEY |
set |
顯示所有環境變數。 | set |
設定程式設計環境
建立 Node.js Express 應用程式。
在主控台視窗中,為名為
form-recognizer-app
的應用程式建立並流覽至新的目錄。mkdir form-recognizer-app cd form-recognizer-app
執行
npm init
命令來初始化應用程式,並建構您的專案。npm init
使用終端機中顯示的提示來指定專案的屬性。
- 名稱、版本號碼和進入點是最重要的屬性。
- 我們建議您將進入點的名稱保留為
index.js
。 描述、測試命令、GitHub 存放庫、關鍵詞、作者和授權資訊都是選擇性屬性。 在此專案中可以跳過它們。 - 選取 [輸入 以接受括弧中的建議。
完成提示之後,命令會在
package.json
目錄中建立 檔案。安裝
ai-form-recognizer
用戶端程式庫和azure/identity
npm 套件:npm i @azure/ai-form-recognizer @azure/identity
您應用程式的 package.json 檔案會隨著相依項目更新。
在應用程式目錄中建立名為 index.js 的檔案。
小提示
您可以使用 PowerShell 建立新的檔案。 按住 Shift 鍵,並在資料夾上按下滑鼠右鍵,然後輸入下列命令,以開啟項目目錄中的 PowerShell 視窗:New-Item index.js。
建置您的 應用程式
若要與此文件智慧服務互動,您必須建立 DocumentAnalysisClient
類別的執行個體。 若要這樣做,您需要從 Azure 入口網站取得您的密鑰來建立 AzureKeyCredential
,並且使用 DocumentAnalysisClient
和 Document Intelligence 端點建立 AzureKeyCredential
實例。
在 Visual Studio Code 或您慣用的 IDE 中開啟 index.js
檔案,然後選取下列其中一個程式代碼範例,然後將/貼到您的應用程式:
- 預建的讀取 模型是所有文檔智能模型的核心,並且可以偵測行、文字、位置和語言。 版面配置、一般檔、預先建置和自定義模型全都使用
read
模型作為從檔擷取文字的基礎。 - prebuilt-layout 模型會從文件和影像中擷取文字和文字位置、表格、選取標記和結構資訊。
- prebuilt-tax.us.w2 模型會擷取美國國稅局 (IRS) 稅務表單上所報告的資訊。
- 預建發票 模型會擷取美國國稅服務稅單上報告的資訊。
- 預建收據 模型會從印刷和手寫的銷售收據中擷取重要資訊。
- 預建的 idDocument 模型會從美國駕駛執照、國際護照傳記頁面、美國州身份證、社會保障卡和永久居民卡中擷取重要資訊。
使用 Read 模型
const { AzureKeyCredential, DocumentAnalysisClient } = require("@azure/ai-form-recognizer");
//use your `key` and `endpoint` environment variables
const key = process.env['FR_KEY'];
const endpoint = process.env['FR_ENDPOINT'];
// sample document
const documentUrlRead = "https://raw.githubusercontent.com/Azure-Samples/cognitive-services-REST-api-samples/master/curl/form-recognizer/rest-api/read.png"
// helper function
function* getTextOfSpans(content, spans) {
for (const span of spans) {
yield content.slice(span.offset, span.offset + span.length);
}
}
async function main() {
// create your `DocumentAnalysisClient` instance and `AzureKeyCredential` variable
const client = new DocumentAnalysisClient(endpoint, new AzureKeyCredential(key));
const poller = await client.beginAnalyzeDocument("prebuilt-read", documentUrlRead);
const {
content,
pages,
languages,
styles
} = await poller.pollUntilDone();
if (pages.length <= 0) {
console.log("No pages were extracted from the document.");
} else {
console.log("Pages:");
for (const page of pages) {
console.log("- Page", page.pageNumber, `(unit: ${page.unit})`);
console.log(` ${page.width}x${page.height}, angle: ${page.angle}`);
console.log(` ${page.lines.length} lines, ${page.words.length} words`);
if (page.lines.length > 0) {
console.log(" Lines:");
for (const line of page.lines) {
console.log(` - "${line.content}"`);
// The words of the line can also be iterated independently. The words are computed based on their
// corresponding spans.
for (const word of line.words()) {
console.log(` - "${word.content}"`);
}
}
}
}
}
if (languages.length <= 0) {
console.log("No language spans were extracted from the document.");
} else {
console.log("Languages:");
for (const languageEntry of languages) {
console.log(
`- Found language: ${languageEntry.languageCode} (confidence: ${languageEntry.confidence})`
);
for (const text of getTextOfSpans(content, languageEntry.spans)) {
const escapedText = text.replace(/\r?\n/g, "\\n").replace(/"/g, '\\"');
console.log(` - "${escapedText}"`);
}
}
}
if (styles.length <= 0) {
console.log("No text styles were extracted from the document.");
} else {
console.log("Styles:");
for (const style of styles) {
console.log(
`- Handwritten: ${style.isHandwritten ? "yes" : "no"} (confidence=${style.confidence})`
);
for (const word of getTextOfSpans(content, style.spans)) {
console.log(` - "${word}"`);
}
}
}
}
main().catch((error) => {
console.error("An error occurred:", error);
process.exit(1);
});
請瀏覽 GitHub 上的 Azure 範例存放庫,並檢視 read
模型輸出。
使用 Layout 模型
const { AzureKeyCredential, DocumentAnalysisClient } = require("@azure/ai-form-recognizer");
//use your `key` and `endpoint` environment variables
const key = process.env['FR_KEY'];
const endpoint = process.env['FR_ENDPOINT'];
// sample document
const layoutUrl = "https://raw.githubusercontent.com/Azure-Samples/cognitive-services-REST-api-samples/master/curl/form-recognizer/rest-api/layout.png"
async function main() {
const client = new DocumentAnalysisClient(endpoint, new AzureKeyCredential(key));
const poller = await client.beginAnalyzeDocumentFromUrl(
"prebuilt-layout", layoutUrl);
// Layout extraction produces basic elements such as pages, words, lines, etc. as well as information about the
// appearance (styles) of textual elements.
const { pages, tables } = await poller.pollUntilDone();
if (!pages || pages.length <= 0) {
console.log("No pages were extracted from the document.");
} else {
console.log("Pages:");
for (const page of pages) {
console.log("- Page", page.pageNumber, `(unit: ${page.unit})`);
console.log(` ${page.width}x${page.height}, angle: ${page.angle}`);
console.log(
` ${page.lines && page.lines.length} lines, ${page.words && page.words.length} words`
);
if (page.lines && page.lines.length > 0) {
console.log(" Lines:");
for (const line of page.lines) {
console.log(` - "${line.content}"`);
// The words of the line can also be iterated independently. The words are computed based on their
// corresponding spans.
for (const word of line.words()) {
console.log(` - "${word.content}"`);
}
}
}
}
}
if (!tables || tables.length <= 0) {
console.log("No tables were extracted from the document.");
} else {
console.log("Tables:");
for (const table of tables) {
console.log(
`- Extracted table: ${table.columnCount} columns, ${table.rowCount} rows (${table.cells.length} cells)`
);
}
}
}
main().catch((error) => {
console.error("An error occurred:", error);
process.exit(1);
});
請瀏覽 GitHub 上的 Azure 範例存放庫,並檢視 版面配置模型輸出。
使用通用文件模型
const { AzureKeyCredential, DocumentAnalysisClient } = require("@azure/ai-form-recognizer");
//use your `key` and `endpoint` environment variables
const key = process.env['FR_KEY'];
const endpoint = process.env['FR_ENDPOINT'];
// sample document
const documentUrl = "https://raw.githubusercontent.com/Azure-Samples/cognitive-services-REST-api-samples/master/curl/form-recognizer/sample-layout.pdf"
async function main() {
const client = new DocumentAnalysisClient(endpoint, new AzureKeyCredential(key));
const poller = await client.beginAnalyzeDocumentFromUrl("prebuilt-document", documentUrl);
const {
keyValuePairs
} = await poller.pollUntilDone();
if (!keyValuePairs || keyValuePairs.length <= 0) {
console.log("No key-value pairs were extracted from the document.");
} else {
console.log("Key-Value Pairs:");
for (const {
key,
value,
confidence
} of keyValuePairs) {
console.log("- Key :", `"${key.content}"`);
console.log(" Value:", `"${(value && value.content) || "<undefined>"}" (${confidence})`);
}
}
}
main().catch((error) => {
console.error("An error occurred:", error);
process.exit(1);
});
請瀏覽 GitHub 上的 Azure 範例存放庫,並檢視 一般檔案模型輸出。
使用 W-2 稅務模型
const { AzureKeyCredential, DocumentAnalysisClient } = require("@azure/ai-form-recognizer");
//use your `key` and `endpoint` environment variables
const key = process.env['FR_KEY'];
const endpoint = process.env['FR_ENDPOINT'];
const w2DocumentURL = "https://raw.githubusercontent.com/Azure-Samples/cognitive-services-REST-api-samples/master/curl/form-recognizer/rest-api/w2.png"
async function main() {
const client = new DocumentAnalysisClient(endpoint, new AzureKeyCredential(key));
const poller = await client.beginAnalyzeDocument("prebuilt-tax.us.w2", w2DocumentURL);
const {
documents: [result]
} = await poller.pollUntilDone();
if (result) {
const { Employee, Employer, ControlNumber, TaxYear, AdditionalInfo } = result.fields;
if (Employee) {
const { Name, Address, SocialSecurityNumber } = Employee.properties;
console.log("Employee:");
console.log(" Name:", Name && Name.content);
console.log(" SSN/TIN:", SocialSecurityNumber && SocialSecurityNumber.content);
if (Address && Address.value) {
const { streetAddress, postalCode } = Address.value;
console.log(" Address:");
console.log(" Street Address:", streetAddress);
console.log(" Postal Code:", postalCode);
}
} else {
console.log("No employee information extracted.");
}
if (Employer) {
const { Name, Address, IdNumber } = Employer.properties;
console.log("Employer:");
console.log(" Name:", Name && Name.content);
console.log(" ID (EIN):", IdNumber && IdNumber.content);
if (Address && Address.value) {
const { streetAddress, postalCode } = Address.value;
console.log(" Address:");
console.log(" Street Address:", streetAddress);
console.log(" Postal Code:", postalCode);
}
} else {
console.log("No employer information extracted.");
}
console.log("Control Number:", ControlNumber && ControlNumber.content);
console.log("Tax Year:", TaxYear && TaxYear.content);
if (AdditionalInfo) {
console.log("Additional Info:");
for (const info of AdditionalInfo.values) {
const { LetterCode, Amount } = info.properties;
console.log(`- ${LetterCode && LetterCode.content}: ${Amount && Amount.content}`);
}
}
} else {
throw new Error("Expected at least one document in the result.");
}
}
main().catch((error) => {
console.error(error);
process.exit(1);
});
請瀏覽 GitHub 上的 Azure 範例存放庫,並檢視 W-2 稅務模型輸出。
使用發票模型
const { AzureKeyCredential, DocumentAnalysisClient } = require("@azure/ai-form-recognizer");
//use your `key` and `endpoint` environment variables
const key = process.env['FR_KEY'];
const endpoint = process.env['FR_ENDPOINT'];
// sample url
const invoiceUrl = "https://github.com/Azure-Samples/cognitive-services-REST-api-samples/raw/master/curl/form-recognizer/rest-api/invoice.pdf";
async function main() {
const client = new DocumentAnalysisClient(endpoint, new AzureKeyCredential(key));
const poller = await client.beginAnalyzeDocument("prebuilt-invoice", invoiceUrl);
const {
documents: [result]
} = await poller.pollUntilDone();
if (result) {
const invoice = result.fields;
console.log("Vendor Name:", invoice.VendorName?.content);
console.log("Customer Name:", invoice.CustomerName?.content);
console.log("Invoice Date:", invoice.InvoiceDate?.content);
console.log("Due Date:", invoice.DueDate?.content);
console.log("Items:");
for (const {
properties: item
} of invoice.Items?.values ?? []) {
console.log("-", item.ProductCode?.content ?? "<no product code>");
console.log(" Description:", item.Description?.content);
console.log(" Quantity:", item.Quantity?.content);
console.log(" Date:", item.Date?.content);
console.log(" Unit:", item.Unit?.content);
console.log(" Unit Price:", item.UnitPrice?.content);
console.log(" Tax:", item.Tax?.content);
console.log(" Amount:", item.Amount?.content);
}
console.log("Subtotal:", invoice.SubTotal?.content);
console.log("Previous Unpaid Balance:", invoice.PreviousUnpaidBalance?.content);
console.log("Tax:", invoice.TotalTax?.content);
console.log("Amount Due:", invoice.AmountDue?.content);
} else {
throw new Error("Expected at least one receipt in the result.");
}
}
main().catch((error) => {
console.error("An error occurred:", error);
process.exit(1);
});
請瀏覽 GitHub 上的 Azure 範例存放庫,並檢視 發票模型輸出。
使用收據模型
const { AzureKeyCredential, DocumentAnalysisClient } = require("@azure/ai-form-recognizer");
//use your `key` and `endpoint` environment variables
const key = process.env['FR_KEY'];
const endpoint = process.env['FR_ENDPOINT'];
// sample url
const receiptUrl = "https://raw.githubusercontent.com/Azure-Samples/cognitive-services-REST-api-samples/master/curl/form-recognizer/rest-api/receipt.png";
async function main() {
const client = new DocumentAnalysisClient(endpoint, new AzureKeyCredential(key));
const poller = await client.beginAnalyzeDocument("prebuilt-receipt", receiptUrl);
const {
documents: [result]
} = await poller.pollUntilDone();
if (result) {
const {
MerchantName,
Items,
Total
} = result.fields;
console.log("=== Receipt Information ===");
console.log("Type:", result.docType);
console.log("Merchant:", MerchantName && MerchantName.content);
console.log("Items:");
for (const item of (Items && Items.values) || []) {
const {
Description,
TotalPrice
} = item.properties;
console.log("- Description:", Description && Description.content);
console.log(" Total Price:", TotalPrice && TotalPrice.content);
}
console.log("Total:", Total && Total.content);
} else {
throw new Error("Expected at least one receipt in the result.");
}
}
main().catch((err) => {
console.error("The sample encountered an error:", err);
});
請瀏覽 GitHub 上的 Azure 範例存放庫,並檢視 收據模型輸出。
使用身分證件模型
const { AzureKeyCredential, DocumentAnalysisClient } = require("@azure/ai-form-recognizer");
//use your `key` and `endpoint` environment variables
const key = process.env['FR_KEY'];
const endpoint = process.env['FR_ENDPOINT'];
// sample document
const idDocumentURL = "https://raw.githubusercontent.com/Azure-Samples/cognitive-services-REST-api-samples/master/curl/form-recognizer/rest-api/identity_documents.png"
async function main() {
const client = new DocumentAnalysisClient(endpoint, new AzureKeyCredential(key));
const poller = await client.beginAnalyzeDocument("prebuilt-idDocument", idDocumentURL);
const {
documents: [result]
} = await poller.pollUntilDone();
if (result) {
// The identity document model has multiple document types, so we need to know which document type was actually
extracted.
if (result.docType === "idDocument.driverLicense") {
const { FirstName, LastName, DocumentNumber, DateOfBirth, DateOfExpiration, Height, Weight, EyeColor, Endorsements, Restrictions, VehicleClassifications} = result.fields;
// For the sake of the example, we'll only show a few of the fields that are produced.
console.log("Extracted a Driver License:");
console.log(" Name:", FirstName && FirstName.content, LastName && LastName.content);
console.log(" License No.:", DocumentNumber && DocumentNumber.content);
console.log(" Date of Birth:", DateOfBirth && DateOfBirth.content);
console.log(" Expiration:", DateOfExpiration && DateOfExpiration.content);
console.log(" Height:", Height && Height.content);
console.log(" Weight:", Weight && Weight.content);
console.log(" Eye color:", EyeColor && EyeColor.content);
console.log(" Restrictions:", Restrictions && Restrictions.content);
console.log(" Endorsements:", Endorsements && Endorsements.content);
console.log(" Class:", VehicleClassifications && VehicleClassifications.content);
} else if (result.docType === "idDocument.passport") {
// The passport document type extracts and parses the Passport's machine-readable zone
if (!result.fields.machineReadableZone) {
throw new Error("No Machine Readable Zone extracted from passport.");
}
const {
FirstName,
LastName,
DateOfBirth,
Nationality,
DocumentNumber,
CountryRegion,
DateOfExpiration,
} = result.fields.machineReadableZone.properties;
console.log("Extracted a Passport:");
console.log(" Name:", FirstName && FirstName.content, LastName && LastName.content);
console.log(" Date of Birth:", DateOfBirth && DateOfBirth.content);
console.log(" Nationality:", Nationality && natiNationalityonality.content);
console.log(" Passport No.:", DocumentNumber && DocumentNumber.content);
console.log(" Issuer:", CountryRegion && CountryRegion.content);
console.log(" Expiration Date:", DateOfExpiration && DateOfExpiration.content);
} else {
// The only reason this would happen is if the client library's schema for the prebuilt identity document model is
out of date, and a new document type has been introduced.
console.error("Unknown document type in result:", result);
}
} else {
throw new Error("Expected at least one receipt in the result.");
}
}
main().catch((error) => {
console.error("An error occurred:", error);
process.exit(1);
});
請瀏覽 GitHub 上的 Azure 範例存放庫,並檢視 識別碼檔案模型輸出。
使用名片模型
const { AzureKeyCredential, DocumentAnalysisClient } = require("@azure/ai-form-recognizer");
//use your `key` and `endpoint` environment variables
const key = process.env['FR_KEY'];
const endpoint = process.env['FR_ENDPOINT'];
// sample document
const businessCardURL = "https://raw.githubusercontent.com/Azure-Samples/cognitive-services-REST-api-samples/de5e0d8982ab754823c54de47a47e8e499351523/curl/form-recognizer/rest-api/business_card.jpg"
async function main() {
const client = new DocumentAnalysisClient(endpoint, new AzureKeyCredential(key));
const poller = await client.beginAnalyzeDocument("prebuilt-businessCard", businessCardURL);
const {
documents: [result]
} = await poller.pollUntilDone();
if (result) {
const businessCard = result.fields;
console.log("=== Business Card Information ===");
// There are more fields than just these few, and the model allows for multiple contact & company names as well as
// phone numbers, though we'll only show the first extracted values here.
const name = businessCard.ContactNames && businessCard.ContactNames.values[0];
if (name) {
const {
FirstName,
LastName
} = name.properties;
console.log("Name:", FirstName && FirstName.content, LastName && LastName.content);
}
const company = businessCard.CompanyNames && businessCard.CompanyNames.values[0];
if (company) {
console.log("Company:", company.content);
}
const address = businessCard.Addresses && businessCard.Addresses.values[0];
if (address) {
console.log("Address:", address.content);
}
const jobTitle = businessCard.JobTitles && businessCard.JobTitles.values[0];
if (jobTitle) {
console.log("Job title:", jobTitle.content);
}
const department = businessCard.Departments && businessCard.Departments.values[0];
if (department) {
console.log("Department:", department.content);
}
const email = businessCard.Emails && businessCard.Emails.values[0];
if (email) {
console.log("Email:", email.content);
}
const workPhone = businessCard.WorkPhones && businessCard.WorkPhones.values[0];
if (workPhone) {
console.log("Work phone:", workPhone.content);
}
const website = businessCard.Websites && businessCard.Websites.values[0];
if (website) {
console.log("Website:", website.content);
}
} else {
throw new Error("Expected at least one business card in the result.");
}
}
main().catch((error) => {
console.error("An error occurred:", error);
process.exit(1);
});
請瀏覽 GitHub 上的 Azure 範例存放庫,並檢視 名片模型輸出。
用戶端連結庫 | REST API 參考 | 套件 (PyPi) | 範例 | 支援的 REST API 版本
先決條件
Azure 訂用帳戶 - 免費建立一個訂用帳戶。
Python 3.7 或更新版本 (英文)。 您安裝的 Python 應包含 pip。 您可以藉由在命令列上執行
pip --version
來檢查您是否已安裝 pip。 安裝最新版本的 Python 以取得 pip。最新的 Visual Studio Code 版本或您慣用的 IDE。 請參閱 在 Visual Studio Code中開始使用 Python。
Azure AI 服務或文件智慧服務資源。 建立 單一服務 或 多服務。 您可以使用免費定價層 (
F0
) 來試用服務,之後可升級至付費層以用於實際執行環境。從您所建立資源的金鑰和端點,將應用程式連線至 Azure 文件智慧服務。
- 部署資源之後,請選取 [前往資源]。
- 在左側導覽功能表中,選取 [金鑰和端點]。
- 複製其中一個金鑰和 端點,以供本文稍後使用。
URL 的文件檔案。 針對此專案,您可以使用下表中針對每項功能的範例表單:
特徵 / 功能 modelID document-url Read 模型 prebuilt-read 範例手冊 版面配置模型 預設佈局 範例預約確認 W-2 表單模型 prebuilt-tax.us.w2 範例 W-2 表單 發票模型 prebuilt-invoice 範例發票 收據模型 prebuilt-receipt 範例收據 識別碼文件模型 prebuilt-idDocument 範例身份文件
設定環境變數
若要與此文件智慧服務互動,您必須建立 DocumentAnalysisClient
類別的執行個體。 若要這樣做,請使用 Azure 入口網站中的 key
和 endpoint
具現化用戶端。 針對此專案,請使用環境變數來儲存和存取認證。
這很重要
請謹慎使用 API 金鑰。 請勿在程式碼中直接包含 API 金鑰,且切勿公開張貼金鑰。 如果您使用 API 金鑰,請安全地將其儲存在 Azure 金鑰保存庫。 如需在應用程式中安全地使用 API 金鑰的詳細資訊,請參閱搭配 Azure 金鑰保存庫 的 API 金鑰。
如需 AI 服務安全性的詳細資訊,請參閱驗證對 Azure AI 服務的要求。
若要設定 Document Intelligence 資源金鑰的環境變數,請開啟主控台視窗,並遵循作系統和開發環境的指示。 將 <yourKey> 和 <yourEndpoint> 取代為 Azure 入口網站中資源的值。
Windows 中的環境變數不會區分大小寫。 它們通常會以大寫方式宣告,單字之間以底線連結。 在命令提示字元中,執行下列命令:
設定您的金鑰變數:
setx DI_KEY <yourKey>
設定您的端點變數
setx DI_ENDPOINT <yourEndpoint>
設定環境變數之後,請關閉 [命令提示字元] 視窗。 值會維持不變,直到您再次變更這些值為止。
重新啟動讀取環境變數的任何執行中程式。 例如,如果您使用 Visual Studio 或 Visual Studio Code 作為編輯器,請在執行範例程式代碼之前重新啟動。
以下是搭配環境變數使用的一些更實用的命令:
命令 | 動作 | 範例 |
---|---|---|
setx VARIABLE_NAME= |
將值設定為空字串,以刪除環境變數。 | setx DI_KEY= |
setx VARIABLE_NAME=value |
設定或變更環境變數的值。 | setx DI_KEY=<yourKey> |
set VARIABLE_NAME |
顯示特定環境變數的值。 | set DI_KEY |
set |
顯示所有環境變數。 | set |
設定程式設計環境
在本機環境中開啟控制台視窗,並使用 pip 安裝適用於 Python 的 Azure AI Document Intelligence 用戶端連結庫:
pip install azure-ai-documentintelligence==1.0.0b4
建立 Python 應用程式
若要與此文件智慧服務互動,您必須建立 DocumentIntelligenceClient
類別的執行個體。 若要這樣做,您需要從 Azure 入口網站取得您的密鑰來建立 AzureKeyCredential
,並且使用 DocumentIntelligenceClient
和 Document Intelligence 端點建立 AzureKeyCredential
實例。
在編輯器或 IDE 中建立名為 form_recognizer_quickstart.py 的新 Python 檔案。
開啟 form_recognizer_quickstart.py 檔案,然後選取下列其中一個程式代碼範例,然後將/貼到您的應用程式:
- 預建的讀取 模型是所有文檔智能模型的核心,並且可以偵測行、文字、位置和語言。 版面配置、一般檔、預先建置和自定義模型全都使用
read
模型作為從檔擷取文字的基礎。 - prebuilt-layout 模型會從文件和影像中擷取文字和文字位置、表格、選取標記和結構資訊。
- prebuilt-tax.us.w2 模型會擷取美國國稅局 (IRS) 稅務表單上所報告的資訊。
- 預設發票 模型會從各種格式的銷售發票中擷取關鍵欄位和明細項目。
- 預建收據 模型會從印刷和手寫的銷售收據中擷取重要資訊。
- 預建的 idDocument 模型會從美國駕駛執照、國際護照傳記頁面、美國州身份證、社會保障卡和永久居民卡中擷取重要資訊。
- 預建的讀取 模型是所有文檔智能模型的核心,並且可以偵測行、文字、位置和語言。 版面配置、一般檔、預先建置和自定義模型全都使用
從命令提示字元執行 Python 程式代碼。
python form_recognizer_quickstart.py
使用 Read 模型
import os
from azure.core.credentials import AzureKeyCredential
from azure.ai.documentintelligence import DocumentIntelligenceClient
from azure.ai.documentintelligence.models import AnalyzeResult
from azure.ai.documentintelligence.models import AnalyzeDocumentRequest
# use your `key` and `endpoint` environment variables
key = os.environ.get('DI_KEY')
endpoint = os.environ.get('DI_ENDPOINT')
# helper functions
def get_words(page, line):
result = []
for word in page.words:
if _in_span(word, line.spans):
result.append(word)
return result
def _in_span(word, spans):
for span in spans:
if word.span.offset >= span.offset and (word.span.offset + word.span.length) <= (span.offset + span.length):
return True
return False
def analyze_read():
# sample document
formUrl = "https://raw.githubusercontent.com/Azure-Samples/cognitive-services-REST-api-samples/master/curl/form-recognizer/rest-api/read.png"
client = DocumentIntelligenceClient(
endpoint=endpoint, credential=AzureKeyCredential(key)
)
poller = client.begin_analyze_document(
"prebuilt-read", AnalyzeDocumentRequest(url_source=formUrl
))
result: AnalyzeResult = poller.result()
print("----Languages detected in the document----")
if result.languages is not None:
for language in result.languages:
print(f"Language code: '{language.locale}' with confidence {language.confidence}")
print("----Styles detected in the document----")
if result.styles:
for style in result.styles:
if style.is_handwritten:
print("Found the following handwritten content: ")
print(",".join([result.content[span.offset : span.offset + span.length] for span in style.spans]))
if style.font_style:
print(f"The document contains '{style.font_style}' font style, applied to the following text: ")
print(",".join([result.content[span.offset : span.offset + span.length] for span in style.spans]))
for page in result.pages:
print(f"----Analyzing document from page #{page.page_number}----")
print(f"Page has width: {page.width} and height: {page.height}, measured with unit: {page.unit}")
if page.lines:
for line_idx, line in enumerate(page.lines):
words = get_words(page, line)
print(
f"...Line # {line_idx} has {len(words)} words and text '{line.content}' within bounding polygon '{line.polygon}'"
)
for word in words:
print(f"......Word '{word.content}' has a confidence of {word.confidence}")
if page.selection_marks:
for selection_mark in page.selection_marks:
print(
f"...Selection mark is '{selection_mark.state}' within bounding polygon "
f"'{selection_mark.polygon}' and has a confidence of {selection_mark.confidence}"
)
if result.paragraphs:
print(f"----Detected #{len(result.paragraphs)} paragraphs in the document----")
for paragraph in result.paragraphs:
print(f"Found paragraph with role: '{paragraph.role}' within {paragraph.bounding_regions} bounding region")
print(f"...with content: '{paragraph.content}'")
result.paragraphs.sort(key=lambda p: (p.spans.sort(key=lambda s: s.offset), p.spans[0].offset))
print("-----Print sorted paragraphs-----")
for idx, paragraph in enumerate(result.paragraphs):
print(
f"...paragraph:{idx} with offset: {paragraph.spans[0].offset} and length: {paragraph.spans[0].length}"
)
print("----------------------------------------")
if __name__ == "__main__":
analyze_read()
請瀏覽 GitHub 上的 Azure 範例存放庫,並檢視 read
模型輸出。
使用 Layout 模型
import os
from azure.core.credentials import AzureKeyCredential
from azure.ai.documentintelligence import DocumentIntelligenceClient
from azure.ai.documentintelligence.models import AnalyzeResult
from azure.ai.documentintelligence.models import AnalyzeDocumentRequest
# use your `key` and `endpoint` environment variables
key = os.environ.get('DI_KEY')
endpoint = os.environ.get('DI_ENDPOINT')
def analyze_layout():
# sample document
formUrl = "https://raw.githubusercontent.com/Azure-Samples/cognitive-services-REST-api-samples/master/curl/form-recognizer/rest-api/layout.png"
client = DocumentIntelligenceClient(
endpoint=endpoint, credential=AzureKeyCredential(key)
)
poller = client.begin_analyze_document(
"prebuilt-layout", AnalyzeDocumentRequest(url_source=formUrl
))
result: AnalyzeResult = poller.result()
if result.styles and any([style.is_handwritten for style in result.styles]):
print("Document contains handwritten content")
else:
print("Document does not contain handwritten content")
for page in result.pages:
print(f"----Analyzing layout from page #{page.page_number}----")
print(f"Page has width: {page.width} and height: {page.height}, measured with unit: {page.unit}")
if page.lines:
for line_idx, line in enumerate(page.lines):
words = get_words(page, line)
print(
f"...Line # {line_idx} has word count {len(words)} and text '{line.content}' "
f"within bounding polygon '{line.polygon}'"
)
for word in words:
print(f"......Word '{word.content}' has a confidence of {word.confidence}")
if page.selection_marks:
for selection_mark in page.selection_marks:
print(
f"Selection mark is '{selection_mark.state}' within bounding polygon "
f"'{selection_mark.polygon}' and has a confidence of {selection_mark.confidence}"
)
if result.tables:
for table_idx, table in enumerate(result.tables):
print(f"Table # {table_idx} has {table.row_count} rows and " f"{table.column_count} columns")
if table.bounding_regions:
for region in table.bounding_regions:
print(f"Table # {table_idx} location on page: {region.page_number} is {region.polygon}")
for cell in table.cells:
print(f"...Cell[{cell.row_index}][{cell.column_index}] has text '{cell.content}'")
if cell.bounding_regions:
for region in cell.bounding_regions:
print(f"...content on page {region.page_number} is within bounding polygon '{region.polygon}'")
print("----------------------------------------")
if __name__ == "__main__":
analyze_layout()
請瀏覽 GitHub 上的 Azure 範例存放庫,並檢視 版面配置模型輸出。
使用 W-2 稅務模型
import os
from azure.core.credentials import AzureKeyCredential
from azure.ai.documentintelligence import DocumentIntelligenceClient
from azure.ai.documentintelligence.models import AnalyzeResult
from azure.ai.documentintelligence.models import AnalyzeDocumentRequest
# use your `key` and `endpoint` environment variables
key = os.environ.get('DI_KEY')
endpoint = os.environ.get('DI_ENDPOINT')
# formatting function
def format_address_value(address_value):
return f"\n......House/building number: {address_value.house_number}\n......Road: {address_value.road}\n......City: {address_value.city}\n......State: {address_value.state}\n......Postal code: {address_value.postal_code}"
def analyze_tax_us_w2():
# sample document
formUrl = "https://raw.githubusercontent.com/Azure-Samples/cognitive-services-REST-api-samples/master/curl/form-recognizer/rest-api/w2.png"
client = DocumentIntelligenceClient(
endpoint=endpoint, credential=AzureKeyCredential(key)
)
poller = client.begin_analyze_document(
"prebuilt-tax.us.w2", AnalyzeDocumentRequest(url_source=formUrl
))
w2s: AnalyzeResult = poller.result()
if w2s.documents:
for idx, w2 in enumerate(w2s.documents):
print(f"--------Analyzing US Tax W-2 Form #{idx + 1}--------")
if w2.fields:
form_variant = w2.fields.get("W2FormVariant")
if form_variant:
print(
f"Form variant: {form_variant.get('valueString')} has confidence: " f"{form_variant.confidence}"
)
tax_year = w2.fields.get("TaxYear")
if tax_year:
print(f"Tax year: {tax_year.get('valueString')} has confidence: {tax_year.confidence}")
w2_copy = w2.fields.get("W2Copy")
if w2_copy:
print(f"W-2 Copy: {w2_copy.get('valueString')} has confidence: {w2_copy.confidence}")
employee = w2.fields.get("Employee")
if employee:
print("Employee data:")
employee_name = employee.get("valueObject").get("Name")
if employee_name:
f"confidence: {fed_income_tax_withheld.confidence}"
)
social_security_wages = w2.fields.get("SocialSecurityWages")
if social_security_wages:
print(
f"Social Security wages: {social_security_wages.get('valueNumber')} has confidence: "
f"{social_security_wages.confidence}"
)
social_security_tax_withheld = w2.fields.get("SocialSecurityTaxWithheld")
if social_security_tax_withheld:
print(
f"Social Security tax withheld: {social_security_tax_withheld.get('valueNumber')} "
f"has confidence: {social_security_tax_withheld.confidence}"
)
medicare_wages_tips = w2.fields.get("MedicareWagesAndTips")
if medicare_wages_tips:
print(
f"Medicare wages and tips: {medicare_wages_tips.get('valueNumber')} has confidence: "
f"{medicare_wages_tips.confidence}"
)
medicare_tax_withheld = w2.fields.get("MedicareTaxWithheld")
if medicare_tax_withheld:
print(
f"Medicare tax withheld: {medicare_tax_withheld.get('valueNumber')} has confidence: "
f"{medicare_tax_withheld.confidence}"
)
social_security_tips = w2.fields.get("SocialSecurityTips")
if social_security_tips:
print(
f"Social Security tips: {social_security_tips.get('valueNumber')} has confidence: "
f"{social_security_tips.confidence}"
)
allocated_tips = w2.fields.get("AllocatedTips")
if allocated_tips:
print(
f"Allocated tips: {allocated_tips.get('valueNumber')} has confidence: {allocated_tips.confidence}"
)
verification_code = w2.fields.get("VerificationCode")
if verification_code:
print(
f"Verification code: {verification_code.get('valueNumber')} has confidence: {verification_code.confidence}"
)
dependent_care_benefits = w2.fields.get("DependentCareBenefits")
if dependent_care_benefits:
print(
f"Dependent care benefits: {dependent_care_benefits.get('valueNumber')} has confidence: {dependent_care_benefits.confidence}"
)
non_qualified_plans = w2.fields.get("NonQualifiedPlans")
if non_qualified_plans:
print(
f"Non-qualified plans: {non_qualified_plans.get('valueNumber')} has confidence: {non_qualified_plans.confidence}"
)
additional_info = w2.fields.get("AdditionalInfo")
if additional_info:
print("Additional information:")
for item in additional_info.get("valueArray"):
letter_code = item.get("valueObject").get("LetterCode")
if letter_code:
print(
f"...Letter code: {letter_code.get('valueString')} has confidence: {letter_code.confidence}"
)
amount = item.get("valueObject").get("Amount")
if amount:
print(f"...Amount: {amount.get('valueNumber')} has confidence: {amount.confidence}")
is_statutory_employee = w2.fields.get("IsStatutoryEmployee")
if is_statutory_employee:
print(
f"Is statutory employee: {is_statutory_employee.get('valueString')} has confidence: {is_statutory_employee.confidence}"
)
is_retirement_plan = w2.fields.get("IsRetirementPlan")
if is_retirement_plan:
print(
f"Is retirement plan: {is_retirement_plan.get('valueString')} has confidence: {is_retirement_plan.confidence}"
)
third_party_sick_pay = w2.fields.get("IsThirdPartySickPay")
if third_party_sick_pay:
print(
f"Is third party sick pay: {third_party_sick_pay.get('valueString')} has confidence: {third_party_sick_pay.confidence}"
)
other_info = w2.fields.get("Other")
if other_info:
print(f"Other information: {other_info.get('valueString')} has confidence: {other_info.confidence}")
state_tax_info = w2.fields.get("StateTaxInfos")
if state_tax_info:
print("State Tax info:")
for tax in state_tax_info.get("valueArray"):
state = tax.get("valueObject").get("State")
if state:
print(f"...State: {state.get('valueString')} has confidence: {state.confidence}")
employer_state_id_number = tax.get("valueObject").get("EmployerStateIdNumber")
if employer_state_id_number:
print(
f"...Employer state ID number: {employer_state_id_number.get('valueString')} has "
f"confidence: {employer_state_id_number.confidence}"
)
state_wages_tips = tax.get("valueObject").get("StateWagesTipsEtc")
if state_wages_tips:
print(
f"...State wages, tips, etc: {state_wages_tips.get('valueNumber')} has confidence: "
f"{state_wages_tips.confidence}"
)
state_income_tax = tax.get("valueObject").get("StateIncomeTax")
if state_income_tax:
print(
f"...State income tax: {state_income_tax.get('valueNumber')} has confidence: "
f"{state_income_tax.confidence}"
)
local_tax_info = w2.fields.get("LocalTaxInfos")
if local_tax_info:
print("Local Tax info:")
for tax in local_tax_info.get("valueArray"):
local_wages_tips = tax.get("valueObject").get("LocalWagesTipsEtc")
if local_wages_tips:
print(
f"...Local wages, tips, etc: {local_wages_tips.get('valueNumber')} has confidence: "
f"{local_wages_tips.confidence}"
)
local_income_tax = tax.get("valueObject").get("LocalIncomeTax")
if local_income_tax:
print(
f"...Local income tax: {local_income_tax.get('valueNumber')} has confidence: "
f"{local_income_tax.confidence}"
)
locality_name = tax.get("valueObject").get("LocalityName")
if locality_name:
print(
f"...Locality name: {locality_name.get('valueString')} has confidence: "
f"{locality_name.confidence}"
)
print("----------------------------------------")
if __name__ == "__main__":
analyze_tax_us_w2()
請瀏覽 GitHub 上的 Azure 範例存放庫,並檢視 W-2 稅務模型輸出。
使用發票模型
import os
from azure.core.credentials import AzureKeyCredential
from azure.ai.documentintelligence import DocumentIntelligenceClient
from azure.ai.documentintelligence.models import AnalyzeResult
from azure.ai.documentintelligence.models import AnalyzeDocumentRequest
# use your `key` and `endpoint` environment variables
key = os.environ.get('DI_KEY')
endpoint = os.environ.get('DI_ENDPOINT')
def analyze_invoice():
invoiceUrl = "https://raw.githubusercontent.com/Azure-Samples/cognitive-services-REST-api-samples/master/curl/form-recognizer/sample-invoice.pdf"
client = DocumentIntelligenceClient(
endpoint=endpoint, credential=AzureKeyCredential(key)
)
poller = client.begin_analyze_document(
"prebuilt-invoice", AnalyzeDocumentRequest(url_source=formUrl), locale="en-US")
result: AnalyzeResult = poller.result()
if invoices.documents:
for idx, invoice in enumerate(invoices.documents):
print(f"--------Analyzing invoice #{idx + 1}--------")
if invoice.fields:
vendor_name = invoice.fields.get("VendorName")
if vendor_name:
print(f"Vendor Name: {vendor_name.get('content')} has confidence: {vendor_name.get('confidence')}")
vendor_address = invoice.fields.get("VendorAddress")
if vendor_address:
print(
f"Vendor Address: {vendor_address.get('content')} has confidence: {vendor_address.get('confidence')}"
)
vendor_address_recipient = invoice.fields.get("VendorAddressRecipient")
if vendor_address_recipient:
print(
f"Vendor Address Recipient: {vendor_address_recipient.get('content')} has confidence: {vendor_address_recipient.get('confidence')}"
)
customer_name = invoice.fields.get("CustomerName")
if customer_name:
print(
f"Customer Name: {customer_name.get('content')} has confidence: {customer_name.get('confidence')}"
)
customer_id = invoice.fields.get("CustomerId")
if invoice_id:
print(f"Invoice Id: {invoice_id.get('content')} has confidence: {invoice_id.get('confidence')}")
invoice_date = invoice.fields.get("InvoiceDate")
if invoice_date:
print(
f"Invoice Date: {invoice_date.get('content')} has confidence: {invoice_date.get('confidence')}"
)
invoice_total = invoice.fields.get("InvoiceTotal")
if invoice_total:
print(
f"Invoice Total: {invoice_total.get('content')} has confidence: {invoice_total.get('confidence')}"
)
due_date = invoice.fields.get("DueDate")
if due_date:
print(f"Due Date: {due_date.get('content')} has confidence: {due_date.get('confidence')}")
purchase_order = invoice.fields.get("PurchaseOrder")
if purchase_order:
print(
f"Purchase Order: {purchase_order.get('content')} has confidence: {purchase_order.get('confidence')}"
)
billing_address = invoice.fields.get("BillingAddress")
if billing_address:
print(
f"Billing Address: {billing_address.get('content')} has confidence: {billing_address.get('confidence')}"
)
billing_address_recipient = invoice.fields.get("BillingAddressRecipient")
if billing_address_recipient:
print(
f"Billing Address Recipient: {billing_address_recipient.get('content')} has confidence: {billing_address_recipient.get('confidence')}"
)
shipping_address = invoice.fields.get("ShippingAddress")
if shipping_address:
print(
f"Shipping Address: {shipping_address.get('content')} has confidence: {shipping_address.get('confidence')}"
)
shipping_address_recipient = invoice.fields.get("ShippingAddressRecipient")
if shipping_address_recipient:
print(
f"Shipping Address Recipient: {shipping_address_recipient.get('content')} has confidence: {shipping_address_recipient.get('confidence')}"
)
print("Invoice items:")
items = invoice.fields.get("Items")
if items:
for idx, item in enumerate(items.get("valueArray")):
print(f"...Item #{idx + 1}")
item_description = item.get("valueObject").get("Description")
if item_description:
print(
f"......Description: {item_description.get('content')} has confidence: {item_description.get('confidence')}"
)
item_quantity = item.get("valueObject").get("Quantity")
if item_quantity:
print(
f"......Quantity: {item_quantity.get('content')} has confidence: {item_quantity.get('confidence')}"
)
unit = item.get("valueObject").get("Unit")
if unit:
print(f"......Unit: {unit.get('content')} has confidence: {unit.get('confidence')}")
unit_price = item.get("valueObject").get("UnitPrice")
if unit_price:
unit_price_code = (
unit_price.get("valueCurrency").get("currencyCode")
if unit_price.get("valueCurrency").get("currencyCode")
else ""
)
print(
f"......Unit Price: {unit_price.get('content')}{unit_price_code} has confidence: {unit_price.get('confidence')}"
)
product_code = item.get("valueObject").get("ProductCode")
if product_code:
print(
f"......Product Code: {product_code.get('content')} has confidence: {product_code.get('confidence')}"
)
item_date = item.get("valueObject").get("Date")
if item_date:
print(
f"......Date: {item_date.get('content')} has confidence: {item_date.get('confidence')}"
)
tax = item.get("valueObject").get("Tax")
if tax:
print(f"......Tax: {tax.get('content')} has confidence: {tax.get('confidence')}")
amount = item.get("valueObject").get("Amount")
if amount:
print(f"......Amount: {amount.get('content')} has confidence: {amount.get('confidence')}")
subtotal = invoice.fields.get("SubTotal")
if subtotal:
print(f"Subtotal: {subtotal.get('content')} has confidence: {subtotal.get('confidence')}")
total_tax = invoice.fields.get("TotalTax")
if total_tax:
print(f"Total Tax: {total_tax.get('content')} has confidence: {total_tax.get('confidence')}")
previous_unpaid_balance = invoice.fields.get("PreviousUnpaidBalance")
if previous_unpaid_balance:
print(
f"Previous Unpaid Balance: {previous_unpaid_balance.get('content')} has confidence: {previous_unpaid_balance.get('confidence')}"
)
amount_due = invoice.fields.get("AmountDue")
if amount_due:
print(f"Amount Due: {amount_due.get('content')} has confidence: {amount_due.get('confidence')}")
service_start_date = invoice.fields.get("ServiceStartDate")
if service_start_date:
print(
f"Service Start Date: {service_start_date.get('content')} has confidence: {service_start_date.get('confidence')}"
)
service_end_date = invoice.fields.get("ServiceEndDate")
if service_end_date:
print(
f"Service End Date: {service_end_date.get('content')} has confidence: {service_end_date.get('confidence')}"
)
service_address = invoice.fields.get("ServiceAddress")
if service_address:
print(
f"Service Address: {service_address.get('content')} has confidence: {service_address.get('confidence')}"
)
service_address_recipient = invoice.fields.get("ServiceAddressRecipient")
if service_address_recipient:
print(
f"Service Address Recipient: {service_address_recipient.get('content')} has confidence: {service_address_recipient.get('confidence')}"
)
remittance_address = invoice.fields.get("RemittanceAddress")
if remittance_address:
print(
f"Remittance Address: {remittance_address.get('content')} has confidence: {remittance_address.get('confidence')}"
)
remittance_address_recipient = invoice.fields.get("RemittanceAddressRecipient")
if remittance_address_recipient:
print(
f"Remittance Address Recipient: {remittance_address_recipient.get('content')} has confidence: {remittance_address_recipient.get('confidence')}"
)
print("----------------------------------------")
if __name__ == "__main__":
analyze_invoice()
請瀏覽 GitHub 上的 Azure 範例存放庫,並檢視 發票模型輸出。
使用收據模型
import os
from azure.core.credentials import AzureKeyCredential
from azure.ai.documentintelligence import DocumentIntelligenceClient
from azure.ai.documentintelligence.models import AnalyzeResult
from azure.ai.documentintelligence.models import AnalyzeDocumentRequest
# use your `key` and `endpoint` environment variables
key = os.environ.get('DI_KEY')
endpoint = os.environ.get('DI_ENDPOINT')
def analyze_receipts():
# sample document
receiptUrl = "https://raw.githubusercontent.com/Azure-Samples/cognitive-services-REST-api-samples/master/curl/form-recognizer/rest-api/receipt.png"
client = DocumentIntelligenceClient(
endpoint=endpoint, credential=AzureKeyCredential(key)
)
poller = client.begin_analyze_document(
"prebuilt-receipt", AnalyzeDocumentRequest(url_source=receiptUrl), locale="en-US"
)
receipts: AnalyzeResult = poller.result()
if receipts.documents:
for idx, receipt in enumerate(receipts.documents):
print(f"--------Analysis of receipt #{idx + 1}--------")
print(f"Receipt type: {receipt.doc_type if receipt.doc_type else 'N/A'}")
if receipt.fields:
merchant_name = receipt.fields.get("MerchantName")
if merchant_name:
print(
f"Merchant Name: {merchant_name.get('valueString')} has confidence: "
f"{merchant_name.confidence}"
)
transaction_date = receipt.fields.get("TransactionDate")
if transaction_date:
print(
f"Transaction Date: {transaction_date.get('valueDate')} has confidence: "
f"{transaction_date.confidence}"
)
items = receipt.fields.get("Items")
if items:
print("Receipt items:")
for idx, item in enumerate(items.get("valueArray")):
print(f"...Item #{idx + 1}")
item_description = item.get("valueObject").get("Description")
if item_description:
print(
f"......Item Description: {item_description.get('valueString')} has confidence: "
f"{item_description.confidence}"
)
item_quantity = item.get("valueObject").get("Quantity")
if item_quantity:
print(
f"......Item Quantity: {item_quantity.get('valueString')} has confidence: "
f"{item_quantity.confidence}"
)
item_total_price = item.get("valueObject").get("TotalPrice")
if item_total_price:
print(
f"......Total Item Price: {format_price(item_total_price.get('valueCurrency'))} has confidence: "
f"{item_total_price.confidence}"
)
subtotal = receipt.fields.get("Subtotal")
if subtotal:
print(
f"Subtotal: {format_price(subtotal.get('valueCurrency'))} has confidence: {subtotal.confidence}"
)
tax = receipt.fields.get("TotalTax")
if tax:
print(f"Total tax: {format_price(tax.get('valueCurrency'))} has confidence: {tax.confidence}")
tip = receipt.fields.get("Tip")
if tip:
print(f"Tip: {format_price(tip.get('valueCurrency'))} has confidence: {tip.confidence}")
total = receipt.fields.get("Total")
if total:
print(f"Total: {format_price(total.get('valueCurrency'))} has confidence: {total.confidence}")
print("--------------------------------------")
if __name__ == "__main__":
analyze_receipts()
請瀏覽 GitHub 上的 Azure 範例存放庫,並檢視 收據模型輸出。
使用身分證件模型
import os
from azure.core.credentials import AzureKeyCredential
from azure.ai.documentintelligence import DocumentIntelligenceClient
from azure.ai.documentintelligence.models import AnalyzeResult
from azure.ai.documentintelligence.models import AnalyzeDocumentRequest
# use your `key` and `endpoint` environment variables
key = os.environ.get('DI_KEY')
endpoint = os.environ.get('DI_ENDPOINT')
def analyze_identity_documents():
# sample document
identityUrl = "https://raw.githubusercontent.com/Azure-Samples/cognitive-services-REST-api-samples/master/curl/form-recognizer/rest-api/identity_documents.png"
client = DocumentIntelligenceClient(
endpoint=endpoint, credential=AzureKeyCredential(key)
)
poller =client.begin_analyze_document(
"prebuilt-idDocument", AnalyzeDocumentRequest(url_source=identityUrl)
)
id_documents: AnalyzeResult = poller.result()
if id_documents.documents:
for idx, id_document in enumerate(id_documents.documents):
print(f"--------Analyzing ID document #{idx + 1}--------")
if id_document.fields:
first_name = id_document.fields.get("FirstName")
if first_name:
print(f"First Name: {first_name.get('valueString')} has confidence: {first_name.confidence}")
last_name = id_document.fields.get("LastName")
if last_name:
print(f"Last Name: {last_name.get('valueString')} has confidence: {last_name.confidence}")
document_number = id_document.fields.get("DocumentNumber")
if document_number:
print(
f"Document Number: {document_number.get('valueString')} has confidence: {document_number.confidence}"
)
dob = id_document.fields.get("DateOfBirth")
if dob:
print(f"Date of Birth: {dob.get('valueDate')} has confidence: {dob.confidence}")
doe = id_document.fields.get("DateOfExpiration")
if doe:
print(f"Date of Expiration: {doe.get('valueDate')} has confidence: {doe.confidence}")
sex = id_document.fields.get("Sex")
if sex:
print(f"Sex: {sex.get('valueString')} has confidence: {sex.confidence}")
address = id_document.fields.get("Address")
if address:
print(f"Address: {address.get('valueString')} has confidence: {address.confidence}")
country_region = id_document.fields.get("CountryRegion")
if country_region:
print(
f"Country/Region: {country_region.get('valueCountryRegion')} has confidence: {country_region.confidence}"
)
region = id_document.fields.get("Region")
if region:
print(f"Region: {region.get('valueString')} has confidence: {region.confidence}")
print("--------------------------------------")
if __name__ == "__main__":
analyze_identity_documents()
請瀏覽 GitHub 上的 Azure 範例存放庫,並檢視 識別碼檔案模型輸出。
用戶端連結庫 |REST API 參考 | 套件 (PyPi) | 範例 | 支援的 REST API 版本
用戶端連結庫 |REST API 參考 | 套件 (PyPi) | 範例 | 支援的 REST API 版本
先決條件
Azure 訂用帳戶 - 免費建立一個訂用帳戶。
Python 3.7 或更新版本 (英文)。 您安裝的 Python 應包含 pip。 您可以藉由在命令列上執行
pip --version
來檢查您是否已安裝 pip。 安裝最新版本的 Python 以取得 pip。最新的 Visual Studio Code 版本或您慣用的 IDE。 請參閱 在 Visual Studio Code中開始使用 Python。
Azure AI 服務或文件智慧服務資源。 建立 單一服務 或 多服務。 您可以使用免費定價層 (
F0
) 來試用服務,之後可升級至付費層以用於實際執行環境。從您所建立資源的金鑰和端點,將應用程式連線至 Azure 文件智慧服務。
- 部署資源之後,請選取 [前往資源]。
- 在左側導覽功能表中,選取 [金鑰和端點]。
- 複製其中一個金鑰和 端點,以供本文稍後使用。
URL 的文件檔案。 針對此專案,您可以使用下表中針對每項功能的範例表單:
特徵 / 功能 modelID document-url Read 模型 prebuilt-read 範例手冊 版面配置模型 預設佈局 範例預約確認 W-2 表單模型 prebuilt-tax.us.w2 範例 W-2 表單 發票模型 prebuilt-invoice 範例發票 收據模型 prebuilt-receipt 範例收據 識別碼文件模型 prebuilt-idDocument 範例身份文件 名片模型 prebuilt-businessCard 範例名片
設定環境變數
若要與此文件智慧服務互動,您必須建立 DocumentAnalysisClient
類別的執行個體。 若要這樣做,請使用 Azure 入口網站中的 key
和 endpoint
具現化用戶端。 針對此專案,請使用環境變數來儲存和存取認證。
這很重要
請謹慎使用 API 金鑰。 請勿在程式碼中直接包含 API 金鑰,且切勿公開張貼金鑰。 如果您使用 API 金鑰,請安全地將其儲存在 Azure 金鑰保存庫。 如需在應用程式中安全地使用 API 金鑰的詳細資訊,請參閱搭配 Azure 金鑰保存庫 的 API 金鑰。
如需 AI 服務安全性的詳細資訊,請參閱驗證對 Azure AI 服務的要求。
若要設定 Document Intelligence 資源金鑰的環境變數,請開啟主控台視窗,並遵循作系統和開發環境的指示。 將 <yourKey> 和 <yourEndpoint> 取代為 Azure 入口網站中資源的值。
Windows 中的環境變數不會區分大小寫。 它們通常會以大寫方式宣告,單字之間以底線連結。 在命令提示字元中,執行下列命令:
設定您的金鑰變數:
setx DI_KEY <yourKey>
設定您的端點變數
setx DI_ENDPOINT <yourEndpoint>
設定環境變數之後,請關閉 [命令提示字元] 視窗。 值會維持不變,直到您再次變更這些值為止。
重新啟動讀取環境變數的任何執行中程式。 例如,如果您使用 Visual Studio 或 Visual Studio Code 作為編輯器,請在執行範例程式代碼之前重新啟動。
以下是搭配環境變數使用的一些更實用的命令:
命令 | 動作 | 範例 |
---|---|---|
setx VARIABLE_NAME= |
將值設定為空字串,以刪除環境變數。 | setx DI_KEY= |
setx VARIABLE_NAME=value |
設定或變更環境變數的值。 | setx DI_KEY=<yourKey> |
set VARIABLE_NAME |
顯示特定環境變數的值。 | set DI_KEY |
set |
顯示所有環境變數。 | set |
設定程式設計環境
在本機環境中開啟控制台視窗,並使用 pip 安裝適用於 Python 的 Azure AI Document Intelligence 用戶端連結庫:
pip install azure-ai-formrecognizer==3.2.0
建立 Python 應用程式
若要與此文件智慧服務互動,您必須建立 DocumentAnalysisClient
類別的執行個體。 若要這樣做,您需要從 Azure 入口網站取得您的密鑰來建立 AzureKeyCredential
,並且使用 DocumentAnalysisClient
和 Document Intelligence 端點建立 AzureKeyCredential
實例。
在編輯器或 IDE 中建立名為 form_recognizer_quickstart.py 的新 Python 檔案。
開啟 form_recognizer_quickstart.py 檔案,然後選取下列其中一個程式代碼範例,然後將/貼到您的應用程式:
- 預建的讀取 模型是所有文檔智能模型的核心,並且可以偵測行、文字、位置和語言。 版面配置、一般檔、預先建置和自定義模型全都使用
read
模型作為從檔擷取文字的基礎。 - prebuilt-layout 模型會從文件和影像中擷取文字和文字位置、表格、選取標記和結構資訊。
- prebuilt-tax.us.w2 模型會擷取美國國稅局 (IRS) 稅務表單上所報告的資訊。
- 預設發票 模型會從各種格式的銷售發票中擷取關鍵欄位和明細項目。
- 預建收據 模型會從印刷和手寫的銷售收據中擷取重要資訊。
- 預建的 idDocument 模型會從美國駕駛執照、國際護照傳記頁面、美國州身份證、社會保障卡和永久居民卡中擷取重要資訊。
- 預建的讀取 模型是所有文檔智能模型的核心,並且可以偵測行、文字、位置和語言。 版面配置、一般檔、預先建置和自定義模型全都使用
從命令提示字元執行 Python 程式代碼。
python form_recognizer_quickstart.py
使用 Read 模型
import os
from azure.ai.formrecognizer import DocumentAnalysisClient
from azure.core.credentials import AzureKeyCredential
# use your `key` and `endpoint` environment variables
key = os.environ.get('FR_KEY')
endpoint = os.environ.get('FR_ENDPOINT')
# formatting function
def format_polygon(polygon):
if not polygon:
return "N/A"
return ", ".join(["[{}, {}]".format(p.x, p.y) for p in polygon])
def analyze_read():
# sample document
formUrl = "https://raw.githubusercontent.com/Azure-Samples/cognitive-services-REST-api-samples/master/curl/form-recognizer/rest-api/read.png"
document_analysis_client = DocumentAnalysisClient(
endpoint=endpoint, credential=AzureKeyCredential(key)
)
poller = document_analysis_client.begin_analyze_document_from_url(
"prebuilt-read", formUrl
)
result = poller.result()
print("Document contains content: ", result.content)
for idx, style in enumerate(result.styles):
print(
"Document contains {} content".format(
"handwritten" if style.is_handwritten else "no handwritten"
)
)
for page in result.pages:
print("----Analyzing Read from page #{}----".format(page.page_number))
print(
"Page has width: {} and height: {}, measured with unit: {}".format(
page.width, page.height, page.unit
)
)
for line_idx, line in enumerate(page.lines):
print(
"...Line # {} has text content '{}' within bounding box '{}'".format(
line_idx,
line.content,
format_polygon(line.polygon),
)
)
for word in page.words:
print(
"...Word '{}' has a confidence of {}".format(
word.content, word.confidence
)
)
print("----------------------------------------")
if __name__ == "__main__":
analyze_read()
請瀏覽 GitHub 上的 Azure 範例存放庫,並檢視 read
模型輸出。
使用 Layout 模型
import os
from azure.ai.formrecognizer import DocumentAnalysisClient
from azure.core.credentials import AzureKeyCredential
# use your `key` and `endpoint` environment variables
key = os.environ.get('FR_KEY')
endpoint = os.environ.get('FR_ENDPOINT')
# formatting function
def format_polygon(polygon):
if not polygon:
return "N/A"
return ", ".join(["[{}, {}]".format(p.x, p.y) for p in polygon])
def analyze_layout():
# sample document
formUrl = "https://raw.githubusercontent.com/Azure-Samples/cognitive-services-REST-api-samples/master/curl/form-recognizer/rest-api/layout.png"
document_analysis_client = DocumentAnalysisClient(
endpoint=endpoint, credential=AzureKeyCredential(key)
)
poller = document_analysis_client.begin_analyze_document_from_url(
"prebuilt-layout", formUrl
)
result = poller.result()
for idx, style in enumerate(result.styles):
print(
"Document contains {} content".format(
"handwritten" if style.is_handwritten else "no handwritten"
)
)
for page in result.pages:
print("----Analyzing layout from page #{}----".format(page.page_number))
print(
"Page has width: {} and height: {}, measured with unit: {}".format(
page.width, page.height, page.unit
)
)
for line_idx, line in enumerate(page.lines):
words = line.get_words()
print(
"...Line # {} has word count {} and text '{}' within bounding box '{}'".format(
line_idx,
len(words),
line.content,
format_polygon(line.polygon),
)
)
for word in words:
print(
"......Word '{}' has a confidence of {}".format(
word.content, word.confidence
)
)
for selection_mark in page.selection_marks:
print(
"...Selection mark is '{}' within bounding box '{}' and has a confidence of {}".format(
selection_mark.state,
format_polygon(selection_mark.polygon),
selection_mark.confidence,
)
)
for table_idx, table in enumerate(result.tables):
print(
"Table # {} has {} rows and {} columns".format(
table_idx, table.row_count, table.column_count
)
)
for region in table.bounding_regions:
print(
"Table # {} location on page: {} is {}".format(
table_idx,
region.page_number,
format_polygon(region.polygon),
)
)
for cell in table.cells:
print(
"...Cell[{}][{}] has content '{}'".format(
cell.row_index,
cell.column_index,
cell.content,
)
)
for region in cell.bounding_regions:
print(
"...content on page {} is within bounding box '{}'".format(
region.page_number,
format_polygon(region.polygon),
)
)
print("----------------------------------------")
if __name__ == "__main__":
analyze_layout()
請瀏覽 GitHub 上的 Azure 範例存放庫,並檢視 版面配置模型輸出。
使用通用文件模型
import os
from azure.ai.formrecognizer import DocumentAnalysisClient
from azure.core.credentials import AzureKeyCredential
# use your `key` and `endpoint` environment variables
key = os.environ.get('FR_KEY')
endpoint = os.environ.get('FR_ENDPOINT')
# formatting function
def format_bounding_region(bounding_regions):
if not bounding_regions:
return "N/A"
return ", ".join("Page #{}: {}".format(region.page_number, format_polygon(region.polygon)) for region in bounding_regions)
# formatting function
def format_polygon(polygon):
if not polygon:
return "N/A"
return ", ".join(["[{}, {}]".format(p.x, p.y) for p in polygon])
def analyze_general_documents():
# sample document
docUrl = "https://raw.githubusercontent.com/Azure-Samples/cognitive-services-REST-api-samples/master/curl/form-recognizer/sample-layout.pdf"
# create your `DocumentAnalysisClient` instance and `AzureKeyCredential` variable
document_analysis_client = DocumentAnalysisClient(endpoint=endpoint, credential=AzureKeyCredential(key))
poller = document_analysis_client.begin_analyze_document_from_url(
"prebuilt-document", docUrl)
result = poller.result()
for style in result.styles:
if style.is_handwritten:
print("Document contains handwritten content: ")
print(",".join([result.content[span.offset:span.offset + span.length] for span in style.spans]))
print("----Key-value pairs found in document----")
for kv_pair in result.key_value_pairs:
if kv_pair.key:
print(
"Key '{}' found within '{}' bounding regions".format(
kv_pair.key.content,
format_bounding_region(kv_pair.key.bounding_regions),
)
)
if kv_pair.value:
print(
"Value '{}' found within '{}' bounding regions\n".format(
kv_pair.value.content,
format_bounding_region(kv_pair.value.bounding_regions),
)
)
for page in result.pages:
print("----Analyzing document from page #{}----".format(page.page_number))
print(
"Page has width: {} and height: {}, measured with unit: {}".format(
page.width, page.height, page.unit
)
)
for line_idx, line in enumerate(page.lines):
print(
"...Line # {} has text content '{}' within bounding box '{}'".format(
line_idx,
line.content,
format_polygon(line.polygon),
)
)
for word in page.words:
print(
"...Word '{}' has a confidence of {}".format(
word.content, word.confidence
)
)
for selection_mark in page.selection_marks:
print(
"...Selection mark is '{}' within bounding box '{}' and has a confidence of {}".format(
selection_mark.state,
format_polygon(selection_mark.polygon),
selection_mark.confidence,
)
)
for table_idx, table in enumerate(result.tables):
print(
"Table # {} has {} rows and {} columns".format(
table_idx, table.row_count, table.column_count
)
)
for region in table.bounding_regions:
print(
"Table # {} location on page: {} is {}".format(
table_idx,
region.page_number,
format_polygon(region.polygon),
)
)
for cell in table.cells:
print(
"...Cell[{}][{}] has content '{}'".format(
cell.row_index,
cell.column_index,
cell.content,
)
)
for region in cell.bounding_regions:
print(
"...content on page {} is within bounding box '{}'\n".format(
region.page_number,
format_polygon(region.polygon),
)
)
print("----------------------------------------")
if __name__ == "__main__":
analyze_general_documents()
請瀏覽 GitHub 上的 Azure 範例存放庫,並檢視 一般檔案模型輸出。
使用 W-2 稅務模型
import os
from azure.ai.formrecognizer import DocumentAnalysisClient
from azure.core.credentials import AzureKeyCredential
# use your `key` and `endpoint` environment variables
key = os.environ.get('FR_KEY')
endpoint = os.environ.get('FR_ENDPOINT')
# formatting function
def format_address_value(address_value):
return f"\n......House/building number: {address_value.house_number}\n......Road: {address_value.road}\n......City: {address_value.city}\n......State: {address_value.state}\n......Postal code: {address_value.postal_code}"
def analyze_tax_us_w2():
# sample document
formUrl = "https://raw.githubusercontent.com/Azure-Samples/cognitive-services-REST-api-samples/master/curl/form-recognizer/rest-api/w2.png"
document_analysis_client = DocumentAnalysisClient(
endpoint=endpoint, credential=AzureKeyCredential(key)
)
poller = document_analysis_client.begin_analyze_document_from_url(
"prebuilt-tax.us.w2", formUrl
)
w2s = poller.result()
for idx, w2 in enumerate(w2s.documents):
print("--------Analyzing US Tax W-2 Form #{}--------".format(idx 1))
form_variant = w2.fields.get("W2FormVariant")
if form_variant:
print(
"Form variant: {} has confidence: {}".format(
form_variant.value, form_variant.confidence
)
)
tax_year = w2.fields.get("TaxYear")
if tax_year:
print(
"Tax year: {} has confidence: {}".format(
tax_year.value, tax_year.confidence
)
)
w2_copy = w2.fields.get("W2Copy")
if w2_copy:
print(
"W-2 Copy: {} has confidence: {}".format(
w2_copy.value,
w2_copy.confidence,
)
)
employee = w2.fields.get("Employee")
if employee:
print("Employee data:")
employee_name = employee.value.get("Name")
if employee_name:
print(
"...Name: {} has confidence: {}".format(
employee_name.value, employee_name.confidence
)
)
employee_ssn = employee.value.get("SocialSecurityNumber")
if employee_ssn:
print(
"...SSN: {} has confidence: {}".format(
employee_ssn.value, employee_ssn.confidence
)
)
employee_address = employee.value.get("Address")
if employee_address:
print(
"...Address: {}\n......has confidence: {}".format(
format_address_value(employee_address.value),
employee_address.confidence,
)
)
employee_zipcode = employee.value.get("ZipCode")
if employee_zipcode:
print(
"...Zipcode: {} has confidence: {}".format(
employee_zipcode.value, employee_zipcode.confidence
)
)
control_number = w2.fields.get("ControlNumber")
if control_number:
print(
"Control Number: {} has confidence: {}".format(
control_number.value, control_number.confidence
)
)
employer = w2.fields.get("Employer")
if employer:
print("Employer data:")
employer_name = employer.value.get("Name")
if employer_name:
print(
"...Name: {} has confidence: {}".format(
employer_name.value, employer_name.confidence
)
)
employer_id = employer.value.get("IdNumber")
if employer_id:
print(
"...ID Number: {} has confidence: {}".format(
employer_id.value, employer_id.confidence
)
)
employer_address = employer.value.get("Address")
if employer_address:
print(
"...Address: {}\n......has confidence: {}".format(
format_address_value(employer_address.value),
employer_address.confidence,
)
)
employer_zipcode = employer.value.get("ZipCode")
if employer_zipcode:
print(
"...Zipcode: {} has confidence: {}".format(
employer_zipcode.value, employer_zipcode.confidence
)
)
wages_tips = w2.fields.get("WagesTipsAndOtherCompensation")
if wages_tips:
print(
"Wages, tips, and other compensation: {} has confidence: {}".format(
wages_tips.value,
wages_tips.confidence,
)
)
fed_income_tax_withheld = w2.fields.get("FederalIncomeTaxWithheld")
if fed_income_tax_withheld:
print(
"Federal income tax withheld: {} has confidence: {}".format(
fed_income_tax_withheld.value, fed_income_tax_withheld.confidence
)
)
social_security_wages = w2.fields.get("SocialSecurityWages")
if social_security_wages:
print(
"Social Security wages: {} has confidence: {}".format(
social_security_wages.value, social_security_wages.confidence
)
)
social_security_tax_withheld = w2.fields.get("SocialSecurityTaxWithheld")
if social_security_tax_withheld:
print(
"Social Security tax withheld: {} has confidence: {}".format(
social_security_tax_withheld.value,
social_security_tax_withheld.confidence,
)
)
medicare_wages_tips = w2.fields.get("MedicareWagesAndTips")
if medicare_wages_tips:
print(
"Medicare wages and tips: {} has confidence: {}".format(
medicare_wages_tips.value, medicare_wages_tips.confidence
)
)
medicare_tax_withheld = w2.fields.get("MedicareTaxWithheld")
if medicare_tax_withheld:
print(
"Medicare tax withheld: {} has confidence: {}".format(
medicare_tax_withheld.value, medicare_tax_withheld.confidence
)
)
social_security_tips = w2.fields.get("SocialSecurityTips")
if social_security_tips:
print(
"Social Security tips: {} has confidence: {}".format(
social_security_tips.value, social_security_tips.confidence
)
)
allocated_tips = w2.fields.get("AllocatedTips")
if allocated_tips:
print(
"Allocated tips: {} has confidence: {}".format(
allocated_tips.value,
allocated_tips.confidence,
)
)
verification_code = w2.fields.get("VerificationCode")
if verification_code:
print(
"Verification code: {} has confidence: {}".format(
verification_code.value, verification_code.confidence
)
)
dependent_care_benefits = w2.fields.get("DependentCareBenefits")
if dependent_care_benefits:
print(
"Dependent care benefits: {} has confidence: {}".format(
dependent_care_benefits.value,
dependent_care_benefits.confidence,
)
)
non_qualified_plans = w2.fields.get("NonQualifiedPlans")
if non_qualified_plans:
print(
"Non-qualified plans: {} has confidence: {}".format(
non_qualified_plans.value,
non_qualified_plans.confidence,
)
)
additional_info = w2.fields.get("AdditionalInfo")
if additional_info:
print("Additional information:")
for item in additional_info.value:
letter_code = item.value.get("LetterCode")
if letter_code:
print(
"...Letter code: {} has confidence: {}".format(
letter_code.value, letter_code.confidence
)
)
amount = item.value.get("Amount")
if amount:
print(
"...Amount: {} has confidence: {}".format(
amount.value, amount.confidence
)
)
is_statutory_employee = w2.fields.get("IsStatutoryEmployee")
if is_statutory_employee:
print(
"Is statutory employee: {} has confidence: {}".format(
is_statutory_employee.value, is_statutory_employee.confidence
)
)
is_retirement_plan = w2.fields.get("IsRetirementPlan")
if is_retirement_plan:
print(
"Is retirement plan: {} has confidence: {}".format(
is_retirement_plan.value, is_retirement_plan.confidence
)
)
third_party_sick_pay = w2.fields.get("IsThirdPartySickPay")
if third_party_sick_pay:
print(
"Is third party sick pay: {} has confidence: {}".format(
third_party_sick_pay.value, third_party_sick_pay.confidence
)
)
other_info = w2.fields.get("Other")
if other_info:
print(
"Other information: {} has confidence: {}".format(
other_info.value,
other_info.confidence,
)
)
state_tax_info = w2.fields.get("StateTaxInfos")
if state_tax_info:
print("State Tax info:")
for tax in state_tax_info.value:
state = tax.value.get("State")
if state:
print(
"...State: {} has confidence: {}".format(
state.value, state.confidence
)
)
employer_state_id_number = tax.value.get("EmployerStateIdNumber")
if employer_state_id_number:
print(
"...Employer state ID number: {} has confidence: {}".format(
employer_state_id_number.value,
employer_state_id_number.confidence,
)
)
state_wages_tips = tax.value.get("StateWagesTipsEtc")
if state_wages_tips:
print(
"...State wages, tips, etc: {} has confidence: {}".format(
state_wages_tips.value, state_wages_tips.confidence
)
)
state_income_tax = tax.value.get("StateIncomeTax")
if state_income_tax:
print(
"...State income tax: {} has confidence: {}".format(
state_income_tax.value, state_income_tax.confidence
)
)
local_tax_info = w2.fields.get("LocalTaxInfos")
if local_tax_info:
print("Local Tax info:")
for tax in local_tax_info.value:
local_wages_tips = tax.value.get("LocalWagesTipsEtc")
if local_wages_tips:
print(
"...Local wages, tips, etc: {} has confidence: {}".format(
local_wages_tips.value, local_wages_tips.confidence
)
)
local_income_tax = tax.value.get("LocalIncomeTax")
if local_income_tax:
print(
"...Local income tax: {} has confidence: {}".format(
local_income_tax.value, local_income_tax.confidence
)
)
locality_name = tax.value.get("LocalityName")
if locality_name:
print(
"...Locality name: {} has confidence: {}".format(
locality_name.value, locality_name.confidence
)
)
print("----------------------------------------")
if __name__ == "__main__":
analyze_tax_us_w2()
請瀏覽 GitHub 上的 Azure 範例存放庫,並檢視 W-2 稅務模型輸出。
使用發票模型
import os
from azure.ai.formrecognizer import DocumentAnalysisClient
from azure.core.credentials import AzureKeyCredential
# use your `key` and `endpoint` environment variables
key = os.environ.get('FR_KEY')
endpoint = os.environ.get('FR_ENDPOINT')
# formatting function
def format_bounding_region(bounding_regions):
if not bounding_regions:
return "N/A"
return ", ".join("Page #{}: {}".format(region.page_number, format_polygon(region.polygon)) for region in bounding_regions)
# formatting function
def format_polygon(polygon):
if not polygon:
return "N/A"
return ", ".join(["[{}, {}]".format(p.x, p.y) for p in polygon])
def analyze_invoice():
invoiceUrl = "https://raw.githubusercontent.com/Azure-Samples/cognitive-services-REST-api-samples/master/curl/form-recognizer/sample-invoice.pdf"
document_analysis_client = DocumentAnalysisClient(
endpoint=endpoint, credential=AzureKeyCredential(key)
)
poller = document_analysis_client.begin_analyze_document_from_url(
"prebuilt-invoice", invoiceUrl)
invoices = poller.result()
for idx, invoice in enumerate(invoices.documents):
print("--------Recognizing invoice #{}--------".format(idx + 1))
vendor_name = invoice.fields.get("VendorName")
if vendor_name:
print(
"Vendor Name: {} has confidence: {}".format(
vendor_name.value, vendor_name.confidence
)
)
vendor_address = invoice.fields.get("VendorAddress")
if vendor_address:
print(
"Vendor Address: {} has confidence: {}".format(
vendor_address.value, vendor_address.confidence
)
)
vendor_address_recipient = invoice.fields.get("VendorAddressRecipient")
if vendor_address_recipient:
print(
"Vendor Address Recipient: {} has confidence: {}".format(
vendor_address_recipient.value, vendor_address_recipient.confidence
)
)
customer_name = invoice.fields.get("CustomerName")
if customer_name:
print(
"Customer Name: {} has confidence: {}".format(
customer_name.value, customer_name.confidence
)
)
customer_id = invoice.fields.get("CustomerId")
if customer_id:
print(
"Customer Id: {} has confidence: {}".format(
customer_id.value, customer_id.confidence
)
)
customer_address = invoice.fields.get("CustomerAddress")
if customer_address:
print(
"Customer Address: {} has confidence: {}".format(
customer_address.value, customer_address.confidence
)
)
customer_address_recipient = invoice.fields.get("CustomerAddressRecipient")
if customer_address_recipient:
print(
"Customer Address Recipient: {} has confidence: {}".format(
customer_address_recipient.value,
customer_address_recipient.confidence,
)
)
invoice_id = invoice.fields.get("InvoiceId")
if invoice_id:
print(
"Invoice Id: {} has confidence: {}".format(
invoice_id.value, invoice_id.confidence
)
)
invoice_date = invoice.fields.get("InvoiceDate")
if invoice_date:
print(
"Invoice Date: {} has confidence: {}".format(
invoice_date.value, invoice_date.confidence
)
)
invoice_total = invoice.fields.get("InvoiceTotal")
if invoice_total:
print(
"Invoice Total: {} has confidence: {}".format(
invoice_total.value, invoice_total.confidence
)
)
due_date = invoice.fields.get("DueDate")
if due_date:
print(
"Due Date: {} has confidence: {}".format(
due_date.value, due_date.confidence
)
)
purchase_order = invoice.fields.get("PurchaseOrder")
if purchase_order:
print(
"Purchase Order: {} has confidence: {}".format(
purchase_order.value, purchase_order.confidence
)
)
billing_address = invoice.fields.get("BillingAddress")
if billing_address:
print(
"Billing Address: {} has confidence: {}".format(
billing_address.value, billing_address.confidence
)
)
billing_address_recipient = invoice.fields.get("BillingAddressRecipient")
if billing_address_recipient:
print(
"Billing Address Recipient: {} has confidence: {}".format(
billing_address_recipient.value,
billing_address_recipient.confidence,
)
)
shipping_address = invoice.fields.get("ShippingAddress")
if shipping_address:
print(
"Shipping Address: {} has confidence: {}".format(
shipping_address.value, shipping_address.confidence
)
)
shipping_address_recipient = invoice.fields.get("ShippingAddressRecipient")
if shipping_address_recipient:
print(
"Shipping Address Recipient: {} has confidence: {}".format(
shipping_address_recipient.value,
shipping_address_recipient.confidence,
)
)
print("Invoice items:")
for idx, item in enumerate(invoice.fields.get("Items").value):
print("...Item #{}".format(idx + 1))
item_description = item.value.get("Description")
if item_description:
print(
"......Description: {} has confidence: {}".format(
item_description.value, item_description.confidence
)
)
item_quantity = item.value.get("Quantity")
if item_quantity:
print(
"......Quantity: {} has confidence: {}".format(
item_quantity.value, item_quantity.confidence
)
)
unit = item.value.get("Unit")
if unit:
print(
"......Unit: {} has confidence: {}".format(
unit.value, unit.confidence
)
)
unit_price = item.value.get("UnitPrice")
if unit_price:
print(
"......Unit Price: {} has confidence: {}".format(
unit_price.value, unit_price.confidence
)
)
product_code = item.value.get("ProductCode")
if product_code:
print(
"......Product Code: {} has confidence: {}".format(
product_code.value, product_code.confidence
)
)
item_date = item.value.get("Date")
if item_date:
print(
"......Date: {} has confidence: {}".format(
item_date.value, item_date.confidence
)
)
tax = item.value.get("Tax")
if tax:
print(
"......Tax: {} has confidence: {}".format(tax.value, tax.confidence)
)
amount = item.value.get("Amount")
if amount:
print(
"......Amount: {} has confidence: {}".format(
amount.value, amount.confidence
)
)
subtotal = invoice.fields.get("SubTotal")
if subtotal:
print(
"Subtotal: {} has confidence: {}".format(
subtotal.value, subtotal.confidence
)
)
total_tax = invoice.fields.get("TotalTax")
if total_tax:
print(
"Total Tax: {} has confidence: {}".format(
total_tax.value, total_tax.confidence
)
)
previous_unpaid_balance = invoice.fields.get("PreviousUnpaidBalance")
if previous_unpaid_balance:
print(
"Previous Unpaid Balance: {} has confidence: {}".format(
previous_unpaid_balance.value, previous_unpaid_balance.confidence
)
)
amount_due = invoice.fields.get("AmountDue")
if amount_due:
print(
"Amount Due: {} has confidence: {}".format(
amount_due.value, amount_due.confidence
)
)
service_start_date = invoice.fields.get("ServiceStartDate")
if service_start_date:
print(
"Service Start Date: {} has confidence: {}".format(
service_start_date.value, service_start_date.confidence
)
)
service_end_date = invoice.fields.get("ServiceEndDate")
if service_end_date:
print(
"Service End Date: {} has confidence: {}".format(
service_end_date.value, service_end_date.confidence
)
)
service_address = invoice.fields.get("ServiceAddress")
if service_address:
print(
"Service Address: {} has confidence: {}".format(
service_address.value, service_address.confidence
)
)
service_address_recipient = invoice.fields.get("ServiceAddressRecipient")
if service_address_recipient:
print(
"Service Address Recipient: {} has confidence: {}".format(
service_address_recipient.value,
service_address_recipient.confidence,
)
)
remittance_address = invoice.fields.get("RemittanceAddress")
if remittance_address:
print(
"Remittance Address: {} has confidence: {}".format(
remittance_address.value, remittance_address.confidence
)
)
remittance_address_recipient = invoice.fields.get("RemittanceAddressRecipient")
if remittance_address_recipient:
print(
"Remittance Address Recipient: {} has confidence: {}".format(
remittance_address_recipient.value,
remittance_address_recipient.confidence,
)
)
print("----------------------------------------")
if __name__ == "__main__":
analyze_invoice()
請瀏覽 GitHub 上的 Azure 範例存放庫,並檢視 發票模型輸出。
使用收據模型
import os
from azure.ai.formrecognizer import DocumentAnalysisClient
from azure.core.credentials import AzureKeyCredential
# use your `key` and `endpoint` environment variables
key = os.environ.get('FR_KEY')
endpoint = os.environ.get('FR_ENDPOINT')
def analyze_receipts():
# sample document
receiptUrl = "https://raw.githubusercontent.com/Azure-Samples/cognitive-services-REST-api-samples/master/curl/form-recognizer/rest-api/receipt.png"
document_analysis_client = DocumentAnalysisClient(
endpoint=endpoint, credential=AzureKeyCredential(key)
)
poller = document_analysis_client.begin_analyze_document_from_url(
"prebuilt-receipt", receiptUrl, locale="en-US"
)
receipts = poller.result()
for idx, receipt in enumerate(receipts.documents):
print("--------Analysis of receipt #{}--------".format(idx 1))
print("Receipt type: {}".format(receipt.doc_type or "N/A"))
merchant_name = receipt.fields.get("MerchantName")
if merchant_name:
print(
"Merchant Name: {} has confidence: {}".format(
merchant_name.value, merchant_name.confidence
)
)
transaction_date = receipt.fields.get("TransactionDate")
if transaction_date:
print(
"Transaction Date: {} has confidence: {}".format(
transaction_date.value, transaction_date.confidence
)
)
if receipt.fields.get("Items"):
print("Receipt items:")
for idx, item in enumerate(receipt.fields.get("Items").value):
print("...Item #{}".format(idx 1))
item_description = item.value.get("Description")
if item_description:
print(
"......Item Description: {} has confidence: {}".format(
item_description.value, item_description.confidence
)
)
item_quantity = item.value.get("Quantity")
if item_quantity:
print(
"......Item Quantity: {} has confidence: {}".format(
item_quantity.value, item_quantity.confidence
)
)
item_price = item.value.get("Price")
if item_price:
print(
"......Individual Item Price: {} has confidence: {}".format(
item_price.value, item_price.confidence
)
)
item_total_price = item.value.get("TotalPrice")
if item_total_price:
print(
"......Total Item Price: {} has confidence: {}".format(
item_total_price.value, item_total_price.confidence
)
)
subtotal = receipt.fields.get("Subtotal")
if subtotal:
print(
"Subtotal: {} has confidence: {}".format(
subtotal.value, subtotal.confidence
)
)
tax = receipt.fields.get("TotalTax")
if tax:
print("Total tax: {} has confidence: {}".format(tax.value, tax.confidence))
tip = receipt.fields.get("Tip")
if tip:
print("Tip: {} has confidence: {}".format(tip.value, tip.confidence))
total = receipt.fields.get("Total")
if total:
print("Total: {} has confidence: {}".format(total.value, total.confidence))
print("--------------------------------------")
if __name__ == "__main__":
analyze_receipts()
請瀏覽 GitHub 上的 Azure 範例存放庫,並檢視 收據模型輸出。
使用身分證件模型
import os
from azure.ai.formrecognizer import DocumentAnalysisClient
from azure.core.credentials import AzureKeyCredential
# use your `key` and `endpoint` environment variables
key = os.environ.get('FR_KEY')
endpoint = os.environ.get('FR_ENDPOINT')
def analyze_identity_documents():
# sample document
identityUrl = "https://raw.githubusercontent.com/Azure-Samples/cognitive-services-REST-api-samples/master/curl/form-recognizer/rest-api/identity_documents.png"
document_analysis_client = DocumentAnalysisClient(
endpoint=endpoint, credential=AzureKeyCredential(key)
)
poller = document_analysis_client.begin_analyze_document_from_url(
"prebuilt-idDocument", identityUrl
)
id_documents = poller.result()
for idx, id_document in enumerate(id_documents.documents):
print("--------Analyzing ID document #{}--------".format(idx + 1))
first_name = id_document.fields.get("FirstName")
if first_name:
print(
"First Name: {} has confidence: {}".format(
first_name.value, first_name.confidence
)
)
last_name = id_document.fields.get("LastName")
if last_name:
print(
"Last Name: {} has confidence: {}".format(
last_name.value, last_name.confidence
)
)
document_number = id_document.fields.get("DocumentNumber")
if document_number:
print(
"Document Number: {} has confidence: {}".format(
document_number.value, document_number.confidence
)
)
dob = id_document.fields.get("DateOfBirth")
if dob:
print(
"Date of Birth: {} has confidence: {}".format(dob.value, dob.confidence)
)
doe = id_document.fields.get("DateOfExpiration")
if doe:
print(
"Date of Expiration: {} has confidence: {}".format(
doe.value, doe.confidence
)
)
sex = id_document.fields.get("Sex")
if sex:
print("Sex: {} has confidence: {}".format(sex.value, sex.confidence))
address = id_document.fields.get("Address")
if address:
print(
"Address: {} has confidence: {}".format(
address.value, address.confidence
)
)
country_region = id_document.fields.get("CountryRegion")
if country_region:
print(
"Country/Region: {} has confidence: {}".format(
country_region.value, country_region.confidence
)
)
region = id_document.fields.get("Region")
if region:
print(
"Region: {} has confidence: {}".format(region.value, region.confidence)
)
print("--------------------------------------")
if __name__ == "__main__":
analyze_identity_documents()
請瀏覽 GitHub 上的 Azure 範例存放庫,並檢視 識別碼檔案模型輸出。
使用名片模型
import os
from azure.ai.formrecognizer import DocumentAnalysisClient
from azure.core.credentials import AzureKeyCredential
# use your `key` and `endpoint` environment variables
key = os.environ.get('FR_KEY')
endpoint = os.environ.get('FR_ENDPOINT')
def analyze_business_card():
# sample document
businessCardUrl = "https://raw.githubusercontent.com/Azure-Samples/cognitive-services-REST-api-samples/de5e0d8982ab754823c54de47a47e8e499351523/curl/form-recognizer/rest-api/business_card.jpg"
document_analysis_client = DocumentAnalysisClient(
endpoint=endpoint, credential=AzureKeyCredential(key)
)
poller = document_analysis_client.begin_analyze_document_from_url(
"prebuilt-businessCard", businessCardUrl, locale="en-US"
)
business_cards = poller.result()
for idx, business_card in enumerate(business_cards.documents):
print("--------Analyzing business card #{}--------".format(idx + 1))
contact_names = business_card.fields.get("ContactNames")
if contact_names:
for contact_name in contact_names.value:
print(
"Contact First Name: {} has confidence: {}".format(
contact_name.value["FirstName"].value,
contact_name.value[
"FirstName"
].confidence,
)
)
print(
"Contact Last Name: {} has confidence: {}".format(
contact_name.value["LastName"].value,
contact_name.value[
"LastName"
].confidence,
)
)
company_names = business_card.fields.get("CompanyNames")
if company_names:
for company_name in company_names.value:
print(
"Company Name: {} has confidence: {}".format(
company_name.value, company_name.confidence
)
)
departments = business_card.fields.get("Departments")
if departments:
for department in departments.value:
print(
"Department: {} has confidence: {}".format(
department.value, department.confidence
)
)
job_titles = business_card.fields.get("JobTitles")
if job_titles:
for job_title in job_titles.value:
print(
"Job Title: {} has confidence: {}".format(
job_title.value, job_title.confidence
)
)
emails = business_card.fields.get("Emails")
if emails:
for email in emails.value:
print(
"Email: {} has confidence: {}".format(email.value, email.confidence)
)
websites = business_card.fields.get("Websites")
if websites:
for website in websites.value:
print(
"Website: {} has confidence: {}".format(
website.value, website.confidence
)
)
addresses = business_card.fields.get("Addresses")
if addresses:
for address in addresses.value:
print(
"Address: {} has confidence: {}".format(
address.value, address.confidence
)
)
mobile_phones = business_card.fields.get("MobilePhones")
if mobile_phones:
for phone in mobile_phones.value:
print(
"Mobile phone number: {} has confidence: {}".format(
phone.content, phone.confidence
)
)
faxes = business_card.fields.get("Faxes")
if faxes:
for fax in faxes.value:
print(
"Fax number: {} has confidence: {}".format(
fax.content, fax.confidence
)
)
work_phones = business_card.fields.get("WorkPhones")
if work_phones:
for work_phone in work_phones.value:
print(
"Work phone number: {} has confidence: {}".format(
work_phone.content, work_phone.confidence
)
)
other_phones = business_card.fields.get("OtherPhones")
if other_phones:
for other_phone in other_phones.value:
print(
"Other phone number: {} has confidence: {}".format(
other_phone.value, other_phone.confidence
)
)
print("--------------------------------------")
if __name__ == "__main__":
analyze_business_card()
請瀏覽 GitHub 上的 Azure 範例存放庫,並檢視 名片模型輸出。
備註
此專案會使用 cURL 命令行工具來執行 REST API 呼叫。
| 文件智慧服務 REST API (部分內容可能是機器或 AI 翻譯) | 支援的 Azure SDK
(部分內容可能是機器或 AI 翻譯)
先決條件
Azure 訂用帳戶 - 免費建立一個訂用帳戶。
已安裝 cURL 命令行工具。 Windows 10 和 Windows 11 隨附 cURL 的複本。 在命令提示字元中,輸入下列 cURL 命令。 如果說明選項顯示,cURL 會安裝在 Windows 環境中。
curl -help
如果未安裝 cURL,您可以在這裡取得:
Azure AI 服務或文件智慧服務資源。 建立 單一服務 或 多服務。 您可以使用免費定價層 (
F0
) 來試用服務,之後可升級至付費層以用於實際執行環境。從您所建立資源的金鑰和端點,將應用程式連線至 Azure 文件智慧服務。
- 部署資源之後,請選取 [前往資源]。
- 在左側導覽功能表中,選取 [金鑰和端點]。
- 複製其中一個金鑰和 端點,以供本文稍後使用。
設定環境變數
若要與此文件智慧服務互動,您必須建立 DocumentAnalysisClient
類別的執行個體。 若要這樣做,請使用 Azure 入口網站中的 key
和 endpoint
具現化用戶端。 針對此專案,請使用環境變數來儲存和存取認證。
這很重要
請謹慎使用 API 金鑰。 請勿在程式碼中直接包含 API 金鑰,且切勿公開張貼金鑰。 如果您使用 API 金鑰,請安全地將其儲存在 Azure 金鑰保存庫。 如需在應用程式中安全地使用 API 金鑰的詳細資訊,請參閱搭配 Azure 金鑰保存庫 的 API 金鑰。
如需 AI 服務安全性的詳細資訊,請參閱驗證對 Azure AI 服務的要求。
若要設定 Document Intelligence 資源金鑰的環境變數,請開啟主控台視窗,並遵循作系統和開發環境的指示。 將 <yourKey> 和 <yourEndpoint> 取代為 Azure 入口網站中資源的值。
Windows 中的環境變數不會區分大小寫。 它們通常會以大寫方式宣告,單字之間以底線連結。 在命令提示字元中,執行下列命令:
設定您的金鑰變數:
setx DI_KEY <yourKey>
設定您的端點變數
setx DI_ENDPOINT <yourEndpoint>
設定環境變數之後,請關閉 [命令提示字元] 視窗。 值會維持不變,直到您再次變更這些值為止。
重新啟動讀取環境變數的任何執行中程式。 例如,如果您使用 Visual Studio 或 Visual Studio Code 作為編輯器,請在執行範例程式代碼之前重新啟動。
以下是搭配環境變數使用的一些更實用的命令:
命令 | 動作 | 範例 |
---|---|---|
setx VARIABLE_NAME= |
將值設定為空字串,以刪除環境變數。 | setx DI_KEY= |
setx VARIABLE_NAME=value |
設定或變更環境變數的值。 | setx DI_KEY=<yourKey> |
set VARIABLE_NAME |
顯示特定環境變數的值。 | set DI_KEY |
set |
顯示所有環境變數。 | set |
分析文件並取得結果
POST 要求可用來以預建或自訂模型分析文件。 GET 要求可用來擷取文件分析呼叫的結果。 modelId
用於 POST 作業,resultId
則用於 GET 作業。
使用下表作為參考。 將 <modelId> 和 <document-url> 取代為您所需的值:
型號 | modelId | 說明 | document-url |
---|---|---|---|
Read 模型 | prebuilt-read | 樣本手冊 | https://raw.githubusercontent.com/Azure-Samples/cognitive-services-REST-api-samples/master/curl/form-recognizer/rest-api/read.png |
版面配置模型 | 預設佈局 | 預約確認範例 | https://raw.githubusercontent.com/Azure-Samples/cognitive-services-REST-api-samples/master/curl/form-recognizer/rest-api/layout.png |
W-2 表單模型 | prebuilt-tax.us.w2 | 範例 W-2 表單 | https://raw.githubusercontent.com/Azure-Samples/cognitive-services-REST-api-samples/master/curl/form-recognizer/rest-api/w2.png |
發票模型 | prebuilt-invoice | 發票範例 | https://github.com/Azure-Samples/cognitive-services-REST-api-samples/raw/master/curl/form-recognizer/rest-api/invoice.pdf |
收據模型 | prebuilt-receipt | 範例收據 | https://raw.githubusercontent.com/Azure-Samples/cognitive-services-REST-api-samples/master/curl/form-recognizer/rest-api/receipt.png |
識別碼文件模型 | prebuilt-idDocument | 範例標識碼檔 | https://raw.githubusercontent.com/Azure-Samples/cognitive-services-REST-api-samples/master/curl/form-recognizer/rest-api/identity_documents.png |
POST 要求
開啟bash視窗並執行下列 cURL 命令。 這些命令包含先前在設定環境變數區段中建立的端點和主要環境變數。 如果您的變數名稱不同,請取代這些變數。 請記得取代 <modelId> 和 <document-url> 參數。
curl -i -X POST "POST {endpoint}/documentintelligence/documentModels/{modelId}:analyze?_overload=analyzeDocument&api-version=2024-11-30" -H "Content-Type: application/json" -H "Ocp-Apim-Subscription-Key: {DI_KEY}" --data-ascii "{'urlSource': '<document-url>'}"
若要啟用附加元件功能,請使用POST要求中的 features
查詢參數。 2023-07-31
(GA)和之後的版本提供四項附加功能:ocr.highResolution、ocr.formula、ocr.font和 queryFields.premium。 若要深入瞭解每個功能,請參閱 自定義模型。
您只能呼叫 Read 和 Layout 模型的 highResolution、公式和字型功能,以及一般文件模型的 queryFields 功能。 下列範例示範如何呼叫 Layout 模型的 highResolution、公式和字型功能。
curl -i -X POST "{endpoint}/documentintelligence/documentModels/prebuilt-layout:analyze?features=ocr.highResolution,ocr.formula,ocr.font?api-version=2024-11-30" -H "Content-Type: application/json" -H "Ocp-Apim-Subscription-Key: {DI_KEY}" --data-ascii "{'urlSource': '<document-url>'}"
POST 回應
您收到 202 (Success)
回應,其中包含 Operation-location
標頭。 使用這個標頭的值來擷取響應結果。
取得分析結果 (GET 請求)
呼叫 Analyze document
API 之後,請呼叫 Get analyze
結果 API,以取得作業的狀態和擷取的數據。
cURL 命令行工具不會格式化包含 JSON 內容的 API 回應,這會使內容難以讀取。 若要設定 JSON 回應的格式,請包括直立線符號字元,後面接著具有 GET 要求的 JSON 格式設定工具。
使用 Node.js json 工具 作為 cURL 的 JSON 格式器。 如果您沒有安裝 Node.js,請下載並安裝最新版本。
開啟 bash 視窗,並使用下列命令安裝 json 工具:
npm install -g jsontool
包括直立線符號字元
| json
與 GET 要求,以最適當地列印 JSON 輸出。curl -i -X GET "<endpoint>documentintelligence/documentModels/prebuilt-read/analyzeResults/0e49604a-2d8e-4b15-b6b8-bb456e5d3e0a?api-version=2024-11-30"-H "Ocp-Apim-Subscription-Key: <subscription key>" | json
GET 要求
執行下列命令之前,請進行下列變更:
- 將 <POST 回應>取代為
Operation-location
中的 標頭。 - 如果 <DI_KEY 與程式代碼中的名稱不同,請將其替換為您的環境變數。
- 將 *<json-tool> 取代為您的 JSON 格式設定工具。
curl -i -X GET "<POST response>" -H "Ocp-Apim-Subscription-Key: {DI_KEY}" | `<json-tool>`
檢查回應
您收到具有 JSON 輸出的 200 (Success)
回應。 第一個 status
欄位會指出作業的狀態。 如果工作未完成,則的值 status
為 running
或 notStarted
。 手動或透過腳本再次呼叫 API。 我們建議您在每次呼叫之間間隔一秒或更長的時間。
請瀏覽 GitHub 上的 Azure 範例存放庫,以檢視每個檔案智慧模型的 GET
回應:
型號 | 輸出 URL |
---|---|
Read 模型 | Read 模型輸出 (英文) |
版面配置模型 | Layout 模型輸出 (英文) |
W-2 稅制模型 | W-2 稅務模型輸出 (英文) |
發票模型 | 發票模型輸出 (英文) |
收據模型 | 收據模型輸出 |
識別碼文件模型 | 身分證明文件模型輸出 (英文) |
| 文件智慧服務 REST API (部分內容可能是機器或 AI 翻譯) | 支援的 Azure SDKS (部分內容可能是機器或 AI 翻譯) |
| 文件智慧服務 REST API (部分內容可能是機器或 AI 翻譯) | 支援的 Azure SDKS (部分內容可能是機器或 AI 翻譯) |
備註
此專案會使用 cURL
命令行工具來執行 REST API 呼叫。
先決條件
Azure 訂用帳戶 - 免費建立一個訂用帳戶。
已安裝 cURL 命令行工具。 Windows 10 和 Windows 11 隨附 cURL 的複本。 在命令提示字元中,輸入下列 cURL 命令。 如果說明選項顯示,cURL 會安裝在 Windows 環境中。
curl -help
如果未安裝 cURL,您可以在這裡取得:
Azure AI 服務或文件智慧服務資源。 建立 單一服務 或 多服務。 您可以使用免費定價層 (
F0
) 來試用服務,之後可升級至付費層以用於實際執行環境。從您所建立資源的金鑰和端點,將應用程式連線至 Azure 文件智慧服務。
- 部署資源之後,請選取 [前往資源]。
- 在左側導覽功能表中,選取 [金鑰和端點]。
- 複製其中一個金鑰和 端點,以供本文稍後使用。
設定環境變數
若要與此文件智慧服務互動,您必須建立 DocumentAnalysisClient
類別的執行個體。 若要這樣做,請使用 Azure 入口網站中的 key
和 endpoint
具現化用戶端。 針對此專案,請使用環境變數來儲存和存取認證。
這很重要
請謹慎使用 API 金鑰。 請勿在程式碼中直接包含 API 金鑰,且切勿公開張貼金鑰。 如果您使用 API 金鑰,請安全地將其儲存在 Azure 金鑰保存庫。 如需在應用程式中安全地使用 API 金鑰的詳細資訊,請參閱搭配 Azure 金鑰保存庫 的 API 金鑰。
如需 AI 服務安全性的詳細資訊,請參閱驗證對 Azure AI 服務的要求。
若要設定 Document Intelligence 資源金鑰的環境變數,請開啟主控台視窗,並遵循作系統和開發環境的指示。 將 <yourKey> 和 <yourEndpoint> 取代為 Azure 入口網站中資源的值。
Windows 中的環境變數不會區分大小寫。 它們通常會以大寫方式宣告,單字之間以底線連結。 在命令提示字元中,執行下列命令:
設定您的金鑰變數:
setx DI_KEY <yourKey>
設定您的端點變數
setx DI_ENDPOINT <yourEndpoint>
設定環境變數之後,請關閉 [命令提示字元] 視窗。 值會維持不變,直到您再次變更這些值為止。
重新啟動讀取環境變數的任何執行中程式。 例如,如果您使用 Visual Studio 或 Visual Studio Code 作為編輯器,請在執行範例程式代碼之前重新啟動。
以下是搭配環境變數使用的一些更實用的命令:
命令 | 動作 | 範例 |
---|---|---|
setx VARIABLE_NAME= |
將值設定為空字串,以刪除環境變數。 | setx DI_KEY= |
setx VARIABLE_NAME=value |
設定或變更環境變數的值。 | setx DI_KEY=<yourKey> |
set VARIABLE_NAME |
顯示特定環境變數的值。 | set DI_KEY |
set |
顯示所有環境變數。 | set |
分析文件並取得結果
POST 要求可用來以預建或自訂模型分析文件。 GET 要求可用來擷取文件分析呼叫的結果。 modelId
用於 POST 作業,resultId
則用於 GET 作業。
使用下表作為參考。 將 <modelId> 和 <document-url> 取代為您所需的值:
型號 | modelId | 說明 | document-url |
---|---|---|---|
Read 模型 | prebuilt-read | 樣本手冊 | https://raw.githubusercontent.com/Azure-Samples/cognitive-services-REST-api-samples/master/curl/form-recognizer/rest-api/read.png |
版面配置模型 | 預設佈局 | 預約確認範例 | https://raw.githubusercontent.com/Azure-Samples/cognitive-services-REST-api-samples/master/curl/form-recognizer/rest-api/layout.png |
W-2 表單模型 | prebuilt-tax.us.w2 | 範例 W-2 表單 | https://raw.githubusercontent.com/Azure-Samples/cognitive-services-REST-api-samples/master/curl/form-recognizer/rest-api/w2.png |
發票模型 | prebuilt-invoice | 發票範例 | https://github.com/Azure-Samples/cognitive-services-REST-api-samples/raw/master/curl/form-recognizer/rest-api/invoice.pdf |
收據模型 | prebuilt-receipt | 範例收據 | https://raw.githubusercontent.com/Azure-Samples/cognitive-services-REST-api-samples/master/curl/form-recognizer/rest-api/receipt.png |
識別碼文件模型 | prebuilt-idDocument | 範例標識碼檔 | https://raw.githubusercontent.com/Azure-Samples/cognitive-services-REST-api-samples/master/curl/form-recognizer/rest-api/identity_documents.png |
POST 要求
開啟主控台視窗,然後執行下列 cURL 命令: 這些命令包含先前在設定環境變數區段中建立的端點和主要環境變數。 如果您的變數名稱不同,請取代這些變數。 請記得取代 <modelId> 和 <document-url> 參數。
curl -i -X POST "%FR_ENDPOINT%formrecognizer/documentModels/<modelId>:analyze?api-version=2023-07-31" -H "Content-Type: application/json" -H "Ocp-Apim-Subscription-Key: %FR_KEY%" --data-ascii "{'urlSource': '<document-url>'}"
若要啟用附加元件功能,請使用POST要求中的 features
查詢參數。 2023-07-31
(GA) 版本提供四項附加元件功能:ocr.highResolution、ocr.formula、ocr.font,以及 queryFields.premium。 若要深入瞭解每個功能,請參閱 自定義模型。
您只能呼叫 Read 和 Layout 模型的 highResolution、公式和字型功能,以及一般文件模型的 queryFields 功能。 下列範例示範如何呼叫 Layout 模型的 highResolution、公式和字型功能。
curl -i -X POST "%FR_ENDPOINT%formrecognizer/documentModels/prebuilt-layout:analyze?features=ocr.highResolution,ocr.formula,ocr.font?api-version=2023-07-31" -H "Content-Type: application/json" -H "Ocp-Apim-Subscription-Key: %FR_KEY%" --data-ascii "{'urlSource': '<document-url>'}"
POST 回應
您收到 202 (Success)
回應,其中包含 Operation-location
標頭。 使用這個標頭的值來擷取響應結果。
取得分析結果 (GET 請求)
呼叫 Analyze document
API 之後,請呼叫 [Get analyze
result}(/rest/api/aiservices/document-models/get-analyze-result?view=rest-aiservices-2023-07-31&preserve-view=true&tabs=HTTP) API,以取得作業和擷取數據的狀態。
cURL 命令行工具不會格式化包含 JSON 內容的 API 回應,這會使內容難以讀取。 若要設定 JSON 回應的格式,請包括直立線符號字元,後面接著具有 GET 要求的 JSON 格式設定工具。
使用 Node.js json 工具 作為 cURL 的 JSON 格式器。 如果您沒有安裝 Node.js,請下載並安裝最新版本。
開啟主控台視窗,並使用下列命令安裝 json 工具:
npm install -g jsontool
包括直立線符號字元
| json
與 GET 要求,以最適當地列印 JSON 輸出。curl -i -X GET "<endpoint>formrecognizer/documentModels/prebuilt-read/analyzeResults/0e49604a-2d8e-4b15-b6b8-bb456e5d3e0a?api-version=2023-07-31"-H "Ocp-Apim-Subscription-Key: <subscription key>" | json
GET 要求
執行下列命令之前,請進行下列變更:
- 將 <POST 回應>取代為
Operation-location
中的 標頭。 - 如果與程式碼中的名稱不同,請將 <FR_KEY 取代為您環境變數的變數。
- 將 *<json-tool> 取代為您的 JSON 格式設定工具。
curl -i -X GET "<POST response>" -H "Ocp-Apim-Subscription-Key: %FR_KEY%" | `<json-tool>`
檢查回應
您收到具有 JSON 輸出的 200 (Success)
回應。 第一個 status
欄位會指出作業的狀態。 如果工作未完成,則的值 status
為 running
或 notStarted
。 手動或透過腳本再次呼叫 API。 我們建議您在每次呼叫之間間隔一秒或更長的時間。
請瀏覽 GitHub 上的 Azure 範例存放庫,以檢視每個檔案智慧模型的 GET
回應:
型號 | 輸出 URL |
---|---|
Read 模型 | Read 模型輸出 (英文) |
版面配置模型 | Layout 模型輸出 (英文) |
W-2 稅制模型 | W-2 稅務模型輸出 (英文) |
發票模型 | 發票模型輸出 (英文) |
收據模型 | 收據模型輸出 |
識別碼文件模型 | 身分證明文件模型輸出 (英文) |
後續步驟
祝賀! 您已瞭解如何使用文件智慧模型,以不同方式分析各種檔。 接下來,探索 Document Intelligence Studio 和參考文件。
在這份指南中,您將瞭解如何將文件智能添加至應用程式和工作流程。 使用您選擇的程式設計語言或 REST API。 Azure AI 檔智慧是雲端式 Azure AI 服務,使用機器學習從您的檔擷取索引鍵/值組、文字和數據表。 建議您在了解技術時使用免費服務。 請記住,免費的頁數限制為每個月 500 頁。
您可以使用下列 API 從表單與檔案擷取結構化資料:
這很重要
此項目的目標是 Document Intelligence REST API v2.1。
本文中的程式代碼會使用同步方法和未受保護的認證記憶體。
參考文件 | 程式庫來源程式碼 | 套件 (NuGet) | 範例
先決條件
Azure 訂用帳戶 - 免費建立一個訂用帳戶。
Visual Studio IDE 或目前版本的 .NET Core。
包含一組訓練資料的 Azure 儲存 Blob。 如需組合您的訓練數據集的提示和選項,請參閱 建置和訓練自定義模型。 在此專案中,您可以使用 Train 資料夾中的檔案,這些檔案位於 範例數據集下。 下載並擷取 sample_data.zip。
智慧資源。 您可以使用免費定價層 (
F0
) 來試用服務,之後可升級至付費層以用於實際執行環境。從您所建立資源的金鑰和端點,將應用程式連線至 Azure 文件智慧服務。
- 部署資源之後,請選取 [前往資源]。
- 在左側導覽功能表中,選取 [金鑰和端點]。
- 複製其中一個金鑰和 端點,以供本文稍後使用。
設定程式設計環境
在主控台視窗中,使用 dotnet new
命令建立名為 formrecognizer-project
的新主控台應用程式。 此命令會建立簡單的 "Hello World" C# 專案,內含單一原始程式檔:program.cs。
dotnet new console -n formrecognizer-project
將目錄變更為新建立的應用程式資料夾。 您可以使用下列命令建置應用程式:
dotnet build
建置輸出應該不會有警告或錯誤。
...
Build succeeded.
0 Warning(s)
0 Error(s)
...
安裝用戶端程式庫
在應用程式目錄中,使用下列命令安裝適用於 .NET 的 Document Intelligence 用戶端連結庫:
dotnet add package Azure.AI.FormRecognizer --version 3.1.1
從項目目錄中,在編輯器或 IDE 中開啟 Program.cs 檔案。 新增下列 using
指示詞:
using Azure;
using Azure.AI.FormRecognizer;
using Azure.AI.FormRecognizer.Models;
using Azure.AI.FormRecognizer.Training;
using System;
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
在應用程式的 Program
類別中,為資源的密鑰和端點建立變數。
這很重要
前往 Azure 入口網站。 如果已成功部署您在 [必要條件] 區段中所建立的文件智慧服務資源,請選取 [後續步驟] 下的 [前往資源] 按鈕。 在左側導覽功能表中,在 [資源管理] 底下,選取 [[金鑰] 和 [端點]。
當您完成時,請記得從程式碼中移除金鑰。 永遠不要公開發佈它。 針對生產環境,請使用安全方法來儲存和存取您的認證。 如需詳細資訊,請參閱 Azure AI 服務安全性。
private static readonly string endpoint = "PASTE_YOUR_FORM_RECOGNIZER_ENDPOINT_HERE";
private static readonly string apiKey = "PASTE_YOUR_FORM_RECOGNIZER_SUBSCRIPTION_KEY_HERE";
private static readonly AzureKeyCredential credential = new AzureKeyCredential(apiKey);
在應用程式的 Main
方法中,新增對這個專案中使用的異步工作的呼叫:
static void Main(string[] args) {
// new code:
var recognizeContent = RecognizeContent(recognizerClient);
Task.WaitAll(recognizeContent);
var analyzeReceipt = AnalyzeReceipt(recognizerClient, receiptUrl);
Task.WaitAll(analyzeReceipt);
var analyzeBusinessCard = AnalyzeBusinessCard(recognizerClient, bcUrl);
Task.WaitAll(analyzeBusinessCard);
var analyzeInvoice = AnalyzeInvoice(recognizerClient, invoiceUrl);
Task.WaitAll(analyzeInvoice);
var analyzeId = AnalyzeId(recognizerClient, idUrl);
Task.WaitAll(analyzeId);
var trainModel = TrainModel(trainingClient, trainingDataUrl);
Task.WaitAll(trainModel);
var trainModelWithLabels = TrainModelWithLabels(trainingClient, trainingDataUrl);
Task.WaitAll(trainModel);
var analyzeForm = AnalyzePdfForm(recognizerClient, modelId, formUrl);
Task.WaitAll(analyzeForm);
var manageModels = ManageModels(trainingClient, trainingDataUrl);
Task.WaitAll(manageModels);
}
使用物件模型
使用文件智慧,您可以建立兩種不同的客戶端類型。 第一個是 FormRecognizerClient
,會查詢服務,以辨識出表單欄位和內容。 第二個 FormTrainingClient
會建立及管理自定義模型,以改善辨識。
FormRecognizerClient
提供下列作業:
- 使用定型的自定義模型來分析自定義表單,來辨識表單域和內容。 這些值會在
RecognizedForm
物件的集合中傳回。 請參閱使用自訂模型分析表單。 - 辨識表單內容,包括表格、線條和文字,而不需要訓練模型。 表單內容會在
FormPage
物件的集合中傳回。 請參閱分析版面配置。 - 使用文件智慧服務的預先定型模型,辨識來自美國收據、名片、發票和標識符檔的通用字段。
FormTrainingClient
會提供作業以:
- 定型自定義模型,以分析自定義表單中找到的所有欄位和值。 傳回
CustomFormModel
,指出模型所分析的表單類型,以及針對每個表單類型擷取的欄位。 - 將自定義模型定型,以分析您透過標記自定義表單所指定的特定欄位和值。 傳回
CustomFormModel
,指出模型擷取的欄位,以及每個欄位的估計精確度。 - 管理在您的帳戶中建立的模型。
- 將自定義模型從一個 Document Intelligence 資源複製到另一個資源。
備註
模型也可以使用圖形使用者介面來定型,例如 範例卷標工具。
驗證用戶端
在 Main
下,建立名為 AuthenticateClient
的方法。 在其他工作中使用此方法,向 Document Intelligence 服務驗證您的要求。 此方法會使用 AzureKeyCredential
物件,因此如有需要,您可以更新密鑰而不建立新的客戶端物件。
private static FormRecognizerClient AuthenticateClient()
{
var credential = new AzureKeyCredential(apiKey);
var client = new FormRecognizerClient(new Uri(endpoint), credential);
return client;
}
針對驗證訓練用戶端的新方法,重複這些步驟。
static private FormTrainingClient AuthenticateTrainingClient()
{
var credential = new AzureKeyCredential(apiKey);
var client = new FormTrainingClient(new Uri(endpoint), credential);
return client;
}
取得用於測試的資產
您也需要為訓練和測試資料新增 URL 的參考。 將這些參考新增至 Program
類別的根目錄。
若要擷取自定義模型定型數據的SAS URL,請移至 Azure 入口網站中的記憶體資源,然後選取 [資料記憶體]>[容器]。
瀏覽至您的容器,按下滑鼠右鍵,然後選取 產生 SAS。
取得您容器的 SAS,而不是儲存體帳戶本身的 SAS。
請確定已選取 讀取、寫入、刪除和 列出 許可權,然後選取 產生 SAS 令牌和 URL。
將 [URL] 區段中的值複製到暫存位置。 其格式應該為:
https://<storage account>.blob.core.windows.net/<container name>?<SAS value>
。
重複上述步驟,以取得 Blob 記憶體容器中個別檔的 SAS URL。 將SAS URL儲存至暫存位置。
儲存所包含範例影像的 URL。 該映像也可在 GitHub取得。
string trainingDataUrl = "PASTE_YOUR_SAS_URL_OF_YOUR_FORM_FOLDER_IN_BLOB_STORAGE_HERE";
string formUrl = "PASTE_YOUR_FORM_RECOGNIZER_FORM_URL_HERE";
string receiptUrl = "https://docs.microsoft.com/azure/cognitive-services/form-recognizer/media" + "/contoso-allinone.jpg";
string bcUrl = "https://raw.githubusercontent.com/Azure/azure-sdk-for-python/master/sdk/formrecognizer/azure-ai-formrecognizer/samples/sample_forms/business_cards/business-card-english.jpg";
string invoiceUrl = "https://raw.githubusercontent.com/Azure-Samples/cognitive-services-REST-api-samples/master/curl/form-recognizer/simple-invoice.png";
string idUrl = "https://raw.githubusercontent.com/Azure-Samples/cognitive-services-REST-api-samples/master/curl/form-recognizer/id-license.jpg";
分析版面配置
您可以使用檔智慧來分析檔中的數據表、線條和文字,而不需要定型模型。 傳回的值是 FormPage 物件的集合。 在提交的文件中,每個頁面都有一個物件。 若要了解有關版面抽取的更多資訊,請參閱 Document Intelligence 版面配置模型。
若要分析位於指定 URL 的檔案內容,請使用 StartRecognizeContentFromUri
方法。
private static async Task RecognizeContent(FormRecognizerClient recognizerClient)
{
var invoiceUri = "https://raw.githubusercontent.com/Azure-Samples/cognitive-services-REST-api-samples/master/curl/form-recognizer/simple-invoice.png";
FormPageCollection formPages = await recognizerClient
.StartRecognizeContentFromUri(new Uri(invoiceUri))
.WaitForCompletionAsync();
小提示
您也可以從本機檔案取得內容。 請參閱 FormRecognizerClient 方法,例如 StartRecognizeContent
。 或者,針對涉及本機影像的相關案例,請參閱 GitHub (英文) 上的範例程式碼。
此工作的其餘部分會將內容資訊列印至主控台。
foreach (FormPage page in formPages)
{
Console.WriteLine($"Form Page {page.PageNumber} has {page.Lines.Count} lines.");
for (int i = 0; i < page.Lines.Count; i++)
{
FormLine line = page.Lines[i];
Console.WriteLine($" Line {i} has {line.Words.Count} word{(line.Words.Count > 1 ? "s" : "")}, and text: '{line.Text}'.");
}
for (int i = 0; i < page.Tables.Count; i++)
{
FormTable table = page.Tables[i];
Console.WriteLine($"Table {i} has {table.RowCount} rows and {table.ColumnCount} columns.");
foreach (FormTableCell cell in table.Cells)
{
Console.WriteLine($" Cell ({cell.RowIndex}, {cell.ColumnIndex}) contains text: '{cell.Text}'.");
}
}
}
}
結果看起來像下列輸出。
Form Page 1 has 18 lines.
Line 0 has 1 word, and text: 'Contoso'.
Line 1 has 1 word, and text: 'Address:'.
Line 2 has 3 words, and text: 'Invoice For: Microsoft'.
Line 3 has 4 words, and text: '1 Redmond way Suite'.
Line 4 has 3 words, and text: '1020 Enterprise Way'.
Line 5 has 3 words, and text: '6000 Redmond, WA'.
Line 6 has 3 words, and text: 'Sunnayvale, CA 87659'.
Line 7 has 1 word, and text: '99243'.
Line 8 has 2 words, and text: 'Invoice Number'.
Line 9 has 2 words, and text: 'Invoice Date'.
Line 10 has 3 words, and text: 'Invoice Due Date'.
Line 11 has 1 word, and text: 'Charges'.
Line 12 has 2 words, and text: 'VAT ID'.
Line 13 has 1 word, and text: '34278587'.
Line 14 has 1 word, and text: '6/18/2017'.
Line 15 has 1 word, and text: '6/24/2017'.
Line 16 has 1 word, and text: '$56,651.49'.
Line 17 has 1 word, and text: 'PT'.
Table 0 has 2 rows and 6 columns.
Cell (0, 0) contains text: 'Invoice Number'.
Cell (0, 1) contains text: 'Invoice Date'.
Cell (0, 2) contains text: 'Invoice Due Date'.
Cell (0, 3) contains text: 'Charges'.
Cell (0, 5) contains text: 'VAT ID'.
Cell (1, 0) contains text: '34278587'.
Cell (1, 1) contains text: '6/18/2017'.
Cell (1, 2) contains text: '6/24/2017'.
Cell (1, 3) contains text: '$56,651.49'.
Cell (1, 5) contains text: 'PT'.
分析收據
本節示範如何使用預先定型的收據模型,從美國收據分析及擷取通用字段。 如需收據分析的詳細資訊,請參閱 Document Intelligence 收據模型。
若要分析來自 URL 的收據,請使用 StartRecognizeReceiptsFromUri
方法。
private static async Task AnalyzeReceipt(
FormRecognizerClient recognizerClient, string receiptUri)
{
RecognizedFormCollection receipts = await recognizerClient.StartRecognizeReceiptsFromUri(new Uri(receiptUrl)).WaitForCompletionAsync();
小提示
您也可以分析本地收據圖像。 請參閱 FormRecognizerClient 方法,例如 StartRecognizeReceipts
。 或者,針對涉及本機影像的相關案例,請參閱 GitHub (英文) 上的範例程式碼。
傳回的值是 RecognizedForm
物件的集合。 在提交的文件中,每個頁面都有一個物件。 下列程式代碼會處理指定 URI 上的收據,並將主要欄位和值列印至主控台。
foreach (RecognizedForm receipt in receipts)
{
FormField merchantNameField;
if (receipt.Fields.TryGetValue("MerchantName", out merchantNameField))
{
if (merchantNameField.Value.ValueType == FieldValueType.String)
{
string merchantName = merchantNameField.Value.AsString();
Console.WriteLine($"Merchant Name: '{merchantName}', with confidence {merchantNameField.Confidence}");
}
}
FormField transactionDateField;
if (receipt.Fields.TryGetValue("TransactionDate", out transactionDateField))
{
if (transactionDateField.Value.ValueType == FieldValueType.Date)
{
DateTime transactionDate = transactionDateField.Value.AsDate();
Console.WriteLine($"Transaction Date: '{transactionDate}', with confidence {transactionDateField.Confidence}");
}
}
FormField itemsField;
if (receipt.Fields.TryGetValue("Items", out itemsField))
{
if (itemsField.Value.ValueType == FieldValueType.List)
{
foreach (FormField itemField in itemsField.Value.AsList())
{
Console.WriteLine("Item:");
if (itemField.Value.ValueType == FieldValueType.Dictionary)
{
IReadOnlyDictionary<string, FormField> itemFields = itemField.Value.AsDictionary();
FormField itemNameField;
if (itemFields.TryGetValue("Name", out itemNameField))
{
if (itemNameField.Value.ValueType == FieldValueType.String)
{
string itemName = itemNameField.Value.AsString();
Console.WriteLine($" Name: '{itemName}', with confidence {itemNameField.Confidence}");
}
}
FormField itemTotalPriceField;
if (itemFields.TryGetValue("TotalPrice", out itemTotalPriceField))
{
if (itemTotalPriceField.Value.ValueType == FieldValueType.Float)
{
float itemTotalPrice = itemTotalPriceField.Value.AsFloat();
Console.WriteLine($" Total Price: '{itemTotalPrice}', with confidence {itemTotalPriceField.Confidence}");
}
}
}
}
}
}
FormField totalField;
if (receipt.Fields.TryGetValue("Total", out totalField))
{
if (totalField.Value.ValueType == FieldValueType.Float)
{
float total = totalField.Value.AsFloat();
Console.WriteLine($"Total: '{total}', with confidence '{totalField.Confidence}'");
}
}
}
}
結果看起來像下列輸出。
Form Page 1 has 18 lines.
Line 0 has 1 word, and text: 'Contoso'.
Line 1 has 1 word, and text: 'Address:'.
Line 2 has 3 words, and text: 'Invoice For: Microsoft'.
Line 3 has 4 words, and text: '1 Redmond way Suite'.
Line 4 has 3 words, and text: '1020 Enterprise Way'.
Line 5 has 3 words, and text: '6000 Redmond, WA'.
Line 6 has 3 words, and text: 'Sunnayvale, CA 87659'.
Line 7 has 1 word, and text: '99243'.
Line 8 has 2 words, and text: 'Invoice Number'.
Line 9 has 2 words, and text: 'Invoice Date'.
Line 10 has 3 words, and text: 'Invoice Due Date'.
Line 11 has 1 word, and text: 'Charges'.
Line 12 has 2 words, and text: 'VAT ID'.
Line 13 has 1 word, and text: '34278587'.
Line 14 has 1 word, and text: '6/18/2017'.
Line 15 has 1 word, and text: '6/24/2017'.
Line 16 has 1 word, and text: '$56,651.49'.
Line 17 has 1 word, and text: 'PT'.
Table 0 has 2 rows and 6 columns.
Cell (0, 0) contains text: 'Invoice Number'.
Cell (0, 1) contains text: 'Invoice Date'.
Cell (0, 2) contains text: 'Invoice Due Date'.
Cell (0, 3) contains text: 'Charges'.
Cell (0, 5) contains text: 'VAT ID'.
Cell (1, 0) contains text: '34278587'.
Cell (1, 1) contains text: '6/18/2017'.
Cell (1, 2) contains text: '6/24/2017'.
Cell (1, 3) contains text: '$56,651.49'.
Cell (1, 5) contains text: 'PT'.
Merchant Name: 'Contoso Contoso', with confidence 0.516
Transaction Date: '6/10/2019 12:00:00 AM', with confidence 0.985
Item:
Name: '8GB RAM (Black)', with confidence 0.916
Total Price: '999', with confidence 0.559
Item:
Name: 'SurfacePen', with confidence 0.858
Total Price: '99.99', with confidence 0.386
Total: '1203.39', with confidence '0.774'
分析名片
本節示範如何使用預先定型的模型,從英文名片分析和擷取通用字段。 如需名片分析的詳細資訊,請參閱 Document Intelligence 名片模型。
若要從 URL 分析名片,請使用 StartRecognizeBusinessCardsFromUriAsync
方法。
private static async Task AnalyzeBusinessCard(
FormRecognizerClient recognizerClient, string bcUrl) {
RecognizedFormCollection businessCards = await recognizerClient.StartRecognizeBusinessCardsFromUriAsync(bcUrl).WaitForCompletionAsync();
小提示
您也可以分析本機名片影像。 請參閱 FormRecognizerClient 方法,例如 StartRecognizeBusinessCards
。 或者,針對涉及本機影像的相關案例,請參閱 GitHub (英文) 上的範例程式碼。
下列程式代碼會處理指定 URI 上的名片,並將主要欄位和值列印至主控台。
foreach(RecognizedForm businessCard in businessCards) {
FormField ContactNamesField;
if (businessCard.Fields.TryGetValue("ContactNames", out ContactNamesField)) {
if (ContactNamesField.Value.ValueType == FieldValueType.List) {
foreach(FormField contactNameField in ContactNamesField.Value.AsList()) {
Console.WriteLine($ "Contact Name: {contactNameField.ValueData.Text}");
if (contactNameField.Value.ValueType == FieldValueType.Dictionary) {
IReadOnlyDictionary < string,
FormField > contactNameFields = contactNameField.Value.AsDictionary();
FormField firstNameField;
if (contactNameFields.TryGetValue("FirstName", out firstNameField)) {
if (firstNameField.Value.ValueType == FieldValueType.String) {
string firstName = firstNameField.Value.AsString();
Console.WriteLine($ " First Name: '{firstName}', with confidence {firstNameField.Confidence}");
}
}
FormField lastNameField;
if (contactNameFields.TryGetValue("LastName", out lastNameField)) {
if (lastNameField.Value.ValueType == FieldValueType.String) {
string lastName = lastNameField.Value.AsString();
Console.WriteLine($ " Last Name: '{lastName}', with confidence {lastNameField.Confidence}");
}
}
}
}
}
}
FormField jobTitlesFields;
if (businessCard.Fields.TryGetValue("JobTitles", out jobTitlesFields)) {
if (jobTitlesFields.Value.ValueType == FieldValueType.List) {
foreach(FormField jobTitleField in jobTitlesFields.Value.AsList()) {
if (jobTitleField.Value.ValueType == FieldValueType.String) {
string jobTitle = jobTitleField.Value.AsString();
Console.WriteLine($ " Job Title: '{jobTitle}', with confidence {jobTitleField.Confidence}");
}
}
}
}
FormField departmentFields;
if (businessCard.Fields.TryGetValue("Departments", out departmentFields)) {
if (departmentFields.Value.ValueType == FieldValueType.List) {
foreach(FormField departmentField in departmentFields.Value.AsList()) {
if (departmentField.Value.ValueType == FieldValueType.String) {
string department = departmentField.Value.AsString();
Console.WriteLine($ " Department: '{department}', with confidence {departmentField.Confidence}");
}
}
}
}
FormField emailFields;
if (businessCard.Fields.TryGetValue("Emails", out emailFields)) {
if (emailFields.Value.ValueType == FieldValueType.List) {
foreach(FormField emailField in emailFields.Value.AsList()) {
if (emailField.Value.ValueType == FieldValueType.String) {
string email = emailField.Value.AsString();
Console.WriteLine($ " Email: '{email}', with confidence {emailField.Confidence}");
}
}
}
}
FormField websiteFields;
if (businessCard.Fields.TryGetValue("Websites", out websiteFields)) {
if (websiteFields.Value.ValueType == FieldValueType.List) {
foreach(FormField websiteField in websiteFields.Value.AsList()) {
if (websiteField.Value.ValueType == FieldValueType.String) {
string website = websiteField.Value.AsString();
Console.WriteLine($ " Website: '{website}', with confidence {websiteField.Confidence}");
}
}
}
}
FormField mobilePhonesFields;
if (businessCard.Fields.TryGetValue("MobilePhones", out mobilePhonesFields)) {
if (mobilePhonesFields.Value.ValueType == FieldValueType.List) {
foreach(FormField mobilePhoneField in mobilePhonesFields.Value.AsList()) {
if (mobilePhoneField.Value.ValueType == FieldValueType.PhoneNumber) {
string mobilePhone = mobilePhoneField.Value.AsPhoneNumber();
Console.WriteLine($ " Mobile phone number: '{mobilePhone}', with confidence {mobilePhoneField.Confidence}");
}
}
}
}
FormField otherPhonesFields;
if (businessCard.Fields.TryGetValue("OtherPhones", out otherPhonesFields)) {
if (otherPhonesFields.Value.ValueType == FieldValueType.List) {
foreach(FormField otherPhoneField in otherPhonesFields.Value.AsList()) {
if (otherPhoneField.Value.ValueType == FieldValueType.PhoneNumber) {
string otherPhone = otherPhoneField.Value.AsPhoneNumber();
Console.WriteLine($ " Other phone number: '{otherPhone}', with confidence {otherPhoneField.Confidence}");
}
}
}
}
FormField faxesFields;
if (businessCard.Fields.TryGetValue("Faxes", out faxesFields)) {
if (faxesFields.Value.ValueType == FieldValueType.List) {
foreach(FormField faxField in faxesFields.Value.AsList()) {
if (faxField.Value.ValueType == FieldValueType.PhoneNumber) {
string fax = faxField.Value.AsPhoneNumber();
Console.WriteLine($ " Fax phone number: '{fax}', with confidence {faxField.Confidence}");
}
}
}
}
FormField addressesFields;
if (businessCard.Fields.TryGetValue("Addresses", out addressesFields)) {
if (addressesFields.Value.ValueType == FieldValueType.List) {
foreach(FormField addressField in addressesFields.Value.AsList()) {
if (addressField.Value.ValueType == FieldValueType.String) {
string address = addressField.Value.AsString();
Console.WriteLine($ " Address: '{address}', with confidence {addressField.Confidence}");
}
}
}
}
FormField companyNamesFields;
if (businessCard.Fields.TryGetValue("CompanyNames", out companyNamesFields)) {
if (companyNamesFields.Value.ValueType == FieldValueType.List) {
foreach(FormField companyNameField in companyNamesFields.Value.AsList()) {
if (companyNameField.Value.ValueType == FieldValueType.String) {
string companyName = companyNameField.Value.AsString();
Console.WriteLine($ " Company name: '{companyName}', with confidence {companyNameField.Confidence}");
}
}
}
}
}
}
分析發票
本節示範如何使用預先定型的模型,分析及擷取銷售發票中的一般字段。 如需發票分析的詳細資訊,請參閱 Document Intelligence 發票模型。
若要從 URL 分析發票,請使用 StartRecognizeInvoicesFromUriAsync
方法。
private static async Task AnalyzeInvoice(
FormRecognizerClient recognizerClient, string invoiceUrl) {
var options = new RecognizeInvoicesOptions() {
Locale = "en-US"
};
RecognizedFormCollection invoices = await recognizerClient.StartRecognizeInvoicesFromUriAsync(invoiceUrl, options).WaitForCompletionAsync();
小提示
您也可以分析當地的發票影像。 請參閱 FormRecognizerClient 方法,例如 StartRecognizeInvoices
。 或者,針對涉及本機影像的相關案例,請參閱 GitHub (英文) 上的範例程式碼。
下列程式代碼會處理指定 URI 上的發票,並將主要欄位和值列印至主控台。
RecognizedForm invoice = invoices.Single();
FormField invoiceIdField;
if (invoice.Fields.TryGetValue("InvoiceId", out invoiceIdField)) {
if (invoiceIdField.Value.ValueType == FieldValueType.String) {
string invoiceId = invoiceIdField.Value.AsString();
Console.WriteLine($ " Invoice Id: '{invoiceId}', with confidence {invoiceIdField.Confidence}");
}
}
FormField invoiceDateField;
if (invoice.Fields.TryGetValue("InvoiceDate", out invoiceDateField)) {
if (invoiceDateField.Value.ValueType == FieldValueType.Date) {
DateTime invoiceDate = invoiceDateField.Value.AsDate();
Console.WriteLine($ " Invoice Date: '{invoiceDate}', with confidence {invoiceDateField.Confidence}");
}
}
FormField dueDateField;
if (invoice.Fields.TryGetValue("DueDate", out dueDateField)) {
if (dueDateField.Value.ValueType == FieldValueType.Date) {
DateTime dueDate = dueDateField.Value.AsDate();
Console.WriteLine($ " Due Date: '{dueDate}', with confidence {dueDateField.Confidence}");
}
}
FormField vendorNameField;
if (invoice.Fields.TryGetValue("VendorName", out vendorNameField)) {
if (vendorNameField.Value.ValueType == FieldValueType.String) {
string vendorName = vendorNameField.Value.AsString();
Console.WriteLine($ " Vendor Name: '{vendorName}', with confidence {vendorNameField.Confidence}");
}
}
FormField vendorAddressField;
if (invoice.Fields.TryGetValue("VendorAddress", out vendorAddressField)) {
if (vendorAddressField.Value.ValueType == FieldValueType.String) {
string vendorAddress = vendorAddressField.Value.AsString();
Console.WriteLine($ " Vendor Address: '{vendorAddress}', with confidence {vendorAddressField.Confidence}");
}
}
FormField customerNameField;
if (invoice.Fields.TryGetValue("CustomerName", out customerNameField)) {
if (customerNameField.Value.ValueType == FieldValueType.String) {
string customerName = customerNameField.Value.AsString();
Console.WriteLine($ " Customer Name: '{customerName}', with confidence {customerNameField.Confidence}");
}
}
FormField customerAddressField;
if (invoice.Fields.TryGetValue("CustomerAddress", out customerAddressField)) {
if (customerAddressField.Value.ValueType == FieldValueType.String) {
string customerAddress = customerAddressField.Value.AsString();
Console.WriteLine($ " Customer Address: '{customerAddress}', with confidence {customerAddressField.Confidence}");
}
}
FormField customerAddressRecipientField;
if (invoice.Fields.TryGetValue("CustomerAddressRecipient", out customerAddressRecipientField)) {
if (customerAddressRecipientField.Value.ValueType == FieldValueType.String) {
string customerAddressRecipient = customerAddressRecipientField.Value.AsString();
Console.WriteLine($ " Customer address recipient: '{customerAddressRecipient}', with confidence {customerAddressRecipientField.Confidence}");
}
}
FormField invoiceTotalField;
if (invoice.Fields.TryGetValue("InvoiceTotal", out invoiceTotalField)) {
if (invoiceTotalField.Value.ValueType == FieldValueType.Float) {
float invoiceTotal = invoiceTotalField.Value.AsFloat();
Console.WriteLine($ " Invoice Total: '{invoiceTotal}', with confidence {invoiceTotalField.Confidence}");
}
}
}
分析身分證明文件
本節示範如何使用文件智慧預先建置的標識符模型,分析及擷取政府簽發的身份證中的關鍵資訊—全球護照和美國駕照。 如需了解更多關於身份證件分析的資訊,請參閱 文件智能身份證件模型。
若要從 URI 分析識別碼檔,請使用 StartRecognizeIdentityDocumentsFromUriAsync
方法。
private static async Task AnalyzeId(
FormRecognizerClient recognizerClient, string idUrl) {
RecognizedFormCollection identityDocument = await recognizerClient.StartRecognizeIdDocumentsFromUriAsync(idUrl).WaitForCompletionAsync();
小提示
您也可以分析本機身分證明文件影像。 請參閱 FormRecognizerClient 方法,例如 StartRecognizeIdentityDocumentsAsync
。 此外,如需涉及本機影像的案例,請參閱 GitHub 上的範例程式代碼。
下列程式代碼會處理位於指定 URI 的識別碼檔,並將主要欄位和值列印至主控台。
RecognizedForm identityDocument = identityDocuments.Single();
if (identityDocument.Fields.TryGetValue("Address", out FormField addressField)) {
if (addressField.Value.ValueType == FieldValueType.String) {
string address = addressField.Value.AsString();
Console.WriteLine($ "Address: '{address}', with confidence {addressField.Confidence}");
}
}
if (identityDocument.Fields.TryGetValue("CountryRegion", out FormField countryRegionField)) {
if (countryRegionField.Value.ValueType == FieldValueType.CountryRegion) {
string countryRegion = countryRegionField.Value.AsCountryRegion();
Console.WriteLine($ "CountryRegion: '{countryRegion}', with confidence {countryRegionField.Confidence}");
}
}
if (identityDocument.Fields.TryGetValue("DateOfBirth", out FormField dateOfBirthField)) {
if (dateOfBirthField.Value.ValueType == FieldValueType.Date) {
DateTime dateOfBirth = dateOfBirthField.Value.AsDate();
Console.WriteLine($ "Date Of Birth: '{dateOfBirth}', with confidence {dateOfBirthField.Confidence}");
}
}
if (identityDocument.Fields.TryGetValue("DateOfExpiration", out FormField dateOfExpirationField)) {
if (dateOfExpirationField.Value.ValueType == FieldValueType.Date) {
DateTime dateOfExpiration = dateOfExpirationField.Value.AsDate();
Console.WriteLine($ "Date Of Expiration: '{dateOfExpiration}', with confidence {dateOfExpirationField.Confidence}");
}
}
if (identityDocument.Fields.TryGetValue("DocumentNumber", out FormField documentNumberField)) {
if (documentNumberField.Value.ValueType == FieldValueType.String) {
string documentNumber = documentNumberField.Value.AsString();
Console.WriteLine($ "Document Number: '{documentNumber}', with confidence {documentNumberField.Confidence}");
}
RecognizedForm identityDocument = identityDocuments.Single();
if (identityDocument.Fields.TryGetValue("Address", out FormField addressField)) {
if (addressField.Value.ValueType == FieldValueType.String) {
string address = addressField.Value.AsString();
Console.WriteLine($ "Address: '{address}', with confidence {addressField.Confidence}");
}
}
if (identityDocument.Fields.TryGetValue("CountryRegion", out FormField countryRegionField)) {
if (countryRegionField.Value.ValueType == FieldValueType.CountryRegion) {
string countryRegion = countryRegionField.Value.AsCountryRegion();
Console.WriteLine($ "CountryRegion: '{countryRegion}', with confidence {countryRegionField.Confidence}");
}
}
if (identityDocument.Fields.TryGetValue("DateOfBirth", out FormField dateOfBirthField)) {
if (dateOfBirthField.Value.ValueType == FieldValueType.Date) {
DateTime dateOfBirth = dateOfBirthField.Value.AsDate();
Console.WriteLine($ "Date Of Birth: '{dateOfBirth}', with confidence {dateOfBirthField.Confidence}");
}
}
if (identityDocument.Fields.TryGetValue("DateOfExpiration", out FormField dateOfExpirationField)) {
if (dateOfExpirationField.Value.ValueType == FieldValueType.Date) {
DateTime dateOfExpiration = dateOfExpirationField.Value.AsDate();
Console.WriteLine($ "Date Of Expiration: '{dateOfExpiration}', with confidence {dateOfExpirationField.Confidence}");
}
}
if (identityDocument.Fields.TryGetValue("DocumentNumber", out FormField documentNumberField)) {
if (documentNumberField.Value.ValueType == FieldValueType.String) {
string documentNumber = documentNumberField.Value.AsString();
Console.WriteLine($ "Document Number: '{documentNumber}', with confidence {documentNumberField.Confidence}");
}
}
if (identityDocument.Fields.TryGetValue("FirstName", out FormField firstNameField)) {
if (firstNameField.Value.ValueType == FieldValueType.String) {
string firstName = firstNameField.Value.AsString();
Console.WriteLine($ "First Name: '{firstName}', with confidence {firstNameField.Confidence}");
}
}
if (identityDocument.Fields.TryGetValue("LastName", out FormField lastNameField)) {
if (lastNameField.Value.ValueType == FieldValueType.String) {
string lastName = lastNameField.Value.AsString();
Console.WriteLine($ "Last Name: '{lastName}', with confidence {lastNameField.Confidence}");
}
}
if (identityDocument.Fields.TryGetValue("Region", out FormField regionfield)) {
if (regionfield.Value.ValueType == FieldValueType.String) {
string region = regionfield.Value.AsString();
Console.WriteLine($ "Region: '{region}', with confidence {regionfield.Confidence}");
}
}
訓練自訂模型
本節示範如何使用您自己的數據來定型模型。 定型的模型可以輸出結構化數據,其中包含源檔中的索引鍵/值關聯性。 定型模型之後,您可以測試、重新定型,並最終使用它,根據需求可靠地從更多窗體中擷取數據。
備註
您也可以使用圖形使用者介面來定型模型,例如 檔案智慧範例標籤工具。
訓練不含標籤的模型
訓練自定義模型,以分析自定義表單中找到的所有欄位和值,而不需手動標記訓練檔。 下列方法會將模型定型在一組指定的檔上,並將模型的狀態列印至主控台。
private static async Task<String> TrainModel(
FormTrainingClient trainingClient, string trainingDataUrl)
{
CustomFormModel model = await trainingClient
.StartTrainingAsync(new Uri(trainingDataUrl), useTrainingLabels: false)
.WaitForCompletionAsync();
Console.WriteLine($"Custom Model Info:");
Console.WriteLine($" Model Id: {model.ModelId}");
Console.WriteLine($" Model Status: {model.Status}");
Console.WriteLine($" Training model started on: {model.TrainingStartedOn}");
Console.WriteLine($" Training model completed on: {model.TrainingCompletedOn}");
傳回 CustomFormModel
物件包含模型可分析之表單類型的相關信息,以及可從每個表單類型擷取的欄位。 下列程式代碼區塊會將此資訊列印至主控台。
foreach (CustomFormSubmodel submodel in model.Submodels)
{
Console.WriteLine($"Submodel Form Type: {submodel.FormType}");
foreach (CustomFormModelField field in submodel.Fields.Values)
{
Console.Write($" FieldName: {field.Name}");
if (field.Label != null)
{
Console.Write($", FieldLabel: {field.Label}");
}
Console.WriteLine("");
}
}
最後,傳回定型的模型標識符,以供後續步驟使用。
return model.ModelId;
}
為了提高可讀性,此輸出將被截短。
Merchant Name: 'Contoso Contoso', with confidence 0.516
Transaction Date: '6/10/2019 12:00:00 AM', with confidence 0.985
Item:
Name: '8GB RAM (Black)', with confidence 0.916
Total Price: '999', with confidence 0.559
Item:
Name: 'SurfacePen', with confidence 0.858
Total Price: '99.99', with confidence 0.386
Total: '1203.39', with confidence '0.774'
Form Page 1 has 18 lines.
Line 0 has 1 word, and text: 'Contoso'.
Line 1 has 1 word, and text: 'Address:'.
Line 2 has 3 words, and text: 'Invoice For: Microsoft'.
Line 3 has 4 words, and text: '1 Redmond way Suite'.
Line 4 has 3 words, and text: '1020 Enterprise Way'.
...
Table 0 has 2 rows and 6 columns.
Cell (0, 0) contains text: 'Invoice Number'.
Cell (0, 1) contains text: 'Invoice Date'.
Cell (0, 2) contains text: 'Invoice Due Date'.
Cell (0, 3) contains text: 'Charges'.
...
Custom Model Info:
Model Id: 95035721-f19d-40eb-8820-0c806b42798b
Model Status: Ready
Training model started on: 8/24/2020 6:36:44 PM +00:00
Training model completed on: 8/24/2020 6:36:50 PM +00:00
Submodel Form Type: form-95035721-f19d-40eb-8820-0c806b42798b
FieldName: CompanyAddress
FieldName: CompanyName
FieldName: CompanyPhoneNumber
...
Custom Model Info:
Model Id: e7a1181b-1fb7-40be-bfbe-1ee154183633
Model Status: Ready
Training model started on: 8/24/2020 6:36:44 PM +00:00
Training model completed on: 8/24/2020 6:36:52 PM +00:00
Submodel Form Type: form-0
FieldName: field-0, FieldLabel: Additional Notes:
FieldName: field-1, FieldLabel: Address:
FieldName: field-2, FieldLabel: Company Name:
FieldName: field-3, FieldLabel: Company Phone:
FieldName: field-4, FieldLabel: Dated As:
FieldName: field-5, FieldLabel: Details
FieldName: field-6, FieldLabel: Email:
FieldName: field-7, FieldLabel: Hero Limited
FieldName: field-8, FieldLabel: Name:
FieldName: field-9, FieldLabel: Phone:
...
訓練具備標籤的模型
您也可以手動標記訓練文件來訓練自訂模型。 在某些情況下,使用標籤來訓練會讓效能更佳。 若要使用標籤來訓練,您的 Blob 儲存體容器中除了訓練文件以外,還必須要有特殊的標籤資訊檔案 (<filename>.pdf.labels.json)。 檔智慧範例卷標工具 提供使用者介面,協助您建立這些標籤檔案。 取得它們之後,您可以呼叫 StartTrainingAsync
方法,並將 uselabels
參數設定為 true
。
private static async Task<Guid> TrainModelWithLabelsAsync(
FormRecognizerClient trainingClient, string trainingDataUrl)
{
CustomFormModel model = await trainingClient
.StartTrainingAsync(new Uri(trainingDataUrl), useTrainingLabels: true)
.WaitForCompletionAsync();
Console.WriteLine($"Custom Model Info:");
Console.WriteLine($" Model Id: {model.ModelId}");
Console.WriteLine($" Model Status: {model.Status}");
Console.WriteLine($" Training model started on: {model.TrainingStartedOn}");
Console.WriteLine($" Training model completed on: {model.TrainingCompletedOn}");
傳回的 CustomFormModel
會指出模型可以擷取的欄位,以及其在每個欄位中的估計精確度。 下列程式代碼區塊會將此資訊列印至主控台。
foreach (CustomFormSubmodel submodel in model.Submodels)
{
Console.WriteLine($"Submodel Form Type: {submodel.FormType}");
foreach (CustomFormModelField field in submodel.Fields.Values)
{
Console.Write($" FieldName: {field.Name}");
if (field.Label != null)
{
Console.Write($", FieldLabel: {field.Label}");
}
Console.WriteLine("");
}
}
return model.ModelId;
}
為了提高可讀性,此輸出將被截短。
Form Page 1 has 18 lines.
Line 0 has 1 word, and text: 'Contoso'.
Line 1 has 1 word, and text: 'Address:'.
Line 2 has 3 words, and text: 'Invoice For: Microsoft'.
Line 3 has 4 words, and text: '1 Redmond way Suite'.
Line 4 has 3 words, and text: '1020 Enterprise Way'.
Line 5 has 3 words, and text: '6000 Redmond, WA'.
...
Table 0 has 2 rows and 6 columns.
Cell (0, 0) contains text: 'Invoice Number'.
Cell (0, 1) contains text: 'Invoice Date'.
Cell (0, 2) contains text: 'Invoice Due Date'.
...
Merchant Name: 'Contoso Contoso', with confidence 0.516
Transaction Date: '6/10/2019 12:00:00 AM', with confidence 0.985
Item:
Name: '8GB RAM (Black)', with confidence 0.916
Total Price: '999', with confidence 0.559
Item:
Name: 'SurfacePen', with confidence 0.858
Total Price: '99.99', with confidence 0.386
Total: '1203.39', with confidence '0.774'
Custom Model Info:
Model Id: 63c013e3-1cab-43eb-84b0-f4b20cb9214c
Model Status: Ready
Training model started on: 8/24/2020 6:42:54 PM +00:00
Training model completed on: 8/24/2020 6:43:01 PM +00:00
Submodel Form Type: form-63c013e3-1cab-43eb-84b0-f4b20cb9214c
FieldName: CompanyAddress
FieldName: CompanyName
FieldName: CompanyPhoneNumber
FieldName: DatedAs
FieldName: Email
FieldName: Merchant
...
使用自定義模型分析表單
本節示範如何透過使用您依據自己的表單訓練的模型,從自訂範本類型中擷取鍵值資訊及其他內容。
這很重要
若要實作此案例,您必須已經將模型定型,以便將其標識碼傳遞至下列方法。
使用 StartRecognizeCustomFormsFromUri
方法。
// Analyze PDF form data
private static async Task AnalyzePdfForm(
FormRecognizerClient recognizerClient, String modelId, string formUrl)
{
RecognizedFormCollection forms = await recognizerClient
.StartRecognizeCustomFormsFromUri(modelId, new Uri(formUrl))
.WaitForCompletionAsync();
小提示
您也可以分析本機檔案。 請參閱 FormRecognizerClient 方法,例如 StartRecognizeCustomForms
。 或者,針對涉及本機影像的相關案例,請參閱 GitHub (英文) 上的範例程式碼。
傳回的值是 RecognizedForm
物件的集合。 在提交的文件中,每個頁面都有一個物件。 下列程式代碼會將分析結果列印至主控台。 它會列印每個已辨識的字段和對應的值,以及信賴分數。
foreach (RecognizedForm form in forms)
{
Console.WriteLine($"Form of type: {form.FormType}");
foreach (FormField field in form.Fields.Values)
{
Console.WriteLine($"Field '{field.Name}: ");
if (field.LabelData != null)
{
Console.WriteLine($" Label: '{field.LabelData.Text}");
}
Console.WriteLine($" Value: '{field.ValueData.Text}");
Console.WriteLine($" Confidence: '{field.Confidence}");
}
Console.WriteLine("Table data:");
foreach (FormPage page in form.Pages)
{
for (int i = 0; i < page.Tables.Count; i++)
{
FormTable table = page.Tables[i];
Console.WriteLine($"Table {i} has {table.RowCount} rows and {table.ColumnCount} columns.");
foreach (FormTableCell cell in table.Cells)
{
Console.WriteLine($" Cell ({cell.RowIndex}, {cell.ColumnIndex}) contains {(cell.IsHeader ? "header" : "text")}: '{cell.Text}'");
}
}
}
}
}
此輸出回應會因可讀性而截斷。
Custom Model Info:
Model Id: 9b0108ee-65c8-450e-b527-bb309d054fc4
Model Status: Ready
Training model started on: 8/24/2020 7:00:31 PM +00:00
Training model completed on: 8/24/2020 7:00:32 PM +00:00
Submodel Form Type: form-9b0108ee-65c8-450e-b527-bb309d054fc4
FieldName: CompanyAddress
FieldName: CompanyName
FieldName: CompanyPhoneNumber
...
Form Page 1 has 18 lines.
Line 0 has 1 word, and text: 'Contoso'.
Line 1 has 1 word, and text: 'Address:'.
Line 2 has 3 words, and text: 'Invoice For: Microsoft'.
Line 3 has 4 words, and text: '1 Redmond way Suite'.
...
Table 0 has 2 rows and 6 columns.
Cell (0, 0) contains text: 'Invoice Number'.
Cell (0, 1) contains text: 'Invoice Date'.
Cell (0, 2) contains text: 'Invoice Due Date'.
...
Merchant Name: 'Contoso Contoso', with confidence 0.516
Transaction Date: '6/10/2019 12:00:00 AM', with confidence 0.985
Item:
Name: '8GB RAM (Black)', with confidence 0.916
Total Price: '999', with confidence 0.559
Item:
Name: 'SurfacePen', with confidence 0.858
Total Price: '99.99', with confidence 0.386
Total: '1203.39', with confidence '0.774'
Custom Model Info:
Model Id: dc115156-ce0e-4202-bbe4-7426e7bee756
Model Status: Ready
Training model started on: 8/24/2020 7:00:31 PM +00:00
Training model completed on: 8/24/2020 7:00:41 PM +00:00
Submodel Form Type: form-0
FieldName: field-0, FieldLabel: Additional Notes:
FieldName: field-1, FieldLabel: Address:
FieldName: field-2, FieldLabel: Company Name:
FieldName: field-3, FieldLabel: Company Phone:
FieldName: field-4, FieldLabel: Dated As:
...
Form of type: custom:form
Field 'Azure.AI.FormRecognizer.Models.FieldValue:
Value: '$56,651.49
Confidence: '0.249
Field 'Azure.AI.FormRecognizer.Models.FieldValue:
Value: 'PT
Confidence: '0.245
Field 'Azure.AI.FormRecognizer.Models.FieldValue:
Value: '99243
Confidence: '0.114
...
管理自定義模型
本節示範如何管理帳戶中儲存的自定義模型。 您會在下列方法內完成多個作業:
private static async Task ManageModels(
FormTrainingClient trainingClient, string trainingFileUrl)
{
檢查 FormRecognizer 資源帳戶中的模型數目
下列程式代碼區塊會檢查您在 Document Intelligence 帳戶中儲存的模型數目,並將其與帳戶限制進行比較。
// Check number of models in the FormRecognizer account,
// and the maximum number of models that can be stored.
AccountProperties accountProperties = trainingClient.GetAccountProperties();
Console.WriteLine($"Account has {accountProperties.CustomModelCount} models.");
Console.WriteLine($"It can have at most {accountProperties.CustomModelLimit} models.");
輸出
Account has 20 models.
It can have at most 5000 models.
列出目前儲存在資源帳戶中的模型
下列程式代碼會封鎖您的帳戶中目前的模型,並將其詳細數據列印至主控台。
Pageable<CustomFormModelInfo> models = trainingClient.GetCustomModels();
foreach (CustomFormModelInfo modelInfo in models)
{
Console.WriteLine($"Custom Model Info:");
Console.WriteLine($" Model Id: {modelInfo.ModelId}");
Console.WriteLine($" Model Status: {modelInfo.Status}");
Console.WriteLine($" Training model started on: {modelInfo.TrainingStartedOn}");
Console.WriteLine($" Training model completed on: {modelInfo.TrainingCompletedOn}");
}
為了提高可讀性,此輸出將被截短。
Custom Model Info:
Model Id: 05932d5a-a2f8-4030-a2ef-4e5ed7112515
Model Status: Creating
Training model started on: 8/24/2020 7:35:02 PM +00:00
Training model completed on: 8/24/2020 7:35:02 PM +00:00
Custom Model Info:
Model Id: 150828c4-2eb2-487e-a728-60d5d504bd16
Model Status: Ready
Training model started on: 8/24/2020 7:33:25 PM +00:00
Training model completed on: 8/24/2020 7:33:27 PM +00:00
Custom Model Info:
Model Id: 3303e9de-6cec-4dfb-9e68-36510a6ecbb2
Model Status: Ready
Training model started on: 8/24/2020 7:29:27 PM +00:00
Training model completed on: 8/24/2020 7:29:36 PM +00:00
使用模型的標識碼取得特定模型
下列程式碼區塊會訓練新的模型 (如訓練沒有標籤的模型中所述),然後使用其識別碼來擷取第二個參考。
// Create a new model to store in the account
CustomFormModel model = await trainingClient.StartTrainingAsync(
new Uri(trainingFileUrl)).WaitForCompletionAsync();
// Get the model that was just created
CustomFormModel modelCopy = trainingClient.GetCustomModel(model.ModelId);
Console.WriteLine($"Custom Model {modelCopy.ModelId} recognizes the following form types:");
foreach (CustomFormSubmodel submodel in modelCopy.Submodels)
{
Console.WriteLine($"Submodel Form Type: {submodel.FormType}");
foreach (CustomFormModelField field in submodel.Fields.Values)
{
Console.Write($" FieldName: {field.Name}");
if (field.Label != null)
{
Console.Write($", FieldLabel: {field.Label}");
}
Console.WriteLine("");
}
}
為了提高可讀性,此輸出將被截短。
Custom Model Info:
Model Id: 150828c4-2eb2-487e-a728-60d5d504bd16
Model Status: Ready
Training model started on: 8/24/2020 7:33:25 PM +00:00
Training model completed on: 8/24/2020 7:33:27 PM +00:00
Submodel Form Type: form-150828c4-2eb2-487e-a728-60d5d504bd16
FieldName: CompanyAddress
FieldName: CompanyName
FieldName: CompanyPhoneNumber
FieldName: DatedAs
FieldName: Email
FieldName: Merchant
FieldName: PhoneNumber
FieldName: PurchaseOrderNumber
FieldName: Quantity
FieldName: Signature
FieldName: Subtotal
FieldName: Tax
FieldName: Total
FieldName: VendorName
FieldName: Website
...
從資源帳戶刪除模型
您也可以參考其識別碼,從您的帳戶中刪除模型。 此步驟也會結束此方法。
// Delete the model from the account.
trainingClient.DeleteModel(model.ModelId);
}
執行應用程式
使用 dotnet run
命令從您的應用程式目錄執行應用程式。
dotnet run
清理資源
如果您想要清除和移除 Azure AI 服務訂用帳戶,則可以刪除資源或資源群組。 刪除資源群組也會刪除與其相關聯的任何其他資源。
故障排除
當您使用 .NET SDK 與 Azure AI Document Intelligence 用戶端連結庫互動時,服務傳回的錯誤會導致 RequestFailedException
。 它們包含 REST API 要求所傳回的相同 HTTP 狀態代碼。
例如,如果您提交具有無效 URI 的收據影像,則會傳回 400
錯誤,指出 不正確的要求。
try
{
RecognizedReceiptCollection receipts = await client.StartRecognizeReceiptsFromUri(new Uri(receiptUri)).WaitForCompletionAsync();
}
catch (RequestFailedException e)
{
Console.WriteLine(e.ToString());
}
您注意到其他資訊已被記錄下來,例如作業的客戶端請求ID。
Message:
Azure.RequestFailedException: Service request failed.
Status: 400 (Bad Request)
Content:
{"error":{"code":"FailedToDownloadImage","innerError":
{"requestId":"8ca04feb-86db-4552-857c-fde903251518"},
"message":"Failed to download image from input URL."}}
Headers:
Transfer-Encoding: chunked
x-envoy-upstream-service-time: REDACTED
apim-request-id: REDACTED
Strict-Transport-Security: REDACTED
X-Content-Type-Options: REDACTED
Date: Mon, 20 Apr 2020 22:48:35 GMT
Content-Type: application/json; charset=utf-8
後續步驟
在此專案中,您已使用 Document Intelligence .NET 用戶端連結庫,以不同方式定型模型和分析表單。 接下來,瞭解建立更佳訓練數據集的秘訣,並產生更精確的模型。
這很重要
此項目的目標是 Document Intelligence REST API 2.1 版。
參考文件 | 程式庫來源程式碼 | 套件 (Maven) | 範例
先決條件
Azure 訂用帳戶 - 免費建立一個訂用帳戶。
Gradle 建置工具,或其他相依性管理員。
文件智能資源。 您可以使用免費定價層 (
F0
) 來試用服務,之後可升級至付費層以用於實際執行環境。從您所建立資源的金鑰和端點,將應用程式連線至 Azure 文件智慧服務。
- 部署資源之後,請選取 [前往資源]。
- 在左側導覽功能表中,選取 [金鑰和端點]。
- 複製其中一個金鑰和 端點,以供本文稍後使用。
包含一組訓練資料的 Azure 儲存 Blob。 如需組合您的訓練數據集的提示和選項,請參閱 建置和訓練自定義模型。 針對本專案,您可以使用範例資料集 (英文) 的 Train 資料夾中的檔案。 下載並擷取 sample_data.zip。
設定程式設計環境
若要設定程式設計環境,請建立 Gradle 專案並安裝用戶端連結庫。
建立新的 Gradle 專案
在主控台視窗中,為您的應用程式建立目錄並流覽至該目錄。
mkdir myapp
cd myapp
從您的工作目錄執行 gradle init
命令。 此命令會建立 Gradle 的基本組建檔案,包括 build.gradle.kts,將在執行階段使用 build.gradle.kts,來建立及設定應用程式。
gradle init --type basic
當系統提示您選擇 DSL時,請選取 [Kotlin]。
安裝用戶端程式庫
此專案使用 Gradle 相依性管理員。 您可以在 Maven 中央存放庫中找到用戶端程式庫和其他相依性管理員的資訊。
在專案的 build.gradle.kts 檔案中,將用戶端程式庫納入為 implementation
陳述式,以及必要的外掛程式和設定。
plugins {
java
application
}
application {
mainClass.set("FormRecognizer")
}
repositories {
mavenCentral()
}
dependencies {
implementation(group = "com.azure", name = "azure-ai-formrecognizer", version = "3.1.1")
}
建立 Java 檔案
從工作目錄執行下列命令:
mkdir -p src/main/java
流覽至新的資料夾,並建立名為 FormRecognizer.java的檔案。 在編輯器或 IDE 中開啟它,並新增下列 import
語句:
import com.azure.ai.formrecognizer.*;
import com.azure.ai.formrecognizer.training.*;
import com.azure.ai.formrecognizer.models.*;
import com.azure.ai.formrecognizer.training.models.*;
import java.util.concurrent.atomic.AtomicReference;
import java.util.List;
import java.util.Map;
import java.time.LocalDate;
import com.azure.core.credential.AzureKeyCredential;
import com.azure.core.http.rest.PagedIterable;
import com.azure.core.util.Context;
import com.azure.core.util.polling.SyncPoller;
在應用程式的 FormRecognizer 類別中,為資源的密鑰和端點建立變數。
static final String key = "PASTE_YOUR_FORM_RECOGNIZER_SUBSCRIPTION_KEY_HERE";
static final String endpoint = "PASTE_YOUR_FORM_RECOGNIZER_ENDPOINT_HERE";
這很重要
前往 Azure 入口網站。 如果已成功部署您在 [必要條件] 區段中所建立的文件智慧服務資源,請在 [後續步驟] 下選取 [前往資源]。 您可以在 [金鑰] 和 [端點]底下的 [資源管理] 中找到您的金鑰和端點。
當您完成時,請記得從程式碼中移除金鑰。 永遠不要公開發佈它。 針對生產環境,請使用安全方法來儲存和存取您的認證。 如需詳細資訊,請參閱 Azure AI 服務 安全性。
在應用程式的 main
方法中,新增此專案中所用方法的呼叫。 您稍後會定義這些呼叫。 您也需要為訓練和測試資料新增 URL 的參考。
若要擷取自定義模型定型數據的SAS URL,請移至 Azure 入口網站中的記憶體資源,然後選取 [資料記憶體]>[容器]。
瀏覽至您的容器,按下滑鼠右鍵,然後選取 產生 SAS。
取得您容器的 SAS,而不是儲存體帳戶本身的 SAS。
請確定已選取 讀取、寫入、刪除和 列出 許可權,然後選取 產生 SAS 令牌和 URL。
將 [URL] 區段中的值複製到暫存位置。 其格式應該為:
https://<storage account>.blob.core.windows.net/<container name>?<SAS value>
。
若要取得要測試之表單的 URL,您可以使用上述步驟取得 Blob 記憶體中個別檔的 SAS URL。 或使用位於他處的文件 URL。
也請使用上述方法取得收據影像的 URL。
String trainingDataUrl = "PASTE_YOUR_SAS_URL_OF_YOUR_FORM_FOLDER_IN_BLOB_STORAGE_HERE";
String formUrl = "PASTE_YOUR_FORM_RECOGNIZER_FORM_URL_HERE";
String receiptUrl = "https://docs.microsoft.com/azure/cognitive-services/form-recognizer/media" + "/contoso-allinone.jpg";
String bcUrl = "https://raw.githubusercontent.com/Azure/azure-sdk-for-python/master/sdk/formrecognizer/azure-ai-formrecognizer/samples/sample_forms/business_cards/business-card-english.jpg";
String invoiceUrl = "https://raw.githubusercontent.com/Azure/azure-sdk-for-python/master/sdk/formrecognizer/azure-ai-formrecognizer/samples/sample_forms/forms/Invoice_1.pdf";
String idUrl = "https://raw.githubusercontent.com/Azure-Samples/cognitive-services-REST-api-samples/master/curl/form-recognizer/id-license.jpg"
// Call Form Recognizer scenarios:
System.out.println("Get form content...");
GetContent(recognizerClient, formUrl);
System.out.println("Analyze receipt...");
AnalyzeReceipt(recognizerClient, receiptUrl);
System.out.println("Analyze business card...");
AnalyzeBusinessCard(recognizerClient, bcUrl);
System.out.println("Analyze invoice...");
AnalyzeInvoice(recognizerClient, invoiceUrl);
System.out.println("Analyze id...");
AnalyzeId(recognizerClient, idUrl);
System.out.println("Train Model with training data...");
String modelId = TrainModel(trainingClient, trainingDataUrl);
System.out.println("Analyze PDF form...");
AnalyzePdfForm(recognizerClient, modelId, formUrl);
System.out.println("Manage models...");
ManageModels(trainingClient, trainingDataUrl);
使用物件模型
使用文件智慧,您可以建立兩種不同的客戶端類型。 第一個是 FormRecognizerClient
,會查詢服務,以辨識出表單欄位和內容。 第二個 FormTrainingClient
會建立及管理自定義模型,以改善辨識。
FormRecognizerClient
提供以下任務的操作:
- 使用定型的自定義模型來分析自定義表單,來辨識表單域和內容。 這些值會在
RecognizedForm
物件的集合中傳回。 請參閱分析自訂表單。 - 辨識表單內容,包括表格、線條和文字,而不需要訓練模型。 表單內容會在
FormPage
物件的集合中傳回。 請參閱分析版面配置。 - 使用文件智慧服務的預先定型模型,辨識來自美國收據、名片、發票和標識符檔的通用字段。
FormTrainingClient
會提供作業以:
- 定型自定義模型,以分析自定義表單中找到的所有欄位和值。 傳回
CustomFormModel
,指出模型所分析的表單類型,以及針對每個表單類型擷取的欄位。 - 將自定義模型定型,以分析您透過標記自定義表單所指定的特定欄位和值。 傳回
CustomFormModel
,指出模型擷取的欄位,以及每個欄位的估計精確度。 - 管理在您的帳戶中建立的模型。
- 將自定義模型從一個 Document Intelligence 資源複製到另一個資源。
備註
模型也可以使用圖形使用者介面來定型,例如 範例卷標工具。
驗證用戶端
在 main
方法頂端,新增下列程序代碼。 您可以使用您先前定義的訂用帳戶變數來驗證兩個客戶端物件。 您可以使用 AzureKeyCredential
物件,因此如有需要,您可以更新密鑰而不建立新的客戶端物件。
FormRecognizerClient recognizerClient = new FormRecognizerClientBuilder()
.credential(new AzureKeyCredential(key)).endpoint(endpoint).buildClient();
FormTrainingClient trainingClient = new FormTrainingClientBuilder().credential(new AzureKeyCredential(key))
.endpoint(endpoint).buildClient();
分析版面配置
您可以使用檔智慧來分析檔中的數據表、線條和文字,而不需要定型模型。 如需版面配置擷取的詳細資訊,請參閱 檔案智慧版面配置模型。
若要分析位於指定 URL 的檔案內容,請使用 beginRecognizeContentFromUrl
方法。
private static void GetContent(FormRecognizerClient recognizerClient, String invoiceUri) {
String analyzeFilePath = invoiceUri;
SyncPoller<FormRecognizerOperationResult, List<FormPage>> recognizeContentPoller = recognizerClient
.beginRecognizeContentFromUrl(analyzeFilePath);
List<FormPage> contentResult = recognizeContentPoller.getFinalResult();
小提示
您也可以從本機檔案取得內容。 請參閱 FormRecognizerClient 方法,例如 beginRecognizeContent
。 或者,針對涉及本機影像的相關案例,請參閱 GitHub (英文) 上的範例程式碼。
傳回的值是 FormPage
物件的集合。 在提交的文件中,每個頁面都有一個物件。 下列程式代碼會逐一查看這些物件,並列印擷取的索引鍵/值組和數據表數據。
contentResult.forEach(formPage -> {
// Table information
System.out.println("----Recognizing content ----");
System.out.printf("Has width: %f and height: %f, measured with unit: %s.%n", formPage.getWidth(),
formPage.getHeight(), formPage.getUnit());
formPage.getTables().forEach(formTable -> {
System.out.printf("Table has %d rows and %d columns.%n", formTable.getRowCount(),
formTable.getColumnCount());
formTable.getCells().forEach(formTableCell -> {
System.out.printf("Cell has text %s.%n", formTableCell.getText());
});
System.out.println();
});
});
}
結果看起來像下列輸出。
Get form content...
----Recognizing content ----
Has width: 8.500000 and height: 11.000000, measured with unit: inch.
Table has 2 rows and 6 columns.
Cell has text Invoice Number.
Cell has text Invoice Date.
Cell has text Invoice Due Date.
Cell has text Charges.
Cell has text VAT ID.
Cell has text 458176.
Cell has text 3/28/2018.
Cell has text 4/16/2018.
Cell has text $89,024.34.
Cell has text ET.
分析收據
本節示範如何使用預先定型的收據模型,從美國收據分析及擷取通用字段。 如需收據分析的詳細資訊,請參閱 Document Intelligence 收據模型。
若要分析來自 URI 的收據,請使用 beginRecognizeReceiptsFromUrl
方法。
private static void AnalyzeReceipt(FormRecognizerClient recognizerClient, String receiptUri) {
SyncPoller<FormRecognizerOperationResult, List<RecognizedForm>> syncPoller = recognizerClient
.beginRecognizeReceiptsFromUrl(receiptUri);
List<RecognizedForm> receiptPageResults = syncPoller.getFinalResult();
小提示
您也可以分析本地收據圖像。 請參閱 FormRecognizerClient 方法,例如 beginRecognizeReceipts
。 或者,針對涉及本機影像的相關案例,請參閱 GitHub (英文) 上的範例程式碼。
傳回的值是 RecognizedReceipt
物件的集合。 在提交的文件中,每個頁面都有一個物件。 下一個程式代碼區塊會逐一查看收據,並將其詳細數據列印至主控台。
for (int i = 0; i < receiptPageResults.size(); i++) {
RecognizedForm recognizedForm = receiptPageResults.get(i);
Map<String, FormField> recognizedFields = recognizedForm.getFields();
System.out.printf("----------- Recognized Receipt page %d -----------%n", i);
FormField merchantNameField = recognizedFields.get("MerchantName");
if (merchantNameField != null) {
if (FieldValueType.STRING == merchantNameField.getValue().getValueType()) {
String merchantName = merchantNameField.getValue().asString();
System.out.printf("Merchant Name: %s, confidence: %.2f%n", merchantName,
merchantNameField.getConfidence());
}
}
FormField merchantAddressField = recognizedFields.get("MerchantAddress");
if (merchantAddressField != null) {
if (FieldValueType.STRING == merchantAddressField.getValue().getValueType()) {
String merchantAddress = merchantAddressField.getValue().asString();
System.out.printf("Merchant Address: %s, confidence: %.2f%n", merchantAddress,
merchantAddressField.getConfidence());
}
}
FormField transactionDateField = recognizedFields.get("TransactionDate");
if (transactionDateField != null) {
if (FieldValueType.DATE == transactionDateField.getValue().getValueType()) {
LocalDate transactionDate = transactionDateField.getValue().asDate();
System.out.printf("Transaction Date: %s, confidence: %.2f%n", transactionDate,
transactionDateField.getConfidence());
}
}
下一個代碼區塊會遍歷收據上偵測到的個別項,並將其詳細資料列印至控制台。
FormField receiptItemsField = recognizedFields.get("Items");
if (receiptItemsField != null) {
System.out.printf("Receipt Items: %n");
if (FieldValueType.LIST == receiptItemsField.getValue().getValueType()) {
List<FormField> receiptItems = receiptItemsField.getValue().asList();
receiptItems.stream()
.filter(receiptItem -> FieldValueType.MAP == receiptItem.getValue().getValueType())
.map(formField -> formField.getValue().asMap())
.forEach(formFieldMap -> formFieldMap.forEach((key, formField) -> {
if ("Name".equals(key)) {
if (FieldValueType.STRING == formField.getValue().getValueType()) {
String name = formField.getValue().asString();
System.out.printf("Name: %s, confidence: %.2fs%n", name,
formField.getConfidence());
}
}
if ("Quantity".equals(key)) {
if (FieldValueType.FLOAT == formField.getValue().getValueType()) {
Float quantity = formField.getValue().asFloat();
System.out.printf("Quantity: %f, confidence: %.2f%n", quantity,
formField.getConfidence());
}
}
if ("Price".equals(key)) {
if (FieldValueType.FLOAT == formField.getValue().getValueType()) {
Float price = formField.getValue().asFloat();
System.out.printf("Price: %f, confidence: %.2f%n", price,
formField.getConfidence());
}
}
if ("TotalPrice".equals(key)) {
if (FieldValueType.FLOAT == formField.getValue().getValueType()) {
Float totalPrice = formField.getValue().asFloat();
System.out.printf("Total Price: %f, confidence: %.2f%n", totalPrice,
formField.getConfidence());
}
}
}));
}
}
}
}
結果看起來像下列輸出。
Analyze receipt...
----------- Recognized Receipt page 0 -----------
Merchant Name: Contoso Contoso, confidence: 0.62
Merchant Address: 123 Main Street Redmond, WA 98052, confidence: 0.99
Transaction Date: 2020-06-10, confidence: 0.90
Receipt Items:
Name: Cappuccino, confidence: 0.96s
Quantity: null, confidence: 0.957s]
Total Price: 2.200000, confidence: 0.95
Name: BACON & EGGS, confidence: 0.94s
Quantity: null, confidence: 0.927s]
Total Price: null, confidence: 0.93
分析名片
本節示範如何使用預先定型的模型,從英文名片分析和擷取通用字段。 如需名片分析的詳細資訊,請參閱 Document Intelligence 名片模型。
若要從 URL 分析名片,請使用 beginRecognizeBusinessCardsFromUrl
方法。
private static void AnalyzeBusinessCard(FormRecognizerClient recognizerClient, String bcUrl) {
SyncPoller < FormRecognizerOperationResult,
List < RecognizedForm >> recognizeBusinessCardPoller = client.beginRecognizeBusinessCardsFromUrl(businessCardUrl);
List < RecognizedForm > businessCardPageResults = recognizeBusinessCardPoller.getFinalResult();
小提示
您也可以分析本機名片影像。 請參閱 FormRecognizerClient 方法,例如 beginRecognizeBusinessCards
。 或者,針對涉及本機影像的相關案例,請參閱 GitHub (英文) 上的範例程式碼。
傳回的值是 RecognizedForm
物件的集合。 文件中每張卡片都有一個物件。 下列程式代碼會處理指定 URI 上的名片,並將主要欄位和值列印至主控台。
for (int i = 0; i < businessCardPageResults.size(); i++) {
RecognizedForm recognizedForm = businessCardPageResults.get(i);
Map < String,
FormField > recognizedFields = recognizedForm.getFields();
System.out.printf("----------- Recognized business card info for page %d -----------%n", i);
FormField contactNamesFormField = recognizedFields.get("ContactNames");
if (contactNamesFormField != null) {
if (FieldValueType.LIST == contactNamesFormField.getValue().getValueType()) {
List < FormField > contactNamesList = contactNamesFormField.getValue().asList();
contactNamesList.stream().filter(contactName - >FieldValueType.MAP == contactName.getValue().getValueType()).map(contactName - >{
System.out.printf("Contact name: %s%n", contactName.getValueData().getText());
return contactName.getValue().asMap();
}).forEach(contactNamesMap - >contactNamesMap.forEach((key, contactName) - >{
if ("FirstName".equals(key)) {
if (FieldValueType.STRING == contactName.getValue().getValueType()) {
String firstName = contactName.getValue().asString();
System.out.printf("\tFirst Name: %s, confidence: %.2f%n", firstName, contactName.getConfidence());
}
}
if ("LastName".equals(key)) {
if (FieldValueType.STRING == contactName.getValue().getValueType()) {
String lastName = contactName.getValue().asString();
System.out.printf("\tLast Name: %s, confidence: %.2f%n", lastName, contactName.getConfidence());
}
}
}));
}
}
FormField jobTitles = recognizedFields.get("JobTitles");
if (jobTitles != null) {
if (FieldValueType.LIST == jobTitles.getValue().getValueType()) {
List < FormField > jobTitlesItems = jobTitles.getValue().asList();
jobTitlesItems.stream().forEach(jobTitlesItem - >{
if (FieldValueType.STRING == jobTitlesItem.getValue().getValueType()) {
String jobTitle = jobTitlesItem.getValue().asString();
System.out.printf("Job Title: %s, confidence: %.2f%n", jobTitle, jobTitlesItem.getConfidence());
}
});
}
}
FormField departments = recognizedFields.get("Departments");
if (departments != null) {
if (FieldValueType.LIST == departments.getValue().getValueType()) {
List < FormField > departmentsItems = departments.getValue().asList();
departmentsItems.stream().forEach(departmentsItem - >{
if (FieldValueType.STRING == departmentsItem.getValue().getValueType()) {
String department = departmentsItem.getValue().asString();
System.out.printf("Department: %s, confidence: %.2f%n", department, departmentsItem.getConfidence());
}
});
}
}
FormField emails = recognizedFields.get("Emails");
if (emails != null) {
if (FieldValueType.LIST == emails.getValue().getValueType()) {
List < FormField > emailsItems = emails.getValue().asList();
emailsItems.stream().forEach(emailsItem - >{
if (FieldValueType.STRING == emailsItem.getValue().getValueType()) {
String email = emailsItem.getValue().asString();
System.out.printf("Email: %s, confidence: %.2f%n", email, emailsItem.getConfidence());
}
});
}
}
FormField websites = recognizedFields.get("Websites");
if (websites != null) {
if (FieldValueType.LIST == websites.getValue().getValueType()) {
List < FormField > websitesItems = websites.getValue().asList();
websitesItems.stream().forEach(websitesItem - >{
if (FieldValueType.STRING == websitesItem.getValue().getValueType()) {
String website = websitesItem.getValue().asString();
System.out.printf("Web site: %s, confidence: %.2f%n", website, websitesItem.getConfidence());
}
});
}
}
FormField mobilePhones = recognizedFields.get("MobilePhones");
if (mobilePhones != null) {
if (FieldValueType.LIST == mobilePhones.getValue().getValueType()) {
List < FormField > mobilePhonesItems = mobilePhones.getValue().asList();
mobilePhonesItems.stream().forEach(mobilePhonesItem - >{
if (FieldValueType.PHONE_NUMBER == mobilePhonesItem.getValue().getValueType()) {
String mobilePhoneNumber = mobilePhonesItem.getValue().asPhoneNumber();
System.out.printf("Mobile phone number: %s, confidence: %.2f%n", mobilePhoneNumber, mobilePhonesItem.getConfidence());
}
});
}
}
FormField otherPhones = recognizedFields.get("OtherPhones");
if (otherPhones != null) {
if (FieldValueType.LIST == otherPhones.getValue().getValueType()) {
List < FormField > otherPhonesItems = otherPhones.getValue().asList();
otherPhonesItems.stream().forEach(otherPhonesItem - >{
if (FieldValueType.PHONE_NUMBER == otherPhonesItem.getValue().getValueType()) {
String otherPhoneNumber = otherPhonesItem.getValue().asPhoneNumber();
System.out.printf("Other phone number: %s, confidence: %.2f%n", otherPhoneNumber, otherPhonesItem.getConfidence());
}
});
}
}
FormField faxes = recognizedFields.get("Faxes");
if (faxes != null) {
if (FieldValueType.LIST == faxes.getValue().getValueType()) {
List < FormField > faxesItems = faxes.getValue().asList();
faxesItems.stream().forEach(faxesItem - >{
if (FieldValueType.PHONE_NUMBER == faxesItem.getValue().getValueType()) {
String faxPhoneNumber = faxesItem.getValue().asPhoneNumber();
System.out.printf("Fax phone number: %s, confidence: %.2f%n", faxPhoneNumber, faxesItem.getConfidence());
}
});
}
}
FormField addresses = recognizedFields.get("Addresses");
if (addresses != null) {
if (FieldValueType.LIST == addresses.getValue().getValueType()) {
List < FormField > addressesItems = addresses.getValue().asList();
addressesItems.stream().forEach(addressesItem - >{
if (FieldValueType.STRING == addressesItem.getValue().getValueType()) {
String address = addressesItem.getValue().asString();
System.out.printf("Address: %s, confidence: %.2f%n", address, addressesItem.getConfidence());
}
});
}
}
FormField companyName = recognizedFields.get("CompanyNames");
if (companyName != null) {
if (FieldValueType.LIST == companyName.getValue().getValueType()) {
List < FormField > companyNameItems = companyName.getValue().asList();
companyNameItems.stream().forEach(companyNameItem - >{
if (FieldValueType.STRING == companyNameItem.getValue().getValueType()) {
String companyNameValue = companyNameItem.getValue().asString();
System.out.printf("Company name: %s, confidence: %.2f%n", companyNameValue, companyNameItem.getConfidence());
}
});
}
}
}
}
分析發票
本節示範如何使用預先定型的模型,分析及擷取銷售發票中的一般字段。 如需發票分析的詳細資訊,請參閱 Document Intelligence 發票模型。
若要從 URL 分析發票,請使用 beginRecognizeInvoicesFromUrl
方法。
private static void AnalyzeInvoice(FormRecognizerClient recognizerClient, String invoiceUrl) {
SyncPoller < FormRecognizerOperationResult,
List < RecognizedForm >> recognizeInvoicesPoller = client.beginRecognizeInvoicesFromUrl(invoiceUrl);
List < RecognizedForm > recognizedInvoices = recognizeInvoicesPoller.getFinalResult();
小提示
您也可以分析本地發票。 請參閱 FormRecognizerClient 方法,例如 beginRecognizeInvoices
。 或者,針對涉及本機影像的相關案例,請參閱 GitHub (英文) 上的範例程式碼。
傳回的值是 RecognizedForm
物件的集合。 文件中每張發票都有一個物件。 下列程式代碼會處理指定 URI 上的發票,並將主要欄位和值列印至主控台。
for (int i = 0; i < recognizedInvoices.size(); i++) {
RecognizedForm recognizedInvoice = recognizedInvoices.get(i);
Map < String,
FormField > recognizedFields = recognizedInvoice.getFields();
System.out.printf("----------- Recognized invoice info for page %d -----------%n", i);
FormField vendorNameField = recognizedFields.get("VendorName");
if (vendorNameField != null) {
if (FieldValueType.STRING == vendorNameField.getValue().getValueType()) {
String merchantName = vendorNameField.getValue().asString();
System.out.printf("Vendor Name: %s, confidence: %.2f%n", merchantName, vendorNameField.getConfidence());
}
}
FormField vendorAddressField = recognizedFields.get("VendorAddress");
if (vendorAddressField != null) {
if (FieldValueType.STRING == vendorAddressField.getValue().getValueType()) {
String merchantAddress = vendorAddressField.getValue().asString();
System.out.printf("Vendor address: %s, confidence: %.2f%n", merchantAddress, vendorAddressField.getConfidence());
}
}
FormField customerNameField = recognizedFields.get("CustomerName");
if (customerNameField != null) {
if (FieldValueType.STRING == customerNameField.getValue().getValueType()) {
String merchantAddress = customerNameField.getValue().asString();
System.out.printf("Customer Name: %s, confidence: %.2f%n", merchantAddress, customerNameField.getConfidence());
}
}
FormField customerAddressRecipientField = recognizedFields.get("CustomerAddressRecipient");
if (customerAddressRecipientField != null) {
if (FieldValueType.STRING == customerAddressRecipientField.getValue().getValueType()) {
String customerAddr = customerAddressRecipientField.getValue().asString();
System.out.printf("Customer Address Recipient: %s, confidence: %.2f%n", customerAddr, customerAddressRecipientField.getConfidence());
}
}
FormField invoiceIdField = recognizedFields.get("InvoiceId");
if (invoiceIdField != null) {
if (FieldValueType.STRING == invoiceIdField.getValue().getValueType()) {
String invoiceId = invoiceIdField.getValue().asString();
System.out.printf("Invoice Id: %s, confidence: %.2f%n", invoiceId, invoiceIdField.getConfidence());
}
}
FormField invoiceDateField = recognizedFields.get("InvoiceDate");
if (customerNameField != null) {
if (FieldValueType.DATE == invoiceDateField.getValue().getValueType()) {
LocalDate invoiceDate = invoiceDateField.getValue().asDate();
System.out.printf("Invoice Date: %s, confidence: %.2f%n", invoiceDate, invoiceDateField.getConfidence());
}
}
FormField invoiceTotalField = recognizedFields.get("InvoiceTotal");
if (customerAddressRecipientField != null) {
if (FieldValueType.FLOAT == invoiceTotalField.getValue().getValueType()) {
Float invoiceTotal = invoiceTotalField.getValue().asFloat();
System.out.printf("Invoice Total: %.2f, confidence: %.2f%n", invoiceTotal, invoiceTotalField.getConfidence());
}
}
}
}
分析身分證明文件
本節示範如何使用文件智慧預先建置的標識符模型,分析及擷取政府簽發的身份證中的關鍵資訊—全球護照和美國駕照。 如需了解更多關於身份證件分析的資訊,請參閱 文件智能身份證件模型。
若要從 URI 分析識別碼檔,請使用 beginRecognizeIdentityDocumentsFromUrl
方法。
private static void AnalyzeId(FormRecognizerClient client, String idUrl) {
SyncPoller < FormRecognizerOperationResult,
List < RecognizedForm >> analyzeIdentityDocumentPoller = client.beginRecognizeIdentityDocumentsFromUrl(licenseDocumentUrl);
List < RecognizedForm > identityDocumentResults = analyzeIdentityDocumentPoller.getFinalResult();
小提示
您也可以分析本機身分證明文件影像。 請參閱 FormRecognizerClient 方法,例如 beginRecognizeIdentityDocuments
。 此外,如需涉及本機影像的案例,請參閱 GitHub 上的範例程式代碼。
下列程式代碼會處理位於指定 URI 的識別碼檔,並將主要欄位和值列印至主控台。
for (int i = 0; i < identityDocumentResults.size(); i++) {
RecognizedForm recognizedForm = identityDocumentResults.get(i);
Map < String,
FormField > recognizedFields = recognizedForm.getFields();
System.out.printf("----------- Recognized license info for page %d -----------%n", i);
FormField addressField = recognizedFields.get("Address");
if (addressField != null) {
if (FieldValueType.STRING == addressField.getValue().getValueType()) {
String address = addressField.getValue().asString();
System.out.printf("Address: %s, confidence: %.2f%n", address, addressField.getConfidence());
}
}
FormField countryRegionFormField = recognizedFields.get("CountryRegion");
if (countryRegionFormField != null) {
if (FieldValueType.STRING == countryRegionFormField.getValue().getValueType()) {
String countryRegion = countryRegionFormField.getValue().asCountryRegion();
System.out.printf("Country or region: %s, confidence: %.2f%n", countryRegion, countryRegionFormField.getConfidence());
}
}
FormField dateOfBirthField = recognizedFields.get("DateOfBirth");
if (dateOfBirthField != null) {
if (FieldValueType.DATE == dateOfBirthField.getValue().getValueType()) {
LocalDate dateOfBirth = dateOfBirthField.getValue().asDate();
System.out.printf("Date of Birth: %s, confidence: %.2f%n", dateOfBirth, dateOfBirthField.getConfidence());
}
}
FormField dateOfExpirationField = recognizedFields.get("DateOfExpiration");
if (dateOfExpirationField != null) {
if (FieldValueType.DATE == dateOfExpirationField.getValue().getValueType()) {
LocalDate expirationDate = dateOfExpirationField.getValue().asDate();
System.out.printf("Document date of expiration: %s, confidence: %.2f%n", expirationDate, dateOfExpirationField.getConfidence());
}
}
FormField documentNumberField = recognizedFields.get("DocumentNumber");
if (documentNumberField != null) {
if (FieldValueType.STRING == documentNumberField.getValue().getValueType()) {
String documentNumber = documentNumberField.getValue().asString();
System.out.printf("Document number: %s, confidence: %.2f%n", documentNumber, documentNumberField.getConfidence());
}
}
FormField firstNameField = recognizedFields.get("FirstName");
if (firstNameField != null) {
if (FieldValueType.STRING == firstNameField.getValue().getValueType()) {
String firstName = firstNameField.getValue().asString();
System.out.printf("First Name: %s, confidence: %.2f%n", firstName, documentNumberField.getConfidence());
}
}
FormField lastNameField = recognizedFields.get("LastName");
if (lastNameField != null) {
if (FieldValueType.STRING == lastNameField.getValue().getValueType()) {
String lastName = lastNameField.getValue().asString();
System.out.printf("Last name: %s, confidence: %.2f%n", lastName, lastNameField.getConfidence());
}
}
FormField regionField = recognizedFields.get("Region");
if (regionField != null) {
if (FieldValueType.STRING == regionField.getValue().getValueType()) {
String region = regionField.getValue().asString();
System.out.printf("Region: %s, confidence: %.2f%n", region, regionField.getConfidence());
}
}
}
訓練自訂模型
本節示範如何使用您自己的數據來定型模型。 定型的模型可以輸出結構化數據,其中包含源檔中的索引鍵/值關聯性。 定型模型之後,您可以測試、重新定型,並最終使用它,根據需求可靠地從更多窗體中擷取數據。
備註
您也可以使用圖形使用者介面來定型模型,例如 檔案智慧範例標籤工具。
訓練不含標籤的模型
訓練自定義模型,以分析自定義表單中找到的所有欄位和值,而不需手動標記訓練檔。
下列方法會將模型定型在一組指定的檔上,並將模型的狀態列印至主控台。
private static String TrainModel(FormTrainingClient trainingClient, String trainingDataUrl) {
SyncPoller<FormRecognizerOperationResult, CustomFormModel> trainingPoller = trainingClient
.beginTraining(trainingDataUrl, false);
CustomFormModel customFormModel = trainingPoller.getFinalResult();
// Model Info
System.out.printf("Model Id: %s%n", customFormModel.getModelId());
System.out.printf("Model Status: %s%n", customFormModel.getModelStatus());
System.out.printf("Training started on: %s%n", customFormModel.getTrainingStartedOn());
System.out.printf("Training completed on: %s%n%n", customFormModel.getTrainingCompletedOn());
傳回 CustomFormModel
物件包含模型可分析之表單類型的相關信息,以及可從每個表單類型擷取的欄位。 下列程式代碼區塊會將此資訊列印至主控台。
System.out.println("Recognized Fields:");
// looping through the subModels, which contains the fields they were trained on
// Since the given training documents are unlabeled, we still group them but
// they do not have a label.
customFormModel.getSubmodels().forEach(customFormSubmodel -> {
// Since the training data is unlabeled, we are unable to return the accuracy of
// this model
System.out.printf("The subModel has form type %s%n", customFormSubmodel.getFormType());
customFormSubmodel.getFields().forEach((field, customFormModelField) -> System.out
.printf("The model found field '%s' with label: %s%n", field, customFormModelField.getLabel()));
});
最後,這個方法會傳回模型的唯一標識符。
return customFormModel.getModelId();
}
結果看起來像下列輸出。
Train Model with training data...
Model Id: 20c3544d-97b4-49d9-b39b-dc32d85f1358
Model Status: ready
Training started on: 2020-08-31T16:52:09Z
Training completed on: 2020-08-31T16:52:23Z
Recognized Fields:
The subModel has form type form-0
The model found field 'field-0' with label: Address:
The model found field 'field-1' with label: Charges
The model found field 'field-2' with label: Invoice Date
The model found field 'field-3' with label: Invoice Due Date
The model found field 'field-4' with label: Invoice For:
The model found field 'field-5' with label: Invoice Number
The model found field 'field-6' with label: VAT ID
訓練具備標籤的模型
您也可以手動標記訓練文件來訓練自訂模型。 在某些情況下,使用標籤來訓練會讓效能更佳。 若要使用標籤來訓練,您的 Blob 儲存體容器中除了訓練文件以外,還必須要有特殊的標籤資訊檔案 (<filename>.pdf.labels.json)。 檔智慧範例卷標工具 提供使用者介面,協助您建立這些標籤檔案。 取得它們之後,您可以呼叫 beginTraining
方法,並將 useTrainingLabels
參數設定為 true
。
private static String TrainModelWithLabels(FormTrainingClient trainingClient, String trainingDataUrl) {
// Train custom model
String trainingSetSource = trainingDataUrl;
SyncPoller<FormRecognizerOperationResult, CustomFormModel> trainingPoller = trainingClient
.beginTraining(trainingSetSource, true);
CustomFormModel customFormModel = trainingPoller.getFinalResult();
// Model Info
System.out.printf("Model Id: %s%n", customFormModel.getModelId());
System.out.printf("Model Status: %s%n", customFormModel.getModelStatus());
System.out.printf("Training started on: %s%n", customFormModel.getTrainingStartedOn());
System.out.printf("Training completed on: %s%n%n", customFormModel.getTrainingCompletedOn());
傳回的 CustomFormModel
會指出模型可以擷取的欄位,以及其在每個欄位中的估計精確度。 下列程式代碼區塊會將此資訊列印至主控台。
// looping through the subModels, which contains the fields they were trained on
// The labels are based on the ones you gave the training document.
System.out.println("Recognized Fields:");
// Since the data is labeled, we are able to return the accuracy of the model
customFormModel.getSubmodels().forEach(customFormSubmodel -> {
System.out.printf("The subModel with form type %s has accuracy: %.2f%n", customFormSubmodel.getFormType(),
customFormSubmodel.getAccuracy());
customFormSubmodel.getFields()
.forEach((label, customFormModelField) -> System.out.printf(
"The model found field '%s' to have name: %s with an accuracy: %.2f%n", label,
customFormModelField.getName(), customFormModelField.getAccuracy()));
});
return customFormModel.getModelId();
}
結果看起來像下列輸出。
Train Model with training data...
Model Id: 20c3544d-97b4-49d9-b39b-dc32d85f1358
Model Status: ready
Training started on: 2020-08-31T16:52:09Z
Training completed on: 2020-08-31T16:52:23Z
Recognized Fields:
The subModel has form type form-0
The model found field 'field-0' with label: Address:
The model found field 'field-1' with label: Charges
The model found field 'field-2' with label: Invoice Date
The model found field 'field-3' with label: Invoice Due Date
The model found field 'field-4' with label: Invoice For:
The model found field 'field-5' with label: Invoice Number
The model found field 'field-6' with label: VAT ID
使用自定義模型分析表單
本節示範如何使用以自身表單訓練的模型,從您的自訂範本類型中擷取機碼/值資訊和其他內容。
這很重要
若要實作此案例,您必須已經將模型定型,才能將其標識碼傳遞至方法作業。 請參閱訓練具備標籤的模型。
使用 beginRecognizeCustomFormsFromUrl
方法。
// Analyze PDF form data
private static void AnalyzePdfForm(FormRecognizerClient formClient, String modelId, String pdfFormUrl) {
SyncPoller<FormRecognizerOperationResult, List<RecognizedForm>> recognizeFormPoller = formClient
.beginRecognizeCustomFormsFromUrl(modelId, pdfFormUrl);
List<RecognizedForm> recognizedForms = recognizeFormPoller.getFinalResult();
小提示
您也可以分析本機檔案。 請參閱 FormRecognizerClient 方法,例如 beginRecognizeCustomForms
。 或者,針對涉及本機影像的相關案例,請參閱 GitHub (英文) 上的範例程式碼。
傳回的值是 RecognizedForm
物件的集合。 在提交的文件中,每個頁面都有一個物件。 下列程式代碼會將分析結果列印至主控台。 它會列印每個已辨識的字段和對應的值,以及信賴分數。
for (int i = 0; i < recognizedForms.size(); i++) {
final RecognizedForm form = recognizedForms.get(i);
System.out.printf("----------- Recognized custom form info for page %d -----------%n", i);
System.out.printf("Form type: %s%n", form.getFormType());
form.getFields().forEach((label, formField) ->
// label data is populated if you are using a model trained with unlabeled data,
// since the service needs to make predictions for labels if not explicitly
// given to it.
System.out.printf("Field '%s' has label '%s' with a confidence " + "score of %.2f.%n", label,
formField.getLabelData().getText(), formField.getConfidence()));
}
}
結果看起來像下列輸出。
Analyze PDF form...
----------- Recognized custom template info for page 0 -----------
Form type: form-0
Field 'field-0' has label 'Address:' with a confidence score of 0.91.
Field 'field-1' has label 'Invoice For:' with a confidence score of 1.00.
Field 'field-2' has label 'Invoice Number' with a confidence score of 1.00.
Field 'field-3' has label 'Invoice Date' with a confidence score of 1.00.
Field 'field-4' has label 'Invoice Due Date' with a confidence score of 1.00.
Field 'field-5' has label 'Charges' with a confidence score of 1.00.
Field 'field-6' has label 'VAT ID' with a confidence score of 1.00.
管理自定義模型
本節示範如何管理帳戶中儲存的自定義模型。 下列程式代碼會在單一方法中執行所有模型管理工作,例如。 從複製下列方法簽章開始:
private static void ManageModels(FormTrainingClient trainingClient, String trainingFileUrl) {
檢查 FormRecognizer 資源帳戶中的模型數目
下列程式代碼區塊會檢查您在 Document Intelligence 帳戶中儲存的模型數目,並將其與帳戶限制進行比較。
AtomicReference<String> modelId = new AtomicReference<>();
// First, we see how many custom models we have, and what our limit is
AccountProperties accountProperties = trainingClient.getAccountProperties();
System.out.printf("The account has %s custom models, and we can have at most %s custom models",
accountProperties.getCustomModelCount(), accountProperties.getCustomModelLimit());
結果看起來像下列輸出。
The account has 12 custom models, and we can have at most 250 custom models
列出目前儲存在資源帳戶中的模型
下列程式代碼會封鎖您的帳戶中目前的模型,並將其詳細數據列印至主控台。
// Next, we get a paged list of all of our custom models
PagedIterable<CustomFormModelInfo> customModels = trainingClient.listCustomModels();
System.out.println("We have following models in the account:");
customModels.forEach(customFormModelInfo -> {
System.out.printf("Model Id: %s%n", customFormModelInfo.getModelId());
// get custom model info
modelId.set(customFormModelInfo.getModelId());
CustomFormModel customModel = trainingClient.getCustomModel(customFormModelInfo.getModelId());
System.out.printf("Model Id: %s%n", customModel.getModelId());
System.out.printf("Model Status: %s%n", customModel.getModelStatus());
System.out.printf("Training started on: %s%n", customModel.getTrainingStartedOn());
System.out.printf("Training completed on: %s%n", customModel.getTrainingCompletedOn());
customModel.getSubmodels().forEach(customFormSubmodel -> {
System.out.printf("Custom Model Form type: %s%n", customFormSubmodel.getFormType());
System.out.printf("Custom Model Accuracy: %.2f%n", customFormSubmodel.getAccuracy());
if (customFormSubmodel.getFields() != null) {
customFormSubmodel.getFields().forEach((fieldText, customFormModelField) -> {
System.out.printf("Field Text: %s%n", fieldText);
System.out.printf("Field Accuracy: %.2f%n", customFormModelField.getAccuracy());
});
}
});
});
結果看起來像下列輸出。
此回應已截斷,以取得可讀性。
We have following models in the account:
Model Id: 0b048b60-86cc-47ec-9782-ad0ffaf7a5ce
Model Id: 0b048b60-86cc-47ec-9782-ad0ffaf7a5ce
Model Status: ready
Training started on: 2020-06-04T18:33:08Z
Training completed on: 2020-06-04T18:33:10Z
Custom Model Form type: form-0b048b60-86cc-47ec-9782-ad0ffaf7a5ce
Custom Model Accuracy: 1.00
Field Text: invoice date
Field Accuracy: 1.00
Field Text: invoice number
Field Accuracy: 1.00
...
從資源帳戶刪除模型
您也可以參考其識別碼,從您的帳戶中刪除模型。
// Delete Custom Model
System.out.printf("Deleted model with model Id: %s, operation completed with status: %s%n", modelId.get(),
trainingClient.deleteModelWithResponse(modelId.get(), Context.NONE).getStatusCode());
}
執行應用程式
流覽回您的主要項目目錄。 然後,使用下列命令建置應用程式:
gradle build
使用 run
目標執行應用程式:
gradle run
清理資源
如果您想要清除和移除 Azure AI 服務訂用帳戶,則可以刪除資源或資源群組。 刪除資源群組也會刪除與其相關聯的任何其他資源。
故障排除
文件智慧服務用戶端會引發 ErrorResponseException
例外狀況。 例如,如果您嘗試提供無效的檔案來源 URL,就會引發 ErrorResponseException
,並出現指出失敗原因的錯誤。 在下列代碼段中,會藉由捕捉例外並顯示與錯誤相關的附加資訊,以正常方式處理錯誤。
try {
formRecognizerClient.beginRecognizeContentFromUrl("invalidSourceUrl");
} catch (ErrorResponseException e) {
System.out.println(e.getMessage());
}
啟用用戶端記錄
適用於 Java 的 Azure SDK 提供一致的記錄案例,協助針對應用程式錯誤進行疑難解答並加速解決。 記錄會在到達最終狀態之前捕捉應用程式的運行流程,以協助找出根本問題。 如需啟用記錄的詳細資訊,請參閱記錄 Wiki (英文)。
後續步驟
在此專案中,您已使用 Document Intelligence Java 用戶端連結庫,以不同方式定型模型和分析表單。 接下來,瞭解建立更佳訓練數據集的秘訣,並產生更精確的模型。
這很重要
此項目的目標是 Document Intelligence REST API 2.1 版。
參考文件 | 程式庫來源程式碼 | 套件 (npm) | 範例
先決條件
Azure 訂用帳戶 - 免費建立一個訂用帳戶。
最新版的 Visual Studio Code。
Node.js的最新 LTS 版本。
包含一組訓練資料的 Azure 儲存 Blob。 如需組合您的訓練數據集的提示和選項,請參閱 建置和訓練自定義模型。 在此專案中,您可以使用 Train 資料夾中的檔案,這些檔案位於 範例數據集下。 下載並擷取 sample_data.zip。
Azure AI 服務或文件智慧服務資源。 建立文件智能資源。 您可以使用免費定價層 (
F0
) 來試用服務,之後可升級至付費層以用於實際執行環境。從您所建立資源的金鑰和端點,將應用程式連線至 Azure 文件智慧服務。
- 部署資源之後,請選取 [前往資源]。
- 在左側導覽功能表中,選取 [金鑰和端點]。
- 複製其中一個金鑰和 端點,以供本文稍後使用。
設定程式設計環境
建立應用程式並安裝客戶端連結庫。
建立新的 Node.js 應用程式
在主控台視窗中,建立應用程式的目錄,然後流覽至它。
mkdir myapp cd myapp
執行
npm init
命令以使用 package.json 檔案建立節點應用程式。npm init
安裝用戶端程式庫
安裝
ai-form-recognizer
npm 套件:npm install @azure/ai-form-recognizer
您應用程式的 package.json 檔案會隨著相依項目更新。
建立名為 index.js的檔案,加以開啟,然後匯入下列連結庫:
const { FormRecognizerClient, FormTrainingClient, AzureKeyCredential } = require("@azure/ai-form-recognizer"); const fs = require("fs");
為資源的 Azure 端點和金鑰建立變數。
const apiKey = "PASTE_YOUR_FORM_RECOGNIZER_SUBSCRIPTION_KEY_HERE"; const endpoint = "PASTE_YOUR_FORM_RECOGNIZER_ENDPOINT_HERE";
這很重要
前往 Azure 入口網站。 如果已成功部署您在 [必要條件] 區段中所建立的文件智慧服務資源,請在 [後續步驟] 下選取 [前往資源]。 您可以在 [金鑰] 和 [端點]底下的 [資源管理] 中找到您的金鑰和端點。
當您完成時,請記得從程式碼中移除金鑰。 永遠不要公開發佈它。 針對生產環境,請使用安全方法來儲存和存取您的認證。 如需詳細資訊,請參閱 Azure AI 服務安全性。
使用物件模型
使用文件智慧,您可以建立兩種不同的客戶端類型。 第一個是 FormRecognizerClient
,會查詢服務,以辨識出表單欄位和內容。 第二個 FormTrainingClient
會建立及管理自定義模型,以改善辨識。
FormRecognizerClient
提供下列作業:
- 使用定型的自定義模型來分析自定義表單,來辨識表單域和內容。 這些值會在
RecognizedForm
物件的集合中傳回。 - 辨識表單內容,包括資料表、線條和單字,而不需要訓練模型。 表單內容會在
FormPage
物件的集合中傳回。 - 使用文件智慧服務的預先定型模型,辨識來自美國收據、名片、發票和標識符檔的通用字段。
FormTrainingClient
會提供作業以:
- 定型自定義模型,以分析自定義表單中找到的所有欄位和值。 傳回
CustomFormModel
,指出模型所分析的表單類型,以及針對每個表單類型擷取的欄位。 如需詳細資訊,請參閱 服務的未標記模型訓練文件。 - 將自定義模型定型,以分析您透過標記自定義表單所指定的特定欄位和值。 傳回
CustomFormModel
,指出模型擷取的欄位,以及每個欄位的估計精確度。 如需詳細資訊,請參閱本文中的訓練具備標籤的模型。 - 管理在您的帳戶中建立的模型。
- 將自定義模型從一個 Document Intelligence 資源複製到另一個資源。
備註
您也可以使用圖形使用者介面來定型模型,例如 範例標籤工具。
驗證用戶端
使用您定義的訂用帳戶變數來驗證客戶端物件。 使用 AzureKeyCredential
物件,因此如有需要,您可以更新金鑰而不建立新的客戶端物件。 您還可以建立訓練用戶端物件。
const trainingClient = new FormTrainingClient(endpoint, new AzureKeyCredential(apiKey));
const client = new FormRecognizerClient(endpoint, new AzureKeyCredential(apiKey));
取得用於測試的資產
您也需要為訓練和測試資料新增 URL 的參考。
若要擷取自定義模型定型數據的SAS URL,請移至 Azure 入口網站中的記憶體資源,然後選取 [資料記憶體]>[容器]。
瀏覽至您的容器,按下滑鼠右鍵,然後選取 產生 SAS。
取得您容器的 SAS,而不是儲存體帳戶本身的 SAS。
請確定已選取 讀取、寫入、刪除和 列出 許可權,然後選取 產生 SAS 令牌和 URL。
將 [URL] 區段中的值複製到暫存位置。 其格式應該為:
https://<storage account>.blob.core.windows.net/<container name>?<SAS value>
。
使用範例中包含的收據影像。 這些圖片也可在 GitHub取得。 您可以使用上述步驟來取得 Blob 記憶體中個別檔的 SAS URL。
分析版面配置
您可以使用檔智慧來分析檔中的數據表、線條和文字,而不需要定型模型。 如需版面配置擷取的詳細資訊,請參閱 檔案智慧版面配置模型。 若要分析位於指定 URI 的檔案內容,請使用 beginRecognizeContentFromUrl
方法。
async function recognizeContent() {
const formUrl = "https://raw.githubusercontent.com/Azure-Samples/cognitive-services-REST-api-samples/master/curl/form-recognizer/simple-invoice.png";
const poller = await client.beginRecognizeContentFromUrl(formUrl);
const pages = await poller.pollUntilDone();
if (!pages || pages.length === 0) {
throw new Error("Expecting non-empty list of pages!");
}
for (const page of pages) {
console.log(
`Page ${page.pageNumber}: width ${page.width} and height ${page.height} with unit ${page.unit}`
);
for (const table of page.tables) {
for (const cell of table.cells) {
console.log(`cell [${cell.rowIndex},${cell.columnIndex}] has text ${cell.text}`);
}
}
}
}
recognizeContent().catch((err) => {
console.error("The sample encountered an error:", err);
});
小提示
您也可以使用 FormRecognizerClient 方法從本機檔案取得內容,例如 beginRecognizeContent
。
Page 1: width 8.5 and height 11 with unit inch
cell [0,0] has text Invoice Number
cell [0,1] has text Invoice Date
cell [0,2] has text Invoice Due Date
cell [0,3] has text Charges
cell [0,5] has text VAT ID
cell [1,0] has text 34278587
cell [1,1] has text 6/18/2017
cell [1,2] has text 6/24/2017
cell [1,3] has text $56,651.49
cell [1,5] has text PT
分析收據
本節示範如何使用預先定型的收據模型,從美國收據分析及擷取通用字段。 如需收據分析的詳細資訊,請參閱 Document Intelligence 收據模型。
若要分析來自 URI 的收據,請使用 beginRecognizeReceiptsFromUrl
方法。 下列程式代碼會在指定的 URI 處理收據,並將主要欄位和值列印至主控台。
async function recognizeReceipt() {
receiptUrl = "https://raw.githubusercontent.com/Azure/azure-sdk-for-python/master/sdk/formrecognizer/azure-ai-formrecognizer/tests/sample_forms/receipt/contoso-receipt.png";
const poller = await client.beginRecognizeReceiptsFromUrl(receiptUrl, {
onProgress: (state) => { console.log(`status: ${state.status}`); }
});
const receipts = await poller.pollUntilDone();
if (!receipts || receipts.length <= 0) {
throw new Error("Expecting at lease one receipt in analysis result");
}
const receipt = receipts[0];
console.log("First receipt:");
const receiptTypeField = receipt.fields["ReceiptType"];
if (receiptTypeField.valueType === "string") {
console.log(` Receipt Type: '${receiptTypeField.value || "<missing>"}', with confidence of ${receiptTypeField.confidence}`);
}
const merchantNameField = receipt.fields["MerchantName"];
if (merchantNameField.valueType === "string") {
console.log(` Merchant Name: '${merchantNameField.value || "<missing>"}', with confidence of ${merchantNameField.confidence}`);
}
const transactionDate = receipt.fields["TransactionDate"];
if (transactionDate.valueType === "date") {
console.log(` Transaction Date: '${transactionDate.value || "<missing>"}', with confidence of ${transactionDate.confidence}`);
}
const itemsField = receipt.fields["Items"];
if (itemsField.valueType === "array") {
for (const itemField of itemsField.value || []) {
if (itemField.valueType === "object") {
const itemNameField = itemField.value["Name"];
if (itemNameField.valueType === "string") {
console.log(` Item Name: '${itemNameField.value || "<missing>"}', with confidence of ${itemNameField.confidence}`);
}
}
}
}
const totalField = receipt.fields["Total"];
if (totalField.valueType === "number") {
console.log(` Total: '${totalField.value || "<missing>"}', with confidence of ${totalField.confidence}`);
}
}
recognizeReceipt().catch((err) => {
console.error("The sample encountered an error:", err);
});
小提示
您也可以使用 FormRecognizerClient 方法來分析本機收據影像,例如 beginRecognizeReceipts
。
status: notStarted
status: running
status: succeeded
First receipt:
Receipt Type: 'Itemized', with confidence of 0.659
Merchant Name: 'Contoso Contoso', with confidence of 0.516
Transaction Date: 'Sun Jun 09 2019 17:00:00 GMT-0700 (Pacific Daylight Time)', with confidence of 0.985
Item Name: '8GB RAM (Black)', with confidence of 0.916
Item Name: 'SurfacePen', with confidence of 0.858
Total: '1203.39', with confidence of 0.774
分析名片
本節示範如何使用預先定型的模型,從英文名片分析和擷取通用字段。 如需名片分析的詳細資訊,請參閱 Document Intelligence 名片模型。
若要從 URL 分析名片,請使用 beginRecognizeBusinessCardsFromURL
方法。
async function recognizeBusinessCards() {
bcUrl = "https://github.com/Azure-Samples/cognitive-services-REST-api-samples/curl/form-recognizer/businessCard.png";
const poller = await client.beginRecognizeBusinessCardsFromUrl(bcUrl, {
onProgress: (state) => {
console.log(`status: ${state.status}`);
}
});
const [businessCard] = await poller.pollUntilDone();
if (businessCard === undefined) {
throw new Error("Failed to extract data from at least one business card.");
}
const contactNames = businessCard.fields["ContactNames"].value;
if (Array.isArray(contactNames)) {
console.log("- Contact Names:");
for (const contactName of contactNames) {
if (contactName.valueType === "object") {
const firstName = contactName.value?.["FirstName"].value ?? "<no first name>";
const lastName = contactName.value?.["LastName"].value ?? "<no last name>";
console.log(` - ${firstName} ${lastName} (${contactName.confidence} confidence)`);
}
}
}
printSimpleArrayField(businessCard, "CompanyNames");
printSimpleArrayField(businessCard, "Departments");
printSimpleArrayField(businessCard, "JobTitles");
printSimpleArrayField(businessCard, "Emails");
printSimpleArrayField(businessCard, "Websites");
printSimpleArrayField(businessCard, "Addresses");
printSimpleArrayField(businessCard, "MobilePhones");
printSimpleArrayField(businessCard, "Faxes");
printSimpleArrayField(businessCard, "WorkPhones");
printSimpleArrayField(businessCard, "OtherPhones");
}
// Helper function to print array field values.
function printSimpleArrayField(businessCard, fieldName) {
const fieldValues = businessCard.fields[fieldName]?.value;
if (Array.isArray(fieldValues)) {
console.log(`- ${fieldName}:`);
for (const item of fieldValues) {
console.log(` - ${item.value ?? "<no value>"} (${item.confidence} confidence)`);
}
} else if (fieldValues === undefined) {
console.log(`No ${fieldName} were found in the document.`);
} else {
console.error(
`Error: expected field "${fieldName}" to be an Array, but it was a(n) ${businessCard.fields[fieldName].valueType}`
);
}
}
recognizeBusinessCards().catch((err) => {
console.error("The sample encountered an error:", err);
});
小提示
您也可以使用 FormRecognizerClient 方法來分析本機名片影像,例如 beginRecognizeBusinessCards
。
分析發票
本節示範如何使用預先定型的模型,分析及擷取銷售發票中的一般字段。 如需發票分析的詳細資訊,請參閱 Document Intelligence 發票模型。
若要從 URL 分析發票,請使用 beginRecognizeInvoicesFromUrl
方法。
async function recognizeInvoices() {
invoiceUrl = "https://github.com/Azure-Samples/cognitive-services-REST-api-samples/curl/form-recognizer/invoice_sample.jpg";
const poller = await client.beginRecognizeInvoicesFromUrl(invoiceUrl, {
onProgress: (state) => {
console.log(`status: ${state.status}`);
}
});
const [invoice] = await poller.pollUntilDone();
if (invoice === undefined) {
throw new Error("Failed to extract data from at least one invoice.");
}
// Helper function to print fields.
function fieldToString(field) {
const {
name,
valueType,
value,
confidence
} = field;
return `${name} (${valueType}): '${value}' with confidence ${confidence}'`;
}
console.log("Invoice fields:");
for (const [name, field] of Object.entries(invoice.fields)) {
if (field.valueType !== "array" && field.valueType !== "object") {
console.log(`- ${name} ${fieldToString(field)}`);
}
}
let idx = 0;
console.log("- Items:");
const items = invoice.fields["Items"]?.value;
for (const item of items ?? []) {
const value = item.value;
const subFields = [
"Description",
"Quantity",
"Unit",
"UnitPrice",
"ProductCode",
"Date",
"Tax",
"Amount"
]
.map((fieldName) => value[fieldName])
.filter((field) => field !== undefined);
console.log(
[
` - Item #${idx}`,
// Now we will convert those fields into strings to display
...subFields.map((field) => ` - ${fieldToString(field)}`)
].join("\n")
);
}
}
recognizeInvoices().catch((err) => {
console.error("The sample encountered an error:", err);
});
小提示
您也可以使用 FormRecognizerClient 方法來分析本機收據影像,例如 beginRecognizeInvoices
。
分析身分證明文件
本節示範如何使用文件情報預先建置的標識符模型,分析及擷取政府簽發的身份證重要資訊,包括全球護照和美國駕駛執照。 如需了解更多關於身份證件分析的資訊,請參閱 文件智能身份證件模型。
若要從 URL 分析識別碼檔,請使用 beginRecognizeIdDocumentsFromUrl
方法。
async function recognizeIdDocuments() {
idUrl = "https://github.com/Azure-Samples/cognitive-services-REST-api-samples/curl/form-recognizer/id-license.jpg";
const poller = await client.beginRecognizeIdDocumentsFromUrl(idUrl, {
onProgress: (state) => {
console.log(`status: ${state.status}`);
}
});
const [idDocument] = await poller.pollUntilDone();
if (idDocument === undefined) {
throw new Error("Failed to extract data from at least one identity document.");
}
console.log("Document Type:", idDocument.formType);
console.log("Identity Document Fields:");
function printField(fieldName) {
// Fields are extracted from the `fields` property of the document result
const field = idDocument.fields[fieldName];
console.log(
`- ${fieldName} (${field?.valueType}): '${field?.value ?? "<missing>"}', with confidence ${field?.confidence
}`
);
}
printField("FirstName");
printField("LastName");
printField("DocumentNumber");
printField("DateOfBirth");
printField("DateOfExpiration");
printField("Sex");
printField("Address");
printField("Country");
printField("Region");
}
recognizeIdDocuments().catch((err) => {
console.error("The sample encountered an error:", err);
});
訓練自訂模型
本節示範如何使用您自己的數據來定型模型。 定型的模型可以輸出結構化數據,其中包含源檔中的索引鍵/值關聯性。 定型模型之後,您可以測試、重新定型,並最終使用它,根據需求可靠地從更多窗體中擷取數據。
備註
您也可以使用圖形使用者介面 (GUI) 來定型模型,例如 Document Intelligence 範例標籤工具。
訓練不含標籤的模型
訓練自定義模型,以分析自定義表單中找到的所有欄位和值,而不需手動標記訓練檔。
下列函式會在一組指定的檔上定型模型,並將模型的狀態列印至主控台。
async function trainModel() {
const containerSasUrl = "<SAS-URL-of-your-form-folder-in-blob-storage>";
const poller = await trainingClient.beginTraining(containerSasUrl, false, {
onProgress: (state) => { console.log(`training status: ${state.status}`); }
});
const model = await poller.pollUntilDone();
if (!model) {
throw new Error("Expecting valid training result!");
}
console.log(`Model ID: ${model.modelId}`);
console.log(`Status: ${model.status}`);
console.log(`Training started on: ${model.trainingStartedOn}`);
console.log(`Training completed on: ${model.trainingCompletedOn}`);
if (model.submodels) {
for (const submodel of model.submodels) {
// since the training data is unlabeled, we are unable to return the accuracy of this model
console.log("We have recognized the following fields");
for (const key in submodel.fields) {
const field = submodel.fields[key];
console.log(`The model found field '${field.name}'`);
}
}
}
// Training document information
if (model.trainingDocuments) {
for (const doc of model.trainingDocuments) {
console.log(`Document name: ${doc.name}`);
console.log(`Document status: ${doc.status}`);
console.log(`Document page count: ${doc.pageCount}`);
console.log(`Document errors: ${doc.errors}`);
}
}
}
trainModel().catch((err) => {
console.error("The sample encountered an error:", err);
});
以下是使用可從 JavaScript SDK (英文) 取得的訓練資料所訓練模型的輸出。 此範例結果已截斷,以取得可讀性。
training status: creating
training status: ready
Model ID: 9d893595-1690-4cf2-a4b1-fbac0fb11909
Status: ready
Training started on: Thu Aug 20 2020 20:27:26 GMT-0700 (Pacific Daylight Time)
Training completed on: Thu Aug 20 2020 20:27:37 GMT-0700 (Pacific Daylight Time)
We have recognized the following fields
The model found field 'field-0'
The model found field 'field-1'
The model found field 'field-2'
The model found field 'field-3'
The model found field 'field-4'
The model found field 'field-5'
The model found field 'field-6'
The model found field 'field-7'
...
Document name: Form_1.jpg
Document status: succeeded
Document page count: 1
Document errors:
Document name: Form_2.jpg
Document status: succeeded
Document page count: 1
Document errors:
Document name: Form_3.jpg
Document status: succeeded
Document page count: 1
Document errors:
...
訓練具備標籤的模型
您也可以手動標記訓練文件來訓練自訂模型。 在某些情況下,使用標籤來訓練會讓效能更佳。 若要使用標籤來訓練,您的 Blob 儲存體容器中除了訓練文件以外,還必須要有特殊的標籤資訊檔案 (<filename>.pdf.labels.json)。 檔智慧範例標籤工具 提供 UI 來協助您建立這些標籤檔案。 取得它們之後,您可以呼叫 beginTraining
方法,並將 uselabels
參數設定為 true
。
async function trainModelLabels() {
const containerSasUrl = "<SAS-URL-of-your-form-folder-in-blob-storage>";
const poller = await trainingClient.beginTraining(containerSasUrl, true, {
onProgress: (state) => { console.log(`training status: ${state.status}`); }
});
const model = await poller.pollUntilDone();
if (!model) {
throw new Error("Expecting valid training result!");
}
console.log(`Model ID: ${model.modelId}`);
console.log(`Status: ${model.status}`);
console.log(`Training started on: ${model.trainingStartedOn}`);
console.log(`Training completed on: ${model.trainingCompletedOn}`);
if (model.submodels) {
for (const submodel of model.submodels) {
// since the training data is unlabeled, we are unable to return the accuracy of this model
console.log("We have recognized the following fields");
for (const key in submodel.fields) {
const field = submodel.fields[key];
console.log(`The model found field '${field.name}'`);
}
}
}
// Training document information
if (model.trainingDocuments) {
for (const doc of model.trainingDocuments) {
console.log(`Document name: ${doc.name}`);
console.log(`Document status: ${doc.status}`);
console.log(`Document page count: ${doc.pageCount}`);
console.log(`Document errors: ${doc.errors}`);
}
}
}
trainModelLabels().catch((err) => {
console.error("The sample encountered an error:", err);
});
以下是使用可從 JavaScript SDK (英文) 取得的訓練資料所訓練模型的輸出。 此範例結果已截斷,以取得可讀性。
training status: creating
training status: ready
Model ID: 789b1b37-4cc3-4e36-8665-9dde68618072
Status: ready
Training started on: Thu Aug 20 2020 20:30:37 GMT-0700 (Pacific Daylight Time)
Training completed on: Thu Aug 20 2020 20:30:43 GMT-0700 (Pacific Daylight Time)
We have recognized the following fields
The model found field 'CompanyAddress'
The model found field 'CompanyName'
The model found field 'CompanyPhoneNumber'
The model found field 'DatedAs'
...
Document name: Form_1.jpg
Document status: succeeded
Document page count: 1
Document errors: undefined
Document name: Form_2.jpg
Document status: succeeded
Document page count: 1
Document errors: undefined
Document name: Form_3.jpg
Document status: succeeded
Document page count: 1
Document errors: undefined
...
使用自定義模型分析表單
本節示範如何使用以自身表單訓練的模型,從您的自訂範本類型中擷取機碼/值資訊和其他內容。
這很重要
若要實作此案例,您必須已經將模型定型,才能將其標識碼傳遞至方法作業。 請參閱 將模型定型 一節。
您可以使用 beginRecognizeCustomFormsFromUrl
方法。 傳回的值是 RecognizedForm
物件的集合。 在提交的文件中,每個頁面都有一個物件。
async function recognizeCustom() {
// Model ID from when you trained your model.
const modelId = "<modelId>";
const formUrl = "https://raw.githubusercontent.com/Azure-Samples/cognitive-services-REST-api-samples/master/curl/form-recognizer/simple-invoice.png";
const poller = await client.beginRecognizeCustomForms(modelId, formUrl, {
onProgress: (state) => { console.log(`status: ${state.status}`); }
});
const forms = await poller.pollUntilDone();
console.log("Forms:");
for (const form of forms || []) {
console.log(`${form.formType}, page range: ${form.pageRange}`);
console.log("Pages:");
for (const page of form.pages || []) {
console.log(`Page number: ${page.pageNumber}`);
console.log("Tables");
for (const table of page.tables || []) {
for (const cell of table.cells) {
console.log(`cell (${cell.rowIndex},${cell.columnIndex}) ${cell.text}`);
}
}
}
console.log("Fields:");
for (const fieldName in form.fields) {
// each field is of type FormField
const field = form.fields[fieldName];
console.log(
`Field ${fieldName} has value '${field.value}' with a confidence score of ${field.confidence}`
);
}
}
}
recognizeCustom().catch((err) => {
console.error("The sample encountered an error:", err);
});
小提示
您也可以使用 FormRecognizerClient 方法來分析本機檔案,例如 beginRecognizeCustomForms
。
status: notStarted
status: succeeded
Forms:
custom:form, page range: [object Object]
Pages:
Page number: 1
Tables
cell (0,0) Invoice Number
cell (0,1) Invoice Date
cell (0,2) Invoice Due Date
cell (0,3) Charges
cell (0,5) VAT ID
cell (1,0) 34278587
cell (1,1) 6/18/2017
cell (1,2) 6/24/2017
cell (1,3) $56,651.49
cell (1,5) PT
Fields:
Field Merchant has value 'Invoice For:' with a confidence score of 0.116
Field CompanyPhoneNumber has value '$56,651.49' with a confidence score of 0.249
Field VendorName has value 'Charges' with a confidence score of 0.145
Field CompanyAddress has value '1 Redmond way Suite 6000 Redmond, WA' with a confidence score of 0.258
Field CompanyName has value 'PT' with a confidence score of 0.245
Field Website has value '99243' with a confidence score of 0.114
Field DatedAs has value 'undefined' with a confidence score of undefined
Field Email has value 'undefined' with a confidence score of undefined
Field PhoneNumber has value 'undefined' with a confidence score of undefined
Field PurchaseOrderNumber has value 'undefined' with a confidence score of undefined
Field Quantity has value 'undefined' with a confidence score of undefined
Field Signature has value 'undefined' with a confidence score of undefined
Field Subtotal has value 'undefined' with a confidence score of undefined
Field Tax has value 'undefined' with a confidence score of undefined
Field Total has value 'undefined' with a confidence score of undefined
管理自定義模型
本節示範如何管理帳戶中儲存的自定義模型。 下列程式代碼會在單一函式中執行所有模型管理工作,例如。
取得模型數目
下列程式代碼區塊會取得您帳戶中目前使用的模型數目。
async function countModels() {
// First, we see how many custom models we have, and what our limit is
const accountProperties = await trainingClient.getAccountProperties();
console.log(
`Our account has ${accountProperties.customModelCount} custom models, and we can have at most ${accountProperties.customModelLimit} custom models`
);
}
countModels().catch((err) => {
console.error("The sample encountered an error:", err);
});
取得帳戶中的模型清單
下列程式代碼區塊提供帳戶中可用模型的完整清單,包括建立模型的時間及其目前狀態的相關信息。
async function listModels() {
// returns an async iteratable iterator that supports paging
const result = trainingClient.listCustomModels();
let i = 0;
for await (const modelInfo of result) {
console.log(`model ${i++}:`);
console.log(modelInfo);
}
}
listModels().catch((err) => {
console.error("The sample encountered an error:", err);
});
結果看起來像下列輸出。
model 0:
{
modelId: '453cc2e6-e3eb-4e9f-aab6-e1ac7b87e09e',
status: 'invalid',
trainingStartedOn: 2020-08-20T22:28:52.000Z,
trainingCompletedOn: 2020-08-20T22:28:53.000Z
}
model 1:
{
modelId: '628739de-779c-473d-8214-d35c72d3d4f7',
status: 'ready',
trainingStartedOn: 2020-08-20T23:16:51.000Z,
trainingCompletedOn: 2020-08-20T23:16:59.000Z
}
model 2:
{
modelId: '789b1b37-4cc3-4e36-8665-9dde68618072',
status: 'ready',
trainingStartedOn: 2020-08-21T03:30:37.000Z,
trainingCompletedOn: 2020-08-21T03:30:43.000Z
}
model 3:
{
modelId: '9d893595-1690-4cf2-a4b1-fbac0fb11909',
status: 'ready',
trainingStartedOn: 2020-08-21T03:27:26.000Z,
trainingCompletedOn: 2020-08-21T03:27:37.000Z
}
依頁面取得模型識別碼的清單
此程式代碼區塊提供模型和模型標識碼的編頁清單。
async function listModelsByPage() {
// using `byPage()`
i = 1;
for await (const response of trainingClient.listCustomModels().byPage()) {
for (const modelInfo of response.modelList) {
console.log(`model ${i++}: ${modelInfo.modelId}`);
}
}
}
listModelsByPage().catch((err) => {
console.error("The sample encountered an error:", err);
});
結果看起來像下列輸出。
model 1: 453cc2e6-e3eb-4e9f-aab6-e1ac7b87e09e
model 2: 628739de-779c-473d-8214-d35c72d3d4f7
model 3: 789b1b37-4cc3-4e36-8665-9dde68618072
依識別碼取得模型
下列函式會採用模型標識碼,並取得相符的模型物件。 預設不會呼叫此函式。
async function getModel(modelId) {
// Now we'll get the first custom model in the paged list
const model = await client.getCustomModel(modelId);
console.log("--- First Custom Model ---");
console.log(`Model Id: ${model.modelId}`);
console.log(`Status: ${model.status}`);
console.log("Documents used in training:");
for (const doc of model.trainingDocuments || []) {
console.log(`- ${doc.name}`);
}
}
從資源帳戶刪除模型
您也可以參考其識別碼,從您的帳戶中刪除模型。 此函式會刪除具有指定識別碼的模型。 預設不會呼叫此函式。
async function deleteModel(modelId) {
await client.deleteModel(modelId);
try {
const deleted = await client.getCustomModel(modelId);
console.log(deleted);
} catch (err) {
// Expected
console.log(`Model with id ${modelId} has been deleted`);
}
}
結果看起來像下列輸出。
Model with id 789b1b37-4cc3-4e36-8665-9dde68618072 has been deleted
執行應用程式
在項目檔上使用 node
命令執行應用程式。
node index.js
清理資源
如果您想要清除和移除 Azure AI 服務訂用帳戶,則可以刪除資源或資源群組。 刪除資源群組也會刪除與其相關聯的任何其他資源。
故障排除
您可以使用此連結庫來設定下列環境變數,以查看偵錯記錄。
export DEBUG=azure*
如需有關如何啟用日誌的詳細指示,請參閱 @azure/logger 套件文件 。
後續步驟
針對此專案,您已使用 Document Intelligence JavaScript 用戶端連結庫,以不同方式定型模型和分析表單。 接下來,瞭解建立更佳訓練數據集的秘訣,並產生更精確的模型。
這很重要
此項目的目標是 Document Intelligence REST API 2.1 版。
參考文件 | 程式庫來源程式碼 | 套件 (PyPi) | 範例
先決條件
Azure 訂用帳戶 - 免費建立一個訂用帳戶。
Python 3.x。 您安裝的 Python 應包含 pip。 您可以藉由在命令列上執行
pip --version
來檢查您是否已安裝 pip。 安裝最新版本的 Python 以取得 pip。包含一組訓練資料的 Azure 儲存 Blob。 如需組合您的訓練數據集的提示和選項,請參閱 建置和訓練自定義模型。 在此專案中,您可以使用 Train 資料夾中的檔案,這些檔案位於 範例數據集下。 下載並擷取 sample_data.zip。
文件智慧服務資源。 在 Azure 入口網站中建立文件智慧資源 。 您可以使用免費定價層 (
F0
) 來試用服務,之後可升級至付費層以用於實際執行環境。- 部署資源之後,請選取 [前往資源]。
- 在左側導覽功能表中,選取 [金鑰和端點]。
- 複製其中一個金鑰和 端點,以供本文稍後使用。
設定程式設計環境
安裝客戶端連結庫並建立 Python 應用程式。
安裝用戶端程式庫
安裝 Python 之後,請執行下列命令來安裝最新版的 Document Intelligence 用戶端連結庫。
pip install azure-ai-formrecognizer
建立 Python 應用程式
在編輯器或 IDE 中建立名為 form-recognizer.py 的 Python 應用程式。
匯入下列函式庫。
import os from azure.core.exceptions import ResourceNotFoundError from azure.ai.formrecognizer import FormRecognizerClient from azure.ai.formrecognizer import FormTrainingClient from azure.core.credentials import AzureKeyCredential
為資源的 Azure 端點和金鑰建立變數。
endpoint = "PASTE_YOUR_FORM_RECOGNIZER_ENDPOINT_HERE" key = "PASTE_YOUR_FORM_RECOGNIZER_SUBSCRIPTION_KEY_HERE"
使用物件模型
使用文件智慧,您可以建立兩種不同的客戶端類型。 第一個是 form_recognizer_client
,會查詢服務,以辨識出表單欄位和內容。 第二個-form_training_client
- 會建立和管理自定義模型以改善辨識。
form_recognizer_client
提供下列作業:
- 使用定型的自定義模型來分析自定義表單,來辨識表單域和內容。
- 辨識表單內容,包括表格、線條和文字,而不需要訓練模型。
- 在 Document Intelligence 服務上使用預先定型的收據模型,從收據辨識常見的欄位。
form_training_client
會提供作業以:
- 定型自定義模型,以分析自定義表單中找到的所有欄位和值。 請參閱本文中的訓練不具備標籤的模型。
- 將自定義模型定型,以分析您透過標記自定義表單所指定的特定欄位和值。 請參閱本文中的訓練具備標籤的模型。
- 管理在您的帳戶中建立的模型。
- 將自定義模型從一個 Document Intelligence 資源複製到另一個資源。
備註
模型也可以使用圖形使用者介面來定型,例如 檔智慧卷標工具。
驗證用戶端
使用您先前定義的訂用帳戶變數來驗證兩個客戶端物件。 使用 AzureKeyCredential
物件,因此如有需要,您可以更新金鑰而不建立新的客戶端物件。
form_recognizer_client = FormRecognizerClient(endpoint, AzureKeyCredential(key))
form_training_client = FormTrainingClient(endpoint, AzureKeyCredential(key))
取得用於測試的資產
您需要為訓練和測試資料新增 URL 的參考。
若要擷取自定義模型定型數據的SAS URL,請移至 Azure 入口網站中的記憶體資源,然後選取 [資料記憶體]>[容器]。
瀏覽至您的容器,按下滑鼠右鍵,然後選取 產生 SAS。
取得您容器的 SAS,而不是儲存體帳戶本身的 SAS。
請確定已選取 讀取、寫入、刪除和 列出 許可權,然後選取 產生 SAS 令牌和 URL。
將 [URL] 區段中的值複製到暫存位置。 其格式應該為:
https://<storage account>.blob.core.windows.net/<container name>?<SAS value>
。
使用範例中包含的範例表單和收據影像,這些範例也可在 GitHub 取得。 或者,您也可以使用上述步驟來取得 Blob 記憶體中個別檔的 SAS URL。
分析版面配置
您可以使用檔智慧來分析檔中的數據表、線條和文字,而不需要定型模型。 如需版面配置擷取的詳細資訊,請參閱 檔案智慧版面配置模型。
若要分析位於指定 URL 的檔案內容,請使用 begin_recognize_content_from_url
方法。 傳回的值是 FormPage
物件的集合。 在提交的文件中,每個頁面都有一個物件。 下列程式代碼會逐一查看這些物件,並列印擷取的索引鍵/值組和數據表數據。
formUrl = "https://raw.githubusercontent.com/Azure/azure-sdk-for-python/master/sdk/formrecognizer/azure-ai-formrecognizer/tests/sample_forms/forms/Form_1.jpg"
poller = form_recognizer_client.begin_recognize_content_from_url(formUrl)
page = poller.result()
table = page[0].tables[0] # page 1, table 1
print("Table found on page {}:".format(table.page_number))
for cell in table.cells:
print("Cell text: {}".format(cell.text))
print("Location: {}".format(cell.bounding_box))
print("Confidence score: {}\n".format(cell.confidence))
小提示
您也可以使用 FormRecognizerClient (英文) 方法從本機影像取得內容,例如 begin_recognize_content
。
Table found on page 1:
Cell text: Invoice Number
Location: [Point(x=0.5075, y=2.8088), Point(x=1.9061, y=2.8088), Point(x=1.9061, y=3.3219), Point(x=0.5075, y=3.3219)]
Confidence score: 1.0
Cell text: Invoice Date
Location: [Point(x=1.9061, y=2.8088), Point(x=3.3074, y=2.8088), Point(x=3.3074, y=3.3219), Point(x=1.9061, y=3.3219)]
Confidence score: 1.0
Cell text: Invoice Due Date
Location: [Point(x=3.3074, y=2.8088), Point(x=4.7074, y=2.8088), Point(x=4.7074, y=3.3219), Point(x=3.3074, y=3.3219)]
Confidence score: 1.0
Cell text: Charges
Location: [Point(x=4.7074, y=2.8088), Point(x=5.386, y=2.8088), Point(x=5.386, y=3.3219), Point(x=4.7074, y=3.3219)]
Confidence score: 1.0
...
分析收據
本節示範如何使用預先定型的收據模型,從美國收據分析及擷取通用字段。 如需收據分析的詳細資訊,請參閱 Document Intelligence 收據模型。 若要分析來自 URL 的收據,請使用 begin_recognize_receipts_from_url
方法。
receiptUrl = "https://raw.githubusercontent.com/Azure/azure-sdk-for-python/master/sdk/formrecognizer/azure-ai-formrecognizer/tests/sample_forms/receipt/contoso-receipt.png"
poller = form_recognizer_client.begin_recognize_receipts_from_url(receiptUrl)
result = poller.result()
for receipt in result:
for name, field in receipt.fields.items():
if name == "Items":
print("Receipt Items:")
for idx, items in enumerate(field.value):
print("...Item #{}".format(idx + 1))
for item_name, item in items.value.items():
print("......{}: {} has confidence {}".format(item_name, item.value, item.confidence))
else:
print("{}: {} has confidence {}".format(name, field.value, field.confidence))
小提示
您也可以使用 FormRecognizerClient 方法來分析在地收據影像,例如 begin_recognize_receipts
。
ReceiptType: Itemized has confidence 0.659
MerchantName: Contoso Contoso has confidence 0.516
MerchantAddress: 123 Main Street Redmond, WA 98052 has confidence 0.986
MerchantPhoneNumber: None has confidence 0.99
TransactionDate: 2019-06-10 has confidence 0.985
TransactionTime: 13:59:00 has confidence 0.968
Receipt Items:
...Item #1
......Name: 8GB RAM (Black) has confidence 0.916
......TotalPrice: 999.0 has confidence 0.559
...Item #2
......Quantity: None has confidence 0.858
......Name: SurfacePen has confidence 0.858
......TotalPrice: 99.99 has confidence 0.386
Subtotal: 1098.99 has confidence 0.964
Tax: 104.4 has confidence 0.713
Total: 1203.39 has confidence 0.774
分析名片
本節示範如何使用預先定型的模型,從英文名片分析和擷取通用字段。 如需名片分析的詳細資訊,請參閱 Document Intelligence 名片模型。
若要從 URL 分析名片,請使用 begin_recognize_business_cards_from_url
方法。
bcUrl = "https://raw.githubusercontent.com/Azure/azure-sdk-for-python/master/sdk/formrecognizer/azure-ai-formrecognizer/samples/sample_forms/business_cards/business-card-english.jpg"
poller = form_recognizer_client.begin_recognize_business_cards_from_url(bcUrl)
business_cards = poller.result()
for idx, business_card in enumerate(business_cards):
print("--------Recognizing business card #{}--------".format(idx+1))
contact_names = business_card.fields.get("ContactNames")
if contact_names:
for contact_name in contact_names.value:
print("Contact First Name: {} has confidence: {}".format(
contact_name.value["FirstName"].value, contact_name.value["FirstName"].confidence
))
print("Contact Last Name: {} has confidence: {}".format(
contact_name.value["LastName"].value, contact_name.value["LastName"].confidence
))
company_names = business_card.fields.get("CompanyNames")
if company_names:
for company_name in company_names.value:
print("Company Name: {} has confidence: {}".format(company_name.value, company_name.confidence))
departments = business_card.fields.get("Departments")
if departments:
for department in departments.value:
print("Department: {} has confidence: {}".format(department.value, department.confidence))
job_titles = business_card.fields.get("JobTitles")
if job_titles:
for job_title in job_titles.value:
print("Job Title: {} has confidence: {}".format(job_title.value, job_title.confidence))
emails = business_card.fields.get("Emails")
if emails:
for email in emails.value:
print("Email: {} has confidence: {}".format(email.value, email.confidence))
websites = business_card.fields.get("Websites")
if websites:
for website in websites.value:
print("Website: {} has confidence: {}".format(website.value, website.confidence))
addresses = business_card.fields.get("Addresses")
if addresses:
for address in addresses.value:
print("Address: {} has confidence: {}".format(address.value, address.confidence))
mobile_phones = business_card.fields.get("MobilePhones")
if mobile_phones:
for phone in mobile_phones.value:
print("Mobile phone number: {} has confidence: {}".format(phone.value, phone.confidence))
faxes = business_card.fields.get("Faxes")
if faxes:
for fax in faxes.value:
print("Fax number: {} has confidence: {}".format(fax.value, fax.confidence))
work_phones = business_card.fields.get("WorkPhones")
if work_phones:
for work_phone in work_phones.value:
print("Work phone number: {} has confidence: {}".format(work_phone.value, work_phone.confidence))
other_phones = business_card.fields.get("OtherPhones")
if other_phones:
for other_phone in other_phones.value:
print("Other phone number: {} has confidence: {}".format(other_phone.value, other_phone.confidence))
小提示
您也可以使用 FormRecognizerClient (英文) 方法來分析本機名片影像,例如 begin_recognize_business_cards
。
分析發票
本節示範如何使用預先定型的模型,分析及擷取銷售發票中的一般字段。 如需發票分析的詳細資訊,請參閱 Document Intelligence 發票模型。
若要從 URL 分析發票,請使用 begin_recognize_invoices_from_url
方法。
invoiceUrl = "https://raw.githubusercontent.com/Azure-Samples/cognitive-services-REST-api-samples/master/curl/form-recognizer/simple-invoice.png"
poller = form_recognizer_client.begin_recognize_invoices_from_url(invoiceUrl)
invoices = poller.result()
for idx, invoice in enumerate(invoices):
print("--------Recognizing invoice #{}--------".format(idx+1))
vendor_name = invoice.fields.get("VendorName")
if vendor_name:
print("Vendor Name: {} has confidence: {}".format(vendor_name.value, vendor_name.confidence))
vendor_address = invoice.fields.get("VendorAddress")
if vendor_address:
print("Vendor Address: {} has confidence: {}".format(vendor_address.value, vendor_address.confidence))
customer_name = invoice.fields.get("CustomerName")
if customer_name:
print("Customer Name: {} has confidence: {}".format(customer_name.value, customer_name.confidence))
customer_address = invoice.fields.get("CustomerAddress")
if customer_address:
print("Customer Address: {} has confidence: {}".format(customer_address.value, customer_address.confidence))
customer_address_recipient = invoice.fields.get("CustomerAddressRecipient")
if customer_address_recipient:
print("Customer Address Recipient: {} has confidence: {}".format(customer_address_recipient.value, customer_address_recipient.confidence))
invoice_id = invoice.fields.get("InvoiceId")
if invoice_id:
print("Invoice Id: {} has confidence: {}".format(invoice_id.value, invoice_id.confidence))
invoice_date = invoice.fields.get("InvoiceDate")
if invoice_date:
print("Invoice Date: {} has confidence: {}".format(invoice_date.value, invoice_date.confidence))
invoice_total = invoice.fields.get("InvoiceTotal")
if invoice_total:
print("Invoice Total: {} has confidence: {}".format(invoice_total.value, invoice_total.confidence))
due_date = invoice.fields.get("DueDate")
if due_date:
print("Due Date: {} has confidence: {}".format(due_date.value, due_date.confidence))
小提示
您也可以使用 FormRecognizerClient (英文) 方法來分析本機發票影像,例如 begin_recognize_invoices
。
分析身分證明文件
本節示範如何使用預建的身份識別模型,分析和擷取政府簽發的身份證件的關鍵資訊,例如全球護照和美國駕照。 如需了解更多關於身份證件分析的資訊,請參閱 文件智能身份證件模型。
若要從 URL 分析識別碼檔,請使用 begin_recognize_id_documents_from_url
方法。
idURL = "https://raw.githubusercontent.com/Azure-Samples/cognitive-services-REST-api-samples/master/curl/form-recognizer/id-license.jpg"
for idx, id_document in enumerate(id_documents):
print("--------Recognizing ID document #{}--------".format(idx+1))
first_name = id_document.fields.get("FirstName")
if first_name:
print("First Name: {} has confidence: {}".format(first_name.value, first_name.confidence))
last_name = id_document.fields.get("LastName")
if last_name:
print("Last Name: {} has confidence: {}".format(last_name.value, last_name.confidence))
document_number = id_document.fields.get("DocumentNumber")
if document_number:
print("Document Number: {} has confidence: {}".format(document_number.value, document_number.confidence))
dob = id_document.fields.get("DateOfBirth")
if dob:
print("Date of Birth: {} has confidence: {}".format(dob.value, dob.confidence))
doe = id_document.fields.get("DateOfExpiration")
if doe:
print("Date of Expiration: {} has confidence: {}".format(doe.value, doe.confidence))
sex = id_document.fields.get("Sex")
if sex:
print("Sex: {} has confidence: {}".format(sex.value, sex.confidence))
address = id_document.fields.get("Address")
if address:
print("Address: {} has confidence: {}".format(address.value, address.confidence))
country_region = id_document.fields.get("CountryRegion")
if country_region:
print("Country/Region: {} has confidence: {}".format(country_region.value, country_region.confidence))
region = id_document.fields.get("Region")
if region:
print("Region: {} has confidence: {}".format(region.value, region.confidence))
小提示
您也可以使用 FormRecognizerClient 方法來分析識別符檔影像,例如 begin_recognize_identity_documents
。
訓練自訂模型
本節示範如何使用您自己的數據來定型模型。 定型的模型可以輸出結構化數據,其中包含源檔中的索引鍵/值關聯性。 定型模型之後,您可以測試、重新定型,並最終使用它,根據需求可靠地從更多窗體中擷取數據。
備註
您也可以使用圖形使用者介面來定型模型,例如 檔案智慧範例標籤工具。
訓練不含標籤的模型
訓練自定義模型,以分析自定義表單中找到的所有欄位和值,而不需手動標記訓練檔。
下列程式代碼會使用定型用戶端搭配 begin_training
函式,在指定的檔集上定型模型。 傳回 CustomFormModel
物件包含模型可分析之表單類型的相關信息,以及可從每個表單類型擷取的欄位。 下列程式代碼區塊會將此資訊列印至主控台。
# To train a model you need an Azure Storage account.
# Use the SAS URL to access your training files.
trainingDataUrl = "PASTE_YOUR_SAS_URL_OF_YOUR_FORM_FOLDER_IN_BLOB_STORAGE_HERE"
poller = form_training_client.begin_training(trainingDataUrl, use_training_labels=False)
model = poller.result()
print("Model ID: {}".format(model.model_id))
print("Status: {}".format(model.status))
print("Training started on: {}".format(model.training_started_on))
print("Training completed on: {}".format(model.training_completed_on))
print("\nRecognized fields:")
for submodel in model.submodels:
print(
"The submodel with form type '{}' has recognized the following fields: {}".format(
submodel.form_type,
", ".join(
[
field.label if field.label else name
for name, field in submodel.fields.items()
]
),
)
)
# Training result information
for doc in model.training_documents:
print("Document name: {}".format(doc.name))
print("Document status: {}".format(doc.status))
print("Document page count: {}".format(doc.page_count))
print("Document errors: {}".format(doc.errors))
以下是使用 Python SDK中可用訓練數據的模型輸出。
Model ID: 628739de-779c-473d-8214-d35c72d3d4f7
Status: ready
Training started on: 2020-08-20 23:16:51+00:00
Training completed on: 2020-08-20 23:16:59+00:00
Recognized fields:
The submodel with form type 'form-0' has recognized the following fields: Additional Notes:, Address:, Company Name:, Company Phone:, Dated As:, Details, Email:, Hero Limited, Name:, Phone:, Purchase Order, Purchase Order #:, Quantity, SUBTOTAL, Seattle, WA 93849 Phone:, Shipped From, Shipped To, TAX, TOTAL, Total, Unit Price, Vendor Name:, Website:
Document name: Form_1.jpg
Document status: succeeded
Document page count: 1
Document errors: []
Document name: Form_2.jpg
Document status: succeeded
Document page count: 1
Document errors: []
Document name: Form_3.jpg
Document status: succeeded
Document page count: 1
Document errors: []
Document name: Form_4.jpg
Document status: succeeded
Document page count: 1
Document errors: []
Document name: Form_5.jpg
Document status: succeeded
Document page count: 1
Document errors: []
訓練具備標籤的模型
您也可以手動標記訓練文件來訓練自訂模型。 在某些情況下,使用標籤來訓練會讓效能更佳。 傳回的 CustomFormModel
會指出模型可以擷取的欄位,以及其在每個欄位中的估計精確度。 下列程式代碼區塊會將此資訊列印至主控台。
這很重要
若要使用標籤來訓練,您的 Blob 儲存體容器中除了訓練文件以外,還必須要有特殊的標籤資訊檔案 (<filename>.pdf.labels.json)。 檔智慧範例標籤工具 提供 UI 來協助您建立這些標籤檔案。 取得它們之後,您可以呼叫 begin_training
函式,並將 use_training_labels
參數設定為 true
。
# To train a model you need an Azure Storage account.
# Use the SAS URL to access your training files.
trainingDataUrl = "PASTE_YOUR_SAS_URL_OF_YOUR_FORM_FOLDER_IN_BLOB_STORAGE_HERE"
poller = form_training_client.begin_training(trainingDataUrl, use_training_labels=True)
model = poller.result()
trained_model_id = model.model_id
print("Model ID: {}".format(trained_model_id))
print("Status: {}".format(model.status))
print("Training started on: {}".format(model.training_started_on))
print("Training completed on: {}".format(model.training_completed_on))
print("\nRecognized fields:")
for submodel in model.submodels:
print(
"The submodel with form type '{}' has recognized the following fields: {}".format(
submodel.form_type,
", ".join(
[
field.label if field.label else name
for name, field in submodel.fields.items()
]
),
)
)
# Training result information
for doc in model.training_documents:
print("Document name: {}".format(doc.name))
print("Document status: {}".format(doc.status))
print("Document page count: {}".format(doc.page_count))
print("Document errors: {}".format(doc.errors))
以下是使用 Python SDK中可用訓練數據的模型輸出。
Model ID: ae636292-0b14-4e26-81a7-a0bfcbaf7c91
Status: ready
Training started on: 2020-08-20 23:20:56+00:00
Training completed on: 2020-08-20 23:20:57+00:00
Recognized fields:
The submodel with form type 'form-ae636292-0b14-4e26-81a7-a0bfcbaf7c91' has recognized the following fields: CompanyAddress, CompanyName, CompanyPhoneNumber, DatedAs, Email, Merchant, PhoneNumber, PurchaseOrderNumber, Quantity, Signature, Subtotal, Tax, Total, VendorName, Website
Document name: Form_1.jpg
Document status: succeeded
Document page count: 1
Document errors: []
Document name: Form_2.jpg
Document status: succeeded
Document page count: 1
Document errors: []
Document name: Form_3.jpg
Document status: succeeded
Document page count: 1
Document errors: []
Document name: Form_4.jpg
Document status: succeeded
Document page count: 1
Document errors: []
Document name: Form_5.jpg
Document status: succeeded
Document page count: 1
Document errors: []
使用自定義模型分析表單
本節示範如何使用以自身表單訓練的模型,從您的自訂範本類型中擷取機碼/值資訊和其他內容。
這很重要
若要實作此情境,您必須有已訓練的模型,才能將其ID傳入方法操作。 請參閱 將模型定型 一節。
您可以使用 begin_recognize_custom_forms_from_url
方法。 傳回的值是 RecognizedForm
物件的集合。 在提交的文件中,每個頁面都有一個物件。 下列程式代碼會將分析結果列印至主控台。 它會列印每個已辨識的字段和對應的值,以及信賴分數。
poller = form_recognizer_client.begin_recognize_custom_forms_from_url(
model_id=trained_model_id, form_url=formUrl)
result = poller.result()
for recognized_form in result:
print("Form type: {}".format(recognized_form.form_type))
for name, field in recognized_form.fields.items():
print("Field '{}' has label '{}' with value '{}' and a confidence score of {}".format(
name,
field.label_data.text if field.label_data else name,
field.value,
field.confidence
))
小提示
您也可以分析本機影像。 請參閱 FormRecognizerClient 方法,例如 begin_recognize_custom_forms
。 或如需本機影像的相關案例,請參閱 GitHub (英文) 上的範例程式碼。
上一個範例中的模型會轉譯下列輸出:
Form type: form-ae636292-0b14-4e26-81a7-a0bfcbaf7c91
Field 'Merchant' has label 'Merchant' with value 'Invoice For:' and a confidence score of 0.116
Field 'CompanyAddress' has label 'CompanyAddress' with value '1 Redmond way Suite 6000 Redmond, WA' and a confidence score of 0.258
Field 'Website' has label 'Website' with value '99243' and a confidence score of 0.114
Field 'VendorName' has label 'VendorName' with value 'Charges' and a confidence score of 0.145
Field 'CompanyPhoneNumber' has label 'CompanyPhoneNumber' with value '$56,651.49' and a confidence score of 0.249
Field 'CompanyName' has label 'CompanyName' with value 'PT' and a confidence score of 0.245
Field 'DatedAs' has label 'DatedAs' with value 'None' and a confidence score of None
Field 'Email' has label 'Email' with value 'None' and a confidence score of None
Field 'PhoneNumber' has label 'PhoneNumber' with value 'None' and a confidence score of None
Field 'PurchaseOrderNumber' has label 'PurchaseOrderNumber' with value 'None' and a confidence score of None
Field 'Quantity' has label 'Quantity' with value 'None' and a confidence score of None
Field 'Signature' has label 'Signature' with value 'None' and a confidence score of None
Field 'Subtotal' has label 'Subtotal' with value 'None' and a confidence score of None
Field 'Tax' has label 'Tax' with value 'None' and a confidence score of None
Field 'Total' has label 'Total' with value 'None' and a confidence score of None
管理自定義模型
本節示範如何管理帳戶中儲存的自定義模型。
檢查 FormRecognizer 資源帳戶中的模型數目
下列程式代碼區塊會檢查您在 Document Intelligence 帳戶中儲存的模型數目,並將其與帳戶限制進行比較。
account_properties = form_training_client.get_account_properties()
print("Our account has {} custom models, and we can have at most {} custom models".format(
account_properties.custom_model_count, account_properties.custom_model_limit
))
結果看起來像下列輸出。
Our account has 5 custom models, and we can have at most 5000 custom models
列出目前儲存在資源帳戶中的模型
下列程式代碼會封鎖您的帳戶中目前的模型,並將其詳細數據列印至主控台。 它也會儲存第一個模型的參考資料。
# Next, we get a paged list of all of our custom models
custom_models = form_training_client.list_custom_models()
print("We have models with the following ids:")
# Let's pull out the first model
first_model = next(custom_models)
print(first_model.model_id)
for model in custom_models:
print(model.model_id)
結果看起來像下列輸出。
以下是測試帳戶的範例輸出。
We have models with the following ids:
453cc2e6-e3eb-4e9f-aab6-e1ac7b87e09e
628739de-779c-473d-8214-d35c72d3d4f7
ae636292-0b14-4e26-81a7-a0bfcbaf7c91
b4b5df77-8538-4ffb-a996-f67158ecd305
c6309148-6b64-4fef-aea0-d39521452699
使用模型的標識碼取得特定模型
下列程式代碼區塊會使用從上一節儲存的模型標識符,並用它來擷取模型的詳細數據。
custom_model = form_training_client.get_custom_model(model_id=trained_model_id)
print("Model ID: {}".format(custom_model.model_id))
print("Status: {}".format(custom_model.status))
print("Training started on: {}".format(custom_model.training_started_on))
print("Training completed on: {}".format(custom_model.training_completed_on))
以下是在上一個範例中建立之自定義模型的範例輸出。
Model ID: ae636292-0b14-4e26-81a7-a0bfcbaf7c91
Status: ready
Training started on: 2020-08-20 23:20:56+00:00
Training completed on: 2020-08-20 23:20:57+00:00
從資源帳戶刪除模型
您也可以參考其識別碼,從您的帳戶中刪除模型。 此程式代碼會刪除上一節中使用的模型。
form_training_client.delete_model(model_id=custom_model.model_id)
try:
form_training_client.get_custom_model(model_id=custom_model.model_id)
except ResourceNotFoundError:
print("Successfully deleted model with id {}".format(custom_model.model_id))
執行應用程式
使用 python
命令執行應用程式:
python form-recognizer.py
清理資源
如果您想要清除和移除 Azure AI 服務訂用帳戶,則可以刪除資源或資源群組。 刪除資源群組也會刪除與其相關聯的任何其他資源。
故障排除
這些問題可能有助於疑難解答。
記錄
此連結庫會使用 標準記錄連結庫 進行記錄。 HTTP 會話的基本資訊,例如 URL 和標頭,會記錄在 INFO 層級。
您可以使用 logging_enable
關鍵詞參數在用戶端上啟用詳細的 DEBUG 記錄層級,包括要求/回應內容和未修剪的標頭。
import sys
import logging
from azure.ai.formrecognizer import FormRecognizerClient
from azure.core.credentials import AzureKeyCredential
# Create a logger for the 'azure' SDK
logger = logging.getLogger('azure')
logger.setLevel(logging.DEBUG)
# Configure a console output
handler = logging.StreamHandler(stream=sys.stdout)
logger.addHandler(handler)
endpoint = "PASTE_YOUR_FORM_RECOGNIZER_ENDPOINT_HERE"
credential = AzureKeyCredential("PASTE_YOUR_FORM_RECOGNIZER_SUBSCRIPTION_KEY_HERE")
# This client will log detailed information about its HTTP sessions, at DEBUG level
form_recognizer_client = FormRecognizerClient(endpoint, credential, logging_enable=True)
同樣地,logging_enable
可對單一作業啟用詳細記錄,即使未對用戶端啟用也可行:
receiptUrl = "https://raw.githubusercontent.com/Azure/azure-sdk-for-python/master/sdk/formrecognizer/azure-ai-formrecognizer/tests/sample_forms/receipt/contoso-receipt.png"
poller = form_recognizer_client.begin_recognize_receipts_from_url(receiptUrl, logging_enable=True)
GitHub 上的 REST 範例
從文件中擷取文字、選取標記及表格結構:擷取佈局數據 - Python
定型自定義模型並擷取自定義表單資料:
- 不使用標籤進行訓練 - Python (英文)
- 使用標籤進行訓練 - Python (英文)
從發票擷取數據:擷取發票數據 - Python
從銷售收據擷取數據:擷取收據數據 - Python
從名片擷取數據:擷取名片數據 - Python
後續步驟
針對此專案,您已使用 Document Intelligence Python 用戶端連結庫,以不同方式定型模型和分析表單。 接下來,瞭解建立更佳訓練數據集的秘訣,並產生更精確的模型。
備註
此專案以 Azure AI 文檔智慧 API 2.1 版為目標,使用 cURL 來執行 REST API 呼叫。
文件智慧服務 REST API (部分內容可能是機器或 AI 翻譯) | Azure REST API 參考 (部分內容可能是機器或 AI 翻譯)
先決條件
Azure 訂用帳戶 - 免費建立一個訂用帳戶。
已安裝 cURL 命令行工具。 Windows 10 和 Windows 11 隨附 cURL 的複本。 在命令提示字元中,輸入下列 cURL 命令。 如果說明選項顯示,cURL 會安裝在 Windows 環境中。
curl -help
如果未安裝 cURL,您可以在這裡取得:
PowerShell 6.0 版以上,或類似的命令列應用程式。
包含一組訓練資料的 Azure 儲存 Blob。 如需組合您的訓練數據集的提示和選項,請參閱 建置和訓練自定義模型。 您可以使用 Train 資料夾中的檔案,這個資料夾屬於 範例資料集。 下載並擷取 sample_data.zip。
Azure AI 服務或文件智慧服務資源。 建立 單一服務 或 多服務。 您可以使用免費定價層 (
F0
) 來試用服務,之後可升級至付費層以用於實際執行環境。從您所建立資源的金鑰和端點,將應用程式連線至 Azure 文件智慧服務。
- 部署資源之後,請選取 [前往資源]。
- 在左側導覽功能表中,選取 [金鑰和端點]。
- 複製其中一個金鑰和 端點,以供本文稍後使用。
收據影像的 URL。 您可以使用範例影像。
名片影像的 URL。 您可以使用範例影像。
發票影像的 URL。 您可以使用 範例檔。
身分證明文件影像的 URL。 您可以使用範例影像
分析版面配置
您可以使用檔智慧來分析及擷取檔中的數據表、選取標記、文字和結構,而不需要定型模型。 如需版面配置擷取的詳細資訊,請參閱 檔案智慧版面配置模型。
執行命令之前,請進行下列變更:
- 將 <端點> 替換成您使用 Document Intelligence 訂用帳戶取得的端點。
- 將 <金鑰> 取代為您從上一個步驟複製的金鑰。
- 以其中一個範例 URL 取代 <your-document-url>。
curl -v -i POST "https://<endpoint>/formrecognizer/v2.1/layout/analyze" -H "Content-Type: application/json" -H "Ocp-Apim-Subscription-Key: <key>" --data-ascii "{'source': '<your-document-url>'}"
您會收到包括唯讀 202 (Success)
標頭的 Operation-Location
回應。 此標頭的值包含 resultId
,可透過查詢以取得非同步作業的狀態,並且可使用 GET 要求搭配您的相同資源訂用帳戶金鑰來擷取結果:
https://cognitiveservice/formrecognizer/v2.1/layout/analyzeResults/<resultId>
在下列範例中,URL 中在 analyzeResults/
之後的字串就是結果識別碼。
https://cognitiveservice/formrecognizer/v2/layout/analyzeResults/54f0b076-4e38-43e5-81bd-b85b8835fdfb
取得配置結果
呼叫 分析版面配置 API 之後,請輪詢 取得分析版面配置結果 API,以取得作業的狀態和擷取的數據。 執行命令之前,請進行下列變更:
- 將 <端點> 替換成您使用 Document Intelligence 訂用帳戶取得的端點。
- 將 <金鑰> 取代為您從上一個步驟複製的金鑰。
- 將 <resultId> 取代為先前步驟中的結果識別碼。
curl -v -X GET "https://<endpoint>/formrecognizer/v2.1/layout/analyzeResults/<resultId>" -H "Ocp-Apim-Subscription-Key: <key>"
您收到帶有 JSON 內容的 200 (success)
回應。
請參閱下列發票影像和其對應的 JSON 輸出。
"readResults"
節點包含每一行文字,以及各自的周框方塊在頁面上的位置。selectionMarks
節點顯示每個選取標記 (核取方塊、選項標記),以及其狀態是selected
或unselected
。"pageResults"
區段包含擷取的資料表。 針對每個表格,會擷取文字、列和欄索引、列和欄擴展、周框方塊等。
為了簡單起見,我們已將此回應本文輸出內容縮短。 請參閱 GitHub 上的完整範例輸出。
{
"status": "succeeded",
"createdDateTime": "2020-08-20T20:40:50Z",
"lastUpdatedDateTime": "2020-08-20T20:40:55Z",
"analyzeResult": {
"version": "2.1.0",
"readResults": [
{
"page": 1,
"angle": 0,
"width": 8.5,
"height": 11,
"unit": "inch",
"lines": [
{
"boundingBox": [
0.5826,
0.4411,
2.3387,
0.4411,
2.3387,
0.7969,
0.5826,
0.7969
],
"text": "Contoso, Ltd.",
"words": [
{
"boundingBox": [
0.5826,
0.4411,
1.744,
0.4411,
1.744,
0.7969,
0.5826,
0.7969
],
"text": "Contoso,",
"confidence": 1
},
{
"boundingBox": [
1.8448,
0.4446,
2.3387,
0.4446,
2.3387,
0.7631,
1.8448,
0.7631
],
"text": "Ltd.",
"confidence": 1
}
]
},
...
]
}
],
"selectionMarks": [
{
"boundingBox": [
3.9737,
3.7475,
4.1693,
3.7475,
4.1693,
3.9428,
3.9737,
3.9428
],
"confidence": 0.989,
"state": "selected"
},
...
]
}
],
"pageResults": [
{
"page": 1,
"tables": [
{
"rows": 5,
"columns": 5,
"cells": [
{
"rowIndex": 0,
"columnIndex": 0,
"text": "Training Date",
"boundingBox": [
0.5133,
4.2167,
1.7567,
4.2167,
1.7567,
4.4492,
0.5133,
4.4492
],
"elements": [
"#/readResults/0/lines/12/words/0",
"#/readResults/0/lines/12/words/1"
]
},
...
]
},
...
]
}
]
}
}
分析收據
本節示範如何使用預先定型的收據模型,從美國收據分析及擷取通用字段。 如需收據分析的詳細資訊,請參閱 Document Intelligence 收據模型。 若要開始分析收據,請使用 cURL 命令呼叫 分析收據 API。 執行命令之前,請進行下列變更:
- 將 <端點> 替換成您使用 Document Intelligence 訂用帳戶取得的端點。
- 將 <收據網址> 替換為收據影像的網址。
- 用您從上一步驟複製的鍵替換 <鍵>`。
curl -i -X POST "https://<endpoint>/formrecognizer/v2.1/prebuilt/receipt/analyze" -H "Content-Type: application/json" -H "Ocp-Apim-Subscription-Key: <key>" --data-ascii "{ 'source': '<your receipt URL>'}"
您收到 202 (Success)
回應,其中包含 Operation-Location
標頭。 此標頭的值會包含一個結果識別碼,可用來查詢非同步作業狀態並取得結果:
https://cognitiveservice/formrecognizer/v2.1/prebuilt/receipt/analyzeResults/<resultId>
在下列範例中,operations/
後面的字串是結果標識碼:
https://cognitiveservice/formrecognizer/v2.1/prebuilt/receipt/operations/aeb13e15-555d-4f02-ba47-04d89b487ed5
取得收據結果
呼叫分析收據 API 之後,請呼叫 取得分析收據結果 API,以取得作業的狀態和擷取的數據。 執行命令之前,請進行下列變更:
- 將<端點>取代為您使用文件智慧服務金鑰取得的端點。
- 將 <resultId> 取代為先前步驟中的結果識別碼。
- 將 <金鑰> 取代為您的金鑰。
curl -X GET "https://<endpoint>/formrecognizer/v2.1/prebuilt/receipt/analyzeResults/<resultId>" -H "Ocp-Apim-Subscription-Key: <key>"
您收到具有 JSON 輸出的 200 (Success)
回應。 第一個 "status"
欄位會指出作業的狀態。 如果作業未完成,而 "status"
的值是 "running"
或 "notStarted"
,此時您應該以手動方式或透過指令碼再次呼叫 API。 我們建議您在每次呼叫之間間隔一秒或更長的時間。
如果您將選擇性的 "readResults"
參數設定為 includeTextDetails
,則 true
節點會包含所有已辨識的文字。 回應會依頁面、逐行、個別單字來組織文字。 "documentResults"
節點包含模型探索到的收據特定值。 您可在 "documentResults"
節點中找到有用的機碼/值組,例如稅額、總計、商家地址等等。
請參閱下列收據影像及其對應的 JSON 輸出。
為了提升可讀性,這段回應文本的輸出已被縮短。 請參閱 GitHub 上的完整範例輸出。
{
"status":"succeeded",
"createdDateTime":"2019-12-17T04:11:24Z",
"lastUpdatedDateTime":"2019-12-17T04:11:32Z",
"analyzeResult":{
"version":"2.1.0",
"readResults":[
{
"page":1,
"angle":0.6893,
"width":1688,
"height":3000,
"unit":"pixel",
"language":"en",
"lines":[
{
"text":"Contoso",
"boundingBox":[
635,
510,
1086,
461,
1098,
558,
643,
604
],
"words":[
{
"text":"Contoso",
"boundingBox":[
639,
510,
1087,
461,
1098,
551,
646,
604
],
"confidence":0.955
}
]
},
...
]
}
],
"documentResults":[
{
"docType":"prebuilt:receipt",
"pageRange":[
1,
1
],
"fields":{
"ReceiptType":{
"type":"string",
"valueString":"Itemized",
"confidence":0.692
},
"MerchantName":{
"type":"string",
"valueString":"Contoso Contoso",
"text":"Contoso Contoso",
"boundingBox":[
378.2,
292.4,
1117.7,
468.3,
1035.7,
812.7,
296.3,
636.8
],
"page":1,
"confidence":0.613,
"elements":[
"#/readResults/0/lines/0/words/0",
"#/readResults/0/lines/1/words/0"
]
},
"MerchantAddress":{
"type":"string",
"valueString":"123 Main Street Redmond, WA 98052",
"text":"123 Main Street Redmond, WA 98052",
"boundingBox":[
302,
675.8,
848.1,
793.7,
809.9,
970.4,
263.9,
852.5
],
"page":1,
"confidence":0.99,
"elements":[
"#/readResults/0/lines/2/words/0",
"#/readResults/0/lines/2/words/1",
"#/readResults/0/lines/2/words/2",
"#/readResults/0/lines/3/words/0",
"#/readResults/0/lines/3/words/1",
"#/readResults/0/lines/3/words/2"
]
},
"MerchantPhoneNumber":{
"type":"phoneNumber",
"valuePhoneNumber":"+19876543210",
"text":"987-654-3210",
"boundingBox":[
278,
1004,
656.3,
1054.7,
646.8,
1125.3,
268.5,
1074.7
],
"page":1,
"confidence":0.99,
"elements":[
"#/readResults/0/lines/4/words/0"
]
},
"TransactionDate":{
"type":"date",
"valueDate":"2019-06-10",
"text":"6/10/2019",
"boundingBox":[
265.1,
1228.4,
525,
1247,
518.9,
1332.1,
259,
1313.5
],
"page":1,
"confidence":0.99,
"elements":[
"#/readResults/0/lines/5/words/0"
]
},
"TransactionTime":{
"type":"time",
"valueTime":"13:59:00",
"text":"13:59",
"boundingBox":[
541,
1248,
677.3,
1261.5,
668.9,
1346.5,
532.6,
1333
],
"page":1,
"confidence":0.977,
"elements":[
"#/readResults/0/lines/5/words/1"
]
},
"Items":{
"type":"array",
"valueArray":[
{
"type":"object",
"valueObject":{
"Quantity":{
"type":"number",
"text":"1",
"boundingBox":[
245.1,
1581.5,
300.9,
1585.1,
295,
1676,
239.2,
1672.4
],
"page":1,
"confidence":0.92,
"elements":[
"#/readResults/0/lines/7/words/0"
]
},
"Name":{
"type":"string",
"valueString":"Cappuccino",
"text":"Cappuccino",
"boundingBox":[
322,
1586,
654.2,
1601.1,
650,
1693,
317.8,
1678
],
"page":1,
"confidence":0.923,
"elements":[
"#/readResults/0/lines/7/words/1"
]
},
"TotalPrice":{
"type":"number",
"valueNumber":2.2,
"text":"$2.20",
"boundingBox":[
1107.7,
1584,
1263,
1574,
1268.3,
1656,
1113,
1666
],
"page":1,
"confidence":0.918,
"elements":[
"#/readResults/0/lines/8/words/0"
]
}
}
},
...
]
},
"Subtotal":{
"type":"number",
"valueNumber":11.7,
"text":"11.70",
"boundingBox":[
1146,
2221,
1297.3,
2223,
1296,
2319,
1144.7,
2317
],
"page":1,
"confidence":0.955,
"elements":[
"#/readResults/0/lines/13/words/1"
]
},
"Tax":{
"type":"number",
"valueNumber":1.17,
"text":"1.17",
"boundingBox":[
1190,
2359,
1304,
2359,
1304,
2456,
1190,
2456
],
"page":1,
"confidence":0.979,
"elements":[
"#/readResults/0/lines/15/words/1"
]
},
"Tip":{
"type":"number",
"valueNumber":1.63,
"text":"1.63",
"boundingBox":[
1094,
2479,
1267.7,
2485,
1264,
2591,
1090.3,
2585
],
"page":1,
"confidence":0.941,
"elements":[
"#/readResults/0/lines/17/words/1"
]
},
"Total":{
"type":"number",
"valueNumber":14.5,
"text":"$14.50",
"boundingBox":[
1034.2,
2617,
1387.5,
2638.2,
1380,
2763,
1026.7,
2741.8
],
"page":1,
"confidence":0.985,
"elements":[
"#/readResults/0/lines/19/words/0"
]
}
}
}
]
}
}
分析名片
本節示範如何使用預先定型的模型,從英文名片分析和擷取通用字段。 如需名片分析的詳細資訊,請參閱 Document Intelligence 名片模型。 若要開始分析名片,您可以使用 cURL 命令呼叫 分析名片 API。 執行命令之前,請進行下列變更:
- 將 <端點> 替換成您使用 Document Intelligence 訂用帳戶取得的端點。
- 將 <你的名片的URL> 替換為收據影像的URL。
- 將 <金鑰> 取代為您從上一個步驟複製的金鑰。
curl -i -X POST "https://<endpoint>/formrecognizer/v2.1/prebuilt/businessCard/analyze" -H "Content-Type: application/json" -H "Ocp-Apim-Subscription-Key: <key>" --data-ascii "{ 'source': '<your receipt URL>'}"
您收到 202 (Success)
回應,其中包含 Operation-Location 標頭。 此標頭的值會包含一個結果識別碼,可用來查詢非同步作業狀態並取得結果:
https://cognitiveservice/formrecognizer/v2.1/prebuilt/businessCard/analyzeResults/<resultId>
在下列範例中,URL 中在 analyzeResults/
之後的字串就是結果識別碼。
https://cognitiveservice/formrecognizer/v2.1/prebuilt/businessCard/analyzeResults/54f0b076-4e38-43e5-81bd-b85b8835fdfb
呼叫分析名片 API 之後,請呼叫 取得分析名片結果 API,以取得作業的狀態和擷取的數據。 執行命令之前,請進行下列變更:
- 將<端點>取代為您使用文件智慧服務金鑰取得的端點。
- 將 <resultId> 取代為先前步驟中的結果識別碼。
- 將 <金鑰> 取代為您的金鑰。
curl -v -X GET https://<endpoint>/formrecognizer/v2.1/prebuilt/businessCard/analyzeResults/<resultId>"
-H "Ocp-Apim-Subscription-Key: <key>"
您收到具有 JSON 輸出的 200 (Success)
回應。
"readResults"
節點包含所有已辨識的文字。 回應會依頁面、逐行、個別單字來組織文字。 "documentResults"
節點包含該模型所探索到的名片專屬值。 "documentResults"
節點是您找到有用的連絡資訊,例如公司名稱、名字、姓氏、電話號碼等等。
此範例 JSON 輸出已縮短,以取得可讀性。 請參閱 GitHub 上的完整範例輸出。
{
"status": "succeeded",
"createdDateTime":"2021-02-09T18:14:05Z",
"lastUpdatedDateTime":"2021-02-09T18:14:10Z",
"analyzeResult": {
"version": "2.1.0",
"readResults": [
{
"page":1,
"angle":-16.6836,
"width":4032,
"height":3024,
"unit":"pixel"
}
],
"documentResults": [
{
"docType": "prebuilt:businesscard",
"pageRange": [
1,
1
],
"fields": {
"ContactNames": {
"type": "array",
"valueArray": [
{
"type": "object",
"valueObject": {
"FirstName": {
"type": "string",
"valueString": "Avery",
"text": "Avery",
"boundingBox": [
703,
1096,
1134,
989,
1165,
1109,
733,
1206
],
"page": 1
},
"text": "Dr. Avery Smith",
"boundingBox": [
419.3,
1154.6,
1589.6,
877.9,
1618.9,
1001.7,
448.6,
1278.4
],
"confidence": 0.993
}
]
},
"Emails": {
"type": "array",
"valueArray": [
{
"type": "string",
"valueString": "avery.smith@contoso.com",
"text": "avery.smith@contoso.com",
"boundingBox": [
2107,
934,
2917,
696,
2935,
764,
2126,
995
],
"page": 1,
"confidence": 0.99
}
]
},
"Websites": {
"type": "array",
"valueArray": [
{
"type": "string",
"valueString": "https://www.contoso.com/",
"text": "https://www.contoso.com/",
"boundingBox": [
2121,
1002,
2992,
755,
3014,
826,
2143,
1077
],
"page": 1,
"confidence": 0.995
}
]
}
}
}
]
}
}
指令碼會將回應輸出到主控台,直到「分析名片」作業完成。
分析發票
您可以使用文件智慧,從指定的發票檔中擷取域文字和語意值。 若要開始分析發票,請使用 cURL 命令。 如需發票分析的詳細資訊,請參閱 發票概念指南。 若要開始分析發票,請使用 cURL 命令呼叫 分析發票 API。
執行命令之前,請進行下列變更:
- 將 <端點> 替換成您使用 Document Intelligence 訂用帳戶取得的端點。
- 將你的發票 URL <> 替換為發票檔案的 URL 位址。
- 將 <金鑰> 取代為您的金鑰。
curl -v -i POST https://<endpoint>/formrecognizer/v2.1/prebuilt/invoice/analyze" -H "Content-Type: application/json" -H "Ocp-Apim-Subscription-Key: <key>" --data-ascii "{'urlSource': '<your invoice URL>'}"
您收到 202 (Success)
回應,其中包含 Operation-Location
標頭。 此標頭的值會包含一個結果識別碼,可用來查詢非同步作業狀態並取得結果:
https://cognitiveservice/formrecognizer/v2.1/prebuilt/receipt/analyzeResults/<resultId>
在下列範例中,URL 之中位於 analyzeResults/
後面的字串部分,就是結果識別碼:
https://cognitiveservice/formrecognizer/v2.1/prebuilt/invoice/analyzeResults/54f0b076-4e38-43e5-81bd-b85b8835fdfb
呼叫分析發票 API 之後,請呼叫 取得分析發票結果 API,以取得作業的狀態和擷取的數據。
執行命令之前,請進行下列變更:
- 將<端點>取代為您使用文件智慧服務金鑰取得的端點。
- 將 <resultId> 取代為先前步驟中的結果識別碼。
- 將 <金鑰> 取代為您的金鑰。
curl -v -X GET "https://<endpoint>/formrecognizer/v2.1/prebuilt/invoice/analyzeResults/<resultId>" -H "Ocp-Apim-Subscription-Key: <key>"
您收到具有 JSON 輸出的 200 (Success)
回應。
- 欄位
"readResults"
包含從發票中擷取的每一行文字。 "pageResults"
包含從發票中擷取的資料表和選取標記。"documentResults"
欄位包含發票最相關部分的重要資訊。
請參閱下列發票檔及其對應的 JSON 輸出。
此回應內容 JSON 內容已縮短以提高可讀性。 請參閱 GitHub 上的完整範例輸出。
{
"status": "succeeded",
"createdDateTime": "2020-11-06T23:32:11Z",
"lastUpdatedDateTime": "2020-11-06T23:32:20Z",
"analyzeResult": {
"version": "2.1.0",
"readResults": [{
"page": 1,
"angle": 0,
"width": 8.5,
"height": 11,
"unit": "inch"
}],
"pageResults": [{
"page": 1,
"tables": [{
"rows": 3,
"columns": 4,
"cells": [{
"rowIndex": 0,
"columnIndex": 0,
"text": "QUANTITY",
"boundingBox": [0.4953,
5.7306,
1.8097,
5.7306,
1.7942,
6.0122,
0.4953,
6.0122]
},
{
"rowIndex": 0,
"columnIndex": 1,
"text": "DESCRIPTION",
"boundingBox": [1.8097,
5.7306,
5.7529,
5.7306,
5.7452,
6.0122,
1.7942,
6.0122]
},
...
],
"boundingBox": [0.4794,
5.7132,
8.0158,
5.714,
8.0118,
6.5627,
0.4757,
6.5619]
},
{
"rows": 2,
"columns": 6,
"cells": [{
"rowIndex": 0,
"columnIndex": 0,
"text": "SALESPERSON",
"boundingBox": [0.4979,
4.963,
1.8051,
4.963,
1.7975,
5.2398,
0.5056,
5.2398]
},
{
"rowIndex": 0,
"columnIndex": 1,
"text": "P.O. NUMBER",
"boundingBox": [1.8051,
4.963,
3.3047,
4.963,
3.3124,
5.2398,
1.7975,
5.2398]
},
...
],
"boundingBox": [0.4976,
4.961,
7.9959,
4.9606,
7.9959,
5.5204,
0.4972,
5.5209]
}]
}],
"documentResults": [{
"docType": "prebuilt:invoice",
"pageRange": [1,
1],
"fields": {
"AmountDue": {
"type": "number",
"valueNumber": 610,
"text": "$610.00",
"boundingBox": [7.3809,
7.8153,
7.9167,
7.8153,
7.9167,
7.9591,
7.3809,
7.9591],
"page": 1,
"confidence": 0.875
},
"BillingAddress": {
"type": "string",
"valueString": "123 Bill St, Redmond WA, 98052",
"text": "123 Bill St, Redmond WA, 98052",
"boundingBox": [0.594,
4.3724,
2.0125,
4.3724,
2.0125,
4.7125,
0.594,
4.7125],
"page": 1,
"confidence": 0.997
},
"BillingAddressRecipient": {
"type": "string",
"valueString": "Microsoft Finance",
"text": "Microsoft Finance",
"boundingBox": [0.594,
4.1684,
1.7907,
4.1684,
1.7907,
4.2837,
0.594,
4.2837],
"page": 1,
"confidence": 0.998
},
...
}
}]
}
}
分析身分識別檔
若要開始分析識別碼 (ID) 檔,請使用 cURL 命令。 如需了解更多關於身份證件分析的資訊,請參閱 文件智能身份證件模型。 若要開始分析識別碼檔,您可以使用 cURL 命令呼叫 分析識別碼檔 API。
執行命令之前,請進行下列變更:
- 將 <端點> 替換成您使用 Document Intelligence 訂用帳戶取得的端點。
- 將<您的身分證明文件 URL> 取代為收據影像的 URL 位址。
- 將 <金鑰> 取代為您從上一個步驟複製的金鑰。
curl -i -X POST "https://<endpoint>/formrecognizer/v2.1/prebuilt/idDocument/analyze" -H "Content-Type: application/json" -H "Ocp-Apim-Subscription-Key: <key>" --data-ascii "{ 'source': '<your ID document URL>'}"
您收到 202 (Success)
回應,其中包含 Operation-Location
標頭。 此標頭的值會包含一個結果識別碼,可用來查詢非同步作業狀態並取得結果:
https://cognitiveservice/formrecognizer/v2.1/prebuilt/documentId/analyzeResults/<resultId>
在下列範例中,analyzeResults/
後面的字串是結果標識碼:
https://westus.api.cognitive.microsoft.com/formrecognizer/v2.1/prebuilt/idDocument/analyzeResults/3bc1d6e0-e24c-41d2-8c50-14e9edc336d1
取得分析身分證明文件結果
呼叫分析標識碼檔 API 之後,請呼叫 取得分析標識符文件結果 API,以取得作業的狀態和擷取的數據。 執行命令之前,請進行下列變更:
- 將<端點>取代為您使用文件智慧服務金鑰取得的端點。
- 將 <resultId> 取代為先前步驟中的結果識別碼。
- 將 <金鑰> 取代為您的金鑰。
curl -X GET "https://<endpoint>/formrecognizer/v2.1/prebuilt/idDocument/analyzeResults/<resultId>" -H "Ocp-Apim-Subscription-Key: <key>"
您收到具有 JSON 輸出的 200 (Success)
回應。 第一個 "status"
欄位會指出作業的狀態。 如果工作未完成,則的值 "status"
為 "running"
或 "notStarted"
。 手動或透過腳本再次呼叫 API,直到您收到 succeeded
值為止。 我們建議您在每次呼叫之間間隔一秒或更長的時間。
- [
"readResults"
] 字段包含從標識符檔擷取的每一行文字。 "documentResults"
欄位包含 物件的陣列,每個物件都代表輸入檔中偵測到的標識碼檔。
以下是範例標識碼檔及其對應的 JSON 輸出。
以下是回應內容。
{
"status": "succeeded",
"createdDateTime": "2021-04-13T17:24:52Z",
"lastUpdatedDateTime": "2021-04-13T17:24:55Z",
"analyzeResult": {
"version": "2.1.0",
"readResults": [
{
"page": 1,
"angle": -0.2823,
"width": 450,
"height": 294,
"unit": "pixel"
}
],
"documentResults": [
{
"docType": "prebuilt:idDocument:driverLicense",
"docTypeConfidence": 0.995,
"pageRange": [
1,
1
],
"fields": {
"Address": {
"type": "string",
"valueString": "123 STREET ADDRESS YOUR CITY WA 99999-1234",
"text": "123 STREET ADDRESS YOUR CITY WA 99999-1234",
"boundingBox": [
158,
151,
326,
151,
326,
177,
158,
177
],
"page": 1,
"confidence": 0.965
},
"CountryRegion": {
"type": "countryRegion",
"valueCountryRegion": "USA",
"confidence": 0.99
},
"DateOfBirth": {
"type": "date",
"valueDate": "1958-01-06",
"text": "01/06/1958",
"boundingBox": [
187,
133,
272,
132,
272,
148,
187,
149
],
"page": 1,
"confidence": 0.99
},
"DateOfExpiration": {
"type": "date",
"valueDate": "2020-08-12",
"text": "08/12/2020",
"boundingBox": [
332,
230,
414,
228,
414,
244,
332,
245
],
"page": 1,
"confidence": 0.99
},
"DocumentNumber": {
"type": "string",
"valueString": "LICWDLACD5DG",
"text": "LIC#WDLABCD456DG",
"boundingBox": [
162,
70,
307,
68,
307,
84,
163,
85
],
"page": 1,
"confidence": 0.99
},
"FirstName": {
"type": "string",
"valueString": "LIAM R.",
"text": "LIAM R.",
"boundingBox": [
158,
102,
216,
102,
216,
116,
158,
116
],
"page": 1,
"confidence": 0.985
},
"LastName": {
"type": "string",
"valueString": "TALBOT",
"text": "TALBOT",
"boundingBox": [
160,
86,
213,
85,
213,
99,
160,
100
],
"page": 1,
"confidence": 0.987
},
"Region": {
"type": "string",
"valueString": "Washington",
"confidence": 0.99
},
"Sex": {
"type": "string",
"valueString": "M",
"text": "M",
"boundingBox": [
226,
190,
232,
190,
233,
201,
226,
201
],
"page": 1,
"confidence": 0.99
}
}
}
]
}
}
訓練自訂模型
若要定型自定義模型,您需要 Azure 記憶體 Blob 中的一組定型數據。 您至少需要五個相同類型/結構的填入表單(PDF 檔和/或影像)。 如需組合您的訓練數據的秘訣和選項,請參閱 建置與訓練自訂模型。
沒有標記數據的訓練是預設,並且更簡單。 或者,您可以事先手動標記部分或全部訓練數據。 手動標記是更複雜的流程,但可產生較佳的訓練模型。
備註
您也可以使用圖形使用者介面來定型模型,例如 檔案智慧範例標籤工具。
訓練不含標籤的模型
若要使用 Azure Blob 容器中的文件來定型文件智慧模型,請執行下列 cURL 命令,呼叫 定型自定義模型 API。 執行命令之前,請進行下列變更:
- 將 <端點> 替換成您使用 Document Intelligence 訂用帳戶取得的端點。
- 將 <金鑰> 取代為您從上一個步驟複製的金鑰。
- 將 <SAS URL> 替換為 Azure Blob 儲存體容器的共用存取簽章(SAS)URL。
若要擷取自定義模型定型數據的SAS URL:
移至 Azure 入口網站中的記憶體資源,然後選取 [資料記憶體>容器]。
瀏覽至您的容器,按下滑鼠右鍵,然後選取 產生 SAS。
取得您容器的 SAS,而不是儲存體帳戶本身的 SAS。
請確定已選取 讀取、寫入、刪除和 列出 許可權,然後選取 產生 SAS 令牌和 URL。
將 [URL] 區段中的值複製到暫存位置。 其格式應該為:
https://<storage account>.blob.core.windows.net/<container name>?<SAS value>
。
進行變更,然後執行命令:
curl -i -X POST "https://<endpoint>/formrecognizer/v2.1/custom/models" -H "Content-Type: application/json" -H "Ocp-Apim-Subscription-Key: <key>" --data-ascii "{ 'source': '<SAS URL>'}"
您收到包含 201 (Success)
標頭的 Location
回應。 此標頭的值包含新定型模型的模型識別碼,可用來查詢作業的狀態並取得結果:
https://<endpoint>/formrecognizer/v2.1/custom/models/<modelId>
在下列範例中,作為URL的一部分,models/
之後的字串是模型標識符。
https://westus.api.cognitive.microsoft.com/formrecognizer/v2.1/custom/models/77d8ecad-b8c1-427e-ac20-a3fe4af503e9
訓練具備標籤的模型
若要使用標籤來訓練,您的 Blob 儲存體容器中除了訓練文件以外,還必須要有特殊的標籤資訊檔案 (<filename>.pdf.labels.json)。 檔智慧範例標籤工具 提供 UI 來協助您建立這些標籤檔案。 有了這些檔案之後,即可呼叫定型自訂模型 API,並且在 JSON 主體中將 "useLabelFile"
參數設定為 true
。
執行命令之前,請進行下列變更:
- 將 <端點> 替換成您使用 Document Intelligence 訂用帳戶取得的端點。
- 將 <金鑰> 取代為您從上一個步驟複製的金鑰。
- 將 <SAS URL> 替換為 Azure Blob 儲存體容器的共用存取簽章(SAS)URL。
若要擷取自定義模型定型數據的SAS URL:
移至 Azure 入口網站中的記憶體資源,然後選取 [資料記憶體>容器.1。 瀏覽至您的容器,按下滑鼠右鍵,然後選取 產生 SAS。
取得您容器的 SAS,而不是儲存體帳戶本身的 SAS。
請確定已選取 讀取、寫入、刪除和 列出 許可權,然後選取 產生 SAS 令牌和 URL。
將 [URL] 區段中的值複製到暫存位置。 其格式應該為:
https://<storage account>.blob.core.windows.net/<container name>?<SAS value>
。
進行變更,然後執行命令:
curl -i -X POST "https://<endpoint>/formrecognizer/v2.1/custom/models" -H "Content-Type: application/json" -H "Ocp-Apim-Subscription-Key: <key>" --data-ascii "{ 'source': '<SAS URL>', 'useLabelFile':true}"
您收到包含 201 (Success)
標頭的 Location
回應。 此標頭的值包含新定型模型的模型識別碼,可用來查詢作業的狀態並取得結果:
https://<endpoint>/formrecognizer/v2.1/custom/models/<modelId>
在下列範例中,作為URL的一部分,models/
之後的字串是模型標識符。
https://westus.api.cognitive.microsoft.com/formrecognizer/v2.1/custom/models/62e79d93-78a7-4d18-85be-9540dbb8e792
開始進行訓練作業後,請使用取得自訂模型檢查訓練狀態。 將模型識別碼傳遞至 API 要求,以檢查定型狀態:
- 將<端點>取代為您使用文件智慧服務金鑰取得的端點。
- 將 <金鑰> 取代為您的金鑰
- 以您在上一個步驟中收到的模型標識碼取代 <模型標識碼>
curl -X GET "https://<endpoint>/formrecognizer/v2.1/custom/models/<modelId>" -H "Content-Type: application/json" -H "Ocp-Apim-Subscription-Key: <key>"
使用自定義模型分析表單
接下來,使用新定型的模型來分析檔,並從中擷取欄位和數據表。 執行下列 cURL 命令,呼叫 分析表單 API。 執行命令之前,請進行下列變更:
- 將<端點>取代為您從文件智慧服務金鑰取得的端點。
- 將<模型識別碼>取代為您在上一節中取得的模型識別碼。
- 將 <SAS URL> 取代為您在 Azure 儲存體中的檔案的 SAS URL。 請依照<訓練>一節中的步驟操作,但不要取得整個 Blob 容器的 SAS URL,而是取得您要分析之特定檔案的 URL。
- 將 <金鑰> 取代為您的金鑰。
curl -v "https://<endpoint>/formrecognizer/v2.1/custom/models/<modelId>/analyze?includeTextDetails=true" -H "Content-Type: application/json" -H "Ocp-Apim-Subscription-Key: <key>" -d "{ 'source': '<SAS URL>' } "
您收到包含 202 (Success)
標頭的 Operation-Location
回應。 這個標頭的值包含您用來追蹤分析作業結果的結果識別碼:
https://cognitiveservice/formrecognizer/v2.1/custom/models/<modelId>/analyzeResults/<resultId>
在下列範例中,URL 中在 analyzeResults/
之後的字串就是結果識別碼。
https://cognitiveservice/formrecognizer/v2/layout/analyzeResults/e175e9db-d920-4c7d-bc44-71d1653cdd06
儲存下一個步驟的結果標識碼。
呼叫 分析窗體結果 API 來查詢分析作業的結果。
- 將<端點>取代為您從文件智慧服務金鑰取得的端點。
- 將<結果識別碼>取代為您在上一節中取得的識別碼。
- 將 <金鑰> 取代為您的金鑰。
curl -X GET "https://<endpoint>/formrecognizer/v2.1/custom/models/<modelId>/analyzeResults/<resultId>" -H "Ocp-Apim-Subscription-Key: <key>"
您收到 200 (Success)
回應,內含下列格式的 JSON 本文。 為了簡單起見,我們已將輸出內容縮短。 請注意底部附近的 "status"
欄位。 當分析作業完成時,此欄位的值 "succeeded"
。 如果分析作業尚未完成,您必須重新執行 命令來再次查詢服務。 我們建議您在每次呼叫之間間隔一秒或更長的時間。
在沒有標籤的情況下訓練的自訂模型中,機碼/值組關聯和表格位於 JSON 輸出的 "pageResults"
節點中。 在沒有標籤的情況下訓練的自訂模型中,機碼/值組關聯位於 "documentResults"
節點中。 如果您也透過 includeTextDetails URL 參數指定純文本擷取,則 "readResults"
節點會顯示檔中所有文字的內容和位置。
為了簡單起見,此範例 JSON 輸出已縮短。 請參閱 GitHub 上的完整範例輸出。
{
"status": "succeeded",
"createdDateTime": "2020-08-21T01:13:28Z",
"lastUpdatedDateTime": "2020-08-21T01:13:42Z",
"analyzeResult": {
"version": "2.1.0",
"readResults": [
{
"page": 1,
"angle": 0,
"width": 8.5,
"height": 11,
"unit": "inch",
"lines": [
{
"text": "Project Statement",
"boundingBox": [
5.0444,
0.3613,
8.0917,
0.3613,
8.0917,
0.6718,
5.0444,
0.6718
],
"words": [
{
"text": "Project",
"boundingBox": [
5.0444,
0.3587,
6.2264,
0.3587,
6.2264,
0.708,
5.0444,
0.708
]
},
{
"text": "Statement",
"boundingBox": [
6.3361,
0.3635,
8.0917,
0.3635,
8.0917,
0.6396,
6.3361,
0.6396
]
}
]
},
...
]
}
],
"pageResults": [
{
"page": 1,
"keyValuePairs": [
{
"key": {
"text": "Date:",
"boundingBox": [
6.9833,
1.0615,
7.3333,
1.0615,
7.3333,
1.1649,
6.9833,
1.1649
],
"elements": [
"#/readResults/0/lines/2/words/0"
]
},
"value": {
"text": "9/10/2020",
"boundingBox": [
7.3833,
1.0802,
7.925,
1.0802,
7.925,
1.174,
7.3833,
1.174
],
"elements": [
"#/readResults/0/lines/3/words/0"
]
},
"confidence": 1
},
...
],
"tables": [
{
"rows": 5,
"columns": 5,
"cells": [
{
"text": "Training Date",
"rowIndex": 0,
"columnIndex": 0,
"boundingBox": [
0.6944,
4.2779,
1.5625,
4.2779,
1.5625,
4.4005,
0.6944,
4.4005
],
"confidence": 1,
"rowSpan": 1,
"columnSpan": 1,
"elements": [
"#/readResults/0/lines/15/words/0",
"#/readResults/0/lines/15/words/1"
],
"isHeader": true,
"isFooter": false
},
...
]
}
],
"clusterId": 0
}
],
"documentResults": [],
"errors": []
}
}
改善結果
檢查 "confidence"
節點下每個鍵/值結果的 "pageResults"
值。 您也應該查看 "readResults"
節點中的信心分數,這些分數對應於文字讀取作業。 讀取結果的信賴度並不會影響索引鍵/值擷取結果的信賴度,因此您應該同時檢查這兩者。
- 如果讀取作業的信賴分數很低,請嘗試改善輸入文件的品質。 如需詳細資訊,請參閱 輸入需求。
- 如果索引鍵/值擷取作業的信賴分數很低,請確定要分析的檔與定型集中使用的檔類型相同。 如果定型集中的文件外觀有變化,請考慮將它們分割成不同的資料夾,併為每個變化定型一個模型。
您鎖定的信賴分數取決於您的使用案例,但通常最好以 80% 或更高的分數為目標。 對於更敏感的案例,例如讀取醫療記錄或帳單,我們建議分數為 100%。
管理自定義模型
使用下列命令中的 列出自定義模型 API,傳回屬於您訂用帳戶的所有自定義模型清單。
- 將 <端點> 替換成您使用 Document Intelligence 訂用帳戶取得的端點。
- 將 <金鑰> 取代為您從上一個步驟複製的金鑰。
curl -v -X GET "https://<endpoint>/formrecognizer/v2.1/custom/models?op=full"
-H "Ocp-Apim-Subscription-Key: <key>"
您會收到 200
成功回應,JSON 數據如下所示。 "modelList"
元素包含您建立的所有模型及其資訊。
{
"summary": {
"count": 0,
"limit": 0,
"lastUpdatedDateTime": "string"
},
"modelList": [
{
"modelId": "string",
"status": "creating",
"createdDateTime": "string",
"lastUpdatedDateTime": "string"
}
],
"nextLink": "string"
}
取得特定模型
若要擷取特定自定義模型的詳細資訊,請使用下列命令中的 取得自定義模型 API。
- 將 <端點> 替換成您使用 Document Intelligence 訂用帳戶取得的端點。
- 將 <金鑰> 取代為您從上一個步驟複製的金鑰。
- 將 <modelId> 替換成您想要查閱的自定義模型識別碼。
curl -v -X GET "https://<endpoint>/formrecognizer/v2.1/custom/models/<modelId>" -H "Ocp-Apim-Subscription-Key: <key>"
您會收到 200
成功回應,其請求體含有 JSON 數據,如下所示。
{
"modelInfo": {
"modelId": "string",
"status": "creating",
"createdDateTime": "string",
"lastUpdatedDateTime": "string"
},
"keys": {
"clusters": {}
},
"trainResult": {
"trainingDocuments": [
{
"documentName": "string",
"pages": 0,
"errors": [
"string"
],
"status": "succeeded"
}
],
"fields": [
{
"fieldName": "string",
"accuracy": 0.0
}
],
"averageModelAccuracy": 0.0,
"errors": [
{
"message": "string"
}
]
}
}
從資源帳戶刪除模型
您也可以參考其識別碼,從您的帳戶中刪除模型。 此命令會呼叫 刪除自定義模型 API,以刪除上一節中使用的模型。
- 將 <端點> 替換成您使用 Document Intelligence 訂用帳戶取得的端點。
- 將 <金鑰> 取代為您從上一個步驟複製的金鑰。
- 將 <modelId> 替換成您想要查閱的自定義模型識別碼。
curl -v -X DELETE "https://<endpoint>/formrecognizer/v2.1/custom/models/<modelId>" -H "Ocp-Apim-Subscription-Key: <key>"
您會收到 204
成功回應,指出您的模型已標示為要刪除。 模型成品會在 48 小時內移除。
後續步驟
在此專案中,您已使用 Document Intelligence REST API 以不同方式分析表單。 接下來,探索參考文件,以深入了解文件智能 API。