API reference

projectkiwi.connector

class projectkiwi.connector.Connector(key, url='https://projectkiwi.io/')

Bases: object

addAnnotation(annotation: Annotation, project: str) int

Add an annotation to a project

Parameters:
  • annotation (Annotation) – the annotation to add (note that not everything is mandatory)

  • project (str) – project id

Returns:

annotation id if successful

Return type:

int

addImagery(filename: str, name: str, project_id: str) str

Add imagery to projectkiwi.io

Parameters:
  • filename (str) – Path to the file to be uploaded

  • name (str) – Name for the imagery

  • project_id (str) – Id of the project to add the layer to

Returns:

imagery id

Return type:

str

addLabel(name: str, project_id: str, color: Optional[str] = None) Label

add a label to the project

Parameters:
  • name (str) – name of the label e.g. object class

  • project_id (str) – id of the project that the label will belong to

  • color (str, optional) – Color string for the label e.g. rgb(255, 0, 100), will be selected randomly if not supplied. Defaults to None.

Returns:

the label including it’s id

Return type:

Label

addPrediction(annotation: Annotation, project: str) int

Add a prediction to a project

Parameters:
  • annotation (Annotation) – an annotation object with a confidence value

  • project (str) – project id

Returns:

annotation id if successful

Return type:

int

Example

Predictions are annotation objects with a confidence value between 0 and 1. The following example creates a prediction for an already existing object class.

>>> from projectkiwi.models import Annotation
>>> prediction = Annotation(shape='Polygon',
...                        label_id=374,
...                        coordinates=[
...                            [-87.612448, 41.867452],
...                            [-87.605238, 41.867452],
...                            [-87.605238, 41.852301],
...                            [-87.612448, 41.852301],
...                            [-87.612448, 41.867452]],
...                        confidence=0.69
...                        )
>>> id = conn.addPrediction(prediction, project="51f969a5361f")
>>> print(f"prediction id: {id}")
prediction id: 259185
getAnnotations(project_id: str) List[Annotation]

Get all annotations in a project

Parameters:

project_id (str) – id for the project to get the predictions for

Returns:

annotations

Return type:

List[Annotation]

Example

All the annotations for a project can be retrieved using this function. Replace the project id listed below with your own.

>>> annotations = conn.getAnnotations(project_id = "51f696a5361f")
>>> print(annotations[0])
Annotation(shape='Polygon', label_id=374, coordinates=[[-87.612448, 41.867452], [-87.605238, 41.867452], [-87.605238, 41.852301], [-87.612448, 41.852301], [-87.612448, 41.867452]], url=None, imagery_id=None, confidence=None, id=3720, label_name='airport', label_color='rgb(10, 184, 227)')
>>> print(annotations[0].geoJSON()) # as geoJSON
{"type": "Feature", "geometry": {"type": "Polygon", "coordinates": [[-87.612448, 41.867452], [-87.605238, 41.867452], [-87.605238, 41.852301], [-87.612448, 41.852301], [-87.612448, 41.867452]]}, "properties": {"label_id": 374, "name": "airport"}}
getImagery(project_id: str) List[ImageryLayer]

Get a list of imagery layers for a project

Parameters:

project (str) – ID of the project to get all the imagery for.

Returns:

list of imagery layers

Return type:

List[ImageryLayer]

getImageryStatus(imagery_id: str) str

Get the status of imagery

Parameters:

imagery_id (str) – Imagery id

Returns:

status

Return type:

str

getImageryUrl(imagery_id: str, project_id: str) str

Get the url for imagery from it’s id

Parameters:
  • imagery_id (str) – Id for the imagery

  • project_id (str) – Project to look in

Returns:

The url template

Return type:

str

getLabels(project_id: str) List[Label]

Get all labels in a project

Parameters:

project_id (str) – id for the project to get the labels for

Returns:

labels

Return type:

List[Label]

getNextTask(queue_id: int) List[Task]

Get a predictable next task for a queue.

Parameters:

queue_id (int) – The ID of the queue

Returns:

task

Return type:

Task

getPredictions(project_id: str) List[Annotation]

Get all predictions in a project

Parameters:

project_id (str) – id for the project to get the predictions for

Returns:

predictions

Return type:

List[Annotation]

Example

All predictions in a project can be retrieved as follows. Replace the project id shown below with your own.

>>> predictions = conn.getPredictions(project_id="51f969a5361f")
>>> print(predictions)
[Annotation(shape='Polygon', label_id=374, coordinates=[[-87.612448, 41.867452], [-87.605238, 41.867452], [-87.605238, 41.852301], [-87.612448, 41.852301], [-87.612448, 41.867452]], url=None, imagery_id=None, confidence=0.69, id=259184, label_name='airport', label_color='rgb(10, 184, 227)')]
getProjects() List[Project]

Get a list of projects for a user

Returns:

projects

Return type:

List[Projects]

getSuperTile(imagery_id: str, zxy: str, max_zoom: int = 22, padding: int = 0) ndarray

Get a tile as higher resolution, as specified by the max zoom.

Parameters:
  • imagery_id (str) – The ID of the imagery

  • zxy (str) – zxy string to specify the tile e.g. 12/345/678

  • max_zoom (int, optional) – Maximum zoom. Defaults to 22.

  • padding (int, optional) – Number of pixels to read on each side of the tile. Defaults to 0.

Returns:

Image data for the tile.

Return type:

np.ndarray

getTask(queue_id: int) List[Task]

Get a random task for a queue.

Parameters:

queue_id (int) – The ID of the queue

Returns:

task

Return type:

Task

getTasks(queue_id: int) List[Task]

Get a list of tasks in a queue.

Parameters:

queue_id (int) – The ID of the queue

Returns:

list of tasks

Return type:

List[Task]

getTile(imagery_id: str, z: int, x: int, y: int, tile_size: int = 256, tile_buffer: int = 0) ndarray

Download a tile given the z,x,y and id

Parameters:
  • imagery_id (str) – id of the imagery

  • z (int) – zoom

  • x (int) – x tile

  • y (int) – y tile

  • tile_size (int) – width or height of the square tile

  • tile_buffer (int) – number of pixels to read each side of the tile

Returns:

numpy array of tile

Return type:

np.ndarray

getTileList(imagery_id: str, project_id: str, zoom: int) List[Tile]

Get a list of tiles for a given imagery id

Parameters:
  • imageryId (str) – ID of the imagery to retrieve a list of tiles for

  • zoom (int) – Zoom level

Returns:

A list of tiles with zxy and url

Return type:

List[Tile]

removeAllPredictions(project_id: str)

Remove all predictions in a project

Parameters:

project_id (str) – project id

projectkiwi.data

class projectkiwi.data.ProjectKiwiDataSet(conn, tasks, project_id, imagery_id, max_zoom, cache_location=PosixPath('cache'), padding=0, inference=False, make_masks=True, transforms=None)

Bases: object

getAnnotations(project_id)
getTaskTile(task)
imgToTensor(img)
projectkiwi.data.boxSizeFiltering(boxes: List, scores: List, class_ids: List, masks: Optional[List] = None, min_side_length=5)

apply a filter on the smallest allowable side length for bounding boxes

Parameters:
  • boxes (List) – bounding boxes for the objects

  • scores (List) – scores between 0 and 1

  • class_ids (List) – class ids

  • masks (List, optional) – masks if there is a mask-rcnn output. Defaults to None.

  • min_side_length (int, optional) – minimum allowed side length in pixels. Defaults to 5.

Returns:

the boxes, scores, ids and optionally masks

Return type:

_type_

projectkiwi.data.nonMaximumSuppression(boxes: List, scores: List, class_ids: List, masks: Optional[List] = None, iou_threshold=0.3)

apply non-maximum suppression to the output of an object detector

Parameters:
  • boxes (List) – bounding boxes for the objects

  • scores (List) – scores between 0 and 1

  • class_ids (List) – class ids

  • masks (List, optional) – masks if there is a mask-rcnn output. Defaults to None.

  • iou_threshold (float, optional) – maximum overlap permitted, objects with a greater overlap with a higher confidence box will be omitted. Defaults to 0.3.

Returns:

the boxes, scores, ids and optionally masks

Return type:

_type_

projectkiwi.data.scoreThresholding(boxes: List, scores: List, class_ids: List, masks: Optional[List] = None, threshold=0.1)

apply a score threshold a list of boxes etc

Parameters:
  • boxes (List) – bounding boxes for the objects

  • scores (List) – scores between 0 and 1

  • class_ids (List) – class ids

  • masks (List, optional) – masks if there is a mask-rcnn output. Defaults to None.

  • threshold (float, optional) – the threshold to apply, objects with scores below this omitted. Defaults to 0.1.

Returns:

the boxes, scores, ids and optionally masks

Return type:

_type_

projectkiwi.ml

projectkiwi.models

class projectkiwi.models.Annotation(*, shape: str, label_id: int, coordinates: List[List[float]], url: Optional[str] = None, imagery_id: Optional[str] = None, confidence: Optional[float] = None, id: Optional[int] = None, label_name: Optional[str] = None, label_color: Optional[str] = None)

Bases: BaseModel

confidence: Optional[float]
coordinates: List[List[float]]
classmethod from_dict(data: dict, annotation_id: Optional[int] = None)
geoJSON() str

Convert the annotation to a geoJSON string

Returns:

geoJSON representation

Return type:

str

Example

>>>
id: Optional[int]
imagery_id: Optional[str]
label_color: Optional[str]
label_id: int
label_name: Optional[str]
shape: str
url: Optional[str]
class projectkiwi.models.ImageryLayer(*, id: str, project: str, name: str, url: str, attribution: str, size_mb: Optional[float] = None, bounds: Optional[List[float]] = None, min_zoom: Optional[int] = None, max_zoom: Optional[int] = None, status: Optional[str] = None)

Bases: BaseModel

attribution: str
bounds: Optional[List[float]]
id: str
max_zoom: Optional[int]
min_zoom: Optional[int]
name: str
project: str
size_mb: Optional[float]
status: Optional[str]
url: str
class projectkiwi.models.Label(*, id: Optional[int] = None, project_id: str, color: str, name: str, status: str)

Bases: BaseModel

color: str
id: Optional[int]
name: str
project_id: str
status: str
class projectkiwi.models.Project(*, name: str, id: str, user_login: str)

Bases: BaseModel

classmethod from_dict(data: dict)
id: str
name: str
user_login: str
class projectkiwi.models.Task(*, complete: bool, id: int, imagery_id: str, queue: int, submitter_login: Optional[str] = None, zxy: str)

Bases: BaseModel

complete: bool
id: int
imagery_id: str
queue: int
submitter_login: Optional[str]
zxy: str
class projectkiwi.models.Tile(*, zxy: str, imagery_id: str, url: str, z: int, x: int, y: int)

Bases: BaseModel

classmethod from_zxy(zxy: str, imagery_id: str, url: str)
imagery_id: str
url: str
x: int
y: int
z: int
zxy: str

projectkiwi.tools

projectkiwi.tools.bboxFromCoords(coordinates: List[List], zxy: str, tile_size: int, clip: bool = False)

Get a bounding box from a polygon (lng, lat)

Parameters:
  • coordinates (List[List]) – List of points in polygon (lng, lat)

  • zxy (str) – Tile zxy

  • tile_size (int) – size of tile, e.g. 256

  • clip (Optional[bool]) – Clip the boxes to the edge of the tiles

Returns:

top-left x coordinate y1 (int): top-left y coordinate x2 (int): bottom-right x coordinate y2 (int): bottom-right y coordinate

Return type:

x1 (int)

projectkiwi.tools.bboxToCoco(x1: int, y1: int, x2: int, y2: int)

Convert two-point bbox to coco format

Parameters:
  • x1 (int) – top-left x coordinate

  • y1 (int) – top-left y coordinate

  • x2 (int) – bottom-right x coordinate

  • y2 (int) – bottom-right y coordinate

Returns:

top-left x coordinate y (int): top-left y coordinate w (int): box width h (int): box height

Return type:

x (int)

projectkiwi.tools.bboxToPolygon(x1, y1, x2, y2)

Get a 4 point polygon from a bounding box.

Parameters:
  • x1 (float) – left edge

  • y1 (float) – top edge

  • x2 (float) – right edge

  • y2 (float) – bottom edge

Returns:

polygon

Return type:

List[List[float]]

projectkiwi.tools.bbox_iou(box1: List, box2: List) float

calculate the intersection over union of two bounding boxes

Parameters:
  • box1 (List) – first box

  • box2 (List) – second box

Returns:

the iou

Return type:

float

projectkiwi.tools.coordsFromBbox(x1: int, y1: int, x2: int, y2: int, zxy: str, width: int, height: int) List[List[float]]

Get lng,lat coordinate list from a bounding box and width height

Parameters:
  • x1 (int) – left edge

  • y1 (int) – top edge

  • x2 (int) – right edge

  • y2 (int) – bottom edge

  • zxy (str) – tile e.g. 12/345/678

  • width (int) – tile width in pixels

  • height (int) – tile height in pixels

Returns:

coordinate for polygon

Return type:

List[List[float]]

projectkiwi.tools.coordsFromPolygon(polygon: List[List[float]], zxy: str, tile_size: int, padding: int = 0) List[List[float]]

get a lat/lng polygon from a polygon in a tile

Parameters:
  • polygon (List[List[float]]) – coordinates in the image [[y,x],[y,x]]

  • zxy (str) – zxy string for the tile e.g. 12/34/567

  • width (int) – width of the tile

  • height (int) – height of the tile

  • padding (int, optional) – number of extra pixels around the edge of the tile. Defaults to 0.

Returns:

coordinates in [[lng,lat],[lng,lat]] format

Return type:

List[List[float]]

projectkiwi.tools.deg2num(lat_deg: float, lon_deg: float, zoom: int)

Convert lat,lng to xyz tile coordinates. reference: https://developers.planet.com/docs/planetschool/xyz-tiles-and-slippy-maps/

Parameters:
  • lat_deg (float) – latitude in decimal degrees

  • lon_deg (float) – longitude in decimal degrees

  • zoom (int) – zoom level e.g. 19

Returns:

x in tile coordinates at specified zoom level y_tile (float): y in tile coordinates at specified zoom level

Return type:

x_tile (float)

projectkiwi.tools.getAnnotationsForTile(annotations: List[Annotation], zxy: str, overlap_threshold: float = 0.2) List[Annotation]

Filter a set of annotations for those that have overlap with some tile

Parameters:
  • annotations (List[Annotation]) – Annotations to filter

  • zxy (str) – The tile e.g. 12/345/678

  • overlap_threshold (float, optional) – How much overlap. Defaults to 0.2.

Returns:

All the annotations that have enough overlap with the specified tile

Return type:

List[Annotation]

projectkiwi.tools.getBboxLatLng(coords: List[List])

Get bounding box for a polygon.

Parameters:

coords (List[List]) – list of points (x,y) = (lng,lat) with bottom left reference (e.g. [[lng,lat], [lng,lat]])

Returns:

closest distance from left reference y1 (float): closest distance from top reference x2 (float): furthest distance from left reference y2 (float): furthest distance from top reference

Return type:

x1 (float)

projectkiwi.tools.getBboxTileCoords(coords: List[List], zxy: str)

Get bounding box for a polygon. output is in tile coordinates

Parameters:

coords (List[List]) – list of points (x,y) = (lng,lat) with bottom left reference (e.g. [[lng,lat], [lng,lat]])

Returns:

closest distance from tile left side y1 (float): closest distance from tile top side x2 (float): furthest distance from tile left side y2 (float): furthest distance from tile top side

Return type:

x1 (float)

projectkiwi.tools.getOverlap(coords: List[List], zxy: str)

Get the portion of a bounding box that is inside a tile

Parameters:
  • coords (List[List]) – list of points in the polygon (lat,lng)

  • zxy (str) – tile e.g. 12/345/678

Returns:

overlap [0,1]

Return type:

float

projectkiwi.tools.iou(poly1: List[List], poly2: List[List]) float

calculate the iou of each polygon

Parameters:
  • poly1 (List[List]) – list of points in the first polygon e.g. [[x,y], [x,y]]

  • poly2 (List[List]) – list of points in the second polygon e.g. [[x,y], [x,y]]

Returns:

iou between the polygons.

Return type:

float

projectkiwi.tools.latLngToImgCoords(coords: List[List], zxy: str, tile_size: int) List[List]

convert a list of coordinates to pixel coordinates in a tile

Parameters:
  • coords (List[List]) – coordinates e.g. [[lng,lat], [lng, lat]]

  • zxy (str) – tile zxy string e.g. 12/34/567

  • tile_size (int) – width of the tile e.g. 256 - dont forget padding

Returns:

_description_

Return type:

List[List]

projectkiwi.tools.maskFromPolygon(polygon: List[List], width: int, height: int) ndarray

generates a binary mask from a polygon in image coordinates

Parameters:
  • polygon (List[List]) – list of points in the polygon, image coordinates

  • width (int) – width of the output mask

  • height (int) – height of the output mask

Returns:

the binary image

Return type:

np.ndarray

projectkiwi.tools.num2deg(xtile: Union[float, int], ytile: Union[float, int], zoom: int)

convert x, y, tile coordinates to lat, lng. ref: https://developers.planet.com/docs/planetschool/xyz-tiles-and-slippy-maps/

Parameters:
  • xtile (Union[float, int]) – x position

  • ytile (Union[float, int]) – y position

  • zoom (int) – zoom level e.g. 19

Returns:

latitude in decimal degrees lng_deg (float): longitude in decimal degrees

Return type:

lat_deg (float)

projectkiwi.tools.splitZXY(zxy: str)

Split an zxy string up in to z,x,y component

Parameters:

zxy (str) – zxy string e.g. 12/345/678

Returns:

tile zoom level x: tile x y: tile y

Return type:

z

Example

Consider splitting the zxy string “12/345/678”:

z, x, y = splitZXY("12/345/678")
print(z,x,y)
# result: 12, 345, 678
projectkiwi.tools.urlFromZxy(z: int, x: int, y: int, imagery_id: str, baseUrl: str, serverless: bool = True) str

Generate a url given a zxy and an imagery id

Parameters:
  • z (int) – zoom

  • x (int) – x tile

  • y (int) – y tile

  • imagery_id (str) – id of the imagery

  • baseUrl (str) – base url e.g. https://projectkiwi.io/

  • serverless (bool) – whether to use tiles from lambda or direct from the api. Defaults to True.

Returns:

url to download the tile, however api key is still required as a param

Return type:

str

projectkiwi.tools.yx_to_xy(yx: List[List]) List[List]

“ switch the ordering in our array, explicitely so we dont forget

Parameters:

yx (List[List]) – [[y,x], [y,x]]

Returns:

[[x,y], [x,y]]

Return type:

List[List]

projectkiwi.transforms

class projectkiwi.transforms.Compose(transforms)

Bases: object

class projectkiwi.transforms.ConvertImageDtype(dtype: dtype)

Bases: Module

forward(image: Tensor, target: Optional[Dict[str, Tensor]] = None) Tuple[Tensor, Optional[Dict[str, Tensor]]]

Defines the computation performed at every call.

Should be overridden by all subclasses.

Note

Although the recipe for forward pass needs to be defined within this function, one should call the Module instance afterwards instead of this since the former takes care of running the registered hooks while the latter silently ignores them.

training: bool
class projectkiwi.transforms.FixedSizeCrop(size, fill=0, padding_mode='constant')

Bases: Module

forward(img, target=None)

Defines the computation performed at every call.

Should be overridden by all subclasses.

Note

Although the recipe for forward pass needs to be defined within this function, one should call the Module instance afterwards instead of this since the former takes care of running the registered hooks while the latter silently ignores them.

training: bool
class projectkiwi.transforms.PILToTensor

Bases: Module

forward(image: Tensor, target: Optional[Dict[str, Tensor]] = None) Tuple[Tensor, Optional[Dict[str, Tensor]]]

Defines the computation performed at every call.

Should be overridden by all subclasses.

Note

Although the recipe for forward pass needs to be defined within this function, one should call the Module instance afterwards instead of this since the former takes care of running the registered hooks while the latter silently ignores them.

training: bool
class projectkiwi.transforms.RandomHorizontalFlip(p=0.5)

Bases: RandomHorizontalFlip

forward(image: Tensor, target: Optional[Dict[str, Tensor]] = None) Tuple[Tensor, Optional[Dict[str, Tensor]]]
Parameters:

img (PIL Image or Tensor) – Image to be flipped.

Returns:

Randomly flipped image.

Return type:

PIL Image or Tensor

training: bool
class projectkiwi.transforms.RandomIoUCrop(min_scale: float = 0.3, max_scale: float = 1.0, min_aspect_ratio: float = 0.5, max_aspect_ratio: float = 2.0, sampler_options: Optional[List[float]] = None, trials: int = 40)

Bases: Module

forward(image: Tensor, target: Optional[Dict[str, Tensor]] = None) Tuple[Tensor, Optional[Dict[str, Tensor]]]

Defines the computation performed at every call.

Should be overridden by all subclasses.

Note

Although the recipe for forward pass needs to be defined within this function, one should call the Module instance afterwards instead of this since the former takes care of running the registered hooks while the latter silently ignores them.

training: bool
class projectkiwi.transforms.RandomPhotometricDistort(contrast: Tuple[float, float] = (0.5, 1.5), saturation: Tuple[float, float] = (0.5, 1.5), hue: Tuple[float, float] = (-0.05, 0.05), brightness: Tuple[float, float] = (0.875, 1.125), p: float = 0.5)

Bases: Module

forward(image: Tensor, target: Optional[Dict[str, Tensor]] = None) Tuple[Tensor, Optional[Dict[str, Tensor]]]

Defines the computation performed at every call.

Should be overridden by all subclasses.

Note

Although the recipe for forward pass needs to be defined within this function, one should call the Module instance afterwards instead of this since the former takes care of running the registered hooks while the latter silently ignores them.

training: bool
class projectkiwi.transforms.RandomShortestSize(min_size: Union[List[int], Tuple[int], int], max_size: int, interpolation: InterpolationMode = InterpolationMode.BILINEAR)

Bases: Module

forward(image: Tensor, target: Optional[Dict[str, Tensor]] = None) Tuple[Tensor, Optional[Dict[str, Tensor]]]

Defines the computation performed at every call.

Should be overridden by all subclasses.

Note

Although the recipe for forward pass needs to be defined within this function, one should call the Module instance afterwards instead of this since the former takes care of running the registered hooks while the latter silently ignores them.

training: bool
class projectkiwi.transforms.RandomZoomOut(fill: Optional[List[float]] = None, side_range: Tuple[float, float] = (1.0, 4.0), p: float = 0.5)

Bases: Module

forward(image: Tensor, target: Optional[Dict[str, Tensor]] = None) Tuple[Tensor, Optional[Dict[str, Tensor]]]

Defines the computation performed at every call.

Should be overridden by all subclasses.

Note

Although the recipe for forward pass needs to be defined within this function, one should call the Module instance afterwards instead of this since the former takes care of running the registered hooks while the latter silently ignores them.

training: bool
class projectkiwi.transforms.ScaleJitter(target_size: Tuple[int, int], scale_range: Tuple[float, float] = (0.1, 2.0), interpolation: InterpolationMode = InterpolationMode.BILINEAR)

Bases: Module

Randomly resizes the image and its bounding boxes within the specified scale range. The class implements the Scale Jitter augmentation as described in the paper “Simple Copy-Paste is a Strong Data Augmentation Method for Instance Segmentation”.

Parameters:
  • target_size (tuple of ints) – The target size for the transform provided in (height, weight) format.

  • scale_range (tuple of ints) – scaling factor interval, e.g (a, b), then scale is randomly sampled from the range a <= scale <= b.

  • interpolation (InterpolationMode) – Desired interpolation enum defined by torchvision.transforms.InterpolationMode. Default is InterpolationMode.BILINEAR.

forward(image: Tensor, target: Optional[Dict[str, Tensor]] = None) Tuple[Tensor, Optional[Dict[str, Tensor]]]

Defines the computation performed at every call.

Should be overridden by all subclasses.

Note

Although the recipe for forward pass needs to be defined within this function, one should call the Module instance afterwards instead of this since the former takes care of running the registered hooks while the latter silently ignores them.

training: bool
class projectkiwi.transforms.SimpleCopyPaste(blending=True, resize_interpolation=InterpolationMode.BILINEAR)

Bases: Module

forward(images: List[Tensor], targets: List[Dict[str, Tensor]]) Tuple[List[Tensor], List[Dict[str, Tensor]]]

Defines the computation performed at every call.

Should be overridden by all subclasses.

Note

Although the recipe for forward pass needs to be defined within this function, one should call the Module instance afterwards instead of this since the former takes care of running the registered hooks while the latter silently ignores them.

training: bool