Class: Paperclip::FaceCrop

Inherits:
Thumbnail
  • Object
show all
Defined in:
lib/processor.rb

Constant Summary collapse

@@debug =
false

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

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

Returns a new instance of FaceCrop.



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
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
# File 'lib/processor.rb', line 19

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

  raise "No detectors were defined" if @@detectors.nil?
  
  faces_regions = []
  faces_parts_regions = []
  
  @@detectors.each do |detector|
    begin
      faces_regions += detector.detect(file.path)
    rescue Exception => e
      Rails.logger.error(e)
    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
    
    
    #puts @top_left_x.to_s
    
    # 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 / 1.2
    @bottom_right_x += average_face_width / 1.2
  
    # new height
    #puts ":::#{@top_left_x}---#{average_face_width}"
    #return
    
    @top_left_y -= average_face_height / 1.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)
    
    if @@debug
      parameters = []
      parameters << "-stroke" << "green"
      parameters << "-fill" << "none"
      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}'"}
      parameters << ":source"
      parameters << ":dest"
      parameters = parameters.flatten.compact.join(" ").strip.squeeze(" ")
                
      Paperclip.run("convert", parameters, :source => "#{File.expand_path(file.path)}", :dest => "#{File.expand_path(file.path)}")
    end
    
    
  end
end

Class Method Details

.detectors=(detectors) ⇒ Object



11
12
13
14
15
16
17
# File 'lib/processor.rb', line 11

def self.detectors=(detectors)
  @@detectors = detectors.map do |name, options|
    #require File.expand_path("../detectors/#{name}", __FILE__)
    detector_class = "FaceCrop::Detector::#{name}".constantize
    detector = detector_class.new(options)
  end
end

Instance Method Details

#transformation_commandObject



114
115
116
117
118
119
120
121
122
123
124
125
# File 'lib/processor.rb', line 114

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