アトラシエの開発ブログ

株式会社アトラシエのブログです

Google Cloud Vision APIを使ってみる

qiita.com

この記事が随分バズりましたが、去年後半にGoogleが画像認識APIを公開しました。 画像認識APIにはいくつか種類があって、安全な画像か(アダルトや暴力が含まれないか)を判定するAPI、画像に何が写っているか判定するAPI、画像中の文字列を解析するAPIなどがあります。

今回は画像に何が写っているかのAPI(LABEL_DETECTION)を使ってみます。

サンプルコード

class CloudVision
  class MissingError < StandardError;end

  ENDPOINT_URL = "https://vision.googleapis.com/v1alpha1/images:annotate?key=#{Settings.services.google.server_api_key}"

  attr_reader :result

  def initialize(url)
    @image_url = url
  end

  def request
    uri = URI.parse(ENDPOINT_URL)
    https = Net::HTTP.new(uri.host, uri.port)
    https.use_ssl = true

    image = open(@image_url).read
    content = Base64.strict_encode64(image)
    req = Net::HTTP::Post.new(uri.request_uri)
    req.body = request_json(content)
    req['Content-Type'] = 'application/json'

    res = https.request(req)
    if res.code.to_i == 200
      @result = JSON.parse(res.body).with_indifferent_access
    else
      raise MissingError.new('cannot fetch cloud vision result')
    end
  end

  private

  def request_json(content)
    {
      requests: [{
        image: {
          content: content
        },
        features: [{
          type: 'LABEL_DETECTION',
          maxResults: 10
        }]
      }]
    }.to_json
  end
end

APIはいくつかあるといいましたが、エンドポイントとしては一つで本文のパラメータで何のAPIを使っているかを指定しています。 このAPIはまだアルファ版なので、申請しないと使えません。が、フォームから簡単に登録できたので難しい審査があるわけではないようです。

APIキーの取得(申請後)

f:id:attracie:20160204190701p:plain

上の画面からCloud Vision APIを開き、APIを有効化する。

あとはタイプがサーバーキーのAPIキーを認証情報の中から作成。

このキーはサーバ用なので、ローカルで使う分には問題ありませんがクライアントアプリなどに組み込んで配布してはいけません。

サンプル実行

1.壁紙

f:id:attracie:20160204191103j:plain

結果

 {"responses"=>[{"labelAnnotations"=>[{"mid"=>"/m/083jv", "description"=>"white", "score"=>0.92508286}, {"mid"=>"/m/02rfdq", "description"=>"interior design", "score"=>0.829825}, {"mid"=>"/m/09qqq", "description"=>"wall", "score"=>0.77109945}, {"mid"=>"/m/03gfsp", "description"=>"ceiling", "score"=>0.57515627}, {"mid"=>"/m/06244p", "description"=>"window film", "score"=>0.57092083}, {"mid"=>"/m/03rszm", "description"=>"curtain", "score"=>0.56402957}, {"mid"=>"/m/0hwky", "description"=>"pattern", "score"=>0.52074558}]}]}

どうやらスコア度が高いものから順番に送ってくれるようです。結果は 白、インテリアデザイン、壁、天井、窓フィルム、カーテン、パターン?となりました。まぁ約0.7以上は間違ってるわけではないのでまぁまぁ。

  1. 切り株に土を盛る作業の画像

f:id:attracie:20160204191448j:plain

結果

{"responses"=>[{"labelAnnotations"=>[{"mid"=>"/m/01m3tw", "description"=>"animal shelter", "score"=>0.58235466}, {"mid"=>"/m/09qqq", "description"=>"wall", "score"=>0.53854597}]}]}

今度は動物の檻、壁という結果に。うーん、金網を檻と判断したか・・・。

  1. フローリング

f:id:attracie:20160204191642j:plain

結果

{"responses"=>[{"labelAnnotations"=>[{"mid"=>"/m/0l7_8", "description"=>"floor", "score"=>0.96207434}, {"mid"=>"/m/020g49", "description"=>"hardwood", "score"=>0.91214508}, {"mid"=>"/m/083vt", "description"=>"wood", "score"=>0.87281144}, {"mid"=>"/m/01c34b", "description"=>"flooring", "score"=>0.83906168}, {"mid"=>"/m/07j7r", "description"=>"tree", "score"=>0.74765408}, {"mid"=>"/m/0hlzt", "description"=>"deciduous", "score"=>0.6577369}, {"mid"=>"/m/05t06b", "description"=>"wood stain", "score"=>0.57129413}]}]}

床、硬材、木材、フローリング、木、落葉樹、木材着色剤

まぁだいたい合ってますね!

4. 棚

f:id:attracie:20160204191914j:plain

結果

{"responses"=>[{"labelAnnotations"=>[{"mid"=>"/m/0c_jw", "description"=>"furniture", "score"=>0.88417172}, {"mid"=>"/m/0l7_8", "description"=>"floor", "score"=>0.82036376}, {"mid"=>"/m/020g49", "description"=>"hardwood", "score"=>0.81980395}, {"mid"=>"/m/01c34b", "description"=>"flooring", "score"=>0.78891808}, {"mid"=>"/m/07p_zw", "description"=>"handrail", "score"=>0.78310829}, {"mid"=>"/m/083vt", "description"=>"wood", "score"=>0.74275166}, {"mid"=>"/m/0gjbg72", "description"=>"shelf", "score"=>0.69625175}, {"mid"=>"/m/0h8n982", "description"=>"shelving", "score"=>0.6897167}, {"mid"=>"/m/03vf67", "description"=>"sideboard", "score"=>0.61258972}]}]}

家具、床、硬木、フローリング、手すり、木、棚、サイドボード

間違ってるわけではないが、フローリングが棚より上位になっている。おそらく形状よりもテクスチャで評価されてるんだろう。(棚に貼ってあるシートだけを見るとフローリングにも見えなくもない)

  1. 蜜を吸う蜂

f:id:attracie:20160204192316j:plain

{"responses"=>[{"labelAnnotations"=>[{"mid"=>"/m/0c9ph5", "description"=>"flower", "score"=>0.90215278}, {"mid"=>"/m/016gq4", "description"=>"morus", "score"=>0.84567684}, {"mid"=>"/m/07j7r", "description"=>"tree", "score"=>0.82456774}, {"mid"=>"/m/04sjm", "description"=>"flowering plant", "score"=>0.80608088}, {"mid"=>"/m/05s2s", "description"=>"plant", "score"=>0.78441721}, {"mid"=>"/m/02xwb", "description"=>"fruit", "score"=>0.77949041}, {"mid"=>"/m/09t49", "description"=>"leaf", "score"=>0.72556472}, {"mid"=>"/m/01c2vn", "description"=>"elderberry", "score"=>0.69951051}, {"mid"=>"/m/0dxb5", "description"=>"berry", "score"=>0.69494152}, {"mid"=>"/m/084z41", "description"=>"viburnum opulus", "score"=>0.69100761}]}]}

花、クワ、木、植木、フルーツ、葉、ニワトコ

一番目立つものについて注力して分析した感じ。

  1. 家の流し

f:id:attracie:20160204192550j:plain

{"responses"=>[{"labelAnnotations"=>[{"mid"=>"/m/0130jx", "description"=>"sink", "score"=>0.78636473}, {"mid"=>"/m/07yv9", "description"=>"vehicle", "score"=>0.77838421}, {"mid"=>"/m/032rk", "description"=>"gun", "score"=>0.5884015}, {"mid"=>"/m/01kcd", "description"=>"brass instrument", "score"=>0.55859768}]}]}

シンク、乗り物、銃、金管楽器・・・。

誤判定が目立ちます。とくに少しテストした感じでは光物、金属的なものが含まれる画像はやたら乗り物(vehicle)に含まれてしまう印象でした。

6-2. 参考

別のサイトの画像です。今度は商品画像的な綺麗な写りのもの。

http://www.amick.net/hikone/setubi/KitchenSink/3821.jpg

{"responses"=>[{"labelAnnotations"=>[{"mid"=>"/m/02pkr5", "description"=>"plumbing fixture", "score"=>0.99995482}, {"mid"=>"/m/0130jx", "description"=>"sink", "score"=>0.99663955}, {"mid"=>"/m/080sjd", "description"=>"farmhouse", "score"=>0.85322839}, {"mid"=>"/m/06ht1", "description"=>"room", "score"=>0.75796545}, {"mid"=>"/m/01jwgf", "description"=>"product", "score"=>0.74807149}]}]}

今度はだいぶいいですね。当たり前ですが、amazonとかの商品画像みたいな、綺麗な画像が一番はっきり判定できます。

総評

例えばPinterestのようなサイトで、投稿画像を自動的に判定してscoreが0.8以上のものにそのままタグ付けする、というような用途ができればなぁと思いましたが、この結果を見る限り厳しいですね。 例えば記事の見出しになるような写真なら間違えないんですが、素人がぱっと撮った写真はダメな印象です。

実際問題としてはもう一段階ステップがあって、例えば想定される画像を絞って判定パターンを限定してあげる(何が写っているかより、壁なのかトイレなのか風呂なのかなどを判定するほうが確実に精度がいい)などが必要になってくるのかなと思います。