{"cells":[{"metadata":{},"cell_type":"markdown","source":"Did you finally train your model and predicted that huge images? Now that you have a HUGE (30k+, 40k+) pixel mask image you have to RLE encode it... and get a OOM exception!\n\nYour problems are solved (at least I hope so). The following function is a modification of [this one](https://www.kaggle.com/lifa08/run-length-encode-and-decode).\n\nBUT there is a trade-off: **the first and the last pixels are not encoded**. This save one `np.concatenate` that duplicates memory and may cause OOM."},{"metadata":{"trusted":true},"cell_type":"code","source":"import numpy as np\nimport cv2\nimport matplotlib.pyplot as plt\n\n%matplotlib inline","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"code","source":"# SRC: https://www.kaggle.com/lifa08/run-length-encode-and-decode\ndef rle_encode(img):\n    '''\n    img: numpy array, 1 - mask, 0 - background\n    Returns run length as string formated\n    '''\n    pixels = img.T.flatten()\n    pixels = np.concatenate([[0], pixels, [0]])\n    runs = np.where(pixels[1:] != pixels[:-1])[0] + 1\n    runs[1::2] -= runs[::2]\n    return ' '.join(str(x) for x in runs)\n\ndef rle_decode(mask_rle, shape):\n    '''\n    mask_rle: run-length as string formated (start length)\n    shape: (height,width) of array to return \n    Returns numpy array, 1 - mask, 0 - background\n    '''\n    s = mask_rle.split()\n    starts, lengths = [np.asarray(x, dtype=int) for x in (s[0:][::2], s[1:][::2])]\n    starts -= 1\n    ends = starts + lengths\n    img = np.zeros(shape[0] * shape[1], dtype=np.uint8)\n\n    for lo, hi in zip(starts, ends):\n        img[lo:hi] = 1\n    return img.reshape(shape)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"code","source":"# New version\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)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Create a sample image."},{"metadata":{"_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","trusted":true},"cell_type":"code","source":"im = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (64, 64))\nplt.imshow(im)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"First we test for equal values."},{"metadata":{"trusted":true},"cell_type":"code","source":"rle = rle_encode(im)\nrle2 = rle_encode_less_memory(im)\n\nassert rle == rle2","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Add border on image."},{"metadata":{"trusted":true},"cell_type":"code","source":"im[0] = 1\nim[-1] = 1\nim[:, 0] = 1\nim[:, -1] = 1\nplt.imshow(im)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Re-encode with each method."},{"metadata":{"trusted":true},"cell_type":"code","source":"rle = rle_encode(im)\nrle2 = rle_encode_less_memory(im)\n\nassert rle != rle2","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Decode and plot results. Note the missing pixels on top-left and bottom-right of second image."},{"metadata":{"trusted":true},"cell_type":"code","source":"im1 = rle_decode(rle, im.shape)\nim2 = rle_decode(rle2, im.shape)\n\nplt.figure(figsize=(10, 5))\nplt.subplot(121)\nplt.title('Exact method')\nplt.imshow(im1)\n\nplt.subplot(122)\nplt.title('Skipping first and last pixel method')\nplt.imshow(im2)","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}