|
| 1 | +import numpy as np |
| 2 | +import pandas as pd |
| 3 | +from sklearn.datasets import make_classification |
| 4 | + |
| 5 | +from siapy.entities import Pixels, Signatures, SpectralImage |
| 6 | +from siapy.features import AutoSpectralIndicesClassification |
| 7 | +from siapy.features.helpers import FeatureSelectorConfig |
| 8 | +from siapy.features.spectral_indices import compute_spectral_indices, get_spectral_indices |
| 9 | + |
| 10 | +# Create a mock spectral image with 4 bands (Red, Green, Blue, Near-infrared) |
| 11 | +rng = np.random.default_rng(seed=42) |
| 12 | +image_array = rng.random((50, 50, 4)) # height, width, bands (R, G, B, N) |
| 13 | +image = SpectralImage.from_numpy(image_array) |
| 14 | + |
| 15 | +# Define region of interest (ROI) pixels for sampling |
| 16 | +roi_pixels = Pixels.from_iterable( |
| 17 | + [(10, 15), (12, 18), (15, 20), (18, 22), (20, 25), (25, 30), (28, 32), (30, 35), (32, 38), (35, 40)] |
| 18 | +) |
| 19 | + |
| 20 | +# Extract spectral signatures from ROI pixels |
| 21 | +signatures = image.to_signatures(roi_pixels) |
| 22 | +print(f"Extracted {len(signatures)} signatures from the image") |
| 23 | + |
| 24 | +# Convert signatures to DataFrame and assign standard band names |
| 25 | +spectral_data = signatures.signals.df.copy() |
| 26 | +spectral_data = spectral_data.rename(columns=dict(zip(spectral_data.columns, ["R", "G", "B", "N"]))) |
| 27 | + |
| 28 | +# Create synthetic classification labels for demonstration purposes |
| 29 | +_, y = make_classification(n_samples=len(spectral_data), n_features=4, random_state=42) |
| 30 | +target = pd.Series(y[: len(spectral_data)]) |
| 31 | + |
| 32 | +# Get all spectral indices that can be computed with available bands |
| 33 | +available_indices = get_spectral_indices(["R", "G", "B", "N"]) |
| 34 | +print(f"Found {len(available_indices)} computable spectral indices") |
| 35 | + |
| 36 | +# Method 1: Manually compute spectral indices |
| 37 | +indices_df = compute_spectral_indices( |
| 38 | + data=spectral_data, |
| 39 | + spectral_indices=list(available_indices.keys())[:10], # Use first 10 indices |
| 40 | +) |
| 41 | +print(f"Computed {indices_df.shape[1]} spectral indices") |
| 42 | + |
| 43 | +# Method 2: Automated feature selection with spectral indices |
| 44 | +# Configure the feature selector |
| 45 | +config = FeatureSelectorConfig( |
| 46 | + k_features=5, # Select 5 best performing indices |
| 47 | + cv=3, # Use 3-fold cross-validation |
| 48 | + verbose=0, |
| 49 | +) |
| 50 | + |
| 51 | +# Create automated selector that finds optimal spectral indices |
| 52 | +auto_spectral = AutoSpectralIndicesClassification( |
| 53 | + spectral_indices=list(available_indices.keys())[:15], # Use first 15 indices as candidates |
| 54 | + selector_config=config, |
| 55 | + merge_with_original=False, # Return only selected indices, not original bands |
| 56 | +) |
| 57 | + |
| 58 | +# Apply feature selection to find the best spectral indices |
| 59 | +selected_features = auto_spectral.fit_transform(spectral_data, target) |
| 60 | +print(f"Selected {selected_features.shape[1]} optimal spectral indices") |
| 61 | + |
| 62 | +# Create new signatures object with selected features |
| 63 | +enhanced_signatures = Signatures.from_signals_and_pixels(signals=selected_features, pixels=signatures.pixels) |
| 64 | +print(f"Created enhanced signatures with shape: {enhanced_signatures.signals.df.shape}") |
| 65 | + |
| 66 | +# Display results - the enhanced signatures contain only the most informative spectral indices |
| 67 | +print(f"Enhanced signatures DataFrame:\n{enhanced_signatures.to_dataframe().head()}") |
0 commit comments