paperclip-facecrop 0.0.6 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -2,15 +2,30 @@ Paperclip::FaceCrop
2
2
  ====================
3
3
  `Paperclip::FaceCrop` is a [Paperclip][paperclip] processor that is aware of the faces found on the image
4
4
  so that they aren't cropped or aren't shown too small while generating the thumbnails.
5
- It uses OpenCV for the facial recognition
5
+ It can use the [OpenCV][opencv] library or the [Face.com][face_com] web service(or both at the same time) for the facial recognition.
6
6
 
7
7
  ![](https://github.com/dagi3d/paperclip-facecrop/raw/master/README_example.jpg)
8
8
 
9
9
  Requirements:
10
10
  -------------
11
+
12
+ ### OpenCV
13
+
14
+ If you want to use OpenCV on your own server, you need to install:
15
+
11
16
  - [OpenCV][opencv]
12
17
  - [OpenCV ruby binding][ruby-opencv]
13
18
 
19
+ In case you get the error message `/ext/opencv/cverror.cpp:143: error: ‘CV_GpuCufftCallError’ was not declared in this scope` while installing the ruby binding,
20
+ checkout the OpenCV_2.2 branch or just remove the line 143 from `/ext/opencv/cverror.cpp`
21
+
22
+
23
+ ### Face.com
24
+ - [rest-client][rest-client]
25
+
26
+ In order to use the Face.com service, you will also need to register in order to get your api key and api secret for your application.
27
+
28
+
14
29
  Installation:
15
30
  -------------
16
31
  - Add to your application `Gemfile`
@@ -21,39 +36,55 @@ Installation:
21
36
 
22
37
  bundle install
23
38
 
24
- - Write an initializer setting the path of the haarcascade filters(`initializers/paperclip.rb` for example):
25
39
 
26
- Paperclip::FaceCrop.classifiers = {
27
- :face => ["/usr/local/share/opencv/haarcascades/haarcascade_frontalface_alt.xml"]
40
+ - Write an initializer setting the detectors configuration (`initializers/paperclip.rb` for example):
41
+
42
+ ### OpenCV
43
+
44
+ Set the path of the haarcascade filters:
45
+
46
+ Paperclip::FaceCrop.detectors = {
47
+ 'OpenCV' => {
48
+ :face => %w(/usr/local/share/opencv/haarcascades/haarcascade_frontalface_alt_tree.xml)
49
+ }
28
50
  }
51
+
52
+
29
53
 
30
- You can use more than one filter to try more accurate searches:
54
+ You can use more than one filter to try more accurate searches:
31
55
 
32
- Paperclip::FaceCrop.classifiers = {
33
- :face => [
34
- "/usr/local/share/opencv/haarcascades/haarcascade_frontalface_alt.xml",
35
- "/usr/local/share/opencv/haarcascades/haarcascade_frontalface_alt_tree.xml",
36
- "/usr/local/share/opencv/haarcascades/haarcascade_profileface.xml"
37
- ]
56
+ Paperclip::FaceCrop.detectors = {
57
+ 'OpenCV' => {
58
+ :face => %w(/usr/local/share/opencv/haarcascades/haarcascade_frontalface_alt_tree.xml
59
+ /usr/local/share/opencv/haarcascades/haarcascade_frontalface_alt.xml
60
+ /usr/local/share/opencv/haarcascades/haarcascade_profileface.xml)
61
+ }
38
62
  }
39
63
 
40
- In order to try to avoid some false positives, you can also specify other classifiers to detect other parts of the face. In that case,
41
- only the found areas that contain parts like a mouth, an eye or a nose will be considered a face:
64
+
65
+
66
+ In order to try to avoid some false positives, you can also specify other classifiers to detect other parts of the face. In that case,
67
+ only the found areas that contain parts like a mouth, an eye or a nose will be considered a face:
42
68
 
43
- Paperclip::FaceCrop.classifiers = {
44
- :face => [
45
- "/usr/local/share/opencv/haarcascades/haarcascade_frontalface_alt.xml",
46
- "/usr/local/share/opencv/haarcascades/haarcascade_frontalface_alt_tree.xml",
47
- "/usr/local/share/opencv/haarcascades/haarcascade_profileface.xml"
48
- ],
49
- :parts => [
50
- "/usr/local/share/opencv/haarcascades/haarcascade_mcs_nose.xml",
51
- "/usr/local/share/opencv/haarcascades/haarcascade_mcs_lefteye.xml",
52
- "/usr/local/share/opencv/haarcascades/haarcascade_mcs_righteye.xml"
53
- ]
69
+ Paperclip::FaceCrop.detectors = {
70
+ 'OpenCV' => {
71
+ :face => %w(/usr/local/share/opencv/haarcascades/haarcascade_frontalface_alt_tree.xml
72
+ /usr/local/share/opencv/haarcascades/haarcascade_frontalface_alt.xml
73
+ /usr/local/share/opencv/haarcascades/haarcascade_profileface.xml),
74
+
75
+ :parts => %w(/usr/local/share/opencv/haarcascades/haarcascade_mcs_nose.xml
76
+ /usr/local/share/opencv/haarcascades/haarcascade_mcs_lefteye.xml
77
+ /usr/local/share/opencv/haarcascades/haarcascade_mcs_righteye.xml)
78
+ }
54
79
  }
80
+
55
81
 
56
-
82
+ ### Face.com
83
+
84
+ Paperclip::FaceCrop.detectors = {
85
+ 'FaceCom' => { :api_key => "<YOUR API KEY>", :api_secret => "<YOUR API SECRET>"}
86
+ }
87
+
57
88
 
58
89
  Usage:
59
90
  ------
@@ -71,15 +102,19 @@ In case no faces were found, it will behave simply as the `Paperclip::Thumbnail`
71
102
 
72
103
  You can also set the debug mode to draw on the image the detected regions:
73
104
 
74
- Paperclip::FaceCrop.debug = (Rails.env == 'development')
105
+ Paperclip::FaceCrop.debug = Rails.env.development?
75
106
 
76
107
  ![](https://github.com/dagi3d/paperclip-facecrop/raw/master/README_example_b.jpg)
77
108
 
109
+ Each detector will draw the found regions in different colors(Face.com detector in red and OpenCV in green)
110
+
78
111
  Credits:
79
112
  --------
80
113
  Copyright (c) 2011 Borja Martín Sánchez de Vivar <borjamREMOVETHIS@dagi3d.net> - <http://dagi3d.net>, released under the MIT license
81
114
  The photo used as example belongs to [Jesper Rønn-Jensen](http://www.flickr.com/photos/jesper/)
82
115
 
116
+ [face_com]: http://face.com
117
+ [rest-client]: https://rubygems.org/gems/rest-client
83
118
  [paperclip]: https://github.com/thoughtbot/paperclip
84
119
  [opencv]: http://opencv.willowgarage.com/
85
120
  [ruby-opencv]: https://github.com/ser1zw/ruby-opencv
data/README_example_b.jpg CHANGED
Binary file
@@ -0,0 +1,27 @@
1
+ require 'rest_client'
2
+
3
+ class FaceCrop::Detector::FaceCom < FaceCrop::Detector::Base
4
+ URL = "http://api.face.com/faces/detect.json"
5
+
6
+ def detect_faces(file)
7
+ query = @options.to_query
8
+ url = "#{URL}?#{query}"
9
+
10
+ response = RestClient.post url, :file => File.new(file)
11
+ response = JSON.parse(response)
12
+
13
+ photo = response['photos'].first
14
+ photo['tags'].map do |tag|
15
+ # values are returned as percentual values
16
+ x = (photo['width'] * (tag['center']['x'] / 100.0)).to_i
17
+ y = (photo['height'] * (tag['center']['y'] / 100.0)).to_i
18
+ w = (photo['width'] * (tag['width'] / 100)).to_i
19
+ h = (photo['height'] * (tag['height'] / 100)).to_i
20
+
21
+ region = FaceCrop::Detector::Region.new(x, y, w, h)
22
+ region.color = "green"
23
+ region
24
+ end
25
+ end
26
+ end
27
+
@@ -0,0 +1,44 @@
1
+ require 'opencv'
2
+ require File.expand_path('../opencv_ext', __FILE__)
3
+
4
+ class FaceCrop::Detector::OpenCV < FaceCrop::Detector::Base
5
+
6
+ def detect_faces(file)
7
+
8
+ image = OpenCV::IplImage.load(file, 1)
9
+
10
+ faces_regions = detect_regions(image, @options[:face])
11
+
12
+ #Paperclip::FaceCrop.classifiers[:nose]
13
+ unless @options[:parts].nil?
14
+ faces_parts_regions = detect_regions(image, @options[:parts])
15
+
16
+ faces_regions.reject! do |face_region|
17
+ region = faces_parts_regions.detect do |part_region|
18
+ # part of a face can't be bigger than the face itself
19
+ face_region.collide?(part_region) && face_region > part_region
20
+ end
21
+
22
+ region.nil?
23
+ end
24
+ end
25
+
26
+ faces_regions
27
+
28
+ end
29
+
30
+ private
31
+ def detect_regions(image, classifiers, color = OpenCV::CvColor::Blue)
32
+ regions = []
33
+
34
+ classifiers.each do |classifier|
35
+ detector = OpenCV::CvHaarClassifierCascade::load(classifier)
36
+ detector.detect_objects(image) do |region|
37
+ region.color = "red"
38
+ regions << region
39
+ end
40
+ end
41
+
42
+ regions
43
+ end
44
+ end
@@ -1,7 +1,7 @@
1
- require 'opencv'
2
-
3
1
  class OpenCV::CvAvgComp
4
2
 
3
+ attr_accessor :color
4
+
5
5
  # collide?
6
6
  #
7
7
  def collide?(comp)
data/lib/face_crop.rb ADDED
@@ -0,0 +1,86 @@
1
+ module FaceCrop
2
+
3
+ # Detector
4
+ #
5
+ module Detector
6
+
7
+ autoload :FaceCom, File.expand_path('../detectors/face_com', __FILE__)
8
+ autoload :OpenCV, File.expand_path('../detectors/opencv', __FILE__)
9
+
10
+ # Base
11
+ #
12
+ class Base
13
+
14
+ # initialize
15
+ #
16
+ def initialize(options)
17
+ @options = options
18
+ end
19
+
20
+ # detect
21
+ #
22
+ def detect(file)
23
+ key = "#{self.class}#{file}"
24
+ regions = FaceCrop::Detector::Cache[key]
25
+ return regions unless regions.nil?
26
+
27
+ regions = detect_faces(file)
28
+ FaceCrop::Detector::Cache[key] = regions
29
+ regions
30
+ end
31
+
32
+ end
33
+
34
+ class Cache
35
+ @@cache = {}
36
+
37
+ def self.[]=(key, faces)
38
+ @@cache[key] = faces
39
+ end
40
+
41
+ def self.[](key)
42
+ @@cache[key]
43
+ end
44
+
45
+ def self.clear
46
+ @@cache = {}
47
+ end
48
+ end
49
+
50
+ # Region
51
+ #
52
+ class Region
53
+ attr_accessor :center
54
+ attr_accessor :width
55
+ attr_accessor :height
56
+ attr_accessor :color
57
+
58
+ def initialize(x, y, width, height)
59
+ @width, @height = width, height
60
+ @center = Point.new(x, y)
61
+ end
62
+
63
+ def top_left
64
+ @top_left ||= Point.new(@center.x - (width / 2), @center.y - (height / 2))
65
+ end
66
+
67
+ def bottom_right
68
+ @bottom_right ||= Point.new(@center.x + (width / 2), @center.y + (height / 2))
69
+ end
70
+
71
+ def to_s
72
+ "#{center.x},#{center.y}-#{width}x#{height}"
73
+ end
74
+ end
75
+
76
+ # Point
77
+ #
78
+ class Point
79
+ attr_accessor :x
80
+ attr_accessor :y
81
+ def initialize(x,y)
82
+ @x, @y = x, y
83
+ end
84
+ end
85
+ end
86
+ end
@@ -1,149 +1,2 @@
1
- require File.join(File.dirname(__FILE__), 'opencv_ext')
2
-
3
- module Paperclip
4
- class FaceCrop < Paperclip::Thumbnail
5
-
6
- @@debug = false
7
-
8
- cattr_accessor :classifiers
9
- cattr_accessor :debug
10
-
11
- def initialize(file, options = {}, attachment = nil)
12
- super(file, options, attachment)
13
-
14
- faces_regions = []
15
- faces_parts_regions = []
16
-
17
- raise "No classifiers were defined" if self.classifiers.nil?
18
-
19
- image = OpenCV::IplImage.load(file.path, 1)
20
-
21
- faces_regions = detect_regions(image, self.classifiers[:face])
22
-
23
- #Paperclip::FaceCrop.classifiers[:nose]
24
- unless self.classifiers[:parts].nil?
25
- faces_parts_regions = detect_regions(image, self.classifiers[:parts], OpenCV::CvColor::Red)
26
-
27
- faces_regions.reject! do |face_region|
28
- region = faces_parts_regions.detect do |part_region|
29
- # part of a face can't be bigger than the face itself
30
- face_region.collide?(part_region) && face_region > part_region
31
- end
32
-
33
- region.nil?
34
- end
35
- end
36
-
37
- x_coords = []
38
- y_coords = []
39
- widths = []
40
- heights = []
41
-
42
- faces_regions.each do |region|
43
- x_coords << region.top_left.x << region.bottom_right.x
44
- y_coords << region.top_left.y << region.bottom_right.y
45
- widths << region.width
46
- heights << region.height
47
- end
48
-
49
- @has_faces = faces_regions.size > 0
50
-
51
- if @has_faces
52
- @top_left_x = x_coords.min
53
- @top_left_y = y_coords.min
54
- @bottom_right_x = x_coords.max
55
- @bottom_right_y = y_coords.max
56
-
57
- # average faces areas
58
- average_face_width = widths.sum / widths.size
59
- average_face_height = heights.sum / heights.size
60
-
61
- # calculating the surrounding margin of the area that covers all the found faces
62
- #
63
-
64
- # new width
65
- @top_left_x -= average_face_width / 2
66
- @bottom_right_x += average_face_width / 2
67
-
68
- # new height
69
- @top_left_y -= average_face_height / 2
70
- @bottom_right_y += average_face_height / 1.6
71
-
72
- calculate_bounds
73
-
74
- # if the new area is smaller than the target geometry, it's scaled so the final image isn't resampled
75
- #
76
- if @faces_width < @target_geometry.width
77
- delta_width = (@target_geometry.width - @faces_width) / 2
78
- @top_left_x -= delta_width
79
- @bottom_right_x += delta_width
80
- calculate_bounds
81
- end
82
-
83
- #raise (@target_geometry.height > 0 and @faces_height < @target_geometry.height).to_s
84
-
85
- if (@target_geometry.height > 0 and @faces_height < @target_geometry.height)
86
- delta_height = (@target_geometry.height - @faces_height) / 2
87
- @top_left_y -= delta_height
88
- @bottom_right_y += delta_height
89
- calculate_bounds
90
- end
91
-
92
- @faces_height = @faces_width if @target_geometry.height == 0
93
-
94
- @current_geometry = Paperclip::Geometry.new(@faces_width, @faces_height)
95
- end
96
-
97
- end
98
-
99
-
100
- def transformation_command
101
- return super unless @has_faces
102
-
103
- scale, crop = @current_geometry.transformation_to(@target_geometry, crop?)
104
- faces_crop = "%dx%d+%d+%d" % [@faces_width, @faces_height, @top_left_x, @top_left_y]
105
-
106
- trans = []
107
- trans << "-crop" << %["#{faces_crop}"] << "+repage"
108
- trans << "-resize" << %["#{scale}"] unless scale.nil? || scale.empty?
109
- trans << "-crop" << %["#{crop}"] << "+repage" if crop
110
- trans
111
- end
112
-
113
- private
114
-
115
- # calculate_bounds
116
- #
117
- def calculate_bounds
118
- @top_left_x = 0 if @top_left_x < 0
119
- @bottom_right_x = @current_geometry.width if @bottom_right_x > @current_geometry.width
120
-
121
- @top_left_y = 0 if @top_left_y < 0
122
- @bottom_right_y = @current_geometry.height if @bottom_right_y > @current_geometry.height
123
-
124
- @faces_width = @bottom_right_x - @top_left_x
125
- @faces_height = @bottom_right_y - @top_left_y
126
- end
127
-
128
- # detect_regions
129
- #
130
- def detect_regions(image, classifiers, color = OpenCV::CvColor::Blue)
131
- regions = []
132
-
133
- classifiers.each do |classifier|
134
- detector = OpenCV::CvHaarClassifierCascade::load(classifier)
135
- detector.detect_objects(image) do |region|
136
- regions << region
137
- image.rectangle!(region.top_left, region.bottom_right, :color => color) if self.debug
138
- end
139
- end
140
-
141
- if self.debug
142
- image.save_image(@file.path)
143
- Rails.logger.info(regions)
144
- end
145
-
146
- regions
147
- end
148
- end
149
- end
1
+ require File.expand_path('../processor', __FILE__)
2
+ require File.expand_path('../railtie', __FILE__)
data/lib/processor.rb ADDED
@@ -0,0 +1,143 @@
1
+ require File.expand_path('../face_crop', __FILE__)
2
+
3
+ module Paperclip
4
+ class FaceCrop < Paperclip::Thumbnail
5
+
6
+ @@debug = false
7
+
8
+ #cattr_accessor :classifiers
9
+ cattr_accessor :debug
10
+
11
+ def self.detectors=(detectors)
12
+ @@detectors = detectors.map do |name, options|
13
+ #require File.expand_path("../detectors/#{name}", __FILE__)
14
+ detector_class = "FaceCrop::Detector::#{name}".constantize
15
+ detector = detector_class.new(options)
16
+ end
17
+ end
18
+
19
+ def initialize(file, options = {}, attachment = nil)
20
+ super(file, options, attachment)
21
+
22
+ raise "No detectors were defined" if @@detectors.nil?
23
+
24
+ faces_regions = []
25
+ faces_parts_regions = []
26
+
27
+ @@detectors.each do |detector|
28
+ begin
29
+ faces_regions += detector.detect(file.path)
30
+ rescue Exception => e
31
+ Rails.logger.error(e)
32
+ end
33
+ end
34
+
35
+ x_coords, y_coords, widths, heights = [], [], [], []
36
+
37
+ faces_regions.each do |region|
38
+ x_coords << region.top_left.x << region.bottom_right.x
39
+ y_coords << region.top_left.y << region.bottom_right.y
40
+ widths << region.width
41
+ heights << region.height
42
+ end
43
+
44
+ @has_faces = faces_regions.size > 0
45
+
46
+ if @has_faces
47
+ @top_left_x = x_coords.min
48
+ @top_left_y = y_coords.min
49
+ @bottom_right_x = x_coords.max
50
+ @bottom_right_y = y_coords.max
51
+
52
+
53
+ #puts @top_left_x.to_s
54
+
55
+ # average faces areas
56
+ average_face_width = widths.sum / widths.size
57
+ average_face_height = heights.sum / heights.size
58
+
59
+ # calculating the surrounding margin of the area that covers all the found faces
60
+ #
61
+
62
+ # new width
63
+ @top_left_x -= average_face_width / 1.2
64
+ @bottom_right_x += average_face_width / 1.2
65
+
66
+ # new height
67
+ #puts ":::#{@top_left_x}---#{average_face_width}"
68
+ #return
69
+
70
+ @top_left_y -= average_face_height / 1.2
71
+ @bottom_right_y += average_face_height / 1.6
72
+
73
+ calculate_bounds
74
+
75
+ # if the new area is smaller than the target geometry, it's scaled so the final image isn't resampled
76
+ #
77
+ if @faces_width < @target_geometry.width
78
+ delta_width = (@target_geometry.width - @faces_width) / 2
79
+ @top_left_x -= delta_width
80
+ @bottom_right_x += delta_width
81
+ calculate_bounds
82
+ end
83
+
84
+ #raise (@target_geometry.height > 0 and @faces_height < @target_geometry.height).to_s
85
+
86
+ if (@target_geometry.height > 0 and @faces_height < @target_geometry.height)
87
+ delta_height = (@target_geometry.height - @faces_height) / 2
88
+ @top_left_y -= delta_height
89
+ @bottom_right_y += delta_height
90
+ calculate_bounds
91
+ end
92
+
93
+ @faces_height = @faces_width if @target_geometry.height == 0
94
+
95
+ @current_geometry = Paperclip::Geometry.new(@faces_width, @faces_height)
96
+
97
+ if @@debug
98
+ parameters = []
99
+ parameters << "-stroke" << "green"
100
+ parameters << "-fill" << "none"
101
+ parameters << faces_regions.map {|r| "-stroke #{r.color} -draw 'rectangle #{r.top_left.x},#{r.top_left.y} #{r.bottom_right.x},#{r.bottom_right.y}'"}
102
+ parameters << ":source"
103
+ parameters << ":dest"
104
+ parameters = parameters.flatten.compact.join(" ").strip.squeeze(" ")
105
+
106
+ Paperclip.run("convert", parameters, :source => "#{File.expand_path(file.path)}", :dest => "#{File.expand_path(file.path)}")
107
+ end
108
+
109
+
110
+ end
111
+ end
112
+
113
+
114
+ def transformation_command
115
+ return super unless @has_faces
116
+
117
+ scale, crop = @current_geometry.transformation_to(@target_geometry, crop?)
118
+ faces_crop = "%dx%d+%d+%d" % [@faces_width, @faces_height, @top_left_x, @top_left_y]
119
+
120
+ trans = []
121
+ trans << "-crop" << %["#{faces_crop}"] << "+repage"
122
+ trans << "-resize" << %["#{scale}"] unless scale.nil? || scale.empty?
123
+ trans << "-crop" << %["#{crop}"] << "+repage" if crop
124
+ trans
125
+ end
126
+
127
+ private
128
+
129
+ # calculate_bounds
130
+ #
131
+ def calculate_bounds
132
+ @top_left_x = 0 if @top_left_x < 0
133
+ @bottom_right_x = @current_geometry.width if @bottom_right_x > @current_geometry.width
134
+
135
+ @top_left_y = 0 if @top_left_y < 0
136
+ @bottom_right_y = @current_geometry.height if @bottom_right_y > @current_geometry.height
137
+
138
+ @faces_width = @bottom_right_x - @top_left_x
139
+ @faces_height = @bottom_right_y - @top_left_y
140
+ end
141
+
142
+ end
143
+ end
data/lib/railtie.rb ADDED
@@ -0,0 +1,22 @@
1
+ module FaceCrop
2
+ class Railtie < Rails::Railtie
3
+ initializer "paperclip-facecrop.extend_has_attachment" do
4
+ raise "Paperclip needed" unless defined?(Paperclip)
5
+ ActiveSupport.on_load :active_record do
6
+
7
+ class ActiveRecord::Base
8
+
9
+ class << self
10
+ def has_attached_file_with_face_crop_cache(name, args)
11
+ has_attached_file_without_face_crop_cache(name, args)
12
+ send("after_#{name}_post_process", lambda { FaceCrop::Detector::Cache.clear })
13
+ end
14
+
15
+ alias_method_chain :has_attached_file, :face_crop_cache
16
+ end
17
+ end
18
+ end
19
+
20
+ end
21
+ end
22
+ end
@@ -3,7 +3,7 @@ $:.push File.expand_path("../lib", __FILE__)
3
3
 
4
4
  Gem::Specification.new do |s|
5
5
  s.name = "paperclip-facecrop"
6
- s.version = "0.0.6"
6
+ s.version = "0.1.0"
7
7
  s.authors = ["Borja Martín"]
8
8
  s.description = %q{Paperclip processor that is aware of the faces detected on the image so that they don't get cropped or aren't shown too small while generating the thumbnails}
9
9
  s.summary = %q{Paperclip processor that is aware of the faces found on the image}
@@ -13,5 +13,4 @@ Gem::Specification.new do |s|
13
13
  s.files = `git ls-files`.split("\n")
14
14
  s.has_rdoc = false
15
15
  s.add_runtime_dependency("paperclip")
16
- s.add_runtime_dependency("opencv", "= 0.0.6")
17
16
  end
metadata CHANGED
@@ -1,99 +1,70 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: paperclip-facecrop
3
- version: !ruby/object:Gem::Version
4
- prerelease: false
5
- segments:
6
- - 0
7
- - 0
8
- - 6
9
- version: 0.0.6
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ prerelease:
10
6
  platform: ruby
11
- authors:
12
- - "Borja Mart\xC3\xADn"
7
+ authors:
8
+ - Borja Martín
13
9
  autorequire:
14
10
  bindir: bin
15
11
  cert_chain: []
16
-
17
- date: 2011-05-12 00:00:00 +02:00
18
- default_executable:
19
- dependencies:
20
- - !ruby/object:Gem::Dependency
12
+ date: 2011-08-14 00:00:00.000000000Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
21
15
  name: paperclip
22
- prerelease: false
23
- requirement: &id001 !ruby/object:Gem::Requirement
16
+ requirement: &2153665720 !ruby/object:Gem::Requirement
24
17
  none: false
25
- requirements:
26
- - - ">="
27
- - !ruby/object:Gem::Version
28
- segments:
29
- - 0
30
- version: "0"
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
31
22
  type: :runtime
32
- version_requirements: *id001
33
- - !ruby/object:Gem::Dependency
34
- name: opencv
35
23
  prerelease: false
36
- requirement: &id002 !ruby/object:Gem::Requirement
37
- none: false
38
- requirements:
39
- - - "="
40
- - !ruby/object:Gem::Version
41
- segments:
42
- - 0
43
- - 0
44
- - 6
45
- version: 0.0.6
46
- type: :runtime
47
- version_requirements: *id002
48
- description: Paperclip processor that is aware of the faces detected on the image so that they don't get cropped or aren't shown too small while generating the thumbnails
24
+ version_requirements: *2153665720
25
+ description: Paperclip processor that is aware of the faces detected on the image
26
+ so that they don't get cropped or aren't shown too small while generating the thumbnails
49
27
  email: borjam@dagi3d.net
50
28
  executables: []
51
-
52
29
  extensions: []
53
-
54
30
  extra_rdoc_files: []
55
-
56
- files:
31
+ files:
57
32
  - .gitignore
58
33
  - Gemfile
59
34
  - README.md
60
35
  - README_example.jpg
61
36
  - README_example_b.jpg
62
37
  - Rakefile
63
- - lib/opencv_ext.rb
38
+ - lib/detectors/face_com.rb
39
+ - lib/detectors/opencv.rb
40
+ - lib/detectors/opencv_ext.rb
41
+ - lib/face_crop.rb
64
42
  - lib/paperclip-facecrop.rb
43
+ - lib/processor.rb
44
+ - lib/railtie.rb
65
45
  - paperclip-facecrop.gemspec
66
- has_rdoc: true
67
46
  homepage: http://github.com/dagi3d/paperclip-facecrop
68
47
  licenses: []
69
-
70
48
  post_install_message:
71
49
  rdoc_options: []
72
-
73
- require_paths:
50
+ require_paths:
74
51
  - lib
75
- required_ruby_version: !ruby/object:Gem::Requirement
52
+ required_ruby_version: !ruby/object:Gem::Requirement
76
53
  none: false
77
- requirements:
78
- - - ">="
79
- - !ruby/object:Gem::Version
80
- segments:
81
- - 0
82
- version: "0"
83
- required_rubygems_version: !ruby/object:Gem::Requirement
54
+ requirements:
55
+ - - ! '>='
56
+ - !ruby/object:Gem::Version
57
+ version: '0'
58
+ required_rubygems_version: !ruby/object:Gem::Requirement
84
59
  none: false
85
- requirements:
86
- - - ">="
87
- - !ruby/object:Gem::Version
88
- segments:
89
- - 0
90
- version: "0"
60
+ requirements:
61
+ - - ! '>='
62
+ - !ruby/object:Gem::Version
63
+ version: '0'
91
64
  requirements: []
92
-
93
65
  rubyforge_project:
94
- rubygems_version: 1.3.7
66
+ rubygems_version: 1.8.6
95
67
  signing_key:
96
68
  specification_version: 3
97
69
  summary: Paperclip processor that is aware of the faces found on the image
98
70
  test_files: []
99
-