{"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":"import torch, torchvision\nprint(torch.__version__, torch.cuda.is_available())\n","metadata":{"execution":{"iopub.status.busy":"2022-01-02T16:14:05.223179Z","iopub.execute_input":"2022-01-02T16:14:05.223526Z","iopub.status.idle":"2022-01-02T16:14:06.991029Z","shell.execute_reply.started":"2022-01-02T16:14:05.223423Z","shell.execute_reply":"2022-01-02T16:14:06.990261Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# cloning Detectron2","metadata":{}},{"cell_type":"code","source":"!python -m pip install 'git+https://github.com/facebookresearch/detectron2.git'     ","metadata":{"execution":{"iopub.status.busy":"2022-01-02T16:14:06.992758Z","iopub.execute_input":"2022-01-02T16:14:06.993019Z","iopub.status.idle":"2022-01-02T16:17:05.851044Z","shell.execute_reply.started":"2022-01-02T16:14:06.992986Z","shell.execute_reply":"2022-01-02T16:17:05.850032Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# imports\ncfg - choosing what model and dataset to refer.\n\nMetadata - for adding segmentatin classes.\n\nVisualizer - for plotting annotations above an image.\n\nmodel_zoo - colection of nn models for different purposes.\n","metadata":{}},{"cell_type":"code","source":"import csv\nimport cv2\nimport os\nimport random\nimport string\n\nfrom pathlib import Path\nimport matplotlib.pyplot as plt\nimport numpy as np\n\nimport detectron2\nfrom detectron2.engine import DefaultPredictor, DefaultTrainer\nfrom detectron2.config import get_cfg\nfrom detectron2.data import MetadataCatalog, DatasetCatalog\nfrom detectron2.utils.visualizer import ColorMode, Visualizer\nfrom detectron2 import model_zoo\nfrom detectron2.data.datasets import register_coco_instances\nfrom detectron2.utils.logger import setup_logger\n\nsetup_logger()\n","metadata":{"execution":{"iopub.status.busy":"2022-01-02T16:17:05.860017Z","iopub.execute_input":"2022-01-02T16:17:05.863137Z","iopub.status.idle":"2022-01-02T16:17:06.503254Z","shell.execute_reply.started":"2022-01-02T16:17:05.863086Z","shell.execute_reply":"2022-01-02T16:17:06.502556Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Data formating\nwe are feeding new dataset to an exsisting COCO dataset in Detectron2.\n\nThe COCO dataset is formatted in JSON and is a collection of\n\n* “info”\n* “licenses”\n* “images”\n* “annotations”\n* “categories” \n* “segment info” for Panoptic annotations","metadata":{}},{"cell_type":"code","source":"dataDir=Path('../input/sartorius-cell-instance-segmentation')\nids, masks=[],[]\n#test_names = (dataDir/'test').ls()","metadata":{"execution":{"iopub.status.busy":"2022-01-02T16:17:06.505231Z","iopub.execute_input":"2022-01-02T16:17:06.505625Z","iopub.status.idle":"2022-01-02T16:17:06.510425Z","shell.execute_reply.started":"2022-01-02T16:17:06.505587Z","shell.execute_reply":"2022-01-02T16:17:06.509387Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Register new dataset \n* fidding our sartorius dataset into coco-dataset.\n* crossvalidationfold5 is a directory of json files that are in a compatible format for Detectron2\n* access to our new dataset throw COCO (i.e dataset_dicts_train/valid , metadata_train)\n","metadata":{}},{"cell_type":"code","source":"if 'my_dataset_train' in DatasetCatalog.list():\n    DatasetCatalog.remove('my_dataset_train')\n\nif \"my_dataset_val\" in DatasetCatalog.list():\n    DatasetCatalog.remove(\"my_dataset_val\")\n\nregister_coco_instances('my_dataset_train', {}, \"../input/crossvalidationfold5/coco_cell_train_fold3.json\", dataDir)\nregister_coco_instances(\"my_dataset_val\", {}, \"../input/crossvalidationfold5/coco_cell_valid_fold3.json\", dataDir) \n\ndataset_dicts_train = DatasetCatalog.get(\"my_dataset_train\")\ndataset_dicts_valid = DatasetCatalog.get(\"my_dataset_val\")\nmetadata_train = MetadataCatalog.get(\"my_dataset_train\")\n","metadata":{"execution":{"iopub.status.busy":"2022-01-02T16:17:06.511818Z","iopub.execute_input":"2022-01-02T16:17:06.512446Z","iopub.status.idle":"2022-01-02T16:17:10.796893Z","shell.execute_reply.started":"2022-01-02T16:17:06.512408Z","shell.execute_reply":"2022-01-02T16:17:10.796154Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Encode - Decode\n**encoding RLE - a matrix mask to a tring:**\n   * img: numpy array, 1 - mask, 0 - background\n   * Returns run length as string formated\n    \n**decoding RLE - a tring to a mask matrix:**\n   * mask_rle: run-length as string formated (start length)\n   * shape: (height,width) of array to return \n   * Returns numpy array, 1 - mask, 0 - background","metadata":{}},{"cell_type":"code","source":"def rle_encode(img):\n    pixels = img.flatten()\n    pixels = np.concatenate([[0], pixels, [0]])\n    \n    runs = np.where(pixels[1:] != pixels[:-1])[0] + 1\n    print(runs)\n    runs[1::2] -= runs[::2]\n    print(runs)\n    return ' '.join(str(x) for x in runs)\n\ndef rle_decode(mask_rle, shape=(520, 704)):\n    s = mask_rle.split()\n    starts, lengths = [np.asarray(x, dtype=int) for x in (s[0:][::2], s[1:][::2])]\n    starts -= 1\n    ends = starts + lengths\n    img = np.zeros(shape[0]*shape[1], dtype=np.uint8)\n    for lo, hi in zip(starts, ends):\n        img[lo:hi] = 1\n    return img.reshape(shape)  # Needed to align to RLE direction","metadata":{"execution":{"iopub.status.busy":"2022-01-02T16:17:10.798208Z","iopub.execute_input":"2022-01-02T16:17:10.79844Z","iopub.status.idle":"2022-01-02T16:17:10.807707Z","shell.execute_reply.started":"2022-01-02T16:17:10.798409Z","shell.execute_reply":"2022-01-02T16:17:10.806691Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"**To verify the data loading is correct, let's visualize the annotations of randomly selected samples in the training set:**","metadata":{}},{"cell_type":"code","source":"for d in random.sample(dataset_dicts_train, 5):\n    img = cv2.imread(d[\"file_name\"])\n    visualizer = Visualizer(img[:, :, ::-1], metadata=metadata_train, scale=1)\n    out = visualizer.draw_dataset_dict(d)\n    plt.figure(figsize=(10,10))\n    plt.imshow(out.get_image())\n    plt.show()","metadata":{"execution":{"iopub.status.busy":"2022-01-02T16:17:10.809415Z","iopub.execute_input":"2022-01-02T16:17:10.809999Z","iopub.status.idle":"2022-01-02T16:17:14.989941Z","shell.execute_reply.started":"2022-01-02T16:17:10.80996Z","shell.execute_reply":"2022-01-02T16:17:14.989335Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Train the model\n* set model configurations\n* make a path to the output files\n* train the model","metadata":{}},{"cell_type":"code","source":"cfg = get_cfg()\nTHRESHOLDS = [.15, .35, .55]\nMIN_PIXELS = [75, 150, 75]\n# load model config\n\ncfg.merge_from_file(model_zoo.get_config_file(\"COCO-InstanceSegmentation/mask_rcnn_R_50_FPN_3x.yaml\"))\ncfg.MODEL.WEIGHTS = model_zoo.get_checkpoint_url(\"COCO-InstanceSegmentation/mask_rcnn_R_50_FPN_3x.yaml\")\ncfg.DATASETS.TRAIN = (\"my_dataset_train\",)\ncfg.DATASETS.TEST = (\"my_dataset_val\",)\n \n\ncfg.DATALOADER.NUM_WORKERS = 2\ncfg.MODEL.ROI_HEADS.BATCH_SIZE_PER_IMAGE = 128\ncfg.MODEL.ROI_HEADS.NUM_CLASSES = 3 \ncfg.SOLVER.IMS_PER_BATCH = 2\ncfg.INPUT.MASK_FORMAT='bitmask'\ncfg.MODEL.ROI_HEADS.SCORE_THRESH_TEST = 0.5\ncfg.SOLVER.BASE_LR = 0.00025  # pick a good LR\ncfg.SOLVER.WARMUP_ITERS = 10 #How many iterations to go from 0 to reach base LR\n\ncfg.SOLVER.MAX_ITER = 2000\ncfg.SOLVER.STEPS = (500, 1000)\ncfg.TEST.DETECTIONS_PER_IMAGE = 1000\ncfg.TEST.EVAL_PERIOD = 250\ncfg.SOLVER.CHECKPOINT_PERIOD=250\ncfg.MODEL.DEVICE = 'cuda'  #or \"cpu\"\n","metadata":{"execution":{"iopub.status.busy":"2022-01-02T16:41:13.36407Z","iopub.execute_input":"2022-01-02T16:41:13.364364Z","iopub.status.idle":"2022-01-02T16:41:13.390429Z","shell.execute_reply.started":"2022-01-02T16:41:13.364334Z","shell.execute_reply":"2022-01-02T16:41:13.389768Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"os.makedirs(cfg.OUTPUT_DIR, exist_ok=True)\ntrainer = DefaultTrainer(cfg) \ntrainer.resume_or_load(resume=False)\ntrainer.train()","metadata":{"_kg_hide-input":false,"execution":{"iopub.status.busy":"2022-01-02T16:41:17.199189Z","iopub.execute_input":"2022-01-02T16:41:17.199433Z","iopub.status.idle":"2022-01-02T17:30:09.181556Z","shell.execute_reply.started":"2022-01-02T16:41:17.199404Z","shell.execute_reply":"2022-01-02T17:30:09.180552Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# predictions\n* update the model weights to our new traind weights.\n* plot and save predictions to a csv file - \"submission\":\n    1. ID      |    PREDICTION\n    2. No overlaping masks\n    3. RLE method\n\n","metadata":{}},{"cell_type":"code","source":"cfg.MODEL.WEIGHTS = os.path.join(cfg.OUTPUT_DIR, \"model_final.pth\")\npredictor = DefaultPredictor(cfg)","metadata":{"execution":{"iopub.status.busy":"2022-01-02T16:17:18.74296Z","iopub.status.idle":"2022-01-02T16:17:18.743825Z","shell.execute_reply.started":"2022-01-02T16:17:18.743594Z","shell.execute_reply":"2022-01-02T16:17:18.743617Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"with open('submission.csv', 'w', newline = '') as f:\n    writer = csv.writer(f)\n    writer.writerow(['id', 'predicted'])\n    test = '../input/sartorius-cell-instance-segmentation/test'\n    for filename in os.listdir(test):\n        img = cv2.imread(os.path.join(test,filename))\n        img_id = filename\n        predictions = predictor(img)\n        \n        visualizer = Visualizer(img[:, :, ::-1], metadata=metadata_train, scale=1, instance_mode=ColorMode.IMAGE_BW )\n        out = visualizer.draw_instance_predictions(predictions[\"instances\"].to(\"cpu\"))\n        plt.figure(figsize=(20,20))\n        plt.imshow(out.get_image())\n        plt.show()\n        \n        pred_class = torch.mode(predictions['instances'].pred_classes)[0]\n        take = predictions['instances'].scores >= THRESHOLDS[pred_class]\n        masks_list = predictions['instances'].pred_masks[take]\n        masks_list = masks_list.cpu().numpy()\n\n        used = np.zeros(img.shape[:2], dtype=int)\n\n        for msk in masks_list:\n            s= []\n            msk = msk * (1-used)\n            used += msk\n            s = (rle_encode(msk))\n            #print(s)\n            writer.writerow([img_id, s])\n    f.close()\n\n","metadata":{"execution":{"iopub.status.busy":"2022-01-02T16:17:18.744956Z","iopub.status.idle":"2022-01-02T16:17:18.745853Z","shell.execute_reply.started":"2022-01-02T16:17:18.745603Z","shell.execute_reply":"2022-01-02T16:17:18.745628Z"},"trusted":true},"execution_count":null,"outputs":[]}]}