CoolFace
Datasetpublic

Ehzoahis/BigEarthNet

BigEarthNet BigEarthNet is a large-scale benchmark dataset for multi-label classification, derived from Sentinel-1 (radar) and Sentinel-2 (optical) satellite imagery. We have pre-processed the dataset by upsampling all sentinel-2 channels to 120x120 pixels and concatenated them together. Please see Torchgeo/bigearthnet for more information about pre-processing. In addition, we map the original 43 land cover classes to 19 broader categories using a predefined conversion scheme.… See the full description on the dataset page: https://huggingface.co/datasets/Ehzoahis/BigEarthNet.

sourceHugging Faceupdated 11mo agoView on Hugging Face
3likes1.1kdownloads
BigEarthNet.py289 linesDownload Raw Back to root
1import os2import json3import shutil4import string5import tarfile6import tifffile7import datasets8 9import numpy as np10import pandas as pd11 12from tqdm import tqdm13 14class_sets = {15        19: [16            'Urban fabric',17            'Industrial or commercial units',18            'Arable land',19            'Permanent crops',20            'Pastures',21            'Complex cultivation patterns',22            'Land principally occupied by agriculture, with significant areas of natural vegetation',23            'Agro-forestry areas',24            'Broad-leaved forest',25            'Coniferous forest',26            'Mixed forest',27            'Natural grassland and sparsely vegetated areas',28            'Moors, heathland and sclerophyllous vegetation',29            'Transitional woodland, shrub',30            'Beaches, dunes, sands',31            'Inland wetlands',32            'Coastal wetlands',33            'Inland waters',34            'Marine waters',35        ],36        43: [37            'Continuous urban fabric',38            'Discontinuous urban fabric',39            'Industrial or commercial units',40            'Road and rail networks and associated land',41            'Port areas',42            'Airports',43            'Mineral extraction sites',44            'Dump sites',45            'Construction sites',46            'Green urban areas',47            'Sport and leisure facilities',48            'Non-irrigated arable land',49            'Permanently irrigated land',50            'Rice fields',51            'Vineyards',52            'Fruit trees and berry plantations',53            'Olive groves',54            'Pastures',55            'Annual crops associated with permanent crops',56            'Complex cultivation patterns',57            'Land principally occupied by agriculture, with significant areas of natural vegetation',58            'Agro-forestry areas',59            'Broad-leaved forest',60            'Coniferous forest',61            'Mixed forest',62            'Natural grassland',63            'Moors and heathland',64            'Sclerophyllous vegetation',65            'Transitional woodland/shrub',66            'Beaches, dunes, sands',67            'Bare rock',68            'Sparsely vegetated areas',69            'Burnt areas',70            'Inland marshes',71            'Peatbogs',72            'Salt marshes',73            'Salines',74            'Intertidal flats',75            'Water courses',76            'Water bodies',77            'Coastal lagoons',78            'Estuaries',79            'Sea and ocean',80        ],81    }82 83label_converter = {84        0: 0,85        1: 0,86        2: 1,87        11: 2,88        12: 2,89        13: 2,90        14: 3,91        15: 3,92        16: 3,93        18: 3,94        17: 4,95        19: 5,96        20: 6,97        21: 7,98        22: 8,99        23: 9,100        24: 10,101        25: 11,102        31: 11,103        26: 12,104        27: 12,105        28: 13,106        29: 14,107        33: 15,108        34: 15,109        35: 16,110        36: 16,111        38: 17,112        39: 17,113        40: 18,114        41: 18,115        42: 18,116    }117 118S2_MEAN = [752.40087073, 884.29673756, 1144.16202635, 1297.47289228, 1624.90992062, 2194.6423161, 2422.21248945, 2517.76053101, 2581.64687018, 2645.51888987, 2368.51236873, 1805.06846033]119S2_STD = [1108.02887453, 1155.15170768, 1183.6292542, 1368.11351514, 1370.265037, 1355.55390699, 1416.51487101, 1474.78900051, 1439.3086061, 1582.28010962, 1455.52084939, 1343.48379601]120 121S1_MEAN = [-12.54847273, -20.19237134]122S1_STD = [5.25697717, 5.91150917]123 124parts = [f"a{letter}" for letter in string.ascii_lowercase]125parts.extend([f"b{letter}" for letter in string.ascii_lowercase[:8]]) 126 127class BigEarthNetDataset(datasets.GeneratorBasedBuilder):128    VERSION = datasets.Version("1.0.0")129 130    DATA_URL = [131        f"https://huggingface.co/datasets/GFM-Bench/BigEarthNet/resolve/main/data/bigearthnet_part_{part}"132        for part in parts133    ]134 135    metadata = {136        "s2c": {137            "bands":["B1", "B2", "B3", "B4", "B5", "B6", "B7", "B8", "B8A", "B9", "B11", "B12"],138            "channel_wv": [442.7, 492.4, 559.8, 664.6, 704.1, 740.5, 782.8, 832.8, 864.7, 945.1, 1613.7, 2202.4],139            "mean": S2_MEAN,140            "std": S2_STD141        },142        "s1": {143            "bands": ["VV", "VH"],144            "channel_wv": [5500, 5700],145            "mean": S1_MEAN,146            "std": S1_STD147        }148    }149 150    SIZE = HEIGHT = WIDTH = 120151 152    NUM_CLASSES = 19153 154    spatial_resolution = 10155 156    def __init__(self, *args, **kwargs):157        self.class2idx = {c: i for i, c in enumerate(class_sets[43])}158 159        super().__init__(*args, **kwargs)160 161    def _info(self):162        metadata = self.metadata163        metadata['size'] = self.SIZE164        metadata['num_classes'] = self.NUM_CLASSES165        metadata['spatial_resolution'] = self.spatial_resolution166        return datasets.DatasetInfo(167            description=json.dumps(metadata),168            features=datasets.Features({169                "optical": datasets.Array3D(shape=(12, self.HEIGHT, self.WIDTH), dtype="float32"),170                "radar": datasets.Array3D(shape=(2, self.HEIGHT, self.WIDTH), dtype="float32"),171                "optical_channel_wv": datasets.Sequence(datasets.Value("float32")),172                "radar_channel_wv": datasets.Sequence(datasets.Value("float32")),173                "label": datasets.Sequence(datasets.Value("float32"), length=self.NUM_CLASSES),174                "spatial_resolution": datasets.Value("int32"),175            }),176        )177 178    def _split_generators(self, dl_manager):179        print(dl_manager.download_config.cache_dir)180        # Ensure cache directory is set181        if dl_manager.download_config.cache_dir is None:182            return []183        if isinstance(self.DATA_URL, list):184            try:185                downloaded_files = dl_manager.download(self.DATA_URL)186                print(f"downloaded files: {downloaded_files}")187                combined_file = os.path.join(dl_manager.download_config.cache_dir, "combined.tar.gz") 188                print(f"copying files to {combined_file}")189                target_dir = os.path.dirname(combined_file)190                os.makedirs(target_dir, exist_ok=True)  # Create only the directory                191                with open(combined_file, 'wb') as outfile:192                    counter = 0 193                    for part_file in tqdm(downloaded_files, desc="Copying files", unit="file"):194                        # print(f"copying {counter}-th file: {part_file}")195                        with open(part_file, 'rb') as infile:196                            shutil.copyfileobj(infile, outfile)197                        counter += 1198                print(f"extacting from {combined_file}")199                # data_dir = dl_manager.extract(combined_file)200                data_dir = os.path.join(dl_manager.download_config.cache_dir, "extracted")201                os.makedirs(data_dir, exist_ok=True)202                with tarfile.open(combined_file, "r:gz") as tar:203                    tar.extractall(path=data_dir)204                os.remove(combined_file)205                print(f"data_dir: {data_dir}")206            except Exception as e:207                print(f"exception: {e}, so setting data_dir to None")208                data_dir = None209        else:210            data_dir = dl_manager.download_and_extract(self.DATA_URL)211 212        return [213            datasets.SplitGenerator(214                name="train",215                gen_kwargs={216                    "split": 'train',217                    "data_dir": data_dir, 218                },219            ),220            datasets.SplitGenerator(221                name="val",222                gen_kwargs={223                    "split": 'val',224                    "data_dir": data_dir,225                },226            ),227            datasets.SplitGenerator(228                name="test",229                gen_kwargs={230                    "split": 'test',231                    "data_dir": data_dir,232                },233            )234        ]235 236    def _generate_examples(self, split, data_dir):237        optical_channel_wv = np.array(self.metadata["s2c"]["channel_wv"])238        radar_channel_wv = np.array(self.metadata["s1"]["channel_wv"])239        spatial_resolution = self.spatial_resolution240 241        data_dir = os.path.join(data_dir, "BigEarthNet")242        metadata = pd.read_csv(os.path.join(data_dir, "metadata.csv"))243        metadata = metadata[metadata["split"] == split].reset_index(drop=True)244 245        for index, row in metadata.iterrows():246            optical_path = os.path.join(data_dir, row.optical_path)247            optical = self._read_image(optical_path).astype(np.float32) # CxHxW248 249            radar_path = os.path.join(data_dir, row.radar_path)250            radar = self._read_image(radar_path).astype(np.float32)251 252            label_path = os.path.join(data_dir, row.label_path)253            label = self._load_label(label_path)254 255            sample = {256                "optical": optical,257                "radar": radar,258                "optical_channel_wv": optical_channel_wv,259                "radar_channel_wv": radar_channel_wv,260                "label": label,261                "spatial_resolution": spatial_resolution,262            }263 264            yield f"{index}", sample265    266    def _load_label(self, label_path):267        with open(label_path) as f:268            labels = json.load(f)['labels']269        indices =[self.class2idx[label] for label in labels]270        indices_optional = [label_converter.get(idx) for idx in indices]271        indices = [idx for idx in indices_optional if idx is not None]272        label = np.zeros(19, dtype=np.int64)273        label[indices] = 1274        return label275    276    def _read_image(self, image_path):277        """Read tiff image from image_path278        Args:279            image_path: 280                Image path to read from281 282        Return:283            image: 284                C, H, W numpy array image285        """286        image = tifffile.imread(image_path)287        image = np.transpose(image, (2, 0, 1))288 289        return image