paperclip-facecrop 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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
+