{"cells":[{"metadata":{},"cell_type":"markdown","source":"OK, do we really need another set of RLE decoding and encoding routines? I think so, because I spent way too much time fiddling with existing ones, so I wrote another one from scratch.\n\nThese routines are\n* memory-efficient\n* fast\n* definitely correct on a pixel basis for the specific format used in this competition.\n\nSome other routines I've found were off 1 pixel (not that it matters, but aren't we all a bit nitpicky in this line of work ;)) or had other limitations."},{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"code","source":"import numpy as np\nimport matplotlib.pyplot as plt\nimport pandas as pd\nimport tifffile as tiff","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","trusted":true},"cell_type":"code","source":"def rle2mask(rle, mask_shape):\n    ''' takes a space-delimited RLE string in column-first order\n    and turns it into a 2d boolean numpy array of shape mask_shape '''\n    \n    mask = np.zeros(np.prod(mask_shape), dtype=bool) # 1d mask array\n    rle = np.array(rle.split()).astype(int) # rle values to ints\n    starts = rle[::2]\n    lengths = rle[1::2]\n    for s, l in zip(starts, lengths):\n        mask[s:s+l] = True\n    return mask.reshape(np.flip(mask_shape)).T # flip because of column-first order\n\n\ndef mask2rle(mask):\n    ''' takes a 2d boolean numpy array and turns it into a space-delimited RLE string '''\n    \n    mask = mask.T.reshape(-1) # make 1D, column-first\n    mask = np.pad(mask, 1) # make sure that the 1d mask starts and ends with a 0\n    starts = np.nonzero((~mask[:-1]) & mask[1:])[0] # start points\n    ends = np.nonzero(mask[:-1] & (~mask[1:]))[0] # end points\n    rle = np.empty(2 * starts.size, dtype=int) # interlacing...\n    rle[0::2] = starts # ...starts...\n    rle[1::2] = ends - starts # ...and lengths\n    rle = ' '.join([ str(elem) for elem in rle ]) # turn into space-separated string\n    return rle","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Let's check with the original train RLEs:"},{"metadata":{"trusted":true},"cell_type":"code","source":"df_enc = pd.read_csv('../input/hubmap-kidney-segmentation/train.csv')\ndf_enc","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"We'll take image 0486052bb:"},{"metadata":{"trusted":true},"cell_type":"code","source":"enc_original = df_enc.iloc[3,1]\nenc_original[:1000]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"tiff_shape = tiff.TiffFile('../input/hubmap-kidney-segmentation/train/0486052bb.tiff').pages[0].shape[:2]\ntiff_shape","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Fast decoding:"},{"metadata":{"trusted":true},"cell_type":"code","source":"%%time\nmask = rle2mask(enc_original, tiff_shape)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Mask looks ok *and is in the correct numpy orientation*:"},{"metadata":{"trusted":true},"cell_type":"code","source":"plt.imshow(mask[::50,::50]);","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Fast encoding, no RAM was harmed in the process..."},{"metadata":{"trusted":true},"cell_type":"code","source":"%%time\nenc_reencoded = mask2rle(mask)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"And the final check:"},{"metadata":{"trusted":true},"cell_type":"code","source":"enc_reencoded[:1000]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"enc_original == enc_reencoded","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"raw","source":"Here we go. Enjoy!"}],"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}