Skip to content

Data Wrangling

This page covers small transformations that are useful after loading data or computing spectral indices.

Work With Raster DataArrays

Every Orthomosaic wraps an xarray.DataArray with shape:

1
(band, y, x)

Access it through mosaic.data. Use xarray and rioxarray methods directly when you need lower-level operations:

1
2
3
4
data = mosaic.data
print(data.dims)
print(data.rio.crs)
print(data.rio.bounds())

Stretch Data For Display

Use VisualizationUtil directly when you need an image array instead of a plot.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
import numpy as np

from uavpy.util import VisualizationUtil

array = np.moveaxis(mosaic.data.compute().values, 0, -1)
rgb_image = VisualizationUtil.raster2image(
    array,
    rgb=(0, 1, 2),
    stretch_method="percentiles",
)

raster2image expects a NumPy array shaped as (height, width, bands) and uses zero-based band indices. By contrast, Orthomosaic.plot(rgb=(1, 2, 3)) uses one-based band indices for user-facing plotting.

Normalize Or Scale Arrays

1
2
3
4
from uavpy.util import MathUtil

normalized = MathUtil.normalize(array)
scaled = MathUtil.scale(array, min_val=0, max_val=255)

Camera Geometry Helpers

1
2
3
4
from uavpy.util import MiscUtil

sensor_size = MiscUtil.sensor_dimensions(field_of_view=25, focal_length=25)
fov = MiscUtil.field_of_view(sensor_dimension=sensor_size, focal_length=25)

Crop By Vector Features

Use Orthomosaic.extract_plots for the common workflow:

1
2
3
4
from uavpy.artifacts import ShapeFile

shape_file = ShapeFile("./data/project/shapefiles/march.shp")
plots = await mosaic.extract_plots(shape_file, plot_id_field="plot_id")

Each returned item is an Orthomosaic, so it can be plotted, indexed, or saved:

1
2
3
for plot in plots:
    plot.plot(rgb=(1, 2, 3), title=str(plot.attrs["plot_id"]))
    plot.save(f"./data/outputs/plot_{plot.attrs['plot_id']}.tif", overwrite=True)

Vector Layers On Maps

ShapeFile can also provide vector data for mapwidgets.VectorLayer:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
import sys

from mapwidgets import MapViewer, VectorLayer
from PySide6.QtWidgets import QApplication
from uavpy.artifacts import ShapeFile

shape_file = ShapeFile("./data/project/shapefiles/march.shp")
await shape_file.load()

app = QApplication.instance() or QApplication(sys.argv[:1])
viewer = MapViewer(backend="maplibre").resize(1200, 800).show()
viewer.add_layer(
    VectorLayer.from_shapefile(shape_file.path, id="plots", name="Plot boundaries"),
    zoom_to=True,
)
viewer.wait_for_map_ready()
app.exec()

GDAL Utility Imports

GDALUtil is loaded lazily from uavpy.util because GDAL's Python bindings require native shared libraries to be available at import time.

1
from uavpy.util import GDALUtil

If this import fails, verify native GDAL first:

1
gdal-config --version