Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Misc. documentation improvements #1840

Merged
merged 3 commits into from
Jul 21, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,10 @@ def setup(app: 'Sphinx') -> None:
'https://pytorch.org/docs/stable/',
'https://pytorch.org/docs/stable/objects.inv',
),
'onnx': (
'https://onnx.ai/onnx/',
'https://onnx.ai/onnx/objects.inv',
),
}

#########################
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from typing import Any, Optional
from typing import Any, Optional, Union
from pyproj import Transformer

import numpy as np
Expand Down Expand Up @@ -99,10 +99,16 @@ def _pixel_to_map(self, pixel_point):
return map_point

@classmethod
def from_dataset(cls,
dataset,
map_crs: Optional[str] = 'epsg:4326',
**kwargs) -> 'RasterioCRSTransformer':
def from_dataset(
cls, dataset: Any, map_crs: Optional[str] = 'epsg:4326', **kwargs
) -> Union[IdentityCRSTransformer, 'RasterioCRSTransformer']:
"""Build from rasterio dataset.

Args:
dataset (Any): Rasterio dataset.
map_crs (Optional[str]): Target map CRS. Defaults to 'epsg:4326'.
**kwargs: Extra args for :meth:`.__init__`.
"""
transform = dataset.transform
image_crs = None if dataset.crs is None else dataset.crs.wkt
map_crs = image_crs if map_crs is None else map_crs
Expand All @@ -118,7 +124,14 @@ def from_dataset(cls,
return cls(transform, image_crs, map_crs, **kwargs)

@classmethod
def from_uri(cls, uri: str, map_crs: Optional[str] = 'epsg:4326',
**kwargs) -> 'RasterioCRSTransformer':
def from_uri(cls, uri: str, map_crs: Optional[str] = 'epsg:4326', **kwargs
) -> Union[IdentityCRSTransformer, 'RasterioCRSTransformer']:
"""Build from raster URI.

Args:
uri (Any): Raster URI.
map_crs (Optional[str]): Target map CRS. Defaults to 'epsg:4326'.
**kwargs: Extra args for :meth:`.__init__`.
"""
with rio.open(uri) as ds:
return cls.from_dataset(ds, map_crs=map_crs, **kwargs)
14 changes: 8 additions & 6 deletions rastervision_core/rastervision/core/data/label/labels.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
"""Defines the abstract Labels class."""

from typing import TYPE_CHECKING, Any, Iterable
from typing import TYPE_CHECKING, Any, Iterable, List
from abc import (ABC, abstractclassmethod, abstractmethod)

if TYPE_CHECKING:
from shapely.geometry import Polygon
from rastervision.core.box import Box


Expand All @@ -15,24 +16,25 @@ class Labels(ABC):
"""

@abstractmethod
def __add__(self, other):
def __add__(self, other: 'Labels'):
"""Add labels to these labels.

Returns a concatenation of this and the other labels.
"""
pass

@abstractmethod
def filter_by_aoi(self, aoi_polygons):
"""Returns a copy of these labels filtered by a given set of AOI polygons
def filter_by_aoi(self, aoi_polygons: List['Polygon']) -> 'Labels':
"""Return a copy of these labels filtered by given AOI polygons.

Args:
aoi_polygons - A list of AOI polygons to filter by, in pixel coordinates.
aoi_polygons: List of AOI polygons to filter by, in pixel
coordinates.
"""
pass

@abstractmethod
def __eq__(self, other):
def __eq__(self, other: 'Labels'):
pass

@abstractmethod
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

from rastervision.core.box import Box
from rastervision.core.data.label.labels import Labels
from rastervision.core.data.label.tfod_utils.np_box_list import BoxList
from rastervision.core.data.label.tfod_utils.np_box_list import NpBoxList
from rastervision.core.data.label.tfod_utils.np_box_list_ops import (
prune_non_overlapping_boxes, clip_to_window, concatenate,
non_max_suppression)
Expand Down Expand Up @@ -33,7 +33,7 @@ def __init__(self,
class_ids: int numpy array of size n with class ids
scores: float numpy array of size n
"""
self.boxlist = BoxList(npboxes)
self.boxlist = NpBoxList(npboxes)
# This field name actually needs to be 'classes' to be able to use
# certain utility functions in the TF Object Detection API.
self.boxlist.add_field('classes', class_ids)
Expand Down Expand Up @@ -103,7 +103,7 @@ def make_empty(cls) -> 'ObjectDetectionLabels':
return cls(npboxes, class_ids, scores)

@staticmethod
def from_boxlist(boxlist: BoxList):
def from_boxlist(boxlist: NpBoxList):
"""Make ObjectDetectionLabels from BoxList object."""
scores = (boxlist.get_field('scores')
if boxlist.has_field('scores') else None)
Expand Down Expand Up @@ -166,7 +166,7 @@ def __len__(self) -> int:
def __str__(self) -> str:
return str(self.boxlist.get())

def to_boxlist(self) -> BoxList:
def to_boxlist(self) -> NpBoxList:
return self.boxlist

def to_dict(self, round_boxes: bool = True) -> dict:
Expand Down Expand Up @@ -245,7 +245,7 @@ def get_overlapping(labels: 'ObjectDetectionLabels',
clip: If True, clip label boxes to the window.
"""
window_npbox = window.npbox_format()
window_boxlist = BoxList(np.expand_dims(window_npbox, axis=0))
window_boxlist = NpBoxList(np.expand_dims(window_npbox, axis=0))
boxlist = prune_non_overlapping_boxes(
labels.boxlist, window_boxlist, minoverlap=ioa_thresh)
if clip:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
from rastervision.core.data.label.utils import discard_prediction_edges

if TYPE_CHECKING:
from shapely.geometry import Polygon
from rastervision.core.data import (ClassConfig, CRSTransformer,
VectorOutputConfig)

Expand Down Expand Up @@ -66,21 +67,34 @@ def get_label_arr(self, window: Box,
pass

def get_windows(self, **kwargs) -> List[Box]:
"""Generate sliding windows over the local extent. The keyword args
are passed to Box.get_windows() and can therefore be used to control
the specifications of the windows.
"""Generate sliding windows over the local extent.

The keyword args are passed to :meth:`.Box.get_windows` and can
therefore be used to control the specifications of the windows.

If the keyword args do not contain size, a list of length 1,
containing the full extent is returned.

Args:
**kwargs: Extra args for :meth:`.Box.get_windows`.
"""
size: Optional[int] = kwargs.pop('size', None)
if size is None:
return [self.extent]
return self.extent.get_windows(size, size, **kwargs)

def filter_by_aoi(self, aoi_polygons: list, null_class_id: int,
def filter_by_aoi(self, aoi_polygons: List['Polygon'], null_class_id: int,
**kwargs) -> 'SemanticSegmentationLabels':
"""Keep only the values that lie inside the AOI."""
"""Keep only the values that lie inside the AOI.

Args:
aoi_polygons (List[Polygon]): AOI polygons to filter by, in pixel
coordinates.
null_class_id (int): Class ID to assign to pixels falling outside
the AOI polygons.
**kwargs: Extra args for
:meth:`.SemanticSegmentationLabels.get_windows`.
"""
if not aoi_polygons:
return self
for window in self.get_windows(**kwargs):
Expand All @@ -95,7 +109,7 @@ def mask_fill(self, window: Box, mask: np.ndarray,
"""
pass

def _filter_window_by_aoi(self, window: Box, aoi_polygons: list,
def _filter_window_by_aoi(self, window: Box, aoi_polygons: List['Polygon'],
null_class_id: int) -> None:
window_geom = window.to_shapely()
label_arr = self[window]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
import numpy as np


class BoxList(object):
class NpBoxList(object):
"""A list of bounding boxes as a [y_min, x_min, y_max, x_max] numpy array.

It is assumed that all bounding boxes within a given list correspond to a
Expand Down
Loading