paperclip-facecrop 0.0.1

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/.gitignore ADDED
@@ -0,0 +1,4 @@
1
+ pkg/*
2
+ *.gem
3
+ Gemfile.lock
4
+ .bundle
data/Gemfile ADDED
Binary file
data/README.md ADDED
@@ -0,0 +1,50 @@
1
+ Paperclip::FaceCrop
2
+ ====================
3
+ `Paperclip::FaceCrop` is a [Paperclip][paperclip] processor that is aware of the faces found on the image
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
6
+
7
+ ![](https://github.com/dagi3d/paperclip-facecrop/raw/master/README_example.jpg)
8
+
9
+ Requirements:
10
+ -------------
11
+ - [OpenCV][opencv]
12
+ - [OpenCV ruby binding][ruby-opencv]
13
+
14
+ Installation:
15
+ -------------
16
+ - Install the gem
17
+
18
+ `gem install paperclip-facecrop'`
19
+
20
+ - Add to `Gemfile`
21
+
22
+ gem 'paperclip-facecrop'
23
+
24
+ - Write an initializer setting the path of the haarcascade filters(`initializers/paperclip.rb` for example):
25
+
26
+ Paperclip::FaceCrop.classifiers = ["/usr/local/share/opencv/haarcascades/haarcascade_frontalface_alt_tree.xml"]
27
+
28
+ You can use more than one filter if you want in order to try more accurate searches.
29
+
30
+ Usage:
31
+ ------
32
+ Just specify your image styles as usual and set :face_crop as the processor:
33
+
34
+ class Image < ActiveRecord::Base
35
+
36
+ has_attached_file :attachment,
37
+ :styles => {:thumbnail => "200x125#"},
38
+ :processors => [:face_crop]
39
+ end
40
+
41
+ In case no faces were found, it will behave simply as the `Paperclip::Thumbnail` processor
42
+
43
+ Credits:
44
+ --------
45
+ Copyright (c) 2011 Borja Martín Sánchez de Vivar <borjamREMOVETHIS@dagi3d.net> - <http://dagi3d.net>, released under the MIT license
46
+ The photo used as example belongs to [Jesper Rønn-Jensen](http://www.flickr.com/photos/jesper/)
47
+
48
+ [paperclip]: https://github.com/thoughtbot/paperclip
49
+ [opencv]: http://opencv.willowgarage.com/
50
+ [ruby-opencv]: https://github.com/ser1zw/ruby-opencv
Binary file
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
@@ -0,0 +1,101 @@
1
+ require 'opencv'
2
+
3
+ class Paperclip::FaceCrop < Paperclip::Thumbnail
4
+
5
+ cattr_accessor :classifiers
6
+
7
+ def initialize(file, options = {}, attachment = nil)
8
+ super(file, options, attachment)
9
+
10
+ x_coords = []
11
+ y_coords = []
12
+ widths = []
13
+ heights = []
14
+
15
+ raise "No classifiers were defined" if Paperclip::FaceCrop.classifiers.nil?
16
+
17
+ image = OpenCV::IplImage.load(file.path)
18
+
19
+ Paperclip::FaceCrop.classifiers.each do |classifier|
20
+ detector = OpenCV::CvHaarClassifierCascade::load(classifier)
21
+ detector.detect_objects(image) do |region|
22
+ x_coords << region.top_left.x << region.bottom_right.x
23
+ y_coords << region.top_left.y << region.bottom_right.y
24
+ widths << region.width
25
+ heights << region.height
26
+ end
27
+ end
28
+
29
+ @has_faces = x_coords.size > 0
30
+
31
+ if @has_faces
32
+ @top_left_x = x_coords.min
33
+ @top_left_y = y_coords.min
34
+ @bottom_right_x = x_coords.max
35
+ @bottom_right_y = y_coords.max
36
+
37
+ # average faces areas
38
+ average_face_width = widths.sum / widths.size
39
+ average_face_height = heights.sum / heights.size
40
+
41
+ # calculating the surrounding margin of the area that covers all the found faces
42
+ #
43
+
44
+ # new width
45
+ @top_left_x -= average_face_width / 2
46
+ @bottom_right_x += average_face_width / 2
47
+
48
+ # new height
49
+ @top_left_y -= average_face_height / 2
50
+ @bottom_right_y += average_face_height / 1.6
51
+
52
+ calculate_bounds
53
+
54
+ # if the new area is smaller than the target geometry, it's scaled so the final image isn't resampled
55
+ #
56
+ if @faces_width < @target_geometry.width
57
+ delta_width = (@target_geometry.width - @faces_width) / 2
58
+ @top_left_x -= delta_width
59
+ @bottom_right_x += delta_width
60
+ calculate_bounds
61
+ end
62
+
63
+ if @faces_height < @target_geometry.height
64
+ delta_height = (@target_geometry.height - @faces_height) / 2
65
+ @top_left_y -= delta_height
66
+ @bottom_right_y += delta_height
67
+ calculate_bounds
68
+ end
69
+
70
+ @current_geometry = Paperclip::Geometry.new(@faces_width, @faces_height)
71
+ end
72
+
73
+ end
74
+
75
+ # calculate_bounds
76
+ #
77
+ def calculate_bounds
78
+ @top_left_x = 0 if @top_left_x < 0
79
+ @bottom_right_x = @current_geometry.width if @bottom_right_x > @current_geometry.width
80
+
81
+ @top_left_y = 0 if @top_left_y < 0
82
+ @bottom_right_y = @current_geometry.height if @bottom_right_y > @current_geometry.height
83
+
84
+ @faces_width = @bottom_right_x - @top_left_x
85
+ @faces_height = @bottom_right_y - @top_left_y
86
+ end
87
+
88
+
89
+ def transformation_command
90
+ return super unless @has_faces
91
+
92
+ scale, crop = @current_geometry.transformation_to(@target_geometry, crop?)
93
+ faces_crop = "%dx%d+%d+%d" % [@faces_width, @faces_height, @top_left_x, @top_left_y]
94
+
95
+ trans = []
96
+ trans << "-crop" << %["#{faces_crop}"] << "+repage"
97
+ trans << "-resize" << %["#{scale}"] unless scale.nil? || scale.empty?
98
+ trans << "-crop" << %["#{crop}"] << "+repage" if crop
99
+ trans
100
+ end
101
+ end
data/lib/version.rb ADDED
@@ -0,0 +1,5 @@
1
+ class Paperclip
2
+ class FaceCrop
3
+ VERSION = "0.0.1"
4
+ end
5
+ end
@@ -0,0 +1,17 @@
1
+ # encoding: utf-8
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require 'version'
4
+ Gem::Specification.new do |s|
5
+ s.name = "paperclip-facecrop"
6
+ s.version = Paperclip::FaceCrop::VERSION
7
+ s.authors = ["Borja Martín"]
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
+ s.summary = %q{Paperclip processor that is aware of the faces found on the image}
10
+ s.email = "borjam@dagi3d.net"
11
+ s.homepage = "http://github.com/dagi3d/paperclip-facecrop"
12
+ s.require_paths = ["lib"]
13
+ s.files = `git ls-files`.split("\n")
14
+ s.has_rdoc = false
15
+ s.add_runtime_dependency("paperclip")
16
+ s.add_runtime_dependency("opencv", "~> 0.0.6")
17
+ end
metadata ADDED
@@ -0,0 +1,98 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: paperclip-facecrop
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 0
8
+ - 1
9
+ version: 0.0.1
10
+ platform: ruby
11
+ authors:
12
+ - "Borja Mart\xC3\xADn"
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2011-05-03 00:00:00 +02:00
18
+ default_executable:
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: paperclip
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ none: false
25
+ requirements:
26
+ - - ">="
27
+ - !ruby/object:Gem::Version
28
+ segments:
29
+ - 0
30
+ version: "0"
31
+ type: :runtime
32
+ version_requirements: *id001
33
+ - !ruby/object:Gem::Dependency
34
+ name: opencv
35
+ 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
49
+ email: borjam@dagi3d.net
50
+ executables: []
51
+
52
+ extensions: []
53
+
54
+ extra_rdoc_files: []
55
+
56
+ files:
57
+ - .gitignore
58
+ - Gemfile
59
+ - README.md
60
+ - README_example.jpg
61
+ - Rakefile
62
+ - lib/paperclip-facecrop.rb
63
+ - lib/version.rb
64
+ - paperclip-facecrop.gemspec
65
+ has_rdoc: true
66
+ homepage: http://github.com/dagi3d/paperclip-facecrop
67
+ licenses: []
68
+
69
+ post_install_message:
70
+ rdoc_options: []
71
+
72
+ require_paths:
73
+ - lib
74
+ required_ruby_version: !ruby/object:Gem::Requirement
75
+ none: false
76
+ requirements:
77
+ - - ">="
78
+ - !ruby/object:Gem::Version
79
+ segments:
80
+ - 0
81
+ version: "0"
82
+ required_rubygems_version: !ruby/object:Gem::Requirement
83
+ none: false
84
+ requirements:
85
+ - - ">="
86
+ - !ruby/object:Gem::Version
87
+ segments:
88
+ - 0
89
+ version: "0"
90
+ requirements: []
91
+
92
+ rubyforge_project:
93
+ rubygems_version: 1.3.7
94
+ signing_key:
95
+ specification_version: 3
96
+ summary: Paperclip processor that is aware of the faces found on the image
97
+ test_files: []
98
+