<kaggle_start><data_title>Danish Golf Courses Orthophotos<data_description>## Context:
This dataset contains 1123 orthophotos of Danish golf courses during spring with a scale of 1:1000 and a resolution of 1600x900 pixels. The orthophotos are captured from 107 different Danish golf courses, where each orthophoto captures a broad portion of the physical layout and features of the golf course. The images can contain between 1 to 4 golf holes each with some remaining parts of other converging holes.

### Content:
The data has been annotated to form the ground truth for semantic segmentation using CVAT.
The different classes annotated are:

- Background
- Fairway
- Green
- Tee
- Bunker
- Water

This dataset is divided into 3 folders:
1. Orthophotos: RGB images 
2. Segmentation masks: annotated images
3. Class masks: annotated images where each pixel value is between 0 to 5 depending on the class<data_name>danish-golf-courses-orthophotos
<code>import numpy as np  # linear algebra
import pandas as pd  # data processing, CSV file I/O (e.g. pd.read_csv)
import pytorch_lightning as pl
from torch.utils.data import random_split, DataLoader, Dataset
from torchvision.io import read_image
import torch
from torch import nn
from torchvision import transforms
import torchvision.transforms.functional as TF  # Used for transforms (resize)
import torch.nn.functional as F

# Input data files are available in the read-only "../input/" directory
# For example, running this (by clicking run or pressing Shift+Enter) will list all files under the input directory
IMAGES_DIR = "/kaggle/input/danish-golf-courses-orthophotos/1. orthophotos/"
MASKS_DIR = "/kaggle/input/danish-golf-courses-orthophotos/3. class masks/"
import os

# for dirname, _, filenames in os.walk('/kaggle/input'):
# for filename in filenames:
# pass
##print(os.path.join(dirname, filename))
# You can write up to 20GB to the current directory (/kaggle/working/) that gets preserved as output when you create a version using "Save & Run All"
# You can also write temporary files to /kaggle/temp/, but they won't be saved outside of the current session
# Hyperparameters
BATCH_SIZE = 1
IMAGE_SIZE = (256, 256)  # Images get resized to a smaller resolution
IN_CHANNELS = 3  # There are 3 channels for RGB


# A Dataset class is created to load
class GolfDataset(Dataset):
    def __init__(self, images_dir, masks_dir):
        self.images_dir = images_dir
        self.masks_dir = masks_dir
        self.images_dir_list = os.listdir(images_dir)

    def __len__(self):
        return len(self.images_dir_list)

    def __getitem__(self, idx):
        image_path = os.path.join(self.images_dir, self.images_dir_list[idx])
        image = read_image(image_path)
        image = image.float()
        mask_path = os.path.join(self.masks_dir, self.images_dir_list[idx])
        mask = read_image(image_path)
        # Apply transformations to the images
        image = TF.resize(image, IMAGE_SIZE)  # Apply resize transform
        mask = TF.resize(mask, IMAGE_SIZE)  # Apply resize transform
        mask = TF.rgb_to_grayscale(mask)  # Apply grayscaling to go from 3->1 channels.
        mask = mask.float()
        return image, mask


gds = GolfDataset(IMAGES_DIR, MASKS_DIR)
print(gds.__getitem__(0)[1])


class GolfDataModule(pl.LightningDataModule):
    def __init__(self, batch_size):
        super().__init__()
        self.batch_size = batch_size
        self.all_images = []

    def prepare_data(self):
        # We don't use this function for loading the data as
        # WARNING
        # prepare_data is called from a single GPU. Do not use it to assign state (self.x = y).
        pass

    def setup(self, stage=None):
        # Data is loaded from the image and mask directories
        self.all_images = GolfDataset(IMAGES_DIR, MASKS_DIR)
        # The data is split into train, val and test with a 70/20/10 split
        self.train_data, self.val_data, self.test_data = random_split(
            self.all_images, [0.7, 0.2, 0.1]
        )

    def train_dataloader(self):
        return DataLoader(self.train_data, batch_size=self.batch_size)

    def val_dataloader(self):
        return DataLoader(self.val_data, batch_size=self.batch_size)

    def test_dataloader(self):
        return DataLoader(self.test_data, batch_size=self.batch_size)


module = GolfDataModule(BATCH_SIZE)
print(module)


# Visualize the data in the golf dataset.
# A random orthophoto is shown along with its mask.
class UNetModel(pl.LightningModule):
    def __init__(self):
        super().__init__()

        def double_conv(in_channels, out_channels):
            return nn.Sequential(
                nn.Conv2d(in_channels, out_channels, kernel_size=3, padding=1),
                nn.ReLU(),
                nn.Conv2d(out_channels, out_channels, kernel_size=3, padding=1),
                nn.ReLU(),
            )

        def down(in_channels, out_channels):
            return nn.Sequential(
                nn.MaxPool2d(kernel_size=2), double_conv(in_channels, out_channels)
            )

        def up(in_channels, out_channels):
            print("up in out", in_channels, " ", out_channels)
            return nn.Sequential(
                nn.ConvTranspose2d(in_channels, out_channels, kernel_size=2, stride=2),
                double_conv(in_channels, out_channels),
            )

        # The encoder part of UNet
        self.l1 = double_conv(3, 64)
        self.l2 = down(64, 128)
        self.l3 = down(128, 256)
        self.l4 = down(256, 512)
        self.l5 = down(512, 1024)
        # The decoder part of UNet
        # self.l6 = up(1024, 512)
        # self.l7 = up(512, 256)
        # self.l8 = up(256, 128)
        # self.l9 = up(128, 64)
        # self.l10 = double_conv(64, 64)
        # Final (1x1) convolution to go from 64 -> 6 channels as we have 6 classes
        self.final = nn.Conv2d(1024, 6, kernel_size=1)
        self.loss_fn = nn.CrossEntropyLoss()
        self.softmax = nn.Softmax2d()

    def forward(self, x):
        x1 = self.l1(x)
        print("shape of x1", x1.shape)
        x2 = self.l2(x1)
        print("shape of x2", x2.shape)
        x3 = self.l3(x2)
        print("shape of x3", x3.shape)
        x4 = self.l4(x3)
        print("shape of x4", x4.shape)
        x5 = self.l5(x4)
        print("shape of x5", x5.shape)
        # x6 = self.l6(x5)
        # print("shape of x6", x6.shape)
        # x7 = self.l7(x6)
        # print("shape of x7", x7.shape)
        # x8 = self.l8(x7)
        # print("shape of x8", x8.shape)
        # x9 = self.l9(x8)
        # print("shape of x9", x9.shape)
        # x10 = self.l10(x9)
        # print("shape of x10", x10.shape)
        return self.final(x5)

    def training_step(self, batch, batch_idx):
        x, y = batch
        x = x.float()
        y = y.float()
        y_pred = self.forward(x)
        y_pred = torch.argmax(y_pred, dim=1)
        # print("bru", y_pred.shape)
        print(y)
        print(y_pred)
        loss = self.loss_fn(y_pred, y)
        return loss

    def validation_step(self, batch, batch_idx):
        pass

    def validation_epoch_end(self, validation_step_outputs):
        pass

    def configure_optimizers(self):
        return torch.optim.AdamW(self.parameters(), lr=0.001)


train_loader = GolfDataModule(BATCH_SIZE)
trainer = pl.Trainer(max_epochs=2, accelerator="gpu", devices=1)
model = UNetModel()
trainer.fit(model, train_loader)
<|endoftext|>
[{"Id": 121679071, "ScriptId": 35882420, "ParentScriptVersionId": NaN, "ScriptLanguageId": 9, "AuthorUserId": 12923738, "CreationDate": "03/10/2023 14:10:30", "VersionNumber": 1.0, "Title": "HEJsa eftggfs", "EvaluationDate": "03/10/2023", "IsChange": true, "TotalLines": 202.0, "LinesInsertedFromPrevious": 202.0, "LinesChangedFromPrevious": 0.0, "LinesUnchangedFromPrevious": 0.0, "LinesInsertedFromFork": NaN, "LinesDeletedFromFork": NaN, "LinesChangedFromFork": NaN, "LinesUnchangedFromFork": NaN, "TotalVotes": 0}]
[{"Id": 174059423, "KernelVersionId": 121679071, "SourceDatasetVersionId": 4727518}]
[{"Id": 4727518, "DatasetId": 2735624, "DatasourceVersionId": 4790362, "CreatorUserId": 6407631, "LicenseName": "Database: Open Database, Contents: \u00a9 Original Authors", "CreationDate": "12/15/2022 13:54:25", "VersionNumber": 1.0, "Title": "Danish Golf Courses Orthophotos", "Slug": "danish-golf-courses-orthophotos", "Subtitle": "1123 orthophotos of Danish golf courses", "Description": "## Context:\nThis dataset contains 1123 orthophotos of Danish golf courses during spring with a scale of 1:1000 and a resolution of 1600x900 pixels. The orthophotos are captured from 107 different Danish golf courses, where each orthophoto captures a broad portion of the physical layout and features of the golf course. The images can contain between 1 to 4 golf holes each with some remaining parts of other converging holes.\n\n### Content:\nThe data has been annotated to form the ground truth for semantic segmentation using CVAT.\nThe different classes annotated are:\n\n- Background\n- Fairway\n- Green\n- Tee\n- Bunker\n- Water\n\nThis dataset is divided into 3 folders:\n1. Orthophotos: RGB images \n2. Segmentation masks: annotated images\n3. Class masks: annotated images where each pixel value is between 0 to 5 depending on the class\n\n### Acknowledgements:\nThis data was collected from the Danish national database \u201dDataforsyningen\".", "VersionNotes": "Initial release", "TotalCompressedBytes": 0.0, "TotalUncompressedBytes": 0.0}]
[{"Id": 2735624, "CreatorUserId": 6407631, "OwnerUserId": 6407631.0, "OwnerOrganizationId": NaN, "CurrentDatasetVersionId": 4727518.0, "CurrentDatasourceVersionId": 4790362.0, "ForumId": 2768924, "Type": 2, "CreationDate": "12/15/2022 13:54:25", "LastActivityDate": "12/15/2022", "TotalViews": 1667, "TotalDownloads": 79, "TotalVotes": 23, "TotalKernels": 2}]
import numpy as np  # linear algebra
import pandas as pd  # data processing, CSV file I/O (e.g. pd.read_csv)
import pytorch_lightning as pl
from torch.utils.data import random_split, DataLoader, Dataset
from torchvision.io import read_image
import torch
from torch import nn
from torchvision import transforms
import torchvision.transforms.functional as TF  # Used for transforms (resize)
import torch.nn.functional as F

# Input data files are available in the read-only "../input/" directory
# For example, running this (by clicking run or pressing Shift+Enter) will list all files under the input directory
IMAGES_DIR = "/kaggle/input/danish-golf-courses-orthophotos/1. orthophotos/"
MASKS_DIR = "/kaggle/input/danish-golf-courses-orthophotos/3. class masks/"
import os

# for dirname, _, filenames in os.walk('/kaggle/input'):
# for filename in filenames:
# pass
##print(os.path.join(dirname, filename))
# You can write up to 20GB to the current directory (/kaggle/working/) that gets preserved as output when you create a version using "Save & Run All"
# You can also write temporary files to /kaggle/temp/, but they won't be saved outside of the current session
# Hyperparameters
BATCH_SIZE = 1
IMAGE_SIZE = (256, 256)  # Images get resized to a smaller resolution
IN_CHANNELS = 3  # There are 3 channels for RGB


# A Dataset class is created to load
class GolfDataset(Dataset):
    def __init__(self, images_dir, masks_dir):
        self.images_dir = images_dir
        self.masks_dir = masks_dir
        self.images_dir_list = os.listdir(images_dir)

    def __len__(self):
        return len(self.images_dir_list)

    def __getitem__(self, idx):
        image_path = os.path.join(self.images_dir, self.images_dir_list[idx])
        image = read_image(image_path)
        image = image.float()
        mask_path = os.path.join(self.masks_dir, self.images_dir_list[idx])
        mask = read_image(image_path)
        # Apply transformations to the images
        image = TF.resize(image, IMAGE_SIZE)  # Apply resize transform
        mask = TF.resize(mask, IMAGE_SIZE)  # Apply resize transform
        mask = TF.rgb_to_grayscale(mask)  # Apply grayscaling to go from 3->1 channels.
        mask = mask.float()
        return image, mask


gds = GolfDataset(IMAGES_DIR, MASKS_DIR)
print(gds.__getitem__(0)[1])


class GolfDataModule(pl.LightningDataModule):
    def __init__(self, batch_size):
        super().__init__()
        self.batch_size = batch_size
        self.all_images = []

    def prepare_data(self):
        # We don't use this function for loading the data as
        # WARNING
        # prepare_data is called from a single GPU. Do not use it to assign state (self.x = y).
        pass

    def setup(self, stage=None):
        # Data is loaded from the image and mask directories
        self.all_images = GolfDataset(IMAGES_DIR, MASKS_DIR)
        # The data is split into train, val and test with a 70/20/10 split
        self.train_data, self.val_data, self.test_data = random_split(
            self.all_images, [0.7, 0.2, 0.1]
        )

    def train_dataloader(self):
        return DataLoader(self.train_data, batch_size=self.batch_size)

    def val_dataloader(self):
        return DataLoader(self.val_data, batch_size=self.batch_size)

    def test_dataloader(self):
        return DataLoader(self.test_data, batch_size=self.batch_size)


module = GolfDataModule(BATCH_SIZE)
print(module)


# Visualize the data in the golf dataset.
# A random orthophoto is shown along with its mask.
class UNetModel(pl.LightningModule):
    def __init__(self):
        super().__init__()

        def double_conv(in_channels, out_channels):
            return nn.Sequential(
                nn.Conv2d(in_channels, out_channels, kernel_size=3, padding=1),
                nn.ReLU(),
                nn.Conv2d(out_channels, out_channels, kernel_size=3, padding=1),
                nn.ReLU(),
            )

        def down(in_channels, out_channels):
            return nn.Sequential(
                nn.MaxPool2d(kernel_size=2), double_conv(in_channels, out_channels)
            )

        def up(in_channels, out_channels):
            print("up in out", in_channels, " ", out_channels)
            return nn.Sequential(
                nn.ConvTranspose2d(in_channels, out_channels, kernel_size=2, stride=2),
                double_conv(in_channels, out_channels),
            )

        # The encoder part of UNet
        self.l1 = double_conv(3, 64)
        self.l2 = down(64, 128)
        self.l3 = down(128, 256)
        self.l4 = down(256, 512)
        self.l5 = down(512, 1024)
        # The decoder part of UNet
        # self.l6 = up(1024, 512)
        # self.l7 = up(512, 256)
        # self.l8 = up(256, 128)
        # self.l9 = up(128, 64)
        # self.l10 = double_conv(64, 64)
        # Final (1x1) convolution to go from 64 -> 6 channels as we have 6 classes
        self.final = nn.Conv2d(1024, 6, kernel_size=1)
        self.loss_fn = nn.CrossEntropyLoss()
        self.softmax = nn.Softmax2d()

    def forward(self, x):
        x1 = self.l1(x)
        print("shape of x1", x1.shape)
        x2 = self.l2(x1)
        print("shape of x2", x2.shape)
        x3 = self.l3(x2)
        print("shape of x3", x3.shape)
        x4 = self.l4(x3)
        print("shape of x4", x4.shape)
        x5 = self.l5(x4)
        print("shape of x5", x5.shape)
        # x6 = self.l6(x5)
        # print("shape of x6", x6.shape)
        # x7 = self.l7(x6)
        # print("shape of x7", x7.shape)
        # x8 = self.l8(x7)
        # print("shape of x8", x8.shape)
        # x9 = self.l9(x8)
        # print("shape of x9", x9.shape)
        # x10 = self.l10(x9)
        # print("shape of x10", x10.shape)
        return self.final(x5)

    def training_step(self, batch, batch_idx):
        x, y = batch
        x = x.float()
        y = y.float()
        y_pred = self.forward(x)
        y_pred = torch.argmax(y_pred, dim=1)
        # print("bru", y_pred.shape)
        print(y)
        print(y_pred)
        loss = self.loss_fn(y_pred, y)
        return loss

    def validation_step(self, batch, batch_idx):
        pass

    def validation_epoch_end(self, validation_step_outputs):
        pass

    def configure_optimizers(self):
        return torch.optim.AdamW(self.parameters(), lr=0.001)


train_loader = GolfDataModule(BATCH_SIZE)
trainer = pl.Trainer(max_epochs=2, accelerator="gpu", devices=1)
model = UNetModel()
trainer.fit(model, train_loader)
