Skip to content

Commit

Permalink
[FormRecognizer] Preview 3: moving to new Receipt design (#12523)
Browse files Browse the repository at this point in the history
  • Loading branch information
kinelski authored Jun 5, 2020
1 parent 12c2c31 commit 6c96ee3
Show file tree
Hide file tree
Showing 19 changed files with 343 additions and 529 deletions.
2 changes: 2 additions & 0 deletions sdk/formrecognizer/Azure.AI.FormRecognizer/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@
- The order of the values for `USReceiptType` have changed so that `Other` has now a value of `1`.
- Parameter `useTrainingLabels` is now required for `FormTrainingClient.StartTraining`.
- Protected constructors have been removed from `Operation` types, such as `TrainingOperation` or `RecognizeContentOperation`.
- `USReceipt`, `USReceiptItem`, `USReceiptType` and `FormField{T}` types removed. Information about a `RecognizedReceipt` must now be extracted from its `RecognizedForm`.
- `ReceiptLocale` removed from `RecognizedReceipt`.

### New Features

Expand Down
90 changes: 70 additions & 20 deletions sdk/formrecognizer/Azure.AI.FormRecognizer/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -137,33 +137,83 @@ Recognize data from US sales receipts using a prebuilt model.
using (FileStream stream = new FileStream(receiptPath, FileMode.Open))
{
RecognizedReceiptCollection receipts = await client.StartRecognizeReceipts(stream).WaitForCompletionAsync();
foreach (var receipt in receipts)

// To see the list of the supported fields returned by service and its corresponding types, consult:
// https://westus2.dev.cognitive.microsoft.com/docs/services/form-recognizer-api-v2-preview/operations/GetAnalyzeReceiptResult
foreach (RecognizedReceipt receipt in receipts)
{
USReceipt usReceipt = receipt.AsUSReceipt();
FormField merchantNameField;
if (receipt.RecognizedForm.Fields.TryGetValue("MerchantName", out merchantNameField))
{
if (merchantNameField.Value.Type == FieldValueType.String)
{
string merchantName = merchantNameField.Value.AsString();

Console.WriteLine($"Merchant Name: '{merchantName}', with confidence {merchantNameField.Confidence}");
}
}

string merchantName = usReceipt.MerchantName?.Value ?? default;
DateTime transactionDate = usReceipt.TransactionDate?.Value ?? default;
IReadOnlyList<USReceiptItem> items = usReceipt.Items ?? default;
float subtotal = usReceipt.Subtotal?.Value ?? default;
float tax = usReceipt.Tax?.Value ?? default;
float tip = usReceipt.Tip?.Value ?? default;
float total = usReceipt.Total?.Value ?? default;
FormField transactionDateField;
if (receipt.RecognizedForm.Fields.TryGetValue("TransactionDate", out transactionDateField))
{
if (transactionDateField.Value.Type == FieldValueType.Date)
{
DateTime transactionDate = transactionDateField.Value.AsDate();

Console.WriteLine($"Recognized USReceipt fields:");
Console.WriteLine($" Merchant Name: '{merchantName}', with confidence {usReceipt.MerchantName.Confidence}");
Console.WriteLine($" Transaction Date: '{transactionDate}', with confidence {usReceipt.TransactionDate.Confidence}");
Console.WriteLine($"Transaction Date: '{transactionDate}', with confidence {transactionDateField.Confidence}");
}
}

for (int i = 0; i < items.Count; i++)
FormField itemsField;
if (receipt.RecognizedForm.Fields.TryGetValue("Items", out itemsField))
{
USReceiptItem item = usReceipt.Items[i];
Console.WriteLine($" Item {i}: Name: '{item.Name.Value}', Quantity: '{item.Quantity?.Value}', Price: '{item.Price?.Value}'");
Console.WriteLine($" TotalPrice: '{item.TotalPrice.Value}'");
if (itemsField.Value.Type == FieldValueType.List)
{
foreach (FormField itemField in itemsField.Value.AsList())
{
Console.WriteLine("Item:");

if (itemField.Value.Type == FieldValueType.Dictionary)
{
IReadOnlyDictionary<string, FormField> itemFields = itemField.Value.AsDictionary();

FormField itemNameField;
if (itemFields.TryGetValue("Name", out itemNameField))
{
if (itemNameField.Value.Type == 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.Type == FieldValueType.Float)
{
float itemTotalPrice = itemTotalPriceField.Value.AsFloat();

Console.WriteLine($" Total Price: '{itemTotalPrice}', with confidence {itemTotalPriceField.Confidence}");
}
}
}
}
}
}

Console.WriteLine($" Subtotal: '{subtotal}', with confidence '{usReceipt.Subtotal.Confidence}'");
Console.WriteLine($" Tax: '{tax}', with confidence '{usReceipt.Tax.Confidence}'");
Console.WriteLine($" Tip: '{tip}', with confidence '{usReceipt.Tip?.Confidence ?? 0.0f}'");
Console.WriteLine($" Total: '{total}', with confidence '{usReceipt.Total.Confidence}'");
FormField totalField;
if (receipt.RecognizedForm.Fields.TryGetValue("Total", out totalField))
{
if (totalField.Value.Type == FieldValueType.Float)
{
float total = totalField.Value.AsFloat();

Console.WriteLine($"Total: '{total}', with confidence '{totalField.Confidence}'");
}
}
}
}
```
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,33 +23,83 @@ To recognize receipts from a URI, use the `StartRecognizeReceiptsFromUri` method

```C# Snippet:FormRecognizerSampleRecognizeReceiptFileFromUri
RecognizedReceiptCollection receipts = await client.StartRecognizeReceiptsFromUri(new Uri(receiptUri)).WaitForCompletionAsync();
foreach (var receipt in receipts)

// To see the list of the supported fields returned by service and its corresponding types, consult:
// https://westus2.dev.cognitive.microsoft.com/docs/services/form-recognizer-api-v2-preview/operations/GetAnalyzeReceiptResult
foreach (RecognizedReceipt receipt in receipts)
{
USReceipt usReceipt = receipt.AsUSReceipt();
FormField merchantNameField;
if (receipt.RecognizedForm.Fields.TryGetValue("MerchantName", out merchantNameField))
{
if (merchantNameField.Value.Type == FieldValueType.String)
{
string merchantName = merchantNameField.Value.AsString();

Console.WriteLine($"Merchant Name: '{merchantName}', with confidence {merchantNameField.Confidence}");
}
}

string merchantName = usReceipt.MerchantName?.Value ?? default;
DateTime transactionDate = usReceipt.TransactionDate?.Value ?? default;
IReadOnlyList<USReceiptItem> items = usReceipt.Items ?? default;
float subtotal = usReceipt.Subtotal?.Value ?? default;
float tax = usReceipt.Tax?.Value ?? default;
float tip = usReceipt.Tip?.Value ?? default;
float total = usReceipt.Total?.Value ?? default;
FormField transactionDateField;
if (receipt.RecognizedForm.Fields.TryGetValue("TransactionDate", out transactionDateField))
{
if (transactionDateField.Value.Type == FieldValueType.Date)
{
DateTime transactionDate = transactionDateField.Value.AsDate();

Console.WriteLine($"Recognized USReceipt fields:");
Console.WriteLine($" Merchant Name: '{merchantName}', with confidence {usReceipt.MerchantName.Confidence}");
Console.WriteLine($" Transaction Date: '{transactionDate}', with confidence {usReceipt.TransactionDate.Confidence}");
Console.WriteLine($"Transaction Date: '{transactionDate}', with confidence {transactionDateField.Confidence}");
}
}

for (int i = 0; i < items.Count; i++)
FormField itemsField;
if (receipt.RecognizedForm.Fields.TryGetValue("Items", out itemsField))
{
USReceiptItem item = usReceipt.Items[i];
Console.WriteLine($" Item {i}: Name: '{item.Name.Value}', Quantity: '{item.Quantity?.Value}', Price: '{item.Price?.Value}'");
Console.WriteLine($" TotalPrice: '{item.TotalPrice.Value}'");
if (itemsField.Value.Type == FieldValueType.List)
{
foreach (FormField itemField in itemsField.Value.AsList())
{
Console.WriteLine("Item:");

if (itemField.Value.Type == FieldValueType.Dictionary)
{
IReadOnlyDictionary<string, FormField> itemFields = itemField.Value.AsDictionary();

FormField itemNameField;
if (itemFields.TryGetValue("Name", out itemNameField))
{
if (itemNameField.Value.Type == 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.Type == FieldValueType.Float)
{
float itemTotalPrice = itemTotalPriceField.Value.AsFloat();

Console.WriteLine($" Total Price: '{itemTotalPrice}', with confidence {itemTotalPriceField.Confidence}");
}
}
}
}
}
}

Console.WriteLine($" Subtotal: '{subtotal}', with confidence '{usReceipt.Subtotal.Confidence}'");
Console.WriteLine($" Tax: '{tax}', with confidence '{usReceipt.Tax.Confidence}'");
Console.WriteLine($" Tip: '{tip}', with confidence '{usReceipt.Tip?.Confidence ?? 0.0f}'");
Console.WriteLine($" Total: '{total}', with confidence '{usReceipt.Total.Confidence}'");
FormField totalField;
if (receipt.RecognizedForm.Fields.TryGetValue("Total", out totalField))
{
if (totalField.Value.Type == FieldValueType.Float)
{
float total = totalField.Value.AsFloat();

Console.WriteLine($"Total: '{total}', with confidence '{totalField.Confidence}'");
}
}
}
```

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,11 @@ internal AccountProperties(ModelsSummary_internal summary)
/// <summary>
/// The current count of trained custom models.
/// </summary>
public int CustomModelCount { get; internal set; }
public int CustomModelCount { get; }

/// <summary>
/// The maximum number of models that can be trained for this subscription.
/// </summary>
public int CustomModelLimit { get; internal set; }
public int CustomModelLimit { get; }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,13 @@ internal CustomFormSubmodel(string formType, float? accuracy, IReadOnlyDictionar
/// <summary>
/// The type of form this submodel recognizes.
/// </summary>
public string FormType { get; internal set; }
public string FormType { get; }

/// <summary>
/// The mean of the accuracies of this model's <see cref="CustomFormModelField"/>
/// instances.
/// </summary>
public float? Accuracy { get; internal set; }
public float? Accuracy { get; }

/// <summary>
/// A dictionary of the fields that this submodel will recognize from the
Expand All @@ -35,6 +35,6 @@ internal CustomFormSubmodel(string formType, float? accuracy, IReadOnlyDictionar
/// label of the field. For models trained with forms only, a unique name is
/// generated for each field.
/// </summary>
public IReadOnlyDictionary<string, CustomFormModelField> Fields { get; internal set; }
public IReadOnlyDictionary<string, CustomFormModelField> Fields { get; }
}
}
8 changes: 4 additions & 4 deletions sdk/formrecognizer/Azure.AI.FormRecognizer/src/FormField.cs
Original file line number Diff line number Diff line change
Expand Up @@ -53,22 +53,22 @@ internal FormField(string name, FieldValue_internal fieldValue, IReadOnlyList<Re
/// <summary>
/// Canonical name; uniquely identifies a field within the form.
/// </summary>
public string Name { get; internal set; }
public string Name { get; }

/// <summary>
/// Contains the text, bounding box and content of the label of the field in the form.
/// </summary>
public FieldText LabelText { get; internal set; }
public FieldText LabelText { get; }

/// <summary>
/// Contains the text, bounding box and content of the value of the field in the form.
/// </summary>
public FieldText ValueText { get; internal set; }
public FieldText ValueText { get; }

/// <summary>
/// The strongly-typed value of this <see cref="FormField"/>.
/// </summary>
public FieldValue Value { get; internal set; }
public FieldValue Value { get; }

/// <summary>
/// Measures the degree of certainty of the recognition result. Value is between [0.0, 1.0].
Expand Down
63 changes: 0 additions & 63 deletions sdk/formrecognizer/Azure.AI.FormRecognizer/src/FormField{T}.cs

This file was deleted.

2 changes: 1 addition & 1 deletion sdk/formrecognizer/Azure.AI.FormRecognizer/src/FormLine.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ internal FormLine(TextLine_internal textLine, int pageNumber)
/// <summary>
/// A list of the words that make up the line.
/// </summary>
public IReadOnlyList<FormWord> Words { get; internal set; }
public IReadOnlyList<FormWord> Words { get; }

private static IReadOnlyList<FormWord> ConvertWords(IReadOnlyList<TextWord_internal> textWords, int pageNumber)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,12 @@ public partial class FormRecognizerError
/// The error code.
/// </summary>
[CodeGenMember("Code")]
public string ErrorCode { get; internal set; }
public string ErrorCode { get; }

/// <summary>
/// The error message.
/// </summary>
[CodeGenMember("Message")]
public string Message { get; internal set; }
public string Message { get; }
}
}
12 changes: 0 additions & 12 deletions sdk/formrecognizer/Azure.AI.FormRecognizer/src/GetModelOptions.cs

This file was deleted.

Loading

0 comments on commit 6c96ee3

Please sign in to comment.