{"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":{},"cell_type":"markdown","source":"# UPDATE on V9:\nThis kernel have two important updates.\n\n* Before Version 8, I couldn't make Ben's and Cropping method work together nicely, so I emphasized on gray scale. Now, I adjust both functions and beleive that color version is better than gray scale.\n\n* Before Version 9, I found a bug that will cause an old crop function to fail in a private test set (it works fine on training and public test sets). Here, I fix that bug. However, I still cannot guarantee whether there will be any more cases on private test set that will fail the crop function. **Update on V11** Now I was able to have a valid LB score with the new crop function, so if anybody still have some submission errors, that is the reason of other bugs.\n\n## update on V14.\n* Compare to circle crop in Section 3.A2 according to @taindow : please visit his kernel : https://www.kaggle.com/taindow/pre-processing-train-and-test-images\n\nOther minor updates. Note on estimation inconsistency and Aravind's history."},{"metadata":{},"cell_type":"markdown","source":"\n# 1. Introduction. Explore first, train later.\n\nHi everyone! As *Aravind Eye Hospital* is one of my favorite organization in the world; they take care of poor people's eyes for free with an impressive sustainable business model.  I will try my best to contribute something to our community. One intuitive way to improve the performance of our model is to simply improve the quality of input images. In this kernel, I will share two ideas which I hope may be useful to some of you : \n\n- **Reducing lighting-condition effects** : as we will see, images come with many different lighting conditions, some images are very dark and difficult to visualize. We can try to convert the image to gray scale, and visualize better. Alternatively, there is a better approach. We can try the method of [Ben Graham (last competition's winner)](https://github.com/btgraham/SparseConvNet/tree/kaggle_Diabetic_Retinopathy_competition)\n- **Cropping uninformative area** : everyone know this :) Here, I just find the codes from internet and choose the best one for you :)\n\nWe are going to apply both techniques to both the official data, and the past competition data (shout out @tanlikesmath for creating this dataset! https://www.kaggle.com/tanlikesmath/diabetic-retinopathy-resized . In the updated version, I also try @donkeys' dataset https://www.kaggle.com/donkeys/retinopathy-train-2015 , which is .png which may be have higer image quality than .jpeg format)\n\nIf I found more useful tricks, I will update the notebook, or if you have more useful tricks and would love to share, please let me know!\n\nI use some parts of codes from @mathormad and @artgor kernels. Thanks both of you!"},{"metadata":{},"cell_type":"markdown","source":"Now let us start by loading the train/test dataframes. The `train_test_split` here is in fact not necessary. But when I first fork the kernel from @mathormad, I found some interesting examples using this split and the current `SEED`, so I continue to use them here."},{"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)\n","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":{},"cell_type":"markdown","source":"## 1.1 Simple picture to explain Diabetic Retinopathy\n\nHow do we know that a patient have diabetic retinopahy? **[There are at least 5 things to spot on](https://www.eyeops.com/contents/our-services/eye-diseases/diabetic-retinopathy)**. Image credit https://www.eyeops.com/\n![credit : https://www.eyeops.com/](https://sa1s3optim.patientpop.com/assets/images/provider/photos/1947516.jpeg)"},{"metadata":{},"cell_type":"markdown","source":"From quick investigations of the data (see various pictures below), I found that *Hemorrphages, Hard Exudates and Cotton Wool spots* are quite easily observed. However, I still could not find examples of *Aneurysm* or *Abnormal Growth of Blood Vessels* from our data yet. Perhaps the latter two cases are important if we want to catch up human benchmnark using our model."},{"metadata":{},"cell_type":"markdown","source":"## 1.2 Original Inputs\n\nFirst, let have a glance of original inputs. Each row depicts each severity level. We can see two problems which make the severity difficult to spot on. First, some images are very dark [pic(0,2) and pic(4,4) ] and sometimes different color illumination is confusing [pic (3,3)]. Second, we can get the uninformative dark areas for some pictures [pic(0,1), pic(0,3)]. This is important when we reduce the picture size, as informative areas become too small. So it is intuitive to crop the uninformative areas out in the second case."},{"metadata":{"_kg_hide-input":true,"trusted":true},"cell_type":"code","source":"%%time\nfig = plt.figure(figsize=(25, 16))\n# display 10 images from each class\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_BGR2RGB)\n        image = cv2.resize(image, (IMG_SIZE, IMG_SIZE))\n\n        plt.imshow(image)\n        ax.set_title('Label: %d-%d-%s' % (class_id, idx, row['id_code']) )\n        \n","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"We can try gray scale and feel understand better for some pictures, as color distraction is gone. For example, we can see more blood clearer in the upper part of pic(4,4), which has severity of level 4."},{"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":{},"cell_type":"markdown","source":"For severity level 4, I feel that two examples here are difficult to spot on, pic(4,1) and pic(4,4). As we try zooming to see the details (use real size image), we can see some abnormalities (*cotton wool spots* or *hard exudates* ?) in those eyes clearer (observe the lower-right part of the eye). Therefore, `IMG_SIZE` is definitely important for this problem. In the next section, we shall see better method than gray-scale conversion."},{"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":"# 2. Try Ben Graham's preprocessing method.\n\nIn the last competition, [Ben Graham (last competition's winner)](https://github.com/btgraham/SparseConvNet/tree/kaggle_Diabetic_Retinopathy_competition) share insightful way to improve lighting condition. Here, we apply his idea, and can see many important details in the eyes much better. For full details, please refer to his technical report in the link above."},{"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"},{"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":{},"cell_type":"markdown","source":"### Try Cropping the images\n\nI have tested on around 200 images, and the method works great. However, if anybody find the outlier cases which cause the auto crop to fail, please let me know. I think now the eye pictures are very like the moon by the way :)\n\n**IMPORTANT UPDATE on Kernel V.9** I found that there is indeed a case in private test set making the old version of crop function fail. (I spent my 13 submissions until I found this bug) E.g. if there is an adversarial image (super dark) in the private test set, the crop function will crop everything and result in 0 dimension image. I have fixed this bug in this kernel version, but I still could not guarantee whether there are other cases in a private test that will make the crop function fail or not. **Update on V11** Now I was able to have a valid LB score with the new crop function, so if anybody still have some submission errors, that is the reason of other bugs.\n"},{"metadata":{},"cell_type":"markdown","source":"# 3.A Important Update on Color Version of Cropping & Ben's Preprocessing\nAt first, when I wrote this kernel, I could not make a color crop nicely, so I thought that gray scale is a better representation. Now I believe that color version is better, so from this point on I will use color cropping\n\nBelow is the cropped of the color version. For color version, note that I use argument `sigmaX = 30` of `cv2.GaussianBlur`, where Ben actually used `sigmaX = 10` which may have better performance. I just feel that this `sigmaX = 30` or `sigmaX = 50` make beautiful [sometimes bloody] yellow moon pictures. Just for the purpose of illustration.\n\nPlease refer to https://www.tutorialkart.com/opencv/python/opencv-python-gaussian-image-smoothing/ . "},{"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":{},"cell_type":"markdown","source":"## 3.A2 Try the new idea of circle crop\n\n@taindow proposes an interesting idea of making a circle crop to the image, so I update the kernel to let you compare the results. Credit : https://www.kaggle.com/taindow/pre-processing-train-and-test-images ... Observe that we now get a magic circle, but by using circle crop, some scabs/wools may get loss."},{"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`"},{"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":{},"cell_type":"markdown","source":"## Try the method on Public Test Set\nWe can also try auto cropping on 50 test data to see that it work fine. Below, we see immediately from this random samples that severed cases, with level >2, are relatively many more compared to the training set."},{"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":{},"cell_type":"markdown","source":"# 4. Try the same method to Past competition data\nThanks @tanlikesmath, https://www.kaggle.com/tanlikesmath/diabetic-retinopathy-resized who provides us a complete previous-competition dataset in the .jpeg format; this is much smaller than the original version with the risk of losing image details. Let apply both normal gray scale, and Ben Graham's method to this dataset."},{"metadata":{"trusted":true},"cell_type":"code","source":"!ls ../input/diabetic-retinopathy-resized/","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"!ls ../input/diabetic-retinopathy-resized/resized_train/resized_train | head","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"df_old = pd.read_csv('../input/diabetic-retinopathy-resized/trainLabels.csv')\n\ndf_old.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_kg_hide-input":true},"cell_type":"code","source":"NUM_SAMP=10\nfig = plt.figure(figsize=(25, 16))\nfor class_id in sorted(train_y.unique()):\n    for i, (idx, row) in enumerate(df_old.loc[df_old['level'] == 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/diabetic-retinopathy-resized/resized_train/resized_train/{row['image']}.jpeg\"\n        image = load_ben_color(path,sigmaX=30)\n\n        plt.imshow(image)\n        ax.set_title('%d-%d-%s' % (class_id, idx, row['image']) )","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Below is the unpreprocess version, just for comparison"},{"metadata":{"trusted":true,"_kg_hide-input":true},"cell_type":"code","source":"NUM_SAMP=10\nfig = plt.figure(figsize=(25, 16))\nfor class_id in sorted(train_y.unique()):\n    for i, (idx, row) in enumerate(df_old.loc[df_old['level'] == 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/diabetic-retinopathy-resized/resized_train/resized_train/{row['image']}.jpeg\"\n        image = cv2.imread(path)\n        image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)\n\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) , IMG_SIZE/10) ,-4 ,128)\n\n        plt.imshow(image, cmap='gray')\n        ax.set_title('%d-%d-%s' % (class_id, idx, row['image']) )","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Ok preprocessing methods seem to works fine; however, the doctors to estimate the severity levels in the past competitions may have different criteria in mind than the doctors of Aravind, so it is possible to have some estimation inconsistency (at least to my eyes the previous data seems more noisy). The following level-4 [pic(4,1) in the plot we just made above] looks not so severe. (Or this is the example case of too many blood vessels ??, refer to Section 1.1)"},{"metadata":{"trusted":true,"_kg_hide-input":true},"cell_type":"code","source":"dpi = 80 #inch\n\npath=f\"../input/diabetic-retinopathy-resized/resized_train/resized_train/31590_right.jpeg\" # too many vessels?\n# path=f\"../input/diabetic-retinopathy-resized/resized_train/resized_train/18017_left.jpeg\" # details are lost\nimage = load_ben_color(path,sigmaX=30)\n# image = cv2.imread(path)\n# image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)\n# image = crop_image1(image)\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)\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":{},"cell_type":"markdown","source":"## 4.1 Let us compare to the .png image.\n\nSome pictures (e.g. pics (4,5-8)) seem to lost details perhaps this is due to .jpeg compression ? I don't think so, but at least we should try to compare with .png. Fortunately, @donkeys also provides us .png version of the previous competition [see ref. in Introduction]."},{"metadata":{"trusted":true,"_kg_hide-input":true},"cell_type":"code","source":"!ls ../input/retinopathy-train-2015/rescaled_train_896/rescaled_train_896/ | head","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_kg_hide-input":true},"cell_type":"code","source":"dpi = 80 #inch\n\npath_jpg=f\"../input/diabetic-retinopathy-resized/resized_train/resized_train/18017_left.jpeg\" # too many vessels?\npath_png=f\"../input/retinopathy-train-2015/rescaled_train_896/rescaled_train_896/18017_left.png\" # details are lost\nimage = cv2.imread(path_png)\nimage = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)\nimage = crop_image(image)\nimage = cv2.resize(image, (IMG_SIZE, IMG_SIZE))\n\nimage2 =  cv2.imread(path_jpg)\nimage2 = cv2.cvtColor(image2, cv2.COLOR_BGR2RGB)\nimage2 = crop_image(image2)\nimage2 = cv2.resize(image2, (IMG_SIZE, IMG_SIZE))\n\n\nheight, width = IMG_SIZE, IMG_SIZE\nprint(height, width)\n\nSCALE=1/4\nfigsize = (width / float(dpi))/SCALE, (height / float(dpi))/SCALE\n\nfig = plt.figure(figsize=figsize)\nax = fig.add_subplot(2, 2, 1, xticks=[], yticks=[])\nax.set_title('png format original' )\nplt.imshow(image, cmap='gray')\nax = fig.add_subplot(2, 2, 2, xticks=[], yticks=[])\nax.set_title('jpg format original' )\nplt.imshow(image2, cmap='gray')\n\nimage = load_ben_color(path_png,sigmaX=30)\nimage2 = load_ben_color(path_jpg,sigmaX=30)\nax = fig.add_subplot(2, 2, 3, xticks=[], yticks=[])\nax.set_title('png format transformed' )\nplt.imshow(image, cmap='gray')\nax = fig.add_subplot(2, 2, 4, xticks=[], yticks=[])\nax.set_title('jpg format transformed' )\nplt.imshow(image2, cmap='gray')","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"OK, so the details are really not there no matter what image compression method. So this may be one example of (many) noisy data in the previous competition. "},{"metadata":{},"cell_type":"markdown","source":"# Appendix A. Heatmap visualization\n\nIn **[this new kernel](https://www.kaggle.com/ratthachat/aptos-spotting-blindness-real-or-spurious/)**, I show another application of preprocessing method, to visualize (and improve) understanbility of the model. If you are interested in please visit the kernel.\n\n![heatmap](https://i.ibb.co/6FM6VCC/gradcam-resized.png)"},{"metadata":{},"cell_type":"markdown","source":"# Appendix B. Inconsistency of Ophthalmologist's Estimation\n\nBe careful that the nature of this problem is noisy. One Doctor can estimate an eye with severity level 3, but another can say level 1. In fact, some doctor can even say level 5! See evidence below from Tensorflow summit. For more information see https://youtu.be/oOeZ7IgEN4o?t=156 .\n\n![inconsistent  estimation in diabetic retinophaty](https://i.ibb.co/6rQ2sFG/inconsistent-estimation.png)\n\nActually, from this summit, Google stated that they already worked with Aravind and have like 800,000 training data. I am a bit confused about the objective of this competition :) ."},{"metadata":{},"cell_type":"markdown","source":"# Appendix C. Infinite Vision: The Story of Aravind Eye Hospital\n\nI really would love everyone to watch ** [this clip](http://) ** to appreciate the story of Aravind and the this competition! Enjoy.\n\n![Aravind Business Model??](https://i.ibb.co/m4C3xWd/Aravind-Model.png)\n\n"},{"metadata":{},"cell_type":"markdown","source":"That's all for now! Hope this is helpful somehow! "},{"metadata":{"trusted":true},"cell_type":"code","source":"","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"","execution_count":null,"outputs":[]}],"metadata":{"kernelspec":{"display_name":"Python 3","language":"python","name":"python3"},"language_info":{"name":"python","version":"3.6.4","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"}},"nbformat":4,"nbformat_minor":1}