快速入门:使用计算机视觉 REST API 和 C# 提取手写文本Quickstart: Extract handwritten text using the Computer Vision REST API and C#

在本快速入门中,你将使用计算机视觉的 REST API 从图像中提取手写文本。In this quickstart, you will extract handwritten text from an image by using Computer Vision's REST API. 使用批量读取 API 和读取操作结果 API,可以检测图像中的手写文本,并将识别的字符提取到计算机可读的字符流中。With the Batch Read API and the Read Operation Result API, you can detect handwritten text in an image and extract recognized characters into a machine-readable character stream.

重要

不同于 OCR 方法,批量读取方法以异步方式运行。Unlike the OCR method, the Batch Read method runs asynchronously. 此方法不返回成功响应正文中的任何信息。This method does not return any information in the body of a successful response. 但是,读取方法返回 Operation-Location 响应标头字段中的 URI。Instead, the Read method returns a URI in the Operation-Location response header field. 然后就可以调用此 URI,它表示读取操作结果方法,以便检查状态并返回批量读取方法调用的结果。You can then call this URI, which represents the Read Operation Result method, in order to check the status and return the results of the Batch Read method call.

如果没有 Azure 订阅,可在开始前创建一个试用帐户If you don't have an Azure subscription, create a Trial before you begin.

先决条件Prerequisites

创建和运行示例应用程序Create and run the sample application

要在 Visual Studio 中创建示例,请执行以下步骤:To create the sample in Visual Studio, do the following steps:

  1. 使用 Visual C# 控制台应用模板在 Visual Studio 中创建新的 Visual Studio 解决方案。Create a new Visual Studio solution in Visual Studio, using the Visual C# Console App template.
  2. 安装 Newtonsoft.Json NuGet 包。Install the Newtonsoft.Json NuGet package.
    1. 在菜单上,单击“工具”,然后依次选择“NuGet 包管理器”、“管理解决方案的 NuGet 包” 。On the menu, click Tools, select NuGet Package Manager, then Manage NuGet Packages for Solution.
    2. 单击“浏览”选项卡,在“搜索”框中键入“Newtonsoft.Json” 。Click the Browse tab, and in the Search box type "Newtonsoft.Json".
    3. 选择显示的 Newtonsoft.Json,单击项目名称旁边的复选框,然后单击“安装” 。Select Newtonsoft.Json when it displays, then click the checkbox next to your project name, and Install.
  3. Program.cs 中的代码替换为以下代码,然后根据需要在代码中进行以下更改:Replace the code in Program.cs with the following code, and then make the following changes in code where needed:
    1. subscriptionKey 的值替换为你的订阅密钥。Replace the value of subscriptionKey with your subscription key.
    2. 如有必要,请将 uriBase 的值替换为获取的订阅密钥所在的 Azure 区域中的批量读取方法的终结点 URL。Replace the value of uriBase with the endpoint URL for the Batch Read method from the Azure region where you obtained your subscription keys, if necessary.
  4. 运行该程序。Run the program.
  5. 在提示符处,输入本地图像的路径。At the prompt, enter the path to a local image.
using Newtonsoft.Json.Linq;
using System;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks;

namespace CSHttpClientSample
{
    static class Program
    {
        // Replace <Subscription Key> with your valid subscription key.
        const string subscriptionKey = "<Subscription Key>";

        const string uriBase =
            "https://api.cognitive.azure.cn/vision/v2.0/read/core/asyncBatchAnalyze";

        static void Main()
        {
            // Get the path and filename to process from the user.
            Console.WriteLine("Handwriting Recognition:");
            Console.Write(
                "Enter the path to an image with handwritten text you wish to read: ");
            string imageFilePath = Console.ReadLine();

            if (File.Exists(imageFilePath))
            {
                // Call the REST API method.
                Console.WriteLine("\nWait a moment for the results to appear.\n");
                ReadHandwrittenText(imageFilePath).Wait();
            }
            else
            {
                Console.WriteLine("\nInvalid file path");
            }
            Console.WriteLine("\nPress Enter to exit...");
            Console.ReadLine();
        }

        /// <summary>
        /// Gets the handwritten text from the specified image file by using
        /// the Computer Vision REST API.
        /// </summary>
        /// <param name="imageFilePath">The image file with handwritten text.</param>
        static async Task ReadHandwrittenText(string imageFilePath)
        {
            try
            {
                HttpClient client = new HttpClient();

                // Request headers.
                client.DefaultRequestHeaders.Add(
                    "Ocp-Apim-Subscription-Key", subscriptionKey);

                // Assemble the URI for the REST API method.
                string uri = uriBase;

                HttpResponseMessage response;

                // Two REST API methods are required to extract handwritten text.
                // One method to submit the image for processing, the other method
                // to retrieve the text found in the image.

                // operationLocation stores the URI of the second REST API method,
                // returned by the first REST API method.
                string operationLocation;

                // Reads the contents of the specified local image
                // into a byte array.
                byte[] byteData = GetImageAsByteArray(imageFilePath);

                // Adds the byte array as an octet stream to the request body.
                using (ByteArrayContent content = new ByteArrayContent(byteData))
                {
                    // This example uses the "application/octet-stream" content type.
                    // The other content types you can use are "application/json"
                    // and "multipart/form-data".
                    content.Headers.ContentType =
                        new MediaTypeHeaderValue("application/octet-stream");

                    // The first REST API method, Batch Read, starts
                    // the async process to analyze the written text in the image.
                    response = await client.PostAsync(uri, content);
                }

                // The response header for the Batch Read method contains the URI
                // of the second method, Read Operation Result, which
                // returns the results of the process in the response body.
                // The Batch Read operation does not return anything in the response body.
                if (response.IsSuccessStatusCode)
                    operationLocation =
                        response.Headers.GetValues("Operation-Location").FirstOrDefault();
                else
                {
                    // Display the JSON error data.
                    string errorString = await response.Content.ReadAsStringAsync();
                    Console.WriteLine("\n\nResponse:\n{0}\n",
                        JToken.Parse(errorString).ToString());
                    return;
                }

                // If the first REST API method completes successfully, the second 
                // REST API method retrieves the text written in the image.
                //
                // Note: The response may not be immediately available. Handwriting
                // recognition is an asynchronous operation that can take a variable
                // amount of time depending on the length of the handwritten text.
                // You may need to wait or retry this operation.
                //
                // This example checks once per second for ten seconds.
                string contentString;
                int i = 0;
                do
                {
                    System.Threading.Thread.Sleep(1000);
                    response = await client.GetAsync(operationLocation);
                    contentString = await response.Content.ReadAsStringAsync();
                    ++i;
                }
                while (i < 10 && contentString.IndexOf("\"status\":\"Succeeded\"") == -1);

                if (i == 10 && contentString.IndexOf("\"status\":\"Succeeded\"") == -1)
                {
                    Console.WriteLine("\nTimeout error.\n");
                    return;
                }

                // Display the JSON response.
                Console.WriteLine("\nResponse:\n\n{0}\n",
                    JToken.Parse(contentString).ToString());
            }
            catch (Exception e)
            {
                Console.WriteLine("\n" + e.Message);
            }
        }

        /// <summary>
        /// Returns the contents of the specified file as a byte array.
        /// </summary>
        /// <param name="imageFilePath">The image file to read.</param>
        /// <returns>The byte array of the image data.</returns>
        static byte[] GetImageAsByteArray(string imageFilePath)
        {
            // Open a read-only file stream for the specified file.
            using (FileStream fileStream =
                new FileStream(imageFilePath, FileMode.Open, FileAccess.Read))
            {
                // Read the file's contents into a byte array.
                BinaryReader binaryReader = new BinaryReader(fileStream);
                return binaryReader.ReadBytes((int)fileStream.Length);
            }
        }
    }
}

检查响应Examine the response

成功的响应以 JSON 格式返回。A successful response is returned in JSON. 示例应用程序会在控制台窗口中分析和显示成功响应,如下例所示:The sample application parses and displays a successful response in the console window, similar to the following example:

{
  "status": "Succeeded",
  "recognitionResults": [
    {
      "page": 1,
      "clockwiseOrientation": 349.59,
      "width": 3200,
      "height": 3200,
      "unit": "pixel",
      "lines": [
        {
          "boundingBox": [202,618,2047,643,2046,840,200,813],
          "text": "Our greatest glory is not",
          "words": [
            {
              "boundingBox": [204,627,481,628,481,830,204,829],
              "text": "Our"
            },
            {
              "boundingBox": [519,628,1057,630,1057,832,518,830],
              "text": "greatest"
            },
            {
              "boundingBox": [1114,630,1549,631,1548,833,1114,832],
              "text": "glory"
            },
            {
              "boundingBox": [1586,631,1785,632,1784,834,1586,833],
              "text": "is"
            },
            {
              "boundingBox": [1822,632,2115,633,2115,835,1822,834],
              "text": "not"
            }
          ]
        },
        {
          "boundingBox": [420,1273,2954,1250,2958,1488,422,1511],
          "text": "but in rising every time we fall",
          "words": [
            {
              "boundingBox": [423,1269,634,1268,635,1507,424,1508],
              "text": "but"
            },
            {
              "boundingBox": [667,1268,808,1268,809,1506,668,1507],
              "text": "in"
            },
            {
              "boundingBox": [874,1267,1289,1265,1290,1504,875,1506],
              "text": "rising"
            },
            {
              "boundingBox": [1331,1265,1771,1263,1772,1502,1332,1504],
              "text": "every"
            },
            {
              "boundingBox": [1812, 1263, 2178, 1261, 2179, 1500, 1813, 1502],
              "text": "time"
            },
            {
              "boundingBox": [2219, 1261, 2510, 1260, 2511, 1498, 2220, 1500],
              "text": "we"
            },
            {
              "boundingBox": [2551, 1260, 3016, 1258, 3017, 1496, 2552, 1498],
              "text": "fall"
            }
          ]
        },
        {
          "boundingBox": [1612, 903, 2744, 935, 2738, 1139, 1607, 1107],
          "text": "in never failing ,",
          "words": [
            {
              "boundingBox": [1611, 934, 1707, 933, 1708, 1147, 1613, 1147],
              "text": "in"
            },
            {
              "boundingBox": [1753, 933, 2132, 930, 2133, 1144, 1754, 1146],
              "text": "never"
            },
            {
              "boundingBox": [2162, 930, 2673, 927, 2674, 1140, 2164, 1144],
              "text": "failing"
            },
            {
              "boundingBox": [2703, 926, 2788, 926, 2790, 1139, 2705, 1140],
              "text": ",",
              "confidence": "Low"
            }
          ]
        }
      ]
    }
  ]
}

清理资源Clean up resources

不再需要 Visual Studio 解决方案时,请将其删除。When no longer needed, delete the Visual Studio solution. 为此,请打开文件资源管理器,导航到在其中创建 Visual Studio 解决方案的文件夹,然后删除该文件夹。To do so, open File Explorer, navigate to the folder in which you created the Visual Studio solution, and delete the folder.

后续步骤Next steps

探索一个使用计算机视觉执行光学字符识别 (OCR) 的基本 Windows 应用程序。Explore a basic Windows application that uses Computer Vision to perform optical character recognition (OCR). 创建智能裁剪的缩略图;加上对图像中的视觉特征(包括人脸)进行检测、分类、标记和描述。Create smart-cropped thumbnails; plus detect, categorize, tag, and describe visual features, including faces, in an image.