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/) | |