đã áp dụng file shapefile vào train và predict

This commit is contained in:
Victor Phan
2026-01-05 11:19:34 +07:00
parent fda2852dd2
commit f401765996
23 changed files with 4148 additions and 85 deletions
+89 -2
View File
@@ -36,6 +36,14 @@ class FeatureExtractor:
'VH_db_mean', 'VV_db_mean', 'VH_VV_ratio'
],
'description': 'Extended aggregate features with statistics'
},
'odc': {
'n_features': 8,
'features': [
'ndvi_mean', 'ndvi_min', 'ndvi_max', 'ndvi_std', 'ndvi_range',
'ndwi_mean', 'ndbi_mean', 'evi_mean'
],
'description': 'ODC mode: 8 aggregate features (NDVI stats + NDWI/NDBI/EVI mean) - matches 01.train_ODC.ipynb'
}
}
@@ -229,6 +237,80 @@ class FeatureExtractor:
return features
def extract_odc_features(
self,
s2_data: xr.Dataset,
vh_data: Optional[xr.DataArray] = None,
vv_data: Optional[xr.DataArray] = None
) -> np.ndarray:
"""
Extract ODC aggregate features (8 features matching 01.train_ODC.ipynb):
ndvi_mean, ndvi_min, ndvi_max, ndvi_std, ndvi_range, ndwi_mean, ndbi_mean, evi_mean
Args:
s2_data: Sentinel-2 Dataset with B02, B03, B04, B08, B11
vh_data: Not used in ODC mode
vv_data: Not used in ODC mode
Returns:
Feature array shape (n_pixels, 8)
"""
# Calculate spectral indices
nir = s2_data["B08"].astype('float32')
red = s2_data["B04"].astype('float32')
green = s2_data["B03"].astype('float32')
blue = s2_data["B02"].astype('float32')
swir = s2_data["B11"].astype('float32') if "B11" in s2_data else s2_data["B02"]
# NDVI = (NIR - Red) / (NIR + Red)
ndvi = (nir - red) / (nir + red + 1e-8)
# NDWI = (Green - NIR) / (Green + NIR)
ndwi = (green - nir) / (green + nir + 1e-8)
# NDBI = (SWIR - NIR) / (SWIR + NIR)
ndbi = (swir - nir) / (swir + nir + 1e-8)
# EVI = 2.5 * (NIR - Red) / (NIR + 6*Red - 7.5*Blue + 1)
evi = 2.5 * (nir - red) / (nir + 6*red - 7.5*blue + 1)
features_list = []
# NDVI statistics (5 features)
if 'time' in ndvi.dims:
features_list.append(ndvi.mean(dim='time').values.flatten()) # ndvi_mean
features_list.append(ndvi.min(dim='time').values.flatten()) # ndvi_min
features_list.append(ndvi.max(dim='time').values.flatten()) # ndvi_max
features_list.append(ndvi.std(dim='time').values.flatten()) # ndvi_std
ndvi_range = (ndvi.max(dim='time') - ndvi.min(dim='time')).values.flatten()
features_list.append(ndvi_range) # ndvi_range
else:
ndvi_flat = ndvi.values.flatten()
features_list.extend([ndvi_flat, ndvi_flat, ndvi_flat, np.zeros_like(ndvi_flat), np.zeros_like(ndvi_flat)])
# NDWI mean (1 feature)
if 'time' in ndwi.dims:
features_list.append(ndwi.mean(dim='time').values.flatten()) # ndwi_mean
else:
features_list.append(ndwi.values.flatten())
# NDBI mean (1 feature)
if 'time' in ndbi.dims:
features_list.append(ndbi.mean(dim='time').values.flatten()) # ndbi_mean
else:
features_list.append(ndbi.values.flatten())
# EVI mean (1 feature)
if 'time' in evi.dims:
features_list.append(evi.mean(dim='time').values.flatten()) # evi_mean
else:
features_list.append(evi.values.flatten())
# Stack all features (total: 8 features)
features = np.column_stack(features_list)
return features
def extract_extended_features(
self,
s2_data: xr.Dataset,
@@ -319,7 +401,7 @@ class FeatureExtractor:
Extract features theo mode đã chọn
Args:
s2_data: Sentinel-2 Dataset (cần cho temporal extended modes)
s2_data: Sentinel-2 Dataset (cần cho temporal, extended, và odc modes)
ndvi_data: NDVI DataArray (cần cho simple mode)
vh_data: VH radar DataArray
vv_data: VV radar DataArray
@@ -342,6 +424,11 @@ class FeatureExtractor:
raise ValueError("s2_data required for extended mode")
return self.extract_extended_features(s2_data, vh_data, vv_data)
elif self.mode == 'odc':
if s2_data is None:
raise ValueError("s2_data required for odc mode")
return self.extract_odc_features(s2_data, vh_data, vv_data)
else:
raise ValueError(f"Unknown mode: {self.mode}")
@@ -359,7 +446,7 @@ def get_feature_extractor(mode: str = 'simple') -> FeatureExtractor:
Factory function để tạo FeatureExtractor
Args:
mode: 'simple', 'temporal', hoặc 'extended'
mode: 'simple', 'temporal', 'extended', hoặc 'odc'
Returns:
FeatureExtractor instance