استخدام مجموعات تطوير البرامج (SDK) للتعرف على النماذج أو واجهة برمجة تطبيقات REST

في هذا الدليل الإرشادي، ستتعرف على كيفية إضافة أداة التعرف على النماذج إلى تطبيقاتك وسير عملك باستخدام SDK أو بلغة برمجة من اختيارك أو واجهة برمجة تطبيقات REST. Azure Form Recognizer هي خدمة Azure Applied الذكاء الاصطناعي المستندة إلى مجموعة النظراء والتي تستخدم التعلم الآلي لاستخراج أزواج القيم الرئيسية والنصوص والجداول من مستنداتك. نوصي باستخدام الخدمة المجانية عندما تعرف التقنية. تذكر أن عدد الصفحات المجانية يقتصر على 500 صفحة في الشهر.

ستستخدم واجهات برمجة التطبيقات التالية لاستخراج البيانات المنظمة من النماذج والمستندات:

هام

  • يستهدف هذا المشروع واجهة برمجة تطبيقات REST للتعرف على النموذج الإصدار 2.1.

  • تستخدم التعليمات البرمجية في هذه المقالة أساليب متزامنة وتخزين بيانات الاعتماد غير المؤمنة من أجل التبسيط.

الوثائق المرجعية | التعليمات البرمجية لمصدر المكتبة | حزمة (NuGet) | نماذج

المتطلبات الأساسية

  • اشتراك Azure - إنشاء اشتراك مجانًا
  • Visual Studio IDE أو الإصدار الحالي من .NET Core.
  • كائن التخزين الثنائي كبير الحجم من Azure الذي يحتوي على مجموعة من بيانات التدريب. راجع إنشاء مجموعة بيانات تدريب لنموذج مخصص للحصول على نصائح وخيارات لتجميع مجموعة بيانات التدريب. بالنسبة لهذا المشروع ، يمكنك استخدام الملفات الموجودة ضمن مجلد Train منمجموعة بيانات العينة (تنزيل sample_data.zipواستخراجه ).
  • بمجرد حصولك على اشتراكك في Azure، قم بإنشاء مورد التعرف على النموذج في مدخل Azure للحصول على المفتاح ونقطة النهاية. بعد انتشاره، حدد Go to resource.
    • ستحتاج إلى المفتاح ونقطة النهاية من المورد الذي تنشئه؛ لتوصيل التطبيق الخاص بك بواجهة برمجة تطبيقات Form Recognizer. الصق المفتاح ونقطة النهاية في التعليمات البرمجية أدناه لاحقا في المشروع.
    • يمكنك استخدام مستوى التسعير الحر (F0) لتجربة الخدمة، والترقية لاحقًا إلى مستوى مدفوع للإنتاج.

الإعداد

في نافذة وحدة تحكم (مثل cmd أو PowerShell أو Bash)، استخدم الأمر ⁧dotnet new⁩ لإنشاء تطبيق وحدة تحكم جديد بالاسم ⁧formrecognizer-project⁩. ينشئ هذا الأمر مشروع "مرحبًا بالعالم" بلغة C# بسيط مع ملف مصدر واحد: ⁧⁧⁩⁩program.cs⁧⁧⁩⁩.

dotnet new console -n formrecognizer-project

غيّر دليلك إلى مجلد التطبيق المنشأ حديثًا. يمكنك إنشاء التطبيق باستخدام:

dotnet build

يجب ألا يحتوي إخراج البناء على تحذيرات أو أخطاء.

...
Build succeeded.
 0 Warning(s)
 0 Error(s)
...

تثبيت مكتبة العميل

ثبّت مكتبة عميل Form Recognizer لـ .NET داخل دليل التطبيق باستخدام الأمر التالي:

dotnet add package Azure.AI.FormRecognizer --version 3.1.1

من دليل المشروع، افتح الملف ⁧⁧Program.cs في المحرر المفضل لديك أو IDE. أضِف توجيهات 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;

في فئة برنامج التطبيق، أنشئ متغيرات لمفتاح المورد ونقطة النهاية.

هام

انتقل إلى مدخل Azure. إذا تم نشر مورد Form Recognizer الذي أنشأته في قسم المتطلبات الأساسية بنجاح، فانقر فوق الزر Go to Resource ضمن Next Steps. يمكنك العثور على مفتاحك ونقطة النهاية في صفحة مفتاح المورد ونقطة النهاية ضمن إدارة الموارد.

تذكر إزالة المفتاح من التعليمات البرمجية عند الانتهاء، وعدم نشره على الملأ مطلقًا. بالنسبة إلى الإنتاج، استخدم أساليب آمنة لتخزين بيانات اعتمادك والوصول إليها. قم بتشكيل مزيد من المعلومات، راجع مقالة أمان الخدمات المعرفية.

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);

في الطريقة الرئيسية للتطبيق، أضف استدعاء إلى المهام غير المتزامنة المستخدمة في هذا المشروع. سوف تنفذ ذلك لاحقًا:

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);

}

نموذج الكائن

باستخدام Form Recognizer، يمكنك إنشاء نوعين مختلفين من العملاء. الأول، يُستخدَم FormRecognizerClient للاستعلام عن الخدمة إلى المحتوى وحقول النموذج الذي تم التعرف عليها. والثاني، يُستخدَم FormTrainingClient لإنشاء نماذج مخصصة وإدارتها لتحسين التعرف.

FormRecognizerClient

يوفر FormRecognizerClient عمليات من أجل:

  • التعرف على حقول النموذج والمحتوى، باستخدام نماذج مخصصة مدرَّبة لتحليل نماذجك المخصصة. يتم إرجاع هذه القيم في مجموعة كائنات RecognizedForm. يُرجى مراجعة تحليل النماذج المخصصة.
  • التعرف على محتوى النموذج، بما في ذلك الجداول والأسطر والكلمات، دون الحاجة إلى التدريب على نموذج. يتم إرجاع محتوى النموذج هذا في مجموعة كائنات FormPage. يُرجى مراجعة مثال تحليل التخطيط.
  • التعرف على الحقول الشائعة من إيصالات الولايات المتحدة وبطاقات العمل والفواتير ومستندات الهوية باستخدام نموذج مدرب مسبقًا على خدمة Form Recognizer.

FormTrainingClient

يوفر FormTrainingClient عمليات من أجل:

  • التدريب على النماذج المخصصة لتحليل كافة الحقول والقيم الموجودة في النماذج المخصصة. يتم إرجاع CustomFormModel للإشارة إلى أنواع النموذج التي سيحللها النموذج، والحقول التي سيستخرجها لكل نوع نموذج.
  • التدريب على النماذج المخصصة لتحليل حقول وقيم محددة تحددها عن طريق تسمية النماذج المخصصة. يتم إرجاع A CustomFormModel مع الإشارة إلى الحقول التي سيستخرجها النموذج، والدقة المقدرة لكل حقل.
  • إدارة النماذج التي تم إنشاؤها في حسابك.
  • نسخ طراز مخصص من مورد Form Recognizer إلى مورد آخر.

ارجع لأمثلة عن التدريب على نموذج وإدارة النماذج المخصصة.

ملاحظة

يمكن أيضاً التدريب على النماذج باستخدام واجهة مستخدم رسومية مثل أداة تسمية Form Recognizer.

مصادقة العميل

في أسفل القائمة الأساسية، أنشئ طريقة جديدة باسم AuthenticateClient. ستستخدم هذه الطريقة في مهام أخرى لمصادقة طلباتك إلى خدمة أداة التعرف على النماذج. تستخدم هذه الطريقة الكائن AzureKeyCredential ، بحيث يمكنك تحديث المفتاح دون إنشاء كائنات عميل جديدة إذا لزم الأمر.

هام

احصل على المفتاح ونقطة النهاية من مدخل Microsoft Azure. إذا تم نشر مورد Form Recognizer الذي أنشأته في قسم المتطلبات الأساسية بنجاح، فانقر فوق الزر Go to Resource ضمن Next Steps. يمكنك العثور على مفتاحك ونقطة النهاية في صفحة مفتاح المورد ونقطة النهاية ضمن إدارة الموارد.

تذكر إزالة المفتاح من التعليمات البرمجية عند الانتهاء، وعدم نشره على الملأ مطلقًا. بالنسبة إلى الإنتاج، استخدم أساليب آمنة لتخزين بيانات اعتمادك والوصول إليها. مثل Azure Key Vault.

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 لبيانات التدريب والاختبار الخاصة بك. أضف هذه المراجع إلى جذر فئة البرنامج .

  • لاسترداد عنوان URL الخاص بـ SAS لبيانات تدريب النموذج المخصص، انتقل إلى مورد التخزين في مدخل Microsoft Azure وحدد علامة التبويب Storage Explorer. انتقل إلى الحاوية الخاصة بك، وانقر بزر الماوس الأيمن، وحدد Get shared access signature. من المهم الحصول على SAS لحاويتك، وليس لحساب التخزين نفسه. تأكد من اختيار الأذونات Read وWrite وDelete وList، ثم انقر فوق Create. ثم انسخ القيمة الموجودة في قسم URL إلى موقع مؤقت. يجب أن يكون بالشكل: https://<storage account>.blob.core.windows.net/<container name>?<SAS value>.

    SAS URL retrieval

  • ثم كرر الخطوات المذكورة أعلاه للحصول على عنوان 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";

تحليل التخطيط

يمكنك استخدام Form Recognizer لتحليل الجداول، والأسطر، والكلمات في المستندات، دون الحاجة إلى التدريب على نموذج. القيمة التي تم إرجاعها هي مجموعة من كائنات FormPage: واحد لكل صفحة في المستند المُرسل. لمزيدٍ من المعلومات حول استخراج التخطيط، راجع الدليل التصوري للتخطيط.

لتحليل محتوى ملف في URI معين، استخدم طريقة 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'.

تحليل الإيصالات

يوضح هذا القسم كيفية تحليل واستخراج الحقول الشائعة من الإيصالات الأمريكية باستخدام نموذج إيصال مدرب مسبقًا. لمزيدٍ من المعلومات حول تحليل الإيصالات، راجع الدليل المفاهيمي للإيصالات.

لتحليل الإيصالات من عنوان 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'

تحليل بطاقات العمل

يوضح هذا القسم كيفية تحليل واستخراج حقول مشتركة من بطاقات العمل باللغة الإنجليزية، باستخدام نموذج مدرَّب مسبقًا. للحصول على مزيد من المعلومات حول تحليل بطاقة العمل، راجع الدليل التصوري لبطاقات العمل.

لتحليل بطاقات العمل من عنوان 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}");
          }
        }
      }
    }
  }
}

تحليل الفواتير

يوضح هذا القسم كيفية تحليل واستخراج حقول مشتركة من فواتير المبيعات، باستخدام نموذج مدرَّب مسبقًا. للحصول على المزيد من المعلومات حول تحليل الفواتير، راجع الدليل التصوري للفواتير.

لتحليل الفواتير من عنوان 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}");
    }
  }
}

تحليل مستندات معرف

يوضح هذا القسم كيفية تحليل واستخراج المعلومات الأساسية من مستندات الهوية الصادرة عن الحكومة - جوازات السفر العالمية ورخص القيادة الأمريكية - باستخدام نموذج المعرف المسبق لـ Form Recognizer. لمزيدٍ من المعلومات حول تحليل مستند المعرف، راجع دليلنا المفاهيمي لنموذج التعريف الذي تم إنشاؤه مسبقاً.

لتحليل مستندات الهوية من عنوان 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:
    ...

تدريب نموذج باستخدام تسميات

يمكنك أيضًا تدريب نماذج مخصصة عن طريق وضع التسميات يدويًا على مستندات التدريب. يؤدي التدريب باستخدام التسميات إلى أداء أفضل في بعض السيناريوهات. للتدريب باستخدام التسميات، تحتاج إلى ملفات معلومات التسمية الخاصة (\<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

تتحقق كتلة التعليمات البرمجية التالية من عدد النماذج التي حفظتها في حسابك على Form Recognizer ويقارنه بالحد الأقصى للحساب.

// 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

تنظيف الموارد

إذا كنت تريد تنظيف وإلغاء اشتراك الخدمات المعرفية، يمكنك حذف المورد أو مجموعة الموارد. يؤدي حذف مجموعة الموارد إلى حذف أية موارد أخرى مقترنة بها أيضًا.

استكشاف الأخطاء وإصلاحها

عندما تتعامل مع مكتبة العميل Form Recognizer للخدمات المعرفية باستخدام .NET SDK، ستسبب الأخطاء التي ترجعها الخدمة إلى إنتاج RequestFailedException. وستتضمن نفس رمز حالة HTTP الذي كان من الممكن أن يتم إرجاعه من قِبل طلب واجهة برمجة تطبيقات REST.

على سبيل المثال، إذا أرسلت صورة إيصال بعنوان URI غير صالح، فسيتم إرجاع الخطأ 400 الذي يشير إلى «طلب غير صالح».

try
{
    RecognizedReceiptCollection receipts = await client.StartRecognizeReceiptsFromUri(new Uri(receiptUri)).WaitForCompletionAsync();
}
catch (RequestFailedException e)
{
    Console.WriteLine(e.ToString());
}

وستلاحظ تسجيل معلومات إضافية، مثل معرّف طلب العميل للعملية.


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

الخطوات التالية

بالنسبة لهذا المشروع، قمت باستخدام مكتبة عميل .NET التعرف على النماذج لتدريب النماذج وتحليل النماذج بطرق مختلفة. يمكنك أيضاً، التعرف على نصائح لإنشاء مجموعة بيانات تدريب أفضل وإنتاج نماذج أكثر دقة.

هام

  • يستهدف هذا المشروع الإصدار 2.1 من واجهة برمجة تطبيقات REST للتعرف على النموذج.

الوثائق المرجعية | التعليمة البرمجية للمصادر المكتبية | نماذج حزمة | (Maven)

المتطلبات الأساسية

الإعداد

بادر بإنشاء مشروع Gradle جديد

في نافذة وحدة التحكم (مثل cmd أو PowerShell أو Bash)، أنشئ دليلاً جديداً لتطبيقك وانتقل إليه.

mkdir myapp && cd myapp

بادر بتشغيل الأمر gradle init من دليل العمل خاصتك. سينشئ هذا الأمر ملفات بناء أساسية لـ Gradle، بما في ذلك build.gradle.kts، والذي يجري استخدامه في وقت التشغيل لإنشاء تطبيقك وتكوينه.

gradle init --type basic

عند مطالبتك باختيار DSL، حدِّد Kotlin.

تثبيت مكتبة العميل

يستخدم هذا المشروع مدير تبعية Gradle. يمكنك العثور على مكتبة العميل ومعلومات مديري التبعية الآخرين على Maven Central Repository.

في ملف 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. افتَحه في المحرر المفضل لديك أو بيئة التطوير المتكاملة وأضِف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. إذا تم نشر مورد Form Recognizer الذي أنشأته في قسم المتطلبات الأساسية بنجاح، فانقر فوق الزر Go to Resource ضمن Next Steps. يمكنك العثور على مفتاحك ونقطة النهاية في صفحة مفتاح المورد ونقطة النهاية ضمن إدارة الموارد.

تذكر إزالة المفتاح من التعليمات البرمجية عند الانتهاء، وعدم نشره على الملأ مطلقًا. بالنسبة إلى الإنتاج، استخدم أساليب آمنة لتخزين بيانات اعتمادك والوصول إليها. لمزيد من المعلومات، راجعأمان الخدمات المعرفية.

في الطريقة الرئيسية للتطبيق، أضف استدعاءات للطرق المستخدمة في هذا المشروع. ستحدد هذه المكالمات لاحقا. ستحتاج أيضاً إلى إضافة مراجع إلى عناوين URL لبيانات التدريب والاختبار الخاصة بك.

  • لاسترداد عنوان URL الخاص بـ SAS لبيانات تدريب النموذج المخصص، انتقل إلى مورد التخزين في مدخل Microsoft Azure وحدد علامة التبويب Storage Explorer. انتقل إلى الحاوية الخاصة بك، وانقر بزر الماوس الأيمن، وحدد Get shared access signature. من المهم الحصول على SAS لحاويتك، وليس لحساب التخزين نفسه. تأكد من اختيار الأذونات Read وWrite وDelete وList، ثم انقر فوق Create. ثم انسخ القيمة الموجودة في قسم URL إلى موقع مؤقت. يجب أن يكون بالشكل: https://<storage account>.blob.core.windows.net/<container name>?<SAS value>.

    SAS URL retrieval

  • للحصول على عنوان URL الخاص بنموذج لاختبار، يمكنك استخدام الخطوات أعلاه للحصول على URL SAS لمستند أحادي في تخزين الكائنات الثنائية كبيرة الحجم. أو، خذ عنوان 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);

نموذج الكائن

باستخدام Form Recognizer، يمكنك إنشاء نوعين مختلفين من العملاء. الأول، يُستخدَم FormRecognizerClient للاستعلام عن الخدمة إلى المحتوى وحقول النموذج الذي تم التعرف عليها. والثاني، يُستخدَم FormTrainingClient لإنشاء نماذج مخصصة وإدارتها لتحسين التعرف.

FormRecognizerClient

يوفر FormRecognizerClient عمليات من أجل:

  • التعرف على حقول النموذج والمحتوى، باستخدام نماذج مخصصة مدرَّبة لتحليل نماذجك المخصصة. يتم إرجاع هذه القيم في مجموعة كائنات RecognizedForm. يُرجى مراجعة تحليل النماذج المخصصة.
  • التعرف على محتوى النموذج، بما في ذلك الجداول والأسطر والكلمات، دون الحاجة إلى التدريب على نموذج. يتم إرجاع محتوى النموذج هذا في مجموعة كائنات FormPage. يُرجى مراجعة مثال تحليل التخطيط.
  • التعرف على الحقول الشائعة من إيصالات الولايات المتحدة وبطاقات العمل والفواتير ومستندات الهوية باستخدام نموذج مدرب مسبقًا على خدمة Form Recognizer.

FormTrainingClient

يوفر FormTrainingClient عمليات من أجل:

  • التدريب على النماذج المخصصة لتحليل كافة الحقول والقيم الموجودة في النماذج المخصصة. يتم إرجاع CustomFormModel للإشارة إلى أنواع النموذج التي سيحللها النموذج، والحقول التي سيستخرجها لكل نوع نموذج.
  • التدريب على النماذج المخصصة لتحليل حقول وقيم محددة تحددها عن طريق تسمية النماذج المخصصة. يتم إرجاع A CustomFormModel مع الإشارة إلى الحقول التي سيستخرجها النموذج والدقة المقدرة لكل حقل.
  • إدارة النماذج التي تم إنشاؤها في حسابك.
  • نسخ طراز مخصص من مورد Form Recognizer إلى مورد آخر.

ملاحظة

يمكن أيضاً التدريب على النماذج باستخدام واجهة مستخدم رسومية مثل أداة تسمية Form Recognizer.

مصادقة العميل

أضف التعليمة البرمجية التالية أعلى الأسلوب الرئيسي⁩ الخاص بك. تقوم هنا، بمصادقة كائنات لاثنين من العملاء باستخدام متغيرات الاشتراك التي حددتها أعلاه. ستستخدم كائن AzureKeyCredential ، بحيث يمكنك تحديث المفتاح إذا لزم الأمر دون إنشاء كائنات عميل جديدة.

FormRecognizerClient recognizerClient = new FormRecognizerClientBuilder()
        .credential(new AzureKeyCredential(key)).endpoint(endpoint).buildClient();

FormTrainingClient trainingClient = new FormTrainingClientBuilder().credential(new AzureKeyCredential(key))
        .endpoint(endpoint).buildClient();

تحليل التخطيط

يمكنك استخدام Form Recognizer لتحليل الجداول والأسطر والكلمات في المستندات، دون الحاجة إلى التدريب على نموذج. لمزيدٍ من المعلومات حول استخراج التخطيط، راجع الدليل التصوري للتخطيط.

لتحليل محتوى ملف في محدد موقع 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 لمعرفة السيناريوهات التي تتضمن صوراً محلية.

القيمة التي تم إرجاعها هي مجموعة من كائنات صفحة نموذج: واحد لكل صفحة في المستند المُقدم. تتكرر التعليمات البرمجية التالية خلال هذه الكائنات كذا طباعة أزواج المفتاح/القيم المستخرجة وبيانات الجدول.

    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.

تحليل الإيصالات

يوضح هذا القسم كيفية تحليل واستخراج الحقول الشائعة من الإيصالات الأمريكية باستخدام نموذج إيصال مدرب مسبقًا. لمزيدٍ من المعلومات حول تحليل الإيصالات، راجع الدليل المفاهيمي للإيصالات.

لتحليل الإيصالات من 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

تحليل بطاقات العمل

يوضح هذا القسم كيفية تحليل واستخراج حقول مشتركة من بطاقات العمل باللغة الإنجليزية، باستخدام نموذج مدرَّب مسبقًا. للحصول على مزيد من المعلومات حول تحليل بطاقة العمل، راجع الدليل التصوري لبطاقات العمل.

لتحليل بطاقات العمل من عنوان 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());
                    }
                });
            }
        }
    }
}

تحليل الفواتير

يوضح هذا القسم كيفية تحليل واستخراج حقول مشتركة من فواتير المبيعات، باستخدام نموذج مدرَّب مسبقًا. للحصول على المزيد من المعلومات حول تحليل الفواتير، راجع الدليل التصوري للفواتير.

لتحليل الفواتير من عنوان 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());
            }
        }
    }
}

تحليل مستندات معرف

يوضح هذا القسم كيفية تحليل واستخراج المعلومات الأساسية من مستندات الهوية الصادرة عن الحكومة - جوازات السفر العالمية ورخص القيادة الأمريكية - باستخدام نموذج المعرف المسبق لـ Form Recognizer. لمزيدٍ من المعلومات حول تحليل مستند المعرف، راجع دليلنا المفاهيمي لنموذج التعريف الذي تم إنشاؤه مسبقاً.

لتحليل مستندات الهوية من عنوان 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

تدريب نموذج باستخدام تسميات

يمكنك أيضًا تدريب نماذج مخصصة عن طريق وضع التسميات يدويًا على مستندات التدريب. يؤدي التدريب باستخدام التسميات إلى أداء أفضل في بعض السيناريوهات. للتدريب على التسميات ، يجب أن يكون لديك ملفات معلومات تسمية خاصة (<اسم> الملف.pdf.labels.json) في حاوية تخزين blob إلى جانب مستندات التدريب. توفر أداة تسمية نموذج التعرف على النموذج واجهة مستخدم لمساعدتك في إنشاء ملفات التسميات هذه. بمجرد حصولك عليهم، يمكنك استدعاء أسلوب 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

تتحقق كتلة التعليمات البرمجية التالية من عدد النماذج التي حفظتها في حسابك على Form Recognizer ويقارنه بالحد الأقصى للحساب.

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

تنظيف الموارد

إذا كنت تريد تنظيف وإلغاء اشتراك الخدمات المعرفية، يمكنك حذف المورد أو مجموعة الموارد. يؤدي حذف مجموعة الموارد إلى حذف أية موارد أخرى مقترنة بها أيضًا.

استكشاف الأخطاء وإصلاحها

يقوم عملاء التعرف على النموذج برفع ErrorResponseException الاستثناءات. مثلاً، إذا حاولت توفير عنوان URL لمصدر ملف غير صالح ErrorResponseException قد يظهر مع خطأ يشير إلى سبب الفشل. في التعليمات البرمجية المتكررة التالية، تتم معالجة الخطأ على نحو آمن من خلال معرفة الاستثناء وعرض معلومات إضافية حول الخطأ.

try {
    formRecognizerClient.beginRecognizeContentFromUrl("invalidSourceUrl");
} catch (ErrorResponseException e) {
    System.out.println(e.getMessage());
}

تمكين تسجيل دخول العميل

تقدم حزمة أدوات تطوير البرمجيات لـJava قصة تسجيل متسقة للمساعدة في استكشاف أخطاء التطبيق وإصلاحها وتسريع دقتها. تتعرف السجلات المُنتجة على تدفق أحد التطبيقات قبل الوصول إلى حالة الوحدة الطرفية للمساعدة في تحديد موقع المشكلة الأساسي. عرض ويكي التسجيل للحصول على إرشادات حول تمكين تسجيل الدخول.

الخطوات التالية

بالنسبة لهذا المشروع، استخدمت مكتبة عميل Java للتعرف على النماذج لتدريب النماذج وتحليل النماذج بطرق مختلفة. يمكنك أيضاً، التعرف على نصائح لإنشاء مجموعة بيانات تدريب أفضل وإنتاج نماذج أكثر دقة.

هام

يستهدف هذا المشروع الإصدار 2.1 من واجهة برمجة تطبيقات REST للتعرف على النموذج.

الوثائق المرجعية | التعليمات البرمجية لمصدر المكتبة | الحزمة (npm) | العينات

المتطلبات الأساسية

  • اشتراك Azure - إنشاء اشتراك مجاناً
  • الإصدار الحالي من Node.js
  • كائن التخزين الثنائي كبير الحجم لـ Azure الذي يحتوي على مجموعة من بيانات التدريب. راجع إنشاء مجموعة بيانات تدريب لنموذج مخصص للحصول على نصائح وخيارات لتجميع مجموعة بيانات التدريب. بالنسبة لهذا المشروع ، يمكنك استخدام الملفات الموجودة ضمن مجلد Train منمجموعة بيانات العينة (تنزيل sample_data.zipواستخراجه ).
  • بمجرد حصولك على اشتراكك في Azure، قم بإنشاء مورد التعرف على النموذج في مدخل Azure للحصول على المفتاح ونقطة النهاية. بعد انتشاره، حدد Go to resource.
    • ستحتاج إلى المفتاح ونقطة النهاية من المورد الذي تنشئه؛ لتوصيل التطبيق الخاص بك بواجهة برمجة تطبيقات Form Recognizer. ستقوم بلصق مفتاحك ونقطة النهاية في الرمز أدناه لاحقا في المشروع
    • يمكنك استخدام مستوى التسعير الحر (F0) لتجربة الخدمة، والترقية لاحقًا إلى مستوى مدفوع للإنتاج.

الإعداد

إنشاء تطبيق Node.js جديد

في نافذة وحدة التحكم (مثل cmd، أو PowerShell، أو Bash)، أنشئ دليلاً جديدًا لتطبيقك، وانتقل إليه.

mkdir myapp && cd myapp

شغل npm initالأمر لإنشاء تطبيق node باستخدام ملف 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. إذا تم نشر مورد Form Recognizer الذي أنشأته في قسم المتطلبات الأساسية بنجاح، فانقر فوق الزر Go to Resource ضمن Next Steps. يمكنك العثور على مفتاحك ونقطة النهاية في صفحة مفتاح المورد ونقطة النهاية ضمن إدارة الموارد.

تذكر إزالة المفتاح من التعليمات البرمجية عند الانتهاء، وعدم نشره على الملأ مطلقًا. بالنسبة إلى الإنتاج، استخدم أساليب آمنة لتخزين بيانات اعتمادك والوصول إليها. لمزيد من المعلومات، راجع مقالة أمان الخدمات المعرفية.

طراز الكائن

باستخدام Form Recognizer، يمكنك إنشاء نوعين مختلفين من العملاء. الأول، يستخدم FormRecognizerClient للاستعلام عن الخدمة إلى حقول النموذج والمحتوى الذي تم التعرف عليه. والثاني، يستخدم FormTrainingClient لإنشاء وإدارة نماذج مخصصة لتحسين التعرف.

FormRecognizerClient

FormRecognizerClientيوفر عمليات لـ:

  • التعرف على حقول النموذج والمحتوى باستخدام نماذج مخصصة مدربة لتحليل نماذجك المخصصة. يتم إرجاع هذه القيم في مجموعة من RecognizedForm كائن.
  • التعرف على محتوى النموذج، بما في ذلك الجداول والأسطر والكلمات، دون الحاجة إلى التدريب على نموذج. يتم إرجاع محتوى النموذج هذا في مجموعة كائنات FormPage.
  • التعرف على المجالات الشائعة سواء في إيصالات الولايات المتحدة وبطاقات العمل والفواتير ومستندات الهوية باستخدام نموذج مدرب مسبقاً على خدمة "التعرف على النموذج".

FormTrainingClient

يوفر FormTrainingClient عمليات من أجل:

  • التدريب على النماذج المخصصة لتحليل كافة الحقول والقيم الموجودة في النماذج المخصصة. يتم إرجاع CustomFormModel للإشارة إلى أنواع النموذج التي سيحللها النموذج، والحقول التي سيستخرجها لكل نوع نموذج. لمزيد من المعلومات، راجعوثائق الخدمة حول التدريب على النماذج غير المصنفة.
  • التدريب على النماذج المخصصة لتحليل حقول وقيم محددة تحددها عن طريق تسمية النماذج المخصصة. يتم إرجاع A CustomFormModel مع الإشارة إلى الحقول التي سيستخرجها النموذج، والدقة المقدرة لكل حقل. راجع وثائق الخدمة الخاصة بتدريب النموذج المسمى للحصول على شرح أكثر تفصيلاً لتطبيق الملصقات على مجموعة بيانات التدريب.
  • إدارة النماذج التي تم إنشاؤها في حسابك.
  • نسخ طراز مخصص من مورد Form Recognizer إلى مورد آخر.

ملاحظة

يمكن أيضاً التدريب على النماذج باستخدام واجهة مستخدم رسومية مثل أداة تسمية Form Recognizer.

مصادقة العميل

قم بمصادقة كائن عميل باستخدام متغيرات الاشتراك التي حددتها. ستستخدم كائنا AzureKeyCredential ، بحيث يمكنك تحديث المفتاح إذا لزم الأمر دون إنشاء كائنات عميل جديدة. كما يمكنك إنشاء كائن عميل تدريب.

const trainingClient = new FormTrainingClient(endpoint, new AzureKeyCredential(apiKey));
const client = new FormRecognizerClient(endpoint, new AzureKeyCredential(apiKey));

الحصول على أصول للاختبار

ستحتاج أيضًا إلى إضافة مراجع إلى عناوين URL لبيانات التدريب والاختبار الخاصة بك.

  • لاسترداد عنوان URL الخاص بـ SAS لبيانات تدريب النموذج المخصص، انتقل إلى مورد التخزين في مدخل Microsoft Azure وحدد علامة التبويب Storage Explorer. انتقل إلى الحاوية الخاصة بك، وانقر بزر الماوس الأيمن، وحدد Get shared access signature. من المهم الحصول على SAS لحاويتك، وليس لحساب التخزين نفسه. تأكد من اختيار الأذونات Read وWrite وDelete وList، ثم انقر فوق Create. ثم انسخ القيمة الموجودة في قسم URL إلى موقع مؤقت. يجب أن يكون بالشكل: https://<storage account>.blob.core.windows.net/<container name>?<SAS value>.

    SAS URL retrieval

  • استخدم عينة من صور الإيصالات المضمنة في العينات أدناه (متوفرة أيضاً على GitHub) أو يمكنك استخدام الخطوات المذكورة أعلاه للحصول على عنوان URL لـ SAS لمستند فردي في مساحة تخزين blob.

تحليل التخطيط

يمكنك استخدام Form Recognizer لتحليل الجداول والأسطر والكلمات في المستندات، دون الحاجة إلى التدريب على نموذج. لمزيدٍ من المعلومات حول استخراج التخطيط، راجع الدليل التصوري للتخطيط. لتحليل محتوى ملف في 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

تحليل الإيصالات

يوضح هذا القسم كيفية تحليل واستخراج الحقول الشائعة من الإيصالات الأمريكية باستخدام نموذج إيصال مدرب مسبقًا. لمزيدٍ من المعلومات حول تحليل الإيصالات، راجع الدليل المفاهيمي للإيصالات.

لتحليل الإيصالات من 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

تحليل بطاقات العمل

يوضح هذا القسم كيفية تحليل واستخراج الحقول المشتركة من بطاقات العمل باللغة الإنجليزية باستخدام طراز مدرب مسبقاً. لمزيدٍ من المعلومات حول تحليل بطاقة العمل، راجع الدليل المفاهيمي لبطاقات العمل.

لتحليل بطاقات العمل من عنوان 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.

تحليل الفواتير

يوضح هذا القسم كيفية تحليل واستخراج حقول مشتركة من فواتير المبيعات، باستخدام نموذج مدرَّب مسبقًا. للحصول على المزيد من المعلومات حول تحليل الفواتير، راجع الدليل التصوري للفواتير.

لتحليل الفواتير من عنوان 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.

تحليل مستندات المعرف

يوضح هذا القسم كيفية تحليل واستخراج المعلومات الأساسية من مستندات الهوية الصادرة عن الحكومة - جوازات السفر العالمية ورخص القيادة الأمريكية - باستخدام نموذج المعرف المسبق لـ Form Recognizer. لمزيدٍ من المعلومات حول تحليل مستند المعرف، راجع دليلنا المفاهيمي لنموذج التعريف الذي تم إنشاؤه مسبقاً.

لتحليل مستندات الهوية من عنوان 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) مثل أداة وضع العلامات النموذجية للتعرف على النماذج.

تدريب نموذج بدون تسميات

التدريب على النماذج المخصصة لتحليل جميع الحقول والقيم الموجودة في النماذج المخصصة لك دون تسمية مستندات التدريب يدوياً.

تقوم الدالة التالية بتدريب نموذج على مجموعة معينة من المستندات وتطبع حالة النموذج إلى وحدة التحكم.

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:
...

التدريب على نموذج باستخدام تسميات

يمكنك أيضًا تدريب نماذج مخصصة عن طريق وضع التسميات يدويًا على مستندات التدريب. يؤدي التدريب باستخدام التسميات إلى أداء أفضل في بعض السيناريوهات. للتدريب باستخدام التسميات، تحتاج إلى ملفات معلومات التسمية الخاصة (\<filename\>.pdf.labels.json) في حاوية مخزن البيانات الثنائية الكبيرة إلى جانب وثائق التدريب. توفر أداة تسمية نموذج التعرف على النموذج واجهة مستخدم لمساعدتك في إنشاء ملفات التسميات هذه. بمجرد الحصول عليها، يمكنك استدعاء 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

تنظيف الموارد

إذا كنت تريد تنظيف وإلغاء اشتراك الخدمات المعرفية، يمكنك حذف المورد أو مجموعة الموارد. يؤدي حذف مجموعة الموارد إلى حذف أية موارد أخرى مقترنة بها أيضًا.

استكشاف الأخطاء وإصلاحها

تمكين السجلات

يمكنك تعيين متغير البيئة التالية لمشاهدة سجلات التصحيح عند استخدام هذه المكتبة.

export DEBUG=azure*

للحصول على إرشادات أكثر تفصيلا حول كيفية تمكين السجلات، راجع مستندات حزمة @azure/المسجل.

الخطوات التالية

بالنسبة لهذا المشروع، استخدمت مكتبة عميل جافا سكريبت التعرف على النماذج لتدريب النماذج وتحليل النماذج بطرق مختلفة. يمكنك أيضاً، التعرف على نصائح لإنشاء مجموعة بيانات تدريب أفضل وإنتاج نماذج أكثر دقة.

راجع أيضًا

  • ما هي Form Recognizer؟

  • يمكن العثور على نموذج التعليمات البرمجية من هذا المشروع على GitHub.

  • يمكن العثور على نموذج التعليمات البرمجية من هذا الدليل على GitHub.

هام

  • يستهدف هذا المشروع الإصدار 2.1 من واجهة برمجة تطبيقات REST للتعرف على النموذج.

الوثائق المرجعية | كود مصدر المكتبة | حزمة (PyPi) | عينات

المتطلبات الأساسية

  • اشتراك Azure - إنشاء اشتراك مجانًا
  • ⁩Python 3.x⁧
    • يجب أن يتضمن تثبيت Python خاصتك pip. يمكنك التحقق مما إذا كانت لديك نقطة مثبتة عن طريق تشغيل pip --version على سطر الأوامر. الحصول على pip عن طريق تثبيت أحدث إصدار من Python.
  • كائن التخزين الثنائي كبير الحجم لـ Azure الذي يحتوي على مجموعة من بيانات التدريب. راجع إنشاء مجموعة بيانات تدريب لنموذج مخصص للحصول على نصائح وخيارات لتجميع مجموعة بيانات التدريب. يمكنك استخدام الملفات الموجودة ضمن مجلد "القطار" من مجموعة البيانات النموذجية (تنزيلsample_data.zipواستخراجها).
  • بمجرد حصولك على اشتراكك في Azure، قم بإنشاء مورد التعرف على النموذج في مدخل Azure للحصول على المفتاح ونقطة النهاية. وبعد نشره انقر فوق اذهب إلى المورد.
    • ستحتاج إلى المفتاح ونقطة النهاية من المورد الذي تقوم بإنشائه لتوصيل تطبيقك إلىForm Recognizer API. الصق مفتاحك ونقطة النهاية في الرمز أدناه.
    • يمكنك استخدام مستوى التسعير الحر (F0) لتجربة الخدمة، والترقية لاحقًا إلى مستوى مدفوع للإنتاج.

الإعداد

تثبيت مكتبة العميل

بعد تثبيت Python، يمكنك تثبيت أحدث إصدار من مكتبة عميل "التعرف على النموذج" مع:

pip install azure-ai-formrecognizer 

إنشاء تطبيق Python جديد

قم بإنشاء تطبيق Python جديد باسم المحرر form-recognizer.py المفضل لديك أو IDE. ثم استيراد المكتبات التالية.

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، يمكنك إنشاء نوعين مختلفين من العملاء. الأول، يستخدم form_recognizer_client للاستعلام عن الخدمة إلى حقول النموذج والمحتوى الذي تم التعرف عليه. والثاني، يستخدم form_training_client لإنشاء وإدارة نماذج مخصصة لتحسين التعرف.

FormRecognizerClient

form_recognizer_clientيوفر عمليات لـ:

  • التعرف على حقول النموذج والمحتوى باستخدام نماذج مخصصة مدربة لتحليل نماذجك المخصصة.
  • التعرف على محتوى النموذج، بما في ذلك الجداول والأسطر والكلمات، دون الحاجة إلى التدريب على نموذج.
  • التعرف على الحقول الشائعة من الإيصالات، باستخدام نموذج استلام مدرب مسبقا على نموذجForm Recognizer service.

FormTrainingClient

يوفر form_training_client عمليات من أجل:

ملاحظة

يمكن أيضاً التدريب على النماذج باستخدام واجهة مستخدم رسومية مثل أداة تسمية Form Recognizer.

مصادقة العميل

تقوم هنا، بمصادقة كائنات لاثنين من العملاء باستخدام متغيرات الاشتراك التي حددتها أعلاه. ستستخدم كائن AzureKeyCredential ، بحيث يمكنك تحديث المفتاح إذا لزم الأمر دون إنشاء كائنات عميل جديدة.

form_recognizer_client = FormRecognizerClient(endpoint, AzureKeyCredential(key))
form_training_client = FormTrainingClient(endpoint, AzureKeyCredential(key))

الحصول على أصول للاختبار

ستحتاج أيضاً إلى إضافة مراجع إلى عناوين URL لبيانات التدريب والاختبار الخاصة بك.

  • لاسترداد عنوان URL الخاص بـ SAS لبيانات تدريب النموذج المخصص، انتقل إلى مورد التخزين في مدخل Microsoft Azure وحدد علامة التبويب Storage Explorer. انتقل إلى الحاوية الخاصة بك، وانقر بزر الماوس الأيمن، وحدد Get shared access signature. من المهم الحصول على SAS لحاويتك، وليس لحساب التخزين نفسه. تأكد من اختيار الأذونات Read وWrite وDelete وList، ثم انقر فوق Create. ثم انسخ القيمة الموجودة في قسم URL إلى موقع مؤقت. يجب أن يكون بالشكل: https://<storage account>.blob.core.windows.net/<container name>?<SAS value>.

    SAS URL retrieval

  • استخدم عينة من صور الإيصالات المضمنة في العينات أدناه (متوفرة أيضاً على GitHub) أو يمكنك استخدام الخطوات المذكورة أعلاه للحصول على عنوان URL لـ SAS لمستند فردي في مساحة تخزين blob.

ملاحظة

تستخدم مقتطفات التعليمات البرمجية في هذا المشروع نماذج بعيدة يتم الوصول إليها بواسطة عناوين URL. إذا كنت تريد معالجة مستندات النموذج المحلي بدلا من ذلك، راجع الطرق ذات الصلة في الوثائق المرجعيةوالعينات.

تحليل التخطيط

يمكنك استخدام Form Recognizer لتحليل الجداول والأسطر والكلمات في المستندات، دون الحاجة إلى التدريب على نموذج. لمزيدٍ من المعلومات حول استخراج التخطيط، راجع الدليل التصوري للتخطيط.

لتحليل محتوى ملف في URI معين، استخدم أسلوب 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
...

تحليل الإيصالات

يوضح هذا القسم كيفية تحليل واستخراج الحقول الشائعة من الإيصالات الأمريكية باستخدام نموذج إيصال مدرب مسبقًا. لمزيدٍ من المعلومات حول تحليل الإيصالات، راجع الدليل المفاهيمي للإيصالات. لتحليل الإيصالات من عنوان 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

تحليل بطاقات العمل

يوضح هذا القسم كيفية تحليل واستخراج حقول مشتركة من بطاقات العمل باللغة الإنجليزية، باستخدام نموذج مدرَّب مسبقًا. للحصول على مزيد من المعلومات حول تحليل بطاقة العمل، راجع الدليل التصوري لبطاقات العمل.

لتحليل بطاقات العمل من عنوان 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.

تحليل الفواتير

يوضح هذا القسم كيفية تحليل واستخراج حقول مشتركة من فواتير المبيعات، باستخدام نموذج مدرَّب مسبقًا. للحصول على المزيد من المعلومات حول تحليل الفواتير، راجع الدليل التصوري للفواتير.

لتحليل الفواتير من عنوان 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.

تحليل مستندات المعرّف

يوضح هذا القسم كيفية تحليل واستخراج المعلومات الأساسية من مستندات الهوية الصادرة عن الحكومة - جوازات السفر العالمية ورخص القيادة الأمريكية - باستخدام نموذج المعرف المسبق لـ Form Recognizer. لمزيدٍ من المعلومات حول تحليل مستند المعرف، راجع دليلنا المفاهيمي لنموذج التعريف الذي تم إنشاؤه مسبقاً.

لتحليل مستندات الهوية من عنوان 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 إرجاعها إلى الحقول التي يمكن للطراز استخراجها، بالإضافة إلى دقتها المقدرة في كل حقل. تطبع كتلة التعليمات البرمجية التالية هذه المعلومات إلى وحدة التحكم.

هام

للتدريب باستخدام التسميات، تحتاج إلى ملفات معلومات التسمية الخاصة (\<filename\>.pdf.labels.json) في حاوية مخزن البيانات الثنائية الكبيرة إلى جانب وثائق التدريب. توفر أداة تسمية نموذج التعرف على النموذج واجهة مستخدم لمساعدتك في إنشاء ملفات التسميات هذه. بمجرد أن يكون لديك، يمكنك استدعاء 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: []

تحليل النماذج باستخدام طرازك المخصص

يوضح هذا القسم كيفية استخراج معلومات المفاتيح/القيمة والمحتويات الأخرى من أنواع القوالب المخصصة، باستخدام النماذج التي دربتها باستخدام النماذج الخاصة بك.

هام

لتنفيذ هذا السيناريو، يجب أن تكون قد تدربت بالفعل على نموذجٍ حتى تتمكن من تمرير معرفه إلى الأسلوب الوارد أدناه. راجع قسم تدريب نموذج.

يمكنك استخدام الأسلوب 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

تتحقق كتلة التعليمات البرمجية التالية من عدد النماذج التي قمت بحفظها في حسابك على "التعرف على النماذج" وتقارنها بحد الحساب.

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 Core.

تسجيل الدخول

تستخدم هذه المكتبة مكتبة تسجيل قياسية لتسجيل الدخول. يتم تسجيل المعلومات الأساسية حول جلسات عمل HTTP (عناوين URL والرؤوس وما إلى ذلك) على مستوى INFO.

يمكن تمكين تسجيل مستوى DEBUG مفصلة بما في ذلك الهيئات طلب /استجابة ورؤوس غير منقحة على عميل مع logging_enable وسيطة الكلمة الأساسية:

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)

نماذج REST على GitHub

الخطوات التالية

بالنسبة لهذا المشروع، استخدمت مكتبة عميل Python للتعرف على النماذج لتدريب النماذج وتحليل النماذج بطرق مختلفة. يمكنك أيضاً، التعرف على نصائح لإنشاء مجموعة بيانات تدريب أفضل وإنتاج نماذج أكثر دقة.

ملاحظة

  • يستهدف هذا المشروع الإصدار 2.1 من واجهة برمجة تطبيقات Azure Form Recognizer API باستخدام cURL لتنفيذ استدعاءات واجهة برمجة تطبيقات REST.

| واجهة برمجة تطبيقات | REST لخدمة Form Recognizerمرجع واجهة برمجة تطبيقاتREST لخدمة Azure |

المتطلبات الأساسية

  • تم تثبيت cURL.
  • الإصدار 6.0+ من PowerShell، أو تطبيق سطر أوامر مشابه.
  • اشتراك Azure - إنشاء اشتراك مجانًا
  • كائن التخزين الثنائي كبير الحجم من Azure الذي يحتوي على مجموعة من بيانات التدريب. راجع إنشاء مجموعة بيانات تدريب لنموذج مخصص للحصول على نصائح وخيارات لتجميع مجموعة بيانات التدريب. يمكنك استخدام الملفات الموجودة ضمن مجلد "القطار" من مجموعة البيانات النموذجية (تنزيلsample_data.zipواستخراجها).
  • بمجرد حصولك على اشتراكك في Azure، قم بإنشاء مورد التعرف على النموذج في مدخل Azure للحصول على المفتاح ونقطة النهاية. بعد انتشاره، حدد Go to resource.
    • ستحتاج إلى المفتاح ونقطة النهاية من المورد الذي تنشئه؛ لتوصيل التطبيق الخاص بك بواجهة برمجة تطبيقات Form Recognizer. ستقوم بلصق مفتاحك ونقطة النهاية في الرمز أدناه لاحقا في المشروع
    • يمكنك استخدام مستوى التسعير المجاني (F0) لتجربة الخدمة، والترقية لاحقًا إلى مستوى مدفوع للإنتاج.
  • عنوان URL لصورة إيصال. يمكنك استخدام صورة نموذج لهذا التشغيل السريع.
  • عنوان URL لصورة إيصال لبطاقة العمل. يمكنك استخدام صورة نموذج لهذا التشغيل السريع.
  • عنوان URL لصورة فاتورة. يمكنك استخدام نموذج مستند لهذا التشغيل السريع.
  • عنوان URL لصورة مستند معرّف. يمكنك استخدام صورة نموذج

تحليل التخطيط

يمكنك استخدام Form Recognizer لتحليل واستخراج الجداول وعلامات التحديد والنص والتصميم في المستندات، دون الحاجة إلى التدريب على نموذج. للحصول على مزيد من المعلومات حول استخراج المخطط، راجع الدليل التصوري للمخطط. قبل تشغيل الأمر، يرجى إجراء هذه التغييرات:

  1. استبدال {endpoint} بنقطة النهاية التي حصلت عليها مع اشتراك Form Recognizer.
  2. استبدل {key} بالمفتاح الذي نسخته من الخطوة السابقة.
  3. استبدال \"{your-document-url} بأحد أمثلة عناوين 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) تتضمن عنوانموقع العملية. تحتوي قيمة هذا العنوان على معرّف نتيجة يمكنك استخدامه للاستعلام عن حالة العملية غير المتزامنة والحصول على النتائج:

https://cognitiveservice/formrecognizer/v2.1/layout/analyzeResults/ {resultId} .

إن السلسلة، في المثال التالي، كجزء من عنوان URL، بعد analyzeResults/ هي معرّف النتيجة.

https://cognitiveservice/formrecognizer/v2/layout/analyzeResults/54f0b076-4e38-43e5-81bd-b85b8835fdfb

الحصول على نتائج المخطط

بعد استدعاء واجهة برمجة تطبيقات تحليل المخطط، يمكنك استدعاء واجهة برمجة تطبيقات تحليل نتائج المخطط للحصول على حالة العملية والبيانات المستخرجة. قبل تشغيل الأمر، يرجى إجراء هذه التغييرات:

  1. استبدال {endpoint} بنقطة النهاية التي حصلت عليها مع اشتراك Form Recognizer.
  2. استبدل {key} بالمفتاح الذي نسخته من الخطوة السابقة.
  3. استبدال {resultId} بمعرّف النتيجة من الخطوة السابقة.

الطلب

curl -v -X GET "https://{endpoint}/formrecognizer/v2.1/layout/analyzeResults/{resultId}" -H "Ocp-Apim-Subscription-Key: {key}"

فحص النتائج

ستتلقى استجابة 200 (success) مع محتوى JSON.

راجع صورة الفاتورة التالية وناتج JSON المقابل لها.

  • تحتوي العقدة "readResults" على كل سطر من النص مع موضع مربع الإحاطة الخاص به على الصفحة.
  • تعرض العقدة selectionMarks كل علامة تحديد (خانة اختيار، علامة راديو) وما إذا كانت حالتها «محددة» أو «غير محددة».
  • يتضمن "pageResults" القسم الجداول المستخرجة. بالنسبة لكل جدول، يتم استخراج النص والصف وفهرس العمود، والصفوف والأعمدة الممتدة، ومربع الإحاطة، وغير ذلك.

Contoso project statement document with a table.

هيئة الاستجابة

تم اختصار هذا الناتج من أجل التبسيط. راجع ناتج النموذج الكامل على 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"
                                ]
                            },
                            ...
                        ]
                    },
                    ...
                ]
            }
        ]
    }
}

تحليل الإيصالات

يوضح هذا القسم كيفية تحليل واستخراج الحقول الشائعة من الإيصالات الأمريكية باستخدام نموذج إيصال مدرب مسبقًا. للحصول على مزيد من المعلومات حول تحليل الإيصالات، راجع الدليل التصوري للإيصالات. لبدء تحليل إيصال، استدعِ واجهة برمجة تطبيقات تحليل الإيصالات باستخدام الأمر cURL أدناه. قبل تشغيل الأمر، يرجى إجراء هذه التغييرات:

  1. استبدال {endpoint} بنقطة النهاية التي حصلت عليها مع اشتراك Form Recognizer.
  2. استبدال {your receipt URL} بعنوان URL لصورة إيصال.
  3. استبدل {key> بالمفتاح الذي نسخته من الخطوة السابقة.

الطلب

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) تتضمن عنوانموقع العملية. تحتوي قيمة هذا العنوان على معرّف نتيجة يمكنك استخدامه للاستعلام عن حالة العملية غير المتزامنة والحصول على النتائج:

https://cognitiveservice/formrecognizer/v2.1/prebuilt/receipt/analyzeResults/ {resultId}

إن السلسلة، في المثال التالي، بعد operations/ هي معرّف النتيجة:

https://cognitiveservice/formrecognizer/v2.1/prebuilt/receipt/operations/54f0b076-4e38-43e5-81bd-b85b8835fdfb

الحصول على نتائج الإيصالات

بعد استدعاء واجهة برمجة تطبيقات تحليل الإيصالات، يمكنك استدعاء واجهة برمجة تطبيقات الحصول على تحليل نتائج الإيصالات للحصول على حالة العملية والبيانات المستخرجة. قبل تشغيل الأمر، يرجى إجراء هذه التغييرات:

  1. استبدل {endpoint} بنقطة النهاية التي حصلت عليها بمفتاح التعرف على النماذج. يمكنك العثور عليه في علامة التبويب نظرة عامة حول مورد Form Recognizer.
  2. استبدال {resultId} بمعرّف النتيجة من الخطوة السابقة.
  3. استبدل {key} بمفتاحك.

الطلب

curl -X GET "https://{endpoint}/formrecognizer/v2.1/prebuilt/receipt/analyzeResults/{resultId}" -H "Ocp-Apim-Subscription-Key: {key}"

فحص الاستجابة

ستتلقى استجابة 200 (Success) مع محتوى JSON. يشير الحقل الأول "status" إلى حالة العملية. إذا لم تكتمل العملية، فإن قيمة "status" ستكون "running" أو "notStarted"، ويجب عليك استدعاء واجهة برمجة التطبيقات مرة أخرى، إما يدويًّا أو من خلال برنامج نصي. نوصي بفاصل زمني من ثانية واحدة أو أكثر بين كل استدعاء وآخر.

تحتوي العقدة "readResults" على النص الذي تم التعرف عليه بأكمله (وذلك في حال إعداد المعلمة includeTextDetails الاختيارية إلى true). يتم تنظيم النص حسب الصفحة، ثم حسب السطر، ثم حسب الكلمات الفردية. تحتوي العقدة "documentResults" على قيم خاصة بالإيصال التي اكتشفها النموذج. هذا هو المكان الذي ستجد فيه أزواج المفاتيح/ القيم المفيدة مثل الضريبة والإجمالي وعنوان التاجر وغير ذلك.

راجع صورة الإيصال التالية وناتج JSON المقابل لها.

A receipt from Contoso store

هيئة الاستجابة

تم اختصار هذا الناتج من أجل إمكانية القراءة. راجع ناتج النموذج الكامل على 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"
            ]
          }
        }
      }
    ]
  }
}

تحليل بطاقات العمل

يوضح هذا القسم كيفية تحليل واستخراج حقول مشتركة من بطاقات العمل باللغة الإنجليزية، باستخدام نموذج مدرَّب مسبقًا. للحصول على مزيد من المعلومات حول تحليل بطاقة العمل، راجع الدليل التصوري لبطاقات العمل. لبدء تحليل بطاقة عمل، يمكنك استدعاء تحليل واجهة برمجة تطبيقات بطاقة العمل باستخدام الأمر cURL أدناه. قبل تشغيل الأمر، يرجى إجراء هذه التغييرات:

  1. استبدال {endpoint} بنقطة النهاية التي حصلت عليها مع اشتراك Form Recognizer.
  2. استبدال {your business card URL} بعنوان URL لصورة إيصال.
  3. استبدل {key} بالمفتاح الذي نسخته من الخطوة السابقة.

الطلب

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) تتضمن عنوانموقع العملية. تحتوي قيمة هذا العنوان على معرّف نتيجة يمكنك استخدامه للاستعلام عن حالة العملية غير المتزامنة والحصول على النتائج:

https://cognitiveservice/formrecognizer/v2.1/prebuilt/businessCard/analyzeResults/ {resultId}

إن السلسلة، في المثال التالي، كجزء من عنوان URL، بعد analyzeResults/ هي معرّف النتيجة.

https://cognitiveservice/formrecognizer/v2.1/prebuilt/businessCard/analyzeResults/54f0b076-4e38-43e5-81bd-b85b8835fdfb

الحصول على نتائج بطاقة العمل

بعد استدعاء واجهة برمجة تطبيقات تحليل بطاقة العمل، يمكنك استدعاء واجهة برمجة تطبيقات الحصول على تحليل نتائج بطاقة العمل للحصول على حالة العملية والبيانات المستخرجة. قبل تشغيل الأمر، يرجى إجراء هذه التغييرات:

  1. استبدل {endpoint} بنقطة النهاية التي حصلت عليها بمفتاح التعرف على النماذج. يمكنك العثور عليه في علامة التبويب نظرة عامة حول مورد Form Recognizer.
  2. استبدال {resultId} بمعرّف النتيجة من الخطوة السابقة.
  3. استبدل {key} بمفتاحك.
curl -v -X GET https://{endpoint}/formrecognizer/v2.1/prebuilt/businessCard/analyzeResults/{resultId}"
-H "Ocp-Apim-Subscription-Key: {key}"

فحص الاستجابة

ستتلقى استجابة 200 (Success) مع محتوى JSON.

تحتوي العقدة "readResults" على النص الذي تم التعرف عليه بالكامل. يتم تنظيم النص حسب الصفحة، ثم حسب السطر، ثم حسب الكلمات الفردية. تحتوي العقدة "documentResults" على قيم خاصة ببطاقة العمل التي اكتشفها النموذج. هذا هو المكان الذي ستجد فيه معلومات اتصال مفيدة، مثل اسم الشركة، والاسم الأول، واسم العائلة، ورقم الهاتف، وغير ذلك.

A business card from Contoso company

تم اختصار ناتج 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
                            }
                        ]
                    }
                }
            }
        ]
    }
}

سيعمل البرنامج النصي على طباعة الاستجابات إلى وحدة التحكم حتى يتم إكمال عملية تحليل بطاقة العمل.

تحليل الفواتير

يمكنك استخدام Form Recognizer لاستخراج نص الحقل والقيم الدلالية من مستند فاتورة معين. لبدء تحليل فاتورة، استخدم الأمر cURL أدناه. للحصول على المزيد من المعلومات حول تحليل الفاتورة، راجع الدليل التصوري للفواتير. لبدء تحليل فاتورة، استدعِ واجهة برمجة تطبيقات تحليل الفواتير باستخدام الأمر cURL أدناه. قبل تشغيل الأمر، يرجى إجراء هذه التغييرات:

  1. استبدال {endpoint} بنقطة النهاية التي حصلت عليها مع اشتراك Form Recognizer.
  2. استبدال {your invoice URL} بعنوان URL لمستند فاتورة.
  3. استبدل {key} بمفتاحك.

الطلب

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 "{​​​​​​​'source': '{your invoice URL}'}​​​​​​​​"

موقع-العملية

ستتلقى استجابة 202 (Success) تتضمن عنوانموقع العملية. تحتوي قيمة هذا العنوان على معرّف نتيجة يمكنك استخدامه للاستعلام عن حالة العملية غير المتزامنة والحصول على النتائج:

https://cognitiveservice/formrecognizer/v2.1/prebuilt/receipt/analyzeResults/ {resultId}

إن السلسلة، في المثال التالي، كجزء من عنوان URL، بعد analyzeResults/ هي معرّف النتيجة:

https://cognitiveservice/formrecognizer/v2.1/prebuilt/invoice/analyzeResults/54f0b076-4e38-43e5-81bd-b85b8835fdfb

الحصول على نتائج الفاتورة

بعد استدعاء واجهة برمجة تطبيقات تحليل الفواتير، يمكنك استدعاء واجهة برمجة تطبيقات الحصول على تحليل نتائج الفواتير للحصول على حالة العملية والبيانات المستخرجة. قبل تشغيل الأمر، يرجى إجراء هذه التغييرات:

  1. استبدل {endpoint} بنقطة النهاية التي حصلت عليها بمفتاح التعرف على النماذج. يمكنك العثور عليه في علامة التبويب نظرة عامة حول مورد Form Recognizer.
  2. استبدال {resultId} بمعرّف النتيجة من الخطوة السابقة.
  3. استبدل {key} بمفتاحك.

الطلب

curl -v -X GET "https://{endpoint}/formrecognizer/v2.1/prebuilt/invoice/analyzeResults/{resultId}" -H "Ocp-Apim-Subscription-Key: {key}"

فحص الاستجابة

ستتلقى استجابة 200 (Success) مع محتوى JSON.

  • يحتوي الحقل "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
                },
                ...
            }
        }]
    }
}

تحليل مستندات الهوية

لبدء تحليل مستند تعريف، استخدم الأمر cURL أدناه. لمزيد من المعلومات حول تحليل مستند المعرّف، راجع الدليل التصوري لمستندات المعرّف. لبدء تحليل مستند معرّف، يمكنك استدعاء واجهة برمجة تطبيقات تحليل مستند المعرّف باستخدام الأمر cURL أدناه. قبل تشغيل الأمر، يرجى إجراء هذه التغييرات:

  1. استبدال {endpoint} بنقطة النهاية التي حصلت عليها مع اشتراك Form Recognizer.
  2. استبدال {your ID document URL} بعنوان URL لصورة إيصال.
  3. استبدل {key} بالمفتاح الذي نسخته من الخطوة السابقة.

الطلب

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) تتضمن عنوانموقع العملية. تحتوي قيمة هذا العنوان على معرّف نتيجة يمكنك استخدامه للاستعلام عن حالة العملية غير المتزامنة والحصول على النتائج:

https://cognitiveservice/formrecognizer/v2.1/prebuilt/documentId/analyzeResults/ {resultId}

إن السلسلة، في المثال التالي، بعد analyzeResults/ هي معرّف النتيجة:

https://westus.api.cognitive.microsoft.com/formrecognizer/v2.1/prebuilt/idDocument/analyzeResults/83d0137b-28e1-4051-98ce-42bd21f77ae0

الحصول على تحليل نتيجة مستند المعرّف

بعد استدعاء واجهة برمجة تطبيقات تحليل مستند المعرّف، يمكنك استدعاء واجهة برمجة تطبيقات الحصول على تحليل نتائج مستند المعرّف للحصول على حالة العملية والبيانات المستخرجة. قبل تشغيل الأمر، يرجى إجراء هذه التغييرات:

  1. استبدل {endpoint} بنقطة النهاية التي حصلت عليها بمفتاح التعرف على النماذج. يمكنك العثور عليه في علامة التبويب نظرة عامة حول مورد Form Recognizer.
  2. استبدال {resultId} بمعرّف النتيجة من الخطوة السابقة.
  3. استبدل {key} بمفتاحك.

الطلب

curl -X GET "https://{endpoint}/formrecognizer/v2.1/prebuilt/businessCard/analyzeResults/{resultId}" -H "Ocp-Apim-Subscription-Key: {key}"

فحص الاستجابة

ستتلقى استجابة 200 (Success) مع محتوى JSON. يشير الحقل الأول "status" إلى حالة العملية. إذا لم تكتمل العملية ، فستكون قيمة "status" أو ، ويجب عليك استدعاء واجهة برمجة التطبيقات مرة أخرى ، إما يدويا أو "notStarted"من خلال برنامج نصي حتى تتلقى القيمةsucceeded."running" نوصي بفاصل زمني من ثانية واحدة أو أكثر بين كل استدعاء وآخر.

  • يحتوي الحقل "readResults" على كل سطر من النص تم استخراجه من مستند المعرّف.
  • يحتوي الحقل "documentResults" على مصفوفة من العناصر، يمثل كل منها مستندًا معرّفًا تم اكتشافه في مستند الإدخال.

فيما يلي نموذج لمستند الهوية وإخراج JSON المقابل له

  • sample driver's license

هيئة الاستجابة

{
    "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 للكائنات الثنائية كبيرة الحجم. أنت بحاجة إلى ما لا يقل عن خمسة نماذج مملوءة (مستندات و/ أو صور PDF) من نفس النوع/ التصميم. راجع إنشاء مجموعة بيانات تدريب لنموذج مخصص للحصول على نصائح وخيارات لتجميع بيانات التدريب.

التدريب بدون البيانات المسماة هو العملية الافتراضية بل وأبسط منها. بدلاً من ذلك، يمكنك تسمية بعض بيانات التدريب مسبقًا يدويًّا أو جميعها. وهذه عملية أكثر تعقيدًا ولكنها تؤدي إلى نموذج أفضل تدريبًا.

ملاحظة

يمكنك أيضا تدريب النماذج باستخدام واجهة مستخدم رسومية مثل أداة وضع العلامات النموذجية للتعرف على النماذج.

التدريب على نموذج بدون تسميات

للتدريب على نموذج Form Recognizer مع المستندات في حاويات كائنات Azure الثنائية كبيرة الحجم، يرجى استدعاء واجهة برمجة تطبيقات التدريب على نموذج مخصص عن طريق تشغيل الأمر cURL التالي. قبل تشغيل الأمر، يرجى إجراء هذه التغييرات:

  1. استبدال {endpoint} بنقطة النهاية التي حصلت عليها مع اشتراك Form Recognizer.

  2. استبدل {key} بالمفتاح الذي نسخته من الخطوة السابقة.

  3. استبدال {SAS URL} بعنوان URL لتوقيع الوصول المشترك (SAS) لحاوية كائنات Azure الثنائية كبيرة الحجم. لاسترداد عنوان URL الخاص بـ SAS لبيانات تدريب النموذج المخصص، انتقل إلى مورد التخزين في مدخل Microsoft Azure وحدد علامة التبويب Storage Explorer. انتقل إلى الحاوية الخاصة بك، وانقر بزر الماوس الأيمن، وحدد Get shared access signature. من المهم الحصول على SAS لحاويتك، وليس لحساب التخزين نفسه. تأكد من اختيار الأذونات Read وWrite وDelete وList، ثم انقر فوق Create. ثم انسخ القيمة الموجودة في قسم URL إلى موقع مؤقت. يجب أن يكون بالشكل: https://<storage account>.blob.core.windows.net/<container name>?<SAS value>.

    SAS URL retrieval

الطلب

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) مع عنوان الموقع. تحتوي قيمة هذا الرأس على معرف نموذج للنموذج المدرب حديثا يمكنك استخدامه للاستعلام عن حالة العملية والحصول على النتائج:

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

التدريب على نموذج باستخدام تسميات

للتدريب مع التسميات، تحتاج إلى ملفات معلومات التسمية الخاصة (\<filename\>.pdf.labels.json) في حاوية كائنات التخزين الثنائية كبيرة الحجم إلى جانب مستندات التدريب. توفر أداة تسمية نموذج التعرف على النموذج واجهة مستخدم لمساعدتك في إنشاء ملفات التسميات هذه. بعد الحصول عليها، يمكنك استدعاء واجهة برمجة تطبيقات التدريب على نموذج مخصص ، مع ضبط المعلمة "useLabelFile" على true في نص JSON.

قبل تشغيل الأمر، يرجى إجراء هذه التغييرات:

  1. استبدال {endpoint} بنقطة النهاية التي حصلت عليها مع اشتراك Form Recognizer.

  2. استبدل {key} بالمفتاح الذي نسخته من الخطوة السابقة.

  3. استبدال {SAS URL} بعنوان URL لتوقيع الوصول المشترك (SAS) لحاوية كائنات Azure الثنائية كبيرة الحجم. لاسترداد عنوان URL الخاص بـ SAS لبيانات تدريب النموذج المخصص، انتقل إلى مورد التخزين في مدخل Microsoft Azure وحدد علامة التبويب Storage Explorer. انتقل إلى الحاوية الخاصة بك، وانقر بزر الماوس الأيمن، وحدد Get shared access signature. من المهم الحصول على SAS لحاويتك، وليس لحساب التخزين نفسه. تأكد من اختيار الأذونات Read وWrite وDelete وList، ثم انقر فوق Create. ثم انسخ القيمة الموجودة في قسم URL إلى موقع مؤقت. يجب أن يكون بالشكل: https://<storage account>.blob.core.windows.net/<container name>?<SAS value>.

    SAS URL retrieval

الطلب

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) مع عنوان الموقع. تحتوي قيمة هذا الرأس على معرف نموذج للنموذج المدرب حديثا يمكنك استخدامه للاستعلام عن حالة العملية والحصول على النتائج:

https://{endpoint}/formrecognizer/v2.1/custom/models/ {modelId}

إن السلسلة، في المثال التالي، كجزء من عنوان URL، بعد models/ هي معرّف النموذج.

https://westus.api.cognitive.microsoft.com/formrecognizer/v2.1/custom/models/4da0bf8e-5325-467c-93bb-9ff13d5f72a2

الحصول على نتائج التدريب

بعد بدء عملية التدريب، استخدم الحصول على نموذج مخصص للتحقق من حالة التدريب. مرر معرّف النموذج إلى طلب واجهة برمجة التطبيقات للتحقق من حالة التدريب:

  1. استبدل {endpoint} بنقطة النهاية التي حصلت عليها بمفتاح التعرف على النماذج.
  2. استبدال {key} المفتاح الخاص بك
  3. استبدال {model ID} بمعرّف النموذج الذي تلقيته في الخطوة السابقة

الطلب

curl -X GET "https://{endpoint}/formrecognizer/v2.1/custom/models/{modelId}" -H "Content-Type: application/json" -H "Ocp-Apim-Subscription-Key: {key}"

تحليل النماذج باستخدام نموذج مخصص

بعد ذلك ، ستستخدم نموذجك المدرب حديثا لتحليل مستند واستخراج الحقول والجداول منه. استدعِ واجهة برمجة تطبيقات تحليل نموذج عن طريق تشغيل الأمر cURL التالي. قبل تشغيل الأمر، يرجى إجراء هذه التغييرات:

  1. استبدل {endpoint} بنقطة النهاية التي حصلت عليها من مفتاح التعرف على النماذج. يمكنك العثور عليه في علامة التبويب نظرة عامة حول مورد Form Recognizer.
  2. استبدال {model ID} بمعرّف النموذج الذي تلقيته في القسم السابق.
  3. استبدال {SAS URL} بعنوان URL لتوقيع وصول مشترك إلى ملفك في تخزين Azure. اتبع الخطوات الموجودة في قسم التدريب، ولكن بدلاً من الحصول على عنوان URL لتوقيع وصول مشترك لحاوية الكائنات الثنائية كبيرة الحجم بأكملها، احصل على عنوان للملف المحدد الذي تريد تحليله.
  4. استبدل {key} بمفتاحك.

الطلب

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) تتضمن عنوانموقع العملية. تتضمن قيمة هذا العنوان معرّف نتيجة ستستخدمه لتتبع نتائج عملية التحليل:

https://cognitiveservice/formrecognizer/v2.1/custom/models/{modelId}/analyzeResults/ {resultId}

إن السلسلة، في المثال التالي، كجزء من عنوان URL، بعد analyzeResults/ هي معرّف النتيجة.

https://cognitiveservice/formrecognizer/v2/layout/analyzeResults/54f0b076-4e38-43e5-81bd-b85b8835fdfb

احفظ معرّف النتائج هذا للخطوة التالية.

الحصول على نتائج التحليل

استدعِ واجهة برمجة تطبيقات تحليل نتائج النموذج للاستعلام عن نتائج عملية تحليل.

  1. استبدل {endpoint} بنقطة النهاية التي حصلت عليها من مفتاح التعرف على النماذج. يمكنك العثور عليه في علامة التبويب نظرة عامة حول مورد Form Recognizer.
  2. استبدال {result ID} بالمعرّف الذي تلقيته في القسم السابق.
  3. استبدل {key} بمفتاحك.

الطلب

curl -X GET "https://{endpoint}/formrecognizer/v2.1/custom/models/{modelId}/analyzeResults/{resultId}" -H "Ocp-Apim-Subscription-Key: {key}"

ستتلقى استجابة 200 (Success) باستخدام نص JSON بالتنسيق التالي. تم اختصار الناتج من أجل التبسيط. لاحظ الحقل "status" بالقرب من الأسفل. سيكون لذلك قيمة "succeeded" عند اكتمال عملية التحليل. إذا لم تكتمل عملية التحليل، فستحتاج إلى الاستعلام عن الخدمة مرة أخرى عن طريق إعادة تشغيل الأمر. نوصي بفاصل زمني من ثانية واحدة أو أكثر بين كل استدعاء وآخر.

في النماذج المخصصة التي تم التدريب عليها بدون تسميات، تكون اقترانات وجداول أزواج من المفتاح/ القيمة موجودة في عقدة "pageResults" لناتج JSON. في النماذج المخصصة المدربة على التسميات، توجد اقترانات زوج المفاتيح/القيمة في العقدة "documentResults" . إذا حددت أيضًا استخراج نص عادي من خلال معلمة عنوان includeTextDetails، فستعرض العقدة "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٪.

إدارة النماذج المخصصة

الحصول على قائمة بالنماذج المخصصة

استخدم واجهة برمجة تطبيقات قائمة النماذج المخصصة في الأمر التالي لإرجاع قائمة بكافة النماذج المخصصة التي تنتمي إلى اشتراكك.

  1. استبدال {endpoint} بنقطة النهاية التي حصلت عليها مع اشتراك Form Recognizer.
  2. استبدل {key} بالمفتاح الذي نسخته من الخطوة السابقة.

الطلب

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"
}

الحصول على نموذج معين

لاسترجاع معلومات مفصلة حول نموذج مخصص معين، استخدم واجهة برمجة تطبيقات الحصول على نموذج مخصص في الأمر التالي.

  1. استبدال {endpoint} بنقطة النهاية التي حصلت عليها مع اشتراك Form Recognizer.
  2. استبدل {key} بالمفتاح الذي نسخته من الخطوة السابقة.
  3. استبدال {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"
      }
    ]
  }
}

حذف نموذج من حساب المورد

يمكنك أيضًا حذف نموذج من حسابك عن طريق الرجوع إلى معرّفه. يستدعي هذا الأمر واجهة برمجة تطبيقات حذف نموذج مخصص لحذف النموذج المستخدم في القسم السابق.

  1. استبدال {endpoint} بنقطة النهاية التي حصلت عليها مع اشتراك Form Recognizer.
  2. استبدل {key} بالمفتاح الذي نسخته من الخطوة السابقة.
  3. استبدال {modelId} بمعرّف النموذج المخصص الذي تريد البحث عنه.

الطلب

curl -v -X DELETE "https://{endpoint}/formrecognizer/v2.1/custom/models/{modelId}" -H "Ocp-Apim-Subscription-Key: {key}"

ستتلقى استجابة 204 ناجحة، تشير إلى وضع علامة على نموذجك لحذفه. سيتم إزالة البيانات الاصطناعية للنموذج في غضون 48 ساعة.

الخطوات التالية

بالنسبة لهذا المشروع، استخدمت واجهة برمجة تطبيقات REST للتعرف على النماذج لتحليل النماذج بطرق مختلفة. ثم استكشاف المستندات المرجعية لمعرفة المزيد من المعلومات حول واجهة برمجة تطبيقات Form Recognizer بمزيد من التفصيل.