{"cells":[{"metadata":{"_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","trusted":true},"cell_type":"code","source":"from IPython.display import clear_output\n\n!pip install ../input/packages/pretrainedmodels-0.7.4-py3-none-any.whl\n!pip install ../input/segmentationmodelspytorch/segmentation_models/timm-0.1.20-py3-none-any.whl\n!pip install ../input/packages/efficientnet_pytorch-0.6.3-py2.py3-none-any.whl\n!pip install ../input/segmentationmodelspytorch/segmentation_models/segmentation_models_pytorch-0.1.2-py3-none-any.whl\n!pip install ../input/bdgpackages/ttach-0.0.3-py3-none-any.whl\nclear_output()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"from PIL import Image\nimport tifffile as tiff\nimport subprocess\nimport pandas as pd\nfrom IPython.display import clear_output\nimport matplotlib.pyplot as plt\nimport 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\n\nimport ttach as tta\n\n\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()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"PATH = \"../input/hubmap-models/\"\nbest_model = torch.load(f\"{PATH}best_model.pth\")","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# tta\ntransforms = tta.Compose(\n    [\n        tta.HorizontalFlip(),\n        tta.Rotate90(angles=[0, 180]),\n        #tta.Scale(scales=[1, 2, 4]),\n        tta.Multiply(factors=[0.9, 1, 1.1]),        # 3배\n    ]\n)\ntta_model = tta.SegmentationTTAWrapper(best_model, transforms)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"with torch.no_grad():\n    sz = 512\n\n    test_path = '../input/hubmap-kidney-segmentation/test/'\n\n    for step, person_idx in enumerate(test_files):\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        landscape =img.shape[0]// 512\n        portrait = img.shape[1]// 512\n\n        sz = 512\n        s_th = 40  #saturation blancking threshold\n        p_th = 200*sz//256 #threshold for the minimum number of pixels\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\n                hsv = cv2.cvtColor(sample_img, cv2.COLOR_BGR2HSV)\n                h, s, v = cv2.split(hsv)\n                if (s>s_th).sum() <= p_th or sample_img.sum() <= p_th: \n                    #predict_mask[start_x : end_x, start_y : end_y] = False\n                    continue\n                #print(sample_img.shape)\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                #--------------------------------------------------------------------------------------\n                sample_pred = best_model.predict(sample_img).cpu().numpy()[0,0,:,:]\n                #--------------------------------------------------------------------------------------\n                sample_pred = cv2.resize(sample_pred,(1024,1024),interpolation = cv2.INTER_NEAREST)\n                sample_pred = np.where(sample_pred > 0.05, 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\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\n        predict_mask_l2 = np.zeros((img.shape[0], img.shape[1]), dtype = bool)\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            #--------------------------------------------------------------------------------------\n            #sample_pred_l2 = best_model.predict(sample_img_l2).cpu().numpy()[0,0,:,:]\n            sample_pred_l2 = tta_model(sample_img_l2).cpu().numpy()[0,0,:,:]\n            #--------------------------------------------------------------------------------------\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.5, True, False).astype(np.uint8)\n\n            contours_l2, hierarchy = cv2.findContours(sample_pred_l2, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)\n            sample_mask_l2 = np.zeros(sample_pred_l2.shape, dtype = np.uint8)\n            #try:\n            if len(contours_l2) < 1:\n                print('no cotour')\n                continue\n\n            for cont_l2 in contours_l2:\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\n                if (min_x < 512) and (max_x > 512):\n                    if (min_y < 512) and (max_y > 512):\n                        \n                        area = cv2.contourArea(cont_l2)\n                        if area < 3500*4:\n                            print('del')# 3500*4보다 작은 면적은 지우기\n                            continue\n                        else:\n\n                            sample_mask_l2[min_x:max_x,min_y:max_y] = sample_pred_l2[min_x:max_x,min_y:max_y]\n\n                            #구멍난 경우 가운데 채우기\n                            sample_mask_l2 = sample_mask_l2.astype(np.uint8)\n                            sample_mask_l2 = cv2.drawContours(sample_mask_l2, [cont_l2], -1, 1, -1)\n                            sample_mask_l2 = sample_mask_l2.astype(np.bool)\n\n\n                            predict_mask_l2[left_x : left_x + 1024, top_y : top_y+ 1024] = np.logical_or(predict_mask_l2[left_x : left_x + 1024, top_y : top_y+ 1024], sample_mask_l2)\n\n        del predict_mask_l1\n        del sample_img\n        del sample_pred\n        del img\n        gc.collect()\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\n    sample_submission = sample_submission.reset_index()\n    sample_submission.to_csv('/kaggle/working/submission.csv',index=False)\n    sample_submission","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}