From c29b010d8761cd053b3c228075cc50ffcfc7a272 Mon Sep 17 00:00:00 2001 From: saumyasinha Date: Mon, 13 Jun 2022 12:41:32 -0700 Subject: [PATCH 01/35] add class for Deep Globe Land Cover dataset --- torchgeo/datasets/__init__.py | 2 + torchgeo/datasets/deepglobelandcover.py | 258 ++++++++++++++++++++++++ 2 files changed, 260 insertions(+) create mode 100644 torchgeo/datasets/deepglobelandcover.py diff --git a/torchgeo/datasets/__init__.py b/torchgeo/datasets/__init__.py index d2b0ff1858e..e7bbb25b9b8 100644 --- a/torchgeo/datasets/__init__.py +++ b/torchgeo/datasets/__init__.py @@ -27,6 +27,7 @@ from .cowc import COWC, COWCCounting, COWCDetection from .cv4a_kenya_crop_type import CV4AKenyaCropType from .cyclone import TropicalCycloneWindEstimation +from .deepglobelandcover import DeepGlobeLandCover from .dfc2022 import DFC2022 from .eddmaps import EDDMapS from .enviroatlas import EnviroAtlas @@ -148,6 +149,7 @@ "COWCCounting", "COWCDetection", "CV4AKenyaCropType", + "DeepGlobeLandCover", "DFC2022", "EnviroAtlas", "ETCI2021", diff --git a/torchgeo/datasets/deepglobelandcover.py b/torchgeo/datasets/deepglobelandcover.py new file mode 100644 index 00000000000..3d557cf3d9b --- /dev/null +++ b/torchgeo/datasets/deepglobelandcover.py @@ -0,0 +1,258 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. + +"""DeepGlobe Land Cover Classification Challenge dataset.""" + +import os +from typing import Callable, Dict, Optional + +import matplotlib.pyplot as plt +import numpy as np +import torch +from matplotlib.figure import Figure +from PIL import Image +from torch import Tensor + +from .geo import VisionDataset +from .utils import ( + check_integrity, + draw_semantic_segmentation_masks, + extract_archive, + rgb_to_mask, +) + + +class DeepGlobeLandCover(VisionDataset): + """DeepGlobe Land Cover Classification Challenge dataset. + + The `DeepGlobe Land Cover Classification Challenge ` dataset + offers high-resolution sub-meter satellite imagery focusing for the task of semantic segmentation to detect areas of urban, agriculture, rangeland, forest, water, barren, and unknown. + It contains 1,146 satellite images of size 2448 x 2448 pixels in total, split into training/validation/test sets, the original dataset can be downloaded from `Kaggle `. + However, we only use the training dataset with 803 images since the original test and valid dataset are not accompanied by labels. The dataset that we use with a custom train/test split can be downloaded from `Kaggle ` (created as a part of Computer Vision by Deep Learning (CS4245) course offered at TU Delft). + + Dataset format: + + * images are RGB data + * masks are RGB image with with unique RGB values representing the class + + Dataset classes: + + 0. Urban land + 1. Agriculture land + 2. Rangeland + 3. Forest land + 4. Water + 5. Barren land + 6. Unknown + + File names for satellite images and the corresponding mask image are id_sat.jpg and id_mask.png, + where id is an integer assigned to every image. + + If you use this dataset in your research, please cite the following paper: + + * DeepGlobe 2018: A Challenge to Parse the Earth Through Satellite Images + + """ + + filename = "data.zip" + data_root = "data" + md5 = "f32684b0b2bf6f8d604cd359a399c061" + splits = ["train", "test"] + classes = [ + "Urban land", + "Agriculture land", + "Rangeland", + "Forest land", + "Water", + "Barren land", + "Unknown" + ] + colormap = [ + (0, 255, 255), + (255, 255, 0), + (255, 0, 255), + (0, 255, 0), + (0, 0, 255), + (255, 255, 255), + (0, 0, 0) + ] + + def __init__( + self, + root: str = "data", + split: str = "train", + transforms: Optional[Callable[[Dict[str, Tensor]], Dict[str, Tensor]]] = None, + checksum: bool = False, + ) -> None: + """Initialize a new DeepGlobeLandCover dataset instance. + + Args: + root: root directory where dataset can be found + split: one of "train" or "test" + transforms: a function/transform that takes input sample and its target as + entry and returns a transformed version + checksum: if True, check the MD5 of the downloaded files (may be slow) + """ + assert split in self.splits + self.root = root + self.split = split + self.transforms = transforms + self.checksum = checksum + + self._verify() + if split == "train": + split_folder = "training_data" + else: + split_folder = "test_data" + + self.files = [] + for image in os.listdir(os.path.join(root, self.data_root, split_folder, "images")): + if image.endswith(".jpg"): + id = image[:-8] + image_path = os.path.join(root, self.data_root, split_folder, "images", image) + mask_path = os.path.join(root, self.data_root, split_folder, "masks", str(id)+"_mask.png") + if os.path.exists(mask_path): + self.files.append(dict(image=image_path, mask=mask_path)) + + def __getitem__(self, index: int) -> Dict[str, Tensor]: + """Return an index within the dataset. + + Args: + index: index to return + + Returns: + data and label at that index + """ + image = self._load_image(index) + mask = self._load_target(index) + sample = {"image": image, "mask": mask} + + if self.transforms is not None: + sample = self.transforms(sample) + + return sample + + def __len__(self) -> int: + """Return the number of data points in the dataset. + + Returns: + length of the dataset + """ + return len(self.files) + + def _load_image(self, index: int) -> Tensor: + """Load a single image. + + Args: + index: index to return + + Returns: + the image + """ + path = self.files[index]["image"] + + with Image.open(path) as img: + array: "np.typing.NDArray[np.int_]" = np.array(img) + tensor = torch.from_numpy(array) + # Convert from HxWxC to CxHxW + tensor = tensor.permute((2, 0, 1)) + return tensor + + + + def _load_target(self, index: int) -> Tensor: + """Load the target mask for a single image. + + Args: + index: index to return + + Returns: + the target mask + """ + path = self.files[index]["mask"] + with Image.open(path) as img: + array: "np.typing.NDArray[np.uint8]" = np.array(img) + array = rgb_to_mask(array, self.colormap) + tensor = torch.from_numpy(array) + # Convert from HxWxC to CxHxW + tensor = tensor.to(torch.long) + return tensor + + def _verify(self) -> None: + """Verify the integrity of the dataset. + + Raises: + RuntimeError: if checksum fails or the dataset is not downloaded + """ + # Check if the files already exist + if os.path.exists(os.path.join(self.root, self.data_root)): + return + + # Check if .zip file already exists (if so extract) + filepath = os.path.join(self.root, self.filename) + + if os.path.isfile(filepath): + if self.checksum and not check_integrity(filepath, self.md5): + raise RuntimeError("Dataset found, but corrupted.") + extract_archive(filepath) + return + + # Check if the user requested to download the dataset + raise RuntimeError( + "Dataset not found in `root` directory, either specify a different" + + " `root` directory or manually download the dataset to this directory." + ) + + def plot( + self, + sample: Dict[str, Tensor], + show_titles: bool = True, + suptitle: Optional[str] = None, + alpha: float = 0.5, + ) -> Figure: + """Plot a sample from the dataset. + + Args: + sample: a sample returned by :meth:`__getitem__` + show_titles: flag indicating whether to show titles above each panel + suptitle: optional string to use as a suptitle + alpha: opacity with which to render predictions on top of the imagery + + Returns: + a matplotlib Figure with the rendered sample + """ + ncols = 1 + image1 = draw_semantic_segmentation_masks( + sample["image"], sample["mask"], alpha=alpha, colors=self.colormap + ) + if "prediction" in sample: + ncols += 1 + image2 = draw_semantic_segmentation_masks( + sample["image"], + sample["prediction"], + alpha=alpha, + colors=self.colormap, + ) + + fig, axs = plt.subplots(ncols=ncols, figsize=(ncols * 10, 10)) + if ncols > 1: + (ax0, ax1) = axs + else: + ax0 = axs + + ax0.imshow(image1) + ax0.axis("off") + if ncols > 1: + ax1.imshow(image2) + ax1.axis("off") + + if show_titles: + ax0.set_title("Ground Truth") + if ncols > 1: + ax1.set_title("Predictions") + + if suptitle is not None: + plt.suptitle(suptitle) + + return fig + From e6c59802a22d9827ed537d4c24ca6bf07b21bf5e Mon Sep 17 00:00:00 2001 From: saumyasinha Date: Mon, 13 Jun 2022 14:33:41 -0700 Subject: [PATCH 02/35] add Lightning data module implementation for deepglobe land cover --- torchgeo/datamodules/__init__.py | 2 + torchgeo/datamodules/deepglobelandcover.py | 122 +++++++++++++++++++++ torchgeo/datasets/deepglobelandcover.py | 11 +- 3 files changed, 132 insertions(+), 3 deletions(-) create mode 100644 torchgeo/datamodules/deepglobelandcover.py diff --git a/torchgeo/datamodules/__init__.py b/torchgeo/datamodules/__init__.py index 02cb2b83e14..2d4ef64c3b5 100644 --- a/torchgeo/datamodules/__init__.py +++ b/torchgeo/datamodules/__init__.py @@ -7,6 +7,7 @@ from .chesapeake import ChesapeakeCVPRDataModule from .cowc import COWCCountingDataModule from .cyclone import CycloneDataModule +from .deepglobelandcover import DeepGlobeLandCoverDataModule from .etci2021 import ETCI2021DataModule from .eurosat import EuroSATDataModule from .fair1m import FAIR1MDataModule @@ -32,6 +33,7 @@ # VisionDataset "BigEarthNetDataModule", "COWCCountingDataModule", + "DeepGlobeLandCoverDataModule", "ETCI2021DataModule", "EuroSATDataModule", "FAIR1MDataModule", diff --git a/torchgeo/datamodules/deepglobelandcover.py b/torchgeo/datamodules/deepglobelandcover.py new file mode 100644 index 00000000000..91037a42b31 --- /dev/null +++ b/torchgeo/datamodules/deepglobelandcover.py @@ -0,0 +1,122 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. + +"""DeepGlobe Land Cover Classification Challenge datamodule.""" + +from typing import Any, Dict, Optional + +import pytorch_lightning as pl +from torch.utils.data import DataLoader, Dataset +from torchvision.transforms import Compose + +from ..datasets import DeepGlobeLandCover +from .utils import dataset_split + + +class DeepGlobeLandCoverDataModule(pl.LightningDataModule): + """LightningDataModule implementation for the DeepGlobe Land Cover Classification Challenge dataset. + + Uses the train/test splits from the dataset. + + """ + + def __init__( + self, + root_dir: str, + batch_size: int = 64, + num_workers: int = 0, + val_split_pct: float = 0.2, + **kwargs: Any, + ) -> None: + """Initialize a LightningDataModule for DeepGlobe Land Cover based DataLoaders. + + Args: + root_dir: The ``root`` argument to pass to the DeepGlobe Land Cover Dataset classes + batch_size: The batch size to use in all created DataLoaders + num_workers: The number of workers to use in all created DataLoaders + val_split_pct: What percentage of the dataset to use as a validation set + """ + super().__init__() # type: ignore[no-untyped-call] + self.root_dir = root_dir + self.batch_size = batch_size + self.num_workers = num_workers + self.val_split_pct = val_split_pct + + def preprocess(self, sample: Dict[str, Any]) -> Dict[str, Any]: + """Transform a single sample from the Dataset. + + Args: + sample: input image dictionary + + Returns: + preprocessed sample + """ + sample["image"] = sample["image"].float() + sample["image"] /= 255.0 + return sample + + def setup(self, stage: Optional[str] = None) -> None: + """Initialize the main ``Dataset`` objects. + + This method is called once per GPU per run. + + Args: + stage: stage to set up + """ + transforms = Compose([self.preprocess]) + + dataset = DeepGlobeLandCover(self.root_dir, "train", transforms=transforms) + + self.train_dataset: Dataset[Any] + self.val_dataset: Dataset[Any] + + if self.val_split_pct > 0.0: + self.train_dataset, self.val_dataset, _ = dataset_split( + dataset, val_pct=self.val_split_pct, test_pct=0.0 + ) + else: + self.train_dataset = dataset + self.val_dataset = dataset + + self.test_dataset = DeepGlobeLandCover(self.root_dir, "test", transforms=transforms) + + def train_dataloader(self) -> DataLoader[Any]: + """Return a DataLoader for training. + + Returns: + training data loader + """ + return DataLoader( + self.train_dataset, + batch_size=self.batch_size, + num_workers=self.num_workers, + shuffle=True, + ) + + def val_dataloader(self) -> DataLoader[Any]: + """Return a DataLoader for validation. + + Returns: + validation data loader + """ + return DataLoader( + self.val_dataset, + batch_size=self.batch_size, + num_workers=self.num_workers, + shuffle=False, + ) + + def test_dataloader(self) -> DataLoader[Any]: + """Return a DataLoader for testing. + + Returns: + testing data loader + """ + return DataLoader( + self.test_dataset, + batch_size=self.batch_size, + num_workers=self.num_workers, + shuffle=False, + ) + + diff --git a/torchgeo/datasets/deepglobelandcover.py b/torchgeo/datasets/deepglobelandcover.py index 3d557cf3d9b..626589d2788 100644 --- a/torchgeo/datasets/deepglobelandcover.py +++ b/torchgeo/datasets/deepglobelandcover.py @@ -26,9 +26,14 @@ class DeepGlobeLandCover(VisionDataset): """DeepGlobe Land Cover Classification Challenge dataset. The `DeepGlobe Land Cover Classification Challenge ` dataset - offers high-resolution sub-meter satellite imagery focusing for the task of semantic segmentation to detect areas of urban, agriculture, rangeland, forest, water, barren, and unknown. - It contains 1,146 satellite images of size 2448 x 2448 pixels in total, split into training/validation/test sets, the original dataset can be downloaded from `Kaggle `. - However, we only use the training dataset with 803 images since the original test and valid dataset are not accompanied by labels. The dataset that we use with a custom train/test split can be downloaded from `Kaggle ` (created as a part of Computer Vision by Deep Learning (CS4245) course offered at TU Delft). + offers high-resolution sub-meter satellite imagery focusing for the task of semantic segmentation to detect areas of + urban, agriculture, rangeland, forest, water, barren, and unknown. + It contains 1,146 satellite images of size 2448 x 2448 pixels in total, + split into training/validation/test sets, the original dataset can be downloaded from + `Kaggle `. + However, we only use the training dataset with 803 images since the original test and + valid dataset are not accompanied by labels. The dataset that we use with a custom train/test split can be downloaded from `Kaggle ` + (created as a part of Computer Vision by Deep Learning (CS4245) course offered at TU Delft). Dataset format: From 283645f1445f3a79a88eacedc7dcfa65cd5372a1 Mon Sep 17 00:00:00 2001 From: saumyasinha Date: Tue, 14 Jun 2022 15:39:30 -0700 Subject: [PATCH 03/35] fix formatting errors --- benchmark.py | 2 +- evaluate.py | 2 +- torchgeo/datamodules/deepglobelandcover.py | 12 ++--- torchgeo/datamodules/potsdam.py | 2 +- torchgeo/datasets/deepglobelandcover.py | 58 ++++++++++++---------- 5 files changed, 40 insertions(+), 36 deletions(-) diff --git a/benchmark.py b/benchmark.py index 5f8a3686a97..c2bfa58378f 100755 --- a/benchmark.py +++ b/benchmark.py @@ -52,7 +52,7 @@ def set_up_parser() -> argparse.ArgumentParser: parser.add_argument( "-b", "--batch-size", - default=2**4, + default=2 ** 4, type=int, help="number of samples in each mini-batch", metavar="SIZE", diff --git a/evaluate.py b/evaluate.py index 74dd72b915e..ad40a0eb90d 100755 --- a/evaluate.py +++ b/evaluate.py @@ -52,7 +52,7 @@ def set_up_parser() -> argparse.ArgumentParser: parser.add_argument( "-b", "--batch-size", - default=2**4, + default=2 ** 4, type=int, help="number of samples in each mini-batch", metavar="SIZE", diff --git a/torchgeo/datamodules/deepglobelandcover.py b/torchgeo/datamodules/deepglobelandcover.py index 91037a42b31..a374735f2c1 100644 --- a/torchgeo/datamodules/deepglobelandcover.py +++ b/torchgeo/datamodules/deepglobelandcover.py @@ -14,7 +14,7 @@ class DeepGlobeLandCoverDataModule(pl.LightningDataModule): - """LightningDataModule implementation for the DeepGlobe Land Cover Classification Challenge dataset. + """LightningDataModule implementation for the DeepGlobe Land Cover dataset. Uses the train/test splits from the dataset. @@ -31,12 +31,12 @@ def __init__( """Initialize a LightningDataModule for DeepGlobe Land Cover based DataLoaders. Args: - root_dir: The ``root`` argument to pass to the DeepGlobe Land Cover Dataset classes + root_dir: The ``root`` argument to pass to the DeepGlobe Dataset classes batch_size: The batch size to use in all created DataLoaders num_workers: The number of workers to use in all created DataLoaders val_split_pct: What percentage of the dataset to use as a validation set """ - super().__init__() # type: ignore[no-untyped-call] + super().__init__() self.root_dir = root_dir self.batch_size = batch_size self.num_workers = num_workers @@ -78,7 +78,9 @@ def setup(self, stage: Optional[str] = None) -> None: self.train_dataset = dataset self.val_dataset = dataset - self.test_dataset = DeepGlobeLandCover(self.root_dir, "test", transforms=transforms) + self.test_dataset = DeepGlobeLandCover( + self.root_dir, "test", transforms=transforms + ) def train_dataloader(self) -> DataLoader[Any]: """Return a DataLoader for training. @@ -118,5 +120,3 @@ def test_dataloader(self) -> DataLoader[Any]: num_workers=self.num_workers, shuffle=False, ) - - diff --git a/torchgeo/datamodules/potsdam.py b/torchgeo/datamodules/potsdam.py index 776d999cb1e..6d5a7bb2784 100644 --- a/torchgeo/datamodules/potsdam.py +++ b/torchgeo/datamodules/potsdam.py @@ -37,7 +37,7 @@ def __init__( num_workers: The number of workers to use in all created DataLoaders val_split_pct: What percentage of the dataset to use as a validation set """ - super().__init__() # type: ignore[no-untyped-call] + super().__init__() self.root_dir = root_dir self.batch_size = batch_size self.num_workers = num_workers diff --git a/torchgeo/datasets/deepglobelandcover.py b/torchgeo/datasets/deepglobelandcover.py index 626589d2788..efc161f2055 100644 --- a/torchgeo/datasets/deepglobelandcover.py +++ b/torchgeo/datasets/deepglobelandcover.py @@ -25,15 +25,19 @@ class DeepGlobeLandCover(VisionDataset): """DeepGlobe Land Cover Classification Challenge dataset. - The `DeepGlobe Land Cover Classification Challenge ` dataset - offers high-resolution sub-meter satellite imagery focusing for the task of semantic segmentation to detect areas of - urban, agriculture, rangeland, forest, water, barren, and unknown. - It contains 1,146 satellite images of size 2448 x 2448 pixels in total, - split into training/validation/test sets, the original dataset can be downloaded from - `Kaggle `. - However, we only use the training dataset with 803 images since the original test and - valid dataset are not accompanied by labels. The dataset that we use with a custom train/test split can be downloaded from `Kaggle ` - (created as a part of Computer Vision by Deep Learning (CS4245) course offered at TU Delft). + The `DeepGlobe Land Cover Classification Challenge + `__ dataset + offers high-resolution sub-meter satellite imagery focusing for the task of + semantic segmentation to detect areas of urban, agriculture, rangeland, forest, + water, barren, and unknown. It contains 1,146 satellite images of size + 2448 x 2448 pixels in total, split into training/validation/test sets, the original + dataset can be downloaded from `Kaggle `__. + However, we only use the training dataset with 803 images since the original test + and valid dataset are not accompanied by labels. The dataset that we use with a + custom train/test split can be downloaded from `Kaggle `__ (created as a + part of Computer Vision by Deep Learning (CS4245) course offered at TU Delft). Dataset format: @@ -50,14 +54,14 @@ class DeepGlobeLandCover(VisionDataset): 5. Barren land 6. Unknown - File names for satellite images and the corresponding mask image are id_sat.jpg and id_mask.png, - where id is an integer assigned to every image. + File names for satellite images and the corresponding mask image are id_sat.jpg and + id_mask.png, where id is an integer assigned to every image. If you use this dataset in your research, please cite the following paper: * DeepGlobe 2018: A Challenge to Parse the Earth Through Satellite Images - """ + """ filename = "data.zip" data_root = "data" @@ -70,7 +74,7 @@ class DeepGlobeLandCover(VisionDataset): "Forest land", "Water", "Barren land", - "Unknown" + "Unknown", ] colormap = [ (0, 255, 255), @@ -79,7 +83,7 @@ class DeepGlobeLandCover(VisionDataset): (0, 255, 0), (0, 0, 255), (255, 255, 255), - (0, 0, 0) + (0, 0, 0), ] def __init__( @@ -103,7 +107,7 @@ def __init__( self.split = split self.transforms = transforms self.checksum = checksum - + self._verify() if split == "train": split_folder = "training_data" @@ -111,11 +115,17 @@ def __init__( split_folder = "test_data" self.files = [] - for image in os.listdir(os.path.join(root, self.data_root, split_folder, "images")): + for image in os.listdir( + os.path.join(root, self.data_root, split_folder, "images") + ): if image.endswith(".jpg"): id = image[:-8] - image_path = os.path.join(root, self.data_root, split_folder, "images", image) - mask_path = os.path.join(root, self.data_root, split_folder, "masks", str(id)+"_mask.png") + image_path = os.path.join( + root, self.data_root, split_folder, "images", image + ) + mask_path = os.path.join( + root, self.data_root, split_folder, "masks", str(id) + "_mask.png" + ) if os.path.exists(mask_path): self.files.append(dict(image=image_path, mask=mask_path)) @@ -163,8 +173,6 @@ def _load_image(self, index: int) -> Tensor: tensor = tensor.permute((2, 0, 1)) return tensor - - def _load_target(self, index: int) -> Tensor: """Load the target mask for a single image. @@ -176,7 +184,7 @@ def _load_target(self, index: int) -> Tensor: """ path = self.files[index]["mask"] with Image.open(path) as img: - array: "np.typing.NDArray[np.uint8]" = np.array(img) + array: "np.typing.NDArray[np.uint8]" = np.array(img) array = rgb_to_mask(array, self.colormap) tensor = torch.from_numpy(array) # Convert from HxWxC to CxHxW @@ -195,7 +203,7 @@ def _verify(self) -> None: # Check if .zip file already exists (if so extract) filepath = os.path.join(self.root, self.filename) - + if os.path.isfile(filepath): if self.checksum and not check_integrity(filepath, self.md5): raise RuntimeError("Dataset found, but corrupted.") @@ -233,10 +241,7 @@ def plot( if "prediction" in sample: ncols += 1 image2 = draw_semantic_segmentation_masks( - sample["image"], - sample["prediction"], - alpha=alpha, - colors=self.colormap, + sample["image"], sample["prediction"], alpha=alpha, colors=self.colormap ) fig, axs = plt.subplots(ncols=ncols, figsize=(ncols * 10, 10)) @@ -260,4 +265,3 @@ def plot( plt.suptitle(suptitle) return fig - From 4f5ea5c96b99ecdc3b8832e12e618d2074c4f887 Mon Sep 17 00:00:00 2001 From: saumyasinha Date: Tue, 14 Jun 2022 16:37:41 -0700 Subject: [PATCH 04/35] fix urls, formats and add link for paper --- torchgeo/datasets/deepglobelandcover.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/torchgeo/datasets/deepglobelandcover.py b/torchgeo/datasets/deepglobelandcover.py index efc161f2055..12c75797077 100644 --- a/torchgeo/datasets/deepglobelandcover.py +++ b/torchgeo/datasets/deepglobelandcover.py @@ -59,7 +59,7 @@ class DeepGlobeLandCover(VisionDataset): If you use this dataset in your research, please cite the following paper: - * DeepGlobe 2018: A Challenge to Parse the Earth Through Satellite Images + * https://arxiv.org/pdf/1805.06561.pdf """ @@ -212,7 +212,7 @@ def _verify(self) -> None: # Check if the user requested to download the dataset raise RuntimeError( - "Dataset not found in `root` directory, either specify a different" + f"Dataset not found in `root={self.root}`, either specify a different" + " `root` directory or manually download the dataset to this directory." ) From 0a478a26bb43b14937150f49b84f6d7dc4184d2d Mon Sep 17 00:00:00 2001 From: saumyasinha Date: Wed, 15 Jun 2022 14:22:44 -0700 Subject: [PATCH 05/35] add tests for deepglobe dataset and datamodule --- tests/data/deepglobelandcover/data.zip | Bin 0 -> 5832 bytes .../data/test_data/images/8_sat.jpg | Bin 0 -> 662 bytes .../data/test_data/images/9_sat.jpg | Bin 0 -> 653 bytes .../data/test_data/masks/8_mask.png | Bin 0 -> 79 bytes .../data/test_data/masks/9_mask.png | Bin 0 -> 79 bytes .../data/training_data/images/1_sat.jpg | Bin 0 -> 654 bytes .../data/training_data/images/2_sat.jpg | Bin 0 -> 654 bytes .../data/training_data/images/3_sat.jpg | Bin 0 -> 649 bytes .../data/training_data/masks/1_mask.png | Bin 0 -> 79 bytes .../data/training_data/masks/2_mask.png | Bin 0 -> 79 bytes .../data/training_data/masks/3_mask.png | Bin 0 -> 79 bytes tests/datamodules/test_deepglobelandcover.py | 33 ++++++++ tests/datasets/test_deepglobelandcover.py | 72 ++++++++++++++++++ torchgeo/datamodules/deepglobelandcover.py | 2 +- torchgeo/datamodules/potsdam.py | 2 +- 15 files changed, 107 insertions(+), 2 deletions(-) create mode 100644 tests/data/deepglobelandcover/data.zip create mode 100644 tests/data/deepglobelandcover/data/test_data/images/8_sat.jpg create mode 100644 tests/data/deepglobelandcover/data/test_data/images/9_sat.jpg create mode 100644 tests/data/deepglobelandcover/data/test_data/masks/8_mask.png create mode 100644 tests/data/deepglobelandcover/data/test_data/masks/9_mask.png create mode 100644 tests/data/deepglobelandcover/data/training_data/images/1_sat.jpg create mode 100644 tests/data/deepglobelandcover/data/training_data/images/2_sat.jpg create mode 100644 tests/data/deepglobelandcover/data/training_data/images/3_sat.jpg create mode 100644 tests/data/deepglobelandcover/data/training_data/masks/1_mask.png create mode 100644 tests/data/deepglobelandcover/data/training_data/masks/2_mask.png create mode 100644 tests/data/deepglobelandcover/data/training_data/masks/3_mask.png create mode 100644 tests/datamodules/test_deepglobelandcover.py create mode 100644 tests/datasets/test_deepglobelandcover.py diff --git a/tests/data/deepglobelandcover/data.zip b/tests/data/deepglobelandcover/data.zip new file mode 100644 index 0000000000000000000000000000000000000000..44b87476ea0d188ac78cb3a8f926041fb7eb1bd6 GIT binary patch literal 5832 zcmeHLX;4#F6n+UI20;)N3XW1V5(G7Dtw6MB6cQB?t1LxX5|&`BfSS0_PNfW>MWuj> z5D^qb6c8!c+S;+h(jdqnpsk9wC?bf6A~@QzDCxa~;0-T%F#fYcm@NEw-*?Wv-#yvX5s3rd0Xd8Y^p{XM4nsVUFpM7>B9aI8+h=M6n+7tWVYdKY1dF+>k%VDK z$r$#rT0DmU5ns&Qyft(%<01eoz-Qba^+={cC0W_K+fz9lDwSgz+!K{vCW($oNXSS? ziOI;wID9zf05>*uUwS%s-HNmTXRlTMYrIx*IBXYpKlVzl4~O%+@A}Hpda2aezwzen z@+wYUgOnCbqnn$X>)9t#tO{e3PaQm^f2~PIqOx_V3@SswF{3ir90B{PjBC^q-5DH0 z(V))d1qTZFAwg|TEzMNR2Fub?X;n>)w7jOex}1EZK(pHJ2U_t&i|MRltqF|cc?SE9 zK3(HmmG$h$?vtD9EA%X{u5@ub?i<)V<XJT^S)Rm;2(-f5EQUp6a? z|4={q^J^Bl!ggbcPlef;kXC~f&+7{c!k*8}@H@F7PiF-+gH?&pYhi zm5`20&lm0NWQlvKZUj}jA78wq{bfr2oeK|siR^fIy3#$<>Fa^!*8Id1PEoym&-)Wk zlq?+x4CV=9N#_TqQ2GwU$HhtFX0}*ya<(Ut*@j*&%NNe7T>6i68Q<(QM_2!Bytchb zi^oFUKGS0!;$+v=6)jm$xk-0Qo#?eeZo$1eoi?#0;Wk~?c4T^@Pf}UtLznp2<_mf+ z1crwDr}cL*yS?vbCwt|T<=WP*|EAW(`v&*y$7c%9$)cuWP|kAIKoz$C%ii}VP)!1% zY8;hR1LZibn*W1pB5&4S)@!s)%@%IU+nMJpHpmb^3Qg>u*05!M zOKym8%99O^dtSWM>yDE}kP$P=2a2ga)YUvT#n>t-h7Z&dfiDWu4){%grgg^tL-^K<0)hrU)oTvnuYVdQfBHN3Ah-N{R^sirG0{ zV?O-Gm;XSrp1Yi3ZNlp*KIhv1tU9qj<^^-$bhm5okXYpHi_Kjzm!q05lvu2;#?2Gzw_ANc+`6qw~$^B>1@m zC9$BYi65O(012E@RAwSyB>Z%tAc2ciHB2&M)&Rh8)*t}JPZ}t&!30J0O2DX2;oPAT zU#?U9)Syyy2ll-9$vF{Q)9q le*{E$*FuR>^awISJq!@3Tslo~$}mhH{6&Iaj+5bk{{b@i3VQ$m literal 0 HcmV?d00001 diff --git a/tests/data/deepglobelandcover/data/test_data/images/8_sat.jpg b/tests/data/deepglobelandcover/data/test_data/images/8_sat.jpg new file mode 100644 index 0000000000000000000000000000000000000000..6cdba83dd16e8b30db8290b3cc4bf23b7eb26967 GIT binary patch literal 662 zcmex=^(PF6}rMnOeST|r4lSw=>~TvNxu(8R<c1}I=;VrF4wW9Q)H;sz?% zD!{d!pzFb!U9xX3zTPI5o8roG<0MW4oqZMDikqloVbuf*=gfJ(V&YTRE(2~ znmD<{#3dx9RMpfqG__1j&CD$#!;2CL#a$oX%`7YwDfZW0;;*tvBdtt>Q)Ql~ S`kafdqK{5LN?%d`|0V#E*W1bf literal 0 HcmV?d00001 diff --git a/tests/data/deepglobelandcover/data/test_data/images/9_sat.jpg b/tests/data/deepglobelandcover/data/test_data/images/9_sat.jpg new file mode 100644 index 0000000000000000000000000000000000000000..250b2509eca42f57a9f0de096c3772470b80cd73 GIT binary patch literal 653 zcmex=^(PF6}rMnOeST|r4lSw=>~TvNxu(8R<c1}I=;VrF4wW9Q)H;sz?% zD!{d!pzFb!U9xX3zTPI5o8roG<0MW4oqZMDikqloVbuf*=gfJ(V&YTRE(2~ znmD<{#3dx9RMpfqG__1j&CD$#!}Fw_b04~8E=kkkRP9u`=qftt#?K!2kIP^E JXE6SM695ew*^(PF6}rMnOeST|r4lSw=>~TvNxu(8R<c1}I=;VrF4wW9Q)H;sz?% zD!{d!pzFb!U9xX3zTPI5o8roG<0MW4oqZMDikqloVbuf*=gfJ(V&YTRE(2~ znmD<{#3dx9RMpfqG__1j&CD$#!{N($>65*;O!8cko)NIwSjbb$(j?Hey8Yhe KAL0xD-vj{DH`sRo literal 0 HcmV?d00001 diff --git a/tests/data/deepglobelandcover/data/training_data/images/2_sat.jpg b/tests/data/deepglobelandcover/data/training_data/images/2_sat.jpg new file mode 100644 index 0000000000000000000000000000000000000000..3e62a87aa7225cb0438014c8cd39c0cee8c5a35d GIT binary patch literal 654 zcmex=^(PF6}rMnOeST|r4lSw=>~TvNxu(8R<c1}I=;VrF4wW9Q)H;sz?% zD!{d!pzFb!U9xX3zTPI5o8roG<0MW4oqZMDikqloVbuf*=gfJ(V&YTRE(2~ znmD<{#3dx9RMpfqG__1j&CD$#!+z7NM~Y8$+N@f2gq6>M*;Zpw*Uw-3k4#@} K`{Pah|C<2q*xK&^ literal 0 HcmV?d00001 diff --git a/tests/data/deepglobelandcover/data/training_data/images/3_sat.jpg b/tests/data/deepglobelandcover/data/training_data/images/3_sat.jpg new file mode 100644 index 0000000000000000000000000000000000000000..5a5aa528ffb7408aeb671fe7b361968bed30c135 GIT binary patch literal 649 zcmex=^(PF6}rMnOeST|r4lSw=>~TvNxu(8R<c1}I=;VrF4wW9Q)H;sz?% zD!{d!pzFb!U9xX3zTPI5o8roG<0MW4oqZMDikqloVbuf*=gfJ(V&YTRE(2~ znmD<{#3dx9RMpfqG__1j&CD$#!@e`8j)qKNJizc}QJ41Fl^^#9-(CDiXsk;J|?+Kz!f; Z0|U1_BlC>b>2*LA44$rjF6*2Ung9T}7a9Nn literal 0 HcmV?d00001 diff --git a/tests/data/deepglobelandcover/data/training_data/masks/3_mask.png b/tests/data/deepglobelandcover/data/training_data/masks/3_mask.png new file mode 100644 index 0000000000000000000000000000000000000000..5eb44ea35847270c9104ab81214a2d2b9a6a1a51 GIT binary patch literal 79 zcmeAS@N?(olHy`uVBq!ia0vp^Od!kwBL7~QRScxWJY5_^D&{2rIsajPV`F0{5H~h5 ZGDrw9F{ul;Sprosc)I$ztaD0e0szm!6n+2z literal 0 HcmV?d00001 diff --git a/tests/datamodules/test_deepglobelandcover.py b/tests/datamodules/test_deepglobelandcover.py new file mode 100644 index 00000000000..a923e881eeb --- /dev/null +++ b/tests/datamodules/test_deepglobelandcover.py @@ -0,0 +1,33 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. + +import os + +import pytest +from _pytest.fixtures import SubRequest + +from torchgeo.datamodules import DeepGlobeLandCoverDataModule + + +class TestDeepGlobeLandCoverDataModule: + @pytest.fixture(scope="class", params=[0.0, 0.5]) + def datamodule(self, request: SubRequest) -> DeepGlobeLandCoverDataModule: + root = os.path.join("tests", "data", "deepglobelandcover") + batch_size = 1 + num_workers = 0 + val_split_size = request.param + dm = DeepGlobeLandCoverDataModule( + root, batch_size, num_workers, val_split_pct=val_split_size + ) + dm.prepare_data() + dm.setup() + return dm + + def test_train_dataloader(self, datamodule: DeepGlobeLandCoverDataModule) -> None: + next(iter(datamodule.train_dataloader())) + + def test_val_dataloader(self, datamodule: DeepGlobeLandCoverDataModule) -> None: + next(iter(datamodule.val_dataloader())) + + def test_test_dataloader(self, datamodule: DeepGlobeLandCoverDataModule) -> None: + next(iter(datamodule.test_dataloader())) diff --git a/tests/datasets/test_deepglobelandcover.py b/tests/datasets/test_deepglobelandcover.py new file mode 100644 index 00000000000..3bde01de367 --- /dev/null +++ b/tests/datasets/test_deepglobelandcover.py @@ -0,0 +1,72 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. + +import os +import shutil +from pathlib import Path + +import matplotlib.pyplot as plt +import pytest +import torch +import torch.nn as nn +from _pytest.fixtures import SubRequest +from _pytest.monkeypatch import MonkeyPatch + +from torchgeo.datasets import DeepGlobeLandCover + + +class TestDeepGlobeLandCover: + @pytest.fixture(params=["train", "test"]) + def dataset( + self, monkeypatch: MonkeyPatch, request: SubRequest + ) -> DeepGlobeLandCover: + md5 = "f32684b0b2bf6f8d604cd359a399c061" + splits = ["train", "test"] + monkeypatch.setattr(DeepGlobeLandCover, "md5", md5) + monkeypatch.setattr(DeepGlobeLandCover, "splits", splits) + root = os.path.join("tests", "data", "deepglobelandcover") + split = request.param + transforms = nn.Identity() # type: ignore[no-untyped-call] + return DeepGlobeLandCover(root, split, transforms, checksum=True) + + def test_getitem(self, dataset: DeepGlobeLandCover) -> None: + x = dataset[0] + assert isinstance(x, dict) + assert isinstance(x["image"], torch.Tensor) + assert isinstance(x["mask"], torch.Tensor) + + def test_len(self, dataset: DeepGlobeLandCover) -> None: + assert len(dataset) == 2 + + def test_extract(self, tmp_path: Path) -> None: + root = os.path.join("tests", "data", "deepglobelandcover") + filename = "data.zip" + shutil.copyfile( + os.path.join(root, filename), os.path.join(str(tmp_path), filename) + ) + DeepGlobeLandCover(root=str(tmp_path)) + + def test_corrupted(self, tmp_path: Path) -> None: + with open(os.path.join(tmp_path, "data.zip"), "w") as f: + f.write("bad") + with pytest.raises(RuntimeError, match="Dataset found, but corrupted."): + DeepGlobeLandCover(root=str(tmp_path), checksum=True) + + def test_invalid_split(self) -> None: + with pytest.raises(AssertionError): + DeepGlobeLandCover(split="foo") + + def test_not_downloaded(self, tmp_path: Path) -> None: + with pytest.raises(RuntimeError, match=f"Dataset not found in `root={str(tmp_path)}`, either specify a different" + + " `root` directory or manually download the dataset to this directory."): + DeepGlobeLandCover(str(tmp_path)) + + def test_plot(self, dataset: DeepGlobeLandCover) -> None: + x = dataset[0].copy() + dataset.plot(x, suptitle="Test") + plt.close() + dataset.plot(x, show_titles=False) + plt.close() + x["prediction"] = x["mask"].clone() + dataset.plot(x) + plt.close() diff --git a/torchgeo/datamodules/deepglobelandcover.py b/torchgeo/datamodules/deepglobelandcover.py index a374735f2c1..1085d0ea31c 100644 --- a/torchgeo/datamodules/deepglobelandcover.py +++ b/torchgeo/datamodules/deepglobelandcover.py @@ -36,7 +36,7 @@ def __init__( num_workers: The number of workers to use in all created DataLoaders val_split_pct: What percentage of the dataset to use as a validation set """ - super().__init__() + super().__init__() # type: ignore[no-untyped-call] self.root_dir = root_dir self.batch_size = batch_size self.num_workers = num_workers diff --git a/torchgeo/datamodules/potsdam.py b/torchgeo/datamodules/potsdam.py index 6d5a7bb2784..776d999cb1e 100644 --- a/torchgeo/datamodules/potsdam.py +++ b/torchgeo/datamodules/potsdam.py @@ -37,7 +37,7 @@ def __init__( num_workers: The number of workers to use in all created DataLoaders val_split_pct: What percentage of the dataset to use as a validation set """ - super().__init__() + super().__init__() # type: ignore[no-untyped-call] self.root_dir = root_dir self.batch_size = batch_size self.num_workers = num_workers From 156af6cdf514d8b076fd116c589e3c96ce96df02 Mon Sep 17 00:00:00 2001 From: saumyasinha Date: Wed, 15 Jun 2022 16:35:35 -0700 Subject: [PATCH 06/35] fix a test case and a few more formatting error --- benchmark.py | 2 +- evaluate.py | 2 +- tests/data/deepglobelandcover/data.zip | Bin 5832 -> 6743 bytes .../data/test_data/images/10_sat.jpg | Bin 0 -> 643 bytes .../data/test_data/masks/10_mask.png | Bin 0 -> 79 bytes tests/datasets/test_deepglobelandcover.py | 10 +++++++--- 6 files changed, 9 insertions(+), 5 deletions(-) create mode 100644 tests/data/deepglobelandcover/data/test_data/images/10_sat.jpg create mode 100644 tests/data/deepglobelandcover/data/test_data/masks/10_mask.png diff --git a/benchmark.py b/benchmark.py index c2bfa58378f..5f8a3686a97 100755 --- a/benchmark.py +++ b/benchmark.py @@ -52,7 +52,7 @@ def set_up_parser() -> argparse.ArgumentParser: parser.add_argument( "-b", "--batch-size", - default=2 ** 4, + default=2**4, type=int, help="number of samples in each mini-batch", metavar="SIZE", diff --git a/evaluate.py b/evaluate.py index ad40a0eb90d..74dd72b915e 100755 --- a/evaluate.py +++ b/evaluate.py @@ -52,7 +52,7 @@ def set_up_parser() -> argparse.ArgumentParser: parser.add_argument( "-b", "--batch-size", - default=2 ** 4, + default=2**4, type=int, help="number of samples in each mini-batch", metavar="SIZE", diff --git a/tests/data/deepglobelandcover/data.zip b/tests/data/deepglobelandcover/data.zip index 44b87476ea0d188ac78cb3a8f926041fb7eb1bd6..444504e63cb48f621d80a1a91658f41e1f03f668 100644 GIT binary patch delta 788 zcmX@1d);J$4wG=|=XqY%fm+el&h#?{sKSH^LLXtAEXAtLB-Sw5 zomGczHmXC!fDVZ)e<0}wbg4fOV{u4sVsSRu9Uz8YK_0{*Aaht#Cl|7rsV@IxQP059 z*U-Vt!(&s_b4KTE=j28$37gozG1n|rO&A#hyqQ@hCkRPQUdE~gbQ4gM#bhqFRHk1b z=0s?KO%`XjhcSUcG`X1F0q*`v&KwB)FyrJ^+_`Y}9o{&E77vKgW|PnJfmDN>Ho2G| ztnnc~3nP<7!{p}z)=YO&KoK?hzA%>{Ml4JY5>yvN4sljch{M!Rd?dst0g6&ESkm~L zX>y`qGLs=Ikdl~uPf!;W#=Jr@OmXa!wSm-ZxK2;ZU`94*Ejt5x>|+UZpj!|oPEHe& zWAf#g+$NOF^oC>dYoTPu?#YEBVv|#aofvNbS+bLl3Oh0Ba7_*n7M=V-gnhEAh&NLl z51iWvC!8J?} S)8Z3m5N2=%dgG4}C~yGrdiNv% delta 461 zcmca^azb~44pW=mXWOvrF#XD$oW-ug_5-0hoWq8R(QcBE+2qq4=}iA^L98s!Xs8{N?{L~en9`HY zxEz?uZ6W4b^W-w+L+!}r%VjEqiq98_gD8(?Dh3*AK6$cWHd7&xwFpd_O}-^`j_G#h zT=;SYAPE4ZgK&H&(5OF7_ObBy}xHr>mPM~Ny(^+n?WSfLH(=T4ImJO0@ qlix`=G5PYrxxSJ^(PF6}rMnOeST|r4lSw=>~TvNxu(8R<c1}I=;VrF4wW9Q)H;sz?% zD!{d!pzFb!U9xX3zTPI5o8roG<0MW4oqZMDikqloVbuf*=gfJ(V&YTRE(2~ znmD<{#3dx9RMpfqG__1j&CD$#Lqp`PiIa0V?cZ@}EZS(Y{DZ#p|C<1&%+p5z literal 0 HcmV?d00001 diff --git a/tests/data/deepglobelandcover/data/test_data/masks/10_mask.png b/tests/data/deepglobelandcover/data/test_data/masks/10_mask.png new file mode 100644 index 0000000000000000000000000000000000000000..b4d8a4f120396734687f69e355f7a237ca5fc67f GIT binary patch literal 79 zcmeAS@N?(olHy`uVBq!ia0vp^Od!kwBL7~QRScxWJY5_^D&{1o{5XFA2#$b=0}Kp2 Xa*WI@&54tNDi}On{an^LB{Ts50)H06 literal 0 HcmV?d00001 diff --git a/tests/datasets/test_deepglobelandcover.py b/tests/datasets/test_deepglobelandcover.py index 3bde01de367..a0985a7eabf 100644 --- a/tests/datasets/test_deepglobelandcover.py +++ b/tests/datasets/test_deepglobelandcover.py @@ -36,7 +36,7 @@ def test_getitem(self, dataset: DeepGlobeLandCover) -> None: assert isinstance(x["mask"], torch.Tensor) def test_len(self, dataset: DeepGlobeLandCover) -> None: - assert len(dataset) == 2 + assert len(dataset) == 3 def test_extract(self, tmp_path: Path) -> None: root = os.path.join("tests", "data", "deepglobelandcover") @@ -57,8 +57,12 @@ def test_invalid_split(self) -> None: DeepGlobeLandCover(split="foo") def test_not_downloaded(self, tmp_path: Path) -> None: - with pytest.raises(RuntimeError, match=f"Dataset not found in `root={str(tmp_path)}`, either specify a different" - + " `root` directory or manually download the dataset to this directory."): + with pytest.raises( + RuntimeError, + match=f"Dataset not found in `root={str(tmp_path)}`, either" + + " specify a different `root` directory or manually download" + + " the dataset to this directory.", + ): DeepGlobeLandCover(str(tmp_path)) def test_plot(self, dataset: DeepGlobeLandCover) -> None: From 48bf64b0cebb5fc47a766e365da63d2b7b419a58 Mon Sep 17 00:00:00 2001 From: saumyasinha Date: Thu, 16 Jun 2022 11:25:36 -0700 Subject: [PATCH 07/35] add data.py and modify error match for data download --- tests/data/deepglobelandcover/data.py | 74 ++++++++++++++++++ tests/data/deepglobelandcover/data.zip | Bin 6743 -> 5748 bytes .../data/test_data/images/10_sat.jpg | Bin 643 -> 0 bytes .../data/test_data/images/8_sat.jpg | Bin 662 -> 0 bytes .../data/test_data/images/9_sat.jpg | Bin 653 -> 0 bytes .../data/test_data/masks/10_mask.png | Bin 79 -> 0 bytes .../data/test_data/masks/8_mask.png | Bin 79 -> 0 bytes .../data/test_data/masks/9_mask.png | Bin 79 -> 0 bytes .../data/training_data/images/1_sat.jpg | Bin 654 -> 0 bytes .../data/training_data/images/2_sat.jpg | Bin 654 -> 0 bytes .../data/training_data/images/3_sat.jpg | Bin 649 -> 0 bytes .../data/training_data/masks/1_mask.png | Bin 79 -> 0 bytes .../data/training_data/masks/2_mask.png | Bin 79 -> 0 bytes .../data/training_data/masks/3_mask.png | Bin 79 -> 0 bytes tests/datasets/test_deepglobelandcover.py | 4 +- torchgeo/datasets/deepglobelandcover.py | 2 +- 16 files changed, 77 insertions(+), 3 deletions(-) create mode 100644 tests/data/deepglobelandcover/data.py delete mode 100644 tests/data/deepglobelandcover/data/test_data/images/10_sat.jpg delete mode 100644 tests/data/deepglobelandcover/data/test_data/images/8_sat.jpg delete mode 100644 tests/data/deepglobelandcover/data/test_data/images/9_sat.jpg delete mode 100644 tests/data/deepglobelandcover/data/test_data/masks/10_mask.png delete mode 100644 tests/data/deepglobelandcover/data/test_data/masks/8_mask.png delete mode 100644 tests/data/deepglobelandcover/data/test_data/masks/9_mask.png delete mode 100644 tests/data/deepglobelandcover/data/training_data/images/1_sat.jpg delete mode 100644 tests/data/deepglobelandcover/data/training_data/images/2_sat.jpg delete mode 100644 tests/data/deepglobelandcover/data/training_data/images/3_sat.jpg delete mode 100644 tests/data/deepglobelandcover/data/training_data/masks/1_mask.png delete mode 100644 tests/data/deepglobelandcover/data/training_data/masks/2_mask.png delete mode 100644 tests/data/deepglobelandcover/data/training_data/masks/3_mask.png diff --git a/tests/data/deepglobelandcover/data.py b/tests/data/deepglobelandcover/data.py new file mode 100644 index 00000000000..f14c63be0a3 --- /dev/null +++ b/tests/data/deepglobelandcover/data.py @@ -0,0 +1,74 @@ +#!/usr/bin/env python3 + +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. + +import os +import shutil + +from PIL import Image +import numpy as np +from torchvision.datasets.utils import calculate_md5 + + +def generate_test_data(root: str, n_samples: int = 3) -> str: + """Creates test data archive for DeepGlobeLandCover dataset and + returns its md5 hash. + Args: + root (str): Path to store test data + n_samples (int, optional): Number of samples. + Returns: + str: md5 hash of created archive + """ + dtype = np.uint8 + size = 2 + + folder_path = os.path.join(root, "data") + + train_img_dir = os.path.join(folder_path, "data", "training_data", "images") + train_mask_dir = os.path.join(folder_path, "data", "training_data", "masks") + test_img_dir = os.path.join(folder_path, "data", "test_data", "images") + test_mask_dir = os.path.join(folder_path, "data", "test_data", "masks") + + if not os.path.exists(train_img_dir): + os.makedirs(train_img_dir) + if not os.path.exists(train_mask_dir): + os.makedirs(train_mask_dir) + if not os.path.exists(test_img_dir): + os.makedirs(test_img_dir) + if not os.path.exists(test_mask_dir): + os.makedirs(test_mask_dir) + + train_ids = [1, 2, 3] + test_ids = [8, 9, 10] + + for i in range(n_samples): + train_id = train_ids[i] + test_id = test_ids[i] + + dtype_max = np.iinfo(dtype).max + train_arr = np.random.randint(dtype_max, size=(size, size, 3), dtype=dtype) + train_img = Image.fromarray(train_arr) + train_img.save(os.path.join(train_img_dir, str(train_id) + "_sat.jpg")) + + test_arr = np.random.randint(dtype_max, size=(size, size, 3), dtype=dtype) + test_img = Image.fromarray(test_arr) + test_img.save(os.path.join(test_img_dir, str(test_id) + "_sat.jpg")) + + train_mask_arr = np.full((size, size, 3), (0, 255, 255), dtype=dtype) + train_mask_img = Image.fromarray(train_mask_arr) + train_mask_img.save(os.path.join(train_mask_dir, str(train_id) + "_mask.png")) + + test_mask_arr = np.full((size, size, 3), (255, 0, 255), dtype=dtype) + test_mask_img = Image.fromarray(test_mask_arr) + test_mask_img.save(os.path.join(test_mask_dir, str(test_id) + "_mask.png")) + + # Create archive + shutil.make_archive(folder_path, "zip", folder_path) + shutil.rmtree(folder_path) + return calculate_md5(f"{folder_path}.zip") + + +if __name__ == "__main__": + md5_hash = generate_test_data(os.getcwd(), 3) + print(md5_hash + "\n") diff --git a/tests/data/deepglobelandcover/data.zip b/tests/data/deepglobelandcover/data.zip index 444504e63cb48f621d80a1a91658f41e1f03f668..10c7bcbf308895d17139a46100772969444b4f0f 100644 GIT binary patch literal 5748 zcmWIWW@Zs#0D)_f7ec@cD8UM(QxZ!O^#gD!;fEMGcPkQosb4G zxCXfCnYoGSsl|9)B#NmgH?cSyp@jqN&xv}@>X#WA7$}h%Zho(aS1G z|6Tw1KQkMnzPZ0So0}UOo0~$)kNVjMXErwX_Rj5{+B|pe+{u%hyWLx+x6hvK9^^42 z-X+W{&M(Z%&CSu(Ki1LHJ<`qXa7^&=0~d}Qaf!Qo>Dr+aZs%_t;Yi_7R##W&H}7ZB zU*9ruQO_d5lMntgvN`gxsj;c0xv8?LIl84e9{cYu@ucxxN-7I8n?^!PQd(ka^798z z9eL~oDQj6z8E@d&#HA@^wTY8mZIiZWmxQTb%!!3>wtQTW zap5Sx)-g|4-#IZ!kAx-#t;%{OH7iPOS=uwPX<_H|*5$pEn-_Obabe;^!HIz`JT zS(W@aaWVP0{~Vjrm!GDtzP|4Mj>^{$7a#YZXIK62(bLua^X=+?{(AenfBt@le@Q6` zX)TOv{t2=C>h5f9o!Kh;MBi;$(F7((u`pL>GsWW$-;OvXsxEfp6I|ZOZ7%mD#EkEk z!mN;ziQYa(pDcXkKH>TSJLPl9z9~O>-Wj&+&olgBV9cc4A35RRyoarq+RjQgZq_rb zG_Cw5vb(FL_08iSs^?|@C11M!<-a*2ELB4iMD1TKn+w1M(Fsft@;DQO#b|mMvgzUU z!>8tV_k=uu7xg9asvBFIzER`4Mf3ai`u(dHW~bDe!Pjnax^gv*~H*` zGA8f)$vo-P`fEGql%Cgk^v!ANcB6Q)(oFfyet$On`0tCBB=(o5t#t>M3;sZ?fLT63 z>KI^s0b=MC7++V2?-CrektH&y5ys9hEeH%+{{p(B}Z&xWt_F1srSc74-NEoU`LgL4)?C+-Er}8*2ww7e# zl6aS*^Qvm=m;R&rPub7gOa0%^iIy1;n18=?3YaQd2&M|7(Nr;1Q^mswv+Zv`?suyB zZ9jiyz9?r;^pDo(7?s2GC!rfI0h2;E!K7e3niPg=Qb^o({C@gf&iD4w?(*Gl!e{QT zn09QD?dkG;R)01AVkC(V6PWJ8+6y@93}~Byw5oFXpC9)7H*VaxS&&6S@<{8<8DWL@ zrZcZf_)zk-IP&?F3oK}*6w&T58YJ#8roKBEnM9az4{-o1bRZC5cOGGh|8Q3rr(m?IHL83c^#^``ZZ9egX?oGzURVgZIAC4MXp* zAq-;!4q{<94BmS~Hw?X{k1$M<9m6na9!9kL@tFo{vctfV#(B6*Lp0!tH%y5Ghtm)( zafD&m8_^J#fs({BxM3*il8B@QYE&c4xrf~x?8ytgkqt9wNuwwy%x~D7V+gBJ5&nau zF!c5r!a!|qdYv=}|*YXGh&3N${2(RZPp+<^G zC~1qe?BP^)(&eOL7qL=OlIV7@U1;`wn}+x6`(~!I`xmF_G&BFq@Atgl^LwA)^E^wP zX!M~Nd`<8wckTVs_oju7#(YH*k<|)UZH%_jGTqxiobJ7K$1sdSe@?@&-nXS6eopWA zb3NtHCE{So+K)hXnt<$f;o~qO0tEz${KdhFz#jRk3~VGg2@`{O`Tr zCB?;s?GuE@?@mkBxE2h&J zlf8Vs{X}A)hMKxshDD`CUY@L|v{ZJZw4~$)^-!i(iR~}UoS{=jadWhXnCDD2+-v;R z68EB%mzUa3tg9%{v$(m?(fOFWckPIS%hK1s7Q%c8Tjy; zxasn%ueUXGB^^b#eF|NU&Dz@7emLX)h3YFio1UC1bV;85Lr-meM)dL7A)Q^Xx}%Th z>>?_3{g+obMSy@7fm`5h0BjQ)k6b+Y&?N8M!&mn=!s{&Rf}Bk=ZG}uKtEH#A&s*rLv-hG5N_UPQQ&l853jmY?u!0tXo?CIh*q3KbASJye&90?sV2!d58g`n!kZ+ z8vo(#{tKukO08<_ajLmKsG85Ct~}X!r|ha;l}&tVz~=OA>FyH4B*|0%=PMH3%o%USq-s7Uu%~NlZ-v2RsdaVQ&gjm>NXZ zBAQy0PHS*O{lQvqFRz+6uQzE^?<_VgrA&}}N>}Kl%4T_to@eoF;+c1LAsF+(u01pz zompG79h_iOPjkiiGBY!L+n1qAsc{nTVl{nTm^9&8jj z7}`@^V{7QCPJ-w6&@7?sE+~BmKO>Hu*UwJu0mW#8k8%G0iE$!m1#9v`SwrUR3JqP89J`a>^qPBOD8pr?L;Thy+URf% zQ|1Vi(qLU!6ZpBd0Jw(tC z{T#rCn=DdnRU0xTHio5!R;t8C_hp({h)Wifr5jZE-Y5L=vGkn)S-AibxN=c*6yi*d zl5n(CksuQ~Ab}G)DT%6CPDui_;yHvsqAWWA8qQy&(27(L=Q<@cOhu+DXxx;inT0r= zp)Af!6$e0PH9!JqH8n>e&R8hPOI0N3#05y;#6?P?YEn{?z*OwhR-UBa+ysE(+@uDW zI5nZbmE^$aor5zJDZV1n#0g4?4-;((PN%pHxWN1Hk$DOn1kO`xh=`3hO5~}djtFVP z0TFD&)esT;HIyhuR~-@3y#XTFy^#_ra!&MmB@xW|_2HyM$Q6X9LJF_Q4AJ+M@GvvO z_0_<05cdM-fL(wZBBFVtM3>YNp;iuvpp~m3B04Ziv}%N!6QO<#h)5ru76Uj0W&r*i LL4A4$;4ti8w`^)n diff --git a/tests/data/deepglobelandcover/data/test_data/images/10_sat.jpg b/tests/data/deepglobelandcover/data/test_data/images/10_sat.jpg deleted file mode 100644 index aa49336bff81e3a3d5129172a42d1e7322ba5c40..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 643 zcmex=^(PF6}rMnOeST|r4lSw=>~TvNxu(8R<c1}I=;VrF4wW9Q)H;sz?% zD!{d!pzFb!U9xX3zTPI5o8roG<0MW4oqZMDikqloVbuf*=gfJ(V&YTRE(2~ znmD<{#3dx9RMpfqG__1j&CD$#Lqp`PiIa0V?cZ@}EZS(Y{DZ#p|C<1&%+p5z diff --git a/tests/data/deepglobelandcover/data/test_data/images/8_sat.jpg b/tests/data/deepglobelandcover/data/test_data/images/8_sat.jpg deleted file mode 100644 index 6cdba83dd16e8b30db8290b3cc4bf23b7eb26967..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 662 zcmex=^(PF6}rMnOeST|r4lSw=>~TvNxu(8R<c1}I=;VrF4wW9Q)H;sz?% zD!{d!pzFb!U9xX3zTPI5o8roG<0MW4oqZMDikqloVbuf*=gfJ(V&YTRE(2~ znmD<{#3dx9RMpfqG__1j&CD$#!;2CL#a$oX%`7YwDfZW0;;*tvBdtt>Q)Ql~ S`kafdqK{5LN?%d`|0V#E*W1bf diff --git a/tests/data/deepglobelandcover/data/test_data/images/9_sat.jpg b/tests/data/deepglobelandcover/data/test_data/images/9_sat.jpg deleted file mode 100644 index 250b2509eca42f57a9f0de096c3772470b80cd73..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 653 zcmex=^(PF6}rMnOeST|r4lSw=>~TvNxu(8R<c1}I=;VrF4wW9Q)H;sz?% zD!{d!pzFb!U9xX3zTPI5o8roG<0MW4oqZMDikqloVbuf*=gfJ(V&YTRE(2~ znmD<{#3dx9RMpfqG__1j&CD$#!}Fw_b04~8E=kkkRP9u`=qftt#?K!2kIP^E JXE6SM695ew*^(PF6}rMnOeST|r4lSw=>~TvNxu(8R<c1}I=;VrF4wW9Q)H;sz?% zD!{d!pzFb!U9xX3zTPI5o8roG<0MW4oqZMDikqloVbuf*=gfJ(V&YTRE(2~ znmD<{#3dx9RMpfqG__1j&CD$#!{N($>65*;O!8cko)NIwSjbb$(j?Hey8Yhe KAL0xD-vj{DH`sRo diff --git a/tests/data/deepglobelandcover/data/training_data/images/2_sat.jpg b/tests/data/deepglobelandcover/data/training_data/images/2_sat.jpg deleted file mode 100644 index 3e62a87aa7225cb0438014c8cd39c0cee8c5a35d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 654 zcmex=^(PF6}rMnOeST|r4lSw=>~TvNxu(8R<c1}I=;VrF4wW9Q)H;sz?% zD!{d!pzFb!U9xX3zTPI5o8roG<0MW4oqZMDikqloVbuf*=gfJ(V&YTRE(2~ znmD<{#3dx9RMpfqG__1j&CD$#!+z7NM~Y8$+N@f2gq6>M*;Zpw*Uw-3k4#@} K`{Pah|C<2q*xK&^ diff --git a/tests/data/deepglobelandcover/data/training_data/images/3_sat.jpg b/tests/data/deepglobelandcover/data/training_data/images/3_sat.jpg deleted file mode 100644 index 5a5aa528ffb7408aeb671fe7b361968bed30c135..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 649 zcmex=^(PF6}rMnOeST|r4lSw=>~TvNxu(8R<c1}I=;VrF4wW9Q)H;sz?% zD!{d!pzFb!U9xX3zTPI5o8roG<0MW4oqZMDikqloVbuf*=gfJ(V&YTRE(2~ znmD<{#3dx9RMpfqG__1j&CD$#!@e`8j)qKNJizc}QJ41Fl^^#9-(CDiXsk;J|?+Kz!f; Z0|U1_BlC>b>2*LA44$rjF6*2Ung9T}7a9Nn diff --git a/tests/data/deepglobelandcover/data/training_data/masks/3_mask.png b/tests/data/deepglobelandcover/data/training_data/masks/3_mask.png deleted file mode 100644 index 5eb44ea35847270c9104ab81214a2d2b9a6a1a51..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 79 zcmeAS@N?(olHy`uVBq!ia0vp^Od!kwBL7~QRScxWJY5_^D&{2rIsajPV`F0{5H~h5 ZGDrw9F{ul;Sprosc)I$ztaD0e0szm!6n+2z diff --git a/tests/datasets/test_deepglobelandcover.py b/tests/datasets/test_deepglobelandcover.py index a0985a7eabf..ad3fa0dce86 100644 --- a/tests/datasets/test_deepglobelandcover.py +++ b/tests/datasets/test_deepglobelandcover.py @@ -20,7 +20,7 @@ class TestDeepGlobeLandCover: def dataset( self, monkeypatch: MonkeyPatch, request: SubRequest ) -> DeepGlobeLandCover: - md5 = "f32684b0b2bf6f8d604cd359a399c061" + md5 = "2cbd68d36b1485f09f32d874dde7c5c5" splits = ["train", "test"] monkeypatch.setattr(DeepGlobeLandCover, "md5", md5) monkeypatch.setattr(DeepGlobeLandCover, "splits", splits) @@ -59,7 +59,7 @@ def test_invalid_split(self) -> None: def test_not_downloaded(self, tmp_path: Path) -> None: with pytest.raises( RuntimeError, - match=f"Dataset not found in `root={str(tmp_path)}`, either" + match="Dataset not found in `root`, either" + " specify a different `root` directory or manually download" + " the dataset to this directory.", ): diff --git a/torchgeo/datasets/deepglobelandcover.py b/torchgeo/datasets/deepglobelandcover.py index 12c75797077..0266b818179 100644 --- a/torchgeo/datasets/deepglobelandcover.py +++ b/torchgeo/datasets/deepglobelandcover.py @@ -212,7 +212,7 @@ def _verify(self) -> None: # Check if the user requested to download the dataset raise RuntimeError( - f"Dataset not found in `root={self.root}`, either specify a different" + "Dataset not found in `root`, either specify a different" + " `root` directory or manually download the dataset to this directory." ) From 502d14e9231039d4f20ea79c4ff131ddfd1b26da Mon Sep 17 00:00:00 2001 From: saumyasinha Date: Thu, 16 Jun 2022 16:45:23 -0700 Subject: [PATCH 08/35] modify draw_semantic_segmentation_masks for cases when mask is a subset of all class labels --- torchgeo/datasets/utils.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/torchgeo/datasets/utils.py b/torchgeo/datasets/utils.py index 3981202d24a..b469c0167bd 100644 --- a/torchgeo/datasets/utils.py +++ b/torchgeo/datasets/utils.py @@ -642,8 +642,8 @@ def draw_semantic_segmentation_masks( a version of ``image`` overlayed with the colors given by ``mask`` and ``colors`` """ - classes = torch.unique(mask) - classes = classes[1:] + classes = torch.from_numpy(np.array(range(len(colors)))) # torch.unique(mask) + # classes = classes[1:] class_masks = mask == classes[:, None, None] img = draw_segmentation_masks( image=image, masks=class_masks, alpha=alpha, colors=colors From b0b95e5355a2c6dc7e99ac89eed0140981d298f3 Mon Sep 17 00:00:00 2001 From: saumyasinha Date: Fri, 17 Jun 2022 10:31:38 -0700 Subject: [PATCH 09/35] fix mypy error --- torchgeo/datasets/utils.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/torchgeo/datasets/utils.py b/torchgeo/datasets/utils.py index b469c0167bd..52d226d89ac 100644 --- a/torchgeo/datasets/utils.py +++ b/torchgeo/datasets/utils.py @@ -642,7 +642,8 @@ def draw_semantic_segmentation_masks( a version of ``image`` overlayed with the colors given by ``mask`` and ``colors`` """ - classes = torch.from_numpy(np.array(range(len(colors)))) # torch.unique(mask) + classes = torch.from_numpy(np.arange(len(colors) if colors else 0, dtype=np.uint8)) + # classes = torch.unique(mask) # classes = classes[1:] class_masks = mask == classes[:, None, None] img = draw_segmentation_masks( From 20d346df3b37675628bc2edbbfff31b780b56827 Mon Sep 17 00:00:00 2001 From: saumyasinha Date: Mon, 27 Jun 2022 12:15:25 -0700 Subject: [PATCH 10/35] add to docs for documentation --- docs/api/datamodules.rst | 5 +++++ docs/api/datasets.rst | 7 ++++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/docs/api/datamodules.rst b/docs/api/datamodules.rst index 4edeb0c37a9..760aa437523 100644 --- a/docs/api/datamodules.rst +++ b/docs/api/datamodules.rst @@ -29,6 +29,11 @@ COWC .. autoclass:: COWCCountingDataModule +Deep Globe Land Cover Challenge +^^^^^^^ + +.. autoclass:: DeepGlobeLandCoverDataModule + ETCI2021 Flood Detection ^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/docs/api/datasets.rst b/docs/api/datasets.rst index f5e171313c9..582d3cd255c 100644 --- a/docs/api/datasets.rst +++ b/docs/api/datasets.rst @@ -164,9 +164,14 @@ Kenya Crop Type .. autoclass:: CV4AKenyaCropType -DFC2022 +Deep Globe Land Cover Challenge ^^^^^^^ +.. autoclass:: DeepGlobeLandCover + +2022 IEEE GRSS Data Fusion Contest (DFC2022) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + .. autoclass:: DFC2022 ETCI2021 Flood Detection From 5165830676dd33c7c72267dc4d90a4bc36212992 Mon Sep 17 00:00:00 2001 From: saumyasinha Date: Mon, 27 Jun 2022 14:04:07 -0700 Subject: [PATCH 11/35] add deepglobe to the dataset lists csv --- docs/api/non_geo_datasets.csv | 67 ++++++++++++++++++----------------- 1 file changed, 34 insertions(+), 33 deletions(-) mode change 100644 => 100755 docs/api/non_geo_datasets.csv diff --git a/docs/api/non_geo_datasets.csv b/docs/api/non_geo_datasets.csv old mode 100644 new mode 100755 index 8e11d7a23b0..b35903e5037 --- a/docs/api/non_geo_datasets.csv +++ b/docs/api/non_geo_datasets.csv @@ -1,33 +1,34 @@ -Dataset,Task,Source,# Samples,# Classes,Size (px),Resolution (m),Bands -`ADVANCE`_,C,"Google Earth, Freesound","5,075",13,512x512,0.5,RGB -`Benin Cashew Plantations`_,S,Airbus Pléiades,70,6,"1,186x1,122",0.5,MSI -`BigEarthNet`_,C,Sentinel-1/2,"590,326",19--43,120x120,10,"SAR, MSI" -`COWC`_,"C, R","CSUAV AFRL, ISPRS, LINZ, AGRC","388,435",2,256x256,0.15,RGB -`Kenya Crop Type`_,S,Sentinel-2,"4,688",7,"3,035x2,016",10,MSI -`DFC2022`_,S,Aerial,,15,"2,000x2,000",0.5,RGB -`ETCI2021 Flood Detection`_,S,Sentinel-1,"66,810",2,256x256,5--20,SAR -`EuroSAT`_,C,Sentinel-2,"27,000",10,64x64,10,MSI -`FAIR1M`_,OD,Gaofen/Google Earth,"15,000",37,"1,024x1,024",0.3--0.8,RGB -`Forest Damage`_,OD,Drone imagery,"1,543",4,"1,500x1,500",,RGB -`GID-15`_,S,Gaofen-2,150,15,"6,800x7,200",3,RGB -`IDTReeS`_,"OD,C",Aerial,591,33,200x200,0.1--1,RGB -`Inria Aerial Image Labeling`_,S,Aerial,360,,"5,000x5,000",0.3,RGB -`LandCover.ai`_,S,Aerial,"10,674",5,512x512,0.25--0.5,RGB -`LEVIR-CD+`_,CD,Google Earth,985,2,"1,024x1,024",0.5,RGB -`LoveDA`_,S,Google Earth,"5,987",7,"1,024x1,024",0.3,RGB -`NASA Marine Debris`_,OD,PlanetScope,707,1,256x256,3,RGB -`NWPU VHR-10`_,I,"Google Earth, Vaihingen",800,10,"358--1,728",0.08--2,RGB -`OSCD`_,CD,Sentinel-2,24,2,"40--1,180",60,MSI -`PatternNet`_,C,Google Earth,"30,400",38,256x256,0.06--5,RGB -`Potsdam`_,S,Aerial,38,6,"6,000x6,000",0.05,MSI -`RESISC45`_,C,Google Earth,"31,500",45,256x256,0.2--30,RGB -`Seasonal Contrast`_,T,Sentinel-2,100K--1M,,264x264,10,MSI -`SEN12MS`_,S,"Sentinel-1/2, MODIS","180,662",33,256x256,10,"SAR, MSI" -`So2Sat`_,C,Sentinel-1/2,"400,673",17,32x32,10,"SAR, MSI" -`SpaceNet`_,I,WorldView-2/3 Planet Lab Dove,"1,889--28,728",2,102--900,0.5--4,MSI -`Tropical Cyclone`_,R,GOES 8--16,"108,110",,256x256,4K--8K,MSI -`UC Merced`_,C,USGS National Map,"21,000",21,256x256,0.3,RGB -`USAVars`_,S,NAIP Aerial,~100K,,,4,"RGB, NIR" -`Vaihingen`_,S,Aerial,33,6,"1,281--3,816",0.09,RGB -`xView2`_,CD,Maxar,"3,732",4,"1,024x1,024",0.8,RGB -`ZueriCrop`_,"I, T",Sentinel-2,116K,48,24x24,10,MSI +Dataset,Task,Source,# Samples,# Classes,Size (px),Resolution (m),Bands +`ADVANCE`_,C,"Google Earth, Freesound","5,075",13,512x512,0.5,RGB +`Benin Cashew Plantations`_,S,Airbus Pléiades,70,6,"1,186x1,122",0.5,MSI +`BigEarthNet`_,C,Sentinel-1/2,"590,326",19--43,120x120,10,"SAR, MSI" +`COWC`_,"C, R","CSUAV AFRL, ISPRS, LINZ, AGRC","388,435",2,256x256,0.15,RGB +`Kenya Crop Type`_,S,Sentinel-2,"4,688",7,"3,035x2,016",10,MSI +`Deep Globe Land Cover`_,S,DigitalGlobe +Vivid,803,7,2448x2448,0.5,RGB +`DFC2022`_,S,Aerial,,15,"2,000x2,000",0.5,RGB +`ETCI2021 Flood Detection`_,S,Sentinel-1,"66,810",2,256x256,5--20,SAR +`EuroSAT`_,C,Sentinel-2,"27,000",10,64x64,10,MSI +`FAIR1M`_,OD,Gaofen/Google Earth,"15,000",37,"1,024x1,024",0.3--0.8,RGB +`Forest Damage`_,OD,Drone imagery,"1,543",4,"1,500x1,500",,RGB +`GID-15`_,S,Gaofen-2,150,15,"6,800x7,200",3,RGB +`IDTReeS`_,"OD,C",Aerial,591,33,200x200,0.1--1,RGB +`Inria Aerial Image Labeling`_,S,Aerial,360,,"5,000x5,000",0.3,RGB +`LandCover.ai`_,S,Aerial,"10,674",5,512x512,0.25--0.5,RGB +`LEVIR-CD+`_,CD,Google Earth,985,2,"1,024x1,024",0.5,RGB +`LoveDA`_,S,Google Earth,"5,987",7,"1,024x1,024",0.3,RGB +`NASA Marine Debris`_,OD,PlanetScope,707,1,256x256,3,RGB +`NWPU VHR-10`_,I,"Google Earth, Vaihingen",800,10,"358--1,728",0.08--2,RGB +`OSCD`_,CD,Sentinel-2,24,2,"40--1,180",60,MSI +`PatternNet`_,C,Google Earth,"30,400",38,256x256,0.06--5,RGB +`Potsdam`_,S,Aerial,38,6,"6,000x6,000",0.05,MSI +`RESISC45`_,C,Google Earth,"31,500",45,256x256,0.2--30,RGB +`Seasonal Contrast`_,T,Sentinel-2,100K--1M,,264x264,10,MSI +`SEN12MS`_,S,"Sentinel-1/2, MODIS","180,662",33,256x256,10,"SAR, MSI" +`So2Sat`_,C,Sentinel-1/2,"400,673",17,32x32,10,"SAR, MSI" +`SpaceNet`_,I,WorldView-2/3 Planet Lab Dove,"1,889--28,728",2,102--900,0.5--4,MSI +`Tropical Cyclone`_,R,GOES 8--16,"108,110",,256x256,4K--8K,MSI +`UC Merced`_,C,USGS National Map,"21,000",21,256x256,0.3,RGB +`USAVars`_,S,NAIP Aerial,~100K,,,4,"RGB, NIR" +`Vaihingen`_,S,Aerial,33,6,"1,281--3,816",0.09,RGB +`xView2`_,CD,Maxar,"3,732",4,"1,024x1,024",0.8,RGB +`ZueriCrop`_,"I, T",Sentinel-2,116K,48,24x24,10,MSI From 68705d2942f3e11ecd62ef46fe6d7a898196cd23 Mon Sep 17 00:00:00 2001 From: saumyasinha Date: Mon, 27 Jun 2022 14:42:37 -0700 Subject: [PATCH 12/35] fix error in building docs --- docs/api/non_geo_datasets.csv | 2 +- tests/data/deepglobelandcover/data.py | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/docs/api/non_geo_datasets.csv b/docs/api/non_geo_datasets.csv index b35903e5037..ff03af1d3d7 100755 --- a/docs/api/non_geo_datasets.csv +++ b/docs/api/non_geo_datasets.csv @@ -4,7 +4,7 @@ Dataset,Task,Source,# Samples,# Classes,Size (px),Resolution (m),Bands `BigEarthNet`_,C,Sentinel-1/2,"590,326",19--43,120x120,10,"SAR, MSI" `COWC`_,"C, R","CSUAV AFRL, ISPRS, LINZ, AGRC","388,435",2,256x256,0.15,RGB `Kenya Crop Type`_,S,Sentinel-2,"4,688",7,"3,035x2,016",10,MSI -`Deep Globe Land Cover`_,S,DigitalGlobe +Vivid,803,7,2448x2448,0.5,RGB +`Deep Globe Land Cover Challenge`_,S,DigitalGlobe +Vivid,803,7,"2,448x2,448",0.5,RGB `DFC2022`_,S,Aerial,,15,"2,000x2,000",0.5,RGB `ETCI2021 Flood Detection`_,S,Sentinel-1,"66,810",2,256x256,5--20,SAR `EuroSAT`_,C,Sentinel-2,"27,000",10,64x64,10,MSI diff --git a/tests/data/deepglobelandcover/data.py b/tests/data/deepglobelandcover/data.py index f14c63be0a3..54c81b8cbaf 100644 --- a/tests/data/deepglobelandcover/data.py +++ b/tests/data/deepglobelandcover/data.py @@ -5,9 +5,8 @@ import os import shutil - -from PIL import Image import numpy as np +from PIL import Image from torchvision.datasets.utils import calculate_md5 From 1a3852d25b8d10409dceac2083b9980e8738492a Mon Sep 17 00:00:00 2001 From: Caleb Robinson Date: Mon, 27 Jun 2022 15:00:55 -0700 Subject: [PATCH 13/35] Update datamodules.rst --- docs/api/datamodules.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/api/datamodules.rst b/docs/api/datamodules.rst index 760aa437523..1ff0044c30b 100644 --- a/docs/api/datamodules.rst +++ b/docs/api/datamodules.rst @@ -30,7 +30,7 @@ COWC .. autoclass:: COWCCountingDataModule Deep Globe Land Cover Challenge -^^^^^^^ +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. autoclass:: DeepGlobeLandCoverDataModule From abb36519ba8d2786b4daa84708f5db62c1ea679c Mon Sep 17 00:00:00 2001 From: Caleb Robinson Date: Mon, 27 Jun 2022 15:02:09 -0700 Subject: [PATCH 14/35] Update datasets.rst --- docs/api/datasets.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/api/datasets.rst b/docs/api/datasets.rst index 582d3cd255c..41a4960e354 100644 --- a/docs/api/datasets.rst +++ b/docs/api/datasets.rst @@ -165,12 +165,12 @@ Kenya Crop Type .. autoclass:: CV4AKenyaCropType Deep Globe Land Cover Challenge -^^^^^^^ +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. autoclass:: DeepGlobeLandCover -2022 IEEE GRSS Data Fusion Contest (DFC2022) -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +DFC2022 +^^^^^^^ .. autoclass:: DFC2022 From 6bc68e61be70e56509b764f55e10f86f03b203da Mon Sep 17 00:00:00 2001 From: Caleb Robinson Date: Mon, 27 Jun 2022 15:04:07 -0700 Subject: [PATCH 15/35] Update data.py --- tests/data/deepglobelandcover/data.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/data/deepglobelandcover/data.py b/tests/data/deepglobelandcover/data.py index 54c81b8cbaf..9599d59395d 100644 --- a/tests/data/deepglobelandcover/data.py +++ b/tests/data/deepglobelandcover/data.py @@ -5,6 +5,7 @@ import os import shutil + import numpy as np from PIL import Image from torchvision.datasets.utils import calculate_md5 From 0b86e136e3518abf240b554ba56b7fe08b84d486 Mon Sep 17 00:00:00 2001 From: Caleb Robinson Date: Wed, 29 Jun 2022 13:17:36 -0700 Subject: [PATCH 16/35] Update utils.py --- torchgeo/datasets/utils.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/torchgeo/datasets/utils.py b/torchgeo/datasets/utils.py index 52d226d89ac..be7ffd0d48b 100644 --- a/torchgeo/datasets/utils.py +++ b/torchgeo/datasets/utils.py @@ -643,8 +643,6 @@ def draw_semantic_segmentation_masks( ``colors`` """ classes = torch.from_numpy(np.arange(len(colors) if colors else 0, dtype=np.uint8)) - # classes = torch.unique(mask) - # classes = classes[1:] class_masks = mask == classes[:, None, None] img = draw_segmentation_masks( image=image, masks=class_masks, alpha=alpha, colors=colors From d664ba9dcaaaae59458c28dd77891161b6f734d0 Mon Sep 17 00:00:00 2001 From: saumyasinha Date: Wed, 29 Jun 2022 16:28:43 -0700 Subject: [PATCH 17/35] change file permissions of non_geo_datasets.csv --- docs/api/non_geo_datasets.csv | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100755 => 100644 docs/api/non_geo_datasets.csv diff --git a/docs/api/non_geo_datasets.csv b/docs/api/non_geo_datasets.csv old mode 100755 new mode 100644 From 3989c3376d0f518e8ab17fb5e79a23934c73c1d6 Mon Sep 17 00:00:00 2001 From: Caleb Robinson Date: Sat, 2 Jul 2022 16:22:00 +0000 Subject: [PATCH 18/35] Add versionadded --- torchgeo/datasets/deepglobelandcover.py | 1 + 1 file changed, 1 insertion(+) diff --git a/torchgeo/datasets/deepglobelandcover.py b/torchgeo/datasets/deepglobelandcover.py index 0266b818179..5acb5e2f4d3 100644 --- a/torchgeo/datasets/deepglobelandcover.py +++ b/torchgeo/datasets/deepglobelandcover.py @@ -61,6 +61,7 @@ class DeepGlobeLandCover(VisionDataset): * https://arxiv.org/pdf/1805.06561.pdf + .. versionadded:: 0.3 """ filename = "data.zip" From 210d375fd0c6e90af5d92a758b5ae21055557e68 Mon Sep 17 00:00:00 2001 From: Caleb Robinson Date: Sat, 2 Jul 2022 09:22:58 -0700 Subject: [PATCH 19/35] Update torchgeo/datasets/deepglobelandcover.py Co-authored-by: Adam J. Stewart --- torchgeo/datasets/deepglobelandcover.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/torchgeo/datasets/deepglobelandcover.py b/torchgeo/datasets/deepglobelandcover.py index 5acb5e2f4d3..d3f0002a015 100644 --- a/torchgeo/datasets/deepglobelandcover.py +++ b/torchgeo/datasets/deepglobelandcover.py @@ -26,7 +26,7 @@ class DeepGlobeLandCover(VisionDataset): """DeepGlobe Land Cover Classification Challenge dataset. The `DeepGlobe Land Cover Classification Challenge - `__ dataset + `__ dataset offers high-resolution sub-meter satellite imagery focusing for the task of semantic segmentation to detect areas of urban, agriculture, rangeland, forest, water, barren, and unknown. It contains 1,146 satellite images of size From 073ea9a6055dd250727846e7599d3cb86215a18b Mon Sep 17 00:00:00 2001 From: Caleb Robinson Date: Sat, 2 Jul 2022 16:28:28 +0000 Subject: [PATCH 20/35] Change end of line sequence --- docs/api/non_geo_datasets.csv | 68 +++++++++++++++++------------------ 1 file changed, 34 insertions(+), 34 deletions(-) diff --git a/docs/api/non_geo_datasets.csv b/docs/api/non_geo_datasets.csv index ff03af1d3d7..7fca8bebec7 100644 --- a/docs/api/non_geo_datasets.csv +++ b/docs/api/non_geo_datasets.csv @@ -1,34 +1,34 @@ -Dataset,Task,Source,# Samples,# Classes,Size (px),Resolution (m),Bands -`ADVANCE`_,C,"Google Earth, Freesound","5,075",13,512x512,0.5,RGB -`Benin Cashew Plantations`_,S,Airbus Pléiades,70,6,"1,186x1,122",0.5,MSI -`BigEarthNet`_,C,Sentinel-1/2,"590,326",19--43,120x120,10,"SAR, MSI" -`COWC`_,"C, R","CSUAV AFRL, ISPRS, LINZ, AGRC","388,435",2,256x256,0.15,RGB -`Kenya Crop Type`_,S,Sentinel-2,"4,688",7,"3,035x2,016",10,MSI -`Deep Globe Land Cover Challenge`_,S,DigitalGlobe +Vivid,803,7,"2,448x2,448",0.5,RGB -`DFC2022`_,S,Aerial,,15,"2,000x2,000",0.5,RGB -`ETCI2021 Flood Detection`_,S,Sentinel-1,"66,810",2,256x256,5--20,SAR -`EuroSAT`_,C,Sentinel-2,"27,000",10,64x64,10,MSI -`FAIR1M`_,OD,Gaofen/Google Earth,"15,000",37,"1,024x1,024",0.3--0.8,RGB -`Forest Damage`_,OD,Drone imagery,"1,543",4,"1,500x1,500",,RGB -`GID-15`_,S,Gaofen-2,150,15,"6,800x7,200",3,RGB -`IDTReeS`_,"OD,C",Aerial,591,33,200x200,0.1--1,RGB -`Inria Aerial Image Labeling`_,S,Aerial,360,,"5,000x5,000",0.3,RGB -`LandCover.ai`_,S,Aerial,"10,674",5,512x512,0.25--0.5,RGB -`LEVIR-CD+`_,CD,Google Earth,985,2,"1,024x1,024",0.5,RGB -`LoveDA`_,S,Google Earth,"5,987",7,"1,024x1,024",0.3,RGB -`NASA Marine Debris`_,OD,PlanetScope,707,1,256x256,3,RGB -`NWPU VHR-10`_,I,"Google Earth, Vaihingen",800,10,"358--1,728",0.08--2,RGB -`OSCD`_,CD,Sentinel-2,24,2,"40--1,180",60,MSI -`PatternNet`_,C,Google Earth,"30,400",38,256x256,0.06--5,RGB -`Potsdam`_,S,Aerial,38,6,"6,000x6,000",0.05,MSI -`RESISC45`_,C,Google Earth,"31,500",45,256x256,0.2--30,RGB -`Seasonal Contrast`_,T,Sentinel-2,100K--1M,,264x264,10,MSI -`SEN12MS`_,S,"Sentinel-1/2, MODIS","180,662",33,256x256,10,"SAR, MSI" -`So2Sat`_,C,Sentinel-1/2,"400,673",17,32x32,10,"SAR, MSI" -`SpaceNet`_,I,WorldView-2/3 Planet Lab Dove,"1,889--28,728",2,102--900,0.5--4,MSI -`Tropical Cyclone`_,R,GOES 8--16,"108,110",,256x256,4K--8K,MSI -`UC Merced`_,C,USGS National Map,"21,000",21,256x256,0.3,RGB -`USAVars`_,S,NAIP Aerial,~100K,,,4,"RGB, NIR" -`Vaihingen`_,S,Aerial,33,6,"1,281--3,816",0.09,RGB -`xView2`_,CD,Maxar,"3,732",4,"1,024x1,024",0.8,RGB -`ZueriCrop`_,"I, T",Sentinel-2,116K,48,24x24,10,MSI +Dataset,Task,Source,# Samples,# Classes,Size (px),Resolution (m),Bands +`ADVANCE`_,C,"Google Earth, Freesound","5,075",13,512x512,0.5,RGB +`Benin Cashew Plantations`_,S,Airbus Pléiades,70,6,"1,186x1,122",0.5,MSI +`BigEarthNet`_,C,Sentinel-1/2,"590,326",19--43,120x120,10,"SAR, MSI" +`COWC`_,"C, R","CSUAV AFRL, ISPRS, LINZ, AGRC","388,435",2,256x256,0.15,RGB +`Kenya Crop Type`_,S,Sentinel-2,"4,688",7,"3,035x2,016",10,MSI +`Deep Globe Land Cover Challenge`_,S,DigitalGlobe +Vivid,803,7,"2,448x2,448",0.5,RGB +`DFC2022`_,S,Aerial,,15,"2,000x2,000",0.5,RGB +`ETCI2021 Flood Detection`_,S,Sentinel-1,"66,810",2,256x256,5--20,SAR +`EuroSAT`_,C,Sentinel-2,"27,000",10,64x64,10,MSI +`FAIR1M`_,OD,Gaofen/Google Earth,"15,000",37,"1,024x1,024",0.3--0.8,RGB +`Forest Damage`_,OD,Drone imagery,"1,543",4,"1,500x1,500",,RGB +`GID-15`_,S,Gaofen-2,150,15,"6,800x7,200",3,RGB +`IDTReeS`_,"OD,C",Aerial,591,33,200x200,0.1--1,RGB +`Inria Aerial Image Labeling`_,S,Aerial,360,,"5,000x5,000",0.3,RGB +`LandCover.ai`_,S,Aerial,"10,674",5,512x512,0.25--0.5,RGB +`LEVIR-CD+`_,CD,Google Earth,985,2,"1,024x1,024",0.5,RGB +`LoveDA`_,S,Google Earth,"5,987",7,"1,024x1,024",0.3,RGB +`NASA Marine Debris`_,OD,PlanetScope,707,1,256x256,3,RGB +`NWPU VHR-10`_,I,"Google Earth, Vaihingen",800,10,"358--1,728",0.08--2,RGB +`OSCD`_,CD,Sentinel-2,24,2,"40--1,180",60,MSI +`PatternNet`_,C,Google Earth,"30,400",38,256x256,0.06--5,RGB +`Potsdam`_,S,Aerial,38,6,"6,000x6,000",0.05,MSI +`RESISC45`_,C,Google Earth,"31,500",45,256x256,0.2--30,RGB +`Seasonal Contrast`_,T,Sentinel-2,100K--1M,,264x264,10,MSI +`SEN12MS`_,S,"Sentinel-1/2, MODIS","180,662",33,256x256,10,"SAR, MSI" +`So2Sat`_,C,Sentinel-1/2,"400,673",17,32x32,10,"SAR, MSI" +`SpaceNet`_,I,WorldView-2/3 Planet Lab Dove,"1,889--28,728",2,102--900,0.5--4,MSI +`Tropical Cyclone`_,R,GOES 8--16,"108,110",,256x256,4K--8K,MSI +`UC Merced`_,C,USGS National Map,"21,000",21,256x256,0.3,RGB +`USAVars`_,S,NAIP Aerial,~100K,,,4,"RGB, NIR" +`Vaihingen`_,S,Aerial,33,6,"1,281--3,816",0.09,RGB +`xView2`_,CD,Maxar,"3,732",4,"1,024x1,024",0.8,RGB +`ZueriCrop`_,"I, T",Sentinel-2,116K,48,24x24,10,MSI From 0dca2e1c7f9504e56b1cea03c22d2a09c3b07caa Mon Sep 17 00:00:00 2001 From: Caleb Robinson Date: Sat, 2 Jul 2022 09:29:09 -0700 Subject: [PATCH 21/35] Update tests/data/deepglobelandcover/data.py Co-authored-by: Adam J. Stewart --- tests/data/deepglobelandcover/data.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/tests/data/deepglobelandcover/data.py b/tests/data/deepglobelandcover/data.py index 9599d59395d..0f9674a6dd2 100644 --- a/tests/data/deepglobelandcover/data.py +++ b/tests/data/deepglobelandcover/data.py @@ -12,13 +12,14 @@ def generate_test_data(root: str, n_samples: int = 3) -> str: - """Creates test data archive for DeepGlobeLandCover dataset and - returns its md5 hash. + """Create test data archive for DeepGlobeLandCover dataset. + Args: - root (str): Path to store test data - n_samples (int, optional): Number of samples. + root: path to store test data + n_samples: number of samples. + Returns: - str: md5 hash of created archive + md5 hash of created archive """ dtype = np.uint8 size = 2 From ff6f2f6c993aef9aa3eb24094823da865e445ae6 Mon Sep 17 00:00:00 2001 From: Caleb Robinson Date: Sat, 2 Jul 2022 16:31:12 +0000 Subject: [PATCH 22/35] exist_ok --- tests/data/deepglobelandcover/data.py | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/tests/data/deepglobelandcover/data.py b/tests/data/deepglobelandcover/data.py index 0f9674a6dd2..071b3a536a6 100644 --- a/tests/data/deepglobelandcover/data.py +++ b/tests/data/deepglobelandcover/data.py @@ -31,14 +31,10 @@ def generate_test_data(root: str, n_samples: int = 3) -> str: test_img_dir = os.path.join(folder_path, "data", "test_data", "images") test_mask_dir = os.path.join(folder_path, "data", "test_data", "masks") - if not os.path.exists(train_img_dir): - os.makedirs(train_img_dir) - if not os.path.exists(train_mask_dir): - os.makedirs(train_mask_dir) - if not os.path.exists(test_img_dir): - os.makedirs(test_img_dir) - if not os.path.exists(test_mask_dir): - os.makedirs(test_mask_dir) + os.makedirs(train_img_dir, exist_ok=True) + os.makedirs(train_mask_dir, exist_ok=True) + os.makedirs(test_img_dir, exist_ok=True) + os.makedirs(test_mask_dir, exist_ok=True) train_ids = [1, 2, 3] test_ids = [8, 9, 10] From b1358b667d5d8d5d93492190ca815e45593c9351 Mon Sep 17 00:00:00 2001 From: Caleb Robinson Date: Sat, 2 Jul 2022 09:31:56 -0700 Subject: [PATCH 23/35] Update tests/datasets/test_deepglobelandcover.py Co-authored-by: Adam J. Stewart --- tests/datasets/test_deepglobelandcover.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/datasets/test_deepglobelandcover.py b/tests/datasets/test_deepglobelandcover.py index ad3fa0dce86..7f8100aba12 100644 --- a/tests/datasets/test_deepglobelandcover.py +++ b/tests/datasets/test_deepglobelandcover.py @@ -26,7 +26,7 @@ def dataset( monkeypatch.setattr(DeepGlobeLandCover, "splits", splits) root = os.path.join("tests", "data", "deepglobelandcover") split = request.param - transforms = nn.Identity() # type: ignore[no-untyped-call] + transforms = nn.Identity() return DeepGlobeLandCover(root, split, transforms, checksum=True) def test_getitem(self, dataset: DeepGlobeLandCover) -> None: From 21721cc73ca2b60916f1e1544dac77206e993c6c Mon Sep 17 00:00:00 2001 From: Caleb Robinson Date: Sat, 2 Jul 2022 16:37:49 +0000 Subject: [PATCH 24/35] Remove datamodule tests --- tests/conf/deepglobelandcover.yaml | 18 +++++++++++ tests/datamodules/test_deepglobelandcover.py | 33 -------------------- tests/trainers/test_segmentation.py | 2 ++ 3 files changed, 20 insertions(+), 33 deletions(-) create mode 100644 tests/conf/deepglobelandcover.yaml delete mode 100644 tests/datamodules/test_deepglobelandcover.py diff --git a/tests/conf/deepglobelandcover.yaml b/tests/conf/deepglobelandcover.yaml new file mode 100644 index 00000000000..0e76bdf8691 --- /dev/null +++ b/tests/conf/deepglobelandcover.yaml @@ -0,0 +1,18 @@ +experiment: + task: "deepglobelandcover" + module: + loss: "ce" + segmentation_model: "unet" + encoder_name: "resnet18" + encoder_weights: null + learning_rate: 1e-3 + learning_rate_schedule_patience: 6 + verbose: false + in_channels: 3 + num_classes: 7 + num_filters: 1 + ignore_zeros: False + datamodule: + root_dir: "tests/data/deepglobelandcover" + batch_size: 1 + num_workers: 0 diff --git a/tests/datamodules/test_deepglobelandcover.py b/tests/datamodules/test_deepglobelandcover.py deleted file mode 100644 index a923e881eeb..00000000000 --- a/tests/datamodules/test_deepglobelandcover.py +++ /dev/null @@ -1,33 +0,0 @@ -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. - -import os - -import pytest -from _pytest.fixtures import SubRequest - -from torchgeo.datamodules import DeepGlobeLandCoverDataModule - - -class TestDeepGlobeLandCoverDataModule: - @pytest.fixture(scope="class", params=[0.0, 0.5]) - def datamodule(self, request: SubRequest) -> DeepGlobeLandCoverDataModule: - root = os.path.join("tests", "data", "deepglobelandcover") - batch_size = 1 - num_workers = 0 - val_split_size = request.param - dm = DeepGlobeLandCoverDataModule( - root, batch_size, num_workers, val_split_pct=val_split_size - ) - dm.prepare_data() - dm.setup() - return dm - - def test_train_dataloader(self, datamodule: DeepGlobeLandCoverDataModule) -> None: - next(iter(datamodule.train_dataloader())) - - def test_val_dataloader(self, datamodule: DeepGlobeLandCoverDataModule) -> None: - next(iter(datamodule.val_dataloader())) - - def test_test_dataloader(self, datamodule: DeepGlobeLandCoverDataModule) -> None: - next(iter(datamodule.test_dataloader())) diff --git a/tests/trainers/test_segmentation.py b/tests/trainers/test_segmentation.py index bfd61291008..ba4772ce471 100644 --- a/tests/trainers/test_segmentation.py +++ b/tests/trainers/test_segmentation.py @@ -13,6 +13,7 @@ from torchgeo.datamodules import ( ChesapeakeCVPRDataModule, + DeepGlobeLandCoverDataModule, ETCI2021DataModule, InriaAerialImageLabelingDataModule, LandCoverAIDataModule, @@ -34,6 +35,7 @@ class TestSemanticSegmentationTask: "name,classname", [ ("chesapeake_cvpr_5", ChesapeakeCVPRDataModule), + ("deepglobelandcover", DeepGlobeLandCoverDataModule), ("etci2021", ETCI2021DataModule), ("inria", InriaAerialImageLabelingDataModule), ("landcoverai", LandCoverAIDataModule), From e65fba79eca95996654f5808928e11a5de702dbd Mon Sep 17 00:00:00 2001 From: Caleb Robinson Date: Sat, 2 Jul 2022 16:37:59 +0000 Subject: [PATCH 25/35] Remove split monkeypatch --- tests/datasets/test_deepglobelandcover.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/datasets/test_deepglobelandcover.py b/tests/datasets/test_deepglobelandcover.py index ad3fa0dce86..afc1f755052 100644 --- a/tests/datasets/test_deepglobelandcover.py +++ b/tests/datasets/test_deepglobelandcover.py @@ -21,9 +21,7 @@ def dataset( self, monkeypatch: MonkeyPatch, request: SubRequest ) -> DeepGlobeLandCover: md5 = "2cbd68d36b1485f09f32d874dde7c5c5" - splits = ["train", "test"] monkeypatch.setattr(DeepGlobeLandCover, "md5", md5) - monkeypatch.setattr(DeepGlobeLandCover, "splits", splits) root = os.path.join("tests", "data", "deepglobelandcover") split = request.param transforms = nn.Identity() # type: ignore[no-untyped-call] From 6aa6f32f8322f087bd4755ee16518ecc9505f7f2 Mon Sep 17 00:00:00 2001 From: Caleb Robinson Date: Sat, 2 Jul 2022 16:39:01 +0000 Subject: [PATCH 26/35] Running black --- tests/data/deepglobelandcover/data.py | 4 ++-- tests/datasets/test_deepglobelandcover.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/data/deepglobelandcover/data.py b/tests/data/deepglobelandcover/data.py index 071b3a536a6..1c8778bf8d4 100644 --- a/tests/data/deepglobelandcover/data.py +++ b/tests/data/deepglobelandcover/data.py @@ -13,11 +13,11 @@ def generate_test_data(root: str, n_samples: int = 3) -> str: """Create test data archive for DeepGlobeLandCover dataset. - + Args: root: path to store test data n_samples: number of samples. - + Returns: md5 hash of created archive """ diff --git a/tests/datasets/test_deepglobelandcover.py b/tests/datasets/test_deepglobelandcover.py index f0b781c09e7..e6f08bbf4e6 100644 --- a/tests/datasets/test_deepglobelandcover.py +++ b/tests/datasets/test_deepglobelandcover.py @@ -24,7 +24,7 @@ def dataset( monkeypatch.setattr(DeepGlobeLandCover, "md5", md5) root = os.path.join("tests", "data", "deepglobelandcover") split = request.param - transforms = nn.Identity() + transforms = nn.Identity() return DeepGlobeLandCover(root, split, transforms, checksum=True) def test_getitem(self, dataset: DeepGlobeLandCover) -> None: From 4d0212fe18f931a83bde89fa19951fd027e5b07e Mon Sep 17 00:00:00 2001 From: Caleb Robinson Date: Sat, 2 Jul 2022 16:56:19 +0000 Subject: [PATCH 27/35] Add val percent to test conf --- tests/conf/deepglobelandcover.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/conf/deepglobelandcover.yaml b/tests/conf/deepglobelandcover.yaml index 0e76bdf8691..cf3102fca35 100644 --- a/tests/conf/deepglobelandcover.yaml +++ b/tests/conf/deepglobelandcover.yaml @@ -14,5 +14,6 @@ experiment: ignore_zeros: False datamodule: root_dir: "tests/data/deepglobelandcover" + val_split_pct: 0.5 batch_size: 1 num_workers: 0 From 09d4a23730c938aa74fd8fee1b1483df8fe1488b Mon Sep 17 00:00:00 2001 From: Caleb Robinson Date: Sat, 2 Jul 2022 17:00:29 +0000 Subject: [PATCH 28/35] Sort filelist so indices are the same across platforms --- torchgeo/datasets/deepglobelandcover.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/torchgeo/datasets/deepglobelandcover.py b/torchgeo/datasets/deepglobelandcover.py index d3f0002a015..75745ac1ddc 100644 --- a/torchgeo/datasets/deepglobelandcover.py +++ b/torchgeo/datasets/deepglobelandcover.py @@ -116,9 +116,9 @@ def __init__( split_folder = "test_data" self.files = [] - for image in os.listdir( + for image in sorted(os.listdir( os.path.join(root, self.data_root, split_folder, "images") - ): + )): if image.endswith(".jpg"): id = image[:-8] image_path = os.path.join( From e49e006534b001a2bf1ee35e14ddbabf25d71a5b Mon Sep 17 00:00:00 2001 From: Caleb Robinson Date: Sat, 2 Jul 2022 17:15:16 +0000 Subject: [PATCH 29/35] Simplified the file and mask fns --- torchgeo/datasets/deepglobelandcover.py | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/torchgeo/datasets/deepglobelandcover.py b/torchgeo/datasets/deepglobelandcover.py index 75745ac1ddc..645bef5049c 100644 --- a/torchgeo/datasets/deepglobelandcover.py +++ b/torchgeo/datasets/deepglobelandcover.py @@ -115,10 +115,11 @@ def __init__( else: split_folder = "test_data" - self.files = [] - for image in sorted(os.listdir( - os.path.join(root, self.data_root, split_folder, "images") - )): + self.image_fns = [] + self.mask_fns = [] + for image in sorted( + os.listdir(os.path.join(root, self.data_root, split_folder, "images")) + ): if image.endswith(".jpg"): id = image[:-8] image_path = os.path.join( @@ -127,8 +128,9 @@ def __init__( mask_path = os.path.join( root, self.data_root, split_folder, "masks", str(id) + "_mask.png" ) - if os.path.exists(mask_path): - self.files.append(dict(image=image_path, mask=mask_path)) + + self.image_fns.append(image_path) + self.mask_fns.append(mask_path) def __getitem__(self, index: int) -> Dict[str, Tensor]: """Return an index within the dataset. @@ -154,7 +156,7 @@ def __len__(self) -> int: Returns: length of the dataset """ - return len(self.files) + return len(self.image_fns) def _load_image(self, index: int) -> Tensor: """Load a single image. @@ -165,7 +167,7 @@ def _load_image(self, index: int) -> Tensor: Returns: the image """ - path = self.files[index]["image"] + path = self.image_fns[index] with Image.open(path) as img: array: "np.typing.NDArray[np.int_]" = np.array(img) @@ -183,7 +185,7 @@ def _load_target(self, index: int) -> Tensor: Returns: the target mask """ - path = self.files[index]["mask"] + path = self.mask_fns[index] with Image.open(path) as img: array: "np.typing.NDArray[np.uint8]" = np.array(img) array = rgb_to_mask(array, self.colormap) From c63afd8e29bd4249ad961ed2891dfb97ce80eda2 Mon Sep 17 00:00:00 2001 From: Caleb Robinson Date: Sat, 2 Jul 2022 17:18:23 +0000 Subject: [PATCH 30/35] Re-adding datamodule tests for coverage --- tests/datamodules/test_deepglobelandcover.py | 33 ++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 tests/datamodules/test_deepglobelandcover.py diff --git a/tests/datamodules/test_deepglobelandcover.py b/tests/datamodules/test_deepglobelandcover.py new file mode 100644 index 00000000000..a923e881eeb --- /dev/null +++ b/tests/datamodules/test_deepglobelandcover.py @@ -0,0 +1,33 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. + +import os + +import pytest +from _pytest.fixtures import SubRequest + +from torchgeo.datamodules import DeepGlobeLandCoverDataModule + + +class TestDeepGlobeLandCoverDataModule: + @pytest.fixture(scope="class", params=[0.0, 0.5]) + def datamodule(self, request: SubRequest) -> DeepGlobeLandCoverDataModule: + root = os.path.join("tests", "data", "deepglobelandcover") + batch_size = 1 + num_workers = 0 + val_split_size = request.param + dm = DeepGlobeLandCoverDataModule( + root, batch_size, num_workers, val_split_pct=val_split_size + ) + dm.prepare_data() + dm.setup() + return dm + + def test_train_dataloader(self, datamodule: DeepGlobeLandCoverDataModule) -> None: + next(iter(datamodule.train_dataloader())) + + def test_val_dataloader(self, datamodule: DeepGlobeLandCoverDataModule) -> None: + next(iter(datamodule.val_dataloader())) + + def test_test_dataloader(self, datamodule: DeepGlobeLandCoverDataModule) -> None: + next(iter(datamodule.test_dataloader())) From 6b0a74b4dca1c2a23737f8f2c15109ca1424609c Mon Sep 17 00:00:00 2001 From: Caleb Robinson Date: Sat, 2 Jul 2022 17:55:36 +0000 Subject: [PATCH 31/35] Add sub-configs to test val_split_pct in the datamodule --- tests/conf/deepglobelandcover_0.yaml | 19 +++++++++++ ...ndcover.yaml => deepglobelandcover_5.yaml} | 0 tests/datamodules/test_deepglobelandcover.py | 33 ------------------- tests/trainers/test_segmentation.py | 3 +- 4 files changed, 21 insertions(+), 34 deletions(-) create mode 100644 tests/conf/deepglobelandcover_0.yaml rename tests/conf/{deepglobelandcover.yaml => deepglobelandcover_5.yaml} (100%) delete mode 100644 tests/datamodules/test_deepglobelandcover.py diff --git a/tests/conf/deepglobelandcover_0.yaml b/tests/conf/deepglobelandcover_0.yaml new file mode 100644 index 00000000000..6c79666027c --- /dev/null +++ b/tests/conf/deepglobelandcover_0.yaml @@ -0,0 +1,19 @@ +experiment: + task: "deepglobelandcover" + module: + loss: "ce" + segmentation_model: "unet" + encoder_name: "resnet18" + encoder_weights: null + learning_rate: 1e-3 + learning_rate_schedule_patience: 6 + verbose: false + in_channels: 3 + num_classes: 7 + num_filters: 1 + ignore_zeros: False + datamodule: + root_dir: "tests/data/deepglobelandcover" + val_split_pct: 0.0 + batch_size: 1 + num_workers: 0 diff --git a/tests/conf/deepglobelandcover.yaml b/tests/conf/deepglobelandcover_5.yaml similarity index 100% rename from tests/conf/deepglobelandcover.yaml rename to tests/conf/deepglobelandcover_5.yaml diff --git a/tests/datamodules/test_deepglobelandcover.py b/tests/datamodules/test_deepglobelandcover.py deleted file mode 100644 index a923e881eeb..00000000000 --- a/tests/datamodules/test_deepglobelandcover.py +++ /dev/null @@ -1,33 +0,0 @@ -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. - -import os - -import pytest -from _pytest.fixtures import SubRequest - -from torchgeo.datamodules import DeepGlobeLandCoverDataModule - - -class TestDeepGlobeLandCoverDataModule: - @pytest.fixture(scope="class", params=[0.0, 0.5]) - def datamodule(self, request: SubRequest) -> DeepGlobeLandCoverDataModule: - root = os.path.join("tests", "data", "deepglobelandcover") - batch_size = 1 - num_workers = 0 - val_split_size = request.param - dm = DeepGlobeLandCoverDataModule( - root, batch_size, num_workers, val_split_pct=val_split_size - ) - dm.prepare_data() - dm.setup() - return dm - - def test_train_dataloader(self, datamodule: DeepGlobeLandCoverDataModule) -> None: - next(iter(datamodule.train_dataloader())) - - def test_val_dataloader(self, datamodule: DeepGlobeLandCoverDataModule) -> None: - next(iter(datamodule.val_dataloader())) - - def test_test_dataloader(self, datamodule: DeepGlobeLandCoverDataModule) -> None: - next(iter(datamodule.test_dataloader())) diff --git a/tests/trainers/test_segmentation.py b/tests/trainers/test_segmentation.py index ba4772ce471..c399293345f 100644 --- a/tests/trainers/test_segmentation.py +++ b/tests/trainers/test_segmentation.py @@ -35,7 +35,8 @@ class TestSemanticSegmentationTask: "name,classname", [ ("chesapeake_cvpr_5", ChesapeakeCVPRDataModule), - ("deepglobelandcover", DeepGlobeLandCoverDataModule), + ("deepglobelandcover_0", DeepGlobeLandCoverDataModule), + ("deepglobelandcover_5", DeepGlobeLandCoverDataModule), ("etci2021", ETCI2021DataModule), ("inria", InriaAerialImageLabelingDataModule), ("landcoverai", LandCoverAIDataModule), From 3ccf788fb0679c363fc8cb1d703c68568b27a881 Mon Sep 17 00:00:00 2001 From: Caleb Robinson Date: Sat, 2 Jul 2022 17:58:28 +0000 Subject: [PATCH 32/35] Lets try it --- torchgeo/datamodules/deepglobelandcover.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/torchgeo/datamodules/deepglobelandcover.py b/torchgeo/datamodules/deepglobelandcover.py index 1085d0ea31c..632add64a92 100644 --- a/torchgeo/datamodules/deepglobelandcover.py +++ b/torchgeo/datamodules/deepglobelandcover.py @@ -82,7 +82,7 @@ def setup(self, stage: Optional[str] = None) -> None: self.root_dir, "test", transforms=transforms ) - def train_dataloader(self) -> DataLoader[Any]: + def train_dataloader(self) -> DataLoader[Dict[str, Any]]: """Return a DataLoader for training. Returns: @@ -95,7 +95,7 @@ def train_dataloader(self) -> DataLoader[Any]: shuffle=True, ) - def val_dataloader(self) -> DataLoader[Any]: + def val_dataloader(self) -> DataLoader[Dict[str, Any]]: """Return a DataLoader for validation. Returns: @@ -108,7 +108,7 @@ def val_dataloader(self) -> DataLoader[Any]: shuffle=False, ) - def test_dataloader(self) -> DataLoader[Any]: + def test_dataloader(self) -> DataLoader[Dict[str, Any]]: """Return a DataLoader for testing. Returns: From 015aa0fd32fe0f7a32e128b8a14973579e69bb4c Mon Sep 17 00:00:00 2001 From: Caleb Robinson Date: Sat, 2 Jul 2022 12:34:06 -0700 Subject: [PATCH 33/35] Update tests/conf/deepglobelandcover_0.yaml Co-authored-by: Adam J. Stewart --- tests/conf/deepglobelandcover_0.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/conf/deepglobelandcover_0.yaml b/tests/conf/deepglobelandcover_0.yaml index 6c79666027c..7a696c7615f 100644 --- a/tests/conf/deepglobelandcover_0.yaml +++ b/tests/conf/deepglobelandcover_0.yaml @@ -11,7 +11,7 @@ experiment: in_channels: 3 num_classes: 7 num_filters: 1 - ignore_zeros: False + ignore_index: null datamodule: root_dir: "tests/data/deepglobelandcover" val_split_pct: 0.0 From 314274330d948a0f81e1724fb2a1748ef8669fc6 Mon Sep 17 00:00:00 2001 From: Caleb Robinson Date: Sat, 2 Jul 2022 19:34:59 +0000 Subject: [PATCH 34/35] nulllllllll --- tests/conf/deepglobelandcover_5.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/conf/deepglobelandcover_5.yaml b/tests/conf/deepglobelandcover_5.yaml index cf3102fca35..32972d7a735 100644 --- a/tests/conf/deepglobelandcover_5.yaml +++ b/tests/conf/deepglobelandcover_5.yaml @@ -11,7 +11,7 @@ experiment: in_channels: 3 num_classes: 7 num_filters: 1 - ignore_zeros: False + ignore_zeros: null datamodule: root_dir: "tests/data/deepglobelandcover" val_split_pct: 0.5 From 7024047513b8d2192c4a4bab847522d72d4401c0 Mon Sep 17 00:00:00 2001 From: "Adam J. Stewart" Date: Sat, 2 Jul 2022 12:39:58 -0700 Subject: [PATCH 35/35] ingore_zeros -> ignore_index --- tests/conf/deepglobelandcover_5.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/conf/deepglobelandcover_5.yaml b/tests/conf/deepglobelandcover_5.yaml index 32972d7a735..18499deebec 100644 --- a/tests/conf/deepglobelandcover_5.yaml +++ b/tests/conf/deepglobelandcover_5.yaml @@ -11,7 +11,7 @@ experiment: in_channels: 3 num_classes: 7 num_filters: 1 - ignore_zeros: null + ignore_index: null datamodule: root_dir: "tests/data/deepglobelandcover" val_split_pct: 0.5