{"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","metadata":{}},{"cell_type":"code","source":"import gc\nimport os\nimport cv2\nimport torch\nimport zipfile\nimport rasterio\nimport numpy as np\nimport pandas as pd\nfrom PIL import Image\nimport tifffile as tiff\nfrom tqdm.notebook import tqdm\nimport matplotlib.pyplot as plt\nfrom rasterio.windows import Window\nfrom torch.utils.data import Dataset\n\n\nimport torch\nfrom torch.autograd import Variable\nimport torch.nn.functional as F\nimport numpy as np\ntry:\n    from itertools import  ifilterfalse\nexcept ImportError: # py3k\n    from itertools import  filterfalse\n    \n\n%reload_ext autoreload\n%autoreload 2\n%matplotlib inline\n\nfrom fastai.vision.all import *\nfrom torch.utils.data import Dataset, DataLoader\nimport pandas as pd\nimport numpy as np\nimport os\nimport cv2\nimport gc\nimport random\nfrom albumentations import *\nfrom sklearn.model_selection import KFold\nimport matplotlib.pyplot as plt\n\nimport warnings\nwarnings.filterwarnings(\"ignore\")\n\n\n!pip install segmentation_models_pytorch\nimport segmentation_models_pytorch as smp\nimport torch\nfrom torch.autograd import Variable\nimport torch.nn.functional as F\nimport numpy as np\ntry:\n    from itertools import  ifilterfalse\nexcept ImportError: # py3k\n    from itertools import  filterfalse","metadata":{"_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","papermill":{"duration":1.650158,"end_time":"2021-03-12T06:31:43.222111","exception":false,"start_time":"2021-03-12T06:31:41.571953","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2022-08-26T05:52:59.432324Z","iopub.execute_input":"2022-08-26T05:52:59.432749Z","iopub.status.idle":"2022-08-26T05:53:23.962118Z","shell.execute_reply.started":"2022-08-26T05:52:59.432714Z","shell.execute_reply":"2022-08-26T05:53:23.960864Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# config","metadata":{}},{"cell_type":"code","source":"DATA = '../input/hubmap-organ-segmentation/train_images/'\ndevice = torch.device('cuda' if torch.cuda.is_available() else 'cpu')\n\nTTA = False\n\nbs = 64\nOUTPUT_SIZE = 256\nDIV_SIZE = 2\nPAD_SIZE = 72\nTH = 0.225\nMODELS = [f\"../input/test-baseline/model_{i}.pth\" for i in range(1,4)]\ndf_train = pd.read_csv('../input/hubmap-organ-segmentation/train.csv')","metadata":{"execution":{"iopub.status.busy":"2022-08-26T06:35:36.918688Z","iopub.execute_input":"2022-08-26T06:35:36.919370Z","iopub.status.idle":"2022-08-26T06:35:37.296886Z","shell.execute_reply.started":"2022-08-26T06:35:36.919319Z","shell.execute_reply":"2022-08-26T06:35:37.295636Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### dataset","metadata":{}},{"cell_type":"code","source":"def enc2mask(encs, shape):\n    img = np.zeros(shape[0]*shape[1], dtype=np.uint8)\n    for m,enc in enumerate(encs):\n        if isinstance(enc,np.float) and np.isnan(enc): continue\n        s = enc.split()\n        for i in range(len(s)//2):\n            start = int(s[2*i]) - 1\n            length = int(s[2*i+1])\n            img[start:start+length] = 1 + m\n    return img.reshape(shape).T\n\ndef mask2enc(mask, n=1):\n    pixels = mask.T.flatten()\n    encs = []\n    for i in range(1,n+1):\n        p = (pixels == i).astype(np.int8)\n        if p.sum() == 0: encs.append(np.nan)\n        else:\n            p = np.concatenate([[0], p, [0]])\n            runs = np.where(p[1:] != p[:-1])[0] + 1\n            runs[1::2] -= runs[::2]\n            encs.append(' '.join(str(x) for x in runs))\n    return encs\n\n#https://www.kaggle.com/bguberfain/memory-aware-rle-encoding\n#with transposed mask\ndef rle_encode_less_memory(img):\n    #the image should be transposed\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)","metadata":{"execution":{"iopub.status.busy":"2022-08-26T07:11:05.347454Z","iopub.execute_input":"2022-08-26T07:11:05.348390Z","iopub.status.idle":"2022-08-26T07:11:05.413677Z","shell.execute_reply.started":"2022-08-26T07:11:05.348354Z","shell.execute_reply":"2022-08-26T07:11:05.412765Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# https://www.kaggle.com/datasets/thedevastator/hubmap-2022-256x256\n\nmean = np.array([0.7720342, 0.74582646, 0.76392896])\nstd = np.array([0.24745085, 0.26182273, 0.25782376])\nidentity = rasterio.Affine(1, 0, 0, 0, 1, 0)\n\ndef img2tensor(img,dtype:np.dtype=np.float32):\n    if img.ndim==2 : img = np.expand_dims(img,2)\n    img = np.transpose(img,(2,0,1))\n    return torch.from_numpy(img.astype(dtype, copy=False))\n\nidentity = rasterio.Affine(1, 0, 0, 0, 1, 0)\nclass HuBMAPDataset(Dataset):\n    def __init__(self, img_id, output_size=768, div_size=3, pad_size=72, encs=None):\n        \"\"\"\n        img_id: 画像のid\n        output_size: 出力の画像サイズ\n        div_size: 大きな画像の分割数\n        pad_size: 空白のサイズ（元画像サイズ基準）\n        \"\"\"\n        \n        self.data = rasterio.open(os.path.join(DATA, str(img_id)+'.tiff'), transform=identity, num_threads='all_cpus')\n        if self.data.count != 3:\n            subdatasets = self.data.subdatasets\n            self.layers = []\n            if len(subdatasets) > 0:\n                for i, subdataset in enumerate(subdatasets, 0):\n                    self.layers.append(rasterio.open(subdataset))\n                    \n                    \n        if isinstance(div_size, int):\n            div_size = (div_size, div_size)\n        if isinstance(pad_size, int):\n            pad_size = (pad_size, pad_size)\n                    \n        self.n0max, self.n1max = div_size\n        self.pad0, self.pad1 = pad_size        \n        self.shape = self.data.shape\n        self.mask = enc2mask(encs,(self.shape[1],self.shape[0])) if encs is not None else None\n        self.output_size = output_size\n        \n        plt.imshow(self.mask)\n        plt.show()\n        \n        \n        # うまく分割できるように調整\n        self.pad0 += (-self.pad0 - self.shape[0]) % self.n0max\n        self.pad1 += (-self.pad0 - self.shape[1]) % self.n1max\n        \n        self.input_size0 = (self.pad0 + self.shape[0])//self.n0max\n        self.input_size1 = (self.pad1 + self.shape[1])//self.n1max\n\n    def __len__(self):\n        return self.n0max*self.n1max\n    \n    def img_size(self):\n        return self.shape\n    \n    def __getitem__(self, idx):\n        # (n0, n1): 切った後の画像の位置\n        n0, n1 = idx//self.n1max, idx%self.n1max\n        # (x0, y0): 画像の左上の位置\n        x0,y0 = -self.pad0//2 + n0*self.input_size0, -self.pad1//2 + n1*self.input_size1\n\n        # make sure that the region to read is within the image\n        p00,p01 = max(0,x0), min(x0+self.input_size0,self.shape[0])\n        p10,p11 = max(0,y0), min(y0+self.input_size1,self.shape[1])\n        img = np.zeros((self.input_size0,self.input_size1,3), np.uint8)\n        mask = np.zeros((self.input_size0,self.input_size1), np.uint8)\n        \n        # mapping the loade region to the tile\n        if self.data.count == 3:\n            img[(p00-x0):(p01-x0),(p10-y0):(p11-y0)] = np.moveaxis(self.data.read([1,2,3],\n                window=Window.from_slices((p00,p01),(p10,p11))), 0, -1)\n        else:\n            for i,layer in enumerate(self.layers):\n                img[(p00-x0):(p01-x0),(p10-y0):(p11-y0),i] =\\\n                  layer.read(1,window=Window.from_slices((p00,p01),(p10,p11)))\n    \n        if self.mask is not None: \n            print(\"mask\")\n            print(self.mask[p00:p01,p10:p11])\n            mask[(p00-x0):(p01-x0),(p10-y0):(p11-y0)] = self.mask[p00:p01,p10:p11]\n        \n        img = cv2.resize(img,(self.output_size,self.output_size),\n                         interpolation = cv2.INTER_AREA)\n        mask = cv2.resize(mask,(self.output_size, self.output_size),\n                         interpolation = cv2.INTER_NEAREST)\n        \n        plt.imshow(mask)\n        plt.show()\n        \n        return img2tensor((img/255.0 - mean)/std), mask, idx","metadata":{"execution":{"iopub.status.busy":"2022-08-26T06:42:30.920830Z","iopub.execute_input":"2022-08-26T06:42:30.921307Z","iopub.status.idle":"2022-08-26T06:42:31.002690Z","shell.execute_reply.started":"2022-08-26T06:42:30.921266Z","shell.execute_reply":"2022-08-26T06:42:31.001799Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class HuBMAPDataset(Dataset):\n    def __init__(self, img_id, output_size=256, div_size=4, pad_size=72, encs=None):\n        \"\"\"\n        img_id: 画像のid\n        output_size: 出力の画像サイズ\n        div_size: 大きな画像の分割数\n        pad_size: 空白のサイズ（元画像サイズ基準）\n        \"\"\"\n        \n        self.data = rasterio.open(os.path.join(DATA, str(img_id)+'.tiff'), num_threads='all_cpus')\n        if self.data.count != 3:\n            subdatasets = self.data.subdatasets\n            self.layers = []\n            if len(subdatasets) > 0:\n                for i, subdataset in enumerate(subdatasets, 0):\n                    self.layers.append(rasterio.open(subdataset))\n                    \n                    \n        if isinstance(div_size, int):\n            div_size = (div_size, div_size)\n        if isinstance(pad_size, int):\n            pad_size = (pad_size, pad_size)\n                    \n        self.n0max, self.n1max = div_size\n        self.pad0, self.pad1 = pad_size        \n        self.shape = self.data.shape\n        self.mask = enc2mask(encs,(self.shape[1],self.shape[0])) if encs is not None else None\n        self.output_size = output_size\n        \n        # うまく分割できるように調整\n        self.pad0 += (-self.pad0 - self.shape[0]) % self.n0max\n        self.pad1 += (-self.pad0 - self.shape[1]) % self.n1max\n        \n        self.input_size0 = (self.pad0 + self.shape[0])//self.n0max\n        self.input_size1 = (self.pad1 + self.shape[1])//self.n1max\n\n    def __len__(self):\n        return self.n0max*self.n1max\n    \n    def img_size(self):\n        return self.shape\n    \n    def __getitem__(self, idx):\n        # (n0, n1): 切った後の画像の位置\n        n0, n1 = idx//self.n1max, idx%self.n1max\n        # (x0, y0): 画像の左上の位置\n        x0,y0 = -self.pad0//2 + n0*self.input_size0, -self.pad1//2 + n1*self.input_size1\n\n        # make sure that the region to read is within the image\n        p00,p01 = max(0,x0), min(x0+self.input_size0,self.shape[0])\n        p10,p11 = max(0,y0), min(y0+self.input_size1,self.shape[1])\n        img = np.zeros((self.input_size0,self.input_size1,3), np.uint8)\n        mask = np.zeros((self.input_size0,self.input_size1), np.uint8)\n        \n        # mapping the loade region to the tile\n        if self.data.count == 3:\n            img[(p00-x0):(p01-x0),(p10-y0):(p11-y0)] = np.moveaxis(self.data.read([1,2,3],\n                window=Window.from_slices((p00,p01),(p10,p11))), 0, -1)\n        else:\n            for i,layer in enumerate(self.layers):\n                img[(p00-x0):(p01-x0),(p10-y0):(p11-y0),i] =\\\n                  layer.read(1,window=Window.from_slices((p00,p01),(p10,p11)))\n                \n        if self.mask is not None: mask[(p00-x0):(p01-x0),(p10-y0):(p11-y0)] = self.mask[p00:p01,p10:p11]\n        \n        img = cv2.resize(img,(self.output_size,self.output_size),\n                         interpolation = cv2.INTER_AREA)\n        mask = cv2.resize(mask,(self.output_size, self.output_size),\n                         interpolation = cv2.INTER_NEAREST)\n\n        return img2tensor((img/255.0 - mean)/std), mask, idx","metadata":{"execution":{"iopub.status.busy":"2022-08-26T07:13:22.539136Z","iopub.execute_input":"2022-08-26T07:13:22.540233Z","iopub.status.idle":"2022-08-26T07:13:22.614508Z","shell.execute_reply.started":"2022-08-26T07:13:22.540192Z","shell.execute_reply":"2022-08-26T07:13:22.612933Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### model","metadata":{}},{"cell_type":"code","source":"class FPN(nn.Module):\n    def __init__(self, input_channels:list, output_channels:list):\n        super().__init__()\n        self.convs = nn.ModuleList(\n            [nn.Sequential(nn.Conv2d(in_ch, out_ch*2, kernel_size=3, padding=1),\n             nn.ReLU(inplace=True), nn.BatchNorm2d(out_ch*2),\n             nn.Conv2d(out_ch*2, out_ch, kernel_size=3, padding=1))\n            for in_ch, out_ch in zip(input_channels, output_channels)])\n        \n    def forward(self, xs:list, last_layer):\n        hcs = [F.interpolate(c(x),scale_factor=2**(len(self.convs)-i),mode='bilinear') \n               for i,(c,x) in enumerate(zip(self.convs, xs))]\n        hcs.append(last_layer)\n        return torch.cat(hcs, dim=1)\n\nclass UnetBlock(Module):\n    def __init__(self, up_in_c:int, x_in_c:int, nf:int=None, blur:bool=False,\n                 self_attention:bool=False, **kwargs):\n        super().__init__()\n        self.shuf = PixelShuffle_ICNR(up_in_c, up_in_c//2, blur=blur, **kwargs)\n        self.bn = nn.BatchNorm2d(x_in_c)\n        ni = up_in_c//2 + x_in_c\n        nf = nf if nf is not None else max(up_in_c//2,32)\n        self.conv1 = ConvLayer(ni, nf, norm_type=None, **kwargs)\n        self.conv2 = ConvLayer(nf, nf, norm_type=None,\n            xtra=SelfAttention(nf) if self_attention else None, **kwargs)\n        self.relu = nn.ReLU(inplace=True)\n\n    def forward(self, up_in:Tensor, left_in:Tensor) -> Tensor:\n        s = left_in\n        up_out = self.shuf(up_in)\n        cat_x = self.relu(torch.cat([up_out, self.bn(s)], dim=1))\n        return self.conv2(self.conv1(cat_x))\n\n    \nclass _ASPPModule(nn.Module):\n    def __init__(self, inplanes, planes, kernel_size, padding, dilation, groups=1):\n        super().__init__()\n        self.atrous_conv = nn.Conv2d(inplanes, planes, kernel_size=kernel_size,\n                stride=1, padding=padding, dilation=dilation, bias=False, groups=groups)\n        self.bn = nn.BatchNorm2d(planes)\n        self.relu = nn.ReLU()\n\n        self._init_weight()\n\n    def forward(self, x):\n        x = self.atrous_conv(x)\n        x = self.bn(x)\n\n        return self.relu(x)\n\n    def _init_weight(self):\n        for m in self.modules():\n            if isinstance(m, nn.Conv2d):\n                torch.nn.init.kaiming_normal_(m.weight)\n            elif isinstance(m, nn.BatchNorm2d):\n                m.weight.data.fill_(1)\n                m.bias.data.zero_()\n                \nclass ASPP(nn.Module):\n    def __init__(self, inplanes=512, mid_c=256, dilations=[6, 12, 18, 24], out_c=None):\n        super().__init__()\n        self.aspps = [_ASPPModule(inplanes, mid_c, 1, padding=0, dilation=1)] + \\\n            [_ASPPModule(inplanes, mid_c, 3, padding=d, dilation=d,groups=4) for d in dilations]\n        self.aspps = nn.ModuleList(self.aspps)\n        self.global_pool = nn.Sequential(nn.AdaptiveMaxPool2d((1, 1)),\n                        nn.Conv2d(inplanes, mid_c, 1, stride=1, bias=False),\n                        nn.BatchNorm2d(mid_c), nn.ReLU())\n        out_c = out_c if out_c is not None else mid_c\n        self.out_conv = nn.Sequential(nn.Conv2d(mid_c*(2+len(dilations)), out_c, 1, bias=False),\n                                    nn.BatchNorm2d(out_c), nn.ReLU(inplace=True))\n        self.conv1 = nn.Conv2d(mid_c*(2+len(dilations)), out_c, 1, bias=False)\n        self._init_weight()\n\n    def forward(self, x):\n        x0 = self.global_pool(x)\n        xs = [aspp(x) for aspp in self.aspps]\n        x0 = F.interpolate(x0, size=xs[0].size()[2:], mode='bilinear', align_corners=True)\n        x = torch.cat([x0] + xs, dim=1)\n        return self.out_conv(x)\n    \n    def _init_weight(self):\n        for m in self.modules():\n            if isinstance(m, nn.Conv2d):\n                torch.nn.init.kaiming_normal_(m.weight)\n            elif isinstance(m, nn.BatchNorm2d):\n                m.weight.data.fill_(1)\n                m.bias.data.zero_()\n    \nclass UneXt50(nn.Module):\n    def __init__(self, stride=1, **kwargs):\n        super().__init__()\n        #encoder\n        m = torch.hub.load('facebookresearch/semi-supervised-ImageNet1K-models', 'resnext50_32x4d_ssl')\n        self.enc0 = nn.Sequential(m.conv1, m.bn1, nn.ReLU(inplace=True))\n        self.enc1 = nn.Sequential(nn.MaxPool2d(kernel_size=3, stride=2, padding=1, dilation=1),\n                            m.layer1) #256\n        self.enc2 = m.layer2 #512\n        self.enc3 = m.layer3 #1024\n        self.enc4 = m.layer4 #2048\n        #aspp with customized dilatations\n        self.aspp = ASPP(2048,256,out_c=512,dilations=[stride*1,stride*2,stride*3,stride*4])\n        self.drop_aspp = nn.Dropout2d(0.5)\n        #decoder\n        self.dec4 = UnetBlock(512,1024,256)\n        self.dec3 = UnetBlock(256,512,128)\n        self.dec2 = UnetBlock(128,256,64)\n        self.dec1 = UnetBlock(64,64,32)\n        self.fpn = FPN([512,256,128,64],[16]*4)\n        self.drop = nn.Dropout2d(0.1)\n        self.final_conv = ConvLayer(32+16*4, 1, ks=1, norm_type=None, act_cls=None)\n        \n    def forward(self, x):\n        enc0 = self.enc0(x)\n        enc1 = self.enc1(enc0)\n        enc2 = self.enc2(enc1)\n        enc3 = self.enc3(enc2)\n        enc4 = self.enc4(enc3)\n        enc5 = self.aspp(enc4)\n        dec3 = self.dec4(self.drop_aspp(enc5),enc3)\n        dec2 = self.dec3(dec3,enc2)\n        dec1 = self.dec2(dec2,enc1)\n        dec0 = self.dec1(dec1,enc0)\n        x = self.fpn([enc5, dec3, dec2, dec1], dec0)\n        x = self.final_conv(self.drop(x))\n        x = F.interpolate(x,scale_factor=2,mode='bilinear')\n        return x\n\n    \n#split the model to encoder and decoder for fast.ai\nsplit_layers = lambda m: [list(m.enc0.parameters())+list(m.enc1.parameters())+\n                list(m.enc2.parameters())+list(m.enc3.parameters())+\n                list(m.enc4.parameters()),\n                list(m.aspp.parameters())+list(m.dec4.parameters())+\n                list(m.dec3.parameters())+list(m.dec2.parameters())+\n                list(m.dec1.parameters())+list(m.fpn.parameters())+\n                list(m.final_conv.parameters())]","metadata":{"execution":{"iopub.status.busy":"2022-08-26T06:20:35.959803Z","iopub.execute_input":"2022-08-26T06:20:35.960316Z","iopub.status.idle":"2022-08-26T06:20:36.055560Z","shell.execute_reply.started":"2022-08-26T06:20:35.960276Z","shell.execute_reply":"2022-08-26T06:20:36.054537Z"},"jupyter":{"source_hidden":true},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### pred","metadata":{}},{"cell_type":"code","source":"#iterator like wrapper that returns predicted masks\nclass Model_pred:\n    def __init__(self, models, dl, tta:bool=True, half:bool=False):\n        self.models = models\n        self.dl = dl\n        self.half = half\n        \n        if tta:\n            self.flips = [[-1],[-2],[-2,-1]]\n        else:\n            self.flips = []\n        \n    def __iter__(self):\n        count = 0\n        with torch.no_grad():\n            for img, mask, idx in iter(self.dl):\n                if ((idx>=0).sum() > 0): #exclude empty images\n                    \n                    img = img[idx>=0].to(device)\n                    idx = idx[idx>=0]\n                    \n                    if self.half: \n                        img = img.to(torch.float16)\n                        \n                    # predict\n                    pred = None\n                    for model in self.models:\n                        p = model(img)\n                        p = torch.sigmoid(p)\n                        if pred is None: pred = p.detach()  \n                        else: pred += p.detach()  \n                        # tta処理\n                        for f in self.flips:\n                            imgf = torch.flip(img,f)\n                            for model in self.models:\n                                p = model(imgf)\n                                p = torch.flip(p,f)\n                                p = torch.sigmoid(p)\n                                pred += p.detach() \n                    pred = pred / (len(self.models) * (1+len(self.flips))) \n                    pred = F.upsample(pred, size=(OUTPUT_SIZE, OUTPUT_SIZE), mode=\"bilinear\")\n                    pred = pred.permute(0,2,3,1).float().cpu()\n                    \n                    \n                    # yield\n                    batch_size = len(pred)\n                    for i in range(batch_size):\n                        yield img[i], mask[i], pred[i], idx[i]\n                        count += 1\n                    \n    def __len__(self):\n        return len(self.dl.dataset)","metadata":{"execution":{"iopub.status.busy":"2022-08-26T07:13:24.727948Z","iopub.execute_input":"2022-08-26T07:13:24.728851Z","iopub.status.idle":"2022-08-26T07:13:24.797035Z","shell.execute_reply.started":"2022-08-26T07:13:24.728810Z","shell.execute_reply":"2022-08-26T07:13:24.795729Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"models = []\nfor path in MODELS:\n    state_dict = torch.load(path, map_location=torch.device('cpu'))\n    \n    ## 利用しているモデルに変える\n#     model = smp.DeepLabV3Plus(encoder_name='resnext50_32x4d', classes=1, activation=None,)\n    model = UneXt50()\n    #########################\n    \n    model.load_state_dict(state_dict)\n    model.float()\n    model.eval()\n    model.to(device)\n    models.append(model)\n\n# del state_dict","metadata":{"execution":{"iopub.status.busy":"2022-08-26T06:20:43.093844Z","iopub.execute_input":"2022-08-26T06:20:43.094279Z","iopub.status.idle":"2022-08-26T06:20:49.458550Z","shell.execute_reply.started":"2022-08-26T06:20:43.094246Z","shell.execute_reply":"2022-08-26T06:20:49.457243Z"},"jupyter":{"source_hidden":true,"outputs_hidden":true},"collapsed":true,"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def view_prediction(row, overall_img, overall_mask, mask_proba, mask_pred, size=200):\n    print(f'id={row[\"id\"]}, {row[\"organ\"]}')\n    plt.subplot(131)\n    plt.title(\"answer\")\n    plt.imshow(cv2.resize(overall_img, (size,size))*std + mean)\n    plt.imshow(cv2.resize(overall_mask.astype(float), (size,size)), alpha=0.4)\n    plt.axis(\"off\")\n\n    plt.subplot(132)\n    plt.title(\"proba\")\n    plt.imshow(cv2.resize(overall_img, (size,size))*std + mean)\n    plt.imshow(cv2.resize(mask_proba, (size,size)), alpha=0.4)\n    plt.axis(\"off\")\n\n    plt.subplot(133)\n    plt.title(\"predict\")\n    plt.imshow(cv2.resize(overall_img, (size,size))*std + mean)\n    plt.imshow(cv2.resize(mask_pred.astype(float), (size,size)), alpha=0.4)\n    plt.axis(\"off\")\n\n    plt.show()\n    ","metadata":{"execution":{"iopub.status.busy":"2022-08-26T07:13:26.257321Z","iopub.execute_input":"2022-08-26T07:13:26.258466Z","iopub.status.idle":"2022-08-26T07:13:26.321539Z","shell.execute_reply.started":"2022-08-26T07:13:26.258424Z","shell.execute_reply":"2022-08-26T07:13:26.320659Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"names,preds = [],[]\nfor cnt, (idx, row) in tqdm(enumerate(df_train.iterrows()),total=len(df_train)):\n    idx = str(row['id'])\n    ds = HuBMAPDataset(idx, output_size=OUTPUT_SIZE, div_size=DIV_SIZE, pad_size=PAD_SIZE, encs=[row[\"rle\"]])\n    #rasterio cannot be used with multiple workers\n    dl = DataLoader(ds, bs, num_workers=0, shuffle=False, pin_memory=True)\n    mp = Model_pred(models, dl, tta=TTA)\n    #generate masks\n    overall_img = torch.zeros(len(ds), 3, OUTPUT_SIZE, OUTPUT_SIZE, dtype=torch.float32)\n    overall_mask = torch.zeros(len(ds), OUTPUT_SIZE, OUTPUT_SIZE, dtype=torch.float32)\n    mask_proba = torch.zeros(len(ds), OUTPUT_SIZE, OUTPUT_SIZE, dtype=torch.float32)\n    \n    for img, mask, pred, idx in iter(mp): \n        overall_img[idx.item()] = img\n        overall_mask[idx.item()] = mask\n        mask_proba[idx.item()] = pred.squeeze(-1)\n\n    size = (ds.img_size()[0]+PAD_SIZE, ds.img_size()[1]+PAD_SIZE)\n    \n    overall_img = overall_img.permute(0,2,3,1).view(ds.n0max,ds.n1max,ds.output_size,ds.output_size,3).permute(0,2,1,3,4).reshape(ds.n0max*ds.output_size, ds.n1max*ds.output_size,3)\n    overall_img = cv2.resize(overall_img.numpy(), size)\n    overall_img = overall_img[PAD_SIZE//2:-PAD_SIZE//2, PAD_SIZE//2:-PAD_SIZE//2]\n    \n    overall_mask = overall_mask.view(ds.n0max,ds.n1max,ds.output_size,ds.output_size).permute(0,2,1,3).reshape(ds.n0max*ds.output_size, ds.n1max*ds.output_size)\n    overall_mask = cv2.resize(overall_mask.numpy(), size)\n    overall_mask = overall_mask[PAD_SIZE//2:-PAD_SIZE//2, PAD_SIZE//2:-PAD_SIZE//2]\n\n    \n    mask_proba = mask_proba.view(ds.n0max,ds.n1max,ds.output_size,ds.output_size).permute(0,2,1,3).reshape(ds.n0max*ds.output_size, ds.n1max*ds.output_size)\n    mask_proba = cv2.resize(mask_proba.numpy(), size)\n    mask_proba = mask_proba[PAD_SIZE//2:-PAD_SIZE//2, PAD_SIZE//2:-PAD_SIZE//2]\n    \n    mask_pred = (mask_proba > TH)\n    \n    # 0番目のデータのみ出力する。\n    if cnt >= 0:\n        view_prediction(row, overall_img, overall_mask, mask_proba, mask_pred)\n    \n    \n    #convert to rle\n    #https://www.kaggle.com/bguberfain/memory-aware-rle-encoding\n    rle = rle_encode_less_memory(mask)\n    names.append(idx)\n    preds.append(rle)\n","metadata":{"execution":{"iopub.status.busy":"2022-08-26T07:13:28.155742Z","iopub.execute_input":"2022-08-26T07:13:28.156187Z","iopub.status.idle":"2022-08-26T07:16:43.496996Z","shell.execute_reply.started":"2022-08-26T07:13:28.156151Z","shell.execute_reply":"2022-08-26T07:16:43.495243Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}