Social media websites have made face recognition pretty much a mundane thing nowadays. Facebook, Google, and others can easily recognize your face in a picture, making it easy for you to categorize and find them, build albums, etc. Building such an algorithm is no easy feat, which is one of the reasons you can find some services that provide this as an API. Among them is Kairos. Kairos provides a simple to use API, where you can detect faces in an image, and enroll faces for later detection and validation. In this article, we’d like to show you how you can use this API using Ruby on Rails. After reading this article, you should have a basic understanding of how the API works and how to get the most of it, so you can implement it in your applications.
How to get access to the API
The easiest way to get started with the Kairos API is through RapidAPI. Head to their website, sign up if you need to, then go to the Kairos API page to subscribe. Click on the “Subscribe to Test” button, then follow the steps to register. They provide a single plan, which has a very generous free tier to get us started.
You’ll then be redirected to their page. On the left, you’ll find the different endpoints they provide. There are two categories for the endpoints. The first category, “Gallery Functions”, refer to endpoints that allow you to interact with Galleries. Galleries are collections of faces that have been enrolled in them. After enrolling faces, you can fetch a list of faces enrolled, remove faces from galleries, and delete whole galleries. Note that “gallery” doesn’t mean the API stores images, but rather collections of face data.
The second category is “Face Functions”. These endpoints allow you to detect, enroll, and verify faces. You can enroll a face to a gallery, then later check if the face appears in a picture you upload.
Test the API on RapidAPI
To test the API you’re going to need pictures of faces. You can certainly test with your family vacation pictures, or just find some images (that you can use) online. We recommend you find some images on CreativeCommons, but ideally, you’d want to have many pictures of the same person (or even the same person along with other people) to test the capabilities of the API. The easiest is to use celebrity pictures, as there are usually many of the same person online.
The first endpoint we’ll be testing is the “Detect” endpoints. This is the simplest of all the endpoints because it “just” detects faces in a picture. It will also try to detect gender, race, age, even the position of the eyes, which might be useful if you want to build an app to let your users try on sunglasses virtually, for example. To test this endpoint, click on “Detect” on the left, then in the middle pane, scroll down until you see a JSON payload, with an image URL. Replace that URL with one of an image and click on “Test Endpoint” on the top. You should see something like this on the right:
Another important thing is the fact that you can submit images as data URIs. A data URI is a string that starts with data:image/jpeg;base64
or something similar, which represents the file all on its own. This is useful if you want to submit an image that isn’t hosted anywhere. Kairos’ API supports this, and it will be relevant when we build our app. There are many different ways of getting a data URI for an image. Google what’s easiest for the browser you’re using. Then, you can just use that as a drop-in replacement for a regular image URL.
The Enroll endpoint is also important. It allows you to add images (of faces) to a gallery you define so that you can later use the Recognize endpoint to find occurrences of that face in another image (a group photo, for example). Let’s try it out:
Here, we’re enrolling the same image of Leo we used before, into the GoodGuys
gallery under the ID Leo
. Now, let’s grab another image of him and try to see if the system can recognize him. It’s usually better if we enroll multiple images of the same people.
Here we’re sending a different image, and testing that Kairos can recognize an occurrence of Leo in it (by specifying the GoodGuys
gallery). As you can see, the API detected the face correctly and found some matches with a high degree of confidence.
How to use the Kairos API with Ruby on Rails
Now that you know a little bit more about how to use the API, we can build something with it. We’re going to build a categorization engine that allows you to add people to different galleries, and then detect these people in pictures you upload. For this particular example, we’ll build a “good guys” and “bad guys” categorizer.
We’re going to be using Ruby on Rails, therefore, you’re going to need to have Ruby installed in your system. Follow the official instructions on how to install it.
Step 1: Install Rails and create the project
First, install Ruby on Rails, in case you haven’t yet. Run gem install rails
in your terminal to do that. Once that’s done, we can create our new project. Run this:
rails new kairos --skip-active-record --skip-test
That might take a while, but once it finishes, our project is done.
Step 2: Setup dependencies
We’re going to use Bootstrap as our UI framework, and we’ll also need a gem (a Ruby library) to make API requests to Kairos. Edit your Gemfile
and add this at the bottom:
gem 'excon'
Now, run bundle install
. To get bootstrap, we’re going to edit our main application layout, which is in app/views/layouts/application.html.erb
:
<!DOCTYPE html> <html> <head> <title>Kairos</title> <%= csrf_meta_tags %> <%= csp_meta_tag %> <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %> <%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %> <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css"> <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css"> </head> <body> <%= yield %> <script src="https://code.jquery.com/jquery-3.5.1.slim.min.js"></script> <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"></script> </body> </html>
This adds Bootstrap, Font Awesome (for nice icons) and jQuery. Once you’re done with this, we’re ready to move on to the next step.
Step 3: Categorize Images
Let’s build the first part of our app, that is the section that allows the user to categorize images, to “train” the system. Open the routes file in config/routes.rb
and add some routes:
Rails.application.routes.draw do root to: 'pictures#index' post 'pictures/upload', as: :upload end
The first route is the root route, which is the first thing the user will see. This will contain our forms, where the user will upload pictures and train the system, and also upload picture to recognize people in them. The second route is the route that will receive the file and call the Kairos API to categorize or recognize.
Then, make a new file in app/controllers/pictures_controller.rb
and add this:
class PicturesController < ApplicationController def index end end
Pretty much nothing, for now, but we’ll get back to this file. Finally, create the UI by creating a new folder and file in app/views/pictures/index.html.erb
:
<div class="container"> <div class="row"> <div class="col-lg-6"> <h2>Train</h2> <%= form_with url: upload_path, method: :post, local: true, multipart: true do %> <%= hidden_field_tag :operation, :train %> <% if @operation == 'train' %> <% if @success %> <div class="alert alert-success"> Successfully enrolled <%= @subject_id %> into <%= @gallery_name.titleize %>! </div> <% else %> <div class="alert alert-danger"> An error occurred! </div> <% end %> <% end %> <p>Tip: Use an image where only one person is visible (preferrably a portrait).</p> <div class="form-group"> <label for="file">Upload</label> <%= file_field_tag :file, class: 'form-control-file', required: true %> </div> <div class="form-group"> <p>As</p> <div class="form-check form-check-inline"> <%= radio_button_tag :gallery_name, :good_guys, true, class: 'form-check-input' %> <label for="gallery_name_good_guys" class="form-check-label">Good Guys</label> </div> <div class="form-check form-check-inline"> <%= radio_button_tag :gallery_name, :bad_guys, false, class: 'form-check-input' %> <label for="gallery_name_bad_guys" class="form-check-label">Bad Guys</label> </div> </div> <div class="form-group"> <label for="name">Name</label> <%= text_field_tag :subject_id, nil, required: true, class: 'form-control' %> </div> <button class="btn btn-primary" type="submit"><i class="fa fa-cog"></i> Train</button> <% end %> </div> </div> </div>
Phew! Quite a lot to unpack here. Let’s go step by step. Most of this is Bootstrap boilerplate to get the form looking nice and tidy. We’re creating a form using Rails’ form_with
helper. This form will upload to the upload_path
, which we just defined in the routes file. Notice the multipart: true
. This tells the browser to submit a file. We’re then defining a hidden tag. We’re doing this because we’re going to share the endpoint where we upload images to both train and recognize images. Using this we can tell the server that this particular form is going to submit an image for training. When we create the second form this will make more sense. After this, we’ll display a success or error alert if applicable (notice we’re using @operation
here). Finally, we’re defining a simple form where the user can select which gallery to enroll an image into and under which name.
You should now be able to start your rails server (run rails s
on your terminal) and go to localhost:3000 on your browser. You’ll be greeted with something like this:
Let’s create the controller methods that will process this image. Open your pictures_controller.rb
file and make it look like this:
class PicturesController < ApplicationController def index end def upload @uri = get_data_uri @operation = params[:operation] @subject_id = params[:subject_id] @gallery_name = params[:gallery_name] if params[:operation] == 'train' response = train!(@uri, @gallery_name, @subject_id) @success = response['Errors'].nil? end render action: :index end private def train!(uri, gallery_name, subject_id) payload = { subject_id: subject_id, gallery_name: gallery_name, image: uri } api_request(:enroll, payload) end def api_request(path, payload) params = { headers: { 'x-rapidapi-key': 'YOUR_API_KEY', 'x-rapidapi-host': 'kairosapi-karios-v1.p.rapidapi.com', 'content-type': 'application/json' } } params[:body] = JSON.dump(payload) response = Excon.post( "https://rapidapi.p.rapidapi.com/#{path}", params ) JSON.parse(response.body) end def get_data_uri file = params[:file] "data:#{file.content_type};base64,#{Base64.encode64(file.read).chop}" end end
Again, many things to process. Let’s go step by step:
- The
index
method just renders our form. - The
upload
method is the one called when our form is submitted. Here we define a couple of instance variables to be used in the view (the form we made earlier), including the image’s data URI. We’ll describe theget_data_uri
method at the end of this list. We check if the operation istrain
, and, if so, call thetrain!
method with the image data URI, the gallery name, and the subject id. If the API response contains errors, we’ll use that to setsuccess
tofalse
and render an error. The method finallyrender
s the same index template, to render the form again. - The
train!
method doesn’t do much more than call theapi_request
method with thepath
andpayload
. - The
api_request
is a somewhat generic method to call Kairos’ API via RapidAPI, using the Excon gem. You’re going to need to use your API Key, which you can find on RapidAPI. - Finally, the
get_data_uri
method constructs a data URI. A data URI consists of thedata:
prefix, the file type, and the base64-encoding of its contents.
With this, you should be able to upload the portrait of someone (again, celebrity portraits are a good source of images from different angles), and get a success or error message. Notice that Kairos’ API only supports JPEG and PNG, so any other image format will give you an error.
Step 4: Recognize Images
It’s time to construct the other side of the app: the recognition part. We’re going to add a form on the right of our training form, where the user will also upload an image and select the gallery to use for recognition. Then Kairos will help us find any occurrences of Good/Bad guys in our images. Open the form template at app/views/pictures/index.html.erb
and add this second form:
<div class="container"> <div class="row"> <!-- the first form goes here --> <div class="col-lg-6"> <h2>Recognize</h2> <%= form_with url: upload_path, method: :post, local: true, multipart: true do %> <%= hidden_field_tag :operation, :recognize %> <% if @operation == 'recognize' %> <% if @success %> <img src="<%= @uri %>" height="100" class="rounded" /> <div class="alert alert-success"> <% if @found.any? %> Found <%= @found.to_sentence %> in the picture. <% else %> Didn't find anyone. <% end %> </div> <% else %> <div class="alert alert-danger"> An error occurred! </div> <% end %> <% end %> <div class="form-group"> <label for="file">Upload</label> <%= file_field_tag :file, class: 'form-control-file', required: true %> </div> <div class="form-group"> <p>As</p> <div class="form-check form-check-inline"> <%= radio_button_tag :gallery_name, :good_guys, true, class: 'form-check-input' %> <label for="gallery_name_good_guys" class="form-check-label">Good Guys</label> </div> <div class="form-check form-check-inline"> <%= radio_button_tag :gallery_name, :bad_guys, false, class: 'form-check-input' %> <label for="gallery_name_bad_guys" class="form-check-label">Bad Guys</label> </div> </div> <button class="btn btn-success" type="submit"><i class="fa fa-search"></i> Recognize</button> <% end %> </div> </div> </div>
There isn’t that much of a difference between this form and the previous one, other than the hidden tag has a different value (it’s “recognize” instead of “train”), and we render the image uploaded, plus a list of matches, if any. Let’s see what changes we need to add to our controller now:
class PicturesController < ApplicationController # ... def upload @uri = get_data_uri @operation = params[:operation] @subject_id = params[:subject_id] @gallery_name = params[:gallery_name] if params[:operation] == 'train' response = train!(@uri, @gallery_name, @subject_id) @success = response['Errors'].nil? elsif params[:operation] == 'recognize' response = recognize!(@uri, @gallery_name) @success = response['Errors'].nil? if @success @found = response['images'].map do |image| # There might not be a `candidates` attribute next if image['candidates'].nil? image['candidates'].first['subject_id'] end.reject(&:nil?) end end render action: :index end private def recognize!(uri, gallery_name) payload = { gallery_name: gallery_name, image: uri } api_request(:recognize, payload) end # ... end
Notice we’ve removed some of the already existing methods for brevity (don’t remove them!). Most of the changes are to the upload
method. When the operation
is “recognize”, we call a different method, the recognize!
method, and pass the image data URI and the gallery name. If the request is successful, we’ll get a list of “images” in the response, each of which represents a face that was detected. Each of these will have a list of candidates
, where Kairos attempted to find matches in the gallery (there might not be a candidate for all faces, of course). Using this, we’ll fetch the first match (which is the one with the highest confidence), and add it to our list.
Give it a try! Find examples where multiple potential matches are posing in the same picture.
Conclusion
We hope this article gave you a good introduction on how to use the Kairos API. There are some endpoints we didn’t explore (like removing subjects from a gallery, for instance), which we’ll leave as an exercise. You should also explore all of the data the API returns for an image, which includes the location of the eyes, the position of the face, and much more. This can be used to draw on top of the images, like, for example, draw bounding boxes around faces detected. Get creative!
How to get access to the Kairos API on RapidAPI?
You can find the Kairos API on RapidAPI. Use the search function and select the API from the list of results, and subscribe to use.
Can you use the Kairos API for free on RapidAPI?
Yes, there's a monthly allowance of 1000 requests at the time of writing. After that, there's a fee.
How do I use the Kairos API on RapidAPI?
This article should have everything you need to get started using the Kairos API.
Leave a Reply