{"metadata":{"kernelspec":{"name":"python3","display_name":"Python 3","language":"python"},"language_info":{"name":"python","version":"3.10.14","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"gpu","dataSources":[{"sourceId":14774,"databundleVersionId":875431,"sourceType":"competition"},{"sourceId":155480,"sourceType":"modelInstanceVersion","isSourceIdPinned":true,"modelInstanceId":132118,"modelId":154919}],"dockerImageVersionId":30786,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"# Detection of Diabetes Retinopathy Stages using Fundus Images\n\n## Dataset : Asia Pacific Tele-Ophthalmology Society (APTOS) 2019\n\n- 3622 samples (2930-732 Train-Validation Split)\n- Reviewed and labeled by a group of trained doctors for the gathered samples, following the principle of the International Clinical Diabetic Retinopathy Disease Severity Scale (ICDRSS)\n\n## Objectives:\n\n**Classify a fundus image into 5 stages/categories of Diabetic Retinopathy *(in the increasing order of severity)* from class 0 to 4**\n\n\n- None\n- Mild (tiny areas of swelling in the blood vessels of the retina, small aneurysm)\n- Moderate (Increased swelling of tiny blood vessels)\n- Severe (A larger section of blood vessels in the retina become blocked)\n- Proliferate (new blood vessels form in the retina, increasing risk of fluid leakage; blurriness, reduced field of vision and blindness)\n\n## Programming Language Opted: Python (NVIDIA P100 GPU Accelerator)\n\n## Classes (derived using Gaussian Blur and Circular Crop for demonstration purposes)\n![Classes](https://github.com/Polymath-Saksh/Amrita_Lab/blob/c574126cb9f0b5524a6e53d166d3e4c9e2f26a40/MIP/Diabetic-Retin.png?raw=true)","metadata":{}},{"cell_type":"code","source":"import cv2\nimport numpy as np\nimport matplotlib.pyplot as plt\nimport pandas as pd\n\nimport tensorflow as tf\nimport keras\nfrom tensorflow.keras.preprocessing.image import ImageDataGenerator\nfrom tensorflow.keras.applications.resnet50 import preprocess_input","metadata":{"execution":{"iopub.status.busy":"2024-11-02T16:15:48.759560Z","iopub.execute_input":"2024-11-02T16:15:48.759889Z","iopub.status.idle":"2024-11-02T16:15:48.764369Z","shell.execute_reply.started":"2024-11-02T16:15:48.759862Z","shell.execute_reply":"2024-11-02T16:15:48.763622Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"IMG_SIZE = 224\nBATCH_SIZE = 32","metadata":{"execution":{"iopub.status.busy":"2024-11-02T16:15:51.315205Z","iopub.execute_input":"2024-11-02T16:15:51.315900Z","iopub.status.idle":"2024-11-02T16:15:51.319226Z","shell.execute_reply.started":"2024-11-02T16:15:51.315866Z","shell.execute_reply":"2024-11-02T16:15:51.318489Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Image Preprocessor\n\n- Read the image\n- RGB Conversion, followed by resizing","metadata":{}},{"cell_type":"code","source":"def preprocessor(path, img_size=224):\n\n    img = cv2.imread(path)\n    img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)\n    img = cv2.resize(img, (img_size, img_size))\n    \n    # Gaussian Blur\n    img = cv2.GaussianBlur(img, (5, 5), 0)\n    img = cv2.addWeighted(img, 4, cv2.GaussianBlur(img, (0, 0), img_size / 30), -4, 128)\n    \n    # Contrast enhancement \n    lab = cv2.cvtColor(img, cv2.COLOR_RGB2LAB)\n    lab[...,0] = cv2.equalizeHist(lab[...,0])\n    img = cv2.cvtColor(lab, cv2.COLOR_LAB2RGB)\n    \n    # Center crop\n    center_crop = img_size // 2\n    crop_size = int(center_crop * 0.95)\n    img = img[center_crop - crop_size:center_crop + crop_size, center_crop - crop_size:center_crop + crop_size]\n    \n    img = cv2.resize(img, (img_size, img_size))\n    img = img / 255.0\n    \n    return img\n","metadata":{"execution":{"iopub.status.busy":"2024-11-02T16:15:56.740738Z","iopub.execute_input":"2024-11-02T16:15:56.741079Z","iopub.status.idle":"2024-11-02T16:15:56.747167Z","shell.execute_reply.started":"2024-11-02T16:15:56.741050Z","shell.execute_reply":"2024-11-02T16:15:56.746312Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def main_preprocessor(path):\n    img = preprocessor(path)\n    img = preprocess_input(img)\n    return img\n\nclass CustomImageDataGenerator(ImageDataGenerator):\n    def flow_from_dataframe(self, dataframe, directory, *args, **kwargs):\n        # Get the original generator\n        generator = super().flow_from_dataframe(\n            dataframe, \n            directory, \n            *args, \n            **kwargs\n        )\n\n        # Custom getitem method\n        def custom_getitem(instance, index):\n            batch_x, batch_y = instance._get_batches_of_transformed_samples(index)\n            \n            for i, path in enumerate(instance.filenames[index * instance.batch_size:(index + 1) * instance.batch_size]):\n                img_path = f\"{directory}/{path}\"\n                batch_x[i] = main_preprocessor(img_path)\n                \n            return batch_x, batch_y\n\n        # Replace the generator's __getitem__ with custom_getitem\n        generator.__getitem__ = custom_getitem.__get__(generator, generator.__class__)\n        \n        return generator\n","metadata":{"execution":{"iopub.status.busy":"2024-11-02T16:19:42.658642Z","iopub.execute_input":"2024-11-02T16:19:42.659026Z","iopub.status.idle":"2024-11-02T16:19:42.665537Z","shell.execute_reply.started":"2024-11-02T16:19:42.658999Z","shell.execute_reply":"2024-11-02T16:19:42.664868Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"datagen = CustomImageDataGenerator(\n        validation_split = 0.25,\n        rescale = 1./255)\n\ntrain_gen = datagen.flow_from_dataframe(\n    dataframe=train_df,\n    directory='/kaggle/input/aptos2019-blindness-detection/train_images',\n    x_col='id_code',\n    y_col='diagnosis',\n    target_size=(IMG_SIZE, IMG_SIZE),\n    batch_size=BATCH_SIZE,\n    class_mode='raw',\n    subset='training'\n)\n\nval_gen = datagen.flow_from_dataframe(\n    dataframe=train_df,\n    directory='/kaggle/input/aptos2019-blindness-detection/train_images',\n    x_col='id_code',\n    y_col='diagnosis',\n    target_size=(IMG_SIZE, IMG_SIZE),\n    batch_size=BATCH_SIZE,\n    class_mode='raw',\n    subset='validation'\n)","metadata":{"execution":{"iopub.status.busy":"2024-11-02T16:16:00.239262Z","iopub.execute_input":"2024-11-02T16:16:00.239589Z","iopub.status.idle":"2024-11-02T16:16:02.636700Z","shell.execute_reply.started":"2024-11-02T16:16:00.239562Z","shell.execute_reply":"2024-11-02T16:16:02.635802Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Check a batch to verify\nsample_batch = next(train_gen)\nprint(\"Sample batch shape:\", sample_batch[0].shape)  # Should match (BATCH_SIZE, IMG_SIZE, IMG_SIZE, 3)\nprint(\"Sample labels:\", sample_batch[1])  # Check labels for accuracy\n","metadata":{"execution":{"iopub.status.busy":"2024-11-02T16:20:11.029639Z","iopub.execute_input":"2024-11-02T16:20:11.030015Z","iopub.status.idle":"2024-11-02T16:20:14.864119Z","shell.execute_reply.started":"2024-11-02T16:20:11.029985Z","shell.execute_reply":"2024-11-02T16:20:14.863292Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from tensorflow.keras.applications import ResNet50\nfrom tensorflow.keras.models import Model\nfrom tensorflow.keras.layers import Dense, GlobalAveragePooling2D\n\n# Load the pre-trained ResNet50 model without the top classification layers\nbase_model = ResNet50(weights='imagenet', include_top=False, input_shape=(IMG_SIZE, IMG_SIZE, 3))\n\nx = base_model.output\nx = GlobalAveragePooling2D()(x)\nx = Dense(1024, activation='relu')(x)\npredictions = Dense(1, activation='linear')(x)  # Use a linear output for regression (ordinal task)\n\nmodel = Model(inputs=base_model.input, outputs=predictions)\n\nfor layer in base_model.layers:\n    layer.trainable = False\n\nmodel.compile(optimizer='adam', loss='mean_squared_error', metrics=['mae'])\n\n\nmodel.summary()","metadata":{"_kg_hide-output":true,"execution":{"iopub.status.busy":"2024-11-02T16:20:25.629372Z","iopub.execute_input":"2024-11-02T16:20:25.629714Z","iopub.status.idle":"2024-11-02T16:20:26.800267Z","shell.execute_reply.started":"2024-11-02T16:20:25.629685Z","shell.execute_reply":"2024-11-02T16:20:26.799546Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import os\n\ntrain_dir = \"/kaggle/input/aptos2019-blindness-detection/train_images\"\nval_dir = \"/kaggle/input/aptos2019-blindness-detection/test_images\"\n\n# Check if the directories exist\nprint(f\"Train directory exists: {os.path.exists(train_dir)}\")\nprint(f\"Validation directory exists: {os.path.exists(val_dir)}\")\n","metadata":{"execution":{"iopub.status.busy":"2024-11-02T16:16:31.766068Z","iopub.execute_input":"2024-11-02T16:16:31.766871Z","iopub.status.idle":"2024-11-02T16:16:31.784230Z","shell.execute_reply.started":"2024-11-02T16:16:31.766839Z","shell.execute_reply":"2024-11-02T16:16:31.783418Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Train the model\nhistory = model.fit(\n    train_gen,\n    validation_data=val_gen,\n    epochs=5,  # Start with 5 epochs and see how it performs\n    verbose=1\n)","metadata":{"execution":{"iopub.status.busy":"2024-11-02T16:20:35.776034Z","iopub.execute_input":"2024-11-02T16:20:35.776418Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# # Save the model as an HDF5 file\n# model.save('blindness_detection_model.h5')","metadata":{"execution":{"iopub.status.busy":"2024-10-22T18:30:33.944264Z","iopub.execute_input":"2024-10-22T18:30:33.944626Z","iopub.status.idle":"2024-10-22T18:30:34.414604Z","shell.execute_reply.started":"2024-10-22T18:30:33.944590Z","shell.execute_reply":"2024-10-22T18:30:34.413587Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# model.save('saved_model/blindness_detection_model')","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# from tensorflow.keras.callbacks import ModelCheckpoint\n\n# # Create a callback to save the best model during training\n# checkpoint = ModelCheckpoint('best_model.keras', monitor='val_loss', save_best_only=True, mode='min', verbose=1)\n\n# # Pass this callback to model.fit()\n# history = model.fit(\n#     train_gen,\n#     validation_data=val_gen,\n#     epochs=5,\n#     callbacks=[checkpoint]\n# )","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Load a saved model","metadata":{}},{"cell_type":"code","source":"# from tensorflow.keras.models import load_model\n\n# model = load_model('/kaggle/input/blindness-detect-dr/keras/default/1/blindness_detection_model.keras')\n\n# # If using TensorFlow SavedModel format\n# # model = load_model('saved_model/blindness_detection_model')","metadata":{"execution":{"iopub.status.busy":"2024-11-04T03:59:38.652584Z","iopub.execute_input":"2024-11-04T03:59:38.653010Z","iopub.status.idle":"2024-11-04T04:00:06.479504Z","shell.execute_reply.started":"2024-11-04T03:59:38.652971Z","shell.execute_reply":"2024-11-04T04:00:06.478706Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Input Preprocess","metadata":{}},{"cell_type":"code","source":"# import cv2\n# import numpy as np\n\n# def preprocess_image(image_path, img_size=224):\n#     img = cv2.imread(image_path)\n#     img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)\n    \n#     # Fundus detection and cropping \n#     gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)\n#     _, thresh = cv2.threshold(gray, 10, 255, cv2.THRESH_BINARY)\n#     contours, _ = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)\n#     if len(contours) > 0:\n#         contour = max(contours, key=cv2.contourArea)\n#         x, y, w, h = cv2.boundingRect(contour)\n#         img = img[y:y+h, x:x+w]\n\n#     height, width, _ = img.shape\n#     if height > width:\n#         pad_width = (height - width) // 2\n#         img = cv2.copyMakeBorder(img, 0, 0, pad_width, pad_width, cv2.BORDER_CONSTANT, value=[0, 0, 0])\n#     elif width > height:\n#         pad_height = (width - height) // 2\n#         img = cv2.copyMakeBorder(img, pad_height, pad_height, 0, 0, cv2.BORDER_CONSTANT, value=[0, 0, 0])\n\n#     img = cv2.resize(img, (img_size, img_size))\n#     img = cv2.GaussianBlur(img, (5, 5), 0)\n#     img = cv2.addWeighted(img, 4, cv2.GaussianBlur(img, (0, 0), img_size / 30), -4, 128)\n    \n#     # Normalize the image as per the original training setup\n#     img = img / 255.0\n    \n#     return np.expand_dims(img, axis=0)  # Add batch dimension\n","metadata":{"execution":{"iopub.status.busy":"2024-11-04T04:00:06.842676Z","iopub.execute_input":"2024-11-04T04:00:06.842981Z","iopub.status.idle":"2024-11-04T04:00:06.853348Z","shell.execute_reply.started":"2024-11-04T04:00:06.842949Z","shell.execute_reply":"2024-11-04T04:00:06.852367Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# # Path to the new image you want to predict\n# image_path = '/kaggle/input/aptos2019-blindness-detection/test_images/003f0afdcd15.png'\n\n# # Preprocess the image\n# processed_image = preprocess_image(image_path)\n\n# # Predict\n# prediction = model.predict(processed_image)\n\n# # Interpret the result\n# print(\"Prediction:\", prediction)\n","metadata":{"execution":{"iopub.status.busy":"2024-11-04T04:00:09.295285Z","iopub.execute_input":"2024-11-04T04:00:09.296046Z","iopub.status.idle":"2024-11-04T04:00:14.810217Z","shell.execute_reply.started":"2024-11-04T04:00:09.296004Z","shell.execute_reply":"2024-11-04T04:00:14.809239Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# predicted_class = np.argmax(prediction, axis=1)[0]\n# predicted_class = int(round(prediction[0][0]))\n\n# print(\"Predicted class:\", predicted_class)","metadata":{"execution":{"iopub.status.busy":"2024-11-04T04:00:18.096437Z","iopub.execute_input":"2024-11-04T04:00:18.097347Z","iopub.status.idle":"2024-11-04T04:00:18.104149Z","shell.execute_reply.started":"2024-11-04T04:00:18.097305Z","shell.execute_reply":"2024-11-04T04:00:18.103251Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# import pandas as pd\n# import os\n\n# # Load the CSV file\n# test_df = pd.read_csv('/kaggle/input/aptos2019-blindness-detection/test.csv')\n\n# # Directory containing the training images\n# test_image_dir = '/kaggle/input/aptos2019-blindness-detection/test_images'\n","metadata":{"execution":{"iopub.status.busy":"2024-11-04T04:01:26.727805Z","iopub.execute_input":"2024-11-04T04:01:26.728173Z","iopub.status.idle":"2024-11-04T04:01:26.745257Z","shell.execute_reply.started":"2024-11-04T04:01:26.728142Z","shell.execute_reply":"2024-11-04T04:01:26.744504Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# import os\n# import matplotlib.pyplot as plt\n# import tensorflow as tf\n# total_predictions = len(test_df)\n\n# #Subplots\n# rows, cols = 2,5\n# fig, axes = plt.subplots(rows, cols, figsize=(10, 10)) \n# fig.suptitle(\"Predicted Classes of Test Images\", fontsize=16)\n\n# axes = axes.flatten()\n\n# for i, (index, row) in enumerate(test_df[:10].iterrows()):\n#     image_id = row['id_code']\n    \n#     # Path to the image file\n#     image_path = os.path.join(test_image_dir, f\"{image_id}.png\")  # or .jpg based on your dataset\n\n#     processed_image = preprocess_image(image_path)\n#     prediction = model.predict(processed_image)\n#     continuous_prediction = prediction[0][0]\n#     predicted_class = int(round(continuous_prediction))\n#     predicted_class = max(0, min(predicted_class, 4))  # Ensure it's in the range [0, 4]\n    \n#     # Load the image for display\n#     image = plt.imread(image_path)\n#     ax = axes[i]\n#     ax.imshow(image)\n#     ax.axis('off')\n#     ax.set_title(f'Class: {predicted_class}')    \n\n# plt.tight_layout(rect=[0, 0, 1, 0.96])\n# plt.show()","metadata":{"_kg_hide-output":true,"execution":{"iopub.status.busy":"2024-11-04T04:11:10.129826Z","iopub.execute_input":"2024-11-04T04:11:10.130652Z","iopub.status.idle":"2024-11-04T04:11:13.348682Z","shell.execute_reply.started":"2024-11-04T04:11:10.130601Z","shell.execute_reply":"2024-11-04T04:11:13.347723Z"},"trusted":true},"execution_count":null,"outputs":[]}]}