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

docs: add examples to package level documentation #30

Merged
merged 1 commit into from
Dec 11, 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
111 changes: 15 additions & 96 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,24 @@

The OversightML Imagery Toolkit is a Python package that contains image processing and photogrammetry routines commonly
used during the analysis of imagery collected by satellites and unmanned aerial vehicles (UAVs). It builds upon GDAL
by providing additional support for images compliant with the National Imagery Transmission Format (NITF) and Sensor
Independent Complex Data (SICD) standards.
by providing additional support for images compliant with the National Imagery Transmission Format (NITF), Sensor
Independent Complex Data (SICD), and Sensor Independent Derived Data (SIDD) standards.

This library contains four core packages under the `aws.osml` namespace:
* **photogrammetry**: convert locations between the image (x, y) and geodetic (lon, lat, elev) coordinate systems
* **gdal**: utilities to work with datasets loaded by GDAL
* **image_processing**: common image manipulation routines
* **features**: common geospatial feature manipulation routines

## Documentation

* **APIs**: You can find API documentation for the OSML Imagery Toolkit hosted on our [GitHub project page](https://aws-solutions-library-samples.github.io/osml-imagery-toolkit/).
If you are working from the source code running `tox -e docs` will trigger the Sphinx documentation build.
* **Example Notebooks**: Example notebooks for some operations are in the `examples` directory
## Installation

The intent is to vend / distribute this software through a Python Package Index.
If your environment has a distribution,
you should be able to install it using pip:
This software is available through a Python Package Index.
If your environment has a distribution, you should be able to install it using pip:
```shell
pip install osml-imagery-toolkit[gdal]
```
Expand All @@ -23,97 +33,6 @@ Note that GDAL is listed as an extra dependency for this package. This is done t
don't want to use GDAL or those that have their own custom installation steps for that library. Future versions of
this package will include image IO backbones that have fewer dependencies.


## Documentation

You can find documentation for this library in the `./doc` directory. Sphinx is used to construct a searchable HTML
version of the API documents.

```shell
tox -e docs
```

## Example Usage

This library contains four core packages under the `aws.osml` namespace.
* photogrammetry: convert locations between the image (x, y) and geodetic (lon, lat, elev) coordinate systems
* gdal: help load and manage datasets loaded by GDAL
* image_processing: common image manipulation routines
* formats: utilities for handling format specific information; normally not accessed directly

```python
from aws.osml.gdal import GDALImageFormats, GDALCompressionOptions, load_gdal_dataset
from aws.osml.image_processing import GDALTileFactory
from aws.osml.photogrammetry import ImageCoordinate, GeodeticWorldCoordinate, SensorModel
```

### Tiling with Updated Image Metadata

Many applications break large remote sensing images into smaller chips or tiles for distributed processing or
dissemination. GDAL's Translate function provides basic capabilities, but it does not correctly update geospatial
metadata to reflect the new image extent. These utilities provide those functions so tile consumers can correctly
interpret the pixel information they have been provided. For NITF imagery that includes the addition of a new ICHIPB
TRE. With SICD the XML ImageData elements are adjusted to identify the sub-image bounds.

```python
# Load the image and create a sensor model
ds, sensor_model = load_gdal_dataset("./imagery/sample.nitf")
tile_factory = GDALTileFactory(ds,
sensor_model,
GDALImageFormats.NITF,
GDALCompressionOptions.NONE
)

# Bounds are [left_x, top_y, width, height]
nitf_encoded_tile_bytes = tile_factory.create_encoded_tile([0, 0, 1024, 1024])
```

### Tiling for Display

Some images, for example 11-bit panchromatic images or SAR imagery with floating point complex data, can not be
displayed directly without remapping the pixels into an 8-bit per pixel grayscale or RGB color model. The TileFactory
supports creation of tiles suitable for human review by setting both the output_type and range_adjustment options.

```python
viz_tile_factory = GDALTileFactory(ds,
sensor_model,
GDALImageFormats.PNG,
GDALCompressionOptions.NONE,
output_type=gdalconst.GDT_Byte,
range_adjustment=RangeAdjustmentType.DRA)

viz_tile = viz_tile_factory.create_encoded_tile([0, 0, 1024, 1024])
```

### More Precise Sensor Models

OversightML provides implementations of the Replacement Sensor Model (RSM), Rational Polynomial
Camera (RPC), and Sensor Independent Complex Data (SICD) sensor models to assist in geo positioning.
When loading a dataset, the toolkit will construct the most accurate sensor model
from the available image metadata. That sensor model can be used in conjunction with an optional
elevation model to convert between image and geodetic coordinates.

```python
ds, sensor_model = load_gdal_dataset("./imagery/sample.nitf")
elevation_model = DigitalElevationModel(
SRTMTileSet(version="1arc_v3"),
GDALDigitalElevationModelTileFactory("./local-SRTM-tiles"))

# Note the order of ImageCoordinate is (x, y)
geodetic_location_of_ul_corner = sensor_model.image_to_world(
ImageCoordinate([0, 0]),
elevation_model=elevation_model)

lon_degrees = -77.404453
lat_degrees = 38.954831
meters_above_ellipsoid = 100.0

image_location = sensor_model.world_to_image(
GeodeticWorldCoordinate([radians(lon_degrees),
radians(lat_degrees),
meters_above_ellipsoid]))
```

## Contributing

This project welcomes contributions and suggestions. If you would like to submit a pull request, see our
Expand Down
2 changes: 1 addition & 1 deletion doc/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ def setup(app):
# -- Project information -----------------------------------------------------
# https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information

project = "OversightML Imagery Core"
project = "OversightML Imagery Toolkit"
copyright = "{}, Amazon.com".format(datetime.datetime.now().year)
author = "Amazon Web Services"

Expand Down
Binary file added doc/images/Photogrammetry-OODiagram.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added doc/images/SAR-HistogramStretchImage.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added doc/images/SAR-QuarterPowerImage.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
8 changes: 4 additions & 4 deletions doc/index.rst
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@

aws-osml-imagery-core
osml-imagery-toolkit
=====================

The OversightML Imagery Core is a Python library that contains image processing and photogrammetry routines commonly
The OversightML Imagery Toolkit is a Python package that contains image processing and photogrammetry routines commonly
used during the analysis of imagery collected by satellites and unmanned aerial vehicles (UAVs). It builds upon GDAL
by providing additional support for images compliant with the Sensor Independent Complex Data (SICD) and National
Imagery Transmission Format (NITF) standards.
by providing additional support for images compliant with the National Imagery Transmission Format (NITF), Sensor
Independent Complex Data (SICD), and Sensor Independent Derived Data (SIDD) standards.

.. toctree::
:maxdepth: 1
Expand Down
4 changes: 4 additions & 0 deletions src/aws/osml/features/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
from .feature_index import Feature2DSpatialIndex, STRFeature2DSpatialIndex
from .imaged_feature_property_accessor import ImagedFeaturePropertyAccessor

"""
The features package contains classes that assist with working with geospatial features derived from imagery.
"""

__all__ = [
"Feature2DSpatialIndex",
"ImagedFeaturePropertyAccessor",
Expand Down
54 changes: 54 additions & 0 deletions src/aws/osml/gdal/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,60 @@
# flake8: noqa
"""
The gdal package contains utilities that assist with loading imagery and metadata using the OSGeo GDAL library.

Loading Imagery and Sensor Models with OSML
*******************************************

OSML provides utilities to load a dataset and automatically construct an appropriate sensor model from metadata
available in the image. Metadata handled by GDAL (e.g. GeoTIFF tags or NITF segment metadata and TREs) is available
through the dataset accessors.

.. code-block:: python
:caption: Example of loading a dataset and sensor model using OSML

from aws.osml.gdal import load_gdal_dataset

# Load the image and create a sensor model
dataset, sensor_model = load_gdal_dataset("./imagery/sample.nitf")
width = dataset.RasterXSize
height = dataset.RasterYSize

print(f"Loaded image with dimensions: ({height}, {width}) (rows, cols)")
print(f"Using Sensor Model Implementation: {type(sensor_model).__name__}")
print(dataset.GetMetadata())


Access to NITF Data Extension Segments
**************************************

SICD and SIDD imagery contains additional metadata in a XML Data Extension Segment that is not currently processed
by GDAL. This information can be accessed with the help of the NITFDESAccessor.

.. code-block:: python
:caption: Example of loading a dataset and sensor model using OSML

import base64
import xml.dom.minidom
from aws.osml.gdal import load_gdal_dataset, NITFDESAccessor

dataset, sensor_model = load_gdal_dataset("./sample-sicd.nitf")

des_accessor = NITFDESAccessor(dataset.GetMetadata("xml:DES"))
xml_data_content_segments = des_accessor.get_segments_by_name("XML_DATA_CONTENT")
if xml_data_content_segments is not None:
for xml_data_segment in xml_data_content_segments:
xml_bytes = des_accessor.parse_field_value(xml_data_segment, "DESDATA", base64.b64decode)
xml_str = xml_bytes.decode("utf-8")
if "SICD" in xml_str:
temp = xml.dom.minidom.parseString(xml_str)
new_xml = temp.toprettyxml()
print(new_xml)
break

-------------------------

APIs
****
"""

from .gdal_config import GDALConfigEnv, set_gdal_default_configuration
Expand Down
87 changes: 86 additions & 1 deletion src/aws/osml/image_processing/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,94 @@
# flake8: noqa
"""
The image_processing package contains various utilities for manipulating overhead imagery.

Image Tiling: Tiling With Updated Image Metadata
************************************************

Many applications break large remote sensing images into smaller chips or tiles for distributed processing or
dissemination. GDAL's Translate function provides basic capabilities, but it does not correctly update geospatial
metadata to reflect the new image extent. These utilities provide those functions so tile consumers can correctly
interpret the pixel information they have been provided.

.. code-block:: python
:caption: Example showing creation of a NITF tile from the upper left corner of an image

# Load the image and create a sensor model
ds, sensor_model = load_gdal_dataset("./imagery/sample.nitf")
tile_factory = GDALTileFactory(ds,
sensor_model,
GDALImageFormats.NITF,
GDALCompressionOptions.NONE
)

# Bounds are [left_x, top_y, width, height]
nitf_encoded_tile_bytes = tile_factory.create_encoded_tile([0, 0, 1024, 1024])


Image Tiling: Tiles for Display
*******************************

Some images, for example 11-bit panchromatic images or SAR imagery with floating point complex data, can not be
displayed directly without remapping the pixels into an 8-bit per pixel grayscale or RGB color model. The TileFactory
supports creation of tiles suitable for human review by setting both the output_type and range_adjustment options.
Note that the output_size parameter can be used to generate lower resolution tiles. This operation will make use of
GDAL generated overviews if they are available to the dataset.

.. code-block:: python
:caption: Example showing creation of a PNG tile scaled down from the full resolution image

viz_tile_factory = GDALTileFactory(ds,
sensor_model,
GDALImageFormats.PNG,
GDALCompressionOptions.NONE,
output_type=gdalconst.GDT_Byte,
range_adjustment=RangeAdjustmentType.DRA)

viz_tile = viz_tile_factory.create_encoded_tile([0, 0, 1024, 1024], output_size=(512, 512))


Complex SAR Data Display
************************

There are a variety of different techniques to convert complex SAR data to a simple image suitable for human display.
The toolkit contains two helper functions that can convert complex image data into an 8-bit grayscle representation
The equations implemented are described in Sections 3.1 and 3.2 of SAR Image Scaling, Dynamic Range, Radiometric
Calibration, and Display (SAND2019-2371).

.. code-block:: python
:caption: Example converting complex SAR data into a 8-bit per pixel image for display

import numpy as np
from aws.osml.image_processing import histogram_stretch, quarter_power_image

sicd_dataset, sensor_model = load_gdal_dataset("./sample-sicd.nitf")
complex_pixels = sicd_dataset.ReadAsArray()

histo_stretch_pixels = histogram_stretch(complex_pixels)
quarter_power_pixels = quarter_power_image(complex_pixels)


.. figure:: ../images/SAR-HistogramStretchImage.png
:width: 400
:alt: Histogram Stretch Applied to Sample SICD Image

Example of applying histogram_stretch to a sample SICD image.


.. figure:: ../images/SAR-QuarterPowerImage.png
:width: 400
:alt: Quarter Power Image Applied to Sample SICD Image

Example of applying quarter_power_image to a sample SICD image.


-------------------------

APIs
****
"""

from .gdal_tile_factory import GDALTileFactory
from .sar_complex_imageop import histogram_stretch, quarter_power_image

__all__ = ["GDALTileFactory"]
__all__ = ["GDALTileFactory", "histogram_stretch", "quarter_power_image"]
Loading