こんにちわmatsunagaです。 今回はRubyからGoole Vision APIを使って画像認識する方法を紹介します。

Google Vision APIとは

Google Vision APIとは、Google Cloud Platform(GCP)が提供する機械学習サービスの一種で、画像に関する様々な情報をAPI経由で取得することができます。
https://cloud.google.com/vision/

現状、以下の機能が提供されています。

機能一覧:

  • LABEL_DETECTION: label検出。画像に何が写っているかを判定。
  • TEXT_DETECTION: 画像向けテキスト抽出。
  • DOCUMENT_TEXT_DETECTION: 文章向けテキスト抽出。
  • SAFE_SEARCH_DETECTION : 性的、暴力判定。
  • FACE_DETECTION : 顔のパーツ判定。顔の各パーツの位置や感情などを判定。
  • LANDMARK_DETECTION: ランドマーク判定。
  • LOGO_DETECTION: 企業ロゴ判定。
  • IMAGE_PROPERTIES: 画像の色。
  • WEB_DETECTION: 似た画像をwebから検索。
  • CROP_HINTS : クロップ領域の判定。

料金

Vsion APIはリクエスト単位で課金がされます。

  • 1000ユニットあたり(1,001~5,000,000 ユニット): $1.50
  • 1000ユニットあたり(5,000,000~ ユニット): $0.60

※WEB_DETECTIONは1000ユニットあたり $3.50
※ユニットの単位について
1機能1リクエストあたりで1ユニット
1度に2機能を使用した場合は2ユニットになる。

準備

Google Cloud Platform のアカウントを作成して、API KEYを取得する必要があります。
取得方法は以下を参照してください。
https://cloud.google.com/vision/docs/common/auth

RubyからVision APIを叩く

Net::HTTPでリクエストAPIを叩きます。
paramsにリクエスト内容を記述します。imagesのcontentに判定したい画像のurlをセットします。
features内のtypeに使用したい機能名を記述します。
下の例だと、ラベル検出・顔検出・画像の色検出・ロゴ検出を使用しています。

#環境変数にAPI KEYをセットする
URL = "https://vision.googleapis.com/v1/images:annotate?key=#{ENV['DO_GOOGLE_VISION_API_KEY']}"
#Net::HTTPでAPIへリクエストを発行する
uri           = URI.parse(URL)
https         = Net::HTTP.new(uri.host, uri.port)
https.use_ssl = true

#リクエストにパラメーターをセットする
  req                 = Net::HTTP::Post.new(uri.request_uri)
  req["Content-Type"] = "application/json"
  param               = {
    "requests" =>
    [
      {
        "image" =>
        {
          "content" => Base64.strict_encode64(open(filepass).read) #画像のfilepassを入れる
        },
        "features" =>
        [
          {
            "type"       => "LABEL_DETECTION"
          },
          {
            "type"       => "FACE_DETECTION"
          },
          {
            "type"       => "IMAGE_PROPERTIES"
          },
          {
            "type"       => "LOGO_DETECTION"
          }
        ]
      }
    ]
  }
  req.body = param.to_json
  res      = https.request(req)
  res.body

レスポンス

それは、猫の画像をAPIに投げてみしょう。。(かわいいですね)
猫

すると、判定結果がJSONでレスポンスされます。

 {
    "responses": [
        {
            "labelAnnotations": [
                {
                    "mid": "/m/01yrx",
                    "description": "cat",
                    "score": 0.9939052,
                    "topicality": 0.9939052
                },
                {
                    "mid": "/m/04rky",
                    "description": "mammal",
                    "score": 0.9226668,
                    "topicality": 0.9226668
                },
                {
                    "mid": "/m/07k6w8",
                    "description": "small to medium sized cats",
                    "score": 0.91960067,
                    "topicality": 0.91960067
                },
                {
                    "mid": "/m/01l7qd",
                    "description": "whiskers",
                    "score": 0.89686733,
                    "topicality": 0.89686733
                },
                {
                    "mid": "/m/0307l",
                    "description": "cat like mammal",
                    "score": 0.8726799,
                    "topicality": 0.8726799
                },
                {
                    "mid": "/m/035qhg",
                    "description": "fauna",
                    "score": 0.86749864,
                    "topicality": 0.86749864
                },
                {
                    "mid": "/m/014sv8",
                    "description": "eye",
                    "score": 0.77095574,
                    "topicality": 0.77095574
                },
                {
                    "mid": "/m/012c9l",
                    "description": "domestic short haired cat",
                    "score": 0.7379063,
                    "topicality": 0.7379063
                },
                {
                    "mid": "/m/0cnmr",
                    "description": "fur",
                    "score": 0.65897423,
                    "topicality": 0.65897423
                },
                {
                    "mid": "/m/04y7lg1",
                    "description": "dragon li",
                    "score": 0.65716416,
                    "topicality": 0.65716416
                }
            ],
            "imagePropertiesAnnotation": {
                "dominantColors": {
                    "colors": [
                        {
                            "color": {
                                "red": 65,
                                "green": 46,
                                "blue": 29
                            },
                            "score": 0.2731936,
                            "pixelFraction": 0.1411111
                        },
                        {
                            "color": {
                                "red": 32,
                                "green": 22,
                                "blue": 18
                            },
                            "score": 0.1408783,
                            "pixelFraction": 0.10468254
                        },
                        {
                            "color": {
                                "red": 237,
                                "green": 230,
                                "blue": 230
                            },
                            "score": 0.06869607,
                            "pixelFraction": 0.06722222
                        },
                        {
                            "color": {
                                "red": 97,
                                "green": 76,
                                "blue": 58
                            },
                            "score": 0.09530489,
                            "pixelFraction": 0.059603173
                        },
                        {
                            "color": {
                                "red": 58,
                                "green": 45,
                                "blue": 39
                            },
                            "score": 0.068939924,
                            "pixelFraction": 0.04436508
                        },
                        {
                            "color": {
                                "red": 77,
                                "green": 49,
                                "blue": 26
                            },
                            "score": 0.051510073,
                            "pixelFraction": 0.029920636
                        },
                        {
                            "color": {
                                "red": 97,
                                "green": 81,
                                "blue": 77
                            },
                            "score": 0.04886782,
                            "pixelFraction": 0.03373016
                        },
                        {
                            "color": {
                                "red": 45,
                                "green": 29,
                                "blue": 18
                            },
                            "score": 0.045259394,
                            "pixelFraction": 0.02111111
                        },
                        {
                            "color": {
                                "red": 132,
                                "green": 110,
                                "blue": 93
                            },
                            "score": 0.028106848,
                            "pixelFraction": 0.022619048
                        },
                        {
                            "color": {
                                "red": 102,
                                "green": 72,
                                "blue": 50
                            },
                            "score": 0.025004687,
                            "pixelFraction": 0.022936508
                        }
                    ]
                }
            },
            "cropHintsAnnotation": {
                "cropHints": [
                    {
                        "boundingPoly": {
                            "vertices": [
                                {},
                                {
                                    "x": 1599
                                },
                                {
                                    "x": 1599,
                                    "y": 899
                                },
                                {
                                    "y": 899
                                }
                            ]
                        },
                        "confidence": 0.79999995,
                        "importanceFraction": 1
                    }
                ]
            }
        }
    ]
}

上記のレスポンスを見てみると、

       {
          "mid": "/m/01yrx",
          "description": "cat",
          "score": 0.9939052,
          "topicality": 0.9939052
      },

とあるので、猫が写っていることを判定できているのがわかります。すごいですね〜。
レスポンスされる要素は機能ごとに異なるので、詳しくはAPIの公式確認してみてください!  
https://cloud.google.com/vision/docs/apis?hl=ja

まとめ

このようにGoogle Vision APIを使うと誰でも簡単に画像認識を使うことができます。
GCPには無料枠があり、お試しで使う分には無料で使用できますので安心です!