Image Module¶
sensingpy.image exposes the core Image class for handling geospatial raster
data with metadata and coordinate systems, and the compose utility for
combining multiple images.
Image¶
Image
¶
Bases: object
A geospatial image processing class for remote sensing operations.
This class provides tools for working with geospatial image data in Python. It wraps xarray Datasets with geospatial metadata and provides methods for common remote sensing operations including reprojection, band manipulation, spatial analysis, and more.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
data
|
Dataset
|
xarray Dataset containing image bands and coordinates |
required |
crs
|
CRS
|
Coordinate reference system of the image |
required |
Attributes:
| Name | Type | Description |
|---|---|---|
data |
Dataset
|
xarray Dataset containing image bands and coordinates |
crs |
CRS
|
Coordinate reference system of the image |
name |
str
|
Optional name identifier for the image |
grid_mapping |
str
|
Name of the grid mapping variable in the Dataset |
Notes
The Image class is designed to maintain spatial reference information throughout
operations. Most methods support an inplace parameter (default True) that controls
whether operations modify the image in-place or return a modified copy. All methods
return self (or a copy) to enable method chaining.
Examples:
>>> # In-place operations (default behavior)
>>> image.mask(water_mask).reproject(new_crs).dropna()
>>>
>>> # Non-mutating operations (create copies)
>>> masked = image.mask(water_mask, inplace=False)
>>> reprojected = image.reproject(new_crs, inplace=False)
Initialize an Image object with geospatial data and coordinate reference system.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
data
|
Dataset
|
The xarray Dataset containing the image data with dimensions and variables representing different bands/channels |
required |
crs
|
CRS
|
The coordinate reference system defining the spatial reference of the image data |
required |
Source code in sensingpy/image.py
Attributes¶
band_names
property
¶
Get list of band names in the image.
Returns:
| Type | Description |
|---|---|
List[str]
|
List of band names |
width
property
¶
Get width of the image in pixels.
Returns:
| Type | Description |
|---|---|
int
|
Image width |
height
property
¶
Get height of the image in pixels.
Returns:
| Type | Description |
|---|---|
int
|
Image height |
count
property
¶
Get number of bands in the image.
Returns:
| Type | Description |
|---|---|
int
|
Number of bands |
x_res
property
¶
Get pixel resolution in x direction.
Returns:
| Type | Description |
|---|---|
float or int
|
X resolution |
y_res
property
¶
Get pixel resolution in y direction.
Returns:
| Type | Description |
|---|---|
float or int
|
Y resolution |
res
property
¶
transform
property
¶
Get affine transform for the image.
Returns:
| Type | Description |
|---|---|
Affine
|
Affine transform object representing the spatial relationship between pixel coordinates and CRS coordinates |
xs_ys
property
¶
Get meshgrid of x and y coordinates.
Returns:
| Type | Description |
|---|---|
Tuple[ndarray, ndarray]
|
X and Y coordinate arrays |
left
property
¶
Get min longitude coordinate of the image.
Returns:
| Type | Description |
|---|---|
float
|
Left coordinate |
right
property
¶
Get max longitude coordinate of the image.
Returns:
| Type | Description |
|---|---|
float
|
Right coordinate |
top
property
¶
Get max latitude coordinate of the image.
Returns:
| Type | Description |
|---|---|
float
|
Top coordinate |
bottom
property
¶
Get min latitude coordinate of the image.
Returns:
| Type | Description |
|---|---|
float
|
Bottom coordinate |
bbox
property
¶
Get bounding box polygon of the image.
Returns:
| Type | Description |
|---|---|
Polygon
|
Shapely polygon representing image bounds |
values
property
¶
Get array of all band values.
Returns:
| Type | Description |
|---|---|
ndarray
|
Array containing band values |
attrs
property
¶
Get the attributes dictionary of the underlying xarray Dataset.
Provides access to metadata attributes stored in the Dataset, such as sensor information, acquisition time, processing history, or custom metadata added by the user.
Returns:
| Type | Description |
|---|---|
dict
|
Dictionary containing all Dataset attributes |
Examples:
>>> # Access attributes
>>> print(image.attrs)
>>>
>>> # Add custom attribute
>>> image.attrs['sensor'] = 'Sentinel-2'
>>> image.attrs['acquisition_date'] = '2024-01-15'
>>>
>>> # Check if attribute exists
>>> if 'crs_wkt' in image.attrs:
>>> print(image.attrs['crs_wkt'])
See Also
attrs_keys : Get list of attribute keys attrs_values : Get list of attribute values
attrs_keys
property
¶
Get list of attribute keys from the underlying xarray Dataset.
Returns a list of all metadata attribute names stored in the Dataset.
Returns:
| Type | Description |
|---|---|
list
|
List of attribute key names |
Examples:
>>> # View all attribute keys
>>> print(image.attrs_keys)
>>> ['sensor', 'acquisition_date', 'processing_level']
>>>
>>> # Iterate through attributes
>>> for key in image.attrs_keys:
>>> print(f"{key}: {image.attrs[key]}")
See Also
attrs : Get the full attributes dictionary attrs_values : Get list of attribute values
attrs_values
property
¶
Get list of attribute values from the underlying xarray Dataset.
Returns a list of all metadata attribute values stored in the Dataset, in the same order as attrs_keys.
Returns:
| Type | Description |
|---|---|
list
|
List of attribute values |
Examples:
>>> # View all attribute values
>>> print(image.attrs_values)
>>> ['Sentinel-2', '2024-01-15', 'L2A']
>>>
>>> # Pair keys with values
>>> for key, value in zip(image.attrs_keys, image.attrs_values):
>>> print(f"{key}: {value}")
See Also
attrs : Get the full attributes dictionary attrs_keys : Get list of attribute keys
Functions¶
replace
¶
Replace occurrences of a substring in all band names with a new substring.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
old
|
str
|
The substring to be replaced in band names |
required |
new
|
str
|
The substring to replace with |
required |
inplace
|
bool
|
If True (default), modifies the image in-place and returns self. If False, returns a modified copy without changing the original. |
True
|
Returns:
| Type | Description |
|---|---|
Self
|
The modified Image object. Returns self if inplace=True, otherwise returns a new Image instance. |
Examples:
>>> # In-place modification (default)
>>> image.replace('B01', 'blue')
>>>
>>> # Create modified copy
>>> renamed = image.replace('B01', 'blue', inplace=False)
>>> # Original image unchanged
Source code in sensingpy/image.py
rename
¶
Rename band names using a dictionary mapping.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
new_names
|
dict
|
Dictionary mapping old band names to new band names |
required |
inplace
|
bool
|
If True (default), modifies the image in-place and returns self. If False, returns a modified copy without changing the original. |
True
|
Returns:
| Type | Description |
|---|---|
Self
|
The modified Image object. Returns self if inplace=True, otherwise returns a new Image instance. |
Examples:
>>> # In-place modification (default)
>>> image.rename({'B1': 'blue', 'B2': 'green'})
>>>
>>> # Create modified copy
>>> renamed = image.rename({'B1': 'blue'}, inplace=False)
>>> # Original image unchanged
Source code in sensingpy/image.py
rename_by_enum
¶
Rename bands using an enumeration mapping.
Renames image bands using a mapping defined in an enumeration class.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
enum
|
Enum
|
Enumeration class containing band name mappings. Each enum value should be a List[str] of wavelength strings that map to the enum name. |
required |
inplace
|
bool
|
If True (default), modifies the image in-place and returns self. If False, returns a modified copy without changing the original. |
True
|
Returns:
| Type | Description |
|---|---|
Self
|
The modified Image object. Returns self if inplace=True, otherwise returns a new Image instance. |
Examples:
>>> # In-place modification (default)
>>> image.rename_by_enum(SENTINEL2_BANDS)
>>> # Renames bands like '443' to 'B1', '493' to 'B2', etc.
>>>
>>> # Create modified copy
>>> renamed = image.rename_by_enum(SENTINEL2_BANDS, inplace=False)
>>> # Original image unchanged
See Also
enums.SENTINEL2_BANDS : Enum for Sentinel-2 band mappings enums.MICASENSE_BANDS : Enum for MicaSense RedEdge band mappings
Source code in sensingpy/image.py
reproject
¶
reproject(new_crs: CRS, interpolation: Resampling = Resampling.nearest, inplace: bool = True) -> Image
Reproject image to new coordinate reference system.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
new_crs
|
CRS
|
Target coordinate reference system |
required |
interpolation
|
Resampling
|
Resampling method to use during reprojection, by default Resampling.nearest. Available options from rasterio.warp.Resampling include: - nearest: Nearest neighbor (default, preserves exact values) - bilinear: Bilinear interpolation (smooth, better for continuous data) - cubic: Cubic interpolation (smoother than bilinear) - cubic_spline: Cubic spline interpolation (smoothest) - lanczos: Lanczos windowed sinc interpolation (sharp edges) - average: Average of all contributing pixels - mode: Mode of all contributing pixels - max: Maximum value of all contributing pixels - min: Minimum value of all contributing pixels - med: Median of all contributing pixels - q1: First quartile of all contributing pixels - q3: Third quartile of all contributing pixels |
nearest
|
inplace
|
bool
|
If True (default), modifies the image in-place and returns self. If False, returns a modified copy without changing the original. |
True
|
Returns:
| Type | Description |
|---|---|
Self
|
The modified Image object. Returns self if inplace=True, otherwise returns a new Image instance with the new CRS. |
Examples:
>>> # Reproject to UTM Zone 10N (in-place, default)
>>> utm_crs = pyproj.CRS.from_epsg(32610)
>>> image.reproject(utm_crs, interpolation=Resampling.bilinear)
>>>
>>> # Reproject to Web Mercator, keep original unchanged
>>> webmerc_crs = pyproj.CRS.from_epsg(3857)
>>> reprojected = image.reproject(webmerc_crs, inplace=False)
Source code in sensingpy/image.py
align
¶
align(reference: Image, interpolation: Resampling = Resampling.nearest, inplace: bool = True) -> Image
Align image to match reference image's CRS, resolution and extent.
Transforms this image to match the coordinate reference system (CRS), spatial resolution, and geographic extent of a reference image.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
reference
|
Image
|
Reference image to align to. This image will be used as the template for CRS, resolution, and extent. |
required |
interpolation
|
Resampling
|
Resampling method from rasterio.warp.Resampling to use during transformation, by default Resampling.nearest. Options include: - nearest: Nearest neighbor (preserves original values, best for categorical data) - bilinear: Bilinear interpolation (smooth, better for continuous data) - cubic: Cubic interpolation (smoother than bilinear) - lanczos: Lanczos windowed sinc interpolation (sharp edges) |
nearest
|
inplace
|
bool
|
If True (default), modifies the image in-place and returns self. If False, returns a modified copy without changing the original. |
True
|
Returns:
| Type | Description |
|---|---|
Self
|
The modified Image object. Returns self if inplace=True, otherwise returns a new Image instance aligned to the reference. |
Examples:
>>> # Align a Landsat image to match a Sentinel-2 reference (in-place, default)
>>> landsat_img.align(sentinel2_img, interpolation=Resampling.bilinear)
>>> assert landsat_img.width == sentinel2_img.width
>>>
>>> # Create aligned copy, keep original unchanged
>>> aligned = landsat_img.align(sentinel2_img, inplace=False)
>>> assert aligned.width == sentinel2_img.width
>>> assert landsat_img.width != sentinel2_img.width # Original unchanged
Source code in sensingpy/image.py
671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 | |
merge
¶
Merge two images into a new Image covering the union of their extents.
Creates a new image that encompasses both images' geographic extents. If images have different sizes or extents, a new matrix is created and filled with data from each image at their respective positions.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
other
|
Image
|
The other image to merge with this one. Must have the same CRS and bands. |
required |
Returns:
| Type | Description |
|---|---|
Image
|
New merged image covering both input images |
Raises:
| Type | Description |
|---|---|
ValueError
|
If the CRS of the two images do not match If the bands of the two images do not match |
Examples:
>>> # Merge two adjacent images
>>> merged = image1.merge(image2)
>>> print(f"Original sizes: {image1.width}x{image1.height}, {image2.width}x{image2.height}")
>>> print(f"Merged size: {merged.width}x{merged.height}")
Source code in sensingpy/image.py
760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 | |
resample
¶
resample(scale: int, downscale: bool = True, interpolation: Resampling = Resampling.nearest, inplace: bool = True) -> Image
Resample image by scaling factor to change spatial resolution.
Changes the spatial resolution of the image by either increasing or decreasing the number of pixels while maintaining the same geographic extent.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
scale
|
int
|
Scale factor to apply. For example, a scale factor of 2 with downscale=True will reduce the image dimensions by half, while with downscale=False it will double the image dimensions. |
required |
downscale
|
bool
|
Direction of scaling operation, by default True: - True: Reduce resolution by dividing dimensions by scale factor - False: Increase resolution by multiplying dimensions by scale factor |
True
|
interpolation
|
Resampling
|
Resampling method from rasterio.warp.Resampling to use, by default Resampling.nearest: - nearest: Nearest neighbor (preserves exact values, best for categorical data) - bilinear: Bilinear interpolation (smooth, better for continuous data) - cubic: Cubic interpolation (smoother than bilinear) - lanczos: Lanczos windowed sinc interpolation (preserves sharp edges) - average: Averages all pixels that contribute to the output pixel |
nearest
|
inplace
|
bool
|
If True (default), modifies the image in-place and returns self. If False, returns a modified copy without changing the original. |
True
|
Returns:
| Type | Description |
|---|---|
Self
|
The modified Image object. Returns self if inplace=True, otherwise returns a new Image instance with the new resolution. |
Examples:
>>> # Reduce image resolution by half (in-place, default)
>>> image.resample(scale=2, downscale=True)
>>> print(f"New dimensions: {image.width}x{image.height}")
>>>
>>> # Double the image resolution, keep original unchanged
>>> upsampled = image.resample(scale=2, downscale=False,
... interpolation=Resampling.bilinear,
... inplace=False)
>>> print(f"Original: {image.width}x{image.height}")
>>> print(f"Upsampled: {upsampled.width}x{upsampled.height}")
Source code in sensingpy/image.py
clip
¶
Clip image to given geometries.
Creates a mask from the input geometries and trims the image extent to the minimum bounding box that contains all non-zero values.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
geometries
|
List[BaseGeometry]
|
List of geometries to clip to. The image will be clipped to the combined extent of all geometries. |
required |
inplace
|
bool
|
If True (default), modifies the image in-place and returns self. If False, returns a modified copy without changing the original. |
True
|
Returns:
| Type | Description |
|---|---|
Self
|
The modified Image object. Returns self if inplace=True, otherwise returns a new Image instance clipped to the geometries. |
Notes
The new extent is calculated by: 1. Finding the first and last rows that contain any values 2. Finding the first and last columns that contain any values 3. Keeping only the data within these bounds
Examples:
>>> # Clip in-place (default)
>>> image.clip([polygon])
>>> # Image is now smaller
>>>
>>> # Create clipped copy, keep original unchanged
>>> clipped = image.clip([polygon], inplace=False)
>>> # Original image dimensions unchanged
Source code in sensingpy/image.py
mask
¶
mask(condition: ndarray, bands: str | List[str] = None, fill_true=None, fill_false=np.nan, inplace: bool = True) -> Image
Mask image bands using condition array.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
condition
|
ndarray
|
Boolean mask array |
required |
bands
|
str or List[str]
|
Band(s) to apply mask to, by default None which applies to all bands |
None
|
fill_true
|
Any
|
Value to set where condition is True, by default None (no change) |
None
|
fill_false
|
Any
|
Value to set where condition is False, by default np.nan |
nan
|
inplace
|
bool
|
If True (default), modifies the image in-place and returns self. If False, returns a modified copy without changing the original. |
True
|
Returns:
| Type | Description |
|---|---|
Self
|
The modified Image object. Returns self if inplace=True, otherwise returns a new Image instance with the mask applied. |
Examples:
>>> # Mask values to NaN where condition is False (in-place, default)
>>> image.mask(water_mask)
>>>
>>> # Set values to 0 where False, keep original image unchanged
>>> masked = image.mask(land_mask, fill_false=0, inplace=False)
>>>
>>> # Set values to 1 where True, 0 where False (in-place)
>>> image.mask(binary_mask, fill_true=1, fill_false=0)
Source code in sensingpy/image.py
geometry_mask
¶
geometry_mask(geometries: List[BaseGeometry], mask_out: bool = True, bands: str | List[str] = None, fill_true=None, fill_false=np.nan, inplace: bool = True) -> Image
Mask image using geometries.
Creates a binary mask from the input geometries and sets values to NaN either inside or outside the geometries depending on the mask_out parameter.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
geometries
|
List[BaseGeometry]
|
List of geometries for masking |
required |
mask_out
|
bool
|
If True mask outside geometries, if False mask inside, by default True |
True
|
bands
|
str or List[str]
|
Band(s) to apply mask to, by default None which applies to all bands |
None
|
fill_true
|
Any
|
Value to set where condition is True (inside/outside depending on mask_out), by default None (no change) |
None
|
fill_false
|
Any
|
Value to set where condition is False, by default np.nan |
nan
|
inplace
|
bool
|
If True (default), modifies the image in-place and returns self. If False, returns a modified copy without changing the original. |
True
|
Returns:
| Type | Description |
|---|---|
Self
|
The modified Image object. Returns self if inplace=True, otherwise returns a new Image instance with the mask applied. |
Examples:
>>> # Mask outside geometries to NaN (in-place, default)
>>> image.geometry_mask(polygons)
>>>
>>> # Mask outside to 0, keep original image unchanged
>>> masked = image.geometry_mask(polygons, fill_false=0, inplace=False)
>>>
>>> # Set inside to 1, outside to 0 (in-place)
>>> image.geometry_mask(polygons, fill_true=1, fill_false=0)
Source code in sensingpy/image.py
dropna
¶
Remove rows and columns that contain all NaN values only when adjacent rows/columns also contain all NaN values.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
inplace
|
bool
|
If True (default), modifies the image in-place and returns self. If False, returns a modified copy without changing the original. |
True
|
Returns:
| Type | Description |
|---|---|
Self
|
The modified Image object. Returns self if inplace=True, otherwise returns a new Image instance with NaN borders removed. |
Notes
The method preserves rows/columns with all NaN values if they are between rows/columns containing valid values. For example, if row 1 has values, row 2 is all NaN, and row 3 has values, row 2 will be preserved.
Examples:
>>> # Drop NaN borders in-place (default)
>>> image.dropna()
>>> print(f"New size: {image.width}x{image.height}")
>>>
>>> # Create copy without NaN borders, keep original unchanged
>>> trimmed = image.dropna(inplace=False)
>>> # Original image dimensions unchanged
Source code in sensingpy/image.py
select
¶
Select specific bands from the image and return as numpy array (copy).
This method returns a copy of the band data as a numpy array. Modifications to the returned array will not affect the original Image.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
bands
|
str or List[str]
|
Band(s) to select. Single string for one band, list of strings for multiple bands. |
required |
Returns:
| Type | Description |
|---|---|
ndarray
|
Copy of selected band data as numpy array: - For single band: 2D array with shape (height, width) - For multiple bands: 3D array with shape (n_bands, height, width) |
Examples:
>>> # Get single band as numpy array
>>> blue = image.select('blue')
>>> print(blue.shape) # (height, width)
>>> blue[mask] = 0 # Does NOT modify original image
>>>
>>> # Get multiple bands
>>> rgb = image.select(['red', 'green', 'blue'])
>>> print(rgb.shape) # (3, height, width)
>>>
>>> # To modify original image, use add_band or __setitem__
>>> modified = image.select('blue')
>>> modified[mask] = 0
>>> image['blue'] = modified # Update original
See Also
getitem : Equivalent method using bracket notation add_band : Add or update a band in the image
Source code in sensingpy/image.py
add_band
¶
Add a new band to the image or update an existing band.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
band_name
|
str
|
Name of the band to add or update |
required |
data
|
ndarray or DataArray
|
Band data to add. Must match the spatial dimensions of existing bands |
required |
inplace
|
bool
|
If True (default), modifies the image in-place and returns self. If False, returns a modified copy without changing the original. |
True
|
Returns:
| Type | Description |
|---|---|
Self
|
The modified Image object. Returns self if inplace=True, otherwise returns a new Image instance with the band added/updated. |
Examples:
>>> # Add new band in-place (default)
>>> image.add_band('ndvi', ndvi_data)
>>> print(image.band_names) # [..., 'ndvi']
>>>
>>> # Create copy with new band, keep original unchanged
>>> with_ndvi = image.add_band('ndvi', ndvi_data, inplace=False)
>>> # 'ndvi' not in original image.band_names
>>>
>>> # Update existing band (in-place)
>>> image.add_band('blue', new_blue_data)
Source code in sensingpy/image.py
drop_bands
¶
Remove specified bands from the image.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
bands
|
str or List[str]
|
Band(s) to remove |
required |
inplace
|
bool
|
If True (default), modifies the image in-place and returns self. If False, returns a modified copy without changing the original. |
True
|
Returns:
| Type | Description |
|---|---|
Self
|
The modified Image object. Returns self if inplace=True, otherwise returns a new Image instance without the dropped bands. |
Examples:
>>> # Drop bands in-place (default)
>>> image.drop_bands(['B1', 'B2'])
>>> print(image.band_names) # B1, B2 removed
>>>
>>> # Create copy without certain bands, keep original unchanged
>>> subset = image.drop_bands(['B1', 'B2'], inplace=False)
>>> # Original image still has B1, B2
Source code in sensingpy/image.py
keep_bands
¶
Keep only specified bands and remove all others from the image.
This is the inverse operation of drop_bands. Only the specified bands will be retained in the image, and all other bands will be removed.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
bands
|
str or List[str]
|
Band(s) to keep. All other bands will be removed. |
required |
inplace
|
bool
|
If True (default), modifies the image in-place and returns self. If False, returns a modified copy without changing the original. |
True
|
Returns:
| Type | Description |
|---|---|
Self
|
The modified Image object. Returns self if inplace=True, otherwise returns a new Image instance with only the specified bands. |
Examples:
>>> # Keep only RGB bands in-place (default)
>>> image.keep_bands(['red', 'green', 'blue'])
>>> print(image.band_names) # ['red', 'green', 'blue']
>>>
>>> # Keep single band
>>> image.keep_bands('ndvi')
>>>
>>> # Create copy with only specific bands, keep original unchanged
>>> rgb_only = image.keep_bands(['red', 'green', 'blue'], inplace=False)
>>> # Original image still has all bands
See Also
drop_bands : Remove specified bands (inverse operation)
Source code in sensingpy/image.py
normalized_diference
¶
Calculate normalized difference between two bands.
Computes the normalized difference index between two bands using the formula: (band1 - band2) / (band1 + band2)
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
band1
|
str
|
Name of the first band in the calculation (numerator) |
required |
band2
|
str
|
Name of the second band in the calculation (denominator) |
required |
Returns:
| Type | Description |
|---|---|
ndarray
|
2D array containing the normalized difference values ranging from -1 to 1. Areas where both bands have zero values will result in NaN values. |
Notes
This is a common operation in remote sensing used to create various spectral indices such as NDVI (Normalized Difference Vegetation Index), NDWI (Normalized Difference Water Index), etc.
Values outside the -1 to 1 range can occur if negative values are present in the input bands.
Examples:
>>> # Calculate NDVI using NIR and Red bands
>>> ndvi = image.normalized_diference('nir', 'red')
>>> image.add_band('ndvi', ndvi)
>>>
>>> # Calculate NDWI using Green and NIR bands
>>> ndwi = image.normalized_diference('green', 'nir')
>>> image.add_band('ndwi', ndwi)
Source code in sensingpy/image.py
extract_values
¶
Extract values at specified coordinates from the image.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
xs
|
ndarray
|
X coordinates (longitude/easting) in the image's CRS |
required |
ys
|
ndarray
|
Y coordinates (latitude/northing) in the image's CRS |
required |
bands
|
List[str]
|
List of band names to extract values from. If None, extracts from all bands, by default None |
None
|
Returns:
| Type | Description |
|---|---|
ndarray
|
Array of extracted values with shape: |
Source code in sensingpy/image.py
interval_choice
¶
Choose random values from intervals in specified band.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
band
|
str
|
Band to sample from |
required |
size
|
int
|
Number of samples |
required |
intervals
|
Iterable
|
Value intervals to sample from |
required |
replace
|
bool
|
Sample with replacement if True, by default True |
True
|
Returns:
| Type | Description |
|---|---|
ndarray
|
Selected values |
Source code in sensingpy/image.py
arginterval_choice
¶
Choose random indices from intervals in specified band.
.. deprecated:: 2.1.0
Use :meth:sample_indices_by_interval instead. This method will be removed in version 3.0.0.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
band
|
str
|
Band to sample from |
required |
size
|
int
|
Number of samples |
required |
intervals
|
Iterable
|
Value intervals to sample from |
required |
replace
|
bool
|
Sample with replacement if True, by default True |
True
|
Returns:
| Type | Description |
|---|---|
ndarray
|
Selected indices |
Source code in sensingpy/image.py
sample_indices_by_interval
¶
sample_indices_by_interval(band: str, size: int, intervals: Iterable, replace: bool = True) -> np.ndarray
Get indices of random samples from value intervals in a specified band.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
band
|
str
|
Band to sample from |
required |
size
|
int
|
Number of samples per interval |
required |
intervals
|
Iterable
|
Value intervals to sample from, e.g., [(0, 2), (2, 4), (4, 6)] |
required |
replace
|
bool
|
Sample with replacement if True, by default True |
True
|
Returns:
| Type | Description |
|---|---|
ndarray
|
Selected indices |
Examples:
>>> # Sample 100 indices from each depth interval
>>> indices = image.sample_indices_by_interval('depth', 100, [0, 5, 10, 15])
Source code in sensingpy/image.py
empty_like
¶
Create empty image with same metadata and coordinates.
Returns:
| Type | Description |
|---|---|
Image
|
New empty image |
Source code in sensingpy/image.py
to_netcdf
¶
Save image to NetCDF file.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
filename
|
str
|
Output filename |
required |
Source code in sensingpy/image.py
to_tif
¶
Save image to GeoTIFF file.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
filename
|
str
|
Output filename |
required |
Source code in sensingpy/image.py
compose¶
compose
¶
Compose multiple images into one using a composition method.
This function combines multiple images by applying a composition method to corresponding pixels across all input images. Common uses include creating cloud-free composites, calculating statistics across time series, or selecting optimal pixels based on quality metrics.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
images
|
List[Image]
|
List of Image objects to compose. All images should have compatible dimensions and coordinate reference systems. |
required |
method
|
Callable or ndarray
|
Method to use for composition. Can be either: - A callable function that takes an array of values across images and returns a single value (e.g., np.nanmean, np.nanmax) - An array of indices specifying which image to select for each pixel |
required |
bands
|
List[str]
|
List of band names to include in the composition, by default None which uses all bands from the first image |
None
|
Returns:
| Type | Description |
|---|---|
Image
|
New Image object containing the composition result |
Notes
The output image retains the spatial metadata (CRS, transform) from the first image in the list, but contains new pixel values based on the composition method.
Examples:
>>> # Create a mean composite from multiple images
>>> mean_composite = compose(image_list, np.nanmean)
>>>
>>> # Create a maximum NDVI composite
>>> import numpy as np
>>> ndvi_values = np.array([img.normalized_diference('nir', 'red') for img in image_list])
>>> best_indices = np.nanargmax(ndvi_values, axis=0)
>>> max_ndvi_composite = compose(image_list, best_indices)