facer 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source :rubygems
2
+ gemspec
3
+ gem 'multipart-post'
data/Manifest.txt ADDED
File without changes
data/README ADDED
@@ -0,0 +1,41 @@
1
+ This Gem is a very alpha version and is provided as is without any warranty.
2
+
3
+ I coded it as a convenient and easy interface to face.com's API for a project I'm working on and I must prepone some assumption on using it:
4
+
5
+ - you are a brave
6
+ - you will send images with only ONE recognizable face at time
7
+ - you expect some errors and bugs and have the bravery and patience to fix them
8
+
9
+ If those requirements are met, go on and use it. If not stop reading and trash the gem...
10
+
11
+ If you are reading this you are brave (or crazy).
12
+
13
+ A little example of usage:
14
+
15
+ linkr=Facer::Linker.new("yourapp","yourkey","yoursecret")
16
+ puts linkr.account.private_namespaces?.inspect
17
+ puts linkr.account.limits?.inspect
18
+
19
+ trainSet={
20
+ "vanessa_paradis" => [
21
+ "http://www.superiorpics.com/hs/vanessa_paradis/main1.jpg",
22
+ "http://nymag.com/daily/fashion/14_paradis_lgl.jpg",
23
+ "http://imstars.aufeminin.com/stars/fan/vanessa-paradis/vanessa-paradis-20060208-107457.jpg",
24
+ "http://www.realbeauty.com/cm/realbeauty/images/NF/rby-hair-vanessa-paradis-5-de.jpg",
25
+ "http://www.wallpaperweb.org/wallpaper/babes/1280x960/vanessa_paradis_20070722_0171_1280x960.jpg",
26
+ "http://chansons-fle.wikispaces.com/file/view/vanessa_paradis_reference.jpg/59524266/vanessa_paradis_reference.jpg"
27
+ ]
28
+ }
29
+
30
+ trainSet.each_pair do |key,value|
31
+ succ= linkr.faces.associate_multi(value,key,"yournamespace").inspect
32
+ puts "Associating #{key}: #{succ}"
33
+ end
34
+
35
+ puts linkr.faces.train_all("clinik").inspect
36
+
37
+ puts linkr.faces.recognize("http://static1.purepeople.com/articles/7/17/12/7/@/85769-vanessa-paradis-et-johnny-depp-637x0-1.jpg","yournamespace").inspect
38
+ puts linkr.faces.recognize("http://howzar.com/Galleries/Vanessa%20Paradis/vanessa-paradis-32.jpg","yournamespace").inspect
39
+ puts linkr.faces.recognize("http://pictures.directnews.co.uk/liveimages/Old+man+smiling_1500_19112072_0_0_7006461_300.jpg","yournamespace").inspect
40
+
41
+ Stefano Valicchia (stefano.valicchia@gmail.com)
data/init.rb ADDED
@@ -0,0 +1 @@
1
+ require File.dirname(__FILE__) + '/lib/facer'
data/lib/facer.rb ADDED
@@ -0,0 +1,25 @@
1
+ #!/usr/bin/env ruby
2
+ $LOAD_PATH << './lib/facer'
3
+ require 'rubygems'
4
+ gem 'multipart-post'
5
+
6
+ require "net/http"
7
+ require "net/http/post/multipart"
8
+ require 'mime/types'
9
+ require "uri"
10
+ require "json"
11
+
12
+ require "linker"
13
+ require "namespace"
14
+ require "account"
15
+ require "faces"
16
+
17
+ # This class manage basilar operations on face.com.
18
+ # It's very alpha so you will find a very basical subset
19
+ # to use face.com services
20
+ # Author:: Stefano Valicchia (mailto:stefano.valicchiagmail.com)
21
+ # Copyright:: Copyright (c) 2002 Giano
22
+ # License:: Distributes under the same terms as Ruby
23
+ module Facer
24
+ VERSION = "0.0.3"
25
+ end
@@ -0,0 +1,54 @@
1
+ module Facer
2
+ # Base class to store security informations and obtain infos on the account
3
+ class Account
4
+ attr_reader :applicationName
5
+ attr_reader :apiKey
6
+ attr_reader :apiSecret
7
+
8
+ # Initialize the class passing a convenient linker reference
9
+ def initialize(linker, app_name,api_key,api_secret)
10
+ @linker=linker
11
+ @applicationName=applicationName
12
+ @apiKey=key
13
+ @apiSecret=secret
14
+ end
15
+
16
+ # Obtain all account's accessible namespaces
17
+ def namespaces?
18
+ t_namespaces=@linker.call("account","namespaces")
19
+ if(t_namespaces["status"].to_sym == :success)
20
+ out={}
21
+ t_namespaces["namespaces"].each do |namespace|
22
+ nm=Namespace.new(@linker,namespace["name"],namespace["size"],namespace["share_mode"].to_sym,namespace["owner"])
23
+ out[nm.name]=nm
24
+ end
25
+ return out
26
+ else
27
+ return {}
28
+ end
29
+ end
30
+
31
+ # Obtain all the namespaces owned by the account owner (public and private)
32
+ def owned_namespaces?
33
+ namespaces?.reject {|key,value| !value.owner}
34
+ end
35
+
36
+ # Obtain all account's private namespaces
37
+ def private_namespaces?
38
+ owned_namespaces?.reject {|key,value| value.shareMode!=:Private}
39
+ end
40
+
41
+ # Retrieve informations about current account's limits
42
+ def limits?
43
+ out=@linker.call("account","limits")
44
+ if(out["status"].to_sym == :success)
45
+ return out["usage"]
46
+ else
47
+ return nil
48
+ end
49
+ end
50
+
51
+ private
52
+ attr_accessor :linker
53
+ end
54
+ end
@@ -0,0 +1,107 @@
1
+ module Facer
2
+ # Base class to query the api on faces and tags info
3
+ # All the queries are in the "simplest form" of a single image/single user query
4
+ # In this version of the gem I assume to use "single face" images
5
+ # You can provide images as a file path or a public url, the library will treat them accordingly
6
+ class Faces
7
+ # Initialize the class passing a convenient linker reference
8
+ def initialize(linker)
9
+ @linker=linker
10
+ end
11
+
12
+ # Detect if the provided image contains a face and, if yes, return face's informations
13
+ def detect(image,detector = :Normal)
14
+ ret={}
15
+ if(URI.parse(image).is_a?(URI::HTTP))
16
+ ret=@linker.call("faces","detect",{"urls" => image, "detector" => detector.to_s})
17
+ else
18
+ ret=@linker.call("faces","detect",{"detector" => detector.to_s},{"upload" => image})
19
+ end
20
+ if(ret["status"].to_sym == :success && ret["photos"].length == 1)
21
+ return ret["photos"][0]
22
+ end
23
+ return nil
24
+ end
25
+
26
+ # Force train a user against the images/tags library
27
+ def train(user,namespace)
28
+ ret=@linker.call("faces","train",{"uids" => "#{user}@#{namespace}"})
29
+ return ret["status"].to_sym == :success
30
+ end
31
+
32
+ # Force train all users in a namespace (veeeery long operation)
33
+ def train_all(namespace)
34
+ namespaces=@linker.account.private_namespaces?
35
+ if(!namespaces || !namespaces[namespace])
36
+ return false
37
+ end
38
+ users=namespaces[namespace].users?
39
+ success=true
40
+ users.each do |user|
41
+ success &= train(user,namespace)
42
+ end
43
+ return success
44
+ end
45
+
46
+ # Attempt to recognize a user in a image end, if so, provide user and face infos
47
+ def recognize(image,namespace,users = "",detector = :Normal)
48
+ if(users.empty?)
49
+ users="all@#{namespace}"
50
+ end
51
+ ret={}
52
+ if(URI.parse(image).is_a?(URI::HTTP))
53
+ ret=@linker.call("faces","recognize",{"urls" => image, "uids" => users, "detector" => detector.to_s, "namespace" => namespace})
54
+ else
55
+ ret=@linker.call("faces","recognize",{"uids" => users, "detector" => detector.to_s, "namespace" => namespace},{"upload" => image})
56
+ end
57
+ if(ret["status"].to_sym == :success && ret["photos"].length == 1)
58
+ img=ret["photos"][0]
59
+ if(img["tags"].length == 1)
60
+ tag=img["tags"][0]
61
+ if(tag["uids"] && tag["uids"].length>0)
62
+ return tag["uids"][0]
63
+ else
64
+ return {"confidence" => 0, "uid" => nil}
65
+ end
66
+ else
67
+ return {"confidence" => -1, "uid" => nil}
68
+ end
69
+ end
70
+ return nil
71
+ end
72
+
73
+ # Associace many images to a user. I assume every images contains a single face
74
+ def associate_multi(images,user,namespace, force_train = false, detector = :Normal)
75
+ success=true
76
+ images.each do |image|
77
+ success &= associate(image,user,namespace,false,detector)
78
+ end
79
+ if(success && force_train)
80
+ return train(user,namespace)
81
+ end
82
+ return success
83
+ end
84
+
85
+ # Associace a face image to a user. I assume the image contains a single face
86
+ def associate(image,user,namespace, force_train = false, detector = :Normal)
87
+ img=detect(image,detector)
88
+ if(img && img["tags"].length == 1)
89
+ tag=img["tags"][0]
90
+ if(tag["attributes"]["face"] && tag["attributes"]["face"]["value"].to_s == "true")
91
+ tid=tag["tid"]
92
+ ret=@linker.call("tags","save",{"tids" => tid, "uid" => "#{user}@#{namespace}"})
93
+ if(ret["status"].to_sym == :success)
94
+ if(force_train)
95
+ return train(user,namespace)
96
+ end
97
+ return true
98
+ end
99
+ end
100
+ end
101
+ return false
102
+ end
103
+
104
+ private
105
+ attr_accessor :linker
106
+ end
107
+ end
@@ -0,0 +1,40 @@
1
+ module Facer
2
+ # Base class to store informations and obtain infos on the namespace
3
+ class Namespace
4
+ attr_reader :name
5
+ attr_reader :size
6
+ attr_reader :shareMode
7
+ attr_reader :owner
8
+
9
+ # Initialize the class passing a convenient linker reference and infos about the namespace
10
+ def initialize(linker,name,size,shareMode,owner)
11
+ @linker=linker
12
+ @name=name
13
+ @size=size
14
+ @shareMode=shareMode
15
+ @owner=owner
16
+ end
17
+
18
+ # Retrieve namespace's user list
19
+ def users?
20
+ if(@owner && @shareMode==:Private)
21
+ t_users=@linker.call("account","users",{"namespaces" => @name})
22
+ out=[]
23
+ if(t_users["status"].to_sym == :success)
24
+ t_users["users"].each_pair do |key,namespace_users|
25
+ out+=namespace_users
26
+ end
27
+ return out
28
+ else
29
+ return []
30
+ end
31
+ else
32
+ return []
33
+ end
34
+ namespaces?.reject {|key,value| !value.owner}
35
+ end
36
+
37
+ private
38
+ attr_accessor :linker
39
+ end
40
+ end
data/lib/linker.rb ADDED
@@ -0,0 +1,52 @@
1
+ require "net/http"
2
+ require "net/http/post/multipart"
3
+ require 'mime/types'
4
+ require "uri"
5
+ require "json"
6
+ module Facer
7
+
8
+ # This class hold the main linkage to face.com
9
+ # acting as a gateway to subclasses
10
+ class Linker
11
+ # The main uri to face.com api.
12
+ FaceComURI="http://api.face.com/"
13
+
14
+ attr_reader :account
15
+ attr_reader :faces
16
+
17
+ # Initialize the linker with security informations
18
+ def initialize(applicationName,key,secret)
19
+ @account=Account.new(self,applicationName,key,secret)
20
+ @faces=Faces.new(self)
21
+ end
22
+
23
+ # Call the service appending security informations to every request
24
+ def call(bclass,method,params = {},files = nil)
25
+ params ||={}
26
+ params["api_key"]=@account.apiKey
27
+ params["api_secret"]=@account.apiSecret
28
+ resp=callAPI(bclass,method,params,files)
29
+ return resp
30
+ end
31
+
32
+ private
33
+ # Call the service using post or multiform data for sending files and transpose to json the response
34
+ def callAPI(bclass,method,params,files)
35
+ uri=URI.parse("#{FaceComURI}#{bclass}/#{method}.json")
36
+ params ||= {}
37
+ if(files)
38
+ files.each_pair do |name,path|
39
+ params[name]=UploadIO.new(path, MIME::Types.type_for(path))
40
+ end
41
+ req = Net::HTTP::Post::Multipart.new(uri.path,params)
42
+ res = Net::HTTP.start(uri.host, uri.port) do |http|
43
+ http.request(req)
44
+ end
45
+ return JSON.parse(res.body)
46
+ else
47
+ res = Net::HTTP.post_form(uri,params)
48
+ return JSON.parse(res.body)
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,8 @@
1
+ require 'test/unit'
2
+
3
+ class MimetypeFuTest < Test::Unit::TestCase
4
+ # Replace this with your real tests.
5
+ def test_this_plugin
6
+ flunk
7
+ end
8
+ end
metadata ADDED
@@ -0,0 +1,110 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: facer
3
+ version: !ruby/object:Gem::Version
4
+ hash: 25
5
+ prerelease:
6
+ segments:
7
+ - 0
8
+ - 0
9
+ - 3
10
+ version: 0.0.3
11
+ platform: ruby
12
+ authors:
13
+ - Stefano Valicchia
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2011-01-11 00:00:00 +01:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: multipart-post
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ hash: 21
30
+ segments:
31
+ - 1
32
+ - 0
33
+ - 1
34
+ version: 1.0.1
35
+ type: :runtime
36
+ version_requirements: *id001
37
+ - !ruby/object:Gem::Dependency
38
+ name: json
39
+ prerelease: false
40
+ requirement: &id002 !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ">="
44
+ - !ruby/object:Gem::Version
45
+ hash: 11
46
+ segments:
47
+ - 1
48
+ - 4
49
+ - 6
50
+ version: 1.4.6
51
+ type: :runtime
52
+ version_requirements: *id002
53
+ description: Simple wrapper for face.com api.
54
+ email: stefano.valicchia@gmail.com
55
+ executables: []
56
+
57
+ extensions: []
58
+
59
+ extra_rdoc_files:
60
+ - Gemfile
61
+ - Manifest.txt
62
+ - README
63
+ files:
64
+ - lib/facer/account.rb
65
+ - lib/facer/faces.rb
66
+ - lib/facer/namespace.rb
67
+ - lib/facer.rb
68
+ - lib/linker.rb
69
+ - init.rb
70
+ - Manifest.txt
71
+ - Gemfile
72
+ - README
73
+ - test/facer_test.rb
74
+ has_rdoc: true
75
+ homepage:
76
+ licenses: []
77
+
78
+ post_install_message:
79
+ rdoc_options:
80
+ - --title
81
+ - Facer
82
+ require_paths:
83
+ - lib
84
+ required_ruby_version: !ruby/object:Gem::Requirement
85
+ none: false
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ hash: 3
90
+ segments:
91
+ - 0
92
+ version: "0"
93
+ required_rubygems_version: !ruby/object:Gem::Requirement
94
+ none: false
95
+ requirements:
96
+ - - ">="
97
+ - !ruby/object:Gem::Version
98
+ hash: 3
99
+ segments:
100
+ - 0
101
+ version: "0"
102
+ requirements:
103
+ - The gem uses multipart-post gem and JSON gem
104
+ rubyforge_project:
105
+ rubygems_version: 1.4.1
106
+ signing_key:
107
+ specification_version: 3
108
+ summary: Wrapper for face.com API.
109
+ test_files:
110
+ - test/facer_test.rb