backstage

合唱音源の新着情報の舞台裏

【Azure×Rails】アップした画像に自動タグ付けするWebアプリを作ってみた

ゴリラの画像ならば「animal」、ラーメンの画像ならば「food」iPadならば「computer」といった具合で、画像に自動でタグ付けをしてみました。

f:id:s2terminal:20170219141516p:plain:w200

マイクロソフトCognitive Servicesのうちのひとつ、Computer VisionRuby on Railsから利用することで、簡単に実現できました。

azure.microsoft.com

今回書いたソースコードGitHubに上げました。

github.com

要件

  • 画像をアップロードする
  • アップロードした画像のタグ情報を取得する
  • タグ情報をDB保存する

画像のアップロード機能

まずRailsプロジェクトを作成します。

$ rails _5.0.1_ new azure_computer_vision_on_rails
$ cd azure_computer_vision_on_rails
$ bundle install --path vendor/bundle

画像情報用のVisionテーブルと、タグ情報用のVisionTagテーブルを作成します。

$ rails generate model Vision url:string
$ rails generate model VisionTag vision_id:integer name:string confidence:float
$ rake db:migrate

Visionコントローラを定義し、「public/uploads」以下にアップロードした画像を保存していきます。

class VisionController < ApplicationController
  def index
    upload_file = params[:image]
    if upload_file != nil
      # 画像のアップロード
      @vision = Vision.create()
      filedir = "./public/uploads/visions/#{@vision.id}"
      FileUtils.mkdir_p(filedir) unless FileTest.exist?(filedir)
      filepath = "uploads/visions/#{@vision.id}/#{upload_file.original_filename}"
      File.open("./public/#{filepath}", 'wb') do |f|
        f.write(upload_file.read)
      end
      @vision.url = "#{request.url}/#{filepath}"

      @vision.save
      redirect_to :action => "show", :id => @vision.id
    end
  end

  def show
    @vision = Vision.find(params[:id])
  end
end

Viewはこんな感じです。

<%= form_tag('/', method: :post, multipart: true) do %>
  <div>
    <input type="file" name="image">
  </div>
  <input type=submit>
<% end %>

あとは下記のことをすると、画像アップローダーとしてはひとまず完成です。

  • config/routes.rbにルーティング情報を定義
  • VisionテーブルとVisionTagsテーブルにActiveRecordリレーションを定義
  • .gitignoreにアップロードバスを追記

Computer Vision APIを利用

Microsoft Cognitive ServiceのWebページに行って、「Get started for free」から「Computer Vision - Preview」を利用開始します。

www.microsoft.com

月間5,000および分間20トランザクション範囲内ならば無料で利用できます。 今回登録に必要な手順は特にありませんでしたが、MicrosoftAzureのアカウントを持っていない場合はもしかしたらここで作成が必要かもしれません。

f:id:s2terminal:20170219134135p:plain

「Key」を表示してsecrets.ymlに記載しておきます。

development:
 azure_computer_vision_api_key: XXXXXXXXXXXXXXXXXXXXXXXXXXX

Cognitive Services APIs ReferenceRubyのサンプルコードがあります。 これを参考にして、APIを叩きタグ情報を保存するコードを記述します。

      # リクエストの生成
      uri = URI('https://westus.api.cognitive.microsoft.com/vision/v1.0/analyze')
      uri.query = URI.encode_www_form({
        'visualFeatures' => 'Tags',
        'language' => 'en'
      })

      http = Net::HTTP::Post.new(uri.request_uri)
      http['Content-Type'] = 'application/json'
      http['Ocp-Apim-Subscription-Key'] = Rails.application.secrets.azure_computer_vision_api_key
      http.body = { url: @vision.url }.to_json
      response = Net::HTTP.start(uri.host, uri.port, :use_ssl => uri.scheme == 'https') do |client|
        client.request(http)
      end

      # レスポンスの加工
      json = JSON.parse(response.body)
      raise json["message"] if response.code != "200"
      json["tags"].each{|tag|
        vision_tag = @vision.vision_tags.build(name: tag["name"], confidence:tag["confidence"])
        vision_tag.save
      }

あとは、この情報を表示するViewを定義すれば完成です。

<% if @vision %>
  <img alt="<%= @vision.url %>" src="<%= @vision.url %>" class="vision_image">
  <ul>
    <% @vision.vision_tags.each do |tag| %>
      <li><%= "#{tag.name} (#{tag.confidence})" %></li>
    <% end %>
  </ul>
<% end %>

詳細はGitHubのコミットログにあります。

デプロイ

このRailsアプリケーションは、アップロードした画像(/uploads/以下)がマイクロソフトからアクセスできるような環境に配置する必要があります。localhostとかでは動作しません。

個人用途のため全IPからアクセス許可するのは嫌だったので、マイクロソフトからのアクセスに絞ります。 noindexを付けて一瞬だけ3000番ポートを全体公開し、$ rails sでアプリケーションを起動し$ netstat -ant | grep 3000$ whoisAPI使用時にアクセスが来るマイクロソフトIPアドレスを調べました。

結果、「13.104.0.0/14,13.64.0.0/11,13.96.0.0/13」に対してアクセスを許可すれば利用できるようでした。 なんか広すぎるのでもう少し絞りたいのですが、今回は特に機密な要件ではないのでこれくらいで進めます。

今回IDCFクラウド仮想マシンを使っていたので、ソースIPのファイアウォールでアクセスを許可すればOKです。

f:id:s2terminal:20170219134258p:plain

完成

試しにゴリラの画像を使ってみると

f:id:s2terminal:20170219134852p:plain:w200

「mammal(哺乳類)」「animal(動物)」「primate(霊長類)」「ape(猿)」といったタグ情報が得られました。 ズバリ「Gorilla」とは出てこなかったものの、かなりの精度で解析されていることがわかります。

また、信頼度は低いものの「close(接近している)」「staring(見つめている)」といった微妙な表現も得られました。

知らなかったのですが<input type="file">スマホから直接カメラを起動して写真をアップロードできるようなので、こんな単純なソースコードでも割とそのまま使い物になって結構面白いです。

f:id:s2terminal:20170219140706p:plain:w200

まとめ

Azure Computer Vision APIを使うことで、画像にタグ付けを簡単に実現できました。