{"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":"markdown","source":"# **Import modules**","metadata":{}},{"cell_type":"code","source":"import sys, os\nimport cv2\nimport math\nfrom os import listdir, walk\nfrom os.path import isfile, join\nimport matplotlib as mpl\nimport matplotlib.pyplot as plt\nimport matplotlib.image as mpimg\nimport matplotlib.patches as mpatches\nimport numpy as np\nimport pandas as pd\nimport csv\nimport re\nfrom skimage import data, util, measure\nfrom PIL import Image\nimport pickle\n\nimport tensorflow as tf\nfrom tensorflow import keras\nfrom tensorflow.keras import layers","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2022-07-14T20:17:15.022303Z","iopub.execute_input":"2022-07-14T20:17:15.022703Z","iopub.status.idle":"2022-07-14T20:17:15.029842Z","shell.execute_reply.started":"2022-07-14T20:17:15.022667Z","shell.execute_reply":"2022-07-14T20:17:15.028548Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# **Define functions**","metadata":{}},{"cell_type":"code","source":"#create binary mask from data in segmentation column in train.csv\ndef str2mask(maskStr,image):\n    #convert string of indices to numeric list\n    maskPixels = list(map(int, maskStr.split()))\n\n    #convert list to 2 column matrix in format [first pixel, pixel count]\n    maskPixels = np.array(maskPixels)\n    maskPixels = maskPixels.reshape(int(len(maskPixels)/2),2)\n\n    #create zeros matrix with dimensions of image\n    mask = np.zeros(image.shape, dtype=int)\n    #convert to vector\n    mask = mask.ravel()\n\n    # create binary mask from mask indices\n    for rows in maskPixels:\n        ii = rows[0] + list(range(0,rows[1]))\n        ii -=1\n        mask[ii] = 1\n\n    mask = np.array(mask)\n    mask = mask.reshape(np.shape(image))\n    return mask\n\n#convert binary mask to string of pixel indices as per train.csv\ndef mask2string(mask):\n    labelVector = measure.label(mask.ravel())\n    a = np.zeros([np.max(labelVector),2],dtype=int)\n    for ii in np.arange(0,a.shape[0]):\n        a[ii,0] = np.where(labelVector==ii+1)[0][0]\n        a[ii,1] = sum(labelVector==ii+1)\n    a = a.ravel()\n    string = \"\"\n    for x in a:\n        string = string + str(int(x)) + \" \"\n    string = string[0:(len(string)-1)]\n    return string\n\ndef mask2stringQuick(mask):    \n    # ref.: https://www.kaggle.com/stainsby/fast-tested-rle    \n    \"\"\" TBD Args: img (np.array):- 1 indicating mask  - 0 indicating background        \n    Returns:         run length as string formated    \"\"\"        \n    pixels = mask.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\n#extract case, day, slice information from ID\ndef interpretID(ID):\n    #id.split('_')\n    #extract numbers from ID string\n    [case,day,sliceNo] = re.findall(r'\\d+', ID)\n    return int(case), int(day), int(sliceNo)\n\n#define file path from root, case, day information\ndef imagePath(folder,case,day):\n    path = folder + '/case' + str(case) + '/case' + str(case) + '_day' + str(day) + '/scans'\n    return path\n\n#find all files in path\ndef filesInPath(path):\n    # create list of files in directory and print number of files\n    fileNames = [f for f in listdir(path) if isfile(join(path, f))]\n    return fileNames\n\n#import stack of all images in path\n#only used for initial visualisation - can be deleted\ndef importImageStack(path):\n    # create list of files in directory and print number of files\n    IMfiles = filesInPath(path)\n\n    #append all images in folder to an np array\n    IM = []\n    for file in IMfiles:\n        image = (2**16-1) * mpimg.imread(path + '/' + file)\n        IM.append(image)\n    return IMfiles, IM\n\n#compare filenames in path with ID information to determine correct filename\ndef findFrameIndex(ID,IMfiles):\n    frame = re.findall(r'\\d+', ID)[2]\n    allFrames = []\n    for row in IMfiles:\n        allFrames.append(re.findall(r'\\d+', row)[0])\n    i=0\n    ind = []\n    while i < len(IMfiles):\n        if frame == allFrames[i]:\n            ind.append(i)\n        i += 1\n    if len(ind)==1:\n        return ind[0]\n    else:\n        print('Error: multiple files found')\n        sys.exit(1)\n\n#find indices of masked entries in train.csv\ndef findMaskInd(strList):\n    #create logical list: true if a mask exists, false if no mask is provided\n    masked = trainData.segmentation != ''\n    maskInd = [i for i, x in enumerate(masked) if x]\n    return maskInd\n\n#change image dimensions to newsize\ndef imResize(im, mask, newsize):\n    im = im.resize(newsize)\n    mask = mask.resize(newsize)\n    return im, mask\n\n#reflect image in vertical axis\ndef imFlip(im, mask):\n    im = tf.image.flip_left_right(im)\n    mask = tf.image.flip_left_right(mask)\n    return im, mask\n    \n#rescale image by normalising with 'denominator'\ndef imNormalise(im, mask, denominator):\n    im = tf.cast(im, tf.float32) / denominator\n    #mask = tf.cast(mask, tf.float32)\n    return im, mask\n\ndef load_image_train(datapoint):\n    input_image = datapoint[\"image\"]\n    input_mask = datapoint[\"segmentation_mask\"]\n    input_image, input_mask = imResize(input_image, input_mask,(128,128))\n    #input_image, input_mask = augment(input_image, input_mask)\n    input_image, input_mask = imNormalize(input_image, input_mask, 2^16-1)\n    return input_image, input_mask\n\ndef load_image_test(datapoint):\n    input_image = datapoint[\"image\"]\n    input_mask = datapoint[\"segmentation_mask\"]\n    input_image, input_mask = imResize(input_image, input_mask)\n    input_image, input_mask = imNormalize(input_image, input_mask, 2^16-1)\n    return input_image, input_mask\n\ndef importSegData(trainData,ind):\n    #find ID associated with index (ind)\n    ID = trainData.id[ind]\n    #extract case number and day\n    [case,day, sliceNo] = interpretID(ID)\n    #define path directory of selected entry\n    folder = '../input/uw-madison-gi-tract-image-segmentation/train'\n    path = imagePath(folder,case,day)\n    #list filenames in path\n    fileNames = filesInPath(path)\n    #find index of ID in fileNames\n    ii = findFrameIndex(ID,fileNames)\n    #Import image\n    image = mpimg.imread(path + '/' + fileNames[ii])\n    \n    #read string of mask pixels\n    maskStr = trainData.segmentation[ind]\n    #convert string to binary mask\n    mask = str2mask(maskStr,image)\n\n    #return class of object\n    label = trainData.object[ind]\n    \n    return image, mask, label\n\ndef Sorensen_Dice(img_pred,img_res):\n    mask1 = img_pred>0\n    mask2 = img_res>0\n    return 2 * np.ma.sum(mask1 & mask2) / (np.ma.sum(mask1) + np.ma.sum(mask2))\n\ndef visualiseMasks(img,mask,ind):\n    colors = ['yellow','green','red']\n    labels = ['Large Bowel', 'Small Bowel', 'Stomach']\n    patches = [ mpatches.Patch(color=colors[i], label=f\"{labels[i]}\") for i in range(len(labels))]\n    cmap1 = mpl.colors.ListedColormap(colors[0])\n    cmap2 = mpl.colors.ListedColormap(colors[1])\n    cmap3= mpl.colors.ListedColormap(colors[2])\n\n    fig, ax = plt.subplots(nrows=1, ncols=1, figsize=(12, 5))\n\n    l1 = ax.imshow(img[ind,:,:,0], cmap='bone')\n    l2 = ax.imshow(np.ma.masked_where(mask[ind,:,:,0]== False,  mask[ind,:,:,0]), cmap=cmap1, alpha=0.5, label=labels[0])\n    l3 = ax.imshow(np.ma.masked_where(mask[ind,:,:,1]== False,  mask[ind,:,:,1]), cmap=cmap2, alpha=0.5, label=labels[1])\n    l4 = ax.imshow(np.ma.masked_where(mask[ind,:,:,2]== False,  mask[ind,:,:,2]), cmap=cmap3, alpha=0.5, label=labels[2])\n\n    plt.legend(handles=patches,fontsize=14,title='Mask Labels', title_fontsize=14, edgecolor=\"black\",bbox_to_anchor=(1.6, 0.65))\n    plt.show()","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2022-07-14T20:17:15.383802Z","iopub.execute_input":"2022-07-14T20:17:15.384758Z","iopub.status.idle":"2022-07-14T20:17:15.422510Z","shell.execute_reply.started":"2022-07-14T20:17:15.384712Z","shell.execute_reply":"2022-07-14T20:17:15.421513Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# **Read train.csv to data frame**","metadata":{}},{"cell_type":"code","source":"#define data root directory\nRoot = '../input/uw-madison-gi-tract-image-segmentation' \n\n#read train.csv data to list\nwith open(os.path.join(Root, \"train.csv\"), 'r') as file:\n    reader = csv.reader(file)\n    T = []\n    for row in reader:\n        T.append(row)\n\n#convert data (excluding column headers) to nparray\nnum = np.array(T[1:len(T)])\n\n#convert data to DataFrame\n#note that 'class' is a protected word in Python so the object class\n#column is renamed 'object'\ntrainData = pd.DataFrame(num, columns=['id','object','segmentation'])\n\n#Create list of all indices in trainData with a segmentation mask\nmaskInd = findMaskInd(trainData.segmentation)\n\nprint(f\"train.csv contains {len(trainData.segmentation)} entries\")\nprint(f\"{len(maskInd)} entries include masks, or {int(100*len(maskInd)/len(trainData.segmentation))} %.\")\n\n#print number of masks with each object label/class\nobjSet = set(trainData.object)\nfor obj in objSet:\n    print(f\"{obj}: {sum(trainData.object[maskInd]==obj)} masks\")","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2022-07-14T20:17:15.728636Z","iopub.execute_input":"2022-07-14T20:17:15.730612Z","iopub.status.idle":"2022-07-14T20:17:19.947255Z","shell.execute_reply.started":"2022-07-14T20:17:15.730564Z","shell.execute_reply":"2022-07-14T20:17:19.944897Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# **Restructure segmentation data**\nAssemble all masks associated with a particular image to one dataset and find file paths for each image ID","metadata":{}},{"cell_type":"code","source":"#reorganise data to create one unique dataset per image and collect all segmentation\n#masks corresponding to the image id\n\ndef organiseTrainingData(trainData):\n    uw_train = pd.DataFrame({'id':trainData['id'][::3]})\n\n    uw_train['large_bowel'] = trainData['segmentation'][::3].values\n    uw_train['small_bowel'] = trainData['segmentation'][1::3].values\n    uw_train['stomach'] = trainData['segmentation'][2::3].values\n\n    folder = '../input/uw-madison-gi-tract-image-segmentation/train'\n\n    case,day,sliceNo,path,filename,height,width = [],[],[],[],[],[],[]\n\n    for id in uw_train['id'].values:\n        [c,d,s] = interpretID(id)\n        p = imagePath(folder,c,d)\n        case.append(c)\n        day.append(d)\n        sliceNo.append(\"{:04n}\".format(s))\n        path.append(p)\n\n        #the following 3 lines to determine the filename corresponding to the ID\n        #are quite slow, can we find a more efficient way ?\n        fileNames = filesInPath(p)\n        ii = findFrameIndex(id,fileNames)\n        filename.append(fileNames[ii])\n    \n        [w,h] = re.findall(r'\\d+', fileNames[ii])[1:3]\n        width.append(int(w))\n        height.append(int(h))\n    \n    uw_train['case'] = case\n    uw_train['day'] = day\n    uw_train['slice'] = sliceNo\n    uw_train['path'] = path\n    uw_train['filename'] = filename\n    uw_train['width'] = width\n    uw_train['height'] = height\n    \n    uw_train.reset_index(inplace=True,drop=True)\n    uw_train.fillna('',inplace=True); \n    uw_train['count'] = np.sum(uw_train.iloc[:,1:4]!='',axis=1).values\n\n    return uw_train\n\nuw_train = organiseTrainingData(trainData)","metadata":{"execution":{"iopub.status.busy":"2022-07-14T20:17:19.950163Z","iopub.execute_input":"2022-07-14T20:17:19.951728Z","iopub.status.idle":"2022-07-14T20:18:42.585760Z","shell.execute_reply.started":"2022-07-14T20:17:19.951681Z","shell.execute_reply":"2022-07-14T20:18:42.584752Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# **Create 'DataGenerator' class**\nEfficient image and mask importing and pre-processing for data training","metadata":{}},{"cell_type":"code","source":"from tqdm.auto import tqdm\n\nclass DataGenerator(tf.keras.utils.Sequence):\n    def __init__(self,data, batch_size = 32, subset=\"train\", shuffle=False,random_state=17):\n        self.data=data\n        self.subset=subset\n        self.batch_size = batch_size\n        self.shuffle = shuffle\n        self.random_state = random_state\n        self.on_epoch_end()\n        \n    def __len__(self):\n        'Denotes the number of batches per epoch'\n        return int(np.floor(self.data.shape[0] / self.batch_size))\n        \n    def on_epoch_end(self):\n        'Updates indexes after each epoch'\n        np.random.seed(self.random_state)\n        self.indexes = np.arange(self.data.shape[0])\n        if self.shuffle == True:\n            np.random.shuffle(self.indexes)\n\n    def __getitem__(self, index): \n        X = np.empty((self.batch_size,128,128,3))\n        y = np.empty((self.batch_size,128,128,3))\n        indexes = self.indexes[index*self.batch_size:(index+1)*self.batch_size]\n        for i,filename in enumerate(self.data['filename'].iloc[indexes]):\n            w=self.data['width'].iloc[indexes[i]]\n            h=self.data['height'].iloc[indexes[i]]\n            \n            img_path = self.data.path.iloc[indexes[i]] + '/' + filename\n            img = self.__load_grayscale(img_path)\n            X[i,] =img\n            if self.subset == 'train':\n                for k,j in zip([0,1,2],[\"large_bowel\",\"small_bowel\",\"stomach\"]):\n                    masks = str2mask(self.data[j].iloc[indexes[i]],np.empty((h,w)))\n                    masks = cv2.resize(masks.astype('uint8'), (128, 128))\n                    y[i,:,:,k] = masks\n        if self.subset == 'train': return X, y\n        else: return X\n        #return X,y\n    \n    def __load_grayscale(self, img_path):\n        img = cv2.imread(img_path, cv2.IMREAD_ANYDEPTH)\n        dsize = (128, 128)\n        img = cv2.resize(img, dsize)\n        img = img.astype(np.float32) / 255.\n        img = np.expand_dims(img, axis=-1)\n        return img\n","metadata":{"execution":{"iopub.status.busy":"2022-07-14T20:18:42.587101Z","iopub.execute_input":"2022-07-14T20:18:42.587463Z","iopub.status.idle":"2022-07-14T20:18:42.604913Z","shell.execute_reply.started":"2022-07-14T20:18:42.587428Z","shell.execute_reply":"2022-07-14T20:18:42.603963Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# **Import segmentation models and define model structure**\nWe will use a Unet model with a Resnet34 backbone for multichannel segmentation model with no overlapping masks\nSee https://github.com/qubvel/segmentation_models for segmentation model documentation","metadata":{}},{"cell_type":"code","source":"! pip install segmentation-models\n! pip install git+https://github.com/qubvel/segmentation_models    \n\nimport segmentation_models as sm\n\n#multichannel segmentation model with no overlapping masks\nsm.set_framework('tf.keras')\nBACKBONE = 'resnet34'\npreprocess_input = sm.get_preprocessing(BACKBONE)","metadata":{"execution":{"iopub.status.busy":"2022-07-14T20:18:42.607609Z","iopub.execute_input":"2022-07-14T20:18:42.608076Z","iopub.status.idle":"2022-07-14T20:19:14.425972Z","shell.execute_reply.started":"2022-07-14T20:18:42.608023Z","shell.execute_reply":"2022-07-14T20:19:14.424721Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"! pip install tensorflow_addons\nfrom sklearn import model_selection\nimport tensorflow_addons as tfa\n\n#Load data set indexes\nids = np.arange(uw_train.shape[0])\n\n# Shuffle split to perform Cross-Validation\nCVShuffle = model_selection.ShuffleSplit(n_splits=1, test_size=0.2, train_size=0.8, random_state=17)\n\ndict_history = {\"iksplit\":[]}\n\n# define callbacks for learning rate scheduling and best checkpoints saving\ncallbck = [\n    tfa.callbacks.TQDMProgressBar(),\n    keras.callbacks.ModelCheckpoint('./scalian_model1', save_weights_only=True, save_best_only=True, mode='min'),\n    keras.callbacks.ReduceLROnPlateau(),\n]","metadata":{"execution":{"iopub.status.busy":"2022-07-14T20:19:14.429125Z","iopub.execute_input":"2022-07-14T20:19:14.429529Z","iopub.status.idle":"2022-07-14T20:19:23.831514Z","shell.execute_reply.started":"2022-07-14T20:19:14.429488Z","shell.execute_reply":"2022-07-14T20:19:23.830126Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# **Train Unet model**\nSplit training data into training and validation sets and launch training","metadata":{}},{"cell_type":"code","source":"weights = pickle.load(open('../input/model-weights/model_weights1','rb'))\nmodel = sm.Unet(BACKBONE, classes=3, activation='sigmoid')\nmodel.compile(\n    'Adam',\n    loss=[sm.losses.bce_jaccard_loss,sm.losses.DiceLoss()],\n    metrics=[sm.metrics.iou_score]\n)\n\n#model.load_weights('weights') \n#weights","metadata":{"execution":{"iopub.status.busy":"2022-07-14T20:19:23.834815Z","iopub.execute_input":"2022-07-14T20:19:23.835213Z","iopub.status.idle":"2022-07-14T20:19:27.123539Z","shell.execute_reply.started":"2022-07-14T20:19:23.835173Z","shell.execute_reply":"2022-07-14T20:19:27.122505Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"for iksplit, (train_indexes,validation_indexes) in enumerate(CVShuffle.split(ids)):\n    print(\"Num split: %s, train_size=%s , val_size=%s\" % (iksplit,len(train_indexes),len(validation_indexes)))\n    model = sm.Unet(BACKBONE, classes=3, activation='sigmoid')\n    model.compile(\n        'Adam',\n        loss=[sm.losses.bce_jaccard_loss,sm.losses.DiceLoss()],\n        metrics=[sm.metrics.iou_score]\n    )\n    \n    training_generator = DataGenerator(uw_train.iloc[train_indexes],batch_size = 256, shuffle=True)\n    validation_generator = DataGenerator(uw_train.iloc[validation_indexes],batch_size = 256, shuffle=True)\n\n    model.fit(training_generator,\n              epochs=20,\n              validation_data=validation_generator,\n              verbose=0,\n              #callbacks=[tqdm_callback]\n              callbacks = callbck\n             )\n    print(model.history)\n    dict_history[\"iksplit\"].append(model.history)\n    \nplt.figure(figsize=(30, 5))\nplt.subplot(121)\nplt.plot(model.history.history['iou_score'])\nplt.plot(model.history.history['val_iou_score'])\nplt.legend([\"Train\",\"Validate\"])\nplt.ylabel('iou_score')\nplt.xlabel('Epoch')\n\nplt.subplot(122)\nplt.plot(model.history.history['loss'])\nplt.plot(model.history.history['val_loss'])\nplt.legend([\"Train\",\"Validate\"])\nplt.ylabel('Loss')\nplt.xlabel('Epoch')\n\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2022-07-14T20:19:27.125117Z","iopub.execute_input":"2022-07-14T20:19:27.125452Z","iopub.status.idle":"2022-07-14T21:32:12.278539Z","shell.execute_reply.started":"2022-07-14T20:19:27.125418Z","shell.execute_reply":"2022-07-14T21:32:12.277440Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# **Read test directory**\nChange folder name from 'train' to 'test' prior to submission.","metadata":{}},{"cell_type":"code","source":"def generateID(case,day,sliceNo):\n    ID = 'case' + str(case) + '_day' + str(day) + '_slice' + sliceNo\n    return ID\n\nRoot = '../input/uw-madison-gi-tract-image-segmentation' \n\n#change folder to 'test' for final submission\nfolder = 'test'\n\npath,filename,case,sliceNo,ID,day = [],[],[],[],[],[]\nheight,width,sliceSep1,sliceSep2 = [],[],[],[]\n\nfor dirname, _, filenames in os.walk(os.path.join(Root,folder)):\n    a = re.findall(r'\\d+', dirname)\n    for file in filenames:\n        path.append(dirname)\n        filename.append(file)\n        case.append(int(a[0]))\n        day.append(int(a[2]))\n        b = re.findall(r'\\d+', file)\n        sliceNo.append((b[0]))\n        ID.append(generateID(int(a[0]),int(a[2]),b[0]))\n        width.append(int(b[1]))\n        height.append(int(b[2]))\n        sliceSep1.append(int(b[3]) + float(b[4])/100)\n        sliceSep2.append(int(b[5]) + float(b[6])/100)\n        \nImageDataset = pd.DataFrame()\nImageDataset[\"ID\"] = ID\nImageDataset[\"case\"] = case\nImageDataset[\"day\"] = day\nImageDataset[\"slice\"] = sliceNo\nImageDataset[\"path\"] = path\nImageDataset[\"filename\"] = filename\nImageDataset[\"width\"] = width\nImageDataset[\"height\"] = height\nImageDataset[\"slice_separation1\"] = sliceSep1\nImageDataset[\"slice_separation2\"] = sliceSep2\n","metadata":{"execution":{"iopub.status.busy":"2022-07-14T21:32:12.280386Z","iopub.execute_input":"2022-07-14T21:32:12.281020Z","iopub.status.idle":"2022-07-14T21:32:12.301454Z","shell.execute_reply.started":"2022-07-14T21:32:12.280979Z","shell.execute_reply":"2022-07-14T21:32:12.300209Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# **Predict masks for test dataset**\nEncode segmentation masks as a string and print results to a csv file","metadata":{}},{"cell_type":"code","source":"def mask2stringQuick(mask):    \n    # ref.: https://www.kaggle.com/stainsby/fast-tested-rle    \n    \"\"\" TBD Args: img (np.array):- 1 indicating mask  - 0 indicating background        \n    Returns:         run length as string formated    \"\"\"        \n    pixels = mask.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\ntest_dataGenerator = DataGenerator(ImageDataset, subset = \"test\", batch_size=1, shuffle=False)\n\nmodel.load_weights('scalian_model1') \n\nID, obj, segmentation = [],[],[]\n\nfor ii in np.arange(0,ImageDataset.shape[0]):\n    img = test_dataGenerator[ii]\n    mask_pr = model.predict(img)\n    \n    #zerosImage = np.zeros(imsize)\n    for k,j in zip([0,1,2],[\"large_bowel\",\"small_bowel\",\"stomach\"]):\n        m = mask_pr[0,:,:,k]\n        threshold = 0.99\n        m = m > threshold\n        if np.count_nonzero(m) >= 1:\n            imsize = [ImageDataset[\"width\"][ii], ImageDataset[\"height\"][ii]]\n            m = cv2.resize(m.astype('uint8'), imsize)\n            seg = mask2stringQuick(m)\n        else:\n            seg = '';\n    \n        ID.append(ImageDataset[\"ID\"][ii])\n        segmentation.append(seg)\n        obj.append(j)\n    \ntestSegmentationData = pd.DataFrame()\ntestSegmentationData[\"id\"] = ID\ntestSegmentationData[\"class\"] = obj\ntestSegmentationData[\"predicted\"] = segmentation\n\ntestSegmentationData.sample\n\ntestSegmentationData.to_csv(\"./submission.csv\",index=False)","metadata":{"execution":{"iopub.status.busy":"2022-07-14T21:36:57.998792Z","iopub.execute_input":"2022-07-14T21:36:57.999623Z","iopub.status.idle":"2022-07-14T21:36:59.198464Z","shell.execute_reply.started":"2022-07-14T21:36:57.999580Z","shell.execute_reply":"2022-07-14T21:36:59.197433Z"},"trusted":true},"execution_count":null,"outputs":[]}]}