Skip to content

Commit 2f759ab

Browse files
[ai-form-recognizer] Selection mark and other new output fields in 2.1-preview.1 (Azure#12540)
* [ai-form-recognizer] Add support for selection mark and other new fields * Added simple tests for selection marks * Recorded new tests * Modified samples to show selection marks in pages * Removed it.only that I left in * Made array concat reduce more explicit * Addressed feedback * Made flattening composed results simpler * Added a test for selection mark values, updated test-resources.json * Addressed more feedback * Fixed typo in test-resources * Updated test-resources to use new container
1 parent ea4ad0d commit 2f759ab

File tree

21 files changed

+1133
-125
lines changed

21 files changed

+1133
-125
lines changed

sdk/formrecognizer/ai-form-recognizer/CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,11 @@
22

33
## 3.1.0-beta.1 (Unreleased)
44

5+
- Added a `formTypeConfidence` property to `RecognizedForm` indicating the model's confidence in determining the correct form type (and therefore the correct model to use) during recognition.
6+
- Added a `properties` field to `CustomFormModelInfo` that may optionally contain extra properties. Currently, the only property is `isComposedModel` which will indicate whether the model is a composed model or a single trained model.
7+
- Added a `modelId` field to the `CustomFormSubmodel`, `TrainingDocumentInfo`, and `RecognizedForm` types containing the ID of the exact model that they are associated with (for example, in the context of a composed model, the `modelId` field can determine which specific component model is associated with the submodel, training document, or recognized form).
8+
- Added support for selection marks in form fields. In addition to the previously-existing variants of `FormField`, custom models can now return fields with `valueType: "selectionMark"` and their `value` will be the state of the selection mark.
9+
- Added a new page element `FormSelectionMark` that represents marks on a page that can be selected (such as checkboxes and radio buttons). The `selectionMarks` field of `FormPage` contains the selection marks that were recognized in the page. A selection mark has a state value that is either "checked" or "unchecked."
510
- Made optimizations to the long-running operation infrastructure that should result in faster and more memory-efficient polling for results of custom form recognition, receipt recognition, and business card recognition.
611
- Added an option for specifying the locale of a document to receipt and business card methods through the `locale` property of the options bag.
712
- Added support for Business Card recognition through the `beginRecognizeBusinessCards` and `beginRecognizeBusinessCardsFromUrl` methods, which mirror their receipt counterparts.

sdk/formrecognizer/ai-form-recognizer/karma.conf.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ module.exports = function(config) {
6060
"FORM_RECOGNIZER_API_KEY",
6161
"FORM_RECOGNIZER_TRAINING_CONTAINER_SAS_URL",
6262
"FORM_RECOGNIZER_TESTING_CONTAINER_SAS_URL",
63+
"FORM_RECOGNIZER_SELECTION_MARK_STORAGE_CONTAINER_SAS_URL",
6364
"FORM_RECOGNIZER_TARGET_RESOURCE_ID",
6465
"FORM_RECOGNIZER_TARGET_RESOURCE_REGION",
6566
"AZURE_CLIENT_ID",

sdk/formrecognizer/ai-form-recognizer/recordings/node/aad_formrecognizerclient_nodejs_only_content_analysis/recording_with_selection_marks.js

Lines changed: 133 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

sdk/formrecognizer/ai-form-recognizer/recordings/node/aad_formrecognizerclient_nodejs_only_custom_forms/recording_with_selection_marks.js

Lines changed: 245 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

sdk/formrecognizer/ai-form-recognizer/recordings/node/api_key_formrecognizerclient_nodejs_only_content_analysis/recording_with_selection_marks.js

Lines changed: 100 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

sdk/formrecognizer/ai-form-recognizer/recordings/node/api_key_formrecognizerclient_nodejs_only_custom_forms/recording_with_selection_marks.js

Lines changed: 179 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

sdk/formrecognizer/ai-form-recognizer/review/ai-form-recognizer.api.md

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -111,16 +111,23 @@ export interface CustomFormModelField {
111111
export interface CustomFormModelInfo {
112112
modelId: string;
113113
modelName?: string;
114+
properties?: CustomFormModelProperties;
114115
status: ModelStatus;
115116
trainingCompletedOn: Date;
116117
trainingStartedOn: Date;
117118
}
118119

120+
// @public
121+
export interface CustomFormModelProperties {
122+
isComposedModel?: boolean;
123+
}
124+
119125
// @public
120126
export interface CustomFormSubmodel {
121127
accuracy?: number;
122128
fields: Record<string, CustomFormModelField>;
123129
formType: string;
130+
modelId?: string;
124131
}
125132

126133
// @public
@@ -138,13 +145,13 @@ export interface FieldData {
138145
export type FormContentType = "application/pdf" | "image/jpeg" | "image/png" | "image/tiff";
139146

140147
// @public
141-
export type FormElement = FormWord | FormLine;
148+
export type FormElement = FormWord | FormLine | FormSelectionMark;
142149

143150
// @public
144151
export interface FormElementCommon {
145152
boundingBox: Point2D[];
146153
pageNumber: number;
147-
text: string;
154+
text?: string;
148155
}
149156

150157
// @public
@@ -177,6 +184,9 @@ export type FormField = {
177184
} | {
178185
value?: Record<string, FormField>;
179186
valueType?: "object";
187+
} | {
188+
value?: SelectionMarkState;
189+
valueType?: "selectionMark";
180190
});
181191

182192
// @public
@@ -188,6 +198,7 @@ export interface FormFieldsReport {
188198
// @public
189199
export interface FormLine extends FormElementCommon {
190200
kind: "line";
201+
text: string;
191202
words: FormWord[];
192203
}
193204

@@ -204,6 +215,7 @@ export interface FormPage {
204215
height: number;
205216
lines?: FormLine[];
206217
pageNumber: number;
218+
selectionMarks?: FormSelectionMark[];
207219
tables?: FormTable[];
208220
textAngle: number;
209221
unit: LengthUnit;
@@ -254,6 +266,13 @@ export interface FormRecognizerOperationOptions extends OperationOptions {
254266
// @public
255267
export type FormRecognizerRequestBody = Blob | ArrayBuffer | ArrayBufferView | NodeJS.ReadableStream;
256268

269+
// @public
270+
export interface FormSelectionMark extends FormElementCommon {
271+
confidence?: number;
272+
kind: "selectionMark";
273+
state: SelectionMarkState;
274+
}
275+
257276
// @public
258277
export interface FormTable {
259278
cells: FormTableCell[];
@@ -295,6 +314,7 @@ export class FormTrainingClient {
295314
export interface FormWord extends FormElementCommon {
296315
confidence?: number;
297316
kind: "word";
317+
text: string;
298318
}
299319

300320
// @public
@@ -401,6 +421,8 @@ export type RecognizeContentOptions = FormRecognizerOperationOptions;
401421
export interface RecognizedForm {
402422
fields: Record<string, FormField>;
403423
formType: string;
424+
formTypeConfidence?: number;
425+
modelId?: string;
404426
pageRange: FormPageRange;
405427
pages: FormPage[];
406428
}
@@ -424,9 +446,13 @@ export type RecognizeFormsOptions = FormRecognizerOperationOptions & {
424446

425447
export { RestResponse }
426448

449+
// @public
450+
export type SelectionMarkState = "selected" | "unselected" | string;
451+
427452
// @public
428453
export interface TrainingDocumentInfo {
429454
errors: FormRecognizerError[];
455+
modelId?: string;
430456
name: string;
431457
pageCount: number;
432458
status: TrainingStatus;
Binary file not shown.

sdk/formrecognizer/ai-form-recognizer/samples/javascript/recognizeContent.js

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,23 @@ const path = require("path");
1414
const dotenv = require("dotenv");
1515
dotenv.config();
1616

17+
/**
18+
* Make a string representing a bounding box.
19+
*/
20+
function boundingBoxToString(box) {
21+
let out = "[";
22+
for (const { x, y } of box) {
23+
out += `(${x}, ${y}),`;
24+
}
25+
// Remove the last comma and add the closing bracket
26+
return out.slice(0, -1) + "]";
27+
}
28+
1729
async function main() {
1830
// You will need to set these environment variables or edit the following values
1931
const endpoint = process.env["FORM_RECOGNIZER_ENDPOINT"] || "<cognitive services endpoint>";
2032
const apiKey = process.env["FORM_RECOGNIZER_API_KEY"] || "<api key>";
21-
const fileName = path.join(__dirname, "./assets/Form_1.jpg");
33+
const fileName = path.join(__dirname, "./assets/selection_mark_form.pdf");
2234

2335
if (!fs.existsSync(fileName)) {
2436
throw new Error(`Expecting file ${fileName} exists`);
@@ -35,14 +47,19 @@ async function main() {
3547
}
3648

3749
for (const page of pages) {
38-
console.log(
39-
`Page ${page.pageNumber}: width ${page.width} and height ${page.height} with unit ${page.unit}`
40-
);
41-
for (const table of page.tables) {
50+
console.log(`- Page number: ${page.pageNumber}`);
51+
console.log(" Tables:");
52+
for (const table of page.tables || []) {
53+
console.log(` - Table (${table.rowCount} x ${table.columnCount})`);
4254
for (const cell of table.cells) {
43-
console.log(`cell [${cell.rowIndex},${cell.columnIndex}] has text ${cell.text}`);
55+
console.log(` cell (${cell.rowIndex},${cell.columnIndex}) ${cell.text}`);
4456
}
4557
}
58+
console.log(" Selection Marks:");
59+
for (const mark of page.selectionMarks || []) {
60+
const box = boundingBoxToString(mark.boundingBox);
61+
console.log(` - ${mark.state} @${box} (${mark.confidence} confidence)`);
62+
}
4663
}
4764
}
4865

sdk/formrecognizer/ai-form-recognizer/samples/javascript/recognizeCustomForm.js

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,18 @@ const path = require("path");
1717
const dotenv = require("dotenv");
1818
dotenv.config();
1919

20+
/**
21+
* Make a string representing a bounding box.
22+
*/
23+
function boundingBoxToString(box) {
24+
let out = "[";
25+
for (const { x, y } of box) {
26+
out += `(${x}, ${y}),`;
27+
}
28+
// Remove the last comma and add the closing bracket
29+
return out.slice(0, -1) + "]";
30+
}
31+
2032
async function main() {
2133
// You will need to set these environment variables or edit the following values
2234
const endpoint = process.env["FORM_RECOGNIZER_ENDPOINT"] || "<cognitive services endpoint>";
@@ -42,23 +54,29 @@ async function main() {
4254

4355
console.log("Forms:");
4456
for (const form of forms || []) {
45-
console.log(`${form.formType}, page range: ${form.pageRange}`);
46-
console.log("Pages:");
57+
console.log(`- ${form.formType}, page range: ${form.pageRange}`);
58+
console.log(" Pages:");
4759
for (const page of form.pages || []) {
48-
console.log(`Page number: ${page.pageNumber}`);
49-
console.log("Tables");
60+
console.log(` - Page number: ${page.pageNumber}`);
61+
console.log(" Tables:");
5062
for (const table of page.tables || []) {
63+
console.log(` - (${table.rowCount} x ${table.columnCount}`);
5164
for (const cell of table.cells) {
52-
console.log(`cell (${cell.rowIndex},${cell.columnIndex}) ${cell.text}`);
65+
console.log(` cell (${cell.rowIndex},${cell.columnIndex}) ${cell.text}`);
5366
}
5467
}
68+
console.log(" Selection Marks:");
69+
for (const mark of page.selectionMarks || []) {
70+
const box = boundingBoxToString(mark.boundingBox);
71+
console.log(` - ${mark.state} @(${box}) (${mark.confidence} confidence)`);
72+
}
5573
}
5674

57-
console.log("Fields:");
75+
console.log(" Fields:");
5876
for (const [fieldName, field] of Object.entries(form.fields)) {
5977
// each field is of type FormField
6078
console.log(
61-
`Field '${fieldName}' has value '${field.value}' with a confidence score of ${field.confidence}`
79+
` - Field '${fieldName}' has value '${field.value}' with a confidence score of ${field.confidence}`
6280
);
6381
}
6482
}

0 commit comments

Comments
 (0)