{"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":"debug = False\n# debug = True","metadata":{"_uuid":"cdb40bf9115f53810c9e13f0a50e53ed9eb6221b","_kg_hide-input":true,"_kg_hide-output":true,"execution":{"iopub.status.busy":"2022-05-09T07:37:53.260129Z","iopub.execute_input":"2022-05-09T07:37:53.260449Z","iopub.status.idle":"2022-05-09T07:37:53.283590Z","shell.execute_reply.started":"2022-05-09T07:37:53.260387Z","shell.execute_reply":"2022-05-09T07:37:53.282703Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from statistics import mean\nimport os \nimport sys\nimport random\nimport math\nimport numpy as np\nimport cv2\nimport matplotlib.pyplot as plt\nimport json\nfrom imgaug import augmenters as iaa\nfrom tqdm import tqdm\nimport pandas as pd \nimport glob ","metadata":{"id":"4kjcC6QqywWl","_uuid":"40c67b3ff0fa04587dec508363308adaa3ceaf34","execution":{"iopub.status.busy":"2022-05-09T07:37:53.286107Z","iopub.execute_input":"2022-05-09T07:37:53.286722Z","iopub.status.idle":"2022-05-09T07:37:54.473559Z","shell.execute_reply.started":"2022-05-09T07:37:53.286663Z","shell.execute_reply":"2022-05-09T07:37:54.472588Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"DATA_DIR = '/kaggle/input/airbus-ship-detection'\n\n# Directory to save logs and trained model\nROOT_DIR = '/kaggle/working'","metadata":{"id":"yP0XLJx_x_6o","_uuid":"6e5764759e6a0a9b698b44645658f66873edd807","execution":{"iopub.status.busy":"2022-05-09T07:37:54.476695Z","iopub.execute_input":"2022-05-09T07:37:54.477424Z","iopub.status.idle":"2022-05-09T07:37:54.483086Z","shell.execute_reply.started":"2022-05-09T07:37:54.477079Z","shell.execute_reply":"2022-05-09T07:37:54.481754Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!git clone https://www.github.com/matterport/Mask_RCNN.git\nos.chdir('Mask_RCNN')\n#!python setup.py -q install","metadata":{"id":"KgllzLnDr7kF","outputId":"6c978df7-2013-437e-acd1-5011048dfb53","_uuid":"b37d22551d332f0f7b722cc7204eb614524b6c21","execution":{"iopub.status.busy":"2022-05-09T07:37:54.486226Z","iopub.execute_input":"2022-05-09T07:37:54.486975Z","iopub.status.idle":"2022-05-09T07:38:04.061611Z","shell.execute_reply.started":"2022-05-09T07:37:54.486913Z","shell.execute_reply":"2022-05-09T07:38:04.060378Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from tensorflow import keras\nsys.path.append(os.path.join(ROOT_DIR, 'Mask_RCNN'))  # To find local version of the library\nfrom mrcnn.config import Config\nfrom mrcnn import utils\nimport mrcnn.model as modellib\nfrom mrcnn import visualize\nfrom mrcnn.model import log","metadata":{"id":"-KZXyWwhzOVU","outputId":"2576cc17-7484-4311-ad72-3c5643dcb5bb","_uuid":"3acbbbe055b6a409d3c50ae0f893acf51b5ae7ba","execution":{"iopub.status.busy":"2022-05-09T07:38:04.062933Z","iopub.execute_input":"2022-05-09T07:38:04.063234Z","iopub.status.idle":"2022-05-09T07:38:04.494332Z","shell.execute_reply.started":"2022-05-09T07:38:04.063176Z","shell.execute_reply":"2022-05-09T07:38:04.493267Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_dicom_dir = os.path.join(DATA_DIR, 'train_v2')\ntest_dicom_dir = os.path.join(DATA_DIR, 'test_v2')\n","metadata":{"id":"FghMmiMjzOX2","_uuid":"50089cc61791871cdf6a5c0037dc4f28b7b7d7cc","execution":{"iopub.status.busy":"2022-05-09T07:38:04.495470Z","iopub.execute_input":"2022-05-09T07:38:04.495771Z","iopub.status.idle":"2022-05-09T07:38:04.502902Z","shell.execute_reply.started":"2022-05-09T07:38:04.495711Z","shell.execute_reply":"2022-05-09T07:38:04.501662Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"\n\nCOCO_WEIGHTS_PATH = \"/kaggle/input/retinanet-mask/retinanet_mask.h5\"","metadata":{"_uuid":"c3ee0cd0ee0b1defdec97b94bc736587c1f7631f","execution":{"iopub.status.busy":"2022-05-09T07:38:04.505032Z","iopub.execute_input":"2022-05-09T07:38:04.506053Z","iopub.status.idle":"2022-05-09T07:38:04.514787Z","shell.execute_reply.started":"2022-05-09T07:38:04.505992Z","shell.execute_reply":"2022-05-09T07:38:04.513456Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# The following parameters have been selected to reduce running time for demonstration purposes \n# These are not optimal \n\nclass DetectorConfig(Config):    \n    # Give the configuration a recognizable name  \n    NAME = 'airbus'\n    \n    GPU_COUNT = 1\n    IMAGES_PER_GPU = 9\n    \n    BACKBONE = 'resnet50'\n    \n    NUM_CLASSES = 2  # background and ship classes\n    \n    IMAGE_MIN_DIM = 384\n    IMAGE_MAX_DIM = 384\n    RPN_ANCHOR_SCALES = (8, 16, 32, 64)\n    TRAIN_ROIS_PER_IMAGE = 64\n    MAX_GT_INSTANCES = 14\n    USE_MINI_MASK = False\n    DETECTION_MAX_INSTANCES = 10\n    DETECTION_MIN_CONFIDENCE = 0.95\n    DETECTION_NMS_THRESHOLD = 0.0\n\n    STEPS_PER_EPOCH = 15 if debug else 150\n    VALIDATION_STEPS = 10 if debug else 125\n    \n    ## balance out losses\n    LOSS_WEIGHTS = {\n        \"rpn_class_loss\": 30.0,\n        \"rpn_bbox_loss\": 0.8,\n        \"mrcnn_class_loss\": 6.0,\n        \"mrcnn_bbox_loss\": 1.0,\n        \"mrcnn_mask_loss\": 1.2\n    }\n\nconfig = DetectorConfig()\nconfig.display()","metadata":{"id":"_SfzTa-1zOck","outputId":"91ae8935-bccb-4b8e-9a7e-aa690f95fd9b","_uuid":"dfcffc4eaa94a41497717851dee9f702d8a2a73b","execution":{"iopub.status.busy":"2022-05-09T07:38:04.521020Z","iopub.execute_input":"2022-05-09T07:38:04.521889Z","iopub.status.idle":"2022-05-09T07:38:04.545066Z","shell.execute_reply.started":"2022-05-09T07:38:04.521802Z","shell.execute_reply":"2022-05-09T07:38:04.544156Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import os\nimport numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\nfrom skimage.io import imread\nimport matplotlib.pyplot as plt\nfrom matplotlib.cm import get_cmap\nfrom skimage.segmentation import mark_boundaries\nfrom skimage.util import montage\nfrom skimage.morphology import binary_opening, disk, label\nimport gc; gc.enable() # memory is tight\n\nmontage_rgb = lambda x: np.stack([montage(x[:, :, :, i]) for i in range(x.shape[3])], -1)\n\ndef multi_rle_encode(img, **kwargs):\n    '''\n    Encode connected regions as separated masks\n    '''\n    labels = label(img)\n    if img.ndim > 2:\n        return [rle_encode(np.sum(labels==k, axis=2), **kwargs) for k in np.unique(labels[labels>0])]\n    else:\n        return [rle_encode(labels==k, **kwargs) for k in np.unique(labels[labels>0])]\n\n# ref: https://www.kaggle.com/paulorzp/run-length-encode-and-decode\ndef rle_encode(img, min_max_threshold=1e-3, max_mean_threshold=None):\n    '''\n    img: numpy array, 1 - mask, 0 - background\n    Returns run length as string formated\n    '''\n    if np.max(img) < min_max_threshold:\n        return '' ## no need to encode if it's all zeros\n    if max_mean_threshold and np.mean(img) > max_mean_threshold:\n        return '' ## ignore overfilled mask\n    pixels = img.T.flatten()\n    pixels = np.concatenate([[0], pixels, [0]])\n    runs = np.where(pixels[1:] != pixels[:-1])[0] + 1\n    runs[1::2] -= runs[::2]\n    return ' '.join(str(x) for x in runs)\n\ndef rle_decode(mask_rle, shape=(768, 768)):\n    '''\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\n    '''\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).T  # Needed to align to RLE direction\n\ndef masks_as_image(in_mask_list):\n    # Take the individual ship masks and create a single mask array for all ships\n    all_masks = np.zeros((768, 768), dtype = np.uint8)\n    for mask in in_mask_list:\n        if isinstance(mask, str):\n            all_masks |= rle_decode(mask)\n    return all_masks\n\ndef masks_as_color(in_mask_list):\n    # Take the individual ship masks and create a color mask array for each ships\n    all_masks = np.zeros((768, 768), dtype = np.float)\n    scale = lambda x: (len(in_mask_list)+x+1) / (len(in_mask_list)*2) ## scale the heatmap image to shift \n    for i,mask in enumerate(in_mask_list):\n        if isinstance(mask, str):\n            all_masks[:,:] += scale(i) * rle_decode(mask)\n    return all_masks","metadata":{"_uuid":"6136132b1f1b311e297d9432772ec4a81230924f","_kg_hide-input":true,"execution":{"iopub.status.busy":"2022-05-09T07:38:04.552402Z","iopub.execute_input":"2022-05-09T07:38:04.552687Z","iopub.status.idle":"2022-05-09T07:38:04.582254Z","shell.execute_reply.started":"2022-05-09T07:38:04.552631Z","shell.execute_reply":"2022-05-09T07:38:04.581019Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from PIL import Image\nfrom sklearn.model_selection import train_test_split\n\nexclude_list = ['6384c3e78.jpg','13703f040.jpg', '14715c06d.jpg',  '33e0ff2d5.jpg',\n                '4d4e09f2a.jpg', '877691df8.jpg', '8b909bb20.jpg', 'a8d99130e.jpg', \n                'ad55c3143.jpg', 'c8260c541.jpg', 'd6c7f17c7.jpg', 'dc3e7c901.jpg',\n                'e44dffe88.jpg', 'ef87bad36.jpg', 'f083256d8.jpg'] #corrupted images\n\ntrain_names = [f for f in os.listdir(train_dicom_dir) if f not in exclude_list]\ntest_names = [f for f in os.listdir(test_dicom_dir) if f not in exclude_list]\n\nprint(len(train_names), len(test_names))","metadata":{"_uuid":"d3e05fa1a38c637fa228acd62b92dd41117a6672","execution":{"iopub.status.busy":"2022-05-09T07:38:04.583338Z","iopub.execute_input":"2022-05-09T07:38:04.583704Z","iopub.status.idle":"2022-05-09T07:38:11.067930Z","shell.execute_reply.started":"2022-05-09T07:38:04.583582Z","shell.execute_reply":"2022-05-09T07:38:11.066713Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# training dataset\nSEGMENTATION = DATA_DIR + '/train_ship_segmentations_v2.csv'\nanns = pd.read_csv(SEGMENTATION)\nanns.head()","metadata":{"_uuid":"3050fa77026411ffdc27bed4a9b667ec0467e4ce","execution":{"iopub.status.busy":"2022-05-09T07:38:11.072535Z","iopub.execute_input":"2022-05-09T07:38:11.073129Z","iopub.status.idle":"2022-05-09T07:38:12.187082Z","shell.execute_reply.started":"2022-05-09T07:38:11.073060Z","shell.execute_reply":"2022-05-09T07:38:12.185970Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_names = anns[anns.EncodedPixels.notnull()].ImageId.unique().tolist()  ## override with ships\n\ntest_size = config.VALIDATION_STEPS * config.IMAGES_PER_GPU\nimage_fps_train, image_fps_val = train_test_split(train_names, test_size=test_size, random_state=42)\n\nif debug:\n    image_fps_train = image_fps_train[:100]\n    image_fps_val = image_fps_val[:100]\n    test_names = test_names[:100]\n    \nprint(len(image_fps_train), len(image_fps_val), len(test_names))","metadata":{"_uuid":"904636402355a305f7b2ccacb8cc55d52151d2e6","execution":{"iopub.status.busy":"2022-05-09T07:38:12.188600Z","iopub.execute_input":"2022-05-09T07:38:12.189239Z","iopub.status.idle":"2022-05-09T07:38:12.247509Z","shell.execute_reply.started":"2022-05-09T07:38:12.189172Z","shell.execute_reply":"2022-05-09T07:38:12.246200Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class DetectorDataset(utils.Dataset):\n    \"\"\"Dataset class for training our dataset.\n    \"\"\"\n\n    def __init__(self, image_fps, image_annotations, orig_height, orig_width):\n        super().__init__(self)\n        \n        # Add classes\n        self.add_class('ship', 1, 'Ship')\n        \n        # add images \n        for i, fp in enumerate(image_fps):\n            annotations = image_annotations.query('ImageId==\"' + fp + '\"')['EncodedPixels']\n            self.add_image('ship', image_id=i, path=os.path.join(train_dicom_dir, fp), \n                           annotations=annotations, orig_height=orig_height, orig_width=orig_width)\n            \n    def image_reference(self, image_id):\n        info = self.image_info[image_id]\n        return info['path']\n\n    def load_image(self, image_id):\n        info = self.image_info[image_id]\n        fp = info['path']\n        image = imread(fp)\n        # If grayscale. Convert to RGB for consistency.\n        if len(image.shape) != 3 or image.shape[2] != 3:\n            image = np.stack((image,) * 3, -1)\n        return image\n\n    def load_mask(self, image_id):\n        info = self.image_info[image_id]\n        annotations = info['annotations']\n#         print(image_id, annotations)\n        count = len(annotations)\n        if count == 0:\n            mask = np.zeros((info['orig_height'], info['orig_width'], 1), dtype=np.uint8)\n            class_ids = np.zeros((1,), dtype=np.int32)\n        else:\n            mask = np.zeros((info['orig_height'], info['orig_width'], count), dtype=np.uint8)\n            class_ids = np.zeros((count,), dtype=np.int32)\n            for i, a in enumerate(annotations):\n                mask[:, :, i] = rle_decode(a)\n                class_ids[i] = 1\n        return mask.astype(np.bool), class_ids.astype(np.int32)","metadata":{"id":"8EBVA1M60yAj","_uuid":"52bd3ffbdde0173a363055482d675da51c2aba99","execution":{"iopub.status.busy":"2022-05-09T07:38:12.249465Z","iopub.execute_input":"2022-05-09T07:38:12.249898Z","iopub.status.idle":"2022-05-09T07:38:12.272043Z","shell.execute_reply.started":"2022-05-09T07:38:12.249788Z","shell.execute_reply":"2022-05-09T07:38:12.270878Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Examine the annotation data, parse the dataset, and view dicom fields","metadata":{"id":"9RlMo04ckd98","_uuid":"1cb852e262b69d348743767d675573368ab672c9"}},{"cell_type":"code","source":"image_fps, image_annotations = train_names, anns","metadata":{"id":"Mxz-pNbt5txY","_uuid":"7aebc88f910b232e3b8759421914a007c6ffed94","execution":{"iopub.status.busy":"2022-05-09T07:38:12.273678Z","iopub.execute_input":"2022-05-09T07:38:12.274654Z","iopub.status.idle":"2022-05-09T07:38:12.288659Z","shell.execute_reply.started":"2022-05-09T07:38:12.274588Z","shell.execute_reply":"2022-05-09T07:38:12.287438Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"ds = imread(os.path.join(train_dicom_dir, image_fps[0])) # read  image from filepath \n_ = plt.imshow(ds)","metadata":{"id":"YPqjEIXWRhSf","_uuid":"6c386dcef041b972f6209dd19e247d547c3c349f","execution":{"iopub.status.busy":"2022-05-09T07:38:12.290487Z","iopub.execute_input":"2022-05-09T07:38:12.291316Z","iopub.status.idle":"2022-05-09T07:38:12.698447Z","shell.execute_reply.started":"2022-05-09T07:38:12.291251Z","shell.execute_reply":"2022-05-09T07:38:12.697271Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Original image size: 768 x 768\nORIG_SIZE = ds.shape[0]\nORIG_SIZE","metadata":{"id":"gYNSd1AhRqOV","_uuid":"74277ae9af4a3b044e62b664d10d76b23848bb43","execution":{"iopub.status.busy":"2022-05-09T07:38:12.699650Z","iopub.execute_input":"2022-05-09T07:38:12.700000Z","iopub.status.idle":"2022-05-09T07:38:12.707994Z","shell.execute_reply.started":"2022-05-09T07:38:12.699946Z","shell.execute_reply":"2022-05-09T07:38:12.706985Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from keras.preprocessing.image import load_img\nfrom keras.preprocessing.image import img_to_array\nfrom mrcnn.config import Config\nfrom mrcnn.model import MaskRCNN\nfrom mrcnn.visualize import display_instances\nfrom matplotlib import pyplot\nfrom matplotlib.patches import Rectangle\nclass InferenceConfig(DetectorConfig):\n    USE_MINI_MASK = False\n    GPU_COUNT = 1\n    IMAGES_PER_GPU = 1\nmodel_path ='/kaggle/input/retinanet-mask/retinanet_mask.h5'\ninference_config = InferenceConfig()\n\n# Recreate the model in inference mode\nmodel = modellib.MaskRCNN(mode='inference', \n                          config=inference_config,\n                          model_dir=ROOT_DIR)\n\n# Load trained weights (fill in path to trained weights here)\nassert model_path != \"\", \"Provide path to trained weights\"\nprint(\"Loading weights from \", model_path)\nmodel.load_weights(model_path, by_name=True)\nclass_names = 'ship'\nfor i in range(6):\n    img = load_img('/kaggle/input/imges/imgs/'+(str(i+1))+'.jpg')\n    img = img_to_array(img)\n    # make prediction\n    results = model.detect([img], verbose=0)\n    r = results[0]\n    # visualize the results\n    visualize.display_instances(img, r['rois'], r['masks'], r['class_ids'], class_names, r['scores'])\n","metadata":{"id":"TgpT9AzC2Bgz","outputId":"60f5a175-4666-497d-b4e8-0bdab39a92d0","_uuid":"52138636b2ae5bf444bba808518cd8313bde65cd","execution":{"iopub.status.busy":"2022-05-09T07:38:37.222089Z","iopub.execute_input":"2022-05-09T07:38:37.222551Z","iopub.status.idle":"2022-05-09T07:38:54.000210Z","shell.execute_reply.started":"2022-05-09T07:38:37.222472Z","shell.execute_reply":"2022-05-09T07:38:53.999254Z"},"trusted":true},"execution_count":null,"outputs":[]}]}