yearbook 0.1.0 → 0.2.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.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.0
1
+ 0.2.0
data/go.rb CHANGED
@@ -4,7 +4,10 @@ require 'yearbook'
4
4
  include Yearbook
5
5
  PIMGS = Dir.glob "#{File.expand_path '../spec/fixtures/images', '__FILE__'}/*.jpg"
6
6
 
7
+ =begin
7
8
  img = Yearbook::Image.new(PIMGS.first)
8
9
  img.write('test.jpg') do |i|
9
10
  i.bw
10
- end
11
+ i.resize_to_fit 200, 500
12
+ end
13
+ =end
@@ -0,0 +1,15 @@
1
+ require 'delegate'
2
+ class AttHash < SimpleDelegator
3
+ def initialize
4
+ @hsh = {}
5
+ super(@hsh)
6
+ end
7
+
8
+ def method_missing(foo, *args, &blk)
9
+ if @hsh.respond_to?(foo)
10
+ @hsh.send(foo, *args, &blk)
11
+ else
12
+ @hsh[foo.to_sym] = args
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,26 @@
1
+ module Yearbook
2
+ module Classifier
3
+
4
+ DATA_DIR = File.expand_path('../../../data/classifiers', __FILE__ )
5
+ DATA_FILES = {
6
+ faces: File.join(DATA_DIR, 'haarcascade_frontalface_default.xml')
7
+
8
+ }
9
+
10
+
11
+ # returns an array of detected objects
12
+ def self.detect_objects(cv_image, object_type)
13
+ detector = load_detector(object_type.to_sym)
14
+
15
+ detector.detect_objects(cv_image)
16
+ end
17
+
18
+
19
+ def self.load_detector(object_type)
20
+ fname = DATA_FILES[object_type]
21
+ puts fname
22
+ OpenCV::CvHaarClassifierCascade::load( fname )
23
+ end
24
+
25
+ end
26
+ end
@@ -1,62 +1,96 @@
1
1
  require 'rmagick'
2
2
  require 'hashie'
3
+ require_relative 'att_hash'
4
+ require_relative 'classifier'
3
5
 
4
6
 
5
7
 
6
- require 'delegate'
7
- class AttHash < SimpleDelegator
8
8
 
9
- def initialize
10
- @hsh = {}
11
- super(@hsh)
12
- end
9
+ module Yearbook
10
+ class Image
13
11
 
14
- def method_missing(foo, *args, &blk)
15
- if @hsh.respond_to?(foo)
16
- @hsh.send(foo, *args, &blk)
17
- else
18
- @hsh[foo.to_sym] = args
12
+ attr_reader :filename
13
+ def initialize(fname)
14
+ @filename = fname
15
+ @objects = []
19
16
  end
20
- end
21
- end
22
17
 
23
18
 
19
+ def detect_objects(obj_type)
20
+ @objects = Classifier.detect_objects(cv_object, obj_type).to_a
21
+ end
24
22
 
25
- module Yearbook
26
- class Image
27
-
28
- def initialize(fname)
29
- @magick_image = read_magick_image(fname)
23
+ def detect_faces
24
+ detect_objects(:faces)
30
25
  end
31
26
 
27
+ def detected_objects
28
+ @objects
29
+ end
32
30
 
33
- def write(out_fname, &blk)
31
+ def write(base_out_fname, &blk)
34
32
  klass = self.class
35
- image_out = image_object
36
33
 
37
- if block_given?
38
- h = AttHash.new
39
- yield h
34
+ if @objects.empty?
35
+ img_objects = Array(image_object)
36
+ else
37
+ img_objects = @objects.map{|o| constitute_from_cv(o, image_object)}
38
+ end
40
39
 
41
-
42
- image_out = h.inject(image_out) do |img, (foo, args)|
43
- klass.send(foo, img, *args)
40
+ img_objects.each_with_index do |image_out, idx|
41
+ if block_given?
42
+ h = AttHash.new
43
+ yield h
44
+
45
+ # transform the image
46
+ image_out = h.inject(image_out) do |img, (foo, args)|
47
+ klass.send(foo, img, *args)
48
+ end
44
49
  end
45
- end
46
50
 
47
- klass.output(image_out, out_fname)
51
+ if idx == 0
52
+ out_fname = base_out_fname
53
+ else
54
+ out_fname = base_out_fname.sub(/\.(?=\w+$)/, "-#{idx}.")
55
+ end
56
+
57
+ klass.output(image_out, out_fname)
58
+ end
48
59
  end
49
60
 
50
61
 
62
+
63
+
64
+
51
65
  private
52
- def read_magick_image(fname)
53
- Magick::Image::read(fname).first
54
- end
55
66
 
67
+
68
+ # defer loading until it is needed
56
69
  def image_object
57
- @magick_image
70
+ @magick_image ||= load_magick_image(@filename)
58
71
  end
59
72
 
73
+ def cv_object
74
+ @cv_image ||= load_cv_image(@filename)
75
+ end
76
+
77
+
78
+
79
+ def constitute_from_cv(c, img)
80
+ pixels = img.dispatch(c.x, c.y, c.width, c.height, "RGB")
81
+
82
+ return Magick::Image.constitute(c.width, c.height, "RGB", pixels)
83
+ end
84
+
85
+
86
+ def load_magick_image(fname)
87
+ Magick::Image::read(fname).first
88
+ end
89
+
90
+
91
+ def load_cv_image(fname)
92
+ IplImage::load(fname)
93
+ end
60
94
 
61
95
 
62
96
  # Image manipulation methods at the class level
@@ -9,6 +9,10 @@ require 'yearbook'
9
9
  Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
10
10
 
11
11
 
12
+ IMAGE_DIR ||= File.expand_path '../spec/fixtures/images', '__FILE__'
13
+
14
+
15
+
12
16
  RSpec.configure do |config|
13
17
 
14
18
  config.filter_run_excluding skip: true
@@ -1,8 +1,59 @@
1
- require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
1
+ require 'spec_helper'
2
2
 
3
- describe "Yearbook" do
4
- it "passes" do
5
- expect(1).to eq 1
6
- end
7
- end
3
+ module Yearbook
4
+ describe Image do
5
+
6
+ context 'instance' do
7
+ before do
8
+ @fname = File.join(IMAGE_DIR, 'bush-george-w.jpg')
9
+ @image = Image.new(@fname)
10
+ @tempfile = Tempfile.new 'bush.jpg'
11
+ end
12
+
13
+ after do
14
+ @tempfile.unlink
15
+ end
16
+
17
+
18
+ describe 'initialization' do
19
+ it 'should have :filename reader' do
20
+ expect(@image.filename).to eq @fname
21
+ end
22
+ end
23
+
24
+ describe '#detect_faces' do
25
+ it 'should return an Array' do
26
+ expect( @image.detect_faces ).to be_an Array
27
+ end
28
+ end
29
+
30
+ describe '#write' do
31
+ it 'should write to disk' do
32
+ @image.write(@tempfile.path)
33
+ expect(@tempfile.size > 10000).to be_true
34
+ end
35
+
36
+ context 'after faces have been detected' do
37
+ before do
38
+ @image.detect_faces
39
+ end
8
40
 
41
+ it 'should write each object to disk' do
42
+ last_num = @image.detected_objects.count - 1
43
+ path = @tempfile.path
44
+ last_path = path.sub(/\.(?=\w+$)/, "-#{last_num}.")
45
+
46
+ @image.write(path)
47
+ expect(File.exists?(last_path)).to be_true
48
+ end
49
+
50
+ end
51
+ end
52
+
53
+
54
+
55
+ end
56
+
57
+
58
+ end
59
+ end
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = "yearbook"
8
- s.version = "0.1.0"
8
+ s.version = "0.2.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["dannguyen"]
12
- s.date = "2013-11-05"
12
+ s.date = "2013-11-06"
13
13
  s.description = "Easy face-cropping"
14
14
  s.email = "dansonguyen@gmail.com"
15
15
  s.extra_rdoc_files = [
@@ -32,6 +32,8 @@ Gem::Specification.new do |s|
32
32
  "data/classifiers/shameem_haarcascade_eye.xml",
33
33
  "go.rb",
34
34
  "lib/yearbook.rb",
35
+ "lib/yearbook/att_hash.rb",
36
+ "lib/yearbook/classifier.rb",
35
37
  "lib/yearbook/image.rb",
36
38
  "spec/fixtures/images/bush-george-w.jpg",
37
39
  "spec/fixtures/images/obama-barack.jpg",
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: yearbook
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-11-05 00:00:00.000000000 Z
12
+ date: 2013-11-06 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rmagick
@@ -178,6 +178,8 @@ files:
178
178
  - data/classifiers/shameem_haarcascade_eye.xml
179
179
  - go.rb
180
180
  - lib/yearbook.rb
181
+ - lib/yearbook/att_hash.rb
182
+ - lib/yearbook/classifier.rb
181
183
  - lib/yearbook/image.rb
182
184
  - spec/fixtures/images/bush-george-w.jpg
183
185
  - spec/fixtures/images/obama-barack.jpg
@@ -203,7 +205,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
203
205
  version: '0'
204
206
  segments:
205
207
  - 0
206
- hash: 577978153578569035
208
+ hash: -163145999741884676
207
209
  required_rubygems_version: !ruby/object:Gem::Requirement
208
210
  none: false
209
211
  requirements: