{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.7.6","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"gpu","dataSources":[{"sourceId":18647,"databundleVersionId":1126921,"sourceType":"competition"}],"dockerImageVersionId":29926,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"###  Analyse d'Images pour le Grade de Cancer de la Prostate\n\n#### Table des Matières\n\n1. [Introduction](#introduction)\n2. [Imports](#imports)\n3. [Chargement des Données](#chargement-des-donnees)\n4. [Fonctions de Traitement d'Images](#fonctions-de-traitement-d-images)\n    - [compute_statistics](#compute_statistics)\n    - [select_k_best_regions](#select_k_best_regions)\n    - [get_k_best_regions](#get_k_best_regions)\n    - [generate_patches](#generate_patches)\n5. [Affichage d'Images](#affichage-d-images)\n    - [display_images](#display_images)\n6. [Tableau Indicatif pour le Grade de Cancer](#tableau-indicatif-pour-le-grade-de-cancer)\n7. [Mapping des Couleurs](#mapping-des-couleurs)\n8. [Affichage du Tableau Indicatif](#affichage-du-tableau-indicatif)\n9. [Entrée de l'Utilisateur](#entree-de-l-utilisateur)\n10. [Vérification de l'ID de l'Image](#verification-de-l-id-de-l-image)\n11. [Affichage de l'Image et du Masque](#affichage-de-l-image-et-du-masque)\n12. [Gestion des Cas d'Erreur](#gestion-des-cas-d-erreur)\n\n### Introduction\n\nCe code a pour objectif d'analyser des images de biopsies de la prostate afin de déterminer le grade de cancer associé. Il comprend des fonctions pour traiter les images, extraire des statistiques pertinentes, sélectionner les meilleures régions d'intérêt, et afficher ces informations de manière visuelle.\n\n### Imports\n\nLes bibliothèques nécessaires pour la manipulation des données, le traitement d'images, la visualisation, et la gestion des fichiers sont importées au début du script. \n\n### Chargement des Données\n\nLes données des images et leurs grades de cancer associés sont chargées à partir d'un fichier CSV (`train.csv`) et le répertoire contenant les images est spécifié.\n\n### Fonctions de Traitement d'Images\n\n#### compute_statistics\n\nCette fonction calcule le ratio de pixels blancs et les concentrations moyennes de pixels verts et bleus dans une image donnée. Ces statistiques sont utiles pour identifier les régions d'intérêt dans les images.\n\n#### select_k_best_regions\n\nCette fonction sélectionne les `k` meilleures régions d'une image en se basant sur le plus faible ratio de pixels blancs. Cela permet de se concentrer sur les régions les plus pertinentes de l'image.\n\n#### get_k_best_regions\n\nCette fonction récupère les meilleures régions d'intérêt à partir de leurs coordonnées dans l'image originale. Ces régions sont ensuite utilisées pour une analyse plus détaillée.\n\n#### generate_patches\n\nCette fonction génère des patches (segments) à partir d'une image en fonction d'une taille de fenêtre et d'un stride (pas). Elle sélectionne ensuite les `k` meilleures régions basées sur les statistiques calculées. Cette approche permet de diviser les images en segments plus petits pour une analyse plus fine.\n\n### Affichage d'Images\n\n#### display_images\n\nCette fonction affiche une grille de régions d'images avec un titre. Elle est utilisée pour visualiser les meilleures régions sélectionnées dans une image.\n\n### Tableau Indicatif pour le Grade de Cancer\n\nUn dictionnaire est défini pour associer les grades ISUP (International Society of Urological Pathology) aux types de cancer. Ce tableau permet de comprendre les différents niveaux de gravité du cancer en fonction des grades.\n\n### Mapping des Couleurs\n\nUn autre dictionnaire est utilisé pour associer les grades ISUP à des couleurs spécifiques, facilitant ainsi la visualisation et la différenciation des grades de cancer.\n\n### Affichage du Tableau Indicatif\n\nLe tableau indicatif pour le grade de cancer est affiché sous forme de DataFrame Pandas, ce qui permet de le visualiser facilement et de le comprendre.\n\n### Entrée de l'Utilisateur\n\nL'utilisateur est invité à entrer l'ID d'une image pour afficher son grade de cancer associé. Cela permet d'analyser des images spécifiques et de voir leurs grades de cancer.\n\n### Vérification de l'ID de l'Image\n\nL'ID de l'image entré par l'utilisateur est vérifié pour s'assurer qu'il est valide et présent dans les données chargées. Si l'ID est valide, le grade ISUP et le type de cancer correspondant sont affichés.\n\n### Affichage de l'Image et du Masque\n\nL'image et son masque (s'il est disponible) sont affichés. Cela permet de visualiser l'image de la biopsie ainsi que les régions annotées par des experts médicaux.\n\n### Gestion des Cas d'Erreur\n\nSi l'ID de l'image n'est pas valide, un message d'erreur est affiché. Cela assure une meilleure expérience utilisateur en gérant les entrées incorrectes de manière appropriée.\n\n---\n\nCe code permet de charger les données d'un fichier CSV, de traiter les images associées pour extraire des statistiques, de sélectionner et afficher les meilleures régions des images, et de visualiser des images et leurs masques associés. Il permet également d'afficher un tableau indicatif pour le grade de cancer en fonction de l'ID de l'image entré par l'utilisateur.","metadata":{}},{"cell_type":"markdown","source":"## Importing dependencies","metadata":{}},{"cell_type":"code","source":"import os\nimport random\nimport skimage.io\nimport numpy as np\nimport pandas as pd\nimport matplotlib.pyplot as plt\nfrom tqdm.auto import tqdm\nimport time\n\n# Charger les données du train.csv\ntrain_df = pd.read_csv('../input/prostate-cancer-grade-assessment/train.csv')\ndata_dir = '../input/prostate-cancer-grade-assessment/train_images/'\n\ndef compute_statistics(image):\n    \"\"\"\n    Args:\n        image (numpy.array): Multi-dimensional array of the form WxHxC\n    \n    Returns:\n        ratio_white_pixels (float): Ratio of white pixels over total pixels in the image.\n        green_concentration (float): Mean concentration of green pixels.\n        blue_concentration (float): Mean concentration of blue pixels.\n    \"\"\"\n    width, height = image.shape[0], image.shape[1]\n    num_pixels = width * height\n    \n    summed_matrix = np.sum(image, axis=-1)\n    num_white_pixels = np.count_nonzero(summed_matrix > 620)  # Note: A 3-channel white pixel has RGB (255, 255, 255)\n    ratio_white_pixels = num_white_pixels / num_pixels\n    \n    green_concentration = np.mean(image[:, :, 1])\n    blue_concentration = np.mean(image[:, :, 2])\n    \n    return ratio_white_pixels, green_concentration, blue_concentration\n\ndef select_k_best_regions(regions, k=20):\n    \"\"\"\n    Args:\n        regions (list): List of 2-component tuples, first component the region, \n                        second component the ratio of white pixels.\n        k (int): Number of regions to select.\n    \n    Returns:\n        list: k best regions based on the lowest ratio of white pixels.\n    \"\"\"\n    regions = [x for x in regions if x[3] > 180 and x[4] > 180]\n    k_best_regions = sorted(regions, key=lambda tup: tup[2])[:k]\n    return k_best_regions\n\ndef get_k_best_regions(coordinates, image, window_size=512):\n    regions = {}\n    for i, tup in enumerate(coordinates):\n        x, y = tup[0], tup[1]\n        regions[i] = image[x : x + window_size, y : y + window_size, :]\n    return regions\n\ndef generate_patches(slide_path, window_size=200, stride=128, k=20):\n    image = skimage.io.MultiImage(slide_path)[-2]\n    image = np.array(image)\n    \n    max_width, max_height = image.shape[0], image.shape[1]\n    regions_container = []\n    \n    i = 0\n    while window_size + stride * i <= max_height:\n        j = 0\n        while window_size + stride * j <= max_width:\n            x_top_left_pixel = j * stride\n            y_top_left_pixel = i * stride\n            \n            patch = image[x_top_left_pixel : x_top_left_pixel + window_size,\n                          y_top_left_pixel : y_top_left_pixel + window_size, :]\n            \n            ratio_white_pixels, green_concentration, blue_concentration = compute_statistics(patch)\n            region_tuple = (x_top_left_pixel, y_top_left_pixel, ratio_white_pixels, green_concentration, blue_concentration)\n            regions_container.append(region_tuple)\n            \n            j += 1\n        i += 1\n    \n    k_best_region_coordinates = select_k_best_regions(regions_container, k=k)\n    k_best_regions = get_k_best_regions(k_best_region_coordinates, image, window_size)\n    \n    return image, k_best_region_coordinates, k_best_regions\n\ndef display_images(regions, title):\n    fig, ax = plt.subplots(5, 4, figsize=(15, 15))\n    \n    for i, region in regions.items():\n        ax[i // 4, i % 4].imshow(region)\n    \n    fig.suptitle(title)\n    plt.show()\n\n# Sélectionner un exemple aléatoire et afficher son grade de cancer\nrandom_index = random.randint(0, len(train_df) - 1)\nrandom_example = train_df.iloc[random_index]\nrandom_image_id = random_example['image_id']\nrandom_grade = random_example['isup_grade']\n\n# Afficher l'exemple sélectionné\nprint(f\"Exemple sélectionné: {random_image_id}, Grade de cancer: {random_grade}\")\n\n# Afficher l'image correspondante\nex_url = os.path.join(data_dir, f\"{random_image_id}.tiff\")\nrandom_image = skimage.io.MultiImage(ex_url)[-2]\nplt.imshow(random_image)\nplt.title(f\"Exemple sélectionné: {random_image_id}, Grade de cancer: {random_grade}\")\nplt.axis('off')\nplt.show()\n\n# Utiliser l'exemple sélectionné pour générer les patchs d'images avec différentes paramètres\nprint(\"Génération des patchs d'images avec différents paramètres...\")\nWINDOW_SIZE = 512\nSTRIDE = 256\nK = 16\n\nimage, best_coordinates, best_regions = generate_patches(ex_url)\ndisplay_images(best_regions, 'Patchs d\\'images générés avec les paramètres par défaut')\n\n# Afficher les patchs d'images générés avec différentes paramètres\nstart_time = time.time()\n\nex_url = data_dir + random_image_id + '.tiff'\n_, best_coordinates, best_regions = generate_patches(ex_url)\n\ndisplay_images(best_regions, f'Exemple: {random_image_id}, Taille de la fenêtre: 200, stride: 128')\n\nend_time = time.time()\nprint(f\"Temps d'exécution pour taille de fenêtre 200, stride 128: {end_time - start_time} secondes\")\n\nstart_time = time.time()\n\n_, best_coordinates, best_regions = generate_patches(ex_url, window_size=128, stride=64)\ndisplay_images(best_regions, f'Exemple: {random_image_id}, Taille de la fenêtre: 128, stride: 64')\n\nend_time = time.time()\nprint(f\"Temps d'exécution pour taille de fenêtre 128, stride 64: {end_time - start_time} secondes\")\n\nstart_time = time.time()\n\n_, best_coordinates, best_regions = generate_patches(ex_url, window_size=512, stride=256)\ndisplay_images(best_regions, f'Exemple: {random_image_id}, Taille de la fenêtre: 512, stride: 256')\n\nend_time = time.time()\nprint(f\"Temps d'exécution pour taille de fenêtre 512, stride 256: {end_time - start_time} secondes\")\n","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2024-05-19T20:45:21.248749Z","iopub.execute_input":"2024-05-19T20:45:21.249085Z","iopub.status.idle":"2024-05-19T20:45:44.065189Z","shell.execute_reply.started":"2024-05-19T20:45:21.249055Z","shell.execute_reply":"2024-05-19T20:45:44.064388Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import os\nimport random\nimport skimage.io\nimport numpy as np\nimport pandas as pd\nimport matplotlib.pyplot as plt\nfrom tqdm.auto import tqdm\nimport time\nimport tensorflow as tf\nfrom tensorflow.keras.models import Sequential\nfrom tensorflow.keras.layers import Conv2D, MaxPooling2D, Flatten, Dense, Dropout\nfrom tensorflow.keras.utils import plot_model\n\n# Charger les données du train.csv\ntrain_df = pd.read_csv('../input/prostate-cancer-grade-assessment/train.csv')\ndata_dir = '../input/prostate-cancer-grade-assessment/train_images/'\n\ndef compute_statistics(image):\n    \"\"\"\n    Args:\n        image (numpy.array): Multi-dimensional array of the form WxHxC\n    \n    Returns:\n        ratio_white_pixels (float): Ratio of white pixels over total pixels in the image.\n        green_concentration (float): Mean concentration of green pixels.\n        blue_concentration (float): Mean concentration of blue pixels.\n    \"\"\"\n    width, height = image.shape[0], image.shape[1]\n    num_pixels = width * height\n    \n    summed_matrix = np.sum(image, axis=-1)\n    num_white_pixels = np.count_nonzero(summed_matrix > 620)  # Note: A 3-channel white pixel has RGB (255, 255, 255)\n    ratio_white_pixels = num_white_pixels / num_pixels\n    \n    green_concentration = np.mean(image[:, :, 1])\n    blue_concentration = np.mean(image[:, :, 2])\n    \n    return ratio_white_pixels, green_concentration, blue_concentration\n\ndef select_k_best_regions(regions, k=20):\n    \"\"\"\n    Args:\n        regions (list): List of 2-component tuples, first component the region, \n                        second component the ratio of white pixels.\n        k (int): Number of regions to select.\n    \n    Returns:\n        list: k best regions based on the lowest ratio of white pixels.\n    \"\"\"\n    regions = [x for x in regions if x[3] > 180 and x[4] > 180]\n    k_best_regions = sorted(regions, key=lambda tup: tup[2])[:k]\n    return k_best_regions\n\ndef get_k_best_regions(coordinates, image, window_size=512):\n    regions = {}\n    for i, tup in enumerate(coordinates):\n        x, y = tup[0], tup[1]\n        regions[i] = image[x : x + window_size, y : y + window_size, :]\n    return regions\n\ndef generate_patches(slide_path, window_size=200, stride=128, k=20):\n    image = skimage.io.MultiImage(slide_path)[-2]\n    image = np.array(image)\n    \n    max_width, max_height = image.shape[0], image.shape[1]\n    regions_container = []\n    \n    i = 0\n    while window_size + stride * i <= max_height:\n        j = 0\n        while window_size + stride * j <= max_width:\n            x_top_left_pixel = j * stride\n            y_top_left_pixel = i * stride\n            \n            patch = image[x_top_left_pixel : x_top_left_pixel + window_size,\n                          y_top_left_pixel : y_top_left_pixel + window_size, :]\n            \n            ratio_white_pixels, green_concentration, blue_concentration = compute_statistics(patch)\n            region_tuple = (x_top_left_pixel, y_top_left_pixel, ratio_white_pixels, green_concentration, blue_concentration)\n            regions_container.append(region_tuple)\n            \n            j += 1\n        i += 1\n    \n    k_best_region_coordinates = select_k_best_regions(regions_container, k=k)\n    k_best_regions = get_k_best_regions(k_best_region_coordinates, image, window_size)\n    \n    return image, k_best_region_coordinates, k_best_regions\n\ndef display_images(regions, title):\n    fig, ax = plt.subplots(5, 4, figsize=(15, 15))\n    \n    for i, region in regions.items():\n        ax[i // 4, i % 4].imshow(region)\n    \n    fig.suptitle(title, fontsize=30)  # Afficher le titre en grand taille\n    plt.show()\n\n# Définir un tableau indicatif pour le grade de cancer\ncancer_grade_table = {\n    0: 'Non spécifié',\n    1: 'Tumeur bénigne',\n    2: 'Cancer à faible risque',\n    3: 'Cancer à risque intermédiaire',\n    4: 'Cancer à risque intermédiaire',\n    5: 'Cancer à risque élevé',\n}\n\n# Mapper les couleurs en fonction du grade\ncolors = {\n    0: '#FFFFFF',  # Blanc\n    1: '#FFD700',  # Or\n    2: '#32CD32',  # Vert\n    3: '#FFA500',  # Orange\n    4: '#FF6347',  # Rouge\n    5: '#8B0000',  # Rouge foncé\n}\n\n# Afficher le tableau indicatif pour le grade de cancer\nprint(\"Tableau indicatif pour le grade de cancer :\")\nprint(pd.DataFrame(list(cancer_grade_table.items()), columns=['Grade ISUP', 'Type de cancer']))\n\n# Demander à l'utilisateur d'entrer l'ID de l'image\nimage_id = input(\"Entrez l'ID de l'image pour voir le grade de cancer (par exemple, '0018ae58b01bdadc8e347995b69f99aa'): \")\n\n# Vérifier si l'ID de l'image est valide\nif image_id in train_df['image_id'].values:\n    # Obtenir le grade ISUP associé à l'image\n    isup_grade = train_df[train_df['image_id'] == image_id]['isup_grade'].values[0]\n    cancer_type = cancer_grade_table[isup_grade]\n\n    # Afficher l'ID de l'image et son grade ISUP\n    print(f\"ID de l'image: {image_id}, Grade ISUP: {isup_grade}, Type de cancer: {cancer_type}\")\n\n    # Afficher le texte avec une taille de police spécifique\n    fig, ax = plt.subplots(figsize=(10, 2))\n    ax.text(0.5, 0.5, f\"ID de l'image: {image_id}\\nGrade ISUP: {isup_grade}\\nType de cancer: {cancer_type}\",\n            fontsize=30, ha='center', va='center')\n    ax.axis('off')\n    plt.show()\n\n    # Récupérer le chemin de l'image correspondante\n    ex_url = os.path.join(data_dir, f\"{image_id}.tiff\")\n    \n    # Afficher l'image correspondante\n    image = skimage.io.MultiImage(ex_url)[-2]\n    plt.figure(figsize=(8, 8))  # Afficher la figure en grand taille\n    plt.imshow(image)\n    plt.title(f\"Image ID: {image_id}\", fontsize=30)  # Afficher le titre en grand taille\n    plt.axis('off')\n    plt.show()\n\n    # Afficher le masque de l'image correspondante\n    mask_url = os.path.join(data_dir, f\"{image_id}_mask.tiff\")\n    if os.path.exists(mask_url):\n        mask = skimage.io.MultiImage(mask_url)[-1]\n        plt.figure(figsize=(8, 8))  # Afficher la figure en grand taille\n        plt.imshow(mask, cmap='gray')\n        plt.title(f\"Masque de l'image ID: {image_id}\", fontsize=30)  # Afficher le titre en grand taille\n        plt.axis('off')\n        plt.show()\n    else:\n        print(\"Aucun masque disponible pour cette image.\")\nelse:\n    print(\"L'ID de l'image entré n'est pas valide.\")\n\n# Définir le modèle CNN\nmodel = Sequential([\n    Conv2D(32, (3, 3), activation='relu', input_shape=(512, 512, 3)),\n    MaxPooling2D((2, 2)),\n    Conv2D(64, (3, 3), activation='relu'),\n    MaxPooling2D((2, 2)),\n    Conv2D(128, (3, 3), activation='relu'),\n    MaxPooling2D((2, 2)),\n    Flatten(),\n    Dense(128, activation='relu'),\n    Dropout(0.5),\n    Dense(6, activation='softmax')  # 6 classes pour les grades ISUP\n])\n\n# Compiler le modèle\nmodel.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy'])\n\n# Sauvegarder le graphique du modèle\nplot_model(model, to_file='cnn_model.png', show_shapes=True, show_layer_names=True)\n\n# Afficher le graphique du modèle\nimg = plt.imread('cnn_model.png')\nplt.figure(figsize=(30, 30))  # Ajuster la taille de la figure si nécessaire\nplt.imshow(img)\nplt.axis('off')\nplt.show()\n","metadata":{"execution":{"iopub.status.busy":"2024-05-19T20:45:44.067225Z","iopub.execute_input":"2024-05-19T20:45:44.06754Z","iopub.status.idle":"2024-05-19T20:46:10.505464Z","shell.execute_reply.started":"2024-05-19T20:45:44.067508Z","shell.execute_reply":"2024-05-19T20:46:10.50436Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"#### Définir le Modèle CNN: Nous avons redéfini le modèle CNN comme précédemment avec des couches de convolution, de pooling, et des couches entièrement connectées.\n## Compiler le Modèle: Le modèle est compilé avec un optimiseur adam et une perte de type sparse_categorical_crossentropy.\n## Visualiser le Modèle: La fonction plot_model de Keras est utilisée pour générer un fichier PNG représentant l'architecture du modèle. Ce fichier est ensuite lu et affiché en utilisant matplotlib.","metadata":{}}]}