Front-End Web & Mobile

Integrating Amazon Location Service with AWS AI/ML services

Amazon Location, announced in re:Invent 2020, is a service that lets you add location data to your applications including maps, points of interests, geocoding, and tracking. It provides cost-effective location-based service using high quality data from trusted providers – Esri and HERE. The service anonymizes all queries sent to data providers by removing customer metadata and account information.

Amazon Location is fully integrated with AWS CloudTrailAmazon CloudWatchAmazon EventBridge, and AWS Identity and Access Management (IAM). It can simplify your development workflow with data integration, and fast tracks apps to production with built-in monitoring, security and compliance features.

In this blog post, we will demonstrate how you can integrate AWS AI/ML services with Amazon Location to add location-based data in your applications. To get started with Amazon Location, we recommend completing the steps given here.

Overview of solution

We’ll consider two use-cases for this blog:

  1. Using Amazon Rekognition with Amazon Location to detect the object in an image and search for corresponding places in the given location
  2. Using Amazon Comprehend with Amazon Location to find addresses in a text and display them on a map

Prerequisites

We’ll use Amazon Cognito authentication as an alternative to using IAM directly for both the services.

For instance, if you are planning to embed the maps publicly (e.g. on your website), make sure to follow these steps for allowing unauthenticated guest access to your application using Amazon Cognito. You can find steps to configure here.

Walkthrough use-case 1: Using Amazon Rekognition with Amazon Location

In this section, we’ll use Amazon Rekognition to identify the object in the image, and then search for nearby places for that object.

The process will involve following steps:

  • Step 1: Identify the object in the image uploaded in S3 using Amazon Rekognition.
  • Step 2: Search for nearby places on the map using Amazon Location.
  • Step 3: Orchestrate the above steps using Step Functions.
  • Step 4: Display results on a map

Step 1: Identify the object in the image uploaded in S3

In this step, let’s create a Lambda function to identify the object in the image using Amazon Rekognition. Here, we have used node.js as language to write code in Lambda function. You can use any coding language supported by Lambda.

// Import sdk and libraries
const AWS = require('aws-sdk');
const Rekognition=require("aws-sdk/clients/rekognition");
// Create constants to store bucket name, picture name and credentials
const bucket = '<S3 bucket name>'; // the bucketname without s3://
const photo = '<Image name>';
const identityPoolId = '<Cognito Identity Pool ARN>';
const credentials = new AWS.CognitoIdentityCredentials({
    IdentityPoolId: identityPoolId,
});

// Store parameters that will be used to access Amazon Rekognition service
const rekognitionParams = {
    Image: {
        S3Object: {
            Bucket: bucket,
            Name: photo
        },
    },
    MaxLabels: 1
};


exports.handler = async(event) => {
    await credentials.getPromise();
    var client = new Rekognition({
        credentials: credentials,
        region: '<AWS Region>',
    });
    let res;
    await client.detectLabels(rekognitionParams, function(err, response) {
        if (err) {
            console.log(err, err.stack); // an error occurred
        }
        else {
            if (response.Labels !== undefined) {
                res = {
                    statusCode: 200,
                    body: response.Labels[0].Name,
                };
            }
        }
    }).promise();
    return res;
};

This function will return the label of the object detected in the image.

Next, we’ll use this label in another Lambda function to call Amazon Location API and search for nearby places.

Step 2: Search for nearby places on the map using Amazon Location

To make a geocoding or reverse geocoding request to Amazon Location, you first need to create a place index in your AWS account. Amazon Location place index resource allows you to select a data source to support search queries. Follow the steps here to create a place index.

Next, create a Lambda function to use Amazon Location service, and call searchPlaceIndexForText method to get the result.

// Import AWS sdk and libraries
const AWS = require('aws-sdk');
const Location = require('aws-sdk/clients/location');
// Get credentials and store place index name
const identityPoolId = "<Amazon Cognito identity pool ARN>";
const indexName = '<Amazon Location place index';
const credentials = new AWS.CognitoIdentityCredentials({
    IdentityPoolId: identityPoolId,
});
//Parameters to be used when calling Amazon Location searchPlaceIndexForText API
var params = {
    IndexName: indexName,// Place index name
    Text: "",
    MaxResults: 5, //Maximum number of results
    BiasPosition: [-123.1187, 49.2819] // Default longitude and latitude(serve as a base location)
};


exports.handler = async(event) => {
    const data = event;
    const dataInput = data.Input;
    // Get the input from Amazon Rekognitionfunction created in step 1 through Step function 
    if (dataInput !== undefined) {
        const inputPayload = dataInput.Payload;
        params.Text=inputPayload.Payload.body;
    }

    await credentials.getPromise();
    const location = new Location({
        credentials: credentials,
        region: '<AWS region>',
    });
    
    
    let arrayLongLat = [];// Array to store resultant latitude and longitude
    let response = {};// Response of the Lambda function
    
    // Call Amazon Location API to search place index for text
    await location.searchPlaceIndexForText(params, function(err, data) {
        if (err) {
            console.log(err, err.stack);
        } // an error occurred
        else {
            data.Results.map(function(v) {
                arrayLongLat.push({
                    longitude: v.Place.Geometry.Point ? v.Place.Geometry.Point[0] : 0,
                    latitude: v.Place.Geometry.Point ? v.Place.Geometry.Point[1] : 0
                });
            });
            response = {
                statusCode: 200,
                body: JSON.stringify(arrayLongLat),
            };
       
        } // successful response
    }).promise();
    return response;
};

This will return an array of longitudes and latitudes near the default location. Next, let’s create a step function to orchestrate the above Lambda functions.

Step 3: Orchestrate with Step Function

AWS Step Functions is a serverless function orchestrator that makes it easy to sequence multiple AWS Lambda functions and other services. It also provides visual interface that helps you run workflows and maintain application state. The output of one step is input to the next that helps implement business logic.

Here is the visual representation and definition of the step function to orchestrate above Lambda functions:

Start, then invoke rekognition lambda function, then invoke location lambda function, then end.

Step function definition:

{
  "Comment": "Amazon Location Example",
  "StartAt": "Invoke Rekognition Lambda function",
  "States": {
    "Invoke Rekognition Lambda function": {
      "Type": "Task",
      "Resource": "arn:aws:states:::lambda:invoke",
      "Parameters": {
        "FunctionName": "arn:aws:lambda:<region:AccountID>:function:TestRekognitionService:$LATEST",
        "Payload.$": "$"
      },
      "ResultPath": "$.Payload",
      "Next": "Invoke Location Lambda function"
    },
    "Invoke Location Lambda function": {
      "Type": "Task",
      "Resource": "arn:aws:states:::lambda:invoke",
      "Parameters": {
        "FunctionName": "arn:aws:lambda:<region:AccountID>:function:TestLocationService:$LATEST",
        "Payload": {
          "Input.$": "$"
        }
      },
      "End": true
    }
  }
}

Step 4: Display result on map

The last step is to display the results (latitude and longitudes) on a map. Amazon Location lets you create and add map resources to display data. To add a map, you first need to create a map resource and select map providers and styles. You can use popular open-source map SDKs, such as Mapbox GL and Tangram, to display the map in your application. Please read more about maps in Amazon Location here. You can also find samples here to create applications and display map on Android, iOS and web applications.

Walkthrough use-case 2: Using Amazon Comprehend with Amazon Location Service

In this section, we will implement a pipeline that leverage Amazon Comprehend and Amazon Location Service.

The goal of this pipeline is generating a map that contains markers on the addresses that have been detected into a text.

A real example of this use-case could relate to travel blogs that want to generate a map starting from the content mentioning all the cities/country they went through.

The process will involve following steps-

  • Step 1: Detect the language of the text in input
  • Step 2: Evaluate if the text is English
  • Step 3: Detect all the addresses contained in a text
  • Step 4: Get the coordinates for each of the address
  • Step 5: Generate an html map with markers

This pipeline will be implemented using AWS Step Functions, below you can find a visual of the Step Function definition.

Link to GitHub repository: https://github.com/aws-samples/amazon-location-detected-addresses-to-map

You can deploy inside you AWS account the latest CloudFormation template by following the link below for your preferred AWS region:

Region Launch Template
US East (N. Virginia) (us-east-1) CloudFormation launch stack button
US West (Oregon) (us-west-2) CloudFormation launch stack button
EU (Ireland) (eu-west-1) CloudFormation launch stack button
EU (London) (eu-west-2) CloudFormation launch stack button
EU (Frankfurt) (eu-central-1) CloudFormation launch stack button
AP (Sydney) (ap-southeast-2) CloudFormation launch stack button

The CloudFormation template that will deploy:

  • 4x AWS Lambda functions
  • 1x Amazon Cognito Identity Pool, for allowing unauthenticated guest access to your application
  • 1x AWS Step Functions
  • All the IAM Roles and Lambda Layer needed

Once deployed you can execute the Step Function to execute pipeline described above.

You can leverage the ExampleCLI value provided in the CloudFormation outputs to test the Step Function via CLI.

To invoke the Step Function, you have to provide as input:

  • The text that you want the pipeline to parse
  • The S3 bucket name and folder name where the html file has to be stored
  • The Cognito Identity Pool Id that you can find it in the CloudFormation stack  Outputs  IdentityPoolId. This will allow unauthenticated guest access to the map
  • The Amazon Location map name you have created
{
    "text": " I live in England, my office is in EC1A 2FD, London.",
    "s3_bucket": "location-to-map-XXXXXX",
    "s3_folder": "map-folder/",
    "identity_pool_id": "us-east-1:205aa252-be23-4616-8849-xxxxxxxxxxxx", 
    "map_name": "ExampleMap01"
}

As output, you will get:

  • An S3 pre-signed link to securely get your html map (NOTE: every pre-signed link is set to expire in 1 hour)

Once deployed the CloudFormation stack above, you can execute the Step Function with your parameters in input. You can execute the Step function via the ExampleCLI command in the CloudFormation outputs, or starting a new execution directly in Step Functions → State machines.

You can access the generated map via the S3 bucket and folder you specified, or via the S3 pre-signed link in Step Function → State machine → Execution output.

Below an example of generated map. The two makers represent the 2 addresses identified in the input text above: England and EC1A 2FD, London.

HTML map generated by AWS Location Service with markers on the addresses detected in the input text.

Let’s go more in details about what each of the Lambda function is doing.

Step 1: Detect the language of the text in input

The first Lambda function is detecting what is the language of the text in input using the DetectDominantLanguage API in Comprehend. Please find here more information on this API and the languages that Comprehend is able to detect.

Step 2: Evaluate if the text is English

In order to detect the addresses in the text we are going to use the DetectPiiEntities API in Comprehend.

This API inspects the input text for entities that contain personally identifiable information (PII) and returns information about them, in our case we process only the Addresses in the response.

Since Amazon Comprehend supports PII detection in only English text, we have to assert that the text is in English.

Note: We are leveraging the DetectPiiEntities and not the DetectEntities API (which is able to detect Location entities) because the first is better to identify addresses.

An example below starting from the text “60 Holborn Viaduct, Holborn, London EC1A 2FD, United Kingdom”:

Step 3: Detect all the addresses contained in a text

As already mentioned in the step above, in this Lambda we are going to detect the addresses in the text with the DetectPiiEntities API in Comprehend. More info on Detect PII, here.

Step 4: Get the coordinates for each of the address

Given a list of address detected in the text, we now want to get the corresponding coordinates for each address.

In order to do that we are going to create a Place Index resource in Amazon Location Service, this is necessary to then invoke the SearchPlaceIndexForText API in Location Service which will perform the Geocoding to get for each address its coordinates. More info on this API, here.

Note: The SearchPlaceIndexForText API is returning multiple result for an Address, in our case we choose the one with the Label that best match our address.

Step 5: Generate an html map with markers

Now that we have a list of addresses and their respective coordinates, the lambda function is injecting each Marker (composed by: coordinates + address label) in a Mapbox GL template.

If you are looking for Amazon Location Service samples, check out this GitHub repo.

Cleaning up

To avoid incurring future charges, delete the CloudFormation stack.

Please, note that you will have to manually delete the S3 bucket created by the CloudFormation stack containing the generated maps, in order to avoid all potential charges.

Common troubleshooting

Conclusion

In this blog we went through some examples of how it is possible to integrate AI Services like Rekognition and Comprehend with Location Service to solve some of the business use-cases the customers are facing when implementing Location Based Services (LBS) in their applications.

About the authors

Kiranpreet Chawla

Kiranpreet Chawla is a Solutions Architect at Amazon Web Services. She currently supports SMB customers in the UK in their digital transformation and cloud journey, and help them use the AWS platform.

Matteo Gabrielli

Matteo is a Solutions Architect at Amazon Web Services (AWS) supporting UK SMB customers in their cloud journey by providing technical guidance and helping them innovate & build secure cloud solutions on AWS. His current areas of depth include machine learning and artificial intelligence.
In his spare time, he enjoys doing Judo (and several other sports), travelling and learning new things.