API reference

projectkiwi.connector

class projectkiwi.connector.Connector(key, url='https://project-kiwi.org/')

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 project-kiwi.org

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://project-kiwi.org/

  • 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