Web APIにはテキストベースのものが多いですが、中には写真や音声、動画などのバイナリデータを扱うものもあります。写真はスマートフォンとの相性も良いので、アイディア次第で様々なアプリに活用できるでしょう。
今回はそんな写真系Web APIの一つ、NTTドコモの提供する画像認識APIとMonacaアプリを組み合わせてみます。

サンプルアプリの紹介

画面はとてもシンプルです。最初はファイル選択ボックスだけが配置してあります。

写真が選択されたら、自動的に画像データを画像認識API(商品認識)に送ります。結果として商品名や購入ページのURLなどが送られてきますので、それを画面上に表示します。

事前準備

docomo Developer support | NTTドコモにてユーザ登録とアプリケーション登録を行ってください。
登録画面で利用するAPIの種類を選択しますが、ここでは「画像認識(カテゴリ認識、オブジェクト認識)」にチェックを入れてください。

登録完了後、「登録アプリケーション一覧」画面で確認できる API key が後ほど必要になります。

画面について

ベースにOnsen UIを使っています。以下はbodyタグの内容です。

<ons-page>
  <div style="padding-top:1em; text-align: center;">
    <input type="file" id="file" accept="image/*" />
    <div id="productResult">
      <div>
        <img id="productImage" style="width:90%" />
      </div>
      <div>
        選択された商品は<strong id="productName"></strong>で、
        種類は<strong id="productCategory"></strong>です。<br />
        この商品は<a id="productUrl"><strong id="productTitle"></strong></a>
        で購入できるようです。
      </div>
    </div>
  </div>
</ons-page>
<button id="submit">送信</button>
<script src="js/app.js"></script>

JavaScriptについて

JavaScriptは www/js/app.js として作成しています。
また、ライブラリにjQueryを使っています。

処理概要は次のようになります。

  • 定数の定義
  • 初期表示設定
  • ファイル選択時の処理
    • ファイルの読み込み
    • 画像認識APIの呼び出し
    • 結果の表示

では順番に紹介していきます。

定数の定義

API keyと、画像認識APIのURLを定数として定義しています。

// docomo Developer supportで得られるAPIキーを設定します
const apiKey = 'YOUR_API_KEY';
// 画像認識APIのURLを指定します
const URL = `https://api.apigw.smt.docomo.ne.jp/imageRecognition/v1/recognize?APIKEY=${apiKey}&recog=product-all&numOfCandidates=1`;

今回は認識対象を商品全般(recog=product-all)としていますが、画像認識のカテゴリ一覧を参考に商品カテゴリを指定することもできます。より認識精度を上げたい場合は、商品カテゴリを絞り込んでおくと良いでしょう。
また、取得する検索結果数(numOfCandidates)には1を指定しています。

初期表示設定

Onsen UIの ons.ready 内にアプリの初期処理を記述します。最初は結果を表示する要素を非表示にしています。

ons.ready(function() {
  // 最初は結果を表示しないようにします
  $('#productResult').hide();

  // 残りの処理はこの中に書いていきます
});

ファイル選択時の処理

ファイル選択ボックス(<input type="file">) でファイルが選択されたタイミングで、 change イベントが発生します。

$('#file').on('change', function(e) {
  // この中に処理を書いていきます

});

ファイルの読み込み

change イベントが発生したら、HTML5のFileReader APIを使って、選択された画像ファイルの読み込みを行います。ファイルが読み込まれたら onload イベントが呼ばれます。

// FileReaderを使って、選択されたファイルの内容を読み込みます
var reader = new FileReader();
// 読み込まれた後の処理です
reader.onload = function(event) {
  // 
};
// ファイルの読み込みを開始します
reader.readAsArrayBuffer(e.target.files[0]);

画像認識APIの呼び出し

onload イベントの引数には画像ファイルのバイナリデータ(ArrayBuffer)が渡されますので、それを画像認識APIに送ります。
画像認識APIの仕様を見ると分かりますが、リクエストボディに画像ファイルのバイナリデータを埋め込んで送信するようになっています。またコンテンツタイプを application/octet-stream にする必要があります。

画像認識APIの実行結果は then メソッドに返ってきます。

reader.onload = function(event) {
  // docomoの画像認識APIを呼び出します
  // ファイルの内容をそのまま適用します
  const data = event.target.result;
  $.ajax({
    type: 'POST',
    url: URL,
    contentType: 'application/octet-stream',
    processData: false,
    data: data
  })
  .then(function(res) {
    // 結果が得られたら表示処理を行います
  });
};

結果の表示

結果が返ってきたら、それを画面上に表示します。
レスポンスの内容については画像認識APIの仕様書を参考にしてください。

// 結果が得られたら表示処理を行います
const obj = res.candidates[0];
$('#productImage').attr('src', obj.imageUrl);
$('#productName').text(obj.detail.itemName);
$('#productCategory').text(obj.category);
$('#productTitle').text(obj.sites[0].title);
$('#productUrl').attr('href', obj.sites[0].url);
// 最後に結果を表示します
$('#productResult').show();

JavaScript全体像

ソースコード全文は次のようになります。

// docomo Developer supportで得られるAPIキーを設定します
const apiKey = 'YOUR_API_KEY';
// 画像認識APIのURLを指定します
const URL = `https://api.apigw.smt.docomo.ne.jp/imageRecognition/v1/recognize?APIKEY=${apiKey}&recog=product-all&numOfCandidates=1`;

ons.ready(function() {
  // 最初は結果を表示しないようにします
  $('#productResult').hide();

  // ファイルが選択されたら処理を開始します
  $('#file').on('change', function(e) {
    // FileReaderを使って、選択されたファイルの内容を読み込みます
    var reader = new FileReader();
    // 読み込まれた後の処理です
    reader.onload = function(event) {
      // docomoの画像認識APIを呼び出します
      // ファイルの内容をそのまま適用します
      const data = event.target.result;
      $.ajax({
        type: 'POST',
        url: URL,
        contentType: 'application/octet-stream',
        processData: false,
        data: data
      })
      .then(function(res) {
        // 結果が得られたら表示処理を行います
        const obj = res.candidates[0];
        $('#productImage').attr('src', obj.imageUrl);
        $('#productName').text(obj.detail.itemName);
        $('#productCategory').text(obj.category);
        $('#productTitle').text(obj.sites[0].title);
        $('#productUrl').attr('href', obj.sites[0].url);
        // 最後に結果を表示します
        $('#productResult').show();
      });
    };
    // ファイルの読み込みを開始します
    reader.readAsArrayBuffer(e.target.files[0]);
  });
});

今回のプロジェクトはこちらのURLを使ってダイレクトインポートできます。
また、ソースコードはgoofmint/Monaca_Docomo_Image_Recognize_Demoにアップロードしてありますので実装時の参考にしてください。

バイナリを扱うWeb APIとしてはFormDataを使うことが多いですが、こちらのWeb APIは異なる方法になっています。このような方法も覚えておくと、役立つ場面がありそうです。