Get started with the Reality Analysis API

Tutorial result example

Important notice

The following tutorial is a step by step detailed description of the low level calls needed for an analysis. It involves using other services, understanding authorizations and creating different json files. It might not be the best way to discover Reality Analysis. We encourage using our Python or TypeScript iTwin Capture SDKs and the included examples if you plan to develop a Python or TypeScript application or for a first discovery even if you plan to use a different language.

Introduction

This quick start tutorial is going to help you work with Reality Analysis.

In this tutorial, you will submit a simple job to detect objects in images.

It is assumed that you already have:

  • Knowledge of the Reality Management API.
  • Knowledge of the Reality Analysis concepts. Check Reality Analysis and read the Overview, Context Scenes, Context Detectors and Job Types sections.

Info

Skill level:

Basic

Duration:

60 minutes

Prerequisites

  • A small set of photos to analyse.
  • A photo object detector. You may download the Coco 2D object detector from the library page.
  • An iTwin and its ID. For instance you can create a iTwin of ID "ITwinID". Check the create and query iTwins guide.

Suggested Tools

Postman

If you want to test the REST API calls directly, you can use Postman or any other solution capable of sending HTTP requests. If you do it this way, you will require an authorization token for the requests to work. This is covered in the "Get a token" section below.

1. Register an Application

You will need to register an application to use the iTwin Platform APIs. You can use the Register button to automatically create your first single page application (SPA). This will allow you to configure Authorization Code Flow for your SPA application and get the correct access token.

Once generated, you will be shown a few lines of code under the button.

  • IMJS_AUTH_CLIENT_CLIENT_ID - this is the unique identifier for your application. Displayed on application details page as Client ID.
  • IMJS_AUTH_CLIENT_REDIRECT_URI - specifies where users are redirected after they have chosen whether or not to authenticate your app. Displayed on application details page as one of Redirect URIs.
  • IMJS_AUTH_CLIENT_LOGOUT_URI - specifies where users can be returned to after logging out. Displayed on application details page as one of Post logout redirect URIs.
  • IMJS_AUTH_CLIENT_SCOPES - list of accesses granted to the application. Displayed on application details page as Scopes.

Or optionally: Register and configure your application manually following instructions in Register and modify an Application tutorial.

Requires you to sign in. Will automatically generate a Single page application (SPA) that is required to complete this tutorial. You will be able to manage your SPA from your My apps page.

2. Get a token

To make a request to the API, you need a user token. There are several ways to get it. You can consult the Authorization API documentation or you can use a sample powershell script to use in your app.

In the following, JWT_TOKEN will stand for this token.

3. Upload data

  • Upload your photos to Reality Management API as CCImageCollection attached to your iTwin project using the Reality Management API.
  • Upload your detector to Reality Management API as ContextDetector attached to your iTwin project using the Reality Management API.

In the following, ITwinID stands for the iTwin project id, ImageCollectionID for the CCImageCollection entry id and DetectorID for the ContextDetector entry id.

Note that your iTwin project will usually store some detectors and all your raw reality data (photos, point clouds, etc.). They are not intended to be uploaded for each Reality Analysis jobs. In many cases, they will have been uploaded previously and probably by someone else.

4. Prepare job input

You will now chose on which reality data the job will be applied, creating the ContextScene pointing to them. It will be very simple in our case, a few photos in a CCImageCollection but remember it could be more complex: pointing to several Reality Management API entries, adding metadata like orientation, etc.

  • Create ContextScene file pointing to the photos your want to analyze. It should look like the file besides.
  • Upload it to Reality Management API as ContextScene entry. Remember to name the file ContextScene.json as should be any ContextScene uploaded on Reality Management API. In the following, PhotosID stands for its id.
json
{
  "version" : "5.0",
  "PhotoCollection" : {
      "Photos" : {
          "0" : {
              "ImagePath" : "0:IMAGE_1059.JPG",
          },
          "1" : {
              "ImagePath" : "0:IMAGE_1060.JPG",
          },
          "2" : {
              "ImagePath" : "0:IMAGE_1061.JPG",
          }
      }
  },
  "References" : {
      "0" : {
          "Path" : "rds:ImageCollectionID"
      }
  }
}

5. Create job

Your next step will be to create the job.

Request

The job is created sending an HTTP POST message to https://api.bentley.com/realitydataanalysis/jobs endpoint with the payload describing the job. Be sure to replace JWT_TOKEN by its value.

http
POST https://api.bentley.com/realitydataanalysis/jobs HTTP/1.1
Authorization: Bearer JWT_TOKEN
Content-Type: application/json

Request Body

The request body defines the job configuration. Be sure to replace ITwinID, PhotosID and DetectorID by their values.

json
{
"type": "objects2D",
"name": "O2D job sample",
"iTwinId": "ITwinID",
"inputs": [
  {
    "type": "photos",
    "id": "PhotosID"
  },
  {
    "type": "photoObjectDetector",
    "id": "DetectorID"
  }
],
"outputs": [
  "objects2D"
],
"options": {}
}

Response body

The API will respond with a 201 Created status code if the call is successful. The most important entry of this response is the id which you will use to refer to the job in following steps.

json
{
"state": "unsubmitted",
"dataCenter": "EastUs",
"id": "JobID",
"createdDateTime": "2024-02-21T08:37:51Z",
"lastModifiedDateTime": "2024-02-21T08:37:51Z",
"email": "name@bentley.com",
"costEstimation": {
  "estimatedCost": 0
},
"outputs": [{
  "type": "objects2D"
}],
"iTwinId": "ITwinID",
"type": "objects2D",
"name": "O2D job sample",
"inputs": [{
  "id": "PhotosID",
  "type": "photos"
}, {
  "id": "DetectorID",
  "type": "photoObjectDetector"
}],
"options": {
  "exportSrs": "",
  "minPhotos": 0,
  "maxDist": 0,
  "useTiePoints": false
}
}

6. Estimate job cost

You can optionally provide relevant quantities about the input to get an estimation of the job cost before deciding to submit it.

Request

Send an HTTP PATCH message to https://api.bentley.com/realitydataanalysis/jobs/JobID endpoint with the payload describing the quantities. Be sure to replace JWT_TOKEN and JobID by their values.

http
PATCH https://api.bentley.com/realitydataanalysis/jobs/JobID HTTP/1.1
Authorization: Bearer JWT_TOKEN
Content-Type: application/json

Request Body

For an 2D object detection job type, these quantities are the number of photos and the total number of gigapixels that will be analyzed.

json
{
"costEstimationParameters": {
  "numberOfPhotos": 3,
  "gigaPixels": 12
}
}

Response body

The API will respond with a 200 OK status code if the call is successful. The estimatedCost is now set.

json
{
"state": "unsubmitted",
"dataCenter": "EastUs",
"id": "JobID",
"createdDateTime": "2024-02-21T08:37:51Z",
"lastModifiedDateTime": "2024-02-21T08:40:51Z",
"email": "name@bentley.com",
"costEstimation": {
  "numberOfPhotos": 3,
  "gigaPixels": 12.0,
  "estimatedCost": 2.4
},
"outputs": [{
  "type": "objects2D"
}],
"iTwinId": "ITwinID",
"type": "objects2D",
"name": "O2D job sample",
"inputs": [{
  "id": "PhotosID",
  "type": "photos"
}, {
  "id": "DetectorID",
  "type": "photoObjectDetector"
}],
"options": {
  "exportSrs": "",
  "minPhotos": 0,
  "maxDist": 0,
  "useTiePoints": false
}
}

7. Submit job

To submit your job, simply change its state to active.

Request

Send an HTTP PATCH message to https://api.bentley.com/realitydataanalysis/jobs/JobID endpoint with the payload to change its state to active. Be sure to replace JWT_TOKEN and JobID by their values.

http
PATCH https://api.bentley.com/realitydataanalysis/jobs/JobID HTTP/1.1
Authorization: Bearer JWT_TOKEN
Content-Type: application/json

Request Body

The only entry to patch is the state of the job.

json
{
"state": "active"
}

Response body

The API will respond with a 200 OK status code if the call is successful. The response indicates that the state has changed to active and adds an executionInformation section, filled so far with a submission time.

json
{
"state": "active",
"executionInformation": {
  "submissionDateTime": "2024-02-21T08:55:46Z"
},
"dataCenter": "EastUs",
"id": "JobID",
"createdDateTime": "2024-02-21T08:37:51Z",
"lastModifiedDateTime": "2024-02-21T08:37:51Z",
"email": "name@bentley.com",
"costEstimation": {
  "numberOfPhotos": 3,
  "gigaPixels": 12.0,
  "estimatedCost": 2.4
},
"outputs": [{
  "type": "objects2D",
  "id": "OutputID"
}],
"iTwinId": "ITwinID",
"type": "objects2D",
"name": "O2D job sample",
"inputs": [{
  "id": "PhotosID",
  "type": "photos"
}, {
  "id": "DetectorID",
  "type": "photoObjectDetector"
}],
"options": {
  "exportSrs": "",
  "minPhotos": 0,
  "maxDist": 0,
  "useTiePoints": false
}
}

8. Monitor job

You will probably want to monitor your job to check its state and advancement.

Request

To monitor the job, send an HTTP GET message to https://api.bentley.com/realitydataanalysis/jobs/JobID/progress endpoint. Be sure to replace JWT_TOKEN and JobID by their values.

http
PATCH https://api.bentley.com/realitydataanalysis/jobs/JobID/progress HTTP/1.1
Authorization: Bearer JWT_TOKEN
Content-Type: application/json

Response body

The response give you the job advancement, state and a step name.

json
{
"progress": {
  "percentage": 25,
  "state": "active",
  "step": "Run_Production"
}
}

Request

At any time, you can get all job information sending an HTTP GET message to https://api.bentley.com/realitydataanalysis/jobs/JobID endpoint.

http
PATCH https://api.bentley.com/realitydataanalysis/jobs/JobID HTTP/1.1
Authorization: Bearer JWT_TOKEN
Content-Type: application/json

Response body

Once the job is over, your can get its final state and check success. The executionInformation section is also filled with more useful data. Your will also get an id in Reality Management API for every output entry. This will allow you to download the results using the Reality Management API.

json
{
"state": "completed",
"executionInformation": {
  "submissionDateTime": "2024-02-21T08:55:46Z",
  "startedDateTime": "2024-02-21T09:05:01Z",
  "endedDateTime": "2024-02-21T09:21:39Z",
  "exitCode": 0,
  "estimatedUnits": 2.5
},
"dataCenter": "EastUs",
"id": "JobID",
"createdDateTime": "2024-02-21T08:37:51Z",
"lastModifiedDateTime": "2024-02-21T08:37:51Z",
"email": "name@bentley.com",
"costEstimation": {
  "numberOfPhotos": 3,
  "gigaPixels": 12.0,
  "estimatedCost": 2.4
},
"outputs": [{
  "type": "objects2D",
  "id": "OutputID"
}],
"iTwinId": "ITwinID",
"type": "objects2D",
"name": "O2D job sample",
"inputs": [{
  "id": "PhotosID",
  "type": "photos"
}, {
  "id": "DetectorID",
  "type": "photoObjectDetector"
}],
"options": {
  "exportSrs": "",
  "minPhotos": 0,
  "maxDist": 0,
  "useTiePoints": false
}
}

Output file

You should obtain a ContextScene file with 2D objects.

json
{
  "version" : "5.0",
  "PhotoCollection" : {
      "Photos" : {
          "0" : {
              "ImagePath" : "0:IMAGE_1059.JPG"
          },
          "1" : {
              "ImagePath" : "0:IMAGE_1060.JPG"
          },
          "2" : {
              "ImagePath" : "0:IMAGE_1061.JPG"
          }
      }
  },
  "Annotations" : {
      "Labels" : {
          "3" : {
              "Name" : "car"
          },
          "4" : {
              "Name" : "motorcycle"
          }
      },
      "Objects2D" : {
          "0" : {
              "e256276a-d478-476d-a654-195dbc23d1d9" : {
                  "LabelInfo" : {
                      "Confidence" : 0.998534977436066,
                      "LabelId" : 3
                  },
                  "Box2D" : {
                      "xmin" : 0.0319100245833397,
                      "ymin" : 0.537032723426819,
                      "xmax" : 0.374318659305573,
                      "ymax" : 0.66499537229538
                  }
              },
              "03f2b2e5-5df5-49a0-8515-62d6df7739bd" : {
                  "LabelInfo" : {
                      "Confidence" : 0.996562480926514,
                      "LabelId" : 3
                  },
                  "Box2D" : {
                      "xmin" : 0.877566039562225,
                      "ymin" : 0.4940065741539,
                      "xmax" : 1,
                      "ymax" : 0.62068098783493
                  }
              }
          },
          "1" : {
              "b61c36dd-98d2-4a2a-902e-9d12d9472f15" : {
                  "LabelInfo" : {
                      "Confidence" : 0.983914494514465,
                      "LabelId" : 3
                  },
                  "Box2D" : {
                      "xmin" : 0.854629874229431,
                      "ymin" : 0.483299434185028,
                      "xmax" : 0.938638925552368,
                      "ymax" : 0.547508895397186
                  }
              },
              ...

10. Other requests

In this tutorial, you have seen almost all the API requests except two:

  • deleting a job: this is only possible if the job has not been submitted yet. The job will be deleted from the service database.
  • canceling a job: it can be done while active. The job will stay in the service database but will not be processed anymore. Please refer to the API Reference.

As mentioned in the documentation, Reality Analysis API is batch oriented to allow concurrent analysis on large datasets. This is why the input and output ContextScenes go through an upload/download to/from Reality Management API. To simplify use cases where these files are light enough to go be transferred via the API requests, future versions will allow direct json transfers as a possible choice.