【Azure×Rails】アップした画像に自動タグ付けするWebアプリを作ってみた
ゴリラの画像ならば「animal」、ラーメンの画像ならば「food」、iPadならば「computer」といった具合で、画像に自動でタグ付けをしてみました。
マイクロソフトのCognitive Servicesのうちのひとつ、Computer VisionをRuby on Railsから利用することで、簡単に実現できました。
要件
- 画像をアップロードする
- アップロードした画像のタグ情報を取得する
- タグ情報を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」を利用開始します。
月間5,000および分間20トランザクション範囲内ならば無料で利用できます。 今回登録に必要な手順は特にありませんでしたが、MicrosoftAzureのアカウントを持っていない場合はもしかしたらここで作成が必要かもしれません。
「Key」を表示してsecrets.ymlに記載しておきます。
development: azure_computer_vision_api_key: XXXXXXXXXXXXXXXXXXXXXXXXXXX
Cognitive Services APIs ReferenceにRubyのサンプルコードがあります。 これを参考にして、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
と$ whois
でAPI使用時にアクセスが来るマイクロソフトのIPアドレスを調べました。
結果、「13.104.0.0/14,13.64.0.0/11,13.96.0.0/13」に対してアクセスを許可すれば利用できるようでした。 なんか広すぎるのでもう少し絞りたいのですが、今回は特に機密な要件ではないのでこれくらいで進めます。
今回IDCFクラウドの仮想マシンを使っていたので、ソースIPのファイアウォールでアクセスを許可すればOKです。
完成
試しにゴリラの画像を使ってみると
「mammal(哺乳類)」「animal(動物)」「primate(霊長類)」「ape(猿)」といったタグ情報が得られました。 ズバリ「Gorilla」とは出てこなかったものの、かなりの精度で解析されていることがわかります。
また、信頼度は低いものの「close(接近している)」「staring(見つめている)」といった微妙な表現も得られました。
知らなかったのですが<input type="file">
はスマホから直接カメラを起動して写真をアップロードできるようなので、こんな単純なソースコードでも割とそのまま使い物になって結構面白いです。
まとめ
Azure Computer Vision APIを使うことで、画像にタグ付けを簡単に実現できました。