{"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":"# 0. Prepare 準備","metadata":{}},{"cell_type":"code","source":"import os\nimport cv2\nimport tifffile\nimport numpy as np\nimport pandas as pd\nimport matplotlib.pyplot as plt\nimport seaborn as sns\n#from PIL import Image\n#from PIL import ImageDraw\n\nfrom tqdm.notebook import tqdm","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","_kg_hide-input":true,"execution":{"iopub.status.busy":"2022-08-15T09:19:59.738307Z","iopub.execute_input":"2022-08-15T09:19:59.739150Z","iopub.status.idle":"2022-08-15T09:19:59.746540Z","shell.execute_reply.started":"2022-08-15T09:19:59.739102Z","shell.execute_reply":"2022-08-15T09:19:59.744822Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_train = pd.read_csv('../input/hubmap-organ-segmentation/train.csv')","metadata":{"execution":{"iopub.status.busy":"2022-08-15T09:19:59.748200Z","iopub.execute_input":"2022-08-15T09:19:59.748574Z","iopub.status.idle":"2022-08-15T09:19:59.898421Z","shell.execute_reply.started":"2022-08-15T09:19:59.748544Z","shell.execute_reply":"2022-08-15T09:19:59.896780Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#https://www.kaggle.com/code/pestipeti/decoding-rle-masks/notebook\ndef mask2rle(img):\n    '''\n    img: numpy array, 1 - mask, 0 - background\n    Returns run length as string formated\n    '''\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\n\ndef rle2mask(mask_rle, shape=(3000,3000)):\n    '''\n    mask_rle: run-length as string formated (start length)\n    shape: (width,height) of array to return \n    Returns numpy array, 1 - mask, 0 - background\n\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.int32)\n    for lo, hi in zip(starts, ends):\n        img[lo:hi] = 1\n    return img.reshape(shape).T","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2022-08-15T09:19:59.900198Z","iopub.execute_input":"2022-08-15T09:19:59.900561Z","iopub.status.idle":"2022-08-15T09:19:59.911668Z","shell.execute_reply.started":"2022-08-15T09:19:59.900527Z","shell.execute_reply":"2022-08-15T09:19:59.910149Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def show_image(idx):\n    fig, ax = plt.subplots(1,3,figsize=(12,12))\n    image = plt.imread(f\"../input/hubmap-organ-segmentation/train_images/{df_train.id[idx]}.tiff\")\n    mask = rle2mask(df_train.rle[idx],shape=(df_train.img_height[idx],df_train.img_width[idx]))\n    display(pd.DataFrame(df_train.loc[idx,['id','organ','age','sex']]).T)\n    ax[0].imshow(image)\n    ax[0].set_title(\"biopsy slide\")\n    ax[0].axis(\"off\")\n    ax[1].imshow(mask,alpha=0.3,cmap='gray')\n    ax[1].set_title(\"FTUs mask\")\n    ax[1].axis(\"off\")\n    ax[2].imshow(image)\n    ax[2].imshow(mask,alpha=0.3,cmap='gray')\n    ax[2].axis(\"off\")\n    plt.show()","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2022-08-15T09:19:59.913721Z","iopub.execute_input":"2022-08-15T09:19:59.914043Z","iopub.status.idle":"2022-08-15T09:19:59.924368Z","shell.execute_reply.started":"2022-08-15T09:19:59.914014Z","shell.execute_reply":"2022-08-15T09:19:59.923495Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Select index 適当な番号を選択\nidx=0\nshow_image(idx)","metadata":{"execution":{"iopub.status.busy":"2022-08-15T09:19:59.925814Z","iopub.execute_input":"2022-08-15T09:19:59.926308Z","iopub.status.idle":"2022-08-15T09:20:04.168361Z","shell.execute_reply.started":"2022-08-15T09:19:59.926274Z","shell.execute_reply":"2022-08-15T09:20:04.167225Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 1. Calculate Size and Count of FTUs サイズとカウントの計算","metadata":{}},{"cell_type":"code","source":"def fill_1mask(arr):\n    if arr.max()==0:\n        return\n    else:\n        y = np.where(arr>0)[0][0]\n        x = np.where(arr>0)[1][0]\n        h, w = arr.shape\n        mask = np.zeros((h+2, w+2), np.uint8)\n        retval,rimage,mask,rect = cv2.floodFill(cv2.UMat(arr), mask, (x,y), 0,flags=8)\n        return rimage.get()\n\ndef show_mask_per_one(idx):\n    arr = rle2mask(df_train.rle[idx],shape=(df_train.img_height[idx],df_train.img_width[idx]))\n    fig, ax = plt.subplots(1,1,figsize=(4,4))\n    ax.set_title('All FTUs')\n    ax.axis(\"off\")\n    ax.imshow(arr,cmap='gray')\n    \n    while arr.max()>0:\n        tmp = fill_1mask(arr)\n        fig, ax = plt.subplots(1,1,figsize=(4,4))\n        ax.imshow(arr - tmp,cmap='gray')\n        ax.set_title('pixel size {}'.format(sum(sum(arr - tmp))))\n        ax.axis(\"off\")\n        arr = tmp\n\ndef get_mask_size_per_one(idx):\n    arr = rle2mask(df_train.rle[idx],shape=(df_train.img_height[idx],df_train.img_width[idx]))\n    mask_size=[]\n    while arr.max()>0:\n        tmp = fill_1mask(arr)\n        mask_size.append(sum(sum(arr - tmp)))\n        arr = tmp\n    return(np.array(mask_size))","metadata":{"execution":{"iopub.status.busy":"2022-08-15T09:20:04.169805Z","iopub.execute_input":"2022-08-15T09:20:04.170166Z","iopub.status.idle":"2022-08-15T09:20:04.182543Z","shell.execute_reply.started":"2022-08-15T09:20:04.170134Z","shell.execute_reply":"2022-08-15T09:20:04.181111Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Calculate pixel size by filling FTUs one by one and taking the difference.<br>\nFTUを1つずつ塗りつぶして差分を取りながらピクセルサイズを計算する。","metadata":{}},{"cell_type":"code","source":"show_mask_per_one(idx)","metadata":{"execution":{"iopub.status.busy":"2022-08-15T09:20:04.183827Z","iopub.execute_input":"2022-08-15T09:20:04.184182Z","iopub.status.idle":"2022-08-15T09:20:15.574869Z","shell.execute_reply.started":"2022-08-15T09:20:04.184132Z","shell.execute_reply":"2022-08-15T09:20:15.573604Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Calculate on all training data and merge results into a data frame.<br>\n全ての学習データ351枚を計算し、結果をデータフレームに結合。","metadata":{}},{"cell_type":"code","source":"for idx in tqdm(range(len(df_train))):\n    tmp_mask_size = get_mask_size_per_one(idx)\n    tmp_mask_size = np.concatenate([[df_train.id[idx]]*len(tmp_mask_size), tmp_mask_size])\n    tmp_mask_size = np.reshape(tmp_mask_size,(2,int(len(tmp_mask_size)/2))).T\n    if idx == 0:\n        mask_size = tmp_mask_size.copy()\n    else:\n        mask_size = np.concatenate([mask_size, tmp_mask_size])","metadata":{"execution":{"iopub.status.busy":"2022-08-15T09:20:15.576051Z","iopub.execute_input":"2022-08-15T09:20:15.576433Z","iopub.status.idle":"2022-08-15T09:29:19.545331Z","shell.execute_reply.started":"2022-08-15T09:20:15.576399Z","shell.execute_reply":"2022-08-15T09:29:19.544129Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_train_size = pd.merge(df_train,\n                         pd.DataFrame(mask_size,columns=['id','FTU_pixel_size']),\n                         on='id',how='outer')\n\n# 画像ピクセルサイズに対するFTUのピクセルサイズの割合\ndf_train_size['FTU_size_rate'] = df_train_size['FTU_pixel_size']/(df_train_size['img_height']*df_train_size['img_width'])\n\n# FTUのカウントは、別DataFrameとして結合\ndf_train_count = pd.merge(df_train,\n                         df_train_size.groupby('id').count()['FTU_pixel_size'],\n                         on='id',how='inner')\ndf_train_count = df_train_count.rename(columns={'FTU_pixel_size': 'FTU_count'})","metadata":{"execution":{"iopub.status.busy":"2022-08-15T09:29:19.546512Z","iopub.execute_input":"2022-08-15T09:29:19.546820Z","iopub.status.idle":"2022-08-15T09:29:19.573722Z","shell.execute_reply.started":"2022-08-15T09:29:19.546791Z","shell.execute_reply":"2022-08-15T09:29:19.572485Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 2. Distribution Analysis 分布の分析\n### 2-1. Organ","metadata":{}},{"cell_type":"code","source":"plt.figure(figsize=(20, 6))\nplt.subplot(131)\nplt.title('FTU count')\nsns.boxplot(x='organ', y='FTU_count', data=df_train_count)\nplt.subplot(132)\nplt.title('FTU pixel size')\nsns.boxplot(x='organ', y='FTU_pixel_size', data=df_train_size)\nplt.subplot(133)\nplt.title('FTU size rate')\nsns.boxplot(x='organ', y='FTU_size_rate', data=df_train_size)\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2022-08-15T09:29:19.575749Z","iopub.execute_input":"2022-08-15T09:29:19.576287Z","iopub.status.idle":"2022-08-15T09:29:20.341446Z","shell.execute_reply.started":"2022-08-15T09:29:19.576218Z","shell.execute_reply":"2022-08-15T09:29:20.340631Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"- The largeintestine has a very large number of FTUs.<br>\n大腸はFTUの数が非常に多い。\n- The spleen has a large FTU size.<br>\n脾臓はFTUのサイズが大きい。","metadata":{}},{"cell_type":"markdown","source":"### 2-2. Organ $\\times$ Sex","metadata":{}},{"cell_type":"code","source":"for organ in df_train['organ'].unique():\n    fig=plt.figure(figsize=(20, 4))\n    fig.suptitle(organ,x=0.1,size=18, weight=2)\n    plt.subplot(131)\n    plt.title('FTU count')\n    sns.violinplot(x='sex',y='FTU_count', data=df_train_count[df_train_count.organ==organ])\n    plt.subplot(132)\n    plt.title('FTU pixel size')\n    sns.violinplot(x='sex',y='FTU_pixel_size', data=df_train_size[df_train_size.organ==organ])\n    plt.subplot(133)\n    plt.title('FTU size rate')\n    sns.violinplot(x='sex',y='FTU_size_rate', data=df_train_size[df_train_size.organ==organ])\n    plt.show()","metadata":{"execution":{"iopub.status.busy":"2022-08-15T09:29:20.342867Z","iopub.execute_input":"2022-08-15T09:29:20.343478Z","iopub.status.idle":"2022-08-15T09:29:22.640887Z","shell.execute_reply.started":"2022-08-15T09:29:20.343442Z","shell.execute_reply":"2022-08-15T09:29:22.639675Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"- There are no major differences in distribution by sex.<br>\n性別で分布に大きな違いはない。","metadata":{}},{"cell_type":"markdown","source":"### 2-3. Organ $\\times$ Age","metadata":{}},{"cell_type":"code","source":"for organ in df_train['organ'].unique():\n    fig=plt.figure(figsize=(20, 4))\n    fig.suptitle(organ,x=0.1,size=18, weight=2)\n    plt.subplot(131)\n    plt.title('FTU count')\n    sns.violinplot(x='age',y='FTU_count', data=df_train_count[df_train_count.organ==organ])\n    plt.subplot(132)\n    plt.title('FTU pixel size')\n    sns.violinplot(x='age',y='FTU_pixel_size', data=df_train_size[df_train_size.organ==organ])\n    plt.subplot(133)\n    plt.title('FTU size rate')\n    sns.violinplot(x='age',y='FTU_size_rate', data=df_train_size[df_train_size.organ==organ])\n    plt.show()","metadata":{"execution":{"iopub.status.busy":"2022-08-15T09:29:22.642461Z","iopub.execute_input":"2022-08-15T09:29:22.642910Z","iopub.status.idle":"2022-08-15T09:29:26.728371Z","shell.execute_reply.started":"2022-08-15T09:29:22.642865Z","shell.execute_reply":"2022-08-15T09:29:26.726955Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"- There are no major differences in distribution by age.<br>\n年齢でも分布に大きな違いはない。","metadata":{}},{"cell_type":"markdown","source":"# 3. Too Small FTU 小さすぎるFTU","metadata":{}},{"cell_type":"code","source":"df_train_size.loc[:,['id','organ','age','sex','FTU_pixel_size']].sort_values('FTU_pixel_size').head(10)","metadata":{"execution":{"iopub.status.busy":"2022-08-15T09:29:26.730010Z","iopub.execute_input":"2022-08-15T09:29:26.730496Z","iopub.status.idle":"2022-08-15T09:29:26.747644Z","shell.execute_reply.started":"2022-08-15T09:29:26.730460Z","shell.execute_reply":"2022-08-15T09:29:26.746449Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"There are five FTUs with pixel sizes below 1,000.<br>\nピクセルサイズで1,000を下回るFTUが5つある。","metadata":{}},{"cell_type":"code","source":"def show_mask_per_one_min(idx,th_size):\n    fig, ax = plt.subplots(1,3,figsize=(12,12))\n    image = plt.imread(f\"../input/hubmap-organ-segmentation/train_images/{df_train.id[idx]}.tiff\")\n    arr = rle2mask(df_train.rle[idx],shape=(df_train.img_height[idx],df_train.img_width[idx]))\n    display(pd.DataFrame(df_train.loc[idx,['id','organ','age','sex']]).T)\n    ax[0].imshow(image)\n    ax[0].set_title(\"biopsy slide\")\n    ax[0].axis(\"off\")\n    \n    \n    ax[1].set_title('All FTUs')\n    ax[1].axis(\"off\")\n    ax[1].imshow(arr,cmap='gray')\n    \n    while arr.max()>0:\n        tmp = fill_1mask(arr)\n        if sum(sum(arr - tmp)) <= th_size:\n            ax[2].imshow(arr - tmp,cmap='gray')\n            ax[2].set_title('pixel size {}'.format(sum(sum(arr - tmp))))\n            ax[2].axis(\"off\")\n        arr = tmp\n    plt.show()","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2022-08-15T09:29:26.749232Z","iopub.execute_input":"2022-08-15T09:29:26.749965Z","iopub.status.idle":"2022-08-15T09:29:26.760646Z","shell.execute_reply.started":"2022-08-15T09:29:26.749919Z","shell.execute_reply":"2022-08-15T09:29:26.759808Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"for id in [9387,26480,25298,15499,4301,6611]:\n    show_mask_per_one_min(df_train[df_train['id']==id].index[0],1140)\n    print('-'*50)","metadata":{"execution":{"iopub.status.busy":"2022-08-15T09:29:26.762172Z","iopub.execute_input":"2022-08-15T09:29:26.762864Z","iopub.status.idle":"2022-08-15T09:30:14.753968Z","shell.execute_reply.started":"2022-08-15T09:29:26.762818Z","shell.execute_reply":"2022-08-15T09:30:14.752865Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"- Segments of less than 1,000 pixels may be better removed as a training/prediction.<br>\n1,000ピクセル未満のセグメントは、学習・予測には削除した方が良いかもしれない。","metadata":{}}]}