Class: Paperclip::FaceCrop

Inherits:
Thumbnail
  • Object
show all
Defined in:
lib/paperclip-facecrop.rb

Constant Summary collapse

@@debug =
false

Instance Method Summary collapse

Constructor Details

#initialize(file, options = {}, attachment = nil) ⇒ FaceCrop

Returns a new instance of FaceCrop.



11
12
13
14
15
16
17
18
19
20
21
22
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
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
# File 'lib/paperclip-facecrop.rb', line 11

def initialize(file, options = {}, attachment = nil)
  super(file, options, attachment)

  faces_regions = []
  faces_parts_regions = []
    
  raise "No classifiers were defined" if self.classifiers.nil?

  image = OpenCV::IplImage.load(file.path, 1)

  faces_regions = detect_regions(image, self.classifiers[:face])

  #Paperclip::FaceCrop.classifiers[:nose]
  unless self.classifiers[:parts].nil?
    faces_parts_regions = detect_regions(image, self.classifiers[:parts], OpenCV::CvColor::Red)
  
    faces_regions.reject! do |face_region|
      region = faces_parts_regions.detect do |part_region|
        face_region.collide?(part_region)
      end
    
      region.nil?
    end
  end

  x_coords = []
  y_coords = []
  widths   = []
  heights  = []

  faces_regions.each do |region|
    x_coords << region.top_left.x << region.bottom_right.x
    y_coords << region.top_left.y << region.bottom_right.y
    widths << region.width
    heights << region.height
  end

  @has_faces = faces_regions.size > 0
 
  if @has_faces
    @top_left_x = x_coords.min
    @top_left_y = y_coords.min
    @bottom_right_x = x_coords.max
    @bottom_right_y = y_coords.max
  
    # average faces areas
    average_face_width  = widths.sum / widths.size
    average_face_height = heights.sum / heights.size
  
    # calculating the surrounding margin of the area that covers all the found faces
    #
  
    # new width
    @top_left_x -= average_face_width / 2
    @bottom_right_x += average_face_width / 2
  
    # new height
    @top_left_y -= average_face_height / 2
    @bottom_right_y += average_face_height / 1.6

    calculate_bounds
  
    # if the new area is smaller than the target geometry, it's scaled so the final image isn't resampled
    #
    if @faces_width < @target_geometry.width 
      delta_width = (@target_geometry.width - @faces_width) / 2
      @top_left_x -= delta_width
      @bottom_right_x += delta_width
      calculate_bounds
    end
  
    #raise (@target_geometry.height > 0 and @faces_height < @target_geometry.height).to_s
  
    if (@target_geometry.height > 0 and @faces_height < @target_geometry.height)
      delta_height = (@target_geometry.height - @faces_height) / 2
      @top_left_y -= delta_height
      @bottom_right_y += delta_height
      calculate_bounds
    end
  
    @faces_height = @faces_width if @target_geometry.height == 0
  
    @current_geometry = Paperclip::Geometry.new(@faces_width, @faces_height)
  end

end

Instance Method Details

#transformation_commandObject



99
100
101
102
103
104
105
106
107
108
109
110
# File 'lib/paperclip-facecrop.rb', line 99

def transformation_command
  return super unless @has_faces

  scale, crop = @current_geometry.transformation_to(@target_geometry, crop?)
  faces_crop = "%dx%d+%d+%d" % [@faces_width, @faces_height, @top_left_x, @top_left_y]

  trans = []
  trans << "-crop" << %["#{faces_crop}"] << "+repage"
  trans << "-resize" << %["#{scale}"] unless scale.nil? || scale.empty?
  trans << "-crop" << %["#{crop}"] << "+repage" if crop
  trans
end