- Published on
How to use AWS Rekognition using Ruby on Rails
Ever wanted to use a technology that can identify specific objects contained in any given image? Well look no further as AWS Rekognition fulfils that need.
Figure 1: Logo of AWS Rekognition
AWS Rekognition is a tool that is part of the AWS Cloud Infrastructure ecosystem. It primarily serves to make it easy to add image and video analysis to any application using machine learning that requires zero knowledge of artificial intelligence.
AWS Rekognition can be used to recognizing objects, people, text and many more. One notable use case for Rekognition is to use it to identify dog breeds via a dog image.
Ok enough about AWS Rekognition, now let's learn how to implement it to a Ruby on Rails project!
Setup
To install Rails we will first need to install Ruby. This can be done using the Ruby Installer if you're using Windows. For any other operating systems please refer to this link: ruby-lang.org
You'll also need to install SQLite3 database, this can be done through the SQLite3 website.
Then you'll need to install Node.js backend JavaScript runtime environment and the Yarn package manager. You can install Node.js by visiting their website and Yarn can be installed through the Yarn website.
Finally, Rails can be installed using the gem install
command, which is a part of RubyGems. To install Rails just run the following command:
gem install rails
In order to verify that everything was installed correctly, running the following command should display the version of Rails installed on your system:
rails --version
We are now finished setting up our Rails application, so on to development!⏩
Development
AWS Management Console Setup
First we need to obtain some credentials from the AWS Management Console by visiting here. For the sake of brevity that process won't be covered here so please refer to the following link specific instructions: https://docs.aws.amazon.com/general/latest/gr/aws-sec-cred-types.html
After obtaining your AWS credentials make sure to save that .csv file in a secure location because we will need it later.
Application Development
Next open up your favorite coding IDE and create a new Rails project, here's a link on how to do so if you're unfamiliar with the process: https://guides.rubyonrails.org/getting_started.html
Once you've got a Rails project up and running, just cd
into it and add the following code to the Gemfile.lock
file:
source 'https://rubygems.org'
git_source(:github) { |repo| "https://github.com/#{repo}.git" }
ruby '2.7.4'
# Bundle edge Rails instead: gem 'rails', github: 'rails/rails'
gem 'rails', '~> 5.2.5'
gem 'jquery-rails'
# Use mysql as the database for Active Record
gem 'mysql2', '>= 0.4.4', '< 0.6.0'
# Use Puma as the app server
gem 'puma', '~> 3.11'
# Use SCSS for stylesheets
gem 'sass-rails', '~> 5.0'
# Use Uglifier as compressor for JavaScript assets
gem 'uglifier', '>= 1.3.0'
gem 'rest-client'
gem 'aws-sdk-rekognition'
gem 'aws-sdk-s3'
gem 'aws-sdk', '~> 3.0', '>= 3.0.1'
gem 'paperclip'
# See https://github.com/rails/execjs#readme for more supported runtimes
# gem 'mini_racer', platforms: :ruby
# Use CoffeeScript for .coffee assets and views
gem 'coffee-rails', '~> 4.2'
# Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder
gem 'jbuilder', '~> 2.5'
gem 'therubyracer'
# Reduces boot times through caching; required in config/boot.rb
gem 'bootsnap', '>= 1.1.0', require: false
gem 'bootstrap', '~> 4.0.0'
gem 'devise'
gem 'figaro'
gem 'faye-websocket', '~> 0.10.4'
gem 'open-uri'
group :development, :test do
# Call 'byebug' anywhere in the code to stop execution and get a debugger console
gem 'byebug', platforms: [:mri, :mingw, :x64_mingw]
end
group :development do
# Access an interactive console on exception pages or by calling 'console' anywhere in the code.
gem 'web-console', '>= 3.3.0'
gem 'listen', '>= 3.0.5', '< 3.2'
# Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring
gem 'spring'
gem 'spring-watcher-listen', '~> 2.0.0'
end
group :test do
# Adds support for Capybara system testing and selenium driver
gem 'capybara', '>= 2.15'
gem 'selenium-webdriver'
# Easy installation and use of chromedriver to run system tests with Chrome
gem 'chromedriver-helper'
end
# Windows does not include zoneinfo files, so bundle the tzinfo-data gem
gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby]
Then run the following command to install all the dependencies listed in the Gemfile:
bundler install
Next in order to create an untracked file that can hold our credentials we need to run the following command to get Figaro to create the config/application.yml
file:
bundle exec figaro install
Now if you navigate to the config
folder we should see an application.yml
file. In it, let's add the following code:
aws_client_id: <YOUR_AWS_CLIENT_ID>
aws_client_secret: <YOUR_AWS_CLIENT_SECRET>
aws_region: <YOUR_AWS_REKOGNITION_REGION>
You'll find your AWS Client Id and Client Secret in the .csv
credentials file that was downloaded to your local machine. The AWS region for your AWS Rekognition project can be found on the top right of the AWS Rekognition project page. Just make the region name is one of the names displayed on the right side of this screenshot:
Figure 2: AWS Region names list
Once our config/application.yml
file is populated with our AWS credentials, we can create a Home controller in our Rails application by running the following command:
rails generate controller home
After running the above command, there should be an app/controllers/home_controller.rb
file created. Let's add the following code to it:
require 'net/https'
require 'uri'
require 'json'
require 'base64'
require 'rest_client'
require 'aws-sdk'
class HomeController < ApplicationController
def index
end
def create
uploaded_file = params[:image_file_data]
salt = (Time.now.to_f * 1000).to_s
file_name = "#{salt}-#{uploaded_file.original_filename}"
File.open(Rails.root.join('public', 'uploads', file_name), 'wb') do |file|
file.write(uploaded_file.read)
credentials = Aws::Credentials.new(ENV['aws_client_id'], ENV['aws_client_secret'])
client = Aws::Rekognition::Client.new region: ENV['aws_region'], credentials: credentials
photo = file_name
path = File.expand_path("public/uploads/#{photo}") # expand path relative to the current directory
file = File.read(path)
if(File.zero?(path))
@result = {}
return
end
attrs = {
image: {
bytes: file
},
max_labels: 10
}
@response = client.detect_labels(attrs)
render "index"
end
end
end
Basically the create()
method will extract image file data from the template first. Then, the connection to AWS will be established using the credentials stored in the /config/application.yml
file. After this, the uploaded image file will be stored in the local file system's {root_folder_path}/public/uploads/{image_name}
path. Finally, this locally stored file will be read by the AWS Rekognition client library to which a response will be issued and printed to the console in an organized manner thanks to the @response.labels.each do |label|
loop.
Next we'll add a simple image file upload form to the Home controller's index template. So locate the app/views/home
folder, create an index.html.erb
file and add the following content:
<%= form_tag "/home/upload_picture", method: :post, multipart: true, class: 'mt-5' do %>
<%= file_field_tag :image_file_data %>
<%= submit_tag 'Upload', class: 'btn btn-primary' %>
<% end %>
<% if @response %>
<% @response.labels.each do |label| %>
<p>------------------</p>
<p><b>Label:</b> <%= label.name %></p>
<p><b>Confidence:</b> <%= label.confidence %></p>
<% end %>
<% end %>
This template file basically renders a simple image upload form. Then once a response from AWS Rekognition is received, the information contained within it is rendered in the for loop below the form. The each label that AWS Rekognition provides in its response contains a name and a confidence level. The name is a best guess of what the image is predominately displaying and the confidence level displays the numerical confidence of the degree to which the deep learning model is confident that the label name matches the image.
With the Home controller completed, we now have to specify some routes in the config/routes.rb
file like so:
Rails.application.routes.draw do
# For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
root to: "home#index"
post '/home/upload_picture', to: 'home#create'
end
This routes.rb
file will define the two routes used for this simple application. The first route is to render the home/index.html.erb
template file and the second route is to send a POST request to the home#create
action upon submitting the form in the home/index.html.erb
page.
We are now ready to run this program so let us do so by running:
bin/rails server
Once the server is up and running navigate to localhost:3000.
Finally, when we can select an image from our local system and upload it by clicking the 'Upload' button, we can see a list of labels along with their numerical confidence level.
Figure 3: Upload Image form
Conclusion
Congratulations! You now know how to implement AWS Rekognition in Ruby on Rails applications. If you need access to the source code for this application you can access it by visiting it's GitHub link.
Well that's it for this post! Thanks for following along in this article and if you have any questions or concerns please feel free to post a comment in this post and I will get back to you when I find the time.
If you found this article helpful please share it and make sure to follow me on Twitter and GitHub, connect with me on LinkedIn, subscribe to my YouTube channel.