{"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":"The data augmentation for this notebook was taken from the excellent \"Gaussian-Laplacian Pyramid Blending\" notebook found here:\n\nhttps://www.kaggle.com/code/nghihuynh/data-augmentation-laplacian-pyramid-blending/notebook","metadata":{}},{"cell_type":"markdown","source":"# Imports","metadata":{}},{"cell_type":"code","source":"import numpy as np\nimport pandas as pd\nimport matplotlib.pyplot as plt\nimport cv2\nimport imageio\nimport tifffile as tiff\nfrom PIL import Image\nimport numpy as np\nimport seaborn as sns\nimport scipy.signal as sig\nfrom scipy import misc\nimport matplotlib.pyplot as plt\nfrom scipy import ndimage\nimport cv2\nimport imageio\nfrom PIL import Image","metadata":{"execution":{"iopub.status.busy":"2022-08-03T14:26:03.274256Z","iopub.execute_input":"2022-08-03T14:26:03.275040Z","iopub.status.idle":"2022-08-03T14:26:05.115961Z","shell.execute_reply.started":"2022-08-03T14:26:03.274912Z","shell.execute_reply":"2022-08-03T14:26:05.114616Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Load Gaussian Kernel","metadata":{}},{"cell_type":"code","source":"kernel = (1.0/256)*np.array([[1, 4, 6, 4, 1],[4, 16, 24, 16, 4],[6, 24, 36, 24, 6],[4, 16, 24, 16, 4],[1, 4, 6, 4, 1]])\n\nplt.imshow(kernel, cmap='seismic')\nplt.show()\n\nkernel.shape","metadata":{"execution":{"iopub.status.busy":"2022-08-03T14:26:05.118817Z","iopub.execute_input":"2022-08-03T14:26:05.119710Z","iopub.status.idle":"2022-08-03T14:26:05.384643Z","shell.execute_reply.started":"2022-08-03T14:26:05.119659Z","shell.execute_reply":"2022-08-03T14:26:05.382616Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Gaussian-Laplacian blending","metadata":{}},{"cell_type":"code","source":"# https://github.com/twyunting/Laplacian-Pyramids\n\n\ndef interpolate(image):\n    \"\"\"\n    Interpolates an image with upsampling rate r = 2\n    \"\"\"\n    image_up = np.zeros((2*image.shape[0], 2*image.shape[1]))\n    # Upsample\n    image_up[::2, ::2] = image\n    # Blur (we need to scale this up since the kernel has unit area)\n    # (The length and width are both doubled, so the area is quadrupled)\n    #return sig.convolve2d(image_up, 4*kernel, 'same')\n    return ndimage.filters.convolve(image_up,4*kernel, mode='constant')\n                                \ndef decimate(image):\n    \"\"\"\n    Decimates an image with downsampling rate r=2.\n    \"\"\"\n    image_blur = ndimage.filters.convolve(image,kernel, mode='constant')\n    # Downsample\n    return image_blur[::2, ::2]                                \n               \n                                      \n# here is the constructions of pyramids\ndef pyramids(image):\n    \"\"\"\n    Constructs Gaussian and Laplacian pyramids.\n    Parameters :\n    image  : the original image (i.e. base of the pyramid)\n    Returns :\n    G   : the Gaussian pyramid\n    L   : the Laplacian pyramid\n    \"\"\"\n    # Initialize pyramids\n    G = [image, ]\n    L = []\n\n    # Build the Gaussian pyramid to maximum depth\n    while image.shape[0] >= 2 and image.shape[1] >= 2:\n        image = decimate(image)\n        G.append(image)\n\n   # Build the Laplacian pyramid\n    for i in range(len(G) - 1):\n        L.append(G[i] - interpolate(G[i + 1]))\n\n    return G[:-1], L\n\n\n# Build Gaussian pyramid and Laplacian pyramids from images A and B, also mask\n# Reference: https://becominghuman.ai/image-blending-using-laplacian-pyramids-2f8e9982077f\ndef pyramidBlending(A, B, mask):\n    [GA, LA] = pyramids(A)\n    [GB ,LB] = pyramids(B)\n    # Build a Gaussian pyramid GR from selected region R (mask that says which pixels come from left and which from right)\n    [Gmask, LMask] = pyramids(mask)\n    # Form a combined pyramid LS from LA and LB using nodes of GR as weights\n    # Equation: LS(i, j) = GR(I, j)*LA(I, j) + (1-GR(I, j)* LB(I, j))\n    # Collapse the LS pyramid to get the final blended image\n    blend = []\n    for i in range(len(LA)):\n        # LS = np.max(Gmask[i])*LA[i] + (1-np.max(Gmask[i]))*LB[i]\n        # make sure the color with in 255 (white)\n        LS = Gmask[i]/255*LA[i] + (1-Gmask[i]/255)*LB[i]\n        blend.append(LS)\n    return blend\n\n# reconstruct the pyramids as well as upsampling and add up with each level\ndef reconstruct(pyramid):\n    rows, cols = pyramid[0].shape\n    res = np.zeros((rows, cols + cols//2), dtype= np.double)\n    # start the smallest pyramid so we need to reverse the order\n    revPyramid = pyramid[::-1]\n    stack = revPyramid[0]\n    # start with the second index\n    for i in range(1, len(revPyramid)):\n        stack = interpolate(stack) + revPyramid[i] # upsampling simultaneously\n    return stack\n   \n\n# https://compvisionlab.wordpress.com/2013/05/13/image-blending-using-pyramid/\n# Besides pyramid Blending, we need to blend image's color\ndef colorBlending(img1, img2, mask):\n    # split to 3 basic color, then using pyramidBlending and reconstruct it, respectively\n    img1R,img1G,img1B = cv2.split(img1)\n    img2R,img2G,img2B = cv2.split(img2)\n    # reconstruct each color channel and convert to uint8 to return proper img\n    R = reconstruct(pyramidBlending(img1R, img2R, mask))\n    G = reconstruct(pyramidBlending(img1G, img2G, mask))\n    B = reconstruct(pyramidBlending(img1B, img2B, mask))\n    output = cv2.merge((R, G, B))#.astype('uint8')\n    imageio.imsave(\"output.png\", output)\n    img = cv2.imread(\"output.png\")\n    #img = imageio.v2.imread(\"output.png\")\n    return img\n    \n","metadata":{"execution":{"iopub.status.busy":"2022-08-03T14:26:05.387119Z","iopub.execute_input":"2022-08-03T14:26:05.387709Z","iopub.status.idle":"2022-08-03T14:26:05.407915Z","shell.execute_reply.started":"2022-08-03T14:26:05.387643Z","shell.execute_reply":"2022-08-03T14:26:05.406719Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"data_frame = pd.read_csv('../input/hubmap-organ-segmentation/train.csv')\ndata_frame.head()","metadata":{"execution":{"iopub.status.busy":"2022-08-03T14:26:05.410566Z","iopub.execute_input":"2022-08-03T14:26:05.411742Z","iopub.status.idle":"2022-08-03T14:26:05.808555Z","shell.execute_reply.started":"2022-08-03T14:26:05.411696Z","shell.execute_reply":"2022-08-03T14:26:05.807123Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# generate mask\nmask = np.zeros((512,512))\nmask[:, 256:] = 255\n\nplt.imshow(mask, cmap='gray')\nplt.title('Mask')\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2022-08-03T14:26:05.812281Z","iopub.execute_input":"2022-08-03T14:26:05.812642Z","iopub.status.idle":"2022-08-03T14:26:06.049471Z","shell.execute_reply.started":"2022-08-03T14:26:05.812611Z","shell.execute_reply":"2022-08-03T14:26:06.048105Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Helper functions","metadata":{}},{"cell_type":"code","source":"def highlight(row):\n    df = lambda x: ['background: #CCCCFF' if x.name in row\n                        else '' for i in x]\n    return df","metadata":{"execution":{"iopub.status.busy":"2022-08-03T14:26:06.051441Z","iopub.execute_input":"2022-08-03T14:26:06.051965Z","iopub.status.idle":"2022-08-03T14:26:06.058071Z","shell.execute_reply.started":"2022-08-03T14:26:06.051919Z","shell.execute_reply":"2022-08-03T14:26:06.056836Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def plot_blended_img(img_A, img_B, mask, organ):\n    plt.figure(figsize=(16,9))\n    \n    plt.subplot(1,4,1)\n    plt.imshow(img_A)\n    plt.title('Image A')\n    \n    plt.subplot(1,4,2)\n    plt.imshow(img_B)\n    plt.title('Image B')\n    \n    plt.subplot(1,4,3)\n    plt.imshow(mask,cmap='gray')\n    plt.title('Mask')\n    \n    plt.subplot(1,4,4)\n    blended_img = colorBlending(img_A, img_B, mask)\n    plt.imshow(blended_img)\n    plt.title('Blended Image')\n    \n    plt.suptitle(f'{organ}', fontsize=20, y=0.75)\n    plt.tight_layout()\n    plt.show()","metadata":{"execution":{"iopub.status.busy":"2022-08-03T14:26:06.059841Z","iopub.execute_input":"2022-08-03T14:26:06.060531Z","iopub.status.idle":"2022-08-03T14:26:06.072740Z","shell.execute_reply.started":"2022-08-03T14:26:06.060493Z","shell.execute_reply":"2022-08-03T14:26:06.071465Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import os\nimport shutil\n\ntry:\n    shutil.rmtree('train')\nexcept:\n    print('Could not remove \"train\"')\n\ntry:\n    os.mkdir('train')\nexcept:\n    print('Could not make train folder.')\n\nprint(len(os.listdir('train')))\n\nfor fname in os.listdir('../input/hubmap-organ-512512/train/'):\n    shutil.copy2(f'../input/hubmap-organ-512512/train/{fname}', f'train/{fname}')\n\nprint(len(os.listdir('train')))","metadata":{"execution":{"iopub.status.busy":"2022-08-03T14:26:06.074295Z","iopub.execute_input":"2022-08-03T14:26:06.075429Z","iopub.status.idle":"2022-08-03T14:26:10.503065Z","shell.execute_reply.started":"2022-08-03T14:26:06.075380Z","shell.execute_reply":"2022-08-03T14:26:10.502128Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sliced = data_frame[['id', 'organ', 'data_source', 'age', 'sex']]\ndisplay(sliced.groupby('organ')['id'].count())\nmaxval = sliced.groupby('organ')['id'].count().max()\nprint(maxval)\nnew = sliced.copy(deep=True)","metadata":{"execution":{"iopub.status.busy":"2022-08-03T14:26:10.504562Z","iopub.execute_input":"2022-08-03T14:26:10.505925Z","iopub.status.idle":"2022-08-03T14:26:10.529038Z","shell.execute_reply.started":"2022-08-03T14:26:10.505881Z","shell.execute_reply":"2022-08-03T14:26:10.527561Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from tqdm import tqdm\n\ndef get_image(id):\n    return imageio.v2.imread(f'train/{id}_0000.png')\n\nfor organ in ['kidney', 'largeintestine', 'lung', 'prostate', 'spleen']:\n#     print(organ)\n    odf = sliced[sliced['organ'] == organ]\n    leng = len(new[new['organ'] == organ])\n    with tqdm(total=maxval - leng, desc=organ) as pbar:\n        while leng < maxval:\n            leng = len(new[new['organ'] == organ])\n            try:\n                two = odf.sample(n = 2)\n                r1 = two.head(1)\n                r2 = two.tail(1)\n                id1 = r1['id'].values[0]\n                id2 = r2['id'].values[0]\n                im1 = get_image(id1)\n                im2 = get_image(id2)\n                blended = colorBlending(im1, im2, mask)\n                #         imageio.v2.imsave(f'train/{id1}.png', im1)\n                #         imageio.v2.imsave(f'train/{id2}.png', im2)\n                imageio.v2.imsave(f'train/{id1}_{id2}.png', blended)\n                new = new.append(pd.Series({'id': f'{id1}_{id2}', 'organ': organ, 'data_source': '', 'age': '', 'sex': ''}), ignore_index = True)\n#                 print(leng)\n                pbar.update(1)\n                #         plot_blended_img(im1, im2, mask, organ)\n            except Exception as e:\n                print(e)\n\nprint('Done!')","metadata":{"execution":{"iopub.status.busy":"2022-08-03T14:26:10.533439Z","iopub.execute_input":"2022-08-03T14:26:10.534626Z","iopub.status.idle":"2022-08-03T14:31:07.742291Z","shell.execute_reply.started":"2022-08-03T14:26:10.534586Z","shell.execute_reply":"2022-08-03T14:31:07.740622Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}