{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.11.13","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"none","dataSources":[{"sourceId":113558,"databundleVersionId":14456136,"sourceType":"competition"}],"dockerImageVersionId":31192,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"# Importations nécessaires\nimport pandas as pd\nimport numpy as np\nimport os\nimport matplotlib.pyplot as plt\n\n# Bibliothèque pour la vision par ordinateur et la manipulation d'images (souvent utilisée pour l'entraînement)\n# !pip install opencv-python # Décommentez si nécessaire dans votre environnement\n# import cv2 \n\n# Configuration du chemin des données\nDATA_DIR = \"/kaggle/input/recodai-luc-scientific-image-forgery-detection/\"\nTRAIN_MASKS_DIR = os.path.join(DATA_DIR, \"train_masks\")\nTRAIN_IMAGES_DIR = os.path.join(DATA_DIR, \"train_images\")\nTEST_IMAGES_DIR = os.path.join(DATA_DIR, \"test_images\")\n\nprint(\"Chemins de base configurés.\")","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"execution":{"iopub.status.busy":"2025-11-14T09:36:15.312173Z","iopub.execute_input":"2025-11-14T09:36:15.312389Z","iopub.status.idle":"2025-11-14T09:36:17.319247Z","shell.execute_reply.started":"2025-11-14T09:36:15.312370Z","shell.execute_reply":"2025-11-14T09:36:17.318179Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"## Fonctions RLE : À AJUSTER AVEC LE CODE OFFICIEL DU NOTEBOOK DE LA MÉTRIQUE !\n# --- Définition de rle_encode et rle_decode (Exemple) ---\n\ndef rle_decode(rle_mask, shape):\n    '''\n    rle_mask: string (par ex. '123 4')\n    shape: (height, width) du masque\n    returns: np.ndarray (masque binaire)\n    '''\n    if rle_mask == 'authentic' or pd.isna(rle_mask):\n        return np.zeros(shape, dtype=np.uint8)\n        \n    # Le format est [start length start length ...]\n    s = rle_mask.split()\n    starts, lengths = [np.asarray(x, dtype=int) for x in (s[0:][::2], s[1:][::2])]\n    starts -= 1\n    ends = starts + lengths\n    \n    img = np.zeros(shape[0] * shape[1], dtype=np.uint8)\n    for lo, hi in zip(starts, ends):\n        img[lo:hi] = 1\n        \n    return img.reshape(shape).T\n\ndef rle_encode(img):\n    '''\n    img: masque binaire np.ndarray (1 = masque, 0 = fond)\n    returns: string RLE (par ex. '123 4')\n    '''\n    pixels = img.T.flatten()\n    pixels = np.concatenate([[0], pixels, [0]])\n    runs = np.where(pixels[1:] != pixels[:-1])[0] + 1\n    runs[1::2] = runs[1::2] - runs[::2]\n    return ' '.join(str(x) for x in runs)\n    \nprint(\"Fonctions RLE définies (vérifiez et remplacez par l'implémentation officielle).\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-14T09:36:49.644717Z","iopub.execute_input":"2025-11-14T09:36:49.645036Z","iopub.status.idle":"2025-11-14T09:36:49.653817Z","shell.execute_reply.started":"2025-11-14T09:36:49.645015Z","shell.execute_reply":"2025-11-14T09:36:49.652851Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Lister les fichiers d'images et de masques\ntrain_image_files = sorted(os.listdir(TRAIN_IMAGES_DIR))\ntrain_mask_files = sorted(os.listdir(TRAIN_MASKS_DIR))\n\nprint(f\"Nombre d'images d'entraînement : {len(train_image_files)}\")\nprint(f\"Nombre de fichiers de masques d'entraînement : {len(train_mask_files)}\")\n\n# Charger le fichier sample_submission pour voir le format (optionnel)\n# sample_submission = pd.read_csv(os.path.join(DATA_DIR, \"sample_submission.csv\"))\n# print(\"\\nExtrait du fichier de soumission:\")\n# print(sample_submission.head())\n\n# Remarque : Les masques sont au format NPY, pas RLE/CSV\n# Le défi est d'associer l'image (PNG) à son ou ses masques (NPY) correspondants","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-14T09:38:03.261303Z","iopub.execute_input":"2025-11-14T09:38:03.261615Z","iopub.status.idle":"2025-11-14T09:38:03.301908Z","shell.execute_reply.started":"2025-11-14T09:38:03.261594Z","shell.execute_reply":"2025-11-14T09:38:03.301101Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import os\n\nDATA_DIR = \"/kaggle/input/recodai-luc-scientific-image-forgery-detection/\"\nTRAIN_MASKS_DIR = os.path.join(DATA_DIR, \"train_masks\")\n\ntry:\n    # Lister et afficher les premiers noms de masques pour vérifier leur format\n    mask_files_list = os.listdir(TRAIN_MASKS_DIR)\n    print(\"--- VÉRIFICATION DU FORMAT DES MASQUES ---\")\n    print(f\"Dossier de masques : {TRAIN_MASKS_DIR}\")\n    print(f\"Nombre total de fichiers de masques trouvés : {len(mask_files_list)}\")\n    print(\"\\nPremiers 10 noms de fichiers dans le dossier train_masks :\")\n    # Afficher les 10 premiers noms de fichiers\n    print(mask_files_list[:10]) \n    \nexcept Exception as e:\n    print(f\"\\nErreur lors de la lecture du dossier de masques : {e}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-14T10:39:38.331704Z","iopub.execute_input":"2025-11-14T10:39:38.332498Z","iopub.status.idle":"2025-11-14T10:39:38.340445Z","shell.execute_reply.started":"2025-11-14T10:39:38.332468Z","shell.execute_reply":"2025-11-14T10:39:38.339330Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import numpy as np\nimport pandas as pd\n\n# On récupère les chemins d'accès depuis le DataFrame que vous avez créé.\n# Assurez-vous que le DataFrame 'successful_forged' est accessible.\n\ntry:\n    # 1. Trouver le chemin d'accès au masque de la première ligne falsifiée\n    example_row = successful_forged.iloc[0]\n    example_mask_path = example_row['mask_paths'][0] \n    \n    # 2. Charger le masque\n    mask_data = np.load(example_mask_path)\n    \n    # 3. Afficher les propriétés\n    print(f\"--- INSPECTION DU MASQUE NPY ---\")\n    print(f\"Chemin du masque: {example_mask_path}\")\n    print(f\"Forme (Shape) du tableau: {mask_data.shape}\")\n    print(f\"Nombre de dimensions (ndim): {mask_data.ndim}\")\n    print(f\"Type de données (Dtype): {mask_data.dtype}\")\n    \n    # 4. Afficher les valeurs uniques et les statistiques\n    if mask_data.size > 0:\n        unique_values = np.unique(mask_data)\n        print(f\"Valeurs uniques dans le masque: {unique_values}\")\n        \n        # Si le masque est binaire, on vérifie la proportion de falsification\n        if 0 in unique_values or 1 in unique_values:\n            total_pixels = mask_data.size\n            forged_pixels = np.sum(mask_data > 0)\n            print(f\"Pourcentage de pixels falsifiés: {(forged_pixels / total_pixels) * 100:.4f}%\")\n        \nexcept NameError:\n    print(\"Erreur: Le DataFrame 'successful_forged' n'est pas défini. Veuillez exécuter la cellule d'indexation complète d'abord.\")\nexcept IndexError:\n    print(\"Erreur: Le DataFrame 'successful_forged' est vide.\")\nexcept Exception as e:\n    print(f\"Erreur lors de l'inspection du NPY : {e}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-14T10:43:30.798773Z","iopub.execute_input":"2025-11-14T10:43:30.799193Z","iopub.status.idle":"2025-11-14T10:43:30.833325Z","shell.execute_reply.started":"2025-11-14T10:43:30.799168Z","shell.execute_reply":"2025-11-14T10:43:30.832295Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import os\nimport pandas as pd\nimport numpy as np\nimport matplotlib.pyplot as plt\n\n# --- 0. Définition des chemins de base ---\nDATA_DIR = \"/kaggle/input/recodai-luc-scientific-image-forgery-detection/\"\nTRAIN_IMAGES_DIR = os.path.join(DATA_DIR, \"train_images\")\nTRAIN_MASKS_DIR = os.path.join(DATA_DIR, \"train_masks\")\n\n# Fonction de recherche des masques (format corrigé : [case_id].npy)\ndef find_mask_paths_corrected(case_id, mask_files_list, mask_dir):\n    \"\"\"\n    Cherche le masque NPY unique au format '[case_id].npy' et retourne son chemin complet.\n    \"\"\"\n    mask_file_name = str(case_id) + '.npy'\n    if mask_file_name in mask_files_list:\n        return [os.path.join(mask_dir, mask_file_name)]\n    return []\n\n# --- 1. Lister tous les fichiers PNG d'entraînement ---\nall_train_images = []\n\n# Sous-dossier 'authentic'\nauthentic_path = os.path.join(TRAIN_IMAGES_DIR, 'authentic')\nif os.path.exists(authentic_path):\n    for img_name in os.listdir(authentic_path):\n        if img_name.endswith('.png'):\n            all_train_images.append({'case_id': img_name.replace('.png', ''), \n                                     'path': os.path.join(authentic_path, img_name),\n                                     'is_forged': False})\n\n# Sous-dossier 'forged'\nforged_path = os.path.join(TRAIN_IMAGES_DIR, 'forged')\nif os.path.exists(forged_path):\n    for img_name in os.listdir(forged_path):\n        if img_name.endswith('.png'):\n            all_train_images.append({'case_id': img_name.replace('.png', ''), \n                                     'path': os.path.join(forged_path, img_name),\n                                     'is_forged': True})\n\n# --- 2. Créer le DataFrame d'Index et gérer les doublons ---\ntrain_df = pd.DataFrame(all_train_images)\n\n# 1. Trier pour mettre les True (forged) en dernier.\ntrain_df = train_df.sort_values(by='is_forged').reset_index(drop=True)\n# 2. Supprimer les doublons sur 'case_id', en gardant le dernier (le cas 'forged').\ntrain_df = train_df.drop_duplicates(subset=['case_id'], keep='last').reset_index(drop=True)\n\n# --- 3. Intégrer les chemins complets des masques ---\n\nmask_files_list = os.listdir(TRAIN_MASKS_DIR) \n\ntrain_df['mask_paths'] = train_df['case_id'].astype(str).apply(\n    lambda x: find_mask_paths_corrected(x, mask_files_list, TRAIN_MASKS_DIR))\ntrain_df['mask_count'] = train_df['mask_paths'].apply(len)\n\n# --- 4. Affichage et Vérification Finale ---\n\nprint(f\"\\nTotal des images d'entraînement uniques listées : {len(train_df)}\")\n\n# Filtrer les images falsifiées avec masque\nforged_check = train_df[train_df['is_forged'] == True]\nsuccessful_forged = forged_check[forged_check['mask_count'] > 0]\n\nprint(\"\\nVérification des images FALSIFIÉES (forged) :\")\nprint(successful_forged[['case_id', 'mask_count', 'path']].head(5)) \n\nprint(\"\\nVérification des images AUTHENTIQUES (sans masque) :\")\nauthentic_check = train_df[train_df['is_forged'] == False]\nprint(authentic_check[['case_id', 'mask_count', 'path']].head(5))\n\n# --- OPTIONNEL : Tester le chargement d'un exemple falsifié (CORRECTION DÉFINITIVE DE SHAPE) ---\ntry:\n    example_row = successful_forged.iloc[0]\n    \n    example_img = plt.imread(example_row['path'])\n    example_mask_path = example_row['mask_paths'][0] \n    \n    # CHARGEMENT ET COMBINAISON DU MASQUE (CORRECTION DE SHAPE)\n    example_mask_3d = np.load(example_mask_path) \n    \n    # Gérer la forme (3, H, W) en combinant les couches (np.max sur l'axe des canaux, axe=0)\n    if example_mask_3d.ndim == 3 and example_mask_3d.shape[0] in [2, 3]:\n        # Combinaison des canaux pour un masque 2D binaire : (H, W)\n        example_mask_2d = np.max(example_mask_3d, axis=0)\n    else:\n        example_mask_2d = example_mask_3d # Si c'est déjà (H, W)\n    \n    print(f\"\\nExemple de chargement réussi : Image {example_row['case_id']} (Masques trouvés : {example_row['mask_count']})\")\n    print(f\"Forme du masque 2D pour l'affichage : {example_mask_2d.shape}\")\n    \n    # Affichage\n    plt.figure(figsize=(12, 6))\n    plt.subplot(1, 2, 1)\n    plt.title(f\"Image Falsifiée : {example_row['case_id']}\")\n    plt.imshow(example_img)\n    \n    plt.subplot(1, 2, 2)\n    plt.title(\"Masque (Région Falsifiée Combinée)\")\n    # Le vmin/vmax=1 est important pour un masque binaire (0=noir, 1=blanc)\n    plt.imshow(example_mask_2d, cmap='gray', vmin=0, vmax=1) \n    plt.show()\n\nexcept IndexError:\n    print(\"\\nAvertissement : Aucune image falsifiée n'a pu être associée à un masque. Le DataFrame final ne contient que des images authentiques.\")\nexcept Exception as e:\n    print(f\"\\nErreur lors du chargement de l'exemple visuel : {e}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-14T10:44:25.491408Z","iopub.execute_input":"2025-11-14T10:44:25.491722Z","iopub.status.idle":"2025-11-14T10:44:26.107722Z","shell.execute_reply.started":"2025-11-14T10:44:25.491700Z","shell.execute_reply":"2025-11-14T10:44:26.106598Z"}},"outputs":[],"execution_count":null}]}