Importing Labels from GeoJSON
This tutorial explains how to use the kili.append_labels_from_geojson_files
function in the Kili SDK to import geometries from GeoJSON files and convert them to annotations in your Kili projects.
Introduction
GeoJSON is a widely-used open standard format for representing simple geographical features along with their non-spatial attributes. Unlike shapefiles, GeoJSON is human-readable, supports web applications natively, and always uses the WGS84 coordinate system (EPSG:4326).
The append_labels_from_geojson_files
function provides three flexible modes to convert GeoJSON features into Kili annotations, making it easy to import existing geographic data into your annotation projects.
Prerequisites
Before using this feature, ensure you have:
- A Kili project of type
IMAGE
orGEOSPATIAL
- One or more GeoJSON files (
.geojson
or.json
) - Understanding of your project's job structure and categories
Function Structure
The append_labels_from_geojson_files
function accepts the following parameters:
Parameter | Type |
---|---|
project_id |
str |
asset_external_id |
str |
geojson_file_paths |
List[str] |
job_names |
Optional[List[str]] |
category_names |
Optional[List[str]] |
Supported Geometry Types
The function supports the following GeoJSON geometry types and their Kili annotation mappings:
GeoJSON Geometry | Kili Annotation Type | Job Tool Required |
---|---|---|
Point | marker | marker |
LineString | polyline | polyline |
Polygon | polygon or semantic | polygon/semantic |
MultiPolygon | semantic | semantic |
Import Modes
The function supports three different import modes, providing flexibility for various use cases:
Mode 1: GeoJSON with Kili Properties
In this mode, your GeoJSON features contain kili
metadata in their properties, specifying the job, annotation type, and categories.
GeoJSON Structure:
{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [2.3522, 48.8566]
},
"properties": {
"name": "Eiffel Tower",
"kili": {
"job": "LANDMARKS",
"type": "marker",
"categories": [{"name": "TOWER"}]
}
}
}
]
}
Python Code:
from kili.client import Kili
kili = Kili(api_key="your_api_key")
# Mode 1: Import with kili properties already in GeoJSON
kili.append_labels_from_geojson_files(
project_id="your_project_id",
asset_external_id="paris_satellite.tif",
geojson_file_paths=["landmarks_with_kili_props.geojson"]
)
Mode 2: Specific Job/Category Mapping
In this mode, you explicitly specify which job and category to use for all compatible geometries in each file.
Python Code:
# Mode 2: Map all features to specific jobs and categories
kili.append_labels_from_geojson_files(
project_id="your_project_id",
asset_external_id="urban_area.jp2",
geojson_file_paths=["roads.geojson", "buildings.geojson", "parks.geojson"],
job_names=["INFRASTRUCTURE", "BUILDINGS", "VEGETATION"],
category_names=["ROAD", "RESIDENTIAL", "PARK"]
)
Mode 3: Automatic Mapping
When neither kili properties nor specific mappings are provided, the function automatically maps geometries based on their type and available jobs in your project.
Automatic Mapping Priority:
Point
→ First available job with 'marker' toolLineString
→ First available job with 'polyline' toolPolygon
→ First available job with 'polygon' tool (fallback to 'semantic')MultiPolygon
→ First available job with 'semantic' tool
Python Code:
# Mode 3: Automatic mapping based on geometry types
kili.append_labels_from_geojson_files(
project_id="your_project_id",
asset_external_id="geographic_data.tif",
geojson_file_paths=["mixed_features.geojson"]
)
Detailed Examples
Example 1: Importing Multiple Annotation Types
This example shows how to import a GeoJSON file containing different geometry types with kili properties:
from kili.client import Kili
kili = Kili(api_key="your_api_key")
# Create a sample GeoJSON with mixed geometries
import json
geojson_data = {
"type": "FeatureCollection",
"features": [
# Point annotation
{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [-73.985428, 40.758896]
},
"properties": {
"kili": {
"job": "POI_DETECTION",
"type": "marker",
"categories": [{"name": "LANDMARK"}]
}
}
},
# LineString annotation
{
"type": "Feature",
"geometry": {
"type": "LineString",
"coordinates": [
[-73.985, 40.758],
[-73.983, 40.760],
[-73.981, 40.762]
]
},
"properties": {
"kili": {
"job": "ROAD_MAPPING",
"type": "polyline",
"categories": [{"name": "HIGHWAY"}]
}
}
},
# Polygon annotation
{
"type": "Feature",
"geometry": {
"type": "Polygon",
"coordinates": [[
[-73.980, 40.755],
[-73.978, 40.755],
[-73.978, 40.757],
[-73.980, 40.757],
[-73.980, 40.755]
]]
},
"properties": {
"kili": {
"job": "ZONE_DETECTION",
"type": "semantic",
"categories": [{"name": "COMMERCIAL_AREA"}]
}
}
}
]
}
# Save to file
with open("mixed_annotations.geojson", "w") as f:
json.dump(geojson_data, f)
# Import into Kili
kili.append_labels_from_geojson_files(
project_id="your_project_id",
asset_external_id="manhattan_satellite.tif",
geojson_file_paths=["mixed_annotations.geojson"]
)
Example 2: Batch Import with Specific Mapping
This example demonstrates importing multiple GeoJSON files with specific job/category mappings:
# Import different infrastructure types
kili.append_labels_from_geojson_files(
project_id="city_planning_project",
asset_external_id="city_orthophoto_2024.tif",
geojson_file_paths=[
"water_infrastructure.geojson",
"power_lines.geojson",
"green_spaces.geojson"
],
job_names=[
"WATER_INFRASTRUCTURE",
"ELECTRICAL_GRID",
"URBAN_VEGETATION"
],
category_names=[
"WATER_PIPELINE",
"HIGH_VOLTAGE_LINE",
"PUBLIC_PARK"
]
)
Example 3: Working with MultiPolygon Features
MultiPolygon features are useful for representing discontinuous areas:
# Create a GeoJSON with MultiPolygon for forest patches
forest_patches = {
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"geometry": {
"type": "MultiPolygon",
"coordinates": [
# First forest patch
[[
[2.10, 48.80],
[2.12, 48.80],
[2.12, 48.82],
[2.10, 48.82],
[2.10, 48.80]
]],
# Second forest patch
[[
[2.15, 48.81],
[2.17, 48.81],
[2.17, 48.83],
[2.15, 48.83],
[2.15, 48.81]
]]
]
},
"properties": {
"kili": {
"job": "LAND_COVER",
"type": "semantic",
"categories": [{"name": "DECIDUOUS_FOREST"}]
}
}
}
]
}
# Save and import
with open("forest_patches.geojson", "w") as f:
json.dump(forest_patches, f)
kili.append_labels_from_geojson_files(
project_id="environmental_monitoring",
asset_external_id="sentinel2_composite.tif",
geojson_file_paths=["forest_patches.geojson"]
)
Best Practices
-
Validate Your GeoJSON: Use online validators (see geojson.io) or the
geojson
Python library to ensure your files are valid before import. -
Check Job Compatibility: Ensure your Kili project has jobs with the appropriate tools for your geometry types:
# Check project structure project = kili.projects(project_id="your_project_id", fields=["jsonInterface"])[0] print(json.dumps(project["jsonInterface"]["jobs"], indent=2))
Troubleshooting
Problem: Features Not Appearing
Possible causes and solutions:
-
Incompatible geometry-job combination:
# Check which tools are available for each job project = kili.projects(project_id="your_project_id", fields=["jsonInterface"])[0] for job_name, job_config in project["jsonInterface"]["jobs"].items(): print(f"{job_name}: {job_config.get('tools', [])}")
-
Coordinates outside image bounds: Verify your coordinates match the geographic extent of your image.
Problem: ValueError for Missing Job or Category
Solution: Verify exact names in your project:
# List all jobs and categories
project = kili.projects(project_id="your_project_id", fields=["jsonInterface"])[0]
for job_name, job_config in project["jsonInterface"]["jobs"].items():
categories = job_config.get("content", {}).get("categories", {})