{"cells":[{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"_kg_hide-input":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 in \n\nimport numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\n\n# Input data files are available in the \"../input/\" directory.\n# For example, running this (by clicking run or pressing Shift+Enter) will list the files in the input directory\n\nimport os\nprint(os.listdir(\"../input\"))\n\n# Any results you write to the current directory are saved as output.","execution_count":null,"outputs":[]},{"metadata":{"_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","trusted":true,"_kg_hide-input":true},"cell_type":"code","source":"import os, sys\nimport numpy as np\nimport pandas as pd\nimport matplotlib.pyplot as plt\nimport skimage.io\nfrom skimage.transform import resize\nfrom imgaug import augmenters as iaa\nfrom tqdm import tqdm\nimport PIL\nfrom PIL import Image, ImageOps\nimport cv2\nfrom sklearn.utils import class_weight, shuffle\nfrom keras.losses import binary_crossentropy\nfrom keras.applications.resnet50 import preprocess_input\nimport keras.backend as K\nimport tensorflow as tf\nfrom sklearn.metrics import f1_score, fbeta_score\nfrom keras.utils import Sequence\nfrom keras.utils import to_categorical\nfrom sklearn.model_selection import train_test_split\n\nWORKERS = 2\nCHANNEL = 3\n\nimport warnings\nwarnings.filterwarnings(\"ignore\")\nIMG_SIZE = 512\nNUM_CLASSES = 5\nSEED = 77\nTRAIN_NUM = 1000 # use 1000 when you just want to explore new idea, use -1 for full train","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"df_train = pd.read_csv('../input/aptos2019-blindness-detection/train.csv')\ndf_test = pd.read_csv('../input/aptos2019-blindness-detection/test.csv')\n\nx = df_train['id_code']\ny = df_train['diagnosis']\n\nx, y = shuffle(x, y, random_state=SEED)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_x, valid_x, train_y, valid_y = train_test_split(x, y, test_size=0.15,\n                                                      stratify=y, random_state=SEED)\nprint(train_x.shape, train_y.shape, valid_x.shape, valid_y.shape)\ntrain_y.hist()\nvalid_y.hist()","execution_count":null,"outputs":[]},{"metadata":{"_kg_hide-input":true,"trusted":true},"cell_type":"code","source":"%%time\nfig = plt.figure(figsize=(25, 16))\nfor class_id in sorted(train_y.unique()):\n    for i, (idx, row) in enumerate(df_train.loc[df_train['diagnosis'] == class_id].sample(5, random_state=SEED).iterrows()):\n        ax = fig.add_subplot(5, 5, class_id * 5 + i + 1, xticks=[], yticks=[])\n        path=f\"../input/aptos2019-blindness-detection/train_images/{row['id_code']}.png\"\n        image = cv2.imread(path)\n        image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)\n#         image=cv2.addWeighted ( image, 0 , cv2.GaussianBlur( image , (0 ,0 ) , 10) ,-4 ,128)\n        image = cv2.resize(image, (IMG_SIZE, IMG_SIZE))\n\n        plt.imshow(image, cmap='gray')\n        ax.set_title('Label: %d-%d-%s' % (class_id, idx, row['id_code']) )","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_kg_hide-input":true},"cell_type":"code","source":"dpi = 80 #inch\n\n# path=f\"../input/aptos2019-blindness-detection/train_images/5c7ab966a3ee.png\" # notice upper part\npath=f\"../input/aptos2019-blindness-detection/train_images/cd54d022e37d.png\" # lower-right, this still looks not so severe, can be class3\nimage = cv2.imread(path)\nimage = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)\nheight, width = image.shape\nprint(height, width)\n\nSCALE=2\nfigsize = (width / float(dpi))/SCALE, (height / float(dpi))/SCALE\n\nfig = plt.figure(figsize=figsize)\nplt.imshow(image, cmap='gray')","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Ben Graham's preprocessing method.\n\n","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"%%time\nfig = plt.figure(figsize=(25, 16))\nfor class_id in sorted(train_y.unique()):\n    for i, (idx, row) in enumerate(df_train.loc[df_train['diagnosis'] == class_id].sample(5, random_state=SEED).iterrows()):\n        ax = fig.add_subplot(5, 5, class_id * 5 + i + 1, xticks=[], yticks=[])\n        path=f\"../input/aptos2019-blindness-detection/train_images/{row['id_code']}.png\"\n        image = cv2.imread(path)\n        image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)\n#         image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)\n        image = cv2.resize(image, (IMG_SIZE, IMG_SIZE))\n        image=cv2.addWeighted ( image,4, cv2.GaussianBlur( image , (0,0) , IMG_SIZE/10) ,-4 ,128) # the trick is to add this line\n\n        plt.imshow(image, cmap='gray')\n        ax.set_title('Label: %d-%d-%s' % (class_id, idx, row['id_code']) )","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# 3. Further improve by auto-cropping\n\nTo crop out the uninformative black areas which are evident on pic(0,1), pic(0,3) and pic(4,1), we can try auto cropping. I found 4 alternative codes from https://stackoverflow.com/questions/13538748/crop-black-edges-with-opencv and https://codereview.stackexchange.com/questions/132914/crop-black-border-of-image-using-numpy/132934 ... Fortunately one method works perfectly for a gray scale image, but none works on a color image. In this kernel, I modify the method working on gray-scale a bit to make it suitable for a color image.\n","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"def crop_image1(img,tol=7):\n    # img is image data\n    # tol  is tolerance\n        \n    mask = img>tol\n    return img[np.ix_(mask.any(1),mask.any(0))]\n\ndef crop_image_from_gray(img,tol=7):\n    if img.ndim ==2:\n        mask = img>tol\n        return img[np.ix_(mask.any(1),mask.any(0))]\n    elif img.ndim==3:\n        gray_img = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)\n        mask = gray_img>tol\n        \n        check_shape = img[:,:,0][np.ix_(mask.any(1),mask.any(0))].shape[0]\n        if (check_shape == 0): # image is too dark so that we crop out everything,\n            return img # return original image\n        else:\n            img1=img[:,:,0][np.ix_(mask.any(1),mask.any(0))]\n            img2=img[:,:,1][np.ix_(mask.any(1),mask.any(0))]\n            img3=img[:,:,2][np.ix_(mask.any(1),mask.any(0))]\n    #         print(img1.shape,img2.shape,img3.shape)\n            img = np.stack([img1,img2,img3],axis=-1)\n    #         print(img.shape)\n        return img\n","execution_count":null,"outputs":[]},{"metadata":{"_kg_hide-input":true,"_kg_hide-output":true,"trusted":true},"cell_type":"code","source":"# OLD version of image color cropping, use crop_image_from_gray instead\n# The above code work only for 1-channel. Here is my simple extension for 3-channels image\ndef crop_image(img,tol=7):\n    if img.ndim ==2:\n        mask = img>tol\n        return img[np.ix_(mask.any(1),mask.any(0))]\n    elif img.ndim==3:\n        h,w,_=img.shape\n#         print(h,w)\n        img1=cv2.resize(crop_image1(img[:,:,0]),(w,h))\n        img2=cv2.resize(crop_image1(img[:,:,1]),(w,h))\n        img3=cv2.resize(crop_image1(img[:,:,2]),(w,h))\n        \n#         print(img1.shape,img2.shape,img3.shape)\n        img[:,:,0]=img1\n        img[:,:,1]=img2\n        img[:,:,2]=img3\n        return img\n\n'''all of these do not work'''\n\ndef crop_image2(image,threshold=5):\n    if len(image.shape) == 3:\n        flatImage = np.max(image, 2)\n    else:\n        flatImage = image\n    assert len(flatImage.shape) == 2\n\n    rows = np.where(np.max(flatImage, 0) > threshold)[0]\n    if rows.size:\n        cols = np.where(np.max(flatImage, 1) > threshold)[0]\n        image = image[cols[0]: cols[-1] + 1, rows[0]: rows[-1] + 1]\n    else:\n        image = image[:1, :1]\n\n    return image\n\ndef crop_image3(image):\n    mask = image > 0\n\n    # Coordinates of non-black pixels.\n    coords = np.argwhere(mask)\n\n    # Bounding box of non-black pixels.\n    x0, y0 = coords.min(axis=0)\n    x1, y1 = coords.max(axis=0) + 1   # slices are exclusive at the top\n    \n    # Get the contents of the bounding box.\n    cropped = image[x0:x1, y0:y1]\n    return cropped\n\ndef crop_image4(image):\n    _,thresh = cv2.threshold(image,1,255,cv2.THRESH_BINARY)\n    contours,hierarchy = cv2.findContours(thresh,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)\n    cnt = contours[0]\n    x,y,w,h = cv2.boundingRect(cnt)\n    crop = image[y:y+h,x:x+w]\n    return crop\n\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def load_ben_color(path, sigmaX=10):\n    image = cv2.imread(path)\n    image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)\n    image = crop_image_from_gray(image)\n    image = cv2.resize(image, (IMG_SIZE, IMG_SIZE))\n    image=cv2.addWeighted ( image,4, cv2.GaussianBlur( image , (0,0) , sigmaX) ,-4 ,128)\n        \n    return image","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_kg_hide-input":true},"cell_type":"code","source":"%%time\n\nNUM_SAMP=7\nfig = plt.figure(figsize=(25, 16))\nfor class_id in sorted(train_y.unique()):\n    for i, (idx, row) in enumerate(df_train.loc[df_train['diagnosis'] == class_id].sample(NUM_SAMP, random_state=SEED).iterrows()):\n        ax = fig.add_subplot(5, NUM_SAMP, class_id * NUM_SAMP + i + 1, xticks=[], yticks=[])\n        path=f\"../input/aptos2019-blindness-detection/train_images/{row['id_code']}.png\"\n        image = load_ben_color(path,sigmaX=30)\n\n        plt.imshow(image)\n        ax.set_title('%d-%d-%s' % (class_id, idx, row['id_code']) )","execution_count":null,"outputs":[]},{"metadata":{"_kg_hide-input":true,"trusted":true},"cell_type":"code","source":"def circle_crop(img, sigmaX=10):   \n    \"\"\"\n    Create circular crop around image centre    \n    \"\"\"    \n    \n    img = cv2.imread(img)\n    img = crop_image_from_gray(img)    \n    img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)\n    \n    height, width, depth = img.shape    \n    \n    x = int(width/2)\n    y = int(height/2)\n    r = np.amin((x,y))\n    \n    circle_img = np.zeros((height, width), np.uint8)\n    cv2.circle(circle_img, (x,y), int(r), 1, thickness=-1)\n    img = cv2.bitwise_and(img, img, mask=circle_img)\n    img = crop_image_from_gray(img)\n    img=cv2.addWeighted ( img,4, cv2.GaussianBlur( img , (0,0) , sigmaX) ,-4 ,128)\n    return img ","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"%%time\n## try circle crop\nNUM_SAMP=7\nfig = plt.figure(figsize=(25, 16))\nfor class_id in sorted(train_y.unique()):\n    for i, (idx, row) in enumerate(df_train.loc[df_train['diagnosis'] == class_id].sample(NUM_SAMP, random_state=SEED).iterrows()):\n        ax = fig.add_subplot(5, NUM_SAMP, class_id * NUM_SAMP + i + 1, xticks=[], yticks=[])\n        path=f\"../input/aptos2019-blindness-detection/train_images/{row['id_code']}.png\"\n        image = circle_crop(path,sigmaX=30)\n\n        plt.imshow(image)\n        ax.set_title('%d-%d-%s' % (class_id, idx, row['id_code']) )","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"\nWe can try plotting a picture (sample train pic(4,1) above) with IMG_SIZE with cropping, now important information is much clearer to see with `sigmaX = 10`","execution_count":null},{"metadata":{"trusted":true,"_kg_hide-input":true},"cell_type":"code","source":"dpi = 80 #inch\n\n# path=f\"../input/aptos2019-blindness-detection/train_images/5c7ab966a3ee.png\" # notice upper part\npath=f\"../input/aptos2019-blindness-detection/train_images/cd54d022e37d.png\" # lower-right, can be class3\nimage = load_ben_color(path,sigmaX=10)\n\nheight, width = IMG_SIZE, IMG_SIZE\nprint(height, width)\n\nSCALE=1\nfigsize = (width / float(dpi))/SCALE, (height / float(dpi))/SCALE\n\nfig = plt.figure(figsize=figsize)\nplt.imshow(image, cmap='gray')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_kg_hide-input":true},"cell_type":"code","source":"%%time\nNUM_SAMP=10\nfig = plt.figure(figsize=(25, 16))\nfor jj in range(5):\n    for i, (idx, row) in enumerate(df_test.sample(NUM_SAMP,random_state=SEED+jj).iterrows()):\n        ax = fig.add_subplot(5, NUM_SAMP, jj * NUM_SAMP + i + 1, xticks=[], yticks=[])\n        path=f\"../input/aptos2019-blindness-detection/test_images/{row['id_code']}.png\"\n        image = load_ben_color(path,sigmaX=30)\n        \n        plt.imshow(image)\n        ax.set_title('%d-%s' % (idx, row['id_code']) )","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_kg_hide-input":true,"_kg_hide-output":true},"cell_type":"code","source":"%%time\n'''Bonus : sigmaX=50'''\nNUM_SAMP=10\nfig = plt.figure(figsize=(25, 16))\nfor jj in range(5):\n    for i, (idx, row) in enumerate(df_test.sample(NUM_SAMP,random_state=SEED+jj).iterrows()):\n        ax = fig.add_subplot(5, NUM_SAMP, jj * NUM_SAMP + i + 1, xticks=[], yticks=[])\n        path=f\"../input/aptos2019-blindness-detection/test_images/{row['id_code']}.png\"\n        image = load_ben_color(path,sigmaX=50)\n\n        plt.imshow(image, cmap='gray')\n        ax.set_title('%d-%s' % (idx, row['id_code']) )","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_kg_hide-input":true,"_kg_hide-output":true},"cell_type":"code","source":"'''\n# This is the old imperfect 'by-channel' color cropping code\n# this code can cause different crop among 3 channels\n\n# try cropping color image with the fixed function\n# path=f\"../input/aptos2019-blindness-detection/train_images/5c7ab966a3ee.png\"\npath=f\"../input/aptos2019-blindness-detection/train_images/cd54d022e37d.png\"\nimage = cv2.imread(path)\nimage = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)\nimage = crop_image(image)\n# image = crop_image_from_gray(image)\nimage = cv2.resize(image, (IMG_SIZE, IMG_SIZE))\nimage=cv2.addWeighted ( image,4, cv2.GaussianBlur( image , (0,0) , 10) ,-4 ,128)\n\nheight, width = IMG_SIZE, IMG_SIZE\nprint(height, width)\n\nSCALE=1\nfigsize = (width / float(dpi))/SCALE, (height / float(dpi))/SCALE\n\nfig = plt.figure(figsize=figsize)\nplt.imshow(image)\n'''","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"","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}