[C#] Cognitive Servicesで光学文字認識(Computer Vision API OCR)

Cloud Application Engineerの内海です。

今回はMicrosoft AzureのCognitive Servicesの中から光学文字認識が可能なComputer Vision APIを使って、画像内の文字認識を行ってみたいと思います。


REST APIへアクセスするために必要なもの

REST APIへのアクセスのためにSubscription keyが必要になります。

1.下記サイトの『Request new trials』より『Computer Vision – Preview』を作成
https://www.microsoft.com/cognitive-services/en-US/subscriptions

2.作成されたSubscriptionよりKeyを取得
(下記画面のShowを押下でKeyが可視化されます。)
computervisonapi1


今回サムネイル作成に利用する画像ファイル

以下の3点を満たしている必要があります。
・ 対応しているファイル形式はJPEGとPNG、GIF、BMP
・ ファイルサイズは4MB以下
・ ピクセル単位で50×50以上必要


REST APIへのアクセス手順

光学文字認識を行いたいを行いたい画像ファイルをHTTPリクエストでPOSTしましょう。

レスポンスとして画像に写っている文字の認識結果がテキストとしてjsonで返ってきます。

POST先アドレスは以下のものになります。

https://api.projectoxford.ai/vision/v1.0/ocr

さらに、POST先アドレスにパラメータを仕込みます。

Key Value
language 解析する言語を指定
“unk”に設定することで自動検出
IETFのBCP47で言語指定も可能
公式リファレンスでは日本語は”Ja”と書かれているが”ja”じゃないと400番レスポンスが返ってくる。
detectOrientation 文字の向きを検出、”true”でOK

リクエストヘッダーは以下を設定しておきましょう。

Key Value
Content-Type 以下の3タイプの内から選択
どこかにアップロードした画像の場合
“application/json”
ローカル上の画像を送るなら以下のどちらか
“application/octet-stream”
“multipart/form-data”
Ocp-Apim-Subscription-Key 取得したSubscription Key

今回はローカル上のファイルを送るため、
リクエストボディには画像ファイルをByte配列として書き込みましょう。
画像ファイルのByte配列化はC#ならこんな感じ

var fs = new FileStream(/*ローカル上の画像ファイルパス*/, FileMode.Open, FileAccess.Read);
var byteData = new byte[fs.Length];
fs.Read(byteData, 0, byteData.Length);
fs.Close();

レスポンス

リクエストパラメータに加えリクエストヘッダーとボディに間違いがなければ画像の解析結果がjsonとして返ってきます。
下記は英語の光学文字認識結果ですが、日本語を解析すると単語単位ではなく1字ずつ結果が返ってきます。

{
  "language": "en",
  "textAngle": -2.0000000000000338,
  "orientation": "Up",
  "regions": [
    {
      "boundingBox": "462,379,497,258",
      "lines": [
        {
          "boundingBox": "462,379,497,74",
          "words": [
            {
              "boundingBox": "462,379,41,73",
              "text": "A"
            },
            {
              "boundingBox": "523,379,153,73",
              "text": "GOAL"
            },
            {
              "boundingBox": "694,379,265,74",
              "text": "WITHOUT"
            }
          ]
        },
        {
          "boundingBox": "565,471,289,74",
          "words": [
            {
              "boundingBox": "565,471,41,73",
              "text": "A"
            },
            {
              "boundingBox": "626,471,150,73",
              "text": "PLAN"
            },
            {
              "boundingBox": "801,472,53,73",
              "text": "IS"
            }
          ]
        },
        {
          "boundingBox": "519,563,375,74",
          "words": [
            {
              "boundingBox": "519,563,149,74",
              "text": "JUST"
            },
            {
              "boundingBox": "683,564,41,72",
              "text": "A"
            },
            {
              "boundingBox": "741,564,153,73",
              "text": "WISH"
            }
          ]
        }
      ]
    }
  ]
}

サンプルコード

サンプルコードを載せておきます。

公式リファレンスに載っているサンプルコードにローカル上の画像ファイルのPOST処理、レスポンスボディをコンソール上に書き出す処理を加えたものになります。

using System;
using System.IO;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Web;

namespace Computer_Vision_API
{
    class Program
    {
        static void Main(string[] args)
        {
            string filename = /*ファイルパス*/;
            OCR(filename);
            Console.ReadLine();
        }
        static async void OCR(string fname)
        {
            var client = new HttpClient();
            var queryString = HttpUtility.ParseQueryString(string.Empty);

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

            // Request parameters
            queryString["language"] = "ja";
            queryString["detectOrientation "] = "true";
            var uri = "https://api.projectoxford.ai/vision/v1.0/ocr?" + queryString;
            
            HttpResponseMessage response;

            using (var fs = new FileStream(fname, FileMode.Open, FileAccess.Read))
            {
                var byteData = new byte[fs.Length];
                fs.Read(byteData, 0, byteData.Length);
                using (var content = new ByteArrayContent(byteData))
                {
                    content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
                    response = await client.PostAsync(uri, content);
                    var responseBody = await response.Content.ReadAsStringAsync();
                    Console.WriteLine(responseBody);
                }
            }
        }
    }
}