findaface 0.0.6 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +14 -13
- data/findaface.gemspec +0 -1
- data/lib/findaface.rb +30 -30
- data/lib/findaface/version.rb +2 -2
- data/report.md +18 -0
- data/spec/findaface_spec.rb +56 -40
- data/spec/photos/eye.jpg +0 -0
- data/spec/photos/face.jpg +0 -0
- data/spec/photos/fruit.jpg +0 -0
- data/spec/photos/nose.jpg +0 -0
- metadata +12 -33
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7f96dc6603d1aedf09e21aa75755408409479d85
|
4
|
+
data.tar.gz: e65f03a7a0efb180a31e35aef2fa2b29e2c47f7c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5a0c7ed26464b1130f89b5c03a57035f31a523494ea0a74b70c9a3b4a627f9e3c3f03060abde40f1b3b4a8033e524d265d264f33bf04843e2bcef2ce188542ae
|
7
|
+
data.tar.gz: 16adb61b23f56c9bb24dcacc1af8610ad92003d1debd93aa898245fb0e084214fe3af9d9c4b54721b11f09d170258f5a4c36bbac01bee065ec8b8042e9898e54
|
data/README.md
CHANGED
@@ -1,11 +1,10 @@
|
|
1
1
|
# Findaface
|
2
2
|
|
3
|
-
When given a path to a picture, this gem attempts to determins whether it contains
|
4
|
-
faces and thus might be appropriate for a profile image. It is looking for faces bigger than 80 pixels squared.
|
3
|
+
When given a path to a picture, this gem attempts to determins whether it contains any faces and thus might be appropriate for a profile image. It is looking for faces bigger than 80 pixels squared.
|
5
4
|
|
6
5
|
It is a modified then gemified version of George Ogata's [find-face](https://github.com/howaboutwe/find-face). If you want a CLI that indicates where the biggest face in an image is, then use the original.
|
7
6
|
|
8
|
-
This gem simply compiles an executable to detect a face then calls it externally, so you won't have to include the humongous OpenCV library into your Ruby process, which can cause memory
|
7
|
+
This gem simply compiles an executable to detect a face then calls it externally, so you won't have to include the humongous OpenCV library into your Ruby process, which can cause a memory leaks / bloat or even a crash. This is what [Paperclip](https://github.com/thoughtbot/paperclip) does for ImageMagick. We also support [posix-spawn](https://github.com/rtomayko/posix-spawn) to mitigate the overhead of fork-exec.
|
9
8
|
|
10
9
|
## Installation
|
11
10
|
|
@@ -52,11 +51,11 @@ $ gem install findaface
|
|
52
51
|
## Usage
|
53
52
|
|
54
53
|
```
|
55
|
-
puts Findaface.has_face?('path/to/me.jpg')
|
54
|
+
puts Findaface.new.has_face?('path/to/me.jpg')
|
56
55
|
=> true
|
57
|
-
puts Findaface.has_face?('path/to/me_in_a_group.jpg')
|
58
|
-
=>
|
59
|
-
puts Findaface.has_face?('path/to/my_cat.jpg')
|
56
|
+
puts Findaface.new.has_face?('path/to/me_in_a_group.jpg')
|
57
|
+
=> true
|
58
|
+
puts Findaface.new.has_face?('path/to/my_cat.jpg')
|
60
59
|
=> false
|
61
60
|
```
|
62
61
|
|
@@ -84,10 +83,10 @@ Basically the scale factor is used to create your scale pyramid. More explanatio
|
|
84
83
|
* max_size: Objects bigger than this are ignored.
|
85
84
|
|
86
85
|
### Using multiple cascades
|
87
|
-
If you add multiple cascades then they will be applied in turn. If any of the cascades
|
88
|
-
findaface returns true.
|
86
|
+
If you add multiple cascades then they will be applied in turn. If any of the cascades match, then findaface returns true. You should add cascades before the first call to `has_face?` (unless you also want the default cascade to be applied).
|
89
87
|
```
|
90
|
-
Findaface.
|
88
|
+
findaface = Findaface.new
|
89
|
+
findaface.add_cascade(
|
91
90
|
{
|
92
91
|
cascade:'haarcascades/haarcascade_mcs_nose.xml',
|
93
92
|
fussyness:6,
|
@@ -96,7 +95,7 @@ Findaface.add_cascade(
|
|
96
95
|
max_size: 512,
|
97
96
|
}
|
98
97
|
)
|
99
|
-
|
98
|
+
findaface.add_cascade(
|
100
99
|
{
|
101
100
|
cascade:'haarcascades/haarcascade_eye.xml',
|
102
101
|
fussyness:6,
|
@@ -106,9 +105,11 @@ Findaface.add_cascade(
|
|
106
105
|
}
|
107
106
|
)
|
108
107
|
|
109
|
-
puts
|
108
|
+
puts findaface.has_face?('path/to/nose.jpg')
|
109
|
+
=> true
|
110
|
+
puts findaface.has_face?('path/to/eye.jpg')
|
110
111
|
=> true
|
111
|
-
puts
|
112
|
+
puts findaface.has_face?('path/to/mouth.jpg')
|
112
113
|
=> false
|
113
114
|
```
|
114
115
|
|
data/findaface.gemspec
CHANGED
@@ -27,6 +27,5 @@ Gem::Specification.new do |spec|
|
|
27
27
|
spec.add_development_dependency "rspec", "~> 2.14"
|
28
28
|
spec.add_development_dependency "pry"
|
29
29
|
spec.add_development_dependency "pry-doc"
|
30
|
-
spec.add_development_dependency "pry-debugger"
|
31
30
|
spec.add_development_dependency "awesome_print"
|
32
31
|
end
|
data/lib/findaface.rb
CHANGED
@@ -1,49 +1,49 @@
|
|
1
1
|
require 'findaface/version'
|
2
2
|
require 'posix/spawn'
|
3
3
|
|
4
|
-
|
4
|
+
class Findaface
|
5
5
|
LIB_PATH = File.dirname(File.expand_path(__FILE__))
|
6
6
|
EXECUTABLE = File.join(LIB_PATH, '../ext/findaface/findaface')
|
7
7
|
DEFAULT_CASCADE = {
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
8
|
+
cascade:'haarcascades/haarcascade_frontalface_alt2.xml',
|
9
|
+
fussyness:4,
|
10
|
+
max_size: 512,
|
11
|
+
min_size: 80,
|
12
|
+
scale_factor: 1.05,
|
13
|
+
}
|
14
14
|
DEFAULT_OPTIONS = DEFAULT_CASCADE.keys
|
15
15
|
|
16
|
-
|
17
|
-
|
18
|
-
|
16
|
+
class << self
|
17
|
+
attr_reader :cascades
|
18
|
+
end
|
19
19
|
|
20
|
-
def
|
20
|
+
def has_face?(path)
|
21
21
|
raise "#{path} file does not exist" unless File.exists?(path)
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
22
|
+
add_cascade(DEFAULT_CASCADE) if @cascades.nil?
|
23
|
+
commands = @cascades.map { |opts| build_command(opts, path) }
|
24
|
+
commands.each { |cmd| return true if POSIX::Spawn::system cmd }
|
25
|
+
false
|
26
26
|
end
|
27
27
|
|
28
|
-
def
|
28
|
+
def add_cascade(options)
|
29
29
|
raise "Invalid setting. Got #{options.keys.sort}, require #{DEFAULT_OPTIONS}" unless options.keys.sort == DEFAULT_OPTIONS
|
30
|
-
|
31
|
-
|
32
|
-
|
30
|
+
@cascades ||= []
|
31
|
+
@cascades << options
|
32
|
+
end
|
33
33
|
|
34
|
-
|
34
|
+
private
|
35
35
|
|
36
|
-
|
36
|
+
def build_command(options, path)
|
37
37
|
"#{EXECUTABLE} " +
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
38
|
+
"--cascade=#{cascade_path(options[:cascade])} " +
|
39
|
+
"--fussyness=#{options[:fussyness]} " +
|
40
|
+
"--scale_factor=#{options[:scale_factor]} " +
|
41
|
+
"--min_size=#{options[:min_size]} " +
|
42
|
+
"--max_size=#{options[:max_size]} " +
|
43
|
+
"#{path}" # > /dev/null 2>&1"
|
44
|
+
end
|
45
45
|
|
46
|
-
|
46
|
+
def cascade_path(cascade_path)
|
47
47
|
File.join(LIB_PATH, cascade_path)
|
48
|
-
|
48
|
+
end
|
49
49
|
end
|
data/lib/findaface/version.rb
CHANGED
@@ -1,3 +1,3 @@
|
|
1
|
-
|
2
|
-
VERSION = '0.0
|
1
|
+
class Findaface
|
2
|
+
VERSION = '1.0.0'
|
3
3
|
end
|
data/report.md
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
= False Negatives
|
2
|
+

|
3
|
+

|
4
|
+

|
5
|
+

|
6
|
+

|
7
|
+

|
8
|
+

|
9
|
+

|
10
|
+

|
11
|
+

|
12
|
+

|
13
|
+

|
14
|
+

|
15
|
+

|
16
|
+

|
17
|
+

|
18
|
+

|
data/spec/findaface_spec.rb
CHANGED
@@ -2,53 +2,69 @@ require_relative '../lib/findaface.rb'
|
|
2
2
|
|
3
3
|
describe Findaface, "has_face?" do
|
4
4
|
|
5
|
+
let(:face) { 'spec/photos/face.jpg' }
|
6
|
+
let(:eye) { 'spec/photos/eye.jpg' }
|
7
|
+
let(:nose) { 'spec/photos/nose.jpg' }
|
8
|
+
let(:fruit) { 'spec/photos/fruit.jpg' }
|
9
|
+
|
5
10
|
it "finds faces" do
|
6
|
-
|
7
|
-
Findaface.has_face?(path).should be_true
|
8
|
-
end
|
11
|
+
Findaface.new.has_face?(face).should be_true
|
9
12
|
end
|
10
13
|
|
11
14
|
it "doesn't give false positives" do
|
12
|
-
|
13
|
-
Findaface.has_face?(path).should be_false
|
14
|
-
end
|
15
|
+
Findaface.new.has_face?(eye).should_not be_true
|
15
16
|
end
|
16
17
|
|
17
|
-
|
18
|
-
|
19
|
-
Findaface.
|
18
|
+
context "with custom cascade options" do
|
19
|
+
before :each do
|
20
|
+
@nose_detecter = Findaface.new
|
21
|
+
@nose_detecter.add_cascade({
|
22
|
+
cascade:'haarcascades/haarcascade_mcs_nose.xml',
|
23
|
+
fussyness: 7,
|
24
|
+
scale_factor: 1.05,
|
25
|
+
min_size: 80,
|
26
|
+
max_size: 512,
|
27
|
+
})
|
28
|
+
end
|
29
|
+
|
30
|
+
it "finds a nose" do
|
31
|
+
@nose_detecter.has_face?(nose).should be_true
|
32
|
+
end
|
33
|
+
|
34
|
+
it "doesn't give false positives" do
|
35
|
+
@nose_detecter.has_face?(eye).should_not be_true
|
20
36
|
end
|
21
37
|
end
|
22
38
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
39
|
+
context "with multiple cascades" do
|
40
|
+
it "can detect a nose, eye, and face" do
|
41
|
+
findaface = Findaface.new
|
42
|
+
findaface.add_cascade(
|
43
|
+
{
|
44
|
+
cascade:'haarcascades/haarcascade_eye.xml',
|
45
|
+
fussyness: 8,
|
46
|
+
scale_factor: 1.05,
|
47
|
+
min_size: 100,
|
48
|
+
max_size: 512,
|
49
|
+
})
|
50
|
+
findaface.add_cascade({
|
51
|
+
cascade:'haarcascades/haarcascade_mcs_nose.xml',
|
52
|
+
fussyness: 8,
|
53
|
+
scale_factor: 1.044,
|
54
|
+
min_size: 100,
|
55
|
+
max_size: 512,
|
56
|
+
})
|
57
|
+
findaface.add_cascade(
|
58
|
+
{
|
59
|
+
cascade:'haarcascades/haarcascade_frontalface_alt2.xml',
|
60
|
+
fussyness: 8,
|
61
|
+
scale_factor: 1.05,
|
62
|
+
min_size: 100,
|
63
|
+
max_size: 512,
|
64
|
+
})
|
65
|
+
[eye, nose, face].each do |path|
|
66
|
+
findaface.has_face?(path).should be_true
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
54
70
|
end
|
data/spec/photos/eye.jpg
ADDED
Binary file
|
Binary file
|
Binary file
|
Binary file
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: findaface
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 1.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Andrew Nagi
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-08-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: posix-spawn
|
@@ -94,20 +94,6 @@ dependencies:
|
|
94
94
|
- - ">="
|
95
95
|
- !ruby/object:Gem::Version
|
96
96
|
version: '0'
|
97
|
-
- !ruby/object:Gem::Dependency
|
98
|
-
name: pry-debugger
|
99
|
-
requirement: !ruby/object:Gem::Requirement
|
100
|
-
requirements:
|
101
|
-
- - ">="
|
102
|
-
- !ruby/object:Gem::Version
|
103
|
-
version: '0'
|
104
|
-
type: :development
|
105
|
-
prerelease: false
|
106
|
-
version_requirements: !ruby/object:Gem::Requirement
|
107
|
-
requirements:
|
108
|
-
- - ">="
|
109
|
-
- !ruby/object:Gem::Version
|
110
|
-
version: '0'
|
111
97
|
- !ruby/object:Gem::Dependency
|
112
98
|
name: awesome_print
|
113
99
|
requirement: !ruby/object:Gem::Requirement
|
@@ -172,15 +158,12 @@ files:
|
|
172
158
|
- lib/readme.txt
|
173
159
|
- lib/softcascade/inria_caltech-17.01.2013.xml
|
174
160
|
- lib/softcascade/soft-cascade-17.12.2012.xml
|
161
|
+
- report.md
|
175
162
|
- spec/findaface_spec.rb
|
176
|
-
- spec/
|
177
|
-
- spec/
|
178
|
-
- spec/
|
179
|
-
- spec/
|
180
|
-
- spec/test_photos/has_face/face.jpg
|
181
|
-
- spec/test_photos/no_face/.gitkeep
|
182
|
-
- spec/test_photos/no_face/fruit.jpg
|
183
|
-
- spec/test_photos/small_faces/beach.jpg
|
163
|
+
- spec/photos/eye.jpg
|
164
|
+
- spec/photos/face.jpg
|
165
|
+
- spec/photos/fruit.jpg
|
166
|
+
- spec/photos/nose.jpg
|
184
167
|
homepage: ''
|
185
168
|
licenses:
|
186
169
|
- MIT
|
@@ -201,18 +184,14 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
201
184
|
version: '0'
|
202
185
|
requirements: []
|
203
186
|
rubyforge_project:
|
204
|
-
rubygems_version: 2.2.
|
187
|
+
rubygems_version: 2.2.2
|
205
188
|
signing_key:
|
206
189
|
specification_version: 4
|
207
190
|
summary: Finds a face in an image.
|
208
191
|
test_files:
|
209
192
|
- spec/findaface_spec.rb
|
210
|
-
- spec/
|
211
|
-
- spec/
|
212
|
-
- spec/
|
213
|
-
- spec/
|
214
|
-
- spec/test_photos/has_face/face.jpg
|
215
|
-
- spec/test_photos/no_face/.gitkeep
|
216
|
-
- spec/test_photos/no_face/fruit.jpg
|
217
|
-
- spec/test_photos/small_faces/beach.jpg
|
193
|
+
- spec/photos/eye.jpg
|
194
|
+
- spec/photos/face.jpg
|
195
|
+
- spec/photos/fruit.jpg
|
196
|
+
- spec/photos/nose.jpg
|
218
197
|
has_rdoc:
|