{"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":"import numpy as np\nimport pandas as pd","metadata":{"execution":{"iopub.status.busy":"2022-09-07T20:35:28.794595Z","iopub.execute_input":"2022-09-07T20:35:28.795454Z","iopub.status.idle":"2022-09-07T20:35:28.809383Z","shell.execute_reply.started":"2022-09-07T20:35:28.795409Z","shell.execute_reply":"2022-09-07T20:35:28.807908Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df=pd.read_csv(\"/kaggle/input/hubmap-organ-segmentation/train.csv\")","metadata":{"execution":{"iopub.status.busy":"2022-09-07T20:35:28.811715Z","iopub.execute_input":"2022-09-07T20:35:28.812571Z","iopub.status.idle":"2022-09-07T20:35:29.194441Z","shell.execute_reply.started":"2022-09-07T20:35:28.812528Z","shell.execute_reply":"2022-09-07T20:35:29.193020Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df.head()","metadata":{"execution":{"iopub.status.busy":"2022-09-07T20:35:29.197866Z","iopub.execute_input":"2022-09-07T20:35:29.198432Z","iopub.status.idle":"2022-09-07T20:35:29.228472Z","shell.execute_reply.started":"2022-09-07T20:35:29.198386Z","shell.execute_reply":"2022-09-07T20:35:29.227630Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import os\nimport gc\nimport cv2\nimport rasterio\nfrom PIL import Image\nfrom tqdm import tqdm\nimport tifffile as tiff\nimport matplotlib.pyplot as plt\nfrom fastai.vision.all import *\nfrom rasterio.windows import Window\nfrom torch.utils.data import Dataset, DataLoader\nimport warnings; warnings.filterwarnings(\"ignore\")","metadata":{"execution":{"iopub.status.busy":"2022-09-07T20:35:29.232012Z","iopub.execute_input":"2022-09-07T20:35:29.232379Z","iopub.status.idle":"2022-09-07T20:35:33.012880Z","shell.execute_reply.started":"2022-09-07T20:35:29.232348Z","shell.execute_reply":"2022-09-07T20:35:33.011516Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"bs = 64\nsz = 256    # the size of tiles\nreduce = 4  # reduce the original images by 4 times\nTH = 0.225  # threshold for positive predictions\ndevice = torch.device('cuda' if torch.cuda.is_available() else 'cpu')","metadata":{"execution":{"iopub.status.busy":"2022-09-07T20:35:33.014634Z","iopub.execute_input":"2022-09-07T20:35:33.015207Z","iopub.status.idle":"2022-09-07T20:35:33.021733Z","shell.execute_reply.started":"2022-09-07T20:35:33.015172Z","shell.execute_reply":"2022-09-07T20:35:33.020290Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# functions to convert encoding to mask and mask to encoding\ndef 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","metadata":{"execution":{"iopub.status.busy":"2022-09-07T20:35:33.023327Z","iopub.execute_input":"2022-09-07T20:35:33.023751Z","iopub.status.idle":"2022-09-07T20:35:33.042696Z","shell.execute_reply.started":"2022-09-07T20:35:33.023711Z","shell.execute_reply":"2022-09-07T20:35:33.041460Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_masks=pd.read_csv(\"/kaggle/input/hubmap-organ-segmentation/train.csv\")[[\"id\",\"rle\"]].set_index(\"id\")","metadata":{"execution":{"iopub.status.busy":"2022-09-07T20:35:33.045140Z","iopub.execute_input":"2022-09-07T20:35:33.045489Z","iopub.status.idle":"2022-09-07T20:35:33.235683Z","shell.execute_reply.started":"2022-09-07T20:35:33.045451Z","shell.execute_reply":"2022-09-07T20:35:33.234660Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_masks.head()","metadata":{"execution":{"iopub.status.busy":"2022-09-07T20:35:33.237113Z","iopub.execute_input":"2022-09-07T20:35:33.237751Z","iopub.status.idle":"2022-09-07T20:35:33.250609Z","shell.execute_reply.started":"2022-09-07T20:35:33.237707Z","shell.execute_reply":"2022-09-07T20:35:33.249204Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"OUT_TRAIN = 'train.zip'\nOUT_MASKS = 'masks.zip'\nsz = 256   # the size of tiles\nreduce = 4 # reduce the original images by 4 times \nMASKS = '../input/hubmap-organ-segmentation/train.csv'\nDATA = '../input/hubmap-organ-segmentation/train_images'\ns_th = 40  # saturation blancking threshold\np_th = 1000*(sz // 256) ** 2 # threshold for the minimum number of pixels","metadata":{"execution":{"iopub.status.busy":"2022-09-07T20:35:33.253672Z","iopub.execute_input":"2022-09-07T20:35:33.254174Z","iopub.status.idle":"2022-09-07T20:35:33.260077Z","shell.execute_reply.started":"2022-09-07T20:35:33.254014Z","shell.execute_reply":"2022-09-07T20:35:33.259115Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class HuBMAPDataset(Dataset):\n    def __init__(self, idx, sz=sz, reduce=reduce, encs=None):\n        self.data = rasterio.open(os.path.join(DATA,str(idx)+'.tiff'),num_threads='all_cpus')\n        # some images have issues with their format \n        # and must be saved correctly before reading with rasterio\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        self.shape = self.data.shape\n        self.reduce = reduce\n        self.sz = reduce*sz\n        self.pad0 = (self.sz - self.shape[0]%self.sz)%self.sz\n        self.pad1 = (self.sz - self.shape[1]%self.sz)%self.sz\n        self.n0max = (self.shape[0] + self.pad0)//self.sz\n        self.n1max = (self.shape[1] + self.pad1)//self.sz\n        self.mask = enc2mask(encs,(self.shape[1],self.shape[0])) if encs is not None else None\n        \n    def __len__(self):\n        return self.n0max*self.n1max\n    \n    def __getitem__(self, idx):\n        # the code below may be a little bit difficult to understand,\n        # but the thing it does is mapping the original image to\n        # tiles created with adding padding (like in the previous version of the kernel)\n        # then the tiles are loaded with rasterio\n        # n0,n1 - are the x and y index of the tile (idx = n0*self.n1max + n1)\n        n0,n1 = idx//self.n1max, idx%self.n1max\n        # x0,y0 - are the coordinates of the lower left corner of the tile in the image\n        # negative numbers correspond to padding (which must not be loaded)\n        x0,y0 = -self.pad0//2 + n0*self.sz, -self.pad1//2 + n1*self.sz\n\n        # make sure that the region to read is within the image\n        p00,p01 = max(0,x0), min(x0+self.sz,self.shape[0])\n        p10,p11 = max(0,y0), min(y0+self.sz,self.shape[1])\n        img = np.zeros((self.sz,self.sz,3),np.uint8)\n        mask = np.zeros((self.sz,self.sz),np.uint8)\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        if self.mask is not None: mask[(p00-x0):(p01-x0),(p10-y0):(p11-y0)] = self.mask[p00:p01,p10:p11]\n        \n        if self.reduce != 1:\n            img = cv2.resize(img,(self.sz//reduce,self.sz//reduce),\n                             interpolation = cv2.INTER_AREA)\n            mask = cv2.resize(mask,(self.sz//reduce,self.sz//reduce),\n                             interpolation = cv2.INTER_NEAREST)\n        #check for empty imges\n        hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)\n        h,s,v = cv2.split(hsv)\n        #return -1 for empty images\n        return img, mask, (-1 if (s>s_th).sum() <= p_th or img.sum() <= p_th else idx)","metadata":{"execution":{"iopub.status.busy":"2022-09-07T20:35:33.261338Z","iopub.execute_input":"2022-09-07T20:35:33.262308Z","iopub.status.idle":"2022-09-07T20:35:33.285892Z","shell.execute_reply.started":"2022-09-07T20:35:33.262270Z","shell.execute_reply":"2022-09-07T20:35:33.284735Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"x_tot,x2_tot = [],[]\nwith zipfile.ZipFile(OUT_TRAIN, 'w') as img_out,\\\n zipfile.ZipFile(OUT_MASKS, 'w') as mask_out:\n    for index, encs in tqdm(df_masks.iterrows(),total=len(df_masks)):\n        #image+mask dataset\n        ds = HuBMAPDataset(index,encs=encs)\n        for i in range(len(ds)):\n            im,m,idx = ds[i]\n            if idx < 0: continue\n                \n            x_tot.append((im/255.0).reshape(-1,3).mean(0))\n            x2_tot.append(((im/255.0)**2).reshape(-1,3).mean(0))\n            \n            #write data   \n            im = cv2.imencode('.png',cv2.cvtColor(im, cv2.COLOR_RGB2BGR))[1]\n            img_out.writestr(f'{index}_{idx:04d}.png', im)\n            m = cv2.imencode('.png',m)[1]\n            mask_out.writestr(f'{index}_{idx:04d}.png', m)\n        \n#image stats\nimg_avr =  np.array(x_tot).mean(0)\nimg_std =  np.sqrt(np.array(x2_tot).mean(0) - img_avr**2)\nprint('mean:',img_avr, ', std:', img_std)","metadata":{"execution":{"iopub.status.busy":"2022-09-07T20:35:33.287650Z","iopub.execute_input":"2022-09-07T20:35:33.287966Z","iopub.status.idle":"2022-09-07T20:39:07.171008Z","shell.execute_reply.started":"2022-09-07T20:35:33.287939Z","shell.execute_reply":"2022-09-07T20:39:07.169742Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"columns, rows = 4,4\nidx0 = 20\nfig=plt.figure(figsize=(columns*4, rows*4))\nwith zipfile.ZipFile(OUT_TRAIN, 'r') as img_arch, \\\n     zipfile.ZipFile(OUT_MASKS, 'r') as msk_arch:\n    fnames = sorted(img_arch.namelist())[8:]\n    for i in range(rows):\n        for j in range(columns):\n            idx = i+j*columns\n            img = cv2.imdecode(np.frombuffer(img_arch.read(fnames[idx0+idx]), \n                                             np.uint8), cv2.IMREAD_COLOR)\n            img = cv2.cvtColor(img, cv2.COLOR_RGB2BGR)\n            mask = cv2.imdecode(np.frombuffer(msk_arch.read(fnames[idx0+idx]), \n                                              np.uint8), cv2.IMREAD_GRAYSCALE)\n    \n            fig.add_subplot(rows, columns, idx+1)\n            plt.axis('off')\n            plt.imshow(Image.fromarray(img))\n            plt.imshow(Image.fromarray(mask), alpha=0.2)\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2022-09-07T20:42:25.596005Z","iopub.execute_input":"2022-09-07T20:42:25.596555Z","iopub.status.idle":"2022-09-07T20:42:27.188550Z","shell.execute_reply.started":"2022-09-07T20:42:25.596491Z","shell.execute_reply":"2022-09-07T20:42:27.187127Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}