2011年7月17日日曜日

face.comのAPIを使って、類似の顔を検索するサービスを作ってみる。

このへんで使った技術を使って、実際にサービスを作ってみる。
face.comのAPIを使って、似た顔を判別させる方法
face.comのAPIをrubyのライブラリを使って遊んでみる

今回はface.comにAKB48の顔写真DBを作り、twitterのアイコンがどれだけAK48のメンバーに似てるか、表示させます。
DBは予め登録してある前提で。

コントローラー
class IndexController < ApplicationController

def index
end

def show
  require 'face'
  require 'open-uri'
  require 'uri'
  require 'net/http'
  @entries = Array.new
  http = Net::HTTP.new( 'api.twitter.com', 80 )
  req = Net::HTTP::Get.new( "http://api.twitter.com/1/users/profile_image/#{params[:user]}.json?size=original" )
  res = http.request( req )
  img_url = URI.parse( res['location'] ).to_s

  client = Face.get_client(:api_key => '' , :api_secret => '')

  data = client.faces_recognize(:urls => img_url , :uids => 'all@akbtter')
  photos = data['photos']
  photos.each do |photo|
    photo['tags'].each do |tags|
     unless tags['uids'] == []
      confidence = tags['uids'][0]['confidence']
      uid = tags['uids'][0]['uid']
      member = Member.find_by_uid( uid )

      hash = {"name" => member.name, "confidence" => confidence }
      @entries << hash
    end
   end
  end
 end
end

ビュー
#index/index.html.erb

AKBったー


twitterのIDを入力すれば、そのユーザーのアイコンがAKBの誰に似ているか判定してくれます。

※現在は神7にのみ対応
<% form_tag :action => 'show' do %>
 <%= text_field_tag 'user' %>
 <%= submit_tag 'チェック' %>
<% end %>


#index/show.html.erb
<% unless @entries.count == 0 %>
<% @entries.each do |f| %>
<%= f["name"] %>に似ています。

似ている度:<%= f["confidence"] %>%
<% end %>
<% else %>
似ているメンバーはいません。
<% end %>

マイグレーション
class CreateMembers < ActiveRecord::Migration
 def self.up
  create_table :members do |t|
   t.string :name, :uid
   t.timestamps
  end
 end

 def self.down
  drop_table :members
 end
end

で、デザインとか整えたりすると、こんな感じのサービスになります。
http://akb.heroku.com

2011年7月16日土曜日

ralisでPC用とiPhone用のデザインを振り分ける

iPhoneからアクセスされると専用のビューを表示させるように設定する。

config/initalizes/mime_types.rbの以下の文のコメントアウトをはずす。
Mime::Type.register_alias "text/html", :iphone

動作させたいコントローラーに以下を追記

before_filter :adjust_format_for_iphone

private

def adjust_format_for_iphone
 request.format = :iphone if request_iphone?
end

public

def request_iphone?
  request.user_agent && request.user_agent[/iPhone|Android/]
end


で、専用のビューを作成する。(ここではindexというコントローラーとindexというアクション名で説明)

layouts/index.iphone.erb #iPhone用のレイアウトファイル
index/index.iphone.erb #index用のレイアウトファイル


あとはそれぞれデザインすればOK。

iPhone用のデザインはUiUIKitというのがあって、それを使うと比較的簡単に作れる。


参考
http://yusukezzz.net/blog/archives/1484
http://d.hatena.ne.jp/t-1732/20100828/1282970904

追記
androidにも対応してみました。
iPhoneと同じデザインですけど。。。
もし個別でやるなら、

private

def adjust_format_for_iphone
 request.format = :iphone if request_iphone?
 request.format = :android if request_android?
end

public

def request_iphone?
  request.user_agent && request.user_agent[/iPhone/]
end

def request_android?
   request.user_agent && request.user_agent[/Android/]
end

にして、index.android.erbですかね?
試してないのでわかりません><

2011年7月15日金曜日

face.comのAPIを使って、似た顔を判別させる方法

face.comのAPIを使うと顔を判断してくれるのですが、このときface.comのDBに似た顔があれば、それを判別して返してくれます。
具体的にどのようなことをすればいいのか日本語で説明しているサイトがなかったので、ちょっと紹介してみます。
なお書いているコードはRubyですが、基本的な流れは他の言語でも一緒です。

face.comの登録はこちらからしてください。
http://developers.face.com/signup/?g

登録したら「API Key」、「API Sercret」、「namespace」をメモっといてください。
都度使用します。
また途中「uid」が出てきますが、これは「任意のID@namespace」です。
任意のIDはどこかで定義することなく、いきなりAPIに飛ばして平気です。
またこの任意のID部分で、なんの写真か判断させますので、人物ごとにユニークなIDをふってください。

【流れ】
1:faces.detectもしくはfaces.recognizeでAPIを叩き、tags.addで使用するデータを取得。
2:1で取得した情報をもとにtags.addでタグ付け。
3:faces.trainで、2で設定したタグをface.comのDBに登録する。
4:faces.recognizeを使って写真を投げると、DBに似た顔の写真があればそのuidを返してくれます。

具体的なコードはこちらです。
登録用と似た写真を判断するようにメソッドを分けてます。

と、その前に
# sudo gem install face
でface.com用のライブラリをインストールしといてください。

require 'rubygems'
require 'face'

#APIkeyの設定
api_key = ''
api_secret = ''

#使用する画像の設定
@img_url = "http://a2.twimg.com/profile_images/1049472282/image_bigger.jpg"
@label = "篠田麻里子"

#shinoda@namespaceが帰ってきたら篠田麻里子だと判定するようDBなどに登録しておくといいんじゃない?
#uidで誰か判定させるので、人物ごとのユニークにしてください。
@uid = "shinoda@namespace"

@client = Face.get_client(:api_key => api_key , :api_secret => api_secret)

#画像の登録
def regist
 data = @client.faces_recognize(:urls => @img_url , :uids => @uid) #face.comのAPIになげる
 photos = data['photos']
 photos.each do |photo|
    photo['tags'].each do |tags|
     result = @client.tags_add(:tid => tags['tid'],
          :uid => @uid,
          :label => @label,
          :url => photo['url'],
          :x => tags['center']['x'],
          :y => tags['center']['y'],
          :width => tags['width'],
          :height => tags['height'],
          :tagger_id => tags['tagger_id']
) #帰ってきたデータをもとにタグを登録。
p result
@client.faces_train(:uids => @uid, :namespace => 'namespace') #タグ付けした情報をface.comのDBに登録。
  end
 end
end

#画像の判定時
def tag_show
 data = @client.faces_recognize(:urls => @img_url , :uids => 'all@namespace') #all@namespaceに対して投げると、namespaceに入っているデータ全部で認定してくれる。
 photos = data['photos']
 photos.each do |photo|
  photo['tags'].each do |tags|
   unless tags['uids'] == []
    puts "#{tags['uids'][0]['uid']}に#{tags['uids'][0]['confidence']}%似ています。"
   end
  end
 end
end


regist
#tag_show


all@namespaceに対してfaces.recognizeさせると、namespaceに登録してあるIDのうち、似ている画像があれば、すべて返してくれる。
投げた写真が、篠田麻里子と前田敦子に似ていた場合、shinoda@namespace,maeda@namespaceみたいな感じで返してくれます。

なお個別に似ているかどうか判断したい場合は個別のuidを指定してください。
(投げた画像が篠田麻里子にどの程度似ているか判定させたい場合、shinoda@namespace宛にfaces.recognizeさせる。
 このとき前田敦子にどれだけ似ていてもその判定はされない。)

似ているどはconfidenceの中に入ってます。

参考:http://journal.mycom.co.jp/column/tool/022/index.html