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 CloudTrail, Amazon CloudWatch, Amazon 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:
- Using Amazon Rekognition with Amazon Location to detect the object in an image and search for corresponding places in the given location
- 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:
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) | |
US West (Oregon) (us-west-2) | |
EU (Ireland) (eu-west-1) | |
EU (London) (eu-west-2) | |
EU (Frankfurt) (eu-central-1) | |
AP (Sydney) (ap-southeast-2) |
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.
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
- The Amazon Location Service was announced in re:Invent 2020, so it’s not present in older version of the AWS SDK. Make sure you are using an updated version of the AWS SDK in your Lambdas.
- If you are planning to expose the map publicly (e.g. on your website), make sure you are allowing unauthenticated guest access to your application using Amazon Cognito.
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.