Google Cloud Vision API を使った

やりたかったこと

Cloud Vision API を使って、Label とか 色検知をしてほしいといわれて、試したことメモ

cloud.google.com

やってみた

まずtutorial を読みながら実行してみた。

最初に、サービスアカウントキーをJSONで作成して、localにダウンロードして、環境変数に登録。

$ export GOOGLE_APPLICATION_CREDENTIALS=keyfile.json

その後、こんな感じでアクセスしたらできた。

'use strict';

const vision = require('@google-cloud/vision');
const sleep = require('sleep');

async function start() {
  const res = ['https://hoge1.jpg', 'https://hoge2.jpg']

  const client = new vision.ImageAnnotatorClient();
  (async () => {
     for(let i = 0; i < res.length; i++) {
       const url = res[i];

       const [result] = await client.labelDetection(url);
       if (result.error) {
         console.log(result.error.message);
         throw 'Error';
       }
       const results = result.labelAnnotations;
       console.log('result: ', results.length);
       await results.forEach(async result => {
          console.log(result);
       });

      sleep.msleep(100); # 一応API制限あるので控えめに...
    }
  })();
}

start();

labelDetectionlabelAnnotationsってところを、imageProperties とかに変えたら、色の検知もできる。

S3のURLを使って試してみた

画像は、S3にあるので、S3のURLを渡してCloud Visition API を動かしていたら、

We can not access the URL currently. Please download the content and pass it in.

というエラーがたまに発生した。

下のURLによると、S3から拒否されちゃったのが原因らしかった。

Vision 'detect' not returning values from remote url since 0.90.0 · Issue #270 · googleapis/nodejs-vision · GitHub

ということで、諦めてlocal PCに全部DLしちゃってやることにした。

画像をDLして試してみた

画像を全部DL

'use strict';

const https = require("https");
const fs = require('fs');

async function start() {
  (async () => {
    const res = ['https://hoge1.jpg', 'https://hoge2.jpg'];
    for(let i = 0; i < res.length; i++) {

      const url = res[i];
      const filename = `hoge${i+1}.jpg`;

   # 今思えばなぜ並列でやってないのだろうか
      await new Promise(function (resolve, reject) {
        const file = fs.createWriteStream(`/Users/username/photos/${filename}`);
        https.get(url, function(response) {
          response.pipe(file);
          resolve()
        });
      });
    }
  })();
}

start();

そしてAPI実行!

# これを
const url = 'https://hoge1.jpg';
const [result] = await client.labelDetection(url);

# これに変更
const path = '/Users/username/photos/hoge1.jpg';
const [result] = await client.labelDetection(path);

問題なくできた

google cloud storage でもやってみた

どうせなので、google cloud storage でもやってみようと思った

localからcloud storageへ

'use strict';

const { Storage } = require('@google-cloud/storage');

const storage = new Storage({
  projectId: '',
  keyFilename: 'keyfile.json'
});

async function start() {
  (async () => {
    for(let i = 0; i < 2; i++) {
      const filename = `hoge${i+1}.jpg`;
      await storage
        .bucket('vision_api_storage')
        .upload(`/Users/user_name/photos/${filename}`, {gzip: true})
         .catch(err => {
          console.error('ERROR:', err);
        });
    }
  })();
}

start();

とすると、 "message":"Bad image data."

というエラーが...

gzip 圧縮しちゃってた...gzip 外せばOK!

そしてAPI実行!

# これを
const url = 'https://hoge1.jpg';
const [result] = await client.labelDetection(url);

# これに変更
const path = 'gs://vision_api_storage/hoge1.jpg';
const [result] = await client.labelDetection(path);

問題なくできた