Loading

Tree Segmentation

[Getting Started Notebook] Trees Segmentation

A Getting Started notebook for Trees Segmentation Puzzle of BlitzX.

Shubhamaicrowd

Starter Code for Trees Segmentation

What we are going to Learn

  • Getting started Image Segmentation using PyTorch.
  • Using models provided by segmentation_models.pytorch for the image segmentation.
  • Training & Testing a Unet model with PyTorch

Note : Create a copy of the notebook and use the copy for submission. Go to File > Save a Copy in Drive to create a new copy

Setting up Environment

Downloading Dataset

So we will first need to download the python library by AIcrowd that will allow us to download the dataset by just inputting the API key.

In [ ]:
!pip install aicrowd-cli

%load_ext aicrowd.magic
Collecting aicrowd-cli
  Downloading https://files.pythonhosted.org/packages/1f/57/59b5a00c6e90c9cc028b3da9dff90e242ad2847e735b1a0e81a21c616e27/aicrowd_cli-0.1.7-py3-none-any.whl (49kB)
     |████████████████████████████████| 51kB 7.6MB/s 
Collecting rich<11,>=10.0.0
  Downloading https://files.pythonhosted.org/packages/0a/9a/1ba0f7c34afd08c7a720834f60c79331e9e6c73c97fdc4054b5733462f35/rich-10.6.0-py3-none-any.whl (208kB)
     |████████████████████████████████| 215kB 35.8MB/s 
Collecting tqdm<5,>=4.56.0
  Downloading https://files.pythonhosted.org/packages/7a/ec/f8ff3ccfc4e59ce619a66a0bf29dc3b49c2e8c07de29d572e191c006eaa2/tqdm-4.61.2-py2.py3-none-any.whl (76kB)
     |████████████████████████████████| 81kB 12.2MB/s 
Requirement already satisfied: toml<1,>=0.10.2 in /usr/local/lib/python3.7/dist-packages (from aicrowd-cli) (0.10.2)
Collecting gitpython<4,>=3.1.12
  Downloading https://files.pythonhosted.org/packages/bc/91/b38c4fabb6e5092ab23492ded4f318ab7299b19263272b703478038c0fbc/GitPython-3.1.18-py3-none-any.whl (170kB)
     |████████████████████████████████| 174kB 46.7MB/s 
Collecting requests<3,>=2.25.1
  Downloading https://files.pythonhosted.org/packages/92/96/144f70b972a9c0eabbd4391ef93ccd49d0f2747f4f6a2a2738e99e5adc65/requests-2.26.0-py2.py3-none-any.whl (62kB)
     |████████████████████████████████| 71kB 11.9MB/s 
Requirement already satisfied: click<8,>=7.1.2 in /usr/local/lib/python3.7/dist-packages (from aicrowd-cli) (7.1.2)
Collecting requests-toolbelt<1,>=0.9.1
  Downloading https://files.pythonhosted.org/packages/60/ef/7681134338fc097acef8d9b2f8abe0458e4d87559c689a8c306d0957ece5/requests_toolbelt-0.9.1-py2.py3-none-any.whl (54kB)
     |████████████████████████████████| 61kB 11.0MB/s 
Requirement already satisfied: typing-extensions<4.0.0,>=3.7.4; python_version < "3.8" in /usr/local/lib/python3.7/dist-packages (from rich<11,>=10.0.0->aicrowd-cli) (3.7.4.3)
Requirement already satisfied: pygments<3.0.0,>=2.6.0 in /usr/local/lib/python3.7/dist-packages (from rich<11,>=10.0.0->aicrowd-cli) (2.6.1)
Collecting commonmark<0.10.0,>=0.9.0
  Downloading https://files.pythonhosted.org/packages/b1/92/dfd892312d822f36c55366118b95d914e5f16de11044a27cf10a7d71bbbf/commonmark-0.9.1-py2.py3-none-any.whl (51kB)
     |████████████████████████████████| 51kB 9.0MB/s 
Collecting colorama<0.5.0,>=0.4.0
  Downloading https://files.pythonhosted.org/packages/44/98/5b86278fbbf250d239ae0ecb724f8572af1c91f4a11edf4d36a206189440/colorama-0.4.4-py2.py3-none-any.whl
Collecting gitdb<5,>=4.0.1
  Downloading https://files.pythonhosted.org/packages/ea/e8/f414d1a4f0bbc668ed441f74f44c116d9816833a48bf81d22b697090dba8/gitdb-4.0.7-py3-none-any.whl (63kB)
     |████████████████████████████████| 71kB 11.9MB/s 
Requirement already satisfied: certifi>=2017.4.17 in /usr/local/lib/python3.7/dist-packages (from requests<3,>=2.25.1->aicrowd-cli) (2021.5.30)
Requirement already satisfied: charset-normalizer~=2.0.0; python_version >= "3" in /usr/local/lib/python3.7/dist-packages (from requests<3,>=2.25.1->aicrowd-cli) (2.0.2)
Requirement already satisfied: idna<4,>=2.5; python_version >= "3" in /usr/local/lib/python3.7/dist-packages (from requests<3,>=2.25.1->aicrowd-cli) (2.10)
Requirement already satisfied: urllib3<1.27,>=1.21.1 in /usr/local/lib/python3.7/dist-packages (from requests<3,>=2.25.1->aicrowd-cli) (1.24.3)
Collecting smmap<5,>=3.0.1
  Downloading https://files.pythonhosted.org/packages/68/ee/d540eb5e5996eb81c26ceffac6ee49041d473bc5125f2aa995cf51ec1cf1/smmap-4.0.0-py2.py3-none-any.whl
ERROR: google-colab 1.0.0 has requirement requests~=2.23.0, but you'll have requests 2.26.0 which is incompatible.
ERROR: datascience 0.10.6 has requirement folium==0.2.1, but you'll have folium 0.8.3 which is incompatible.
Installing collected packages: commonmark, colorama, rich, tqdm, smmap, gitdb, gitpython, requests, requests-toolbelt, aicrowd-cli
  Found existing installation: tqdm 4.41.1
    Uninstalling tqdm-4.41.1:
      Successfully uninstalled tqdm-4.41.1
  Found existing installation: requests 2.23.0
    Uninstalling requests-2.23.0:
      Successfully uninstalled requests-2.23.0
Successfully installed aicrowd-cli-0.1.7 colorama-0.4.4 commonmark-0.9.1 gitdb-4.0.7 gitpython-3.1.18 requests-2.26.0 requests-toolbelt-0.9.1 rich-10.6.0 smmap-4.0.0 tqdm-4.61.2
In [ ]:
%aicrowd login
In [ ]:
# Downloading the Dataset
!rm -rf data
!mkdir data
%aicrowd ds dl -c tree-segmentation -o data
mkdir: cannot create directory ‘data’: File exists
train.zip:   0% 0.00/402M [00:00<?, ?B/s]
train.zip:  42% 168M/402M [00:06<00:08, 28.3MB/s]
train.zip:  92% 369M/402M [00:13<00:01, 27.8MB/s]
train.zip: 100% 402M/402M [00:14<00:00, 28.0MB/s]

test.zip:  32% 101M/316M [00:19<00:42, 5.05MB/s] 
test.zip:  42% 134M/316M [00:25<00:33, 5.43MB/s]
test.zip:  53% 168M/316M [00:30<00:26, 5.67MB/s]
test.zip:  64% 201M/316M [00:35<00:19, 6.02MB/s]
test.zip:  74% 235M/316M [00:40<00:13, 6.09MB/s]
test.zip:  85% 268M/316M [00:45<00:07, 6.60MB/s]
test.zip:  96% 302M/316M [00:51<00:02, 6.20MB/s]
test.zip: 100% 316M/316M [00:54<00:00, 5.85MB/s]
In [ ]:
!unzip data/train.zip -d data/train > /dev/null
!unzip data/test.zip -d data/test > /dev/null
replace data/train/image/0.jpg? [y]es, [n]o, [A]ll, [N]one, [r]ename: N

Downloading & Importing Libraries

Here we are going to use segmentation_models.pytorch which is a really popular library providing a tons of different segmentation models for pytorch including basic unets to DeepLabV3!

Along with that, we will be also using library pytorch-argus to help in training the model.

In [ ]:
!pip install git+https://github.com/qubvel/segmentation_models.pytorch pytorch-argus
Collecting git+https://github.com/qubvel/segmentation_models.pytorch
  Cloning https://github.com/qubvel/segmentation_models.pytorch to /tmp/pip-req-build-br0w1mje
  Running command git clone -q https://github.com/qubvel/segmentation_models.pytorch /tmp/pip-req-build-br0w1mje
Collecting pytorch-argus
  Downloading https://files.pythonhosted.org/packages/f0/77/0a538db339fe4cc84241b7f152a38a144372d0247275b945a259241d4eab/pytorch_argus-0.2.1-py3-none-any.whl
Requirement already satisfied: torchvision>=0.5.0 in /usr/local/lib/python3.7/dist-packages (from segmentation-models-pytorch==0.2.0) (0.10.0+cu102)
Collecting pretrainedmodels==0.7.4
  Downloading https://files.pythonhosted.org/packages/84/0e/be6a0e58447ac16c938799d49bfb5fb7a80ac35e137547fc6cee2c08c4cf/pretrainedmodels-0.7.4.tar.gz (58kB)
     |████████████████████████████████| 61kB 8.8MB/s 
Collecting efficientnet-pytorch==0.6.3
  Downloading https://files.pythonhosted.org/packages/b8/cb/0309a6e3d404862ae4bc017f89645cf150ac94c14c88ef81d215c8e52925/efficientnet_pytorch-0.6.3.tar.gz
Collecting timm==0.4.12
  Downloading https://files.pythonhosted.org/packages/90/fc/606bc5cf46acac3aa9bd179b3954433c026aaf88ea98d6b19f5d14c336da/timm-0.4.12-py3-none-any.whl (376kB)
     |████████████████████████████████| 378kB 40.7MB/s 
Requirement already satisfied: torch>=1.1.0 in /usr/local/lib/python3.7/dist-packages (from pytorch-argus) (1.9.0+cu102)
Requirement already satisfied: pillow>=5.3.0 in /usr/local/lib/python3.7/dist-packages (from torchvision>=0.5.0->segmentation-models-pytorch==0.2.0) (7.1.2)
Requirement already satisfied: numpy in /usr/local/lib/python3.7/dist-packages (from torchvision>=0.5.0->segmentation-models-pytorch==0.2.0) (1.19.5)
Collecting munch
  Downloading https://files.pythonhosted.org/packages/cc/ab/85d8da5c9a45e072301beb37ad7f833cd344e04c817d97e0cc75681d248f/munch-2.5.0-py2.py3-none-any.whl
Requirement already satisfied: tqdm in /usr/local/lib/python3.7/dist-packages (from pretrainedmodels==0.7.4->segmentation-models-pytorch==0.2.0) (4.61.2)
Requirement already satisfied: typing-extensions in /usr/local/lib/python3.7/dist-packages (from torch>=1.1.0->pytorch-argus) (3.7.4.3)
Requirement already satisfied: six in /usr/local/lib/python3.7/dist-packages (from munch->pretrainedmodels==0.7.4->segmentation-models-pytorch==0.2.0) (1.15.0)
Building wheels for collected packages: segmentation-models-pytorch, pretrainedmodels, efficientnet-pytorch
  Building wheel for segmentation-models-pytorch (setup.py) ... done
  Created wheel for segmentation-models-pytorch: filename=segmentation_models_pytorch-0.2.0-cp37-none-any.whl size=88684 sha256=dcb75dfaaf55601885ce6a97fb9ed695a399507df8bf875526232d9c6c797a53
  Stored in directory: /tmp/pip-ephem-wheel-cache-makriwet/wheels/79/3f/09/1587a252e0314d26ad242d6d2e165622ab95c95e5cfe4b942c
  Building wheel for pretrainedmodels (setup.py) ... done
  Created wheel for pretrainedmodels: filename=pretrainedmodels-0.7.4-cp37-none-any.whl size=60966 sha256=df0d095295c8b6680328abbf922d64714ec7ffa4c943094a80173dc181b56275
  Stored in directory: /root/.cache/pip/wheels/69/df/63/62583c096289713f22db605aa2334de5b591d59861a02c2ecd
  Building wheel for efficientnet-pytorch (setup.py) ... done
  Created wheel for efficientnet-pytorch: filename=efficientnet_pytorch-0.6.3-cp37-none-any.whl size=12420 sha256=d2ddc80d0ac56313131319e7b9ff8e892f00afea76bb3b8f651fd43ba44dd2da
  Stored in directory: /root/.cache/pip/wheels/42/1e/a9/2a578ba9ad04e776e80bf0f70d8a7f4c29ec0718b92d8f6ccd
Successfully built segmentation-models-pytorch pretrainedmodels efficientnet-pytorch
Installing collected packages: pytorch-argus, munch, pretrainedmodels, efficientnet-pytorch, timm, segmentation-models-pytorch
Successfully installed efficientnet-pytorch-0.6.3 munch-2.5.0 pretrainedmodels-0.7.4 pytorch-argus-0.2.1 segmentation-models-pytorch-0.2.0 timm-0.4.12
In [ ]:
# Pytorch 
import torch
from torch import nn
import segmentation_models_pytorch as smp
import argus
from torch.utils.data import Dataset, DataLoader

# Reading Dataset, vis and miscellaneous
from PIL import Image
import matplotlib.pyplot as plt
import os
import numpy as np
from tqdm.notebook import tqdm
import cv2
from natsort import natsorted

Training phase ⚙️

Creating the Dataloader

Here, we are simply create a class for pytorch to load the dataset and then to put into the model

In [ ]:
class TreeSegmentationDataset(Dataset):
    def __init__(self, img_directory=None, label_directory=None, train=True):
        

        self.img_directory = img_directory
        self.label_directory = label_directory            

        # If the image direcotry is valid      
        if img_directory != None:
          self.img_list = natsorted(os.listdir(img_directory))
          self.label_list = natsorted(os.listdir(label_directory))

        self.train = train

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

    def __getitem__(self, idx):

        # Reading the image
        img = Image.open(os.path.join(self.img_directory, self.img_list[idx]))


        if self.train == True:
          
          # Readiding the mak image
          mask = Image.open(os.path.join(self.label_directory, self.label_list[idx]))

          img = np.array(img, dtype=np.float32)
          mask = np.array(mask, dtype=np.float32)

          # Change image channel ordering
          img = np.moveaxis(img, -1, 0)

          return img, mask
        
        # If reading test dataset, only return image 
        else:
          
          img = np.array(img, dtype=np.float32)
          img = np.moveaxis(img, -1, 0)

          return img
In [ ]:
# Creating the training dataset
train_dataset = TreeSegmentationDataset(img_directory="data/train/image", label_directory="data/train/segmentation")
train_loader = DataLoader(train_dataset, batch_size=4, num_workers=1, shuffle=False, drop_last=True)
In [ ]:
# Reading the image and corrosponding segmentation
image_batch, segmentation_batch = next(iter(train_loader))

image_batch.shape, segmentation_batch.shape
Out[ ]:
(torch.Size([4, 3, 512, 512]), torch.Size([4, 512, 512]))

Visualizing Dataset

In [ ]:
plt.rcParams["figure.figsize"] = (30,5)

# Going through each image and segmentation
for image, segmentation in zip(image_batch, segmentation_batch):

  # Change the channel ordering
  image = np.moveaxis(image.numpy()/255, 0, -1)

  # Showing the image
  plt.figure()
  plt.subplot(1,2,1)
  plt.imshow(image, 'gray', interpolation='none')
  plt.subplot(1,2,2)
  plt.imshow(image, 'gray', interpolation='none')
  plt.imshow(segmentation, 'jet', interpolation='none', alpha=0.7)
  plt.show()