class Object

Public Instance Methods

classify(file) click to toggle source
# File lib/photographic_memory.rb, line 131
def classify file
  file.rewind
  detect_labels file
rescue Aws::Rekognition::Errors::ServiceError, Aws::Errors::MissingRegionError, Seahorse::Client::NetworkingError
  # This also is not worth crashing over
  []
end
delete(key) click to toggle source
# File lib/photographic_memory.rb, line 101
def delete key
  @s3_client.delete_object({
    bucket: @config[:s3_bucket],
    key: key
  })
end
detect_faces(file) click to toggle source
# File lib/photographic_memory.rb, line 197
def detect_faces file
  file.rewind
  # get the original image from S3 and classify
  client = Aws::Rekognition::Client.new({
    region: @config[:rekognition_region],
    credentials: Aws::Credentials.new(
      @config[:rekognition_access_key_id],
      @config[:rekognition_secret_access_key]
    )
  })
  client.detect_faces({
    image: {
      bytes: file
    },
    attributes: ["ALL"]
  }).face_details
rescue Aws::Rekognition::Errors::ServiceError, Aws::Errors::MissingRegionError, Seahorse::Client::NetworkingError => e
  []
end
detect_gravity(file) click to toggle source
# File lib/photographic_memory.rb, line 139
def detect_gravity file
  file.rewind

  boxes = detect_faces(file).map(&:bounding_box)

  box = boxes.max_by{|b| b.width * b.height } # use the largest face in the photo

  return "Center" if !box

  x = nearest_fifth((box.width / 2)   + ((box.left >= 0) ? box.left : 0))
  y = nearest_fifth((box.height / 2)  + ((box.top  >= 0) ? box.top  : 0))

  gravity_table = {
    0.0 => {
      0.0 => "NorthWest",
      0.5 => "West",
      1.0 => "SouthWest"
    },
    0.5 => {
      0.0 => "North",
      0.5 => "Center",
      1 => "South"
    },
    1.0 => {
      0.0 => "NorthEast",
      0.5 => "East",
      1.0 => "SouthEast"
    }
  }

  gravity_table[x][y]
end
detect_labels(file) click to toggle source
# File lib/photographic_memory.rb, line 176
def detect_labels file
  file.rewind
  # get the original image from S3 and classify
  client = Aws::Rekognition::Client.new({
    region: @config[:rekognition_region],
    credentials: Aws::Credentials.new(
      @config[:rekognition_access_key_id],
      @config[:rekognition_secret_access_key]
    )
  })
  client.detect_labels({
    image: {
      bytes: file
    },
    max_labels: 123, 
    min_confidence: 73, 
  }).labels
rescue Aws::Rekognition::Errors::ServiceError, Aws::Errors::MissingRegionError, Seahorse::Client::NetworkingError => e
  []
end
exif(file) click to toggle source
# File lib/photographic_memory.rb, line 110
def exif file
  file.rewind
  MiniExiftool.new(file, :replace_invalid_chars => "")    
end
get(key) click to toggle source
# File lib/photographic_memory.rb, line 94
def get key
  @s3_client.get_object({
    bucket: @config[:s3_bucket],
    key: key
  }).body
end
nearest_fifth(num) click to toggle source
# File lib/photographic_memory.rb, line 172
def nearest_fifth num
  (num * 2).round / 2.0
end
render(file, convert_options=[]) click to toggle source
# File lib/photographic_memory.rb, line 115
def render file, convert_options=[]
  file.rewind
  run_command ["convert", "-", convert_options, "jpeg:-"].flatten.join(" "), file.read.force_encoding("UTF-8")
end
render_gif(file, convert_options=[]) click to toggle source
# File lib/photographic_memory.rb, line 120
def render_gif file, convert_options=[]
  convert_options.concat(["-coalesce", "-repage 0x0", "+repage"])
  convert_options.each do |option|
    if option.match("-crop")
      option.concat " +repage"
    end
  end
  file.rewind
  run_command ["convert", "-", convert_options, "gif:-"].flatten.join(" "), file.read.force_encoding("UTF-8")
end
run_command(command, input) click to toggle source
# File lib/photographic_memory.rb, line 217
def run_command command, input
  stdin, stdout, stderr, wait_thr = Open3.popen3(command)
  pid = wait_thr.pid

  Timeout.timeout(10) do # cancel in 10 seconds
    stdin.write input
    stdin.close

    output_buffer = []
    error_buffer  = []

    while (output_chunk = stdout.gets) || (error_chunk = stderr.gets)
      output_buffer << output_chunk
      error_buffer  << error_chunk
    end

    output_buffer.compact!
    error_buffer.compact!

    output = output_buffer.any? ? output_buffer.join('') : nil
    error  = error_buffer.any? ? error_buffer.join('') : nil

    unless error
      raise PhotographicMemoryError, "No output received." if !output
    else
      raise PhotographicMemoryError, error
    end
    output
  end
rescue Timeout::Error, Errno::EPIPE => e
  raise PhotographicMemoryError, e.message
ensure
  begin
    Process.kill("KILL", pid) if pid
  rescue Errno::ESRCH
    # Process is already dead so do nothing.
  end
  stdin  = nil
  stdout = nil
  stderr = nil
  wait_thr.value if wait_thr # Process::Status object returned.
end