{"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":"%matplotlib inline\n#這是juoyter notebook的magic word˙\n\nimport matplotlib\nimport matplotlib.pyplot as plt\nfrom IPython import display","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2022-07-05T09:36:46.075655Z","iopub.execute_input":"2022-07-05T09:36:46.076879Z","iopub.status.idle":"2022-07-05T09:36:46.103615Z","shell.execute_reply.started":"2022-07-05T09:36:46.076732Z","shell.execute_reply":"2022-07-05T09:36:46.102502Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Madison GI Tract Image Segmentation","metadata":{}},{"cell_type":"code","source":"import os\n#判斷是否在jupyter notebook上\ndef is_in_ipython():\n    \"Is the code running in the ipython environment (jupyter including)\"\n    program_name = os.path.basename(os.getenv('_', ''))\n\n    if ('jupyter-notebook' in program_name or # jupyter-notebook\n        'ipython'          in program_name or # ipython\n        'jupyter' in program_name or  # jupyter\n        'JPY_PARENT_PID'   in os.environ):    # ipython-notebook\n        return True\n    else:\n        return False\n\n\n#判斷是否在colab上\ndef is_in_colab():\n    if not is_in_ipython(): return False\n    try:\n        from google import colab\n        return True\n    except: return False\n\n#判斷是否在kaggke_kernal上\ndef is_in_kaggle_kernal():\n    if 'kaggle' in os.environ['PYTHONPATH']:\n        return True\n    else:\n        return False\n\nif is_in_colab():\n    from google.colab import drive\n    drive.mount('/content/gdrive')","metadata":{"execution":{"iopub.status.busy":"2022-07-05T09:36:46.106865Z","iopub.execute_input":"2022-07-05T09:36:46.107221Z","iopub.status.idle":"2022-07-05T09:36:46.115792Z","shell.execute_reply.started":"2022-07-05T09:36:46.107194Z","shell.execute_reply":"2022-07-05T09:36:46.114708Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"os.environ['TRIDENT_BACKEND'] = 'pytorch'\n\nif is_in_kaggle_kernal():\n    os.environ['TRIDENT_HOME'] = './trident'\n    \nelif is_in_colab():\n    os.environ['TRIDENT_HOME'] = '/content/gdrive/My Drive/trident'\n\n#為確保安裝最新版 \n!pip uninstall tridentx -y\n!pip install ../input/trident/tridentx-0.7.5-py3-none-any.whl --upgrade\nimport json\nimport copy\nimport numpy as np\nfrom PIL import Image\n#調用trident api\nimport trident as T\nfrom trident import *\nfrom trident.models import resnet,efficientnet,bisenet,densenet\nimport random","metadata":{"execution":{"iopub.status.busy":"2022-07-05T09:36:46.182560Z","iopub.execute_input":"2022-07-05T09:36:46.183320Z","iopub.status.idle":"2022-07-05T09:37:05.864830Z","shell.execute_reply.started":"2022-07-05T09:36:46.183281Z","shell.execute_reply":"2022-07-05T09:37:05.863726Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"首先讀取train.csv，將案例編號、日期以及斷層掃描切片信息自id中拆解出來。","metadata":{}},{"cell_type":"code","source":"import glob\nimport pandas as pd\n#讀取csv\ndf = pd.read_csv('../input/uw-madison-gi-tract-image-segmentation/train.csv')\nprint(df)\n#從id中擷取案例、日期、切片\ndf[\"case\"] = df[\"id\"].apply(lambda x: int(x.split(\"_\")[0].replace(\"case\", \"\")))\ndf[\"day\"] = df[\"id\"].apply(lambda x: int(x.split(\"_\")[1].replace(\"day\", \"\")))\ndf[\"slice\"] = df[\"id\"].apply(lambda x: x.split(\"_\")[3])","metadata":{"execution":{"iopub.status.busy":"2022-07-05T09:37:05.868301Z","iopub.execute_input":"2022-07-05T09:37:05.868957Z","iopub.status.idle":"2022-07-05T09:37:06.620056Z","shell.execute_reply.started":"2022-07-05T09:37:05.868927Z","shell.execute_reply":"2022-07-05T09:37:06.618989Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"移除錯誤案例","metadata":{}},{"cell_type":"code","source":"#移除錯誤案例\nfault1 = 'case7_day0'\nfault2 = 'case81_day30'\ndf = df[~df['id'].str.contains(fault1) & ~df['id'].str.contains(fault2)].reset_index(drop=True)","metadata":{"execution":{"iopub.status.busy":"2022-07-05T09:37:06.621858Z","iopub.execute_input":"2022-07-05T09:37:06.622292Z","iopub.status.idle":"2022-07-05T09:37:06.774485Z","shell.execute_reply.started":"2022-07-05T09:37:06.622251Z","shell.execute_reply":"2022-07-05T09:37:06.773402Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"根據id與圖檔名稱比對，從圖檔完整名稱中還可以獲取圖片長寬信息。","metadata":{}},{"cell_type":"code","source":"\n#訓練圖片根目錄\n# if (subset==\"train\") or (DEBUG):\nDIR=\"../input/uw-madison-gi-tract-image-segmentation/train\"\n# else:\n#     DIR=\"../input/uw-madison-gi-tract-image-segmentation/test\"\n\nall_images = glob.glob(os.path.join(DIR, \"**\", \"*.png\"), recursive=True)\nprint(len(all_images))\nx = all_images[0].rsplit(\"/\", 4)[0] \nprint(x)\n\npath_partial_list = []\nfor i in range(0, df.shape[0]):\n    path_partial_list.append(os.path.join(x,\n                          \"case\"+str(df[\"case\"].values[i]),\n                          \"case\"+str(df[\"case\"].values[i])+\"_\"+ \"day\"+str(df[\"day\"].values[i]),\n                          \"scans\",\n                          \"slice_\"+str(df[\"slice\"].values[i])))\ndf[\"path_partial\"] = path_partial_list\npath_partial_list = []\nfor i in range(0, len(all_images)):\n    path_partial_list.append(str(all_images[i].rsplit(\"_\",4)[0]))\n\ntmp_df = pd.DataFrame()\ntmp_df['path_partial'] = path_partial_list\ntmp_df['path'] = all_images\n\ndf = df.merge(tmp_df, on=\"path_partial\").drop(columns=[\"path_partial\"])\ndf[\"width\"] = df[\"path\"].apply(lambda x: int(x[:-4].rsplit(\"_\",4)[1]))\ndf[\"height\"] = df[\"path\"].apply(lambda x: int(x[:-4].rsplit(\"_\",4)[2]))\ndel x, path_partial_list, tmp_df\n\ndf","metadata":{"execution":{"iopub.status.busy":"2022-07-05T09:37:06.777613Z","iopub.execute_input":"2022-07-05T09:37:06.778088Z","iopub.status.idle":"2022-07-05T09:37:14.943547Z","shell.execute_reply.started":"2022-07-05T09:37:06.778049Z","shell.execute_reply":"2022-07-05T09:37:14.942430Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"確認圖片並非只有一種長寬規格。","metadata":{}},{"cell_type":"code","source":"print(df['width'].unique().tolist())\nprint(df['height'].unique().tolist())\nclassnames=df['class'].unique().tolist()\nclassnames=list(sorted(classnames))\nprint(classnames)","metadata":{"execution":{"iopub.status.busy":"2022-07-05T09:37:14.945389Z","iopub.execute_input":"2022-07-05T09:37:14.945905Z","iopub.status.idle":"2022-07-05T09:37:14.965617Z","shell.execute_reply.started":"2022-07-05T09:37:14.945865Z","shell.execute_reply":"2022-07-05T09:37:14.964284Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"將器官類別轉class_id","metadata":{}},{"cell_type":"code","source":"df['class_id'] = df.apply(lambda row:classnames.index(row['class'])+1,axis=1)\ndf","metadata":{"execution":{"iopub.status.busy":"2022-07-05T09:37:14.969054Z","iopub.execute_input":"2022-07-05T09:37:14.969374Z","iopub.status.idle":"2022-07-05T09:37:16.384482Z","shell.execute_reply.started":"2022-07-05T09:37:14.969339Z","shell.execute_reply":"2022-07-05T09:37:16.383431Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"mask的標註方式是基於RLE-encoded，以下是轉換的工具函數","metadata":{}},{"cell_type":"code","source":"def enc2mask(enc, shape=(266,266),fill_value=0):\n    \n    img = np.zeros(shape[0]*shape[1], dtype=np.uint8)\n    if isinstance(enc,float):\n        return img.reshape(shape)\n    else:\n        s = enc.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        \n        for lo, hi in zip(starts, ends):\n            img[lo:hi] = fill_value\n        return img.reshape(shape)  \n\n\n\ndef mask2enc(mask, n=4):\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\ndef label2color(label_mask,palette):\n    num_classes = len(palette)\n\n    color_label= np.zeros((*label_mask.shape,3)).astype(np.int64)\n    for i in range(num_classes):\n        color_label[label_mask==i]=palette[i]\n    return color_label","metadata":{"execution":{"iopub.status.busy":"2022-07-05T09:37:16.386171Z","iopub.execute_input":"2022-07-05T09:37:16.386638Z","iopub.status.idle":"2022-07-05T09:37:16.397872Z","shell.execute_reply.started":"2022-07-05T09:37:16.386598Z","shell.execute_reply":"2022-07-05T09:37:16.396625Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"將pandas.dataframe中的RLE-encoded轉換為mask","metadata":{}},{"cell_type":"code","source":"\ndf['mask'] = df.apply(lambda row: enc2mask(enc=row.segmentation, shape=(row.height,row.width),fill_value=row.class_id),axis=1)\ndf","metadata":{"execution":{"iopub.status.busy":"2022-07-05T09:37:16.399483Z","iopub.execute_input":"2022-07-05T09:37:16.400038Z","iopub.status.idle":"2022-07-05T09:37:31.593788Z","shell.execute_reply.started":"2022-07-05T09:37:16.399998Z","shell.execute_reply":"2022-07-05T09:37:31.592429Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"找一個案例測試mask解析","metadata":{}},{"cell_type":"code","source":"palette = [(0, 0, 0),(256, 192, 0), (0, 192, 256), (128, 0, 256), (256,64,0)]\ndf_mask=df['height']==310\nfiltered_df = df[df_mask]\n\nmasked_dict={}\nfor index, row in filtered_df.iterrows():\n    if isinstance(row['segmentation'],str):\n        if row['id'] not in masked_dict:\n            masked_dict[row['id']]=row['mask']\n\n        else:\n            mask=row['mask']>0\n            masked_dict[row['id']][mask]=row['mask'][mask]\n    \n\nprint(list(masked_dict.keys())[:5])\ncolor_label=label2color(masked_dict['case133_day0_slice_0047'],palette=palette)\ndisplay.display(array2image(color_label))","metadata":{"execution":{"iopub.status.busy":"2022-07-05T09:37:31.595864Z","iopub.execute_input":"2022-07-05T09:37:31.596325Z","iopub.status.idle":"2022-07-05T09:37:33.610863Z","shell.execute_reply.started":"2022-07-05T09:37:31.596283Z","shell.execute_reply":"2022-07-05T09:37:33.609824Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"視覺化","metadata":{}},{"cell_type":"code","source":"al=AutoLevel()\ncl=CLAHE()\ndef display_xy_imgs(CASE, DAY, slice_list,process=None):\n\n    plot_line = math.ceil(len(slice_list)/5)\n    \n    # 取得圖像路徑\n    TRAIN_DIR='../input/uw-madison-gi-tract-image-segmentation/train/case'+CASE+'/case'+CASE+'_day'+DAY+'/scans/'\n    train_images = glob.glob(os.path.join(TRAIN_DIR, '**', '*.png'), recursive=True)\n    train_images = sorted(train_images)\n    \n    # 顯示圖像\n    fig = plt.figure(figsize=(20,plot_line*4))\n    i=1\n    for slice_i in slice_list:\n        ax = fig.add_subplot(plot_line,5,i)\n        ax.set_title('slice ' + str(slice_i))\n   \n        im =image2array(train_images[slice_i-1])\n        if process is None:\n            pass\n        elif process =='autolevel':\n            im=al(im)\n        elif process =='clahe':\n            \n            im=255*(im/im.max())\n            im=np.stack([im,im,im],axis=-1)\n            im=cl(im)[:,:,0]\n            \n            \n        img = ax.imshow(im,cmap=plt.cm.jet)\n        cbar = fig.colorbar(img, ax=ax, aspect=50, pad=0.08, shrink=0.9, orientation='vertical')\n        i+=1\n    plt.suptitle('case' + CASE + ' day' + DAY,fontsize=16)\n    plt.show()","metadata":{"execution":{"iopub.status.busy":"2022-07-05T09:37:33.615297Z","iopub.execute_input":"2022-07-05T09:37:33.615940Z","iopub.status.idle":"2022-07-05T09:37:33.627440Z","shell.execute_reply.started":"2022-07-05T09:37:33.615890Z","shell.execute_reply":"2022-07-05T09:37:33.626333Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"CASE = '2'\nDAY = '1'\nslice_list = range(1,144,10)\n\ndisplay_xy_imgs(CASE, DAY, slice_list)","metadata":{"execution":{"iopub.status.busy":"2022-07-05T09:37:33.628842Z","iopub.execute_input":"2022-07-05T09:37:33.629301Z","iopub.status.idle":"2022-07-05T09:37:36.430742Z","shell.execute_reply.started":"2022-07-05T09:37:33.629260Z","shell.execute_reply":"2022-07-05T09:37:36.429667Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"display_xy_imgs(CASE, DAY, slice_list,process='autolevel')","metadata":{"execution":{"iopub.status.busy":"2022-07-05T09:37:36.431999Z","iopub.execute_input":"2022-07-05T09:37:36.432486Z","iopub.status.idle":"2022-07-05T09:37:38.758132Z","shell.execute_reply.started":"2022-07-05T09:37:36.432433Z","shell.execute_reply":"2022-07-05T09:37:38.757026Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"display_xy_imgs(CASE, DAY, slice_list,process='clahe')","metadata":{"execution":{"iopub.status.busy":"2022-07-05T09:37:38.759718Z","iopub.execute_input":"2022-07-05T09:37:38.760351Z","iopub.status.idle":"2022-07-05T09:37:41.505027Z","shell.execute_reply.started":"2022-07-05T09:37:38.760309Z","shell.execute_reply":"2022-07-05T09:37:41.500519Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"事先準備所需圖片，將灰階圖片加上前後slice，變成3通道圖片。由於斷層掃描並非圖片，所以需要事先將數據除以最大值後乘上255來做校準。","metadata":{}},{"cell_type":"code","source":"\nfrom mpl_toolkits.mplot3d.art3d import Poly3DCollection\nimport numpy as np\nfrom skimage import measure\nimport scipy\n\ndef plot_3d(image, threshold=-300): \n    p = image.transpose(2,1,0)\n    verts, faces, normals, values = measure.marching_cubes_lewiner(p, threshold)\n    fig = plt.figure(figsize=(10, 10))\n    ax = fig.add_subplot(111, projection='3d')\n    mesh = Poly3DCollection(verts[faces], alpha=0.1)\n    face_color = [0.5, 0.5, 1]\n    mesh.set_facecolor(face_color)\n    ax.add_collection3d(mesh)\n    ax.set_xlim(0, p.shape[0])\n    ax.set_ylim(0, p.shape[1])\n    ax.set_zlim(0, p.shape[2])\n    \n\n    plt.show()\n\n\n\nimages=list(sorted(glob.glob('../input/uw-madison-gi-tract-image-segmentation/train/case2/case2_day1/scans/*.png')))\nimages=[image2array(im) for im in images ]\nimages=np.stack([255*(im/im.max()) if im.max()>0 else im for im in images],axis=0)\n\n\n#計算出放大參數後，用scipy對維照片進行縮放，scipy會自動為圖片進行插補\nimages = scipy.ndimage.interpolation.zoom(images, (1,0.5,0.5), mode='nearest')\nprint(images.shape)\n\nplot_3d(images.copy(),threshold=120)","metadata":{"execution":{"iopub.status.busy":"2022-07-05T09:37:41.506616Z","iopub.execute_input":"2022-07-05T09:37:41.507304Z","iopub.status.idle":"2022-07-05T09:38:28.948708Z","shell.execute_reply.started":"2022-07-05T09:37:41.507258Z","shell.execute_reply":"2022-07-05T09:38:28.947626Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# from tqdm import tqdm\n# images=[]\n# merge_images=[]\n# masks=[]\n# masked_dict={}\n# ids=list(sorted(df['id'].unique().tolist()))\n# make_dir_if_need('./maskes/train')\n# make_dir_if_need('./images/train')\n# images_list=list(sorted(glob.glob('../input/uw-madison-gi-tract-image-segmentation/train/*/*/*/*.png')))\n\n\n\n# for k in tqdm(range(len(ids))):\n#     this_id=ids[k]\n#     df_mask=df['id']==this_id\n#     filtered_df = df[df_mask]\n#     img_path=None\n    \n#     if len(filtered_df)==0:\n#         print(this_id,'not found!')\n#     else:\n#         for index, row in filtered_df.iterrows():\n#             #print(index,row['path'])\n#             if img_path is None:\n#                 img_path=row['path']\n#             if this_id not in masked_dict:\n#                 masked_dict[this_id]=row['mask']\n                \n#             else:\n#                 mask=row['mask']>0\n#                 masked_dict[this_id][mask]=row['mask'][mask]\n    \n#         array2mask(masked_dict[this_id]).save('./maskes/train/{0}.png'.format(this_id))\n\n#         img_idx=images_list.index(img_path)\n#         prev_img=image2array(img_path)\n#         prev_img=255*(prev_img/prev_img.max())\n#         current_img=image2array(img_path)\n#         current_img=255*(current_img/current_img.max())\n#         next_img=image2array(img_path)\n#         next_img=255*(next_img/next_img.max())\n\n\n#         if img_idx>0 and images_list[img_idx-1].split('slice_')[0]==img_path.split('slice_')[0]:\n#             prev_img=image2array(images_list[img_idx-1])\n#             prev_img=255*(prev_img/prev_img.max())\n#         if img_idx+1<len(images_list) and images_list[img_idx+1].split('slice_')[0]==img_path.split('slice_')[0]:\n#             next_img=image2array(images_list[img_idx+1])\n#             next_img=255*(next_img/next_img.max())\n#         merge_im=np.stack([prev_img,current_img,next_img],axis=-1)\n#         array2image(merge_im).save('./images/train/{0}.png'.format(this_id))\n        \n#         del prev_img\n#         del current_img\n#         del next_img\n#         del merge_im\n        \n\n#         images.append(img_path)\n#         merge_images.append('./images/train/{0}.png'.format(this_id))\n#         masks.append('./maskes/train/{0}.png'.format(this_id))\n    \n    \n        \n# print(len(images))\n# print(len(merge_images))\n# print(len(masks))","metadata":{"execution":{"iopub.status.busy":"2022-07-05T09:38:28.950382Z","iopub.execute_input":"2022-07-05T09:38:28.951005Z","iopub.status.idle":"2022-07-05T09:38:28.958775Z","shell.execute_reply.started":"2022-07-05T09:38:28.950965Z","shell.execute_reply":"2022-07-05T09:38:28.957683Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"排除異常mask(出現255)","metadata":{}},{"cell_type":"code","source":"# merge_images=glob.glob('../input/uwmgi-images/images/images/train/*.png')\n# masks=[impath.replace('images/images/train','maskes/maskes/train') for impath in merge_images]\nmerge_images=[]\nmasks=[]\nfor impath in glob.glob('../input/uwmgi-images/images/images/train/*.png'):\n    folder,filename,ext=split_path(impath)\n    this_unique=np.unique(mask2array(impath.replace('images/images/train','maskes/maskes/train')))\n    if 255.0 not in  this_unique:\n        merge_images.append(impath)\n        masks.append(impath.replace('images/images/train','maskes/maskes/train'))\n    \n    \n","metadata":{"execution":{"iopub.status.busy":"2022-07-05T09:38:28.960284Z","iopub.execute_input":"2022-07-05T09:38:28.961723Z","iopub.status.idle":"2022-07-05T09:42:50.157369Z","shell.execute_reply.started":"2022-07-05T09:38:28.961673Z","shell.execute_reply":"2022-07-05T09:42:50.156225Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import torch\nimport gc\ntorch.cuda.synchronize()\ntorch.cuda.empty_cache()\ngc.collect()","metadata":{"execution":{"iopub.status.busy":"2022-07-05T09:42:50.161325Z","iopub.execute_input":"2022-07-05T09:42:50.162732Z","iopub.status.idle":"2022-07-05T09:42:53.711572Z","shell.execute_reply.started":"2022-07-05T09:42:50.162688Z","shell.execute_reply":"2022-07-05T09:42:53.710132Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"建構data provider","metadata":{}},{"cell_type":"code","source":"ds1=ImageDataset(merge_images,object_type=ObjectType.rgb,symbol='images')\nds2=MaskDataset(masks,object_type=ObjectType.label_mask,symbol='maskes')\n\n\nsample_filter=lambda x:x[-1].max()>0 or random.random()>=0.75\n\ndata_provider=DataProvider(traindata=Iterator(data=ds1,label=ds2,sample_filter=sample_filter))\n\n\n\n\n\ndata_provider.paired_transform_funcs=[\n    RandomTransform(rotation_range=0, zoom_range=(0.9,1.2), shift_range=0.05, shear_range=0.0, random_flip=0,keep_prob=0.3,border_mode='zero'), \n    RandomCrop((224,224))]\n\ndata_provider.image_transform_funcs=[\n    AutoLevel(),\n    RandomAdjustGamma(scale=(0.8,1.2)),#調整明暗\n    RandomAdjustHue(scale=(-0.2,0.2)),#調整色相\n    RandomAdjustSaturation(scale=(0.8,1.2)),#調整飽和度\n    SaltPepperNoise(0.005, keep_prob=0.5),#加入胡椒鹽噪音\n    RandomErasing(size_range=(0.05, 0.2), transparency_range=(0.4, 0.8), transparancy_ratio=1.0, keep_prob=0.5), #加入隨機擦去\n    Normalize(127.5,127.5)]\nprint(data_provider.signature)","metadata":{"execution":{"iopub.status.busy":"2022-07-05T09:42:53.713275Z","iopub.execute_input":"2022-07-05T09:42:53.714111Z","iopub.status.idle":"2022-07-05T09:42:53.767869Z","shell.execute_reply.started":"2022-07-05T09:42:53.714069Z","shell.execute_reply":"2022-07-05T09:42:53.766761Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"_data,_mask=data_provider.next()\nprint(np.unique(_mask))\nprint(_data.shape,_data.dtype)\nprint(_mask.shape,_mask.dtype)\n\n","metadata":{"execution":{"iopub.status.busy":"2022-07-05T09:42:53.769474Z","iopub.execute_input":"2022-07-05T09:42:53.769861Z","iopub.status.idle":"2022-07-05T09:42:53.953525Z","shell.execute_reply.started":"2022-07-05T09:42:53.769824Z","shell.execute_reply":"2022-07-05T09:42:53.952474Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"預覽圖片","metadata":{}},{"cell_type":"code","source":"data_provider.preview_images()\n","metadata":{"execution":{"iopub.status.busy":"2022-07-05T09:42:53.954884Z","iopub.execute_input":"2022-07-05T09:42:53.955606Z","iopub.status.idle":"2022-07-05T09:42:54.256463Z","shell.execute_reply.started":"2022-07-05T09:42:53.955566Z","shell.execute_reply":"2022-07-05T09:42:54.255457Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"tiramisu = densenet.DenseNetFcn(blocks=(4,4,5,5,6), growth_rate=16, initial_filters=32, num_classes=4)\n#tiramisu.load_model('../input/madison-gi-tract-image-segmentation/Models/tiramisu.pth.tar')\ntiramisu.load_model('./Models/tiramisu.pth.tar')\ntiramisu.summary()","metadata":{"execution":{"iopub.status.busy":"2022-07-05T09:42:54.258035Z","iopub.execute_input":"2022-07-05T09:42:54.258652Z","iopub.status.idle":"2022-07-05T09:43:00.430956Z","shell.execute_reply.started":"2022-07-05T09:42:54.258614Z","shell.execute_reply":"2022-07-05T09:43:00.429876Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"bisenetv2=ImageSegmentationModel(input_shape=(3,224,224), output=bisenet.BiSeNetV2(n_classes=4))\n#bisenetv2.load_model('../input/madison-gi-tract-image-segmentation/Models/bisenetv2.pth')\nbisenetv2.load_model('./Models/bisenetv2.pth.tar')\nbisenetv2.summary()","metadata":{"execution":{"iopub.status.busy":"2022-07-05T09:43:00.432873Z","iopub.execute_input":"2022-07-05T09:43:00.433684Z","iopub.status.idle":"2022-07-05T09:43:01.204376Z","shell.execute_reply.started":"2022-07-05T09:43:00.433640Z","shell.execute_reply":"2022-07-05T09:43:01.203144Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def draw_seg_image(training_context):\n    palette = [(0, 0, 0),(256, 192, 0), (0, 192, 256), (128, 0, 256), (256,64,0)]\n    data_feed = training_context['data_feed']\n    data = training_context['train_data']\n    model = training_context['current_model']\n    output_data=data[data_feed['output']]\n    target_data=to_numpy(data['maskes'])\n    input_data=to_numpy(data['images'])\n    output_data=np.argmax(to_numpy(output_data),1)\n    tile_images_list=[]\n    input_arr = []\n    target_arr=[]\n    output_arr=[]\n    output_arr1=[]\n    for i in range(len(output_data)):\n        input_arr.append(image_backend_adaption(data_provider.reverse_image_transform(input_data[i])))\n    \n        target_arr.append(label2color(target_data[i],palette))\n        output_arr.append(label2color(output_data[i],palette))\n        img=image_backend_adaption(data_provider.reverse_image_transform(input_data[i])).transpose([1,2,0])\n        pred=output_data[i]\n        color_pred=label2color(output_data[i],palette)\n        #print(img.shape,pred.shape,color_pred.shape)\n        img[pred>0,:]=img[pred>0,:]*0.3+color_pred[pred>0,:]*0.7\n        output_arr1.append(img)\n    tile_images_list.append(input_arr)\n    tile_images_list.append(target_arr)\n    tile_images_list.append(output_arr)\n    tile_images_list.append(output_arr1)\n    fig = tile_rgb_images(*tile_images_list, save_path='Results/segtile_image_{0}.png', imshow=True)\n    plt.close()","metadata":{"execution":{"iopub.status.busy":"2022-07-05T09:43:01.206613Z","iopub.execute_input":"2022-07-05T09:43:01.207653Z","iopub.status.idle":"2022-07-05T09:43:01.220310Z","shell.execute_reply.started":"2022-07-05T09:43:01.207607Z","shell.execute_reply":"2022-07-05T09:43:01.219189Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import torch.nn.functional as F\n\ndef one_hot(label, n_classes):\n    \"\"\"Return One Hot Label\"\"\"\n    one_hot_label = torch.eye(n_classes, device=get_device())[label]\n    one_hot_label = one_hot_label.transpose(1, 3).transpose(2, 3)\n\n    return one_hot_label\n\ndef BoundaryLoss(output, target):\n    \"\"\"Boundary Loss proposed in:\n    Alexey Bokhovkin et al., Boundary Loss for Remote Sensing Imagery Semantic Segmentation\n    https://arxiv.org/abs/1905.07852\n    \"\"\"\n\n    theta0=3\n    theta=5\n    pred=exp(output)\n    gt=target\n    n, c, _, _ = pred.shape\n\n    # softmax so that predicted map can be distributed in [0, 1]\n\n\n    # one-hot vector of ground truth\n    one_hot_gt = one_hot(gt, c)\n\n    # boundary map\n    gt_b = F.max_pool2d(\n        1 - one_hot_gt, kernel_size=theta0, stride=1, padding=(theta0 - 1) // 2)\n    gt_b -= 1 - one_hot_gt\n\n    pred_b = F.max_pool2d(\n        1 - pred, kernel_size=theta0, stride=1, padding=(theta0 - 1) // 2)\n    pred_b -= 1 - pred\n\n    # extended boundary map\n    gt_b_ext = F.max_pool2d(\n        gt_b, kernel_size=theta, stride=1, padding=(theta - 1) // 2)\n\n    pred_b_ext = F.max_pool2d(\n        pred_b, kernel_size=theta, stride=1, padding=(theta - 1) // 2)\n\n    # reshape\n    gt_b = gt_b.view(n, c, -1)\n    pred_b = pred_b.view(n, c, -1)\n    gt_b_ext = gt_b_ext.view(n, c, -1)\n    pred_b_ext = pred_b_ext.view(n, c, -1)\n\n    # Precision, Recall\n    P = torch.sum(pred_b * gt_b_ext, dim=2) / (torch.sum(pred_b, dim=2) + 1e-7)\n    R = torch.sum(pred_b_ext * gt_b, dim=2) / (torch.sum(gt_b, dim=2) + 1e-7)\n\n    # Boundary F1 Score\n    BF1 = 2 * P * R / (P + R + 1e-7)\n\n    # summing BF1 Score for each class and average over mini-batch\n    loss = torch.mean(1 - BF1)\n\n    return loss\n","metadata":{"execution":{"iopub.status.busy":"2022-07-05T09:43:01.222183Z","iopub.execute_input":"2022-07-05T09:43:01.223329Z","iopub.status.idle":"2022-07-05T09:43:01.238893Z","shell.execute_reply.started":"2022-07-05T09:43:01.223289Z","shell.execute_reply":"2022-07-05T09:43:01.237452Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"tiramisu.with_optimizer(optimizer=DiffGrad,lr=2e-4,betas=(0.9, 0.999),gradient_centralization='all')\\\n    .with_loss(DiceLoss(axis=1),loss_weight=2)\\\n    .with_loss(CrossEntropyLoss(ignore_index=0,label_smooth=True,axis=1))\\\n    .with_loss(BoundaryLoss,loss_weight=1.5)\\\n    .with_loss(CrossEntropyLoss(ignore_index=0,enable_ohem=True,ohem_thresh=0.1,axis=1),loss_weight=0.1)\\\n    .with_loss(IoULoss(axis=1),start_epoch=1,loss_weight=0.5)\\\n    .with_metric(pixel_accuracy,name='pixel_accuracy',print_only=True)\\\n    .with_metric(iou,name='iou')\\\n    .with_accumulate_grads(5)\\\n    .with_regularizer('l2',reg_weight=1e-6)\\\n    .with_learning_rate_scheduler(CosineLR(min_lr=1e-5,period=3000))\\\n    .with_model_save_path('Models/tiramisu.pth')\\\n    .trigger_when(when='on_batch_end',frequency=50,action=draw_seg_image)\n\nbisenetv2.with_optimizer(optimizer=DiffGrad,lr=2e-4,betas=(0.9, 0.999),gradient_centralization='all')\\\n    .with_loss(DiceLoss(axis=1),loss_weight=2)\\\n    .with_loss(CrossEntropyLoss(ignore_index=0,label_smooth=True,axis=1))\\\n    .with_loss(BoundaryLoss,loss_weight=1.5)\\\n    .with_loss(CrossEntropyLoss(ignore_index=0,enable_ohem=True,ohem_thresh=0.1,axis=1),loss_weight=0.1)\\\n    .with_loss(IoULoss(axis=1),start_epoch=1,loss_weight=0.5)\\\n    .with_metric(pixel_accuracy,name='pixel_accuracy',print_only=True)\\\n    .with_metric(iou,name='iou')\\\n    .with_accumulate_grads(5)\\\n    .with_regularizer('l2',reg_weight=1e-6)\\\n    .with_learning_rate_scheduler(CosineLR(min_lr=1e-5,period=3000))\\\n    .with_model_save_path('Models/bisenetv2.pth')\\\n    .trigger_when(when='on_batch_end',frequency=50,action=draw_seg_image)","metadata":{"execution":{"iopub.status.busy":"2022-07-05T09:43:01.240864Z","iopub.execute_input":"2022-07-05T09:43:01.241416Z","iopub.status.idle":"2022-07-05T09:43:01.301963Z","shell.execute_reply.started":"2022-07-05T09:43:01.241378Z","shell.execute_reply":"2022-07-05T09:43:01.300957Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plan=TrainingPlan()\\\n    .add_training_item(tiramisu,name='tiramisu')\\\n    .add_training_item(bisenetv2,name='bisenetv2')\\\n    .with_data_loader(data_provider)\\\n    .repeat_epochs(30)\\\n    .with_batch_size(16)\\\n    .print_progress_scheduling(10,unit='batch')\\\n     .out_sample_evaluation_scheduling(frequency=50,unit='batch')\\\n    .display_loss_metric_curve_scheduling(frequency=100,unit='batch',imshow=True)\\\n    .save_model_scheduling(20,unit='batch')\\","metadata":{"execution":{"iopub.status.busy":"2022-07-05T09:43:01.303364Z","iopub.execute_input":"2022-07-05T09:43:01.304225Z","iopub.status.idle":"2022-07-05T09:43:01.311870Z","shell.execute_reply.started":"2022-07-05T09:43:01.304187Z","shell.execute_reply":"2022-07-05T09:43:01.310860Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"\nplan.start_now()","metadata":{"execution":{"iopub.status.busy":"2022-07-05T09:43:01.313585Z","iopub.execute_input":"2022-07-05T09:43:01.314571Z"},"trusted":true},"execution_count":null,"outputs":[]}]}