{"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":"from IPython.display import clear_output\n\n!pip install ../input/segmentationmodelspytorch-013/pretrainedmodels-0.7.4-py3-none-any.whl\n!pip install ../input/segmentationmodelspytorch-013/efficientnet_pytorch-0.6.3-py2.py3-none-any.whl\n!pip install ../input/segmentationmodelspytorch-013/timm-0.3.2-py3-none-any.whl\n!pip install ../input/segmentationmodelspytorch-013/segmentation_models_pytorch-0.1.3-py3-none-any.whl\n\nclear_output()","metadata":{"_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"\nfrom PIL import Image\nimport tifffile as tiff\nimport subprocess\nimport pandas as pd\nfrom IPython.display import clear_output\nimport matplotlib.pyplot as plt\nfrom glob import glob\n\nimport numpy as np\nimport cv2\nimport os\nfrom tqdm.notebook import tqdm\nimport zipfile\nimport gc\nimport segmentation_models_pytorch as smp\nimport torchvision\nimport torchvision.transforms as transforms\nimport torch\nfrom torch.utils.data import TensorDataset, DataLoader,Dataset\nimport torch.nn as nn\nimport torch.nn.functional as F\nimport torch.optim as optim\nfrom torch.optim import lr_scheduler\nfrom torch.utils.data.sampler import SubsetRandomSampler\nfrom torch.optim.lr_scheduler import StepLR, ReduceLROnPlateau, CosineAnnealingLR\nsample_submission = pd.read_csv('../input/hubmap-kidney-segmentation/sample_submission.csv')\nsample_submission = sample_submission.set_index('id')\nseed = 1015\nnp.random.seed(seed)\ntorch.manual_seed(seed)\ntorch.cuda.manual_seed(seed)\ndevice = torch.device('cuda' if torch.cuda.is_available() else 'cpu')\n\n\ndef rle_encode_less_memory(img):\n    '''\n    img: numpy array, 1 - mask, 0 - background\n    Returns run length as string formated\n    This simplified method requires first and last pixel to be zero\n    '''\n    pixels = img.T.flatten()\n\n    # This simplified method requires first and last pixel to be zero\n    pixels[0] = 0\n    pixels[-1] = 0\n    runs = np.where(pixels[1:] != pixels[:-1])[0] + 2\n    runs[1::2] -= runs[::2]\n\n    return ' '.join(str(x) for x in runs)\n\n\ntest_files = sample_submission.index.tolist()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"PATH = \"../input/hubmap-models2\"\n#model_list = ['1_unet-timm-effb7_0.9509_epoch_28.pth', '2_unet-timm-effb7_0.9488_epoch_28.pth', '3_unet-timm-effb7_0.9503_epoch_29.pth', '4_unet-timm-effb7_0.9500_epoch_28.pth', '5_unet-timm-effb7_0.9518_epoch_27.pth', '1_unet-se_resnet50_0.9526_epoch_28.pth', '2_unet-se_resnet50_0.9494_epoch_28.pth', '1_unet-timm-effb0_0.9495_epoch_39.pth', '2_unet-timm-effb0_0.9477_epoch_35.pth', '3_unet-timm-effb0_0.9463_epoch_28.pth']\nmodel_list = ['1_unet-se_resnet50_0.9526_epoch_28.pth', '2_unet-se_resnet50_0.9494_epoch_28.pth', '1_unet-timm-effb0_0.9495_epoch_39.pth', '2_unet-timm-effb0_0.9477_epoch_35.pth', '1_unet-timm-resnest26d_0.9522_epoch_28.pth', '1_unet-se_resnet50_pesudo_0.9572_epoch_26.pth', '1_unet-timm-resnest26d-pesudo_0.9563_epoch_39.pth']","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model_path = list(map(lambda x: os.path.join(PATH, x), model_list))","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model_path","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"models = []\nfor path in model_path:\n    model = torch.load(path, map_location= 'cuda')\n    model.float()\n    model.eval()\n    model.to('cuda')\n    models.append(model)\n\ndel model","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sz = 512\ntest_path = '../input/hubmap-kidney-segmentation/test/'\n\nfor step, person_idx in enumerate(test_files):\n\n    print(f'load {step+1}/{len(test_files)} data...')\n    img = tiff.imread(test_path + person_idx + '.tiff').squeeze()\n    if img.shape[0] == 3:\n        img = img.transpose(1,2,0)\n    predict_mask_l1 = np.zeros((img.shape[0], img.shape[1]), dtype = bool)\n    \n    # \n    landscape =img.shape[0]// 512 # slide는 512\n    portrait = img.shape[1]// 512 # slide는 512\n\n    sz = 512\n    print('predict mask...')\n    for x in tqdm(range(landscape)):\n        for y in range(portrait):\n            start_x =  (512) * x\n            end_x   = (1024) + start_x\n            start_y =  (512) * y\n            end_y   = (1024) + start_y\n\n            if x == landscape-1:\n                start_x = img.shape[0] - 1024\n                end_x   = img.shape[0]\n            if y == portrait-1:\n                start_y = img.shape[1] - 1024\n                end_y   = img.shape[1]\n\n            sample_img = img[start_x : end_x, start_y : end_y,:]\n            sample_img = cv2.resize(sample_img,(sz,sz),interpolation = cv2.INTER_AREA)/256\n            sample_img = torch.cuda.FloatTensor(sample_img.transpose([2,0,1])[np.newaxis,...])\n            with torch.no_grad():\n                sample_pred = models[0].predict(sample_img).cpu().numpy()[0,0,:,:]\n            sample_pred = cv2.resize(sample_pred,(1024,1024),interpolation = cv2.INTER_NEAREST)\n            sample_pred = np.where(sample_pred > 0.1, True, False).astype(bool)\n            predict_mask_l1[start_x + 256 : end_x - 256, start_y + 256 : end_y - 256] = sample_pred[256:256 + 512,256:256 + 512]\n            \n    del sample_img\n    del sample_pred\n    gc.collect()\n\n    predict_mask_l1 = predict_mask_l1.astype(np.uint8)\n    contours, hierarchy = cv2.findContours(predict_mask_l1, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)\n    predict_mask_l2 = np.zeros((img.shape[0], img.shape[1]), dtype = bool)\n\n    for cont in tqdm(contours):\n        center_y, center_x = cont.mean(axis = 0).round(0).astype(int)[0]\n        left_x = int(center_x - 512)\n        top_y = int(center_y - 512)\n\n        if left_x < 0:\n            left_x = 0\n        elif left_x + 1024 > img.shape[0]:\n            left_x = img.shape[0] - 1024\n\n        if top_y < 0:\n            top_y = 0\n        elif top_y + 1024 > img.shape[1]:\n            top_y = img.shape[1] - 1024\n\n        sample_img_l2 = img[left_x : left_x + 1024, top_y : top_y+ 1024,:]\n        sample_img_l2 = cv2.resize(sample_img_l2,(sz,sz),interpolation = cv2.INTER_AREA)/256\n        sample_img_l2 = torch.cuda.FloatTensor(sample_img_l2.transpose([2,0,1])[np.newaxis,...])\n        sample_pred_l2 = None\n        with torch.no_grad():\n            for model in models:\n                pred_l2 = model.predict(sample_img_l2).cpu().numpy()[0,0,:,:]\n                if sample_pred_l2 is None: sample_pred_l2 = pred_l2\n                sample_pred_l2 += pred_l2\n\n        sample_pred_l2 /= len(models)     \n        sample_pred_l2 = cv2.resize(sample_pred_l2,(1024,1024),interpolation = cv2.INTER_NEAREST)\n        sample_pred_l2 = np.where(sample_pred_l2 > 0.3, True, False).astype(np.uint8)\n\n        contours_l2, hierarchy = cv2.findContours(sample_pred_l2,\n                                                  cv2.RETR_EXTERNAL,\n                                                  cv2.CHAIN_APPROX_NONE)\n        \n        \n        # 2차 추론 결과가 1개 이상인지 확인\n        if len(contours_l2) < 1:\n            print('no cotour')\n            continue\n\n        \n        # 2차 추론 결과가 중심에 있을 때 만\n        # 최종 결과에 채우기\n        for cont_l2 in contours_l2:\n            \n            area = cv2.contourArea(cont_l2)\n            \n                \n            # conturs 중 중심\n            min_y, min_x = cont_l2.min(axis = 0).round(0).astype(int)[0]\n            max_y, max_x = cont_l2.max(axis = 0).round(0).astype(int)[0]\n            if (min_x < 512) and (max_x > 512):\n                if (min_y < 512) and (max_y > 512):\n                    # 0으로 채워진 place holder 선언\n                    sample_mask_l2 = np.zeros(sample_pred_l2.shape,\n                                          dtype = np.uint8)\n\n                    # 중심 contour로만 채우기\n                    sample_center = cv2.drawContours(sample_mask_l2,\n                                                   [cont_l2],\n                                                   0,\n                                                   (255, 255, 255),\n                                                   -1)\n\n                    # 기존 predict_mask_l2에 중심 contur를 합집합\n                    predict_mask_l2[left_x : left_x + 1024,\n                                    top_y : top_y+ 1024] =\\\n                        np.logical_or(predict_mask_l2[left_x : left_x + 1024,\n                                                      top_y : top_y+ 1024],\n                                                      sample_center)\n                    \n    del predict_mask_l1\n    del img\n    gc.collect()\n    \n    print('convert mask to rle \\n\\n')\n    predict_rle = rle_encode_less_memory(predict_mask_l2) \n    sample_submission.loc[person_idx,'predicted'] = predict_rle\n\n    del predict_rle\n    del predict_mask_l2\n    gc.collect()\n    sample_submission.reset_index().to_csv('/kaggle/working/submission.csv',index=False)\n    sample_submission.reset_index().to_csv('submission.csv', index = False)\n\nsample_submission = sample_submission.reset_index()\nsample_submission.to_csv('/kaggle/working/submission.csv',index=False)\nsample_submission.to_csv('submission.csv', index = False)\n\nsample_submission","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{"trusted":true},"execution_count":null,"outputs":[]}]}