diff --git a/MRnet-MultiTask-Approach/.gitignore b/MRnet-MultiTask-Approach/.gitignore
new file mode 100644
index 000000000..dc3531416
--- /dev/null
+++ b/MRnet-MultiTask-Approach/.gitignore
@@ -0,0 +1,13 @@
+*.npy
+*.DS_Store
+
+*.pth
+*.csv
+
+*.pyc
+
+.vscode
+
+runs/
+
+*__pycache__*
\ No newline at end of file
diff --git a/MRnet-MultiTask-Approach/LICENSE b/MRnet-MultiTask-Approach/LICENSE
new file mode 100644
index 000000000..dcb49ceb5
--- /dev/null
+++ b/MRnet-MultiTask-Approach/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2020 Big Vision LLC
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/MRnet-MultiTask-Approach/README.md b/MRnet-MultiTask-Approach/README.md
new file mode 100644
index 000000000..d95d31b90
--- /dev/null
+++ b/MRnet-MultiTask-Approach/README.md
@@ -0,0 +1,98 @@
+
+

+
+# Stanford MRnet Challenge
+
+**This repo contains code for the MRNet Challenge (A Multi-Task Approach)**
+
+
+For more details refer to https://stanfordmlgroup.github.io/competitions/mrnet/
+
+
+
+# Install dependencies
+1. `pip install git+https://github.com/ncullen93/torchsample`
+2. `pip install nibabel`
+3. `pip install sklearn`
+4. `pip install pandas`
+
+Install other dependencies as per requirement
+
+# Instructions to run the training
+1. Clone the repository.
+
+2. Download the dataset (~5.7 GB), and put `train` and `valid` folders along with all the the `.csv` files inside `images` folder at root directory.
+```Shell
+ images/
+ train/
+ axial/
+ sagittal/
+ coronal/
+ val/
+ axial/
+ sagittal/
+ coronal/
+ train-abnormal.csv
+ train-acl.csv
+ train-meniscus.csv
+ valid-abnormal.csv
+ valid-acl.csv
+ valid-meniscus.csv
+```
+
+3. Make a new folder called `weights` at root directory, and inside the `weights` folder create three more folders namely `acl`, `abnormal` and `meniscus`.
+
+4. All the hyperparameters are defined in `config.py` file. Feel free to play around those.
+
+5. Now finally run the training using `python train.py`. All the logs for tensorboard will be stored in the `runs` directory at the root of the project.
+
+# Understanding the Dataset
+
+
+
+

+
+
+
+The dataset contains MRIs of different people. Each MRI consists of multiple images.
+Each MRI has data in 3 perpendicular planes. And each plane as variable number of slices.
+
+Each slice is an `256x256` image
+
+For example:
+
+For `MRI 1` we will have 3 planes:
+
+Plane 1- with 35 slices
+
+Plane 2- with 34 slices
+
+Place 3 with 35 slices
+
+Each MRI has to be classisifed against 3 diseases
+
+Major challenge with while selecting the model structure was the inconsistency in the data. Although the image size remains constant , the number of slices per plane are variable within a single MRI and varies across all MRIs.
+
+# Model Specifications
+
+
+
+

+
+
+
+In the last attempt to MRNet challenge, we used 3 different models for each disease, but instead we can leverage the information that the model learns for each of the disease and make inferencing for other disease better.
+
+We used Hard Parameter sharing in this approach.
+
+We will be using 3 Alexnet pretrained as 3 feature extractors for each of the plane. We then combine these feature extractor layers as an input to a `global` fully connected layer for the final classification.
+
+# Contributors
+
+ -- Neelabh Madan
+
+
+
+-- Jatin Prakash
+
+
diff --git a/MRnet-MultiTask-Approach/config.py b/MRnet-MultiTask-Approach/config.py
new file mode 100644
index 000000000..21822c717
--- /dev/null
+++ b/MRnet-MultiTask-Approach/config.py
@@ -0,0 +1,13 @@
+config = {
+ 'max_epoch' : 50,
+ 'log_train' : 50,
+ 'lr' : 1e-5,
+ 'starting_epoch' : 0,
+ 'batch_size' : 1,
+ 'log_val' : 10,
+ 'task' : 'combined',
+ 'weight_decay' : 0.01,
+ 'patience' : 5,
+ 'save_model' : 1,
+ 'exp_name' : 'test'
+}
\ No newline at end of file
diff --git a/MRnet-MultiTask-Approach/content/logo.jpg b/MRnet-MultiTask-Approach/content/logo.jpg
new file mode 100644
index 000000000..9ce47a47b
Binary files /dev/null and b/MRnet-MultiTask-Approach/content/logo.jpg differ
diff --git a/MRnet-MultiTask-Approach/content/model.png b/MRnet-MultiTask-Approach/content/model.png
new file mode 100644
index 000000000..7829d939e
Binary files /dev/null and b/MRnet-MultiTask-Approach/content/model.png differ
diff --git a/MRnet-MultiTask-Approach/content/mri_scan.png b/MRnet-MultiTask-Approach/content/mri_scan.png
new file mode 100644
index 000000000..5556953e1
Binary files /dev/null and b/MRnet-MultiTask-Approach/content/mri_scan.png differ
diff --git a/MRnet-MultiTask-Approach/dataset/__init__.py b/MRnet-MultiTask-Approach/dataset/__init__.py
new file mode 100644
index 000000000..5d9ad0625
--- /dev/null
+++ b/MRnet-MultiTask-Approach/dataset/__init__.py
@@ -0,0 +1 @@
+from .dataset import MRData, load_data
\ No newline at end of file
diff --git a/MRnet-MultiTask-Approach/dataset/dataset.py b/MRnet-MultiTask-Approach/dataset/dataset.py
new file mode 100644
index 000000000..00a17259d
--- /dev/null
+++ b/MRnet-MultiTask-Approach/dataset/dataset.py
@@ -0,0 +1,153 @@
+import os
+import pandas as pd
+import numpy as np
+
+import torch
+import torch.utils.data as data
+
+from torchsample.transforms import RandomRotate, RandomTranslate, RandomFlip, ToTensor, Compose, RandomAffine
+from torchvision import transforms
+
+INPUT_DIM = 224
+MAX_PIXEL_VAL = 255
+MEAN = 58.09
+STDDEV = 49.73
+
+class MRData():
+ """This class used to load MRnet dataset from `./images` dir
+ """
+
+ def __init__(self,task = 'acl', train = True, transform = None, weights = None):
+ """Initialize the dataset
+
+ Args:
+ plane : along which plane to load the data
+ task : for which task to load the labels
+ train : whether to load the train or val data
+ transform : which transforms to apply
+ weights (Tensor) : Give wieghted loss to postive class eg. `weights=torch.tensor([2.223])`
+ """
+ self.planes=['axial', 'coronal', 'sagittal']
+ self.diseases = ['abnormal','acl','meniscus']
+ self.records = {'abnormal' : None, 'acl' : None, 'meniscus' : None}
+ # an empty dictionary
+ self.image_path={}
+
+ if train:
+ for disease in self.diseases:
+ self.records[disease] = pd.read_csv('./images/train-{}.csv'.format(disease),header=None, names=['id', 'label'])
+
+ '''
+ self.image_path[]= dictionary {: path to folder containing
+ image for that plane}
+ '''
+ for plane in self.planes:
+ self.image_path[plane] = './images/train/{}/'.format(plane)
+ else:
+ for disease in self.diseases:
+ self.records[disease] = pd.read_csv('./images/valid-{}.csv'.format(disease),header=None, names=['id', 'label'])
+
+ '''
+ self.image_path[]= dictionary {: path to folder containing
+ image for that plane}
+ '''
+ for plane in self.planes:
+ self.image_path[plane] = './images/valid/{}/'.format(plane)
+
+
+ self.transform = transform
+
+ for disease in self.diseases:
+ self.records[disease]['id'] = self.records[disease]['id'].map(
+ lambda i: '0' * (4 - len(str(i))) + str(i))
+
+ # empty dictionary
+ self.paths={}
+ for plane in self.planes:
+ self.paths[plane] = [self.image_path[plane] + filename +
+ '.npy' for filename in self.records['acl']['id'].tolist()]
+
+ self.labels = {'abnormal' : None, 'acl' : None, 'meniscus' : None}
+ for disease in self.diseases:
+ self.labels[disease] = self.records[disease]['label'].tolist()
+
+ weights_ = []
+ for disease in self.diseases:
+ pos = sum(self.labels[disease])
+ neg = len(self.labels[disease]) - pos
+ weights_.append(neg/pos)
+
+ # Find the wieghts of pos and neg classes
+ if weights:
+ self.weights = torch.FloatTensor(weights)
+ else:
+ self.weights = torch.FloatTensor(weights_)
+
+ print('Weights for loss is : ', self.weights)
+
+ def __len__(self):
+ """Return the total number of images in the dataset."""
+ return len(self.records['acl'])
+
+ def __getitem__(self, index):
+ """
+ Returns `(images,labels)` pair
+ where image is a list [imgsPlane1,imgsPlane2,imgsPlane3]
+ and labels is a list [gt,gt,gt]
+ """
+ img_raw = {}
+
+ for plane in self.planes:
+ img_raw[plane] = np.load(self.paths[plane][index])
+ img_raw[plane] = self._resize_image(img_raw[plane])
+
+ label = []
+ for disease in self.diseases:
+ label.append(self.labels[disease][index])
+
+ label = torch.FloatTensor(label)
+
+ return [img_raw[plane] for plane in self.planes], label
+
+ def _resize_image(self, image):
+ """Resize the image to `(3,224,224)` and apply
+ transforms if possible.
+ """
+ # Resize the image
+ pad = int((image.shape[2] - INPUT_DIM)/2)
+ image = image[:,pad:-pad,pad:-pad]
+ image = (image-np.min(image))/(np.max(image)-np.min(image))*MAX_PIXEL_VAL
+ image = (image - MEAN) / STDDEV
+
+ if self.transform:
+ image = self.transform(image)
+ else:
+ image = np.stack((image,)*3, axis=1)
+
+ image = torch.FloatTensor(image)
+ return image
+
+def load_data(task : str):
+
+ # Define the Augmentation here only
+ augments = Compose([
+ transforms.Lambda(lambda x: torch.Tensor(x)),
+ RandomRotate(25),
+ RandomTranslate([0.11, 0.11]),
+ RandomFlip(),
+ transforms.Lambda(lambda x: x.repeat(3, 1, 1, 1).permute(1, 0, 2, 3)),
+ ])
+
+ print('Loading Train Dataset of {} task...'.format(task))
+ train_data = MRData(task, train=True, transform=augments)
+ train_loader = data.DataLoader(
+ train_data, batch_size=1, num_workers=4, shuffle=True
+ )
+
+ print('Loading Validation Dataset of {} task...'.format(task))
+ val_data = MRData(task, train=False)
+ val_loader = data.DataLoader(
+ val_data, batch_size=1, num_workers=4, shuffle=False
+ )
+
+ return train_loader, val_loader, train_data.weights, val_data.weights
diff --git a/MRnet-MultiTask-Approach/models/MRnet.py b/MRnet-MultiTask-Approach/models/MRnet.py
new file mode 100644
index 000000000..d5d4c7948
--- /dev/null
+++ b/MRnet-MultiTask-Approach/models/MRnet.py
@@ -0,0 +1,56 @@
+import torch
+import torch.nn as nn
+from torchvision import models
+import os
+
+class MRnet(nn.Module):
+ """MRnet uses pretrained resnet50 as a backbone to extract features, this is multilabel classifying model
+ """
+
+ def __init__(self): # add conf file
+
+ super(MRnet,self).__init__()
+
+ # init three backbones for three axis
+ self.axial = models.alexnet(pretrained=True).features
+ self.coronal = models.alexnet(pretrained=True).features
+ self.saggital = models.alexnet(pretrained=True).features
+
+ self.pool_axial = nn.AdaptiveAvgPool2d(1)
+ self.pool_coronal = nn.AdaptiveAvgPool2d(1)
+ self.pool_saggital = nn.AdaptiveAvgPool2d(1)
+
+ self.fc = nn.Sequential(
+ nn.Linear(in_features=3*256,out_features=3)
+ )
+
+ def forward(self,x):
+ """ Input is given in the form of `[image1, image2, image3]` where
+ `image1 = [1, slices, 3, 224, 224]`. Note that `1` is due to the
+ dataloader assigning it a single batch.
+ """
+
+ # squeeze the first dimension as there
+ # is only one patient in each batch
+ images = [torch.squeeze(img, dim=0) for img in x]
+
+ image1 = self.axial(images[0])
+ image2 = self.coronal(images[1])
+ image3 = self.saggital(images[2])
+
+ image1 = self.pool_axial(image1).view(image1.size(0), -1)
+ image2 = self.pool_coronal(image2).view(image2.size(0), -1)
+ image3 = self.pool_saggital(image3).view(image3.size(0), -1)
+
+ image1 = torch.max(image1,dim=0,keepdim=True)[0]
+ image2 = torch.max(image2,dim=0,keepdim=True)[0]
+ image3 = torch.max(image3,dim=0,keepdim=True)[0]
+
+ output = torch.cat([image1,image2,image3], dim=1)
+
+ output = self.fc(output)
+ return output
+
+ def _load_wieghts(self):
+ """load pretrained weights"""
+ pass
\ No newline at end of file
diff --git a/MRnet-MultiTask-Approach/models/__init__.py b/MRnet-MultiTask-Approach/models/__init__.py
new file mode 100644
index 000000000..7e95766c3
--- /dev/null
+++ b/MRnet-MultiTask-Approach/models/__init__.py
@@ -0,0 +1 @@
+from .MRnet import MRnet
\ No newline at end of file
diff --git a/MRnet-MultiTask-Approach/src/README.md b/MRnet-MultiTask-Approach/src/README.md
new file mode 100644
index 000000000..4eab12803
--- /dev/null
+++ b/MRnet-MultiTask-Approach/src/README.md
@@ -0,0 +1 @@
+This contains the submission code for MRnet challenge.
\ No newline at end of file
diff --git a/MRnet-MultiTask-Approach/src/models/MRnet.py b/MRnet-MultiTask-Approach/src/models/MRnet.py
new file mode 100644
index 000000000..38257e8b7
--- /dev/null
+++ b/MRnet-MultiTask-Approach/src/models/MRnet.py
@@ -0,0 +1,56 @@
+import torch
+import torch.nn as nn
+from torchvision import models
+import os
+
+class MRnet(nn.Module):
+ """MRnet uses pretrained resnet50 as a backbone to extract features
+ """
+
+ def __init__(self): # add conf file
+
+ super(MRnet,self).__init__()
+
+ # init three backbones for three axis
+ self.axial = models.alexnet(pretrained=False).features
+ self.coronal = models.alexnet(pretrained=False).features
+ self.saggital = models.alexnet(pretrained=False).features
+
+ self.pool_axial = nn.AdaptiveAvgPool2d(1)
+ self.pool_coronal = nn.AdaptiveAvgPool2d(1)
+ self.pool_saggital = nn.AdaptiveAvgPool2d(1)
+
+ self.fc = nn.Sequential(
+ nn.Linear(in_features=3*256,out_features=1)
+ )
+
+ def forward(self,x):
+ """ Input is given in the form of `[image1, image2, image3]` where
+ `image1 = [1, slices, 3, 224, 224]`. Note that `1` is due to the
+ dataloader assigning it a single batch.
+ """
+
+ # squeeze the first dimension as there
+ # is only one patient in each batch
+ images = [torch.squeeze(img, dim=0) for img in x]
+
+ image1 = self.axial(images[0])
+ image2 = self.coronal(images[1])
+ image3 = self.saggital(images[2])
+
+ image1 = self.pool_axial(image1).view(image1.size(0), -1)
+ image2 = self.pool_coronal(image2).view(image2.size(0), -1)
+ image3 = self.pool_saggital(image3).view(image3.size(0), -1)
+
+ image1 = torch.max(image1,dim=0,keepdim=True)[0]
+ image2 = torch.max(image2,dim=0,keepdim=True)[0]
+ image3 = torch.max(image3,dim=0,keepdim=True)[0]
+
+ output = torch.cat([image1,image2,image3], dim=1)
+
+ output = self.fc(output)
+ return output
+
+ def _load_wieghts(self):
+ """load pretrained weights"""
+ pass
\ No newline at end of file
diff --git a/MRnet-MultiTask-Approach/src/models/__init__.py b/MRnet-MultiTask-Approach/src/models/__init__.py
new file mode 100644
index 000000000..7e95766c3
--- /dev/null
+++ b/MRnet-MultiTask-Approach/src/models/__init__.py
@@ -0,0 +1 @@
+from .MRnet import MRnet
\ No newline at end of file
diff --git a/MRnet-MultiTask-Approach/src/submit_predictions.py b/MRnet-MultiTask-Approach/src/submit_predictions.py
new file mode 100644
index 000000000..afa0b6f5e
--- /dev/null
+++ b/MRnet-MultiTask-Approach/src/submit_predictions.py
@@ -0,0 +1,93 @@
+import torch
+import numpy as np
+import sys
+
+from models import MRnet
+
+
+INPUT_DIM = 224
+MAX_PIXEL_VAL = 255
+MEAN = 58.09
+STDDEV = 49.73
+
+def _resize_image(image):
+ """Resize the image to `(3,224,224)` and apply
+ transforms if possible.
+ """
+ # Resize the image
+ pad = int((image.shape[2] - INPUT_DIM)/2)
+ image = image[:,pad:-pad,pad:-pad]
+ image = (image-np.min(image))/(np.max(image)-np.min(image))*MAX_PIXEL_VAL
+ image = (image - MEAN) / STDDEV
+
+ image = np.stack((image,)*3, axis=1)
+
+ image = torch.FloatTensor(image)
+ return image
+
+def _get_images(axial_path, coron_path, sagit_path):
+ axial = np.load(axial_path)
+ coron = np.load(coron_path)
+ sagit = np.load(sagit_path)
+
+ # Load images and add a extra dimension
+ axial_tensor = _resize_image(axial).unsqueeze(dim=0)
+ coron_tensor = _resize_image(coron).unsqueeze(dim=0)
+ sagit_tensor = _resize_image(sagit).unsqueeze(dim=0)
+
+ return [axial_tensor, coron_tensor, sagit_tensor]
+
+
+if __name__ == '__main__':
+ input_csv_path = sys.argv[1] # 'valid-paths.csv'
+ preds_csv_path = sys.argv[2] # 'pred.csv' # sys.argv[2]
+
+ paths = []
+ for i, fpath in enumerate(open(input_csv_path).readlines()):
+ if 'axial' in fpath:
+ axial_path = fpath.strip()
+ elif 'coronal' in fpath:
+ coron_path = fpath.strip()
+ elif 'sagittal' in fpath:
+ sagit_path = fpath.strip()
+
+ if i % 3 == 2:
+ paths.append((axial_path, coron_path, sagit_path))
+
+ all_predictions = {'abnormal' : [], 'acl' : [], 'meniscus' : []}
+
+ # Loading all models
+ diseases = ['abnormal','acl','meniscus']
+ model_paths = [
+ './src/model_final_train_abnormal_val_auc_0.9394_train_auc_0.9379_epoch_30.pth',
+ './src/model_final_train_acl_val_auc_0.9602_train_auc_0.9956_epoch_32.pth',
+ './src/model_final_train_meniscus_val_auc_0.7837_train_auc_0.9161_epoch_30.pth'
+ ]
+
+ for model_path, disease in zip(model_paths,diseases):
+
+ model = MRnet()
+ state_dict = torch.load(model_path)
+ model.load_state_dict(state_dict['model_state_dict'])
+
+ if torch.cuda.is_available():
+ model = model.cuda()
+
+ for axial_path, coron_path, sagit_path in paths:
+
+ images = _get_images(axial_path, coron_path, sagit_path)
+
+ if torch.cuda.is_available():
+ images = [image.cuda() for image in images]
+
+ with torch.no_grad():
+ output = model(images)
+ prob = torch.sigmoid(output).item()
+ all_predictions[disease].append(prob)
+
+ # Write all results in .csv file
+ with open(preds_csv_path, 'w') as csv_file:
+ for i in range(len(all_predictions['acl'])):
+ csv_file.write(','.join(
+ [str(all_predictions['abnormal'][i]), str(all_predictions['acl'][i]), str(all_predictions['meniscus'][i])]))
+ csv_file.write('\n')
diff --git a/MRnet-MultiTask-Approach/train.py b/MRnet-MultiTask-Approach/train.py
new file mode 100644
index 000000000..0d4429ea9
--- /dev/null
+++ b/MRnet-MultiTask-Approach/train.py
@@ -0,0 +1,112 @@
+from dataset import load_data
+from models import MRnet
+from config import config
+import torch
+from torch.utils.tensorboard import SummaryWriter
+from utils import _train_model, _evaluate_model, _get_lr
+import time
+import torch.utils.data as data
+import os
+
+"""Performs training of a specified model.
+
+Input params:
+ config_file: Takes in configurations to train with
+"""
+
+def train(config : dict):
+ """
+ Function where actual training takes place
+
+ Args:
+ config (dict) : Configuration to train with
+ """
+
+ print('Starting to Train Model...')
+
+ train_loader, val_loader, train_wts, val_wts = load_data(config['task'])
+
+ print('Initializing Model...')
+ model = MRnet()
+ if torch.cuda.is_available():
+ model = model.cuda()
+ train_wts = train_wts.cuda()
+ val_wts = val_wts.cuda()
+
+ print('Initializing Loss Method...')
+ criterion = torch.nn.BCEWithLogitsLoss(pos_weight=train_wts)
+ val_criterion = torch.nn.BCEWithLogitsLoss(pos_weight=val_wts)
+
+ if torch.cuda.is_available():
+ criterion = criterion.cuda()
+ val_criterion = val_criterion.cuda()
+
+ print('Setup the Optimizer')
+ optimizer = torch.optim.Adam(model.parameters(), lr=config['lr'], weight_decay=config['weight_decay'])
+ scheduler = torch.optim.lr_scheduler.ReduceLROnPlateau(
+ optimizer, patience=3, factor=.3, threshold=1e-4, verbose=True)
+
+ starting_epoch = config['starting_epoch']
+ num_epochs = config['max_epoch']
+ patience = config['patience']
+ log_train = config['log_train']
+ log_val = config['log_val']
+
+ best_val_loss = float('inf')
+ best_val_auc = float(0)
+
+ print('Starting Training')
+
+ writer = SummaryWriter(comment='lr={} task={}'.format(config['lr'], config['task']))
+ t_start_training = time.time()
+
+ for epoch in range(starting_epoch, num_epochs):
+
+ current_lr = _get_lr(optimizer)
+ epoch_start_time = time.time() # timer for entire epoch
+
+ print('Started Training')
+ train_loss, train_auc = _train_model(
+ model, train_loader, epoch, num_epochs, optimizer, criterion, writer, current_lr, log_every=log_train)
+
+ print('train loop ended, now val')
+ val_loss, val_auc = _evaluate_model(
+ model, val_loader, val_criterion, epoch, num_epochs, writer, current_lr, log_val)
+
+ writer.add_scalar('Train/Avg Loss', train_loss, epoch)
+ writer.add_scalar('Val/Avg Loss', val_loss, epoch)
+
+ scheduler.step(val_loss)
+
+ t_end = time.time()
+ delta = t_end - epoch_start_time
+
+ print("train loss : {0} | train auc {1} | val loss {2} | val auc {3} | elapsed time {4} s".format(
+ train_loss, train_auc, val_loss, val_auc, delta))
+
+ print('-' * 30)
+
+ writer.flush()
+
+ if val_auc > best_val_auc:
+ best_val_auc = val_auc
+
+ if bool(config['save_model']):
+ file_name = 'model_{}_{}_val_auc_{:0.4f}_train_auc_{:0.4f}_epoch_{}.pth'.format(config['exp_name'], config['task'], val_auc, train_auc, epoch+1)
+ torch.save({
+ 'model_state_dict': model.state_dict()
+ }, './weights/{}/{}'.format(config['task'],file_name))
+
+ t_end_training = time.time()
+ print(f'training took {t_end_training - t_start_training} s')
+ writer.flush()
+ writer.close()
+
+if __name__ == '__main__':
+
+ print('Training Configuration')
+ print(config)
+
+ train(config=config)
+
+ print('Training Ended...')
diff --git a/MRnet-MultiTask-Approach/utils/__init__.py b/MRnet-MultiTask-Approach/utils/__init__.py
new file mode 100644
index 000000000..111b181ce
--- /dev/null
+++ b/MRnet-MultiTask-Approach/utils/__init__.py
@@ -0,0 +1 @@
+from .utils import _train_model, _evaluate_model, _get_lr
\ No newline at end of file
diff --git a/MRnet-MultiTask-Approach/utils/utils.py b/MRnet-MultiTask-Approach/utils/utils.py
new file mode 100644
index 000000000..e591e3d48
--- /dev/null
+++ b/MRnet-MultiTask-Approach/utils/utils.py
@@ -0,0 +1,175 @@
+import torch
+from sklearn import metrics
+import numpy as np
+
+def _get_trainable_params(model):
+ """Get Parameters with `requires.grad` set to `True`"""
+ trainable_params = []
+ for x in model.parameters():
+ if x.requires_grad:
+ trainable_params.append(x)
+ return trainable_params
+
+def _evaluate_model(model, val_loader, criterion, epoch, num_epochs, writer, current_lr, log_every=20):
+ """Runs model over val dataset and returns auc and avg val loss"""
+
+ # Set to eval mode
+ model.eval()
+
+ y_probs = [[],[],[]]
+ y_gt = [[],[],[]]
+ losses = []
+
+ for i, (images, label) in enumerate(val_loader):
+
+ if torch.cuda.is_available():
+ images = [image.cuda() for image in images]
+ label = label.cuda()
+
+ output = model(images)
+
+ loss = criterion(output, label)
+
+ loss_value = loss.item()
+ losses.append(loss_value)
+
+ probas = torch.sigmoid(output)
+
+ for j, x in enumerate(label[0]):
+ y_gt[j].append(int(label[0][j].item()))
+
+ for j, x in enumerate(probas[0]):
+ y_probs[j].append(probas[0][j].item())
+
+ aucs = []
+ for j in range(3):
+ try:
+ aucs.append(metrics.roc_auc_score(y_gt[j], y_probs[j]))
+ except:
+ aucs.append(0.5)
+
+ writer.add_scalar('Val/Loss', loss_value, epoch * len(val_loader) + i)
+ writer.add_scalar('Val/AUC', np.mean(aucs), epoch * len(val_loader) + i)
+ writer.add_scalar('Val/AUC_abnormal', aucs[0], epoch * len(val_loader) + i)
+ writer.add_scalar('Val/AUC_acl', aucs[1], epoch * len(val_loader) + i)
+ writer.add_scalar('Val/AUC_meniscus', aucs[2], epoch * len(val_loader) + i)
+
+ if (i % log_every == 0) & (i > 0):
+ print('''[Epoch: {0} / {1} | Batch : {2} / {3} ]| Avg Val Loss {4} | Val AUC : {5} abnorm:{6} acl:{7} meni:{8} | lr : {9}'''.
+ format(
+ epoch + 1,
+ num_epochs,
+ i,
+ len(val_loader),
+ np.round(np.mean(losses), 4),
+ np.round(np.mean(aucs), 4),
+ np.round(aucs[0], 4),
+ np.round(aucs[1], 4),
+ np.round(aucs[2], 4),
+ current_lr
+ )
+ )
+
+ writer.add_scalar('Val/AUC_epoch', np.mean(aucs), epoch)
+ writer.add_scalar('Val/AUC_epoch_abnormal', aucs[0], epoch)
+ writer.add_scalar('Val/AUC_epoch_acl', aucs[1], epoch)
+ writer.add_scalar('Val/AUC_epoch_meniscus', aucs[2], epoch)
+
+ print('Epoch {} End Val Avg AUC : {} abnorm : {} acl : {} meni : {}'.format(epoch,
+ np.round(np.mean(aucs), 4),
+ np.round(aucs[0], 4),
+ np.round(aucs[1], 4),
+ np.round(aucs[2], 4),))
+
+
+ val_loss_epoch = np.round(np.mean(losses), 4)
+ val_auc_epoch = np.round(np.mean(aucs), 4)
+
+ return val_loss_epoch, val_auc_epoch
+
+def _train_model(model, train_loader, epoch, num_epochs, optimizer, criterion, writer, current_lr, log_every=100):
+
+ # Set to train mode
+ model.train()
+
+ y_probs = [[],[],[]]
+ y_gt = [[],[],[]]
+ losses = []
+
+ for i, (images, label) in enumerate(train_loader):
+ optimizer.zero_grad()
+
+ if torch.cuda.is_available():
+ images = [image.cuda() for image in images]
+ label = label.cuda()
+
+ output = model(images)
+
+ loss = criterion(output, label)
+ loss.backward()
+ optimizer.step()
+
+ loss_value = loss.item()
+ losses.append(loss_value)
+
+ probas = torch.sigmoid(output)
+
+ for j, x in enumerate(label[0]):
+ y_gt[j].append(int(label[0][j].item()))
+
+ for j, x in enumerate(probas[0]):
+ y_probs[j].append(probas[0][j].item())
+
+ aucs = []
+ for j in range(3):
+ try:
+ aucs.append(metrics.roc_auc_score(y_gt[j], y_probs[j]))
+ except:
+ # print("nope")
+ # print(y_gt, y_probs)
+ aucs.append(0.5)
+
+
+ writer.add_scalar('Train/Loss', loss_value,
+ epoch * len(train_loader) + i)
+ writer.add_scalar('Train/AUC', np.mean(aucs), epoch * len(train_loader) + i)
+ writer.add_scalar('Train/AUC_abnormal', aucs[0], epoch * len(train_loader) + i)
+ writer.add_scalar('Train/AUC_acl', aucs[1], epoch * len(train_loader) + i)
+ writer.add_scalar('Train/AUC_meniscus', aucs[2], epoch * len(train_loader) + i)
+
+
+ if (i % log_every == 0) & (i > 0):
+ print('''[Epoch: {0} / {1} | Batch : {2} / {3} ]| Avg Train Loss {4} | Train Avg AUC : {5} abnorm:{6} acl:{7} meni:{8} | lr : {9}'''.
+ format(
+ epoch + 1,
+ num_epochs,
+ i,
+ len(train_loader),
+ np.round(np.mean(losses), 4),
+ np.round(np.mean(aucs), 4),
+ np.round(aucs[0], 4),
+ np.round(aucs[1], 4),
+ np.round(aucs[2], 4),
+ current_lr
+ )
+ )
+
+ writer.add_scalar('Train/AUC_epoch', np.mean(aucs), epoch)
+ writer.add_scalar('Train/AUC_epoch_abnormal', aucs[0], epoch)
+ writer.add_scalar('Train/AUC_epoch_acl', aucs[1], epoch)
+ writer.add_scalar('Train/AUC_epoch_meniscus', aucs[2], epoch)
+
+ train_loss_epoch = np.round(np.mean(losses), 4)
+ train_auc_epoch = np.round(np.mean(aucs), 4)
+
+ print('Epoch {} End Train Avg AUC : {} abnorm : {} acl : {} meni : {}'.format(epoch,
+ np.round(np.mean(aucs), 4),
+ np.round(aucs[0], 4),
+ np.round(aucs[1], 4),
+ np.round(aucs[2], 4),))
+
+ return train_loss_epoch, train_auc_epoch
+
+def _get_lr(optimizer):
+ for param_group in optimizer.param_groups:
+ return param_group['lr']
diff --git a/README.md b/README.md
deleted file mode 100644
index 34f4d1c4c..000000000
--- a/README.md
+++ /dev/null
@@ -1,195 +0,0 @@
-# LearnOpenCV
-This repo contains code for Computer Vision, Deep learning, and AI articles shared on our blog [LearnOpenCV.com](https://www.LearnOpenCV.com).
-
-Want to become an expert in AI? [AI Courses by OpenCV](https://opencv.org/courses/) is a great place to start.
-
-
-
-
-
-
-
-## List of Blog Posts
-
-| Blog Post | |
-| ------------- |:-------------|
-|[PyTorch to Tensorflow Model Conversion](https://www.learnopencv.com/pytorch-to-tensorflow-model-conversion/) | [Code](https://github.com/spmallick/learnopencv/tree/master/PyTorch-to-TensorFlow-Model-Conversion) |
-|[Snake Game with OpenCV Python](https://www.learnopencv.com/snake-game-with-opencv-python/)|[Code](https://github.com/spmallick/learnopencv/tree/master/SnakeGame)|
-|[Stanford MRNet Challenge: Classifying Knee MRIs](https://www.learnopencv.com/stanford-mrnet-challenge-classifying-knee-mris/)|[Code](https://github.com/spmallick/learnopencv/tree/master/MRNet-Single-Model)|
-|[Experiment Logging with TensorBoard and wandb](https://www.learnopencv.com/experiment-logging-with-tensorboard-and-wandb)|[Code](https://github.com/spmallick/learnopencv/tree/master/PyTorch-Vision-Experiment-Logging)|
-|[Understanding Lens Distortion](https://www.learnopencv.com/understanding-lens-distortion/)|[Code](https://github.com/spmallick/learnopencv/tree/master/UnderstandingLensDistortion)|
-|[Image Matting with state-of-the-art Method “F, B, Alpha Matting”](https://www.learnopencv.com/image-matting-with-state-of-the-art-method-f-b-alpha-matting/)|[Code](https://github.com/spmallick/learnopencv/tree/master/FBAMatting) |
-|[Bag Of Tricks For Image Classification - Let's check if it is working or not](https://www.learnopencv.com/bag-of-tricks-for-image-classification-lets-check-if-it-is-working-or-not/)| [Code](https://github.com/spmallick/learnopencv/tree/master/Bag-Of-Tricks-For-Image-Classification)
-|[Getting Started with OpenCV CUDA Module](https://www.learnopencv.com/getting-started-opencv-cuda-module/)|[Code](https://github.com/spmallick/learnopencv/tree/master/Getting-Started-OpenCV-CUDA-Module)|
-|[Training a Custom Object Detector with DLIB & Making Gesture Controlled Applications](https://www.learnopencv.com/training-a-custom-object-detector-with-dlib-making-gesture-controlled-applications/)|[Code](https://github.com/spmallick/learnopencv/tree/master/Training_a_custom_hand_detector_with_dlib) |
-|[How To Run Inference Using TensorRT C++ API](https://www.learnopencv.com/how-to-run-inference-using-tensorrt-c-api/) | [Code](https://github.com/spmallick/learnopencv/tree/master/PyTorch-ONNX-TensorRT-CPP) |
-|[Using Facial Landmarks for Overlaying Faces with Medical Masks](https://www.learnopencv.com/using-facial-landmarks-for-overlaying-faces-with-masks/)|[Code](https://github.com/spmallick/learnopencv/tree/master/FaceMaskOverlay) |
-|[Tensorboard with PyTorch Lightning](https://www.learnopencv.com/tensorboard-with-pytorch-lightning)|[Code](https://github.com/spmallick/learnopencv/tree/master/TensorBoard-With-Pytorch-Lightning)
-|[Otsu's Thresholding with OpenCV](https://www.learnopencv.com/otsu-thresholding-with-opencv/)|[Code](https://github.com/spmallick/learnopencv/tree/master/otsu-method)
-|[PyTorch-to-CoreML-model-conversion](https://www.learnopencv.com/pytorch-to-coreml-model-conversion/) | [Code](https://github.com/spmallick/learnopencv/tree/master/PyTorch-to-CoreML-model-conversion)
-|[Playing Rock, Paper, Scissors with AI](https://www.learnopencv.com/playing-rock-paper-scissors-with-ai/) | [Code](https://github.com/spmallick/learnopencv/tree/master/Playing-rock-paper-scissors-with-AI) |
-|[CNN Receptive Field Computation Using Backprop with TensorFlow](https://www.learnopencv.com/cnn-receptive-field-computation-using-backprop-with-tensorflow/)|[Code](https://github.com/spmallick/learnopencv/tree/master/TensorFlow-Receptive-Field-With-Backprop)|
-|[CNN Fully Convolutional Image Classification with TensorFlow](https://www.learnopencv.com/cnn-fully-convolutional-image-classification-with-tensorflow) | [Code](https://github.com/spmallick/learnopencv/tree/master/TensorFlow-Fully-Convolutional-Image-Classification) |
-|[How to convert a model from PyTorch to TensorRT and speed up inference](https://www.learnopencv.com/how-to-convert-a-model-from-pytorch-to-tensorrt-and-speed-up-inference/) | [Code](https://github.com/spmallick/learnopencv/tree/master/PyTorch-ONNX-TensorRT) |
-|[Efficient image loading](https://www.learnopencv.com/efficient-image-loading/)|[Code](https://github.com/spmallick/learnopencv/tree/master/Efficient-image-loading) |
-|[Graph Convolutional Networks: Model Relations In Data](https://www.learnopencv.com/graph-convolutional-networks-model-relations-in-data/)|[Code](https://github.com/spmallick/learnopencv/tree/master/Graph-Convolutional-Networks-Model-Relations-In-Data)|
-|[Getting Started with Federated Learning with PyTorch and PySyft](https://www.learnopencv.com/federated-learning-using-pytorch-and-pysyft/)|[Code](https://github.com/spmallick/learnopencv/tree/master/Federated-Learning-Intro)|
-|[Creating a Virtual Pen & Eraser](http://www.learnopencv.com/creating-a-virtual-pen-and-eraser-with-opencv/) | [Code](https://github.com/spmallick/learnopencv/tree/master/Creating-a-Virtual-Pen-and-Eraser) |
-|[Getting Started with PyTorch Lightning](https://www.learnopencv.com/getting-started-with-pytorch-lightning/)|[Code](https://github.com/spmallick/learnopencv/tree/master/Pytorch-Lightning)|
-|[Multi-Label Image Classification with PyTorch: Image Tagging](https://www.learnopencv.com/multi-label-image-classification-with-pytorch-image-tagging/)|[Code](https://github.com/spmallick/learnopencv/tree/master/PyTorch-Multi-Label-Image-Classification-Image-Tagging)|
-|[Funny Mirrors Using OpenCV](https://www.learnopencv.com/Funny-Mirrors-Using-OpenCV/)|[code](https://github.com/spmallick/learnopencv/tree/master/FunnyMirrors)|
-|[t-SNE for ResNet feature visualization](https://www.learnopencv.com/t-sne-for-resnet-feature-visualization/)|[Code](https://github.com/spmallick/learnopencv/tree/master/TSNE)|
-|[Multi-Label Image Classification with Pytorch](https://www.learnopencv.com/multi-label-image-classification-with-pytorch/)|[Code](https://github.com/spmallick/learnopencv/tree/master/PyTorch-Multi-Label-Image-Classification)|
-|[CNN Receptive Field Computation Using Backprop](https://www.learnopencv.com/cnn-receptive-field-computation-using-backprop/)|[Code](https://github.com/spmallick/learnopencv/tree/master/PyTorch-Receptive-Field-With-Backprop)|
-|[CNN Receptive Field Computation Using Backprop with TensorFlow](https://www.learnopencv.com/cnn-receptive-field-computation-using-backprop-with-tensorflow/)|[Code](https://github.com/spmallick/learnopencv/tree/master/TensorFlow-Receptive-Field-With-Backprop)|
-|[Augmented Reality using AruCo Markers in OpenCV(C++ and Python)](https://www.learnopencv.com/augmented-reality-using-aruco-markers-in-opencv-(c++-python)/) |[Code](https://github.com/spmallick/learnopencv/tree/master/AugmentedRealityWithArucoMarkers)|
-|[Fully Convolutional Image Classification on Arbitrary Sized Image](https://www.learnopencv.com/fully-convolutional-image-classification-on-arbitrary-sized-image/)|[Code](https://github.com/spmallick/learnopencv/tree/master/PyTorch-Fully-Convolutional-Image-Classification)|
-|[Camera Calibration using OpenCV](https://www.learnopencv.com/camera-calibration-using-opencv/) |[Code](https://github.com/spmallick/learnopencv/tree/master/CameraCalibration)|
-|[Geometry of Image Formation](https://www.learnopencv.com/geometry-of-image-formation/) ||
-|[Ensuring Training Reproducibility in Pytorch](https://www.learnopencv.com/ensuring-training-reproducibility-in-pytorch) ||
-|[Gaze Tracking](https://www.learnopencv.com/gaze-tracking/) ||
-|[Simple Background Estimation in Videos Using OpenCV](https://www.learnopencv.com/simple-background-estimation-in-videos-using-opencv-c-python/) | [Code](https://github.com/spmallick/learnopencv/tree/master/VideoBackgroundEstimation)|
-|[Applications of Foreground-Background separation with Semantic Segmentation](https://www.learnopencv.com/applications-of-foreground-background-separation-with-semantic-segmentation/) | [Code](https://github.com/spmallick/learnopencv/tree/master/app-seperation-semseg) |
-|[EfficientNet: Theory + Code](https://www.learnopencv.com/efficientnet-theory-code) | [Code](https://github.com/spmallick/learnopencv/tree/master/EfficientNet) |
-|[PyTorch for Beginners: Mask R-CNN Instance Segmentation with PyTorch](https://www.learnopencv.com/mask-r-cnn-instance-segmentation-with-pytorch/) | [Code](./PyTorch-Mask-RCNN) |
-|[PyTorch for Beginners: Faster R-CNN Object Detection with PyTorch](https://www.learnopencv.com/faster-r-cnn-object-detection-with-pytorch) | [Code](https://github.com/spmallick/learnopencv/tree/master/PyTorch-faster-RCNN) |
-|[PyTorch for Beginners: Semantic Segmentation using torchvision](https://www.learnopencv.com/pytorch-for-beginners-semantic-segmentation-using-torchvision/) | [Code](https://github.com/spmallick/learnopencv/tree/master/PyTorch-Segmentation-torchvision) |
-|[PyTorch for Beginners: Comparison of pre-trained models for Image Classification](https://www.learnopencv.com/image-classification-using-pre-trained-models-using-pytorch/) | [Code](https://github.com/spmallick/learnopencv/tree/master/Image-classification-pre-trained-models/Image_Classification_using_pre_trained_models.ipynb) |
-|[PyTorch for Beginners: Basics](https://www.learnopencv.com/pytorch-for-beginners-basics/) | [Code](https://github.com/spmallick/learnopencv/tree/master/PyTorch-for-Beginners/PyTorch_for_Beginners.ipynb) |
-|[PyTorch Model Inference using ONNX and Caffe2](https://www.learnopencv.com/pytorch-model-inference-using-onnx-and-caffe2/) | [Code](https://github.com/spmallick/learnopencv/tree/master/Inference-for-PyTorch-Models/ONNX-Caffe2) |
-|[Image Classification Using Transfer Learning in PyTorch](https://www.learnopencv.com/image-classification-using-transfer-learning-in-pytorch/) | [Code](https://github.com/spmallick/learnopencv/tree/master/Image-Classification-in-PyTorch) |
-|[Hangman: Creating games in OpenCV](https://www.learnopencv.com/hangman-creating-games-in-opencv/) | [Code](https://github.com/spmallick/learnopencv/tree/master/Hangman) |
-|[Image Inpainting with OpenCV (C++/Python)](https://www.learnopencv.com/image-inpainting-with-opencv-c-python/) | [Code](https://github.com/spmallick/learnopencv/tree/master/Image-Inpainting) |
-|[Hough Transform with OpenCV (C++/Python)](https://www.learnopencv.com/hough-transform-with-opencv-c-python/) | [Code](https://github.com/spmallick/learnopencv/tree/master/Hough-Transform) |
-|[Xeus-Cling: Run C++ code in Jupyter Notebook](https://www.learnopencv.com/xeus-cling-run-c-code-in-jupyter-notebook/) | [Code](https://github.com/spmallick/learnopencv/tree/master/XeusCling) |
-|[Gender & Age Classification using OpenCV Deep Learning ( C++/Python )](https://www.learnopencv.com/age-gender-classification-using-opencv-deep-learning-c-python/) | [Code](https://github.com/spmallick/learnopencv/tree/master/AgeGender) |
-|[Invisibility Cloak using Color Detection and Segmentation with OpenCV](https://www.learnopencv.com/invisibility-cloak-using-color-detection-and-segmentation-with-opencv/) | [Code](https://github.com/spmallick/learnopencv/tree/master/InvisibilityCloak) |
-|[Fast Image Downloader for Open Images V4 (Python)](https://www.learnopencv.com/fast-image-downloader-for-open-images-v4/) | [Code](https://github.com/spmallick/learnopencv/tree/master/downloadOpenImages) |
-|[Deep Learning based Text Detection Using OpenCV (C++/Python)](https://www.learnopencv.com/deep-learning-based-text-detection-using-opencv-c-python/) | [Code](https://github.com/spmallick/learnopencv/tree/master/TextDetectionEAST) |
-|[Video Stabilization Using Point Feature Matching in OpenCV](https://www.learnopencv.com/video-stabilization-using-point-feature-matching-in-opencv/) | [Code](https://github.com/spmallick/learnopencv/tree/master/VideoStabilization) |
-|[Training YOLOv3 : Deep Learning based Custom Object Detector](https://www.learnopencv.com/training-yolov3-deep-learning-based-custom-object-detector/) | [Code](https://github.com/spmallick/learnopencv/tree/master/YOLOv3-Training-Snowman-Detector ) |
-|[Using OpenVINO with OpenCV](https://www.learnopencv.com/using-openvino-with-opencv/) | [Code](https://github.com/spmallick/learnopencv/tree/master/OpenVINO-OpenCV) |
-|[Duplicate Search on Quora Dataset](https://www.learnopencv.com/duplicate-search-on-quora-dataset/) | [Code](https://github.com/spmallick/learnopencv/tree/master/Quora-Dataset-Duplicate-Search) |
-|[Shape Matching using Hu Moments (C++/Python)](https://www.learnopencv.com/shape-matching-using-hu-moments-c-python/) | [Code](https://github.com/spmallick/learnopencv/tree/master/HuMoments) |
-|[Install OpenCV 4 on CentOS (C++ and Python)](https://www.learnopencv.com/install-opencv-4-on-centos-7/) | [Code](https://github.com/spmallick/learnopencv/blob/master/InstallScripts/installOpenCV-3-on-centos.sh) |
-|[Install OpenCV 3.4.4 on CentOS (C++ and Python)](https://www.learnopencv.com/install-opencv-3-4-4-on-centos-7/) | [Code](https://github.com/spmallick/learnopencv/blob/master/InstallScripts/installOpenCV-3-on-centos.sh) |
-|[Install OpenCV 3.4.4 on Red Hat (C++ and Python)](https://www.learnopencv.com/install-opencv-3-4-4-on-red-hat/) | [Code](https://github.com/spmallick/learnopencv/blob/master/InstallScripts/installOpenCV-3-on-red-hat.sh) |
-|[Install OpenCV 4 on Red Hat (C++ and Python)](https://www.learnopencv.com/install-opencv-4-on-red-hat/) | [Code](https://github.com/spmallick/learnopencv/blob/master/InstallScripts/installOpenCV-4-on-red-hat.sh) |
-|[Install OpenCV 4 on macOS (C++ and Python)](https://www.learnopencv.com/install-opencv-4-on-macos/) | [Code](https://github.com/spmallick/learnopencv/tree/master/InstallScripts/installOpenCV-4-macos.sh) |
-|[Install OpenCV 3.4.4 on Raspberry Pi](https://www.learnopencv.com/install-opencv-3-4-4-on-raspberry-pi/) | [Code](https://github.com/spmallick/learnopencv/blob/master/InstallScripts/installOpenCV-3-raspberry-pi.sh) |
-|[Install OpenCV 3.4.4 on macOS (C++ and Python)](https://www.learnopencv.com/install-opencv-3-4-4-on-macos/) | [Code](https://github.com/spmallick/learnopencv/blob/master/InstallScripts/installOpenCV-3-macos.sh) |
-|[OpenCV QR Code Scanner (C++ and Python)](https://www.learnopencv.com/opencv-qr-code-scanner-c-and-python/) | [Code](https://github.com/spmallick/learnopencv/tree/master/QRCode-OpenCV) |
-|[Install OpenCV 3.4.4 on Windows (C++ and Python)](https://www.learnopencv.com/install-opencv-3-4-4-on-windows/) | [Code](https://github.com/spmallick/learnopencv/tree/master/InstallScripts/Windows-3) |
-|[Install OpenCV 3.4.4 on Ubuntu 16.04 (C++ and Python)](https://www.learnopencv.com/install-opencv-3-4-4-on-ubuntu-16-04/) | [Code](https://github.com/spmallick/learnopencv/blob/master/InstallScripts/installOpenCV-3-on-Ubuntu-16-04.sh) |
-|[Install OpenCV 3.4.4 on Ubuntu 18.04 (C++ and Python)](https://www.learnopencv.com/install-opencv-3-4-4-on-ubuntu-18-04/) | [Code](https://github.com/spmallick/learnopencv/blob/master/InstallScripts/installOpenCV-3-on-Ubuntu-18-04.sh) |
-|[Universal Sentence Encoder](https://www.learnopencv.com/universal-sentence-encoder) | [Code](https://github.com/spmallick/learnopencv/blob/master/Universal-Sentence-Encoder) |
-|[Install OpenCV 4 on Raspberry Pi](https://www.learnopencv.com/install-opencv-4-on-raspberry-pi/) | [Code](https://github.com/spmallick/learnopencv/blob/master/InstallScripts/installOpenCV-4-raspberry-pi.sh) |
-|[Install OpenCV 4 on Windows (C++ and Python)](https://www.learnopencv.com/install-opencv-4-on-windows/) | [Code](https://github.com/spmallick/learnopencv/tree/master/InstallScripts/Windows-4) |
-|[Hand Keypoint Detection using Deep Learning and OpenCV](https://www.learnopencv.com/hand-keypoint-detection-using-deep-learning-and-opencv/) | [Code](https://github.com/spmallick/learnopencv/tree/master/HandPose)|
-|[Deep learning based Object Detection and Instance Segmentation using Mask R-CNN in OpenCV (Python / C++)](https://www.learnopencv.com/deep-learning-based-object-detection-and-instance-segmentation-using-mask-r-cnn-in-opencv-python-c/) | [Code](https://github.com/spmallick/learnopencv/tree/master/Mask-RCNN) |
-|[Install OpenCV 4 on Ubuntu 18.04 (C++ and Python)](https://www.learnopencv.com/install-opencv-4-on-ubuntu-18-04/) | [Code](https://github.com/spmallick/learnopencv/blob/master/InstallScripts/installOpenCV-4-on-Ubuntu-18-04.sh) |
-|[Install OpenCV 4 on Ubuntu 16.04 (C++ and Python)](https://www.learnopencv.com/install-opencv-4-on-ubuntu-16-04/) | [Code](https://github.com/spmallick/learnopencv/blob/master/InstallScripts/installOpenCV-4-on-Ubuntu-16-04.sh) |
-|[Multi-Person Pose Estimation in OpenCV using OpenPose](https://www.learnopencv.com/multi-person-pose-estimation-in-opencv-using-openpose/) | [Code](https://github.com/spmallick/learnopencv/tree/master/OpenPose-Multi-Person) |
-|[Heatmap for Logo Detection using OpenCV (Python)](https://www.learnopencv.com/heatmap-for-logo-detection-using-opencv-python/) | [Code](https://github.com/spmallick/learnopencv/tree/master/heatmap)|
-|[Deep Learning based Object Detection using YOLOv3 with OpenCV ( Python / C++ )](https://www.learnopencv.com/deep-learning-based-object-detection-using-yolov3-with-opencv-python-c/) | [Code](https://github.com/spmallick/learnopencv/tree/master/ObjectDetection-YOLO)|
-|[Convex Hull using OpenCV in Python and C++](https://www.learnopencv.com/convex-hull-using-opencv-in-python-and-c/) | [Code](https://github.com/spmallick/learnopencv/tree/master/ConvexHull)|
-|[MultiTracker : Multiple Object Tracking using OpenCV (C++/Python)](https://www.learnopencv.com/multitracker-multiple-object-tracking-using-opencv-c-python/) | [Code](https://github.com/spmallick/learnopencv/tree/master/MultiObjectTracker) |
-|[Convolutional Neural Network based Image Colorization using OpenCV](https://www.learnopencv.com/convolutional-neural-network-based-image-colorization-using-opencv/) | [Code](https://github.com/spmallick/learnopencv/tree/master/Colorization)|
-|[SVM using scikit-learn](https://www.learnopencv.com/svm-using-scikit-learn-in-python/)|[Code](https://github.com/spmallick/learnopencv/tree/master/SVM-using-Python)|
-|[GOTURN: Deep Learning based Object Tracking](https://www.learnopencv.com/goturn-deep-learning-based-object-tracking/) | [Code](https://github.com/spmallick/learnopencv/tree/master/GOTURN)|
-|[Find the Center of a Blob (Centroid) using OpenCV (C++/Python)](https://www.learnopencv.com/find-center-of-blob-centroid-using-opencv-cpp-python/) | [Code](https://github.com/spmallick/learnopencv/tree/master/CenterofBlob)|
-|[Support Vector Machines (SVM)](https://www.learnopencv.com/support-vector-machines-svm/)|[Code](https://github.com/spmallick/learnopencv/tree/master/SVM-using-Python)|
-|[Batch Normalization in Deep Networks](https://www.learnopencv.com/batch-normalization-in-deep-networks/) | [Code](https://github.com/spmallick/learnopencv/tree/master/BatchNormalization)|
-|[Deep Learning based Character Classification using Synthetic Dataset](https://www.learnopencv.com/deep-learning-character-classification-using-synthetic-dataset/) | [Code](https://github.com/spmallick/learnopencv/tree/master/CharClassification)|
-|[Image Quality Assessment : BRISQUE](https://www.learnopencv.com/image-quality-assessment-brisque/)| [Code](https://github.com/spmallick/learnopencv/tree/master/ImageMetrics)|
-|[Understanding AlexNet](https://www.learnopencv.com/understanding-alexnet/)|
-|[Deep Learning based Text Recognition (OCR) using Tesseract and OpenCV](https://www.learnopencv.com/deep-learning-based-text-recognition-ocr-using-tesseract-and-opencv/)| [Code](https://github.com/spmallick/learnopencv/tree/master/OCR)|
-|[Deep Learning based Human Pose Estimation using OpenCV ( C++ / Python )](https://www.learnopencv.com/deep-learning-based-human-pose-estimation-using-opencv-cpp-python/)|[ Code](https://github.com/spmallick/learnopencv/tree/master/OpenPose)|
-|[Number of Parameters and Tensor Sizes in a Convolutional Neural Network (CNN)](https://www.learnopencv.com/number-of-parameters-and-tensor-sizes-in-convolutional-neural-network/)| |
-|[How to convert your OpenCV C++ code into a Python module](https://www.learnopencv.com/how-to-convert-your-opencv-c-code-into-a-python-module/)|[ Code](https://github.com/spmallick/learnopencv/tree/master/pymodule)|
-|[CV4Faces : Best Project Award 2018](https://www.learnopencv.com/cv4faces-best-project-award-2018/)| |
-|[Facemark : Facial Landmark Detection using OpenCV](https://www.learnopencv.com/facemark-facial-landmark-detection-using-opencv/)|[ Code](https://github.com/spmallick/learnopencv/tree/master/FacialLandmarkDetection)|
-|[Image Alignment (Feature Based) using OpenCV (C++/Python)](https://www.learnopencv.com/image-alignment-feature-based-using-opencv-c-python/)| [Code](https://github.com/spmallick/learnopencv/tree/master/ImageAlignment-FeatureBased)|
-|[Barcode and QR code Scanner using ZBar and OpenCV](https://www.learnopencv.com/barcode-and-qr-code-scanner-using-zbar-and-opencv/)| [Code](https://github.com/spmallick/learnopencv/tree/master/barcode-QRcodeScanner)|
-|[Keras Tutorial : Fine-tuning using pre-trained models](https://www.learnopencv.com/keras-tutorial-fine-tuning-using-pre-trained-models/)| [Code](https://github.com/spmallick/learnopencv/tree/master/Keras-Fine-Tuning)|
-|[OpenCV Transparent API](https://www.learnopencv.com/opencv-transparent-api/)| |
-|[Face Reconstruction using EigenFaces (C++/Python)](https://www.learnopencv.com/face-reconstruction-using-eigenfaces-cpp-python/)|[Code](https://github.com/spmallick/learnopencv/tree/master/ReconstructFaceUsingEigenFaces) |
-|[Eigenface using OpenCV (C++/Python)](https://www.learnopencv.com/eigenface-using-opencv-c-python/)| [Code](https://github.com/spmallick/learnopencv/tree/master/EigenFace)|
-|[Principal Component Analysis](https://www.learnopencv.com/principal-component-analysis/)| |
-|[Keras Tutorial : Transfer Learning using pre-trained models](https://www.learnopencv.com/keras-tutorial-transfer-learning-using-pre-trained-models/)| [Code](https://github.com/spmallick/learnopencv/tree/master/Keras-Transfer-Learning) |
-|[Keras Tutorial : Using pre-trained Imagenet models](https://www.learnopencv.com/keras-tutorial-using-pre-trained-imagenet-models/)| [Code](https://github.com/spmallick/learnopencv/tree/master/Keras-ImageNet-Models) |
-|[Technical Aspects of a Digital SLR](https://www.learnopencv.com/technical-aspects-of-a-digital-slr/) | |
-|[Using Harry Potter interactive wand with OpenCV to create magic](https://www.learnopencv.com/using-harry-potter-interactive-wand-with-opencv-to-create-magic/)| |
-|[Install OpenCV 3 and Dlib on Windows ( Python only )](https://www.learnopencv.com/install-opencv-3-and-dlib-on-windows-python-only/)| |
-|[Image Classification using Convolutional Neural Networks in Keras](https://www.learnopencv.com/image-classification-using-convolutional-neural-networks-in-keras) | [Code](https://github.com/spmallick/learnopencv/tree/master/KerasCNN-CIFAR)|
-|[Understanding Autoencoders using Tensorflow (Python)](https://www.learnopencv.com/understanding-autoencoders-using-tensorflow-python/) | [Code](https://github.com/spmallick/learnopencv/tree/master/DenoisingAutoencoder)|
-|[Best Project Award : Computer Vision for Faces](https://www.learnopencv.com/best-project-award-computer-vision-for-faces/) | |
-|[Understanding Activation Functions in Deep Learning](https://www.learnopencv.com/understanding-activation-functions-in-deep-learning/) | |
-|[Image Classification using Feedforward Neural Network in Keras](https://www.learnopencv.com/image-classification-using-feedforward-neural-network-in-keras/) | [Code](https://github.com/spmallick/learnopencv/tree/master/KerasMLP-MNIST)|
-|[Exposure Fusion using OpenCV (C++/Python)](https://www.learnopencv.com/exposure-fusion-using-opencv-cpp-python/) | [Code](https://github.com/spmallick/learnopencv/tree/master/ExposureFusion)|
-|[Understanding Feedforward Neural Networks](https://www.learnopencv.com/understanding-feedforward-neural-networks/) | |
-|[High Dynamic Range (HDR) Imaging using OpenCV (C++/Python)](http://www.learnopencv.com/high-dynamic-range-hdr-imaging-using-opencv-cpp-python) | [Code](https://github.com/spmallick/learnopencv/tree/master/hdr)|
-|[Deep learning using Keras – The Basics](http://www.learnopencv.com/deep-learning-using-keras-the-basics) | [Code](https://github.com/spmallick/learnopencv/tree/master/keras-linear-regression)|
-|[Selective Search for Object Detection (C++ / Python)](http://www.learnopencv.com/selective-search-for-object-detection-cpp-python/) | [Code](https://github.com/spmallick/learnopencv/tree/master/SelectiveSearch) |
-|[Installing Deep Learning Frameworks on Ubuntu with CUDA support](http://www.learnopencv.com/installing-deep-learning-frameworks-on-ubuntu-with-cuda-support/) | |
-|[Parallel Pixel Access in OpenCV using forEach](http://www.learnopencv.com/parallel-pixel-access-in-opencv-using-foreach/) | [Code](https://github.com/spmallick/learnopencv/tree/master/forEach) |
-|[cvui: A GUI lib built on top of OpenCV drawing primitives](http://www.learnopencv.com/cvui-gui-lib-built-on-top-of-opencv-drawing-primitives/) | [Code](https://github.com/spmallick/learnopencv/tree/master/UI-cvui) |
-|[Install Dlib on Windows](http://www.learnopencv.com/install-dlib-on-windows/) | |
-|[Install Dlib on Ubuntu](http://www.learnopencv.com/install-dlib-on-ubuntu/) | |
-|[Install OpenCV3 on Ubuntu](http://www.learnopencv.com/install-opencv3-on-ubuntu/) | |
-|[Read, Write and Display a video using OpenCV ( C++/ Python )](http://www.learnopencv.com/read-write-and-display-a-video-using-opencv-cpp-python/) | [Code](https://github.com/spmallick/learnopencv/tree/master/VideoReadWriteDisplay) |
-|[Install Dlib on MacOS](http://www.learnopencv.com/install-dlib-on-macos/) | |
-|[Install OpenCV 3 on MacOS](http://www.learnopencv.com/install-opencv3-on-macos/) | |
-|[Install OpenCV 3 on Windows](http://www.learnopencv.com/install-opencv3-on-windows/) | |
-|[Get OpenCV Build Information ( getBuildInformation )](http://www.learnopencv.com/get-opencv-build-information-getbuildinformation/) | |
-|[Color spaces in OpenCV (C++ / Python)](http://www.learnopencv.com/color-spaces-in-opencv-cpp-python/) | [Code](https://github.com/spmallick/learnopencv/tree/master/ColorSpaces)|
-|[Neural Networks : A 30,000 Feet View for Beginners](http://www.learnopencv.com/neural-networks-a-30000-feet-view-for-beginners/) | |
-|[Alpha Blending using OpenCV (C++ / Python)](http://www.learnopencv.com/alpha-blending-using-opencv-cpp-python/) | [Code](https://github.com/spmallick/learnopencv/tree/master/AlphaBlending) |
-|[User stories : How readers of this blog are applying their knowledge to build applications](http://www.learnopencv.com/user-stories-how-readers-of-this-blog-are-applying-their-knowledge-to-build-applications/) | |
-|[How to select a bounding box ( ROI ) in OpenCV (C++/Python) ?](http://www.learnopencv.com/how-to-select-a-bounding-box-roi-in-opencv-cpp-python/) | |
-|[Automatic Red Eye Remover using OpenCV (C++ / Python)](http://www.learnopencv.com/automatic-red-eye-remover-using-opencv-cpp-python/) | [Code](https://github.com/spmallick/learnopencv/tree/master/RedEyeRemover) |
-|[Bias-Variance Tradeoff in Machine Learning](http://www.learnopencv.com/bias-variance-tradeoff-in-machine-learning/) | |
-|[Embedded Computer Vision: Which device should you choose?](http://www.learnopencv.com/embedded-computer-vision-which-device-should-you-choose/) | |
-|[Object Tracking using OpenCV (C++/Python)](http://www.learnopencv.com/object-tracking-using-opencv-cpp-python/) | [Code](https://github.com/spmallick/learnopencv/tree/master/tracking) |
-|[Handwritten Digits Classification : An OpenCV ( C++ / Python ) Tutorial](http://www.learnopencv.com/handwritten-digits-classification-an-opencv-c-python-tutorial/) | [Code](https://github.com/spmallick/learnopencv/tree/master/digits-classification) |
-|[Training a better Haar and LBP cascade based Eye Detector using OpenCV](http://www.learnopencv.com/training-better-haar-lbp-cascade-eye-detector-opencv/) | |
-|[Deep Learning Book Gift Recipients](http://www.learnopencv.com/deep-learning-book-gift-recipients/) | |
-|[Minified OpenCV Haar and LBP Cascades](http://www.learnopencv.com/minified-opencv-haar-and-lbp-cascades/) | [Code](https://github.com/spmallick/learnopencv/tree/master/ninjaEyeDetector)|
-|[Deep Learning Book Gift](http://www.learnopencv.com/deep-learning-book-gift/) | |
-|[Histogram of Oriented Gradients](http://www.learnopencv.com/histogram-of-oriented-gradients/) | |
-|[Image Recognition and Object Detection : Part 1](http://www.learnopencv.com/image-recognition-and-object-detection-part1/) | |
-|[Head Pose Estimation using OpenCV and Dlib](http://www.learnopencv.com/head-pose-estimation-using-opencv-and-dlib/) | [Code](https://github.com/spmallick/learnopencv/tree/master/HeadPose) |
-|[Live CV : A Computer Vision Coding Application](http://www.learnopencv.com/live-cv/) | |
-|[Approximate Focal Length for Webcams and Cell Phone Cameras](http://www.learnopencv.com/approximate-focal-length-for-webcams-and-cell-phone-cameras/) | |
-|[Configuring Qt for OpenCV on OSX](http://www.learnopencv.com/configuring-qt-for-opencv-on-osx/) | [Code](https://github.com/spmallick/learnopencv/tree/master/qt-test) |
-|[Rotation Matrix To Euler Angles](http://www.learnopencv.com/rotation-matrix-to-euler-angles/) | [Code](https://github.com/spmallick/learnopencv/tree/master/RotationMatrixToEulerAngles) |
-|[Speeding up Dlib’s Facial Landmark Detector](http://www.learnopencv.com/speeding-up-dlib-facial-landmark-detector/) | |
-|[Warp one triangle to another using OpenCV ( C++ / Python )](http://www.learnopencv.com/warp-one-triangle-to-another-using-opencv-c-python/) | [Code](https://github.com/spmallick/learnopencv/tree/master/WarpTriangle) |
-|[Average Face : OpenCV ( C++ / Python ) Tutorial](http://www.learnopencv.com/average-face-opencv-c-python-tutorial/) | [Code](https://github.com/spmallick/learnopencv/tree/master/FaceAverage) |
-|[Face Swap using OpenCV ( C++ / Python )](http://www.learnopencv.com/face-swap-using-opencv-c-python/) | [Code](https://github.com/spmallick/learnopencv/tree/master/FaceSwap) |
-|[Face Morph Using OpenCV — C++ / Python](http://www.learnopencv.com/face-morph-using-opencv-cpp-python/) | [Code](https://github.com/spmallick/learnopencv/tree/master/FaceMorph) |
-|[Deep Learning Example using NVIDIA DIGITS 3 on EC2](http://www.learnopencv.com/deep-learning-example-using-nvidia-digits-3-on-ec2/) | |
-|[NVIDIA DIGITS 3 on EC2](http://www.learnopencv.com/nvidia-digits-3-on-ec2/) | |
-|[Homography Examples using OpenCV ( Python / C ++ )](http://www.learnopencv.com/homography-examples-using-opencv-python-c/) | [Code](https://github.com/spmallick/learnopencv/tree/master/Homography) |
-|[Filling holes in an image using OpenCV ( Python / C++ )](http://www.learnopencv.com/filling-holes-in-an-image-using-opencv-python-c/) | [Code](https://github.com/spmallick/learnopencv/tree/master/Holes) |
-|[How to find frame rate or frames per second (fps) in OpenCV ( Python / C++ ) ?](http://www.learnopencv.com/how-to-find-frame-rate-or-frames-per-second-fps-in-opencv-python-cpp/) | [Code](https://github.com/spmallick/learnopencv/tree/master/FPS) |
-|[Delaunay Triangulation and Voronoi Diagram using OpenCV ( C++ / Python) ](http://www.learnopencv.com/delaunay-triangulation-and-voronoi-diagram-using-opencv-c-python/) | [Code](https://github.com/spmallick/learnopencv/tree/master/Delaunay) |
-|[OpenCV (C++ vs Python) vs MATLAB for Computer Vision](http://www.learnopencv.com/opencv-c-vs-python-vs-matlab-for-computer-vision/) | |
-|[Facial Landmark Detection](http://www.learnopencv.com/facial-landmark-detection/) | |
-|[Why does OpenCV use BGR color format ?](http://www.learnopencv.com/why-does-opencv-use-bgr-color-format/) | |
-|[Computer Vision for Predicting Facial Attractiveness](http://www.learnopencv.com/computer-vision-for-predicting-facial-attractiveness/) | [Code](https://github.com/spmallick/learnopencv/tree/master/FacialAttractiveness) |
-|[applyColorMap for pseudocoloring in OpenCV ( C++ / Python )](http://www.learnopencv.com/applycolormap-for-pseudocoloring-in-opencv-c-python/) | [Code](https://github.com/spmallick/learnopencv/tree/master/Colormap) |
-|[Image Alignment (ECC) in OpenCV ( C++ / Python )](http://www.learnopencv.com/image-alignment-ecc-in-opencv-c-python/) | [Code](https://github.com/spmallick/learnopencv/tree/master/ImageAlignment) |
-|[How to find OpenCV version in Python and C++ ?](http://www.learnopencv.com/how-to-find-opencv-version-python-cpp/) | |
-|[Baidu banned from ILSVRC 2015](http://www.learnopencv.com/baidu-banned-from-ilsvrc-2015/) | |
-|[OpenCV Transparent API](http://www.learnopencv.com/opencv-transparent-api/) | |
-|[How Computer Vision Solved the Greatest Soccer Mystery of All Time](http://www.learnopencv.com/how-computer-vision-solved-the-greatest-soccer-mystery-of-all-times/) | |
-|[Embedded Vision Summit 2015](http://www.learnopencv.com/embedded-vision-summit-2015/) | |
-|[Read an Image in OpenCV ( Python, C++ )](http://www.learnopencv.com/read-an-image-in-opencv-python-cpp/) | [Code](https://github.com/spmallick/learnopencv/tree/master/imread) |
-|[Non-Photorealistic Rendering using OpenCV ( Python, C++ )](http://www.learnopencv.com/non-photorealistic-rendering-using-opencv-python-c/) | [Code](https://github.com/spmallick/learnopencv/tree/master/NonPhotorealisticRendering) |
-|[Seamless Cloning using OpenCV ( Python , C++ )](http://www.learnopencv.com/seamless-cloning-using-opencv-python-cpp/) | [Code](https://github.com/spmallick/learnopencv/tree/master/SeamlessCloning) |
-|[OpenCV Threshold ( Python , C++ )](http://www.learnopencv.com/opencv-threshold-python-cpp/) | [Code](https://github.com/spmallick/learnopencv/tree/master/Threshold) |
-|[Blob Detection Using OpenCV ( Python, C++ )](http://www.learnopencv.com/blob-detection-using-opencv-python-c/) | [Code](https://github.com/spmallick/learnopencv/tree/master/BlobDetector) |
-|[Turn your OpenCV Code into a Web API in under 10 minutes — Part 1](http://www.learnopencv.com/turn-your-opencv-Code-into-a-web-api-in-under-10-minutes-part-1/) | |
-|[How to compile OpenCV sample Code ?](http://www.learnopencv.com/how-to-compile-opencv-sample-Code/) | |
-|[Install OpenCV 3 on Yosemite ( OSX 10.10.x )](http://www.learnopencv.com/install-opencv-3-on-yosemite-osx-10-10-x/) | |