クイック スタート:Bing Visual Search REST API と C# を使用して画像に関する分析情報を取得する
警告
2020 年 10 月 30 日に、Bing Search API は Azure AI サービスから Bing Search サービスに移行されました。 このドキュメントは、参考用としてのみ提供されています。 更新されたドキュメントについては、Bing search API のドキュメントを参照してください。 Bing 検索用の新しい Azure リソースを作成する手順については、「Azure Marketplace から Bing Search リソースを作成する」を参照してください。
このクイックスタートでは、Bing Visual Search API に画像をアップロードして、返される分析情報を表示する方法を紹介します。
前提条件
- Visual Studio 2019 のいずれかのエディション。
- NuGet パッケージとして入手できる Json.NET フレームワーク。
- Linux/macOS を使用している場合、このアプリケーションは Mono を使用して実行できます。
Azure リソースを作成する
次のいずれかの Azure リソースを作成して、Bing Visual Search API の使用を開始します。
- ご自身でリソースを削除するまでは Azure portal からご利用いただけます。
-
S9
価格レベルを選択します。
- ご自身でリソースを削除するまでは Azure portal からご利用いただけます。
- 複数の Azure AI サービス全体で同じキーとエンドポイントをアプリケーションに使用します。
プロジェクトの作成と初期化
Visual Studio で、BingSearchApisQuickStart という名前の新しいコンソール ソリューションを作成します。 メイン コード ファイルに次の名前空間を追加します。
using System; using System.Text; using System.Net; using System.IO; using System.Collections.Generic;
サブスクリプション キー、エンドポイント、およびアップロードする画像へのパスを格納する変数を追加します。
uriBase
値には、次のコードのグローバル エンドポイントを使用するか、Azure portal に表示される、お使いのリソースのカスタム サブドメイン エンドポイントを使用できます。const string accessKey = "<my_subscription_key>"; const string uriBase = "https://api.cognitive.microsoft.com/bing/v7.0/images/visualsearch"; static string imagePath = @"<path_to_image>";
画像へのパスを取得するための
GetImageFileName()
という名前のメソッドを作成します。static string GetImageFileName(string path) { return new FileInfo(path).Name; }
画像のバイナリ データを取得するためのメソッドを作成します。
static byte[] GetImageBinary(string path) { return File.ReadAllBytes(path); }
フォーム データを作成する
ローカルの画像をアップロードするには、最初に、API に送信するフォーム データを作成します。 フォーム データには、
Content-Disposition
ヘッダー、"image" に設定されているname
パラメーター、画像のファイル名に設定されているfilename
パラメーターが含まれます。 フォームの内容には、画像のバイナリ データが含まれます。 アップロードできる画像の最大サイズは、1 MB です。--boundary_1234-abcd Content-Disposition: form-data; name="image"; filename="myimagefile.jpg" ÿØÿà JFIF ÖÆ68g-¤CWŸþ29ÌÄøÖ‘º«™æ±èuZiÀ)"óÓß°Î= ØJ9á+*G¦... --boundary_1234-abcd--
POST フォーム データを書式設定する境界文字列を追加します。 境界文字列により、データの開始、終了、改行文字が決まります。
// Boundary strings for form data in body of POST. const string CRLF = "\r\n"; static string BoundaryTemplate = "batch_{0}"; static string StartBoundaryTemplate = "--{0}"; static string EndBoundaryTemplate = "--{0}--";
フォーム データにパラメーターを追加するには、次の変数を使います。
const string CONTENT_TYPE_HEADER_PARAMS = "multipart/form-data; boundary={0}"; const string POST_BODY_DISPOSITION_HEADER = "Content-Disposition: form-data; name=\"image\"; filename=\"{0}\"" + CRLF +CRLF;
BuildFormDataStart()
という名前の関数を作成し、境界文字列と画像へのパスを使用して、フォーム データの開始を作成します。static string BuildFormDataStart(string boundary, string filename) { var startBoundary = string.Format(StartBoundaryTemplate, boundary); var requestBody = startBoundary + CRLF; requestBody += string.Format(POST_BODY_DISPOSITION_HEADER, filename); return requestBody; }
BuildFormDataEnd()
という名前の関数を作成し、境界文字列を使用して、フォーム データの終了を作成します。static string BuildFormDataEnd(string boundary) { return CRLF + CRLF + string.Format(EndBoundaryTemplate, boundary) + CRLF; }
Bing Visual Search API を呼び出す
Bing Visual Search エンドポイントを呼び出し、JSON 応答を返すための関数を作成します。 その関数では、フォーム データの開始と終了、画像データを含むバイト配列、および
contentType
値を受け取ります。WebRequest
使用して、URI、contentType 値、ヘッダーを格納します。request.GetRequestStream()
を使用して、フォーム データと画像データを書き込んだ後、応答を受け取ります。 関数は次のコードのようになります。static string BingImageSearch(string startFormData, string endFormData, byte[] image, string contentTypeValue) { WebRequest request = HttpWebRequest.Create(uriBase); request.ContentType = contentTypeValue; request.Headers["Ocp-Apim-Subscription-Key"] = accessKey; request.Method = "POST"; // Writes the boundary and Content-Disposition header, then writes // the image binary, and finishes by writing the closing boundary. using (Stream requestStream = request.GetRequestStream()) { StreamWriter writer = new StreamWriter(requestStream); writer.Write(startFormData); writer.Flush(); requestStream.Write(image, 0, image.Length); writer.Write(endFormData); writer.Flush(); writer.Close(); } HttpWebResponse response = (HttpWebResponse)request.GetResponseAsync().Result; string json = new StreamReader(response.GetResponseStream()).ReadToEnd(); return json; }
Main メソッドを作成する
アプリケーションの
Main()
メソッドでは、画像のファイル名とバイナリ データを取得します。var filename = GetImageFileName(imagePath); var imageBinary = GetImageBinary(imagePath);
境界を書式設定して、POST の本文を設定します。 その後、
BuildFormDataStart()
とBuildFormDataEnd()
を呼び出して、フォーム データを作成します。// Set up POST body. var boundary = string.Format(BoundaryTemplate, Guid.NewGuid()); var startFormData = BuildFormDataStart(boundary, filename); var endFormData = BuildFormDataEnd(boundary);
CONTENT_TYPE_HEADER_PARAMS
とフォーム データの境界を書式設定して、ContentType
値を作成します。var contentTypeHdrValue = string.Format(CONTENT_TYPE_HEADER_PARAMS, boundary);
BingImageSearch()
を呼び出して API の応答を取得し、応答を出力します。var json = BingImageSearch(startFormData, endFormData, imageBinary, contentTypeHdrValue); Console.WriteLine(json); Console.WriteLine("enter any key to continue"); Console.readKey();
HTTPClient の使用
HttpClient
を使用する場合は、MultipartFormDataContent
クラスを使用してフォーム データを作成できます。 次のコード セクションを使用して、前の例にある対応するメソッドを置き換えます。
Main()
メソッドを次のコードに置き換えます。static void Main() { try { Console.OutputEncoding = System.Text.Encoding.UTF8; if (accessKey.Length == 32) { if (IsImagePathSet(imagePath)) { var filename = GetImageFileName(imagePath); Console.WriteLine("Getting image insights for image: " + filename); var imageBinary = GetImageBinary(imagePath); var boundary = string.Format(BoundaryTemplate, Guid.NewGuid()); var json = BingImageSearch(imageBinary, boundary, uriBase, accessKey); Console.WriteLine("\nJSON Response:\n"); Console.WriteLine(JsonPrettyPrint(json)); } } else { Console.WriteLine("Invalid Bing Visual Search API subscription key!"); Console.WriteLine("Please paste yours into the source code."); } Console.Write("\nPress Enter to exit "); Console.ReadLine(); } catch (Exception e) { Console.WriteLine(e.Message); } }
BingImageSearch()
メソッドを次のコードに置き換えます。/// <summary> /// Calls the Bing visual search endpoint and returns the JSON response. /// </summary> static string BingImageSearch(byte[] image, string boundary, string uri, string subscriptionKey) { var requestMessage = new HttpRequestMessage(HttpMethod.Post, uri); requestMessage.Headers.Add("Ocp-Apim-Subscription-Key", accessKey); var content = new MultipartFormDataContent(boundary); content.Add(new ByteArrayContent(image), "image", "myimage"); requestMessage.Content = content; var httpClient = new HttpClient(); Task<HttpResponseMessage> httpRequest = httpClient.SendAsync(requestMessage, HttpCompletionOption.ResponseContentRead, CancellationToken.None); HttpResponseMessage httpResponse = httpRequest.Result; HttpStatusCode statusCode = httpResponse.StatusCode; HttpContent responseContent = httpResponse.Content; string json = null; if (responseContent != null) { Task<String> stringContentsTask = responseContent.ReadAsStringAsync(); json = stringContentsTask.Result; } return json; }