{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"!pip install ../input/leekunhee-mask-rcnn/Mask_RCNN-master\n\n###coco-weights\n!wget https://github.com/matterport/Mask_RCNN/releases/download/v2.0/mask_rcnn_coco.h5","metadata":{"_kg_hide-output":true,"execution":{"iopub.status.busy":"2021-12-01T15:23:49.58198Z","iopub.execute_input":"2021-12-01T15:23:49.582367Z","iopub.status.idle":"2021-12-01T15:24:09.489617Z","shell.execute_reply.started":"2021-12-01T15:23:49.582339Z","shell.execute_reply":"2021-12-01T15:24:09.488821Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#Full credit goes to this repository--->https://www.kaggle.com/susnato/sartorius-segmentation-mask-rcnn-tf-train\n#https://machinelearningmastery.com/how-to-train-an-object-detection-model-with-keras/","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"**Installing the required dependencies**","metadata":{}},{"cell_type":"code","source":"!pip install keras==2.4.0\n!pip install tensorflow==2.4.0\n!pip install -U scikit-image==0.16.2","metadata":{"execution":{"iopub.status.busy":"2021-12-01T15:24:09.49149Z","iopub.execute_input":"2021-12-01T15:24:09.491712Z","iopub.status.idle":"2021-12-01T15:27:28.170366Z","shell.execute_reply.started":"2021-12-01T15:24:09.491687Z","shell.execute_reply":"2021-12-01T15:27:28.169419Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"**<h3><font color='green'>Imports</h3>**","metadata":{}},{"cell_type":"code","source":"import os\nimport cv2\nimport keras\nimport shutil\nimport numpy as np\nimport pandas as pd\nimport tensorflow as tf\nfrom mrcnn import config, utils\nimport matplotlib.pyplot as plt \nfrom numpy import zeros, asarray\nfrom mrcnn import model as modellib\nimport albumentations as A\nfrom tqdm import tqdm","metadata":{"execution":{"iopub.status.busy":"2021-12-01T15:27:28.173042Z","iopub.execute_input":"2021-12-01T15:27:28.173742Z","iopub.status.idle":"2021-12-01T15:27:31.769212Z","shell.execute_reply.started":"2021-12-01T15:27:28.173698Z","shell.execute_reply":"2021-12-01T15:27:31.76842Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"len(os.listdir('../input/sartorius-cell-instance-segmentation/train'))","metadata":{"execution":{"iopub.status.busy":"2021-12-01T15:27:31.771214Z","iopub.execute_input":"2021-12-01T15:27:31.77142Z","iopub.status.idle":"2021-12-01T15:27:31.849621Z","shell.execute_reply.started":"2021-12-01T15:27:31.771395Z","shell.execute_reply":"2021-12-01T15:27:31.848856Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"**Dividing the images into test and train**","metadata":{}},{"cell_type":"code","source":"os.makedirs('./dataset/train',exist_ok=True)\nos.makedirs('./dataset/val',exist_ok=True)","metadata":{"execution":{"iopub.status.busy":"2021-12-01T15:27:31.850738Z","iopub.execute_input":"2021-12-01T15:27:31.85102Z","iopub.status.idle":"2021-12-01T15:27:31.85664Z","shell.execute_reply.started":"2021-12-01T15:27:31.850982Z","shell.execute_reply":"2021-12-01T15:27:31.855864Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"img_name_lst=os.listdir('../input/sartorius-cell-instance-segmentation/train')\n#img_name_lst.remove('.csv')\n#img_name_lst.remove('_semi_supervised')\nimg_tr=img_name_lst[:int(len(img_name_lst)*0.8)]\nimg_te=img_name_lst[int(len(img_name_lst)*0.8):]\nfor img in img_tr:\n  shutil.copyfile('../input/sartorius-cell-instance-segmentation/train/'+ img,'./dataset/train/{}'.format(img))\nfor img in img_te:\n  shutil.copyfile('../input/sartorius-cell-instance-segmentation/train/'+ img,'./dataset/val/{}'.format(img))","metadata":{"execution":{"iopub.status.busy":"2021-12-01T15:27:31.857746Z","iopub.execute_input":"2021-12-01T15:27:31.858506Z","iopub.status.idle":"2021-12-01T15:27:36.057515Z","shell.execute_reply.started":"2021-12-01T15:27:31.858468Z","shell.execute_reply":"2021-12-01T15:27:36.056694Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(len(os.listdir('./dataset/train')))\nprint(len(os.listdir('./dataset/val')))","metadata":{"execution":{"iopub.status.busy":"2021-12-01T15:27:36.058718Z","iopub.execute_input":"2021-12-01T15:27:36.05914Z","iopub.status.idle":"2021-12-01T15:27:36.064796Z","shell.execute_reply.started":"2021-12-01T15:27:36.059105Z","shell.execute_reply":"2021-12-01T15:27:36.064089Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"**Defining our configuration for training**","metadata":{}},{"cell_type":"code","source":"class CustomConfig(config.Config):\n  IMAGES_PER_GPU=1\n  NUM_CLASSES=1+1\n  NAME='CustomConfig'\n  STEPS_PER_EPOCH=484\n  VALIDATION_STEPS=122\n  BATCH_SIZE=1\n  USE_MINI_MASK=False\n  BACKBONE='resnet101'\nsartorius_model_cfg=CustomConfig()\nsartorius_model_cfg.display()","metadata":{"execution":{"iopub.status.busy":"2021-12-01T15:27:36.065865Z","iopub.execute_input":"2021-12-01T15:27:36.066584Z","iopub.status.idle":"2021-12-01T15:27:36.086503Z","shell.execute_reply.started":"2021-12-01T15:27:36.066546Z","shell.execute_reply":"2021-12-01T15:27:36.085715Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"**Here we have to defining our own custom dataset for training**\n\n**We also have to define a function which would return the mask for image id along with the class id**","metadata":{}},{"cell_type":"code","source":"p=1\ntrain_augment_pipeline=A.Compose([A.RandomScale((0.5,1.5)),\n                                 A.Flip(p=p),\n                                 A.Rotate(limit=45,p=1),\n                                 A.RandomRotate90(p=p),\n                                 A.Resize(520,704)])","metadata":{"execution":{"iopub.status.busy":"2021-12-01T15:27:36.087618Z","iopub.execute_input":"2021-12-01T15:27:36.088015Z","iopub.status.idle":"2021-12-01T15:27:36.093383Z","shell.execute_reply.started":"2021-12-01T15:27:36.08798Z","shell.execute_reply":"2021-12-01T15:27:36.09241Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class CustomDataset(utils.Dataset):\n    \n  def __init__(self,transform=None):\n    super().__init__()\n    self.transform=transform\n    \n  def load_custom(self,dataset_dir,is_train=True):\n    self.add_class('dataset',1,'cell')\n\n    if is_train:\n      img_dir=dataset_dir+'/train'\n\n    else:\n      img_dir=dataset_dir+'/val'\n    \n    for filename in os.listdir(img_dir):\n      img_path=img_dir+'/'+filename\n      image_id=filename.split('.')[0]\n\n      self.add_image('dataset',image_id,img_path,annotation=None)\n\n  def load_mask(self,image_id):\n    info=self.image_info[image_id]\n    train_df=pd.read_csv('../input/sartorius-cell-instance-segmentation/train.csv')\n    annot_values=train_df[train_df['id']==info['id']]['annotation'].values\n    cell_type=train_df[train_df['id']==info['id']]['cell_type'].values\n    mask=np.zeros([520*704,len(annot_values)],dtype=np.uint8)\n    image_arr=cv2.imread('../input/sartorius-cell-instance-segmentation/train/{}.png'.format(info['id']))\n    image=cv2.cvtColor(image_arr,cv2.COLOR_BGR2RGB)\n    image=image.astype(np.float32)\n    masks=[]\n\n    class_ids=[]\n    #Here we are decoding the run length encoded sequence\n    for instance_count,rle in enumerate(annot_values):\n      ind_mask=np.zeros([520*704],dtype=np.uint8)\n      rle_encode=rle.split(' ')\n      run_start=np.array([asarray(rle_encode[i],dtype=int) for i in range(len(rle_encode)) if i%2==0])\n      run_length=np.array([asarray(rle_encode[i],dtype=int) for i in range(len(rle_encode)) if i%2==1])\n      run_end=run_start + run_length\n      \n      for start,end in zip(run_start,run_end):\n        mask[start:end,instance_count]=1\n        ind_mask[start:end]=1\n      ind_mask=ind_mask.reshape(520,704) \n      masks.append(ind_mask)#getting list of individual masks for an image\n     \n      class_ids.append(self.class_names.index('cell'))\n\n    if self.transform is not None:\n\n\n        transformed=self.transform(image=image,masks=masks)#passing list of masks for image\n        final_mask=transformed['masks']\n        final_mask=np.concatenate(np.expand_dims(final_mask,axis=3),axis=-1)\n        a=final_mask.reshape((520*704,final_mask.shape[-1]))\n        if np.any(a,axis=0)>1:\n            print('Invalid Mask Found')\n        return final_mask,asarray(class_ids,dtype=np.int32)\n        \n        \n    else:\n\n        mask=np.reshape(mask,newshape=(520,704,len(annot_values)))\n        return mask,asarray(class_ids,dtype=np.int32)","metadata":{"execution":{"iopub.status.busy":"2021-12-01T15:30:02.566203Z","iopub.execute_input":"2021-12-01T15:30:02.56697Z","iopub.status.idle":"2021-12-01T15:30:02.587149Z","shell.execute_reply.started":"2021-12-01T15:30:02.566909Z","shell.execute_reply":"2021-12-01T15:30:02.586276Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"**Defining a custom callback function which would calculate the mean average precision**","metadata":{}},{"cell_type":"code","source":"class mAPcallback(tf.keras.callbacks.Callback):\n\n  def __init__(self,dataset,tr_model,cfg,infer_model):\n    super().__init__()\n    self.dataset=dataset\n    self.config=cfg\n    self.infer_model=infer_model\n    self.tr_model=tr_model\n\n  def on_epoch_begin(self,epoch,logs=None):\n    print('Training Started for epoch {}'.format(epoch+1))\n\n  def on_train_begin(self,logs=None):\n    self.map_score=[]\n\n  def on_epoch_end(self,epoch,logs=None):\n    print('Calculating mAP for epoch {} ......'.format(epoch+1))\n    weights_path=self.tr_model.find_last()\n    print('Loading weights {}'.format(weights_path))\n    #weights_path='./train_model/' + os.listdir('./train_model/'+os.listdir('./train_model')[0]) + os.listdir('./train_model/'+os.listdir('./train_model')[0])[-1]\n    self.infer_model.load_weights(weights_path,by_name=True)\n    for image_id in tqdm(self.dataset.image_ids):\n      image, image_meta, gt_class_id, gt_bbox, gt_mask=modellib.load_image_gt(self.dataset,self.infer_model.config,image_id)\n      prediction=self.infer_model.detect([image],verbose=0)\n      r=prediction[0]\n      AP_Range=utils.compute_ap_range(gt_bbox,gt_class_id,gt_mask,r['rois'],r['class_ids'], r['scores'], r['masks'], verbose=0)\n      self.map_score.append(AP_Range)\n\n    print('Mean Average Precision Score is {}'.format(np.mean(np.array(self.map_score))))","metadata":{"execution":{"iopub.status.busy":"2021-12-01T15:30:03.344555Z","iopub.execute_input":"2021-12-01T15:30:03.345234Z","iopub.status.idle":"2021-12-01T15:30:03.354991Z","shell.execute_reply.started":"2021-12-01T15:30:03.345195Z","shell.execute_reply":"2021-12-01T15:30:03.354261Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_dataset=CustomDataset(transform=train_augment_pipeline)\ntrain_dataset.load_custom(dataset_dir='./dataset',is_train=True)\ntrain_dataset.prepare()","metadata":{"execution":{"iopub.status.busy":"2021-12-01T15:30:03.658072Z","iopub.execute_input":"2021-12-01T15:30:03.658583Z","iopub.status.idle":"2021-12-01T15:30:03.665424Z","shell.execute_reply.started":"2021-12-01T15:30:03.658545Z","shell.execute_reply":"2021-12-01T15:30:03.664468Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"**Preparing the dataset for training our model**","metadata":{}},{"cell_type":"code","source":"val_dataset=CustomDataset(transform=None)\nval_dataset.load_custom(dataset_dir='./dataset',is_train=False)\nval_dataset.prepare()","metadata":{"execution":{"iopub.status.busy":"2021-12-01T15:30:04.265619Z","iopub.execute_input":"2021-12-01T15:30:04.265885Z","iopub.status.idle":"2021-12-01T15:30:04.270893Z","shell.execute_reply.started":"2021-12-01T15:30:04.265855Z","shell.execute_reply":"2021-12-01T15:30:04.270188Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"os.makedirs('./train_model',exist_ok=True)\nos.makedirs('./validation_model',exist_ok=True)","metadata":{"execution":{"iopub.status.busy":"2021-12-01T15:30:04.551108Z","iopub.execute_input":"2021-12-01T15:30:04.551654Z","iopub.status.idle":"2021-12-01T15:30:04.55519Z","shell.execute_reply.started":"2021-12-01T15:30:04.551622Z","shell.execute_reply":"2021-12-01T15:30:04.554521Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_model=modellib.MaskRCNN(mode='training',config=sartorius_model_cfg,model_dir='./train_model')\nvalidation_model=modellib.MaskRCNN(mode='inference',config=sartorius_model_cfg,model_dir='./validation_model')\ntrain_model.load_weights('./mask_rcnn_coco.h5', by_name=True, exclude=[\"mrcnn_class_logits\", \"mrcnn_bbox_fc\",  \"mrcnn_bbox\", \"mrcnn_mask\"])","metadata":{"execution":{"iopub.status.busy":"2021-12-01T15:30:04.903219Z","iopub.execute_input":"2021-12-01T15:30:04.904022Z","iopub.status.idle":"2021-12-01T15:30:22.997658Z","shell.execute_reply.started":"2021-12-01T15:30:04.903983Z","shell.execute_reply":"2021-12-01T15:30:22.996826Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"map_callback=mAPcallback(val_dataset,train_model,sartorius_model_cfg,validation_model)","metadata":{"execution":{"iopub.status.busy":"2021-12-01T15:30:22.999573Z","iopub.execute_input":"2021-12-01T15:30:22.999866Z","iopub.status.idle":"2021-12-01T15:30:23.005288Z","shell.execute_reply.started":"2021-12-01T15:30:22.999828Z","shell.execute_reply":"2021-12-01T15:30:23.004071Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_model.train(train_dataset,val_dataset,learning_rate=sartorius_model_cfg.LEARNING_RATE,epochs=1,layers='heads',custom_callbacks=[map_callback])","metadata":{"execution":{"iopub.status.busy":"2021-12-01T15:30:23.00723Z","iopub.execute_input":"2021-12-01T15:30:23.007631Z","iopub.status.idle":"2021-12-01T15:32:08.033358Z","shell.execute_reply.started":"2021-12-01T15:30:23.007583Z","shell.execute_reply":"2021-12-01T15:32:08.032202Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"**<h3>references</h3>**\nref:- https://github.com/leekunhee/Mask_RCNN","metadata":{}}]}