{"cells":[{"metadata":{},"cell_type":"markdown","source":"This notebook is messy.\nIn last part of this notebook,I tried making mask of any size and any location without making full-size mask of original image."},{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"_kg_hide-output":true},"cell_type":"code","source":"# This Python 3 environment comes with many helpful analytics libraries installed\n# It is defined by the kaggle/python Docker image: https://github.com/kaggle/docker-python\n# For example, here's several helpful packages to load\n\n#https://www.kaggle.com/hirune924/fast-image-region-loading-using-pyvips\n!apt-get update\n!apt -y install --fix-missing libvips libvips-dev\n!pip install pyvips\n\nimport numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\nimport json\nimport cv2\nimport matplotlib.pyplot as plt\nimport gc\nimport pyvips\n\n# Input data files are available in the read-only \"../input/\" directory\n# For example, running this (by clicking run or pressing Shift+Enter) will list all files under the input directory\n\nimport os\nfor dirname, _, filenames in os.walk('/kaggle/input'):\n    for filename in filenames:\n        print(os.path.join(dirname, filename))\n\n# You can write up to 20GB to the current directory (/kaggle/working/) that gets preserved as output when you create a version using \"Save & Run All\" \n# You can also write temporary files to /kaggle/temp/, but they won't be saved outside of the current session","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","trusted":true,"_kg_hide-input":true},"cell_type":"code","source":"PATH_TRAIN = '/kaggle/input/hubmap-kidney-segmentation/train/'\nPATH_TEST = '/kaggle/input/hubmap-kidney-segmentation/test/'\nPATH_INFO='/kaggle/input/hubmap-kidney-segmentation/HuBMAP-20-dataset_information.csv'\n\ndf_info = pd.read_csv(PATH_INFO)\n\ndef make_related_file_path(idstr,mode='train'):\n    path_tiff = None\n    path_structure_json = None\n    path_json = None\n    idstr = idstr[:-5] if idstr.endswith('.tiff') else idstr\n    \n    if mode == 'train':\n        path_tiff = PATH_TRAIN + idstr +'.tiff'\n        path_structure_json = PATH_TRAIN + idstr + '-anatomical-structure.json'\n        path_json = PATH_TRAIN + idstr + '.json'\n    else:\n        path_tiff = PATH_TEST + idstr+'.tiff'\n        path_structure_json = PATH_TEST + idstr + '-anatomical-structure.json'\n    \n    img_size = df_info[df_info['image_file'] == idstr+'.tiff']['height_pixels'].values[0] , df_info[df_info['image_file'] == (idstr+'.tiff')]['width_pixels'].values[0]\n    \n    return path_tiff , path_structure_json , path_json , img_size\n        ","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_kg_hide-input":true},"cell_type":"code","source":"#These function may help me.\n\ndef read_json(path):\n    content = None\n    with open(path,'r') as f:\n        content = f.read()\n        \n    if content is None:\n        raise(f\"Error loading {path} json file.\")\n    \n    return json.loads(content)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"df_train = pd.read_csv('/kaggle/input/hubmap-kidney-segmentation/train.csv')\ndf_train.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"path_tiff,path_structure,path_json,img_size = make_related_file_path(df_train.iloc[0][0])\n\njson_file = read_json(path_json)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"geodata = []\nfor obj in json_file:\n    data = {}\n    coords = np.array(obj['geometry']['coordinates'])\n    pcentroid = np.mean(coords,axis=1,dtype=np.int)\n    pmax = np.max(coords,axis=1)\n    pmin = np.min(coords,axis=1)\n    \n    data['coords'] = coords\n    data['pcentroid'] = pcentroid\n    data['pmax'] = pmax\n    data['pmin'] = pmin\n    data['pboxcenter'] = (pmax + pmin)//2\n    data['boxlen'] = pmax-pmin\n    geodata.append(data)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"data = read_json(path_structure)\npolys = []\nfor index in range(data.__len__()):\n    geom = np.array(data[index]['geometry']['coordinates'])\n    polys.append(geom)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"shape = img_size\nmask_1 = np.zeros(shape)\nfor i in range(len(polys)):\n    cv2.fillPoly(mask_1, polys[i], i+1)\n\n#plt.imshow(mask_1)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Making minimap"},{"metadata":{},"cell_type":"markdown","source":"Minimap is created based on anatomical structure json file. I'll not train where minimap says 0. We can use anatomical structure in test file. (Maybe?)"},{"metadata":{},"cell_type":"markdown","source":"## Method 1 : Using created mask of original size."},{"metadata":{"trusted":true},"cell_type":"code","source":"chunk = 1024\nh,w = img_size[0], img_size[1]\nminimap = np.zeros(shape=(h//chunk,w//chunk))\nmh = h // chunk\nmw = w // chunk\n\nfor _h in range(mh):\n    for _w in range(mw):\n        ph = _h*chunk\n        pw = _w*chunk\n        \n        minimap[_h,_w] = np.amax(mask_1[ph:ph+chunk,pw:pw+chunk])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"plt.imshow(minimap)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"del mask_1\ngc.collect()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Method 2 : Transform polygon data into resized matrix."},{"metadata":{"trusted":true},"cell_type":"code","source":"polys","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"resized_polys = [poly // chunk for poly in polys]\n\nminimap2 = np.zeros(shape=(h//chunk,w//chunk))\n\nfor i in range(len(resized_polys)):\n    cv2.fillPoly(minimap2, resized_polys[i], i+1,4) # Linetype is 4.\n    \nplt.imshow(minimap2)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Ploting target mask"},{"metadata":{"trusted":true},"cell_type":"code","source":"mask_t = np.zeros(shape=shape,dtype=np.byte)\nfor data in geodata:\n    coord = data['coords']\n    cv2.fillPoly(mask_t,coord,1)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"plt.imshow(mask_t)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Let's see some shapes of target"},{"metadata":{"trusted":true},"cell_type":"code","source":"for data in geodata[:5]:\n    coords = data['coords']\n    pmin = data['pmin']\n    coords = coords - pmin\n    mask = np.zeros(shape=(data['boxlen'][0][1],data['boxlen'][0][0]))\n    centroid = data['pcentroid'] - pmin\n    cv2.fillPoly(mask,coords,1)\n    cv2.circle(mask,tuple(centroid[0]),3,(0,255,0),-1)\n    plt.imshow(mask)\n    plt.show()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"\n# Helper class for manipulate HuBMap Data\n"},{"metadata":{"trusted":true},"cell_type":"code","source":"class HuBMapDataPlay:\n    def __init__(self,\n                 path_base='../input/hubmap-kidney-segmentation/'\n                 ,chunksize = 512\n                 ,only_in_cortex=False ):\n        self.PATH_BASE = path_base\n        self.PATH_TRAIN = os.path.join(self.PATH_BASE,'train/')\n        self.PATH_TEST = os.path.join(self.PATH_BASE,'test/')\n        self.PATH_OUTPUT = './'\n        \n        #self.ANOTOMICAL_STRUCT_TYPE_MEDULLAR = \"Medullar\"\n        #self.ANOTOMICAL_STRUCT_TYPE_CORTEX = \"Cortex\"\n        #self.ANOTOMICAL_STRUCT_TYPE_STRIPE = \"Stripe\"\n        \n        \n        self.PATH ={\n            'BASE' : self.PATH_BASE,\n            'train' : self.PATH_TRAIN,\n            'test' : self.PATH_TEST,\n            'info' : os.path.join(self.PATH_BASE,'HuBMAP-20-dataset_information.csv')\n        }\n        \n        self.IMG_NAME = {\n            'train' : [name for name in os.listdir(self.PATH['train']) if name.endswith('.tiff')],\n            'test' : [name for name in os.listdir(self.PATH['test']) if name.endswith('.tiff')]\n        }\n        \n        self.additionaldata = {\n            'train' : {},\n            'test' : {}\n        }\n        \n        self.chunksize = chunksize\n        self.only_in_cortex = only_in_cortex\n        self.df_info = pd.read_csv(self.PATH['info'])\n        \n        for mode in ['train','test'] :\n            for img_name in self.IMG_NAME[mode]:\n                self.additionaldata[mode][img_name] = self.__get_additional_data(img_name,mode,chunksize is not None or chunksize is not 0)\n        \n        \n    def __get_additional_data(self,idstr,mode='train',create_minimap=True):\n        path_tiff = None\n        path_structure_json = None\n        path_json = None\n        \n        idstr = idstr[:-5] if idstr.endswith('.tiff') else idstr\n        data = {}\n    \n        if mode == 'train':\n            path_tiff = self.PATH_TRAIN + idstr +'.tiff'\n            path_structure_json = self.PATH_TRAIN + idstr + '-anatomical-structure.json'\n            path_json = self.PATH_TRAIN + idstr + '.json'\n        else:\n            path_tiff = self.PATH_TEST + idstr+'.tiff'\n            path_structure_json = self.PATH_TEST + idstr + '-anatomical-structure.json'\n    \n        img_size = self.df_info[self.df_info['image_file'] == idstr+'.tiff']['height_pixels'].values[0] , self.df_info[self.df_info['image_file'] == (idstr+'.tiff')]['width_pixels'].values[0]\n        \n        # get data from *-anatomical-structure.json\n        structure_json = self.__read_json(path_structure_json)\n        structure_polys = []\n        \n        for i in range(structure_json.__len__()):\n            iscortex = structure_json[i]['properties']['classification']['name']==\"Cortex\"\n            if (structure_json[i]['geometry']['type'] == \"Polygon\") and (not self.only_in_cortex or iscortex) :\n                poly = np.array(structure_json[i]['geometry']['coordinates'][0])\n                structure_polys.append(poly)\n            elif (structure_json[i]['geometry']['type'] == \"MultiPolygon\") and (not self.only_in_cortex or iscortex): \n                for poly in structure_json[i]['geometry']['coordinates'][0]:\n                    structure_polys.append(np.array(poly,dtype=np.int))\n        structure_polys = np.array(structure_polys)\n    \n    \n        # Get data from {idstr}.json\n        glomdata = None\n        glo_polys = []\n        if mode == 'train':\n            glomeruli_json = self.__read_json(path_json)\n            glomdata = []\n            glo_no = 0;\n            for obj in glomeruli_json:\n                data = {}\n                coords = np.array(obj['geometry']['coordinates'][0])\n                pcentroid = np.mean(coords,axis=0,dtype=np.int)\n                pmax = np.max(coords,axis=0)\n                pmin = np.min(coords,axis=0)\n                \n                data['no']= glo_no\n                data['coords'] = coords\n                data['pcentroid'] = pcentroid\n                data['pmax'] = pmax\n                data['pmin'] = pmin\n                data['pboxcenter'] = (pmax + pmin)//2\n                data['boxlen'] = pmax-pmin\n                glomdata.append(data)\n                glo_polys.append(coords)\n                glo_no = glo_no + 1\n        glo_polys = np.array(glo_polys)\n        \n        \n        # Create minimap\n        minimap = None\n        if create_minimap :\n            h,w = img_size[0], img_size[1]\n            resized_coords = structure_polys // self.chunksize \n            minimap = np.zeros(shape=((h//self.chunksize)+1,(w//self.chunksize)+1))\n\n            for i in range(len(resized_coords)):\n                cv2.fillPoly(minimap, [resized_coords[i]], i+1,4)\n                \n        # minimap for glu~ polygon\n        minimap_glomeruli = None\n        if create_minimap and mode=='train' :\n            h,w = img_size[0], img_size[1]\n            mh , mw = (h // self.chunksize)+1 , (w // self.chunksize) +1\n            minimap_glomeruli = [[[] for k in range(mw)] for i in range(mh)]\n            for glomeruli in glomdata :\n                _pmmax = glomeruli['pmax'] // self.chunksize\n                _pmmin = glomeruli['pmin'] // self.chunksize\n                for _mw in range(_pmmin[0],_pmmax[0]+1):\n                    for _mh in range(_pmmin[1],_pmmax[1]+1):\n                        try:\n                            minimap_glomeruli[_mh][_mw].append(glomeruli['no'])\n                        except IndexError:\n                            print(f\"\"\"IndexError raised. Glomeruli cannot be located in minimap. Check indexes.\n                            Data in {idstr}\n                            Glomeruli No : {glomeruli['no']}\n                            Minimap size (h,w): {mh},{mw}\n                            Position tried to locate (x,y): {_mw} ,{_mh}\n                            Pmax , Pmin: {glomeruli['pmax']} , {glomeruli['pmin']}\n                            Original Image size (h,w):{h},{w}\"\"\")\n                            \n                       \n        data ={\n            'id' : idstr,\n            'path_tiff' : path_tiff,\n            'path_structure_json' : path_structure_json,\n            'path_json' : path_json,\n            'img_size' : img_size,\n            'structure_polys' : structure_polys,\n            'glomeruli_data' : glomdata,\n            'minimap' : minimap,\n            'minimap_glomeruli':minimap_glomeruli,\n            'glo_polys':glo_polys\n        }\n        \n\n        return data\n        \n    def __read_json(self,path):\n        content = None\n        with open(path,'r') as f:\n            content = f.read()\n        \n        if content is None:\n            raise(f\"Error loading {path} json file.\")\n    \n        return json.loads(content)\n    \n    def draw_mask(self,img_name,pstart,rect): # Only for train data. \n        polygon_numbers = set()\n        pstart = np.array(pstart)\n        rect = np.array(rect)\n        \n        pend = pstart+rect\n        mps = pstart // self.chunksize\n        mpe = pend //self.chunksize\n        mask = np.zeros(shape=rect,dtype=np.byte)\n        \n        data = self.additionaldata['train'][img_name]\n        for _mw in range(mps[0],mpe[0]+1):\n            for _mh in range(mps[1],mpe[1]+1):\n                minimap_glo = data['minimap_glomeruli']\n                polygon_numbers.update(minimap_glo[_mh][_mw])\n        \n        polygons = [data['glo_polys'][poly_no] - pstart for poly_no in polygon_numbers]\n        cv2.fillPoly(mask,polygons,1)\n        \n        return mask\n        \n    def get_img(self,img_name,pstart,rect):\n        path = self.PATH['train']+img_name if img_name in self.IMG_NAME['train'] else self.PATH['train']+img_name\n        img = pyvips.Image.new_from_file(path)\n        patch = img.crop(pstart[0], pstart[1], rect[0], rect[1])\n        np_img = np.ndarray(buffer=patch.write_to_memory(),dtype=np.uint8,shape=[patch.height, patch.width, patch.bands])\n        return np_img\n    \n    def iter_train_chunk(self,img_name,use_minimap=False):\n        minimap = self.additionaldata['train'][img_name]['minimap']\n        h,w = minimap.shape\n        rect = [self.chunksize,self.chunksize]\n        for _w in range(w-1):\n            for _h in range(h-1):\n                \n                if use_minimap and (minimap[_h][_w] == 0) :\n                    continue\n                pstart = [_w*self.chunksize,_h*self.chunksize]\n                img = self.get_img(img_name,pstart,rect)\n                mask = self.draw_mask(img_name,pstart,rect)\n                yield img,mask,_h,_w\n                \n    def get_glomeruli_img_mask(self,img_name,idx):\n        chunkhalf = self.chunksize //2\n        glo = self.additionaldata['train'][img_name]['glomeruli_data'][idx]\n        pstart = glo['pboxcenter'] - chunkhalf\n        img = self.get_img(img_name,pstart,[self.chunksize,self.chunksize])\n        msk = self.draw_mask(img_name,pstart,[self.chunksize,self.chunksize])\n        return img,msk\n      \n                \n    def save_train_images_as_chunk(self,use_minimap=False):\n        for img_name in self.IMG_NAME['train'] :\n            name_head = self.PATH_OUTPUT+img_name[:-5]\n            print(f\"Processing {img_name}\")\n            for img,msk,h,w in self.iter_train_chunk(img_name,use_minimap):\n                np.savez(name_head+f\"_{h}_{w}\",img=img,msk=msk)\n                ","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"cvtr = HuBMapDataPlay()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"msk1 = cvtr.draw_mask('e79de561c.tiff',[50,600],[10000,10000])\nimg1 = cvtr.get_img('e79de561c.tiff',[50,600],[10000,10000])\n\nplt.imshow(msk1)\nplt.show()\nplt.imshow(img1)\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"msk2 = cvtr.draw_mask('0486052bb.tiff',[500,2500],[10240,10240])\nimg2 = cvtr.get_img('0486052bb.tiff',[500,2500],[10240,10240])\n\nplt.imshow(msk2)\nplt.show()\nplt.imshow(img2)\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"%%time\nmsk3 = cvtr.draw_mask('2f6ecfcdf.tiff',[1500,3000],[20000,20000])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"plt.imshow(msk3)\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"%%time\nmsk4 = cvtr.draw_mask('0486052bb.tiff',[4000,3500],[cvtr.chunksize,cvtr.chunksize])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"%%time\nfor img,msk,h,w in cvtr.iter_train_chunk('0486052bb.tiff',True):\n    if not (h%10) and not(w%10):\n        plt.imshow(img)\n        plt.show()\n        plt.imshow(msk)\n        plt.show()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#cvtr.save_train_images_as_chunk(True)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"for i in range(5):\n    img5,msk5=cvtr.get_glomeruli_img_mask('0486052bb.tiff',i*5)\n    plt.imshow(img5)\n    plt.show()\n    plt.imshow(msk5)\n    plt.show()","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}