{"cells":[{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"code","source":"# This Python 3 environment comes with many helpful analytics libraries installed\n# It is defined by the kaggle/python Docker image: https://github.com/kaggle/docker-python\n# For example, here's several helpful packages to load\n\nimport numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\n\n# Input data files are available in the read-only \"../input/\" directory\n# For example, running this (by clicking run or pressing Shift+Enter) will list all files under the input directory\nimport glob\nimport os\nfor dirname, _, filenames in os.walk('/kaggle/input'):\n    for filename in filenames:\n        print(os.path.join(dirname, filename))\n\n# You can write up to 5GB to the current directory (/kaggle/working/) that gets preserved as output when you create a version using \"Save & Run All\" \n# You can also write temporary files to /kaggle/temp/, but they won't be saved outside of the current session","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"**U-net from https://www.kaggle.com/pednt9/gwd-keras-unet-starter with corrected test submission**","execution_count":null},{"metadata":{"_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","trusted":true},"cell_type":"code","source":"import os\nimport sys\nimport random\nimport warnings\n\nimport numpy as np\nimport pandas as pd\n\nimport matplotlib.pyplot as plt\n\nfrom itertools import chain\nfrom skimage.io import imread, imshow, imread_collection, concatenate_images\nfrom skimage.transform import resize\nfrom skimage.measure import label, regionprops\nfrom PIL import Image, ImageDraw\nfrom ast import literal_eval\nfrom tqdm.notebook import tqdm\nimport keras\nfrom keras.models import Model, load_model\nfrom keras.layers import Input, BatchNormalization, Activation, Dense, Dropout\nfrom keras.layers.core import Dropout, Lambda\nfrom keras.layers.convolutional import Conv2D, Conv2DTranspose\nfrom keras.layers.pooling import MaxPooling2D\nfrom keras.layers.merge import concatenate\nfrom keras.callbacks import EarlyStopping, ModelCheckpoint\nfrom keras import backend as K\nfrom keras.optimizers import Adam\nfrom imgaug import augmenters as iaa\nimport tensorflow as tf\nfrom imgaug import augmenters as iaa\n# Set some parameters\nIMG_WIDTH = 256\nIMG_HEIGHT = 256\nassert IMG_WIDTH == IMG_HEIGHT\nBATCH_SIZE = 32 # the higher the better\nIMG_CHANNELS = 3\nTRAIN_PATH = '/kaggle/input/global-wheat-detection/train/'\nTEST_PATH = '/kaggle/input/global-wheat-detection/test/'\nSC_FACTOR = int(1024 / IMG_WIDTH)\n\nwarnings.filterwarnings('ignore')\nseed = 42\n#random.seed = seed\n#np.random.seed = seed","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"PATH = \"../input/global-wheat-detection/\"\ntrain_folder = os.path.join(PATH, \"train\")\ntest_folder = os.path.join(PATH, \"test\")\n\ntrain_csv_path = os.path.join(PATH, \"train.csv\")\ndf = pd.read_csv(train_csv_path)\nsample_sub = pd.read_csv(PATH + \"sample_submission.csv\")\n\ndf.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Get train and test IDs and paths\ntrain_ids = os.listdir(TRAIN_PATH)\ntest_ids = os.listdir(TEST_PATH)\nprint(test_ids)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def make_polygon(coords):\n    xm, ym, w, h = coords\n    xm, ym, w, h = xm / SC_FACTOR, ym / SC_FACTOR, w / SC_FACTOR, h / SC_FACTOR\n    polygon = [(xm, ym), (xm, ym + h), (xm + w, ym + h), (xm + w, ym)]\n    return polygon\n\nmasks = dict() # dictionnary containing all masks\n\nfor img_id, gp in tqdm(df.groupby(\"image_id\")):\n    gp['polygons'] = gp['bbox'].apply(eval).apply(lambda x: make_polygon(x))\n\n    img = Image.new('L', (IMG_WIDTH, IMG_HEIGHT), 0)\n    for pol in gp['polygons'].values:\n        ImageDraw.Draw(img).polygon(pol, outline=1, fill=1)\n\n    mask = np.array(img, dtype=np.uint8)\n    masks[img_id] = mask","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"im = Image.fromarray(masks[list(masks.keys())[4]])\nplt.imshow(im)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Get and resize train images and masks\nX_train = np.zeros((len(train_ids), IMG_HEIGHT, IMG_WIDTH, IMG_CHANNELS), dtype=np.uint8)\nY_train = np.zeros((len(train_ids), IMG_HEIGHT, IMG_WIDTH, 1), dtype=np.bool)\nprint('Getting and resizing train images and masks... ')\nsys.stdout.flush()\n\nfor n, id_ in tqdm(enumerate(train_ids[:]), total=len(train_ids)):\n    path = TRAIN_PATH + id_\n    img = imread(path)[:,:,:IMG_CHANNELS]\n    img = resize(img, (IMG_HEIGHT, IMG_WIDTH), mode='constant', preserve_range=True)\n    X_train[n] = img\n    mask = np.zeros((IMG_HEIGHT, IMG_WIDTH, 1), dtype=np.bool)\n    \n    id_clean = id_.split('.')[0]\n    if id_clean in masks.keys():\n        Y_train[n] = masks[id_clean][:, :, np.newaxis]\n        \n\n# Get and resize test images\nX_test = np.zeros((len(test_ids), IMG_HEIGHT, IMG_WIDTH, IMG_CHANNELS), dtype=np.uint8)\nsizes_test = list()\nprint('Getting and resizing test images... ')\nsys.stdout.flush()\nfor n, id_ in tqdm(enumerate(test_ids), total=len(test_ids)):\n    path = TEST_PATH + id_\n    img = imread(path)[:,:,:IMG_CHANNELS]\n    sizes_test.append([img.shape[0], img.shape[1]])\n    img = resize(img, (IMG_HEIGHT, IMG_WIDTH), mode='constant', preserve_range=True)\n    X_test[n] = img","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"X_train.shape, Y_train.shape","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def show_images(images, num=2):\n    \n    images_to_show = np.random.choice(images, num)\n\n    for image_id in images_to_show:\n\n        image_path = os.path.join(train_folder, image_id + \".jpg\")\n        image = Image.open(image_path)\n\n        # get all bboxes for given image in [xmin, ymin, width, height]\n        bboxes = [literal_eval(box) for box in df[df['image_id'] == image_id]['bbox']]\n\n        # visualize them\n        draw = ImageDraw.Draw(image)\n        for bbox in bboxes:    \n            draw.rectangle([bbox[0], bbox[1], bbox[0] + bbox[2], bbox[1] + bbox[3]], width=3)\n \n        plt.figure(figsize = (15,15))\n        plt.imshow(image)\n        plt.show()\n\n\nunique_images = df['image_id'].unique()\n#print(unique_images)\nshow_images(unique_images)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#Credits to : https://www.kaggle.com/c/tgs-salt-identification-challenge/discussion/63044\n\ndef castF(x):\n    return K.cast(x, K.floatx())\n\ndef castB(x):\n    return K.cast(x, bool)\n\ndef iou_loss_core(true,pred):  #this can be used as a loss if you make it negative\n    intersection = true * pred\n    notTrue = 1 - true\n    union = true + (notTrue * pred)\n\n    return (K.sum(intersection, axis=-1) + K.epsilon()) / (K.sum(union, axis=-1) + K.epsilon())\n\ndef competitionMetric2(true, pred): #any shape can go - can't be a loss function\n\n    tresholds = [0.5 + (i * 0.05)  for i in range(5)]\n\n    #flattened images (batch, pixels)\n    true = K.batch_flatten(true)\n    pred = K.batch_flatten(pred)\n    pred = castF(K.greater(pred, 0.5))\n\n    #total white pixels - (batch,)\n    trueSum = K.sum(true, axis=-1)\n    predSum = K.sum(pred, axis=-1)\n\n    #has mask or not per image - (batch,)\n    true1 = castF(K.greater(trueSum, 1))    \n    pred1 = castF(K.greater(predSum, 1))\n\n    #to get images that have mask in both true and pred\n    truePositiveMask = castB(true1 * pred1)\n\n    #separating only the possible true positives to check iou\n    testTrue = tf.boolean_mask(true, truePositiveMask)\n    testPred = tf.boolean_mask(pred, truePositiveMask)\n\n    #getting iou and threshold comparisons\n    iou = iou_loss_core(testTrue,testPred) \n    truePositives = [castF(K.greater(iou, tres)) for tres in tresholds]\n\n    #mean of thressholds for true positives and total sum\n    truePositives = K.mean(K.stack(truePositives, axis=-1), axis=-1)\n    truePositives = K.sum(truePositives)\n\n    #to get images that don't have mask in both true and pred\n    trueNegatives = (1-true1) * (1 - pred1) # = 1 -true1 - pred1 + true1*pred1\n    trueNegatives = K.sum(trueNegatives) \n\n    return (truePositives + trueNegatives) / castF(K.shape(true)[0])\n# Custom loss function\ndef dice_coef(y_true, y_pred):\n    smooth = 1.\n    y_true_f = K.flatten(y_true)\n    y_pred_f = K.flatten(y_pred)\n    intersection = K.sum(y_true_f * y_pred_f)\n    return (2. * intersection + smooth) / (K.sum(y_true_f) + K.sum(y_pred_f) + smooth)\n\ndef bce_dice_loss(y_true, y_pred):\n    return 0.5 * keras.losses.binary_crossentropy(y_true, y_pred) - dice_coef(y_true, y_pred)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def conv2d_block(input_tensor, n_filters, kernel_size=3, batchnorm=True):\n    # first layer\n    x = Conv2D(filters=n_filters, kernel_size=(kernel_size, kernel_size), kernel_initializer=\"he_normal\",\n               padding=\"same\")(input_tensor)\n    if batchnorm:\n        x = BatchNormalization()(x)\n    x = Activation(\"relu\")(x)\n    # second layer\n    x = Conv2D(filters=n_filters, kernel_size=(kernel_size, kernel_size), kernel_initializer=\"he_normal\",\n               padding=\"same\")(x)\n    if batchnorm:\n        x = BatchNormalization()(x)\n    x = Activation(\"relu\")(x)\n    return x","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"n_filters=16 \ndropout=0.3\nbatchnorm=True\n# Build U-Net model\ninputs = Input((IMG_HEIGHT, IMG_WIDTH, IMG_CHANNELS))\nc1 = conv2d_block(inputs, n_filters=n_filters*1, kernel_size=3, batchnorm=batchnorm)\np1 = MaxPooling2D((2, 2)) (c1)\np1 = Dropout(dropout*0.5)(p1)\n\nc2 = conv2d_block(p1, n_filters=n_filters*2, kernel_size=3, batchnorm=batchnorm)\np2 = MaxPooling2D((2, 2)) (c2)\np2 = Dropout(dropout)(p2)\n\nc3 = conv2d_block(p2, n_filters=n_filters*4, kernel_size=3, batchnorm=batchnorm)\np3 = MaxPooling2D((2, 2)) (c3)\np3 = Dropout(dropout)(p3)\n\nc4 = conv2d_block(p3, n_filters=n_filters*8, kernel_size=3, batchnorm=batchnorm)\np4 = MaxPooling2D(pool_size=(2, 2)) (c4)\np4 = Dropout(dropout)(p4)\n    \nc5 = conv2d_block(p4, n_filters=n_filters*16, kernel_size=3, batchnorm=batchnorm)\n    \n    # expansive path\nu6 = Conv2DTranspose(n_filters*8, (3, 3), strides=(2, 2), padding='same') (c5)\nu6 = concatenate([u6, c4])\nu6 = Dropout(dropout)(u6)\nc6 = conv2d_block(u6, n_filters=n_filters*8, kernel_size=3, batchnorm=batchnorm)\n\nu7 = Conv2DTranspose(n_filters*4, (3, 3), strides=(2, 2), padding='same') (c6)\nu7 = concatenate([u7, c3])\nu7 = Dropout(dropout)(u7)\nc7 = conv2d_block(u7, n_filters=n_filters*4, kernel_size=3, batchnorm=batchnorm)\n\nu8 = Conv2DTranspose(n_filters*2, (3, 3), strides=(2, 2), padding='same') (c7)\nu8 = concatenate([u8, c2])\nu8 = Dropout(dropout)(u8)\nc8 = conv2d_block(u8, n_filters=n_filters*2, kernel_size=3, batchnorm=batchnorm)\n\nu9 = Conv2DTranspose(n_filters*1, (3, 3), strides=(2, 2), padding='same') (c8)\nu9 = concatenate([u9, c1], axis=3)\nu9 = Dropout(dropout)(u9)\nc9 = conv2d_block(u9, n_filters=n_filters*1, kernel_size=3, batchnorm=batchnorm)\n    \noutputs = Conv2D(1, (1, 1), activation='sigmoid') (c9)\n\nmodel = Model(inputs=[inputs], outputs=[outputs])\nmodel.compile(optimizer='adam', loss='binary_crossentropy', metrics=[competitionMetric2])\nmodel.summary()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"from keras.utils import plot_model\nplot_model(model, show_shapes=True)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Fit model\nearlystop = EarlyStopping(patience=10, verbose=1, restore_best_weights=True)\nmodel.fit(X_train, \n         Y_train,\n         validation_split=0.1,\n         batch_size=16, \n         epochs=15, \n         callbacks=[earlystop],\n        )","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"THRESH=0.6\npreds = model.predict(X_test)[:, :, :, 0]\n\nmasked_preds = preds > THRESH\nprint(len(preds[masked_preds]))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def show_images_test(images, num=1):\n    \n    images_to_show = np.random.choice(images, num)\n\n    for image_id in images_to_show:\n\n        image_path = os.path.join(test_folder, image_id + \".jpg\")\n        image = Image.open(image_path)\n\n        # get all bboxes for given image in [xmin, ymin, width, height]\n        #bboxes = [literal_eval(box) for box in df[df['image_id'] == image_id]['bbox']]\n        bbox=get_params_from_bbox(bb.bbox, scaling_factor=SC_FACTOR)\n        # visualize them\n        draw = ImageDraw.Draw(image)\n        for bbox in bboxes:    \n            draw.rectangle([bbox[0], bbox[1], bbox[0] + bbox[2], bbox[1] + bbox[3]], width=3)\n \n        plt.figure(figsize = (15,15))\n        plt.imshow(image)\n        plt.show()\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"n_rows = 3\n\nf, ax = plt.subplots(n_rows, 3, figsize=(14, 10))\nbbox_dict = {}\nfor j, idx in enumerate([4,5,6]):\n    for k, kind in enumerate(['original', 'pred', 'masked_pred']):\n        bboxes=list()\n        if kind == 'original':\n            img = X_test[idx]\n                  \n        elif kind == 'pred':\n            img = preds[idx]\n            \n        elif kind == 'masked_pred':\n            masked_pred = preds[idx] > THRESH\n            img = masked_pred\n           \n        ax[j, k].imshow(img)\n\n\nplt.tight_layout()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def get_params_from_bbox(coords, score, scaling_factor=1):\n    xmin, ymin = coords[1] * scaling_factor, coords[0] * scaling_factor\n    w = (coords[3] - coords[1]) * scaling_factor\n    h = (coords[2] - coords[0]) * scaling_factor\n    return score, xmin, ymin, w, h ","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Allows to extract bounding boxes from binary masks\nbboxes = list()\n\nfor j in range(masked_preds.shape[0]):\n    label_j = label(masked_preds[j, :, :])  \n    props = regionprops(label_j)   # that's were the job is done\n    bboxes.append(props)\n   # for b in bboxes[j]:\n       # print(list(b))\n       # print(preds[j, b.coords].max())","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def preprocess_image(image, image_size):\n    # image, RGB\n    image_height, image_width = image.shape[:2]\n    if image_height > image_width:\n        scale = image_size / image_height\n        resized_height = image_size\n        resized_width = int(image_width * scale)\n    else:\n        scale = image_size / image_width\n        resized_height = int(image_height * scale)\n        resized_width = image_size\n\n    image = cv2.resize(image, (resized_width, resized_height))\n    image = image.astype(np.float32)\n    image /= 255.\n    mean = [0.485, 0.456, 0.406]\n    std = [0.229, 0.224, 0.225]\n    image -= mean\n    image /= std\n    pad_h = image_size - resized_height\n    pad_w = image_size - resized_width\n    image = np.pad(image, [(0, pad_h), (0, pad_w), (0, 0)], mode='constant')\n\n    return image, scale\n\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Here we format the bboxes into the required format\nsample_sub = pd.DataFrame(columns=['image_id', 'PredictionString'])\nfor i in range(masked_preds.shape[0]):\n    bboxes_processed = [get_params_from_bbox(bb.bbox, preds[i, bb.coords].max(), scaling_factor=SC_FACTOR) for bb in bboxes[i]]\n    formated_boxes = [' '.join(map(str, bb_m)) for bb_m in bboxes_processed]\n    print([test_ids[i][:-4], \" \".join(formated_boxes)])\n    sample_sub.loc[i]=[test_ids[i][:-4], \" \".join(formated_boxes)]\n\nprint(sample_sub)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"sample_sub","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"sample_sub.to_csv('submission.csv', index=False)","execution_count":null,"outputs":[]}],"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":4,"nbformat_minor":4}