{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"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":"nvidiaTeslaT4","dataSources":[{"sourceId":14774,"databundleVersionId":875431,"sourceType":"competition"},{"sourceId":9051307,"sourceType":"datasetVersion","datasetId":5457392},{"sourceId":178905,"sourceType":"modelInstanceVersion","isSourceIdPinned":true,"modelInstanceId":152402,"modelId":174858},{"sourceId":179584,"sourceType":"modelInstanceVersion","isSourceIdPinned":true,"modelInstanceId":153013,"modelId":175466},{"sourceId":180400,"sourceType":"modelInstanceVersion","isSourceIdPinned":true,"modelInstanceId":153722,"modelId":176193}],"dockerImageVersionId":30761,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"train_dir = \"/kaggle/input/aptos2019-blindness-detection/train_images\"\ndf_path = \"/kaggle/input/aptos2019-blindness-detection/train.csv\"\n\nimg_width, img_height, num_chans = target_size = (512, 512, 3)","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import pandas as pd\n\ndf = pd.read_csv(df_path)\ndf[\"id_code\"] = list(map(lambda x: f\"{train_dir}/{x}.png\", df[\"id_code\"]))\ndf[\"diagnosis\"] = list(map(str, df[\"diagnosis\"]))\n\ndr_df = df[df[\"diagnosis\"] != \"0\"]","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"dr_df","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import cv2\nimport numpy as np\nimport tensorflow as tf","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def show_image(image, title=\"Image\"):\n    # Convert the image from BGR (OpenCV default) to RGB for correct color display\n    image_rgb = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)\n    \n    # Display the image using matplotlib\n    plt.figure(figsize=(6, 6))\n    plt.imshow(image_rgb)\n    plt.title(title)\n    plt.axis('off')  # Hide axis\n    plt.show()","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def resize_image(image):\n    return cv2.resize(image, (img_width, img_height))","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def crop_image(image):\n    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)\n    \n    gray = np.uint8(gray)\n    \n    blurred = cv2.GaussianBlur(gray, (5, 5), 0)\n    \n    _, thresh = cv2.threshold(blurred, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)\n    \n    contours, _ = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)\n    \n    largest_contour = max(contours, key=cv2.contourArea)\n    \n    mask = np.zeros_like(gray)\n    cv2.drawContours(mask, [largest_contour], -1, 255, thickness=cv2.FILLED)\n    \n    result = cv2.bitwise_and(image, image, mask=mask)\n    \n    x, y, w, h = cv2.boundingRect(largest_contour)\n    cropped = result[y:y+h, x:x+w]\n    \n    return cropped","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def clahe_image(image):\n    image = np.uint8(image)\n    \n    lab = cv2.cvtColor(image, cv2.COLOR_BGR2LAB)\n    \n    lab_planes = list(cv2.split(lab))  # Convert tuple to list\n    \n    clahe = cv2.createCLAHE(clipLimit=7.0, tileGridSize=(8, 8))\n    \n    lab_planes[0] = clahe.apply(lab_planes[0])\n    \n    lab = cv2.merge(lab_planes)\n    \n    clahe_image = cv2.cvtColor(lab, cv2.COLOR_LAB2BGR)\n    \n    med_blur = cv2.medianBlur(clahe_image, ksize=3)\n    \n    # Mask for bleeding vein\n    back_ground = cv2.medianBlur(clahe_image, ksize=35)\n    mask = cv2.addWeighted(med_blur, 1, back_ground, -1, 255)\n    final_image = cv2.bitwise_and(mask, med_blur)\n    \n    return final_image","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def morphological_image(image):\n    # Convert image to grayscale\n    gray = image[0]\n\n    # Thresholding to segment pectoral muscles\n    _, binary = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)\n\n    # Apply morphological operations to enhance segmentation\n    kernel = np.ones((3, 3), np.uint8)\n    morphed = cv2.morphologyEx(binary, cv2.MORPH_CLOSE, kernel, iterations=1)\n\n    # Find contours of segmented pectoral muscles\n    contours, _ = cv2.findContours(morphed, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)\n\n    # Draw contours on original image to highlight pectoral muscles\n    highlighted_image = cv2.drawContours(image.copy(), contours, -1, (0, 255, 0), thickness=1)\n\n    return highlighted_image","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def segment(image):\n    if image is None:\n        return None\n\n    # Convert the image to grayscale\n    gray = image[0]\n\n    # Apply Gaussian Blur for noise reduction\n    blurred = cv2.GaussianBlur(gray, (5, 5), 0)\n\n    # Perform edge detection using Canny\n    edges = cv2.Canny(blurred, 3, 5)\n\n    # Find contours in the edge-detected image\n    contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)\n\n    # Create a mask to store the segmented region\n    mask = np.zeros_like(gray)\n\n    # Draw contours on the mask\n    cv2.drawContours(mask, contours, -1, (255, 255, 255), thickness=cv2.FILLED)\n\n    # Apply the mask to the original image\n    segmented_img = cv2.bitwise_and(image, image, mask=mask)\n\n    return segmented_img","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def to_grayscale_then_rgb(image):\n    image = tf.image.rgb_to_grayscale(image)\n    image = tf.image.grayscale_to_rgb(image)\n    return image","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def preprocess_image(image):\n    \n    image = crop_image(image)\n\n    image = resize_image(image)\n    \n    image = clahe_image(image)\n    \n    image = image * 1.0\n    \n    return image","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from tensorflow.keras.preprocessing.image import ImageDataGenerator\n\ndatagen = ImageDataGenerator(\n    rescale=1./255,\n    rotation_range=10,\n    width_shift_range=0.2,\n    height_shift_range=0.2,\n    shear_range=0.1,\n    zoom_range=0.3,\n    horizontal_flip=True,\n    vertical_flip=False,\n    fill_mode='constant',\n    preprocessing_function=preprocess_image,\n    validation_split=0.2,\n)\n\nmulti_train_gen = datagen.flow_from_dataframe(\n    dr_df,\n    target_size=(img_width, img_height),\n    x_col=\"id_code\",\n    y_col=\"diagnosis\",\n    subset=\"training\",\n    class_mode=\"categorical\",\n    \n)\n\nmulti_val_gen = datagen.flow_from_dataframe(\n    dr_df,\n    target_size=(img_width, img_height),\n    x_col=\"id_code\",\n    y_col=\"diagnosis\",\n    subset=\"validation\",\n    class_mode=\"categorical\",\n)","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import matplotlib.pyplot as plt\n\ndef plot_images(num_images=4):\n    images, labels = next(multi_train_gen)\n    print(labels)\n    class_names = np.array([\"Mild\", \"Moderate\", \"Severe\", \"Proliferative DR\"])\n    plt.figure(figsize=(10, 10))\n    for i in range(num_images):\n        ax = plt.subplot(2, 2, i + 1)\n        plt.imshow(images[i])\n        title = class_names[np.where(labels[i] == 1)]\n        plt.title(title)\n        plt.axis(\"off\")\n    plt.show()","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"plot_images()","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from sklearn.utils.class_weight import compute_class_weight\nimport numpy as np\n\nclasses = multi_train_gen.classes\nclass_weights = compute_class_weight(class_weight='balanced', classes=np.unique(classes), y=classes)\nclass_weights_dict = dict(enumerate(class_weights))\nclass_weights_dict","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import tensorflow as tf\nfrom tensorflow.keras.applications.inception_v3 import InceptionV3\nfrom tensorflow.keras.applications.resnet_v2 import ResNet50V2 as ResNet50\nfrom tensorflow.keras.applications.vgg19 import VGG19\nfrom tensorflow.keras.layers import Dense, Input, Concatenate, Reshape, Layer, Conv2D, multiply, Flatten, Dropout, MaxPool2D, UpSampling2D,\\\n                                    BatchNormalization, Activation, AvgPool2D, MaxPool1D, AvgPool1D, GlobalAveragePooling2D\nfrom tensorflow.keras import Model\nfrom tensorflow.keras.models import Sequential\nfrom tensorflow.keras.callbacks import EarlyStopping, ModelCheckpoint\nimport numpy as np","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"class CAM(Layer):\n    def __init__(self, in_channels, reduction_ratio=16, **kwargs):\n        super(CAM, self).__init__(**kwargs)\n\n        reduced_channels_num = (in_channels // reduction_ratio) if in_channels > reduction_ratio else 1\n        pointwise_in = Conv2D(filters=reduced_channels_num,\n                              kernel_size=(1, 1))\n        pointwise_out = Conv2D(filters=in_channels,\n                               kernel_size=(1, 1))\n\n        self.MLP = Sequential([\n            pointwise_in,\n            Activation('relu'),\n            pointwise_out,\n        ])\n\n    def call(self, x):\n        h, w = x.shape[1:3]\n\n        max_feat = MaxPool2D(pool_size=(h, w), strides=(h, w))(x)\n\n        avg_feat = AvgPool2D(pool_size=(h, w), strides=(h, w))(x)\n\n        max_feat_mlp = self.MLP(max_feat)\n        avg_feat_mlp = self.MLP(avg_feat)\n\n        channel_attention_map = Activation('sigmoid')(max_feat_mlp + avg_feat_mlp)\n\n        return channel_attention_map\n\n\nclass SAM(Layer):\n    def __init__(self, ks=7, **kwargs):\n        super(SAM, self).__init__(**kwargs)\n\n        self.ks = ks\n        self.sigmoid = Activation('sigmoid')\n        self.conv = Conv2D(kernel_size=self.ks,\n                           filters=1,\n                           padding=\"same\")\n\n    def call(self, x):\n        b, h, w, c = x.shape\n\n        reshaped = tf.reshape(x, (-1, h * w, c))\n        permuted = tf.transpose(reshaped, perm=[0, 2, 1])\n\n        max_feat = MaxPool1D(pool_size=c, strides=c)(permuted)\n        max_feat = tf.transpose(max_feat, perm=[0, 1, 2])\n        max_feat = tf.reshape(max_feat, (-1, h, w, 1))\n\n        avg_feat = AvgPool1D(pool_size=c, strides=c)(permuted)\n        avg_feat = tf.transpose(avg_feat, perm=[0, 1, 2])\n        avg_feat = tf.reshape(avg_feat, (-1, h, w, 1))\n\n        concatenated = tf.concat([max_feat, avg_feat], axis=-1)\n    \n        spatial_attention_map = Activation(\"sigmoid\")(self.conv(concatenated))\n        return spatial_attention_map\n\nclass CBAM(Layer):\n    def __init__(self, in_channels):\n        super().__init__()\n        self.CAM = CAM(in_channels)\n        self.SAM = SAM()\n\n    def call(self, x):\n        channel_attention_map = self.CAM(x)\n        gated_tensor = tf.multiply(x, channel_attention_map)\n        spatial_attention_map = self.SAM(gated_tensor)\n\n        refined_tensor = tf.multiply(gated_tensor, spatial_attention_map)\n\n        return refined_tensor","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def InceptionAttention(class_mode, num_classes=1):\n    input_layer = Input(shape=target_size)\n\n    base_model = InceptionV3(weights=\"imagenet\", include_top=False)\n    base_model.trainable = False\n\n    base_features = base_model(input_layer)\n    chans = base_features.shape[-1]\n\n    x = CBAM(chans)(base_features)\n    x = Concatenate()([x, base_features])\n    x = Conv2D(512, 3, padding=\"same\", activation=\"relu\")(x)\n    x = GlobalAveragePooling2D()(x)\n    x = Dense(1024, activation='relu')(x)\n    x = Dropout(0.5)(x)\n\n    if class_mode == \"binary\":\n        x = Dense(2, activation=\"softmax\")(x)\n    elif class_mode == \"categorical\":\n        if num_classes == 1:\n            raise ValueError(\"Invalid num_classes. num_classes should be > 1\")\n        x = Dense(512, activation=\"relu\")(x)\n        x = Dense(num_classes, activation=\"softmax\")(x)\n    else:\n        raise ValueError(\"Invalid class_mode. Choose 'binary' or 'categorical'.\")\n\n    model = Model(inputs=input_layer, outputs=x)\n    return model","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"model = InceptionAttention(class_mode=\"categorical\", num_classes=4)\nmodel.compile(optimizer=\"adam\", loss=\"categorical_crossentropy\", metrics=[\"accuracy\", \"precision\", \"recall\", \"f1_score\"])\nmodel.load_weights(\"/kaggle/input/dr3/keras/default/1/best_inception_model (1).keras\")","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"early_stopping = EarlyStopping(monitor='val_loss', patience=25, restore_best_weights=True)\nmodel_checkpoint = ModelCheckpoint('best_inception_model.keras', monitor='accuracy', save_best_only=True)","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"history = model.fit(\n    multi_train_gen,\n    epochs=100,\n    callbacks=[early_stopping, model_checkpoint],\n    class_weight=class_weights_dict\n)","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import matplotlib.pyplot as plt\n\ntrain_acc = history.history['accuracy']\nval_acc = history.history['val_accuracy']\n\ntrain_precision = history.history['precision']\nval_precision = history.history['val_precision']\n\ntrain_recall = history.history['recall']\nval_recall = history.history['val_recall']\n\ntrain_f1 = history.history['f1_score']\nval_f1 = history.history['val_f1_score']\n\n# Number of epochs\nepochs = range(1, len(train_acc) + 1)\n\n# Plot accuracy\nplt.plot(epochs, train_acc, 'bo', label='Training Accuracy')\nplt.plot(epochs, val_acc, 'b-', label='Validation Accuracy')\nplt.title('Training and Validation Accuracy')\nplt.xlabel('Epochs')\nplt.ylabel('Accuracy')\nplt.legend()\nplt.show()\n\n# Plot precision (assuming single class)\nplt.plot(epochs, train_precision, 'go', label='Training Precision')\nplt.plot(epochs, val_precision, 'g-', label='Validation Precision')\nplt.title('Training and Validation Precision')\nplt.xlabel('Epochs')\nplt.ylabel('Precision')\nplt.legend()\nplt.show()\n\n# Plot recall (assuming single class)\nplt.plot(epochs, train_recall, 'ro', label='Training Recall')\nplt.plot(epochs, val_recall, 'r-', label='Validation Recall')\nplt.title('Training and Validation Recall')\nplt.xlabel('Epochs')\nplt.ylabel('Recall')\nplt.legend()\nplt.show()\n\n# Plot F1-score (assuming single class)\nplt.plot(epochs, train_f1, 'ko', label='Training F1-Score')\nplt.plot(epochs, val_f1, 'k-', label='Validation F1-Score')\nplt.title('Training and Validation F1-Score')\nplt.xlabel('Epochs')\nplt.ylabel('F1-Score')\nplt.legend()\nplt.show()","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null}]}