Imagery Module¶
The imagery module provides core functionality for loading, managing, and manipulating multi-frame imagery datasets.
Core Classes¶
Container for multi-frame imagery datasets with metadata and coordinate conversion capabilities. |
The Imagery class is the foundation for working with image data in VISTA. It provides:
Loading and saving imagery from various formats
Frame-based indexing and slicing
Area of interest (AOI) extraction
Integration with time and geodetic coordinate systems
Support for sensor metadata
Basic Usage¶
Creating and Loading Imagery¶
from vista.imagery import Imagery
# Load from file
img = Imagery.from_file('path/to/data.h5')
# Access imagery properties
print(f"Shape: {img.shape}")
print(f"Number of frames: {img.num_frames}")
print(f"Frame rate: {img.frame_rate}")
Slicing and Subsetting¶
# Get a single frame
frame_10 = img[10]
# Get a range of frames
frames = img[10:20]
# Get an area of interest
aoi = img.get_aoi(x_min=100, x_max=200, y_min=100, y_max=200)
Working with Copies¶
# Create a deep copy
img_copy = img.copy()
# Modify the copy without affecting the original
img_copy.data *= 2.0
Module Reference¶
Module that contains the default imagery object
The Imagery object in this class can be subclassed by third-party objects to implement their own logic including file readers and pixel-to-geodetic conversions
- class vista.imagery.imagery.Imagery(name, images, frames, sensor, row_offset=None, column_offset=None, times=None, description='', _histograms=None, default_histogram_bounds=None)[source]¶
Bases:
objectContainer for multi-frame imagery datasets with metadata and coordinate conversion capabilities.
VISTA’s Imagery class represents a temporal sequence of image frames with associated metadata including timestamps, geodetic coordinate conversion polynomials, and sensor calibration data. This class serves as the foundation for all image-based analysis in VISTA.
Core Attributes¶
- namestr
Human-readable identifier for this imagery dataset
- imagesNDArray[np.float32]
3D array of image data with shape (num_frames, height, width). Pixel values are stored as 32-bit floats to support processing operations.
- framesNDArray[np.int_]
1D array of frame numbers corresponding to each image. Frame numbers need not be sequential or start at zero.
- row_offsetint, optional
Row offset for imagery positioning (default: 0). Used when imagery represents a subset/crop of a larger scene.
- column_offsetint, optional
Column offset for imagery positioning (default: 0). Used when imagery represents a subset/crop of a larger scene.
Temporal Metadata¶
- timesNDArray[np.datetime64], optional
Timestamp for each frame with microsecond precision. Enables time-based analysis and temporal coordinate conversion.
Sensor Information¶
- sensorSensor
Sensor object containing projection polynomials and radiometric calibration data. The Sensor provides geodetic coordinate conversion capabilities, sensor positions, and optional point spread function modeling for irradiance estimation.
Internal Attributes¶
- descriptionstr, optional
Long-form description of the imagery (default: “”)
- _histogramsdict, optional
Cached histograms for performance. Maps frame_index -> (hist_y, hist_x). Computed lazily via get_histogram() method.
- uuidstr
Unique identifier automatically generated for each Imagery instance
- pixel_to_geodetic(frame, rows, columns)¶
Convert pixel coordinates to geodetic (lat/lon/alt)
- geodetic_to_pixel(frame, location)¶
Convert geodetic coordinates to pixel (row/column)
Examples
>>> # Create basic imagery >>> import numpy as np >>> images = np.random.randn(100, 256, 256).astype(np.float32) >>> frames = np.arange(100) >>> imagery = Imagery(name="Test", images=images, frames=frames)
>>> # Create imagery with timestamps >>> times = np.array([np.datetime64('2024-01-01T00:00:00') + ... np.timedelta64(i*100, 'ms') for i in range(100)]) >>> imagery = Imagery(name="Test", images=images, frames=frames, times=times)
>>> # Slice imagery by frame range >>> subset = imagery[10:50] # Frames 10-49
>>> # Extract spatial subset via AOI >>> from vista.aoi import AOI >>> aoi = AOI(name="Region1", x=50, y=50, width=100, height=100) >>> cropped = imagery.get_aoi(aoi)
Notes
Frame numbers in the frames array need not be contiguous or zero-indexed
All optional metadata (times, polynomials, calibration data) is preserved during slicing operations
Geodetic conversion requires valid polynomial coefficients for the frame of interest
Calibration frame arrays define ranges: frame N applies until frame N+1 starts
- get_frame_index(frame_num)[source]¶
Get array index for a specific frame number using efficient lookup.
Uses binary search if frames are sorted (O(log n)), otherwise uses cached dictionary lookup (O(1)).
- get_histogram(frame_index, bins=256, max_rowcol=512)[source]¶
Get histogram for a specific frame using consistent bin edges.
Computes histogram if not cached, using pre-computed global bin edges for consistency across frames.
- Parameters:
- Returns:
(hist_y, bin_centers) - histogram counts and bin center values
- Return type:
- to_hdf5(group)[source]¶
Save imagery data to an HDF5 group.
- Parameters:
group (h5py.Group) – HDF5 group to write imagery data to (typically sensors/<sensor_uuid>/imagery/<imagery_uuid>/)
Notes
This method writes only imagery-specific data: - Image arrays (chunked for efficient loading) - Frame numbers - Times (as unix_nanoseconds) - Row/column offsets - Metadata attributes (name, description, uuid)
Sensor data should be written separately using sensor.to_hdf5()
- __init__(name, images, frames, sensor, row_offset=None, column_offset=None, times=None, description='', _histograms=None, default_histogram_bounds=None)¶
- vista.imagery.imagery.save_imagery_hdf5(file_path, sensor_imagery_map)[source]¶
Save imagery data to HDF5 file with hierarchical sensor/imagery structure.
- Parameters:
Notes
The HDF5 file structure created is: ``` root/ ├── [attrs] format_version, created └── sensors/
├── <sensor_uuid>/ │ ├── [attrs] name, uuid, sensor_type │ ├── position/ (SampledSensor only) │ ├── geolocation/ (if can_geolocate) │ ├── radiometric/ (if calibration data exists) │ └── imagery/ │ ├── <imagery_uuid_1>/ │ │ ├── [attrs] name, uuid, description, … │ └── <imagery_uuid_2>/ └── <sensor_uuid_2>/
└── …
Examples
>>> sensor = SampledSensor(name="MySensor", ...) >>> imagery1 = Imagery(name="img1", sensor=sensor, ...) >>> imagery2 = Imagery(name="img2", sensor=sensor, ...) >>> save_imagery_hdf5("data.h5", {"MySensor": [imagery1, imagery2]})