7
9

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

GCPのCloud Vision APIを使ってみた

Last updated at Posted at 2020-05-10

前提

下記クイックスタートの「Vision APIの設定」は完了しているものとする。
クイックスタート: Vision API を設定する  |  Cloud Vision API  |  Google Cloud

やること

Vision APIの呼び出し方は大きく分けて2つあり、(本当は3つ)
1つは、クライアントライブラリと呼ばれるGCP専用のライブラリを介して呼び出す方法(GCP推奨の方法)であり、
もう1つは、既に用意されているエンドポイントからREST APIを呼び出す方法である。
今回は、クライアントライブラリからのVisionAPIの実行と、REST API経由でのVisionAPIの実行をやってみる。
開発はNodeJSで行う。

クライアントライブラリを使ってVision APIを実行する

公式の説明によると、クライアントライブラリは以下のようなものである。

クライアント ライブラリの説明  |  Cloud API  |  Google Cloud

  • Cloud API を簡単かつ直感的に使用できるように、各言語で慣用的な生成済みコードや手書きコードを提供します。
  • Google での認証など、サーバーとの通信に関する下位レベルのすべての詳細を処理します。
  • npm や pip など、使い慣れたパッケージ管理ツールを使用してインストールできます。
  • 場合によっては、gRPC を使用してパフォーマンスを高めることもできます

プロジェクトの準備

適当なディレクトリを作り、その中でnpm initを実行。
以降はこのディレクトリ配下で作業を行う。

mkdir my-app
cd my-app
npm init

注意

環境変数GOOGLE_APPLICATION_CREDENTIALSで、クイックスタートで作ったサービスアカウントキーファイルへのパスを設定しておく必要がある。

export GOOGLE_APPLICATION_CREDENTIALS=PATH_TO_KEY_FILE

クライアントライブラリのインストール

npm install --save @google-cloud/vision

実装

index.jsを作って、下記のように実装。(公式ドキュメントのサンプルをほぼコピペ)
クイックスタート: クライアント ライブラリの使用  |  Cloud Vision API  |  Google Cloud

async function quickstart() {
  // Imports the Google Cloud client library
  const vision = require("@google-cloud/vision");

  // Creates a client
  const client = new vision.ImageAnnotatorClient();

  // Performs label detection on the image file
  const [result] = await client.labelDetection("./sports.jpg");
  const labels = result.labelAnnotations;
  console.log("Labels:");
  labels.forEach((label) => console.log(label.description));
}
// これだけだとasync-awaitする必要はあまりない(なくても動く)
(async function () {
  await quickstart();
})();

上記で使用しているlabelDetectionAPIは、入力となる画像に含まれる物体、場所、活動、動物の種類、商品などを検出して、ラベルとしてアウトプットしてくれるもの。
例として、サッカー選手が真ん中に写っている画像を入力したときのアウトプットは以下のようになる。すごい。

node index.js 
Labels:
Player
Sports
Sports equipment
Football player
Team sport
Ball game
Soccer player
Soccer
Football
Tournament

REST API経由でのVision APIの呼び出し

Vision API リクエストを作成する  |  Cloud Vision API  |  Google Cloud

エンドポイント

Vision APIのエンドポイントは以下のとおり。

POST https://vision.googleapis.com/v1/images:annotate

認証の設定

REST APIの実行には、「APIキー」または「サービスアカウント」による認証が必要であるが、今回は「APIキー」による認証を採用する。
APIキーの作成は、こちらを参照。 → API キーの使用  |  認証  |  Google Cloud
APIキーを使う場合は、クエリパラメータとして渡す。

POST https://vision.googleapis.com/v1/images:annotate?key=YOUR_API_KEY

APIキーの保護

上記で作成したAPIキーは、デフォルトだと何も制限されていないため、APIキーを知っている人なら誰でもAPIが実行できる状態になっている。
いくつかの制限方法があるが、今回は自分だけ使えれば良いので、IPアドレスでの制限を設定。
https://cloud.google.com/docs/authentication/api-keys?hl=ja&visit_id=637246713360916796-291330020&rd=1#api_key_restrictions
下記のようなサイトで、自分のグローバルIPアドレスを調べて、GCPコンソール上で設定する。
念のためIPv4とIPv6のアドレス両方を許可した。(NodeJSから直接REST APIを実行する場合は、IPv4の設定だけでOKだったが、自分の環境だとブラウザを介してAPIを実行させる場合はIPv6の設定が必要だった。)
https://test-ipv6.com/index.html.ja_JP

IPアドレス制限に引っかかった場合は、以下のようなエラーレスポンスが帰ってくる。
XXX.XXX.XXX.XXXの部分に自分のIPアドレスが入っているので、もし設定がうまくいっておらず下記のようなエラーが出た場合は、XXX.XXX.XXX.XXXを許可するように設定すればOK。(XXX.XXX.XXX.XXXはIPv6の場合もある。)

{
    code: 403,
    message: 'The provided API key has an IP address restriction. The originating IP address of the call (XXX.XXX.XXX.XXX) violates this restriction.',
    status: 'PERMISSION_DENIED',
    details: [ [Object] ]
}

リクエストの形式

{
  "requests":[
    {
      "image":{
        "content":"/9j/7QBEUGhvdG9...image contents...eYxxxzj/Coa6Bax//Z"
      },
      "features":[
        {
          "type":"LABEL_DETECTION",
          "maxResults":1
        }
      ]
    }
  ]
}

image

画像の指定方法は3種類ある。

  • base64形式でimage.contentに直接指定する
  • gcpのストレージサービス Cloud Storage にあるデータのURIをimage.source.imageUriに指定する
  • HTTP または HTTPS でアクセス可能な公開URLをimage.source.imageUriに指定する(※ このパターンはDOSなどの不正利用防止のため失敗することがあるので、本番での利用は非推奨)

今回は、base64形式のパターンを試す。
Base64形式へのエンコード方法は、下記に記載がある。
Base64 エンコード  |  Cloud Vision API  |  Google Cloud

features

Feature  |  Cloud Vision API  |  Google Cloud
typeには、FACE_DETECTION LABEL_DETECTIONなど、機能に応じた文字列を指定する。
maxResultsには、上記で指定した機能で、最大何件検出を行うかを数値で指定する。

レスポンス例(ラベル検出の場合)

{
  "responses": [
    {
      "labelAnnotations": [
        {
          "mid": "/m/0bt9lr",
          "description": "dog",
          "score": 0.97346616
        },
        {
          "mid": "/m/09686",
          "description": "vertebrate",
          "score": 0.85700572
        }
      ]
    }
  ]
}

準備

APIキーの設定

環境変数にAPIキーを設定する。 export VISION_API_KEY={API_KEY}
NodeJSでは、環境変数で設定した値を、process.env["環境変数名"]で取得できる。

パッケージのインストール

リクエストを送るために、axiosをインストールする。npm i axios

実装

今回は今後あまり使わなそうなランドマーク検出を使う。

function toBase64(imagePath) {
  // Read the file into memory.
  const fs = require("fs");
  const imageFile = fs.readFileSync(imagePath);

  // Convert the image data to a Buffer and base64 encode it.
  return Buffer.from(imageFile).toString("base64");
}

(async function () {
  const axios = require("axios");

  const apiKey = process.env["VISION_API_KEY"];
  if (!apiKey) {
    console.log("Env 'VISION_API_KEY' must be set.");
    process.exit(1);
  }

  const visionApiUrl = `https://vision.googleapis.com/v1/images:annotate?key=${apiKey}`;
  const imagePath = "./liberty.jpeg";
  const options = {
    requests: [
      {
        image: {
          content: toBase64(imagePath),
        },
        features: [
          {
            type: "LANDMARK_DETECTION",
            maxResults: 3,
          },
        ],
      },
    ],
  };
  try {
    const result = await axios.post(visionApiUrl, options);
    console.log("Request success!");

    if (result.data && result.data.responses) {
      const responses = result.data.responses;
      
      responses.forEach((response) => {
        console.log("Landmarks:");
        response.landmarkAnnotations.forEach((annotation) =>
          console.log(annotation)
        );
      });
    }
  } catch (error) {
    console.error(error.response || error);
  }
})();

レスポンス

自由の女神像の写真をインプットとした場合の結果

node index.js 
Request success!
Landmarks:
{
  mid: '/m/072p8',
  description: 'Statue of Liberty National Monument',
  score: 0.790907,
  boundingPoly: { vertices: [ [Object], [Object], [Object], [Object] ] },
  locations: [ { latLng: [Object] } ]
}
{
  mid: '/m/072p8',
  description: 'Statue of Liberty',
  score: 0.77413857,
  boundingPoly: { vertices: [ [Object], [Object], [Object], [Object] ] },
  locations: [ { latLng: [Object] } ]
}
{
  mid: '/m/02nd_',
  description: 'New York City',
  score: 0.6340594,
  boundingPoly: { vertices: [ [Object], [Object], [Object], [Object] ] },
  locations: [ { latLng: [Object] } ]
}

(おまけ)Vision APIの実行回数の確認

Vision APIには、ラベル検出、テキスト検出、顔検出などの様々な種類の機能があるが、
それぞれについて、月1000回までが無料利用枠となっている。(機能によって違うが、1001回目からはだいたい$1.50[/1000回]かかる)
個人で、しかもお試しで使ってる分には1000回を超えることはないと思うが、心配だったので確認方法を探した。
料金  |  Cloud Vision API  |  Google Cloud

GCPコンソールのホームにて、
デフォルトだと画面右にある「お支払い」カードの
「→請求の詳細を表示」を押すと、
機能ごとに何回使ったかがわかる。

7
9
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
9

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?