{"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":14174843,"sourceType":"competition"}],"dockerImageVersionId":31192,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import matplotlib.pyplot as plt\nimport matplotlib.image as mpimg\n\nimg_path_mpl = '/kaggle/input/recodai-luc-scientific-image-forgery-detection/train_images/authentic/10636.png'\nimg_mpl = mpimg.imread(img_path_mpl)\nplt.imshow(img_mpl)\nplt.axis('off') \nplt.show()","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"execution":{"iopub.status.busy":"2025-11-09T10:09:55.229793Z","iopub.execute_input":"2025-11-09T10:09:55.230091Z","iopub.status.idle":"2025-11-09T10:09:55.332039Z","shell.execute_reply.started":"2025-11-09T10:09:55.23007Z","shell.execute_reply":"2025-11-09T10:09:55.331165Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import matplotlib.pyplot as plt\nimport matplotlib.image as mpimg\n\nimg_path_mpl = '/kaggle/input/recodai-luc-scientific-image-forgery-detection/train_images/forged/10636.png'\nimg_mpl = mpimg.imread(img_path_mpl)\nplt.imshow(img_mpl)\nplt.axis('off') \nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-09T10:10:12.240195Z","iopub.execute_input":"2025-11-09T10:10:12.241413Z","iopub.status.idle":"2025-11-09T10:10:12.348036Z","shell.execute_reply.started":"2025-11-09T10:10:12.241381Z","shell.execute_reply":"2025-11-09T10:10:12.347176Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import pandas as pd\ndata=pd.read_csv(\"/kaggle/input/recodai-luc-scientific-image-forgery-detection/sample_submission.csv\")\nprint(data.head())\nprint(data.info())","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-08T14:43:03.975389Z","iopub.execute_input":"2025-11-08T14:43:03.975759Z","iopub.status.idle":"2025-11-08T14:43:03.98888Z","shell.execute_reply.started":"2025-11-08T14:43:03.975737Z","shell.execute_reply":"2025-11-08T14:43:03.988077Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# import numpy as np\n# from PIL import Image\n# image_data=np.load(\"/kaggle/input/recodai-luc-scientific-image-forgery-detection/train_masks/1008.npy\")\n# print(image_data.shape)\n# print(image_data.dtype)\n\n# import matplotlib.pyplot as plt \n# #from PIL import Image\n# plt.imshow(image_data,cmap=\"gray\")\n# plt.title(\"Image Loaded\")\n# plt.show()\n\n# pil_image=Image.fromarray(image_data)\n# pil_image.show()\n\n\n\n\n\n# import numpy as np\n# import matplotlib.pyplot as plt\n# from PIL import Image\n\n# # Step 1: Load the .npy file\n# image_path = \"/kaggle/input/recodai-luc-scientific-image-forgery-detection/train_masks/10070.npy\"\n# image_array = np.load(image_path)\n\n# # Step 2: Print basic info\n# print(\"Array shape:\", image_array.shape)\n# print(\"Array data type:\", image_array.dtype)\n\n# # Step 3: Display using matplotlib\n# plt.imshow(image_array, cmap='gray')\n# plt.title(\"Image Loaded from .npy file\")\n# plt.axis('off')\n# plt.show()\n\n# # Step 4: Convert to uint8 if needed (for PIL)\n# if image_array.dtype != np.uint8:\n#     # Normalize to 0–255 range for visualization\n#     normalized = (image_array - image_array.min()) / (image_array.max() - image_array.min())\n#     image_array = (normalized * 255).astype(np.uint8)\n\n# # Step 5: Display using PIL\n# image = Image.fromarray(image_array)\n# image.show()\n\n# # Optional: Save the image\n# # image.save(\"output_image.png\")\n\n\n\n\n# import numpy as np\n# import matplotlib.pyplot as plt\n# from PIL import Image\n\n# # Step 1: Load the .npy file\n# image_path = \"/kaggle/input/recodai-luc-scientific-image-forgery-detection/train_masks/10070.npy\"\n# image_array = np.load(image_path)\n\n# # Step 2: Remove any extra dimensions (like 1-channel)\n# image_array = np.squeeze(image_array)\n\n# print(\"Array shape after squeeze:\", image_array.shape)\n# print(\"Array dtype:\", image_array.dtype)\n\n# # Step 3: Display using matplotlib\n# plt.imshow(image_array, cmap='gray')\n# plt.title(\"Image Loaded from .npy file\")\n# plt.axis('off')\n# plt.show()\n\n# # Step 4: Convert to uint8 for PIL if needed\n# if image_array.dtype != np.uint8:\n#     normalized = (image_array - image_array.min()) / (image_array.max() - image_array.min())\n#     image_array = (normalized * 255).astype(np.uint8)\n\n# # Step 5: Display using PIL\n# image = Image.fromarray(image_array)\n# image.show()\n\n\n\n\n\n\n# import numpy as np\n# import matplotlib.pyplot as plt\n# from PIL import Image\n\n# # Load the .npy file\n# image_path = \"/kaggle/input/recodai-luc-scientific-image-forgery-detection/train_masks/10636.npy\"\n# image_array = np.load(image_path)\n# print(\"Original shape:\", image_array.shape)\n\n# # If shape has more than 2 dimensions, handle appropriately\n# if image_array.ndim == 3 and image_array.shape[0] <= 4:\n#     # Move channels to the last dimension if needed (2, H, W) → (H, W, 2)\n#     image_array = np.transpose(image_array, (1, 2, 0))\n#     print(\"Transposed shape:\", image_array.shape)\n\n# # Normalize and convert to uint8\n# normalized = (image_array - image_array.min()) / (image_array.max() - image_array.min())\n# image_uint8 = (normalized * 255).astype(np.uint8)\n\n# # Display each channel separately\n# for i in range(image_uint8.shape[-1]):\n#     plt.imshow(image_uint8[..., i], cmap='gray')\n#     plt.title(f\"Channel {i+1}\")\n#     plt.axis('off')\n#     plt.show()\n# # Convert (H, W, 2) to (H, W, 3) by adding a third zero channel\n# if image_uint8.shape[-1] == 2:\n#     h, w, _ = image_uint8.shape\n#     merged = np.zeros((h, w, 3), dtype=np.uint8)\n#     merged[..., :2] = image_uint8  # fill R and G\n#     plt.imshow(merged)\n#     plt.title(\"Merged 2-Channel Image (Fake RGB)\")\n#     plt.axis('off')\n#     plt.show()\n\n\n\nimport numpy as np\nimport matplotlib.pyplot as plt\nfrom PIL import Image\n\n# ================================\n# 1. Load the .npy file\n# ================================\nimage_path = \"/kaggle/input/recodai-luc-scientific-image-forgery-detection/train_masks/10632.npy\"\nimage_array = np.load(image_path)\nprint(\"Original shape:\", image_array.shape)\n\n# ================================\n# 2. Normalize and convert to uint8\n# ================================\nimage_array = image_array.astype(np.float32)\nimage_array = (image_array - image_array.min()) / (image_array.max() - image_array.min() + 1e-8)\nimage_uint8 = (image_array * 255).astype(np.uint8)\n\n# ================================\n# 3. Adjust shape for visualization\n# ================================\nif image_uint8.ndim == 3 and image_uint8.shape[0] in [1, 2, 3, 4]:\n    # If channel-first (C, H, W) -> (H, W, C)\n    image_uint8 = np.transpose(image_uint8, (1, 2, 0))\n\nprint(\"Adjusted shape:\", image_uint8.shape)\n\n# ================================\n# 4. Display logic\n# ================================\nif image_uint8.ndim == 2:\n    # Grayscale\n    plt.imshow(image_uint8, cmap='gray')\n    plt.title(\"Grayscale Image\")\n    plt.axis('off')\n    plt.show()\n\nelif image_uint8.ndim == 3:\n    channels = image_uint8.shape[2]\n    if channels == 1:\n        # Single-channel grayscale\n        plt.imshow(image_uint8.squeeze(), cmap='gray')\n        plt.title(\"Single-Channel Image\")\n        plt.axis('off')\n        plt.show()\n\n    elif channels == 2:\n        # Two-channel image — show each channel separately\n        for i in range(2):\n            plt.imshow(image_uint8[..., i], cmap='gray')\n            plt.title(f\"Channel {i+1}\")\n            plt.axis('off')\n            plt.show()\n        # Optionally merge as fake RGB for preview\n        merged = np.zeros((image_uint8.shape[0], image_uint8.shape[1], 3), dtype=np.uint8)\n        merged[..., :2] = image_uint8\n        plt.imshow(merged)\n        plt.title(\"Merged 2-Channel (Fake RGB)\")\n        plt.axis('off')\n        plt.show()\n\n    elif channels in [3, 4]:\n        # RGB or RGBA\n        plt.imshow(image_uint8)\n        plt.title(f\"{'RGB' if channels==3 else 'RGBA'} Image\")\n        plt.axis('off')\n        plt.show()\n\n    else:\n        print(f\"Unsupported number of channels: {channels}\")\n\nelse:\n    print(\"Unsupported image shape:\", image_uint8.shape)\n\n# ================================\n# 5. Optional: Save one channel or full image\n# ================================\n# Example: save first channel\n# Image.fromarray(image_uint8[..., 0]).save(\"output_channel1.png\")\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-09T10:13:22.10193Z","iopub.execute_input":"2025-11-09T10:13:22.102793Z","iopub.status.idle":"2025-11-09T10:13:22.217939Z","shell.execute_reply.started":"2025-11-09T10:13:22.102765Z","shell.execute_reply":"2025-11-09T10:13:22.217143Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import numpy as np\nimport matplotlib.pyplot as plt\nfrom PIL import Image\nfrom pathlib import Path\n\ndef explore_segmentation_data(image_dir, mask_dir):\n    \"\"\"Explore segmentation dataset\"\"\"\n    print(\"=\" * 60)\n    print(\"SEGMENTATION DATASET EXPLORATION\")\n    print(\"=\" * 60)\n    \n    image_paths = sorted(list(Path(image_dir).glob('*.png')) + \n                        list(Path(image_dir).glob('*.png')))\n    mask_paths = sorted(list(Path(mask_dir).glob('*.npy')))\n    \n    print(f\"\\n📊 Dataset Statistics:\")\n    print(f\"  Images: {len(image_paths)}\")\n    print(f\"  Masks: {len(mask_paths)}\")\n    \n    # Check first sample\n    if len(image_paths) > 0 and len(mask_paths) > 0:\n        img = np.array(Image.open(image_paths[0]))\n        mask = np.load(mask_paths[0])\n        \n        print(f\"\\n📐 Image Properties:\")\n        print(f\"  Shape: {img.shape}\")\n        print(f\"  Dtype: {img.dtype}\")\n        print(f\"  Range: [{img.min()}, {img.max()}]\")\n        \n        print(f\"\\n🎭 Mask Properties:\")\n        print(f\"  Shape: {mask.shape}\")\n        print(f\"  Dtype: {mask.dtype}\")\n        print(f\"  Unique values: {np.unique(mask)}\")\n        print(f\"  Range: [{mask.min()}, {mask.max()}]\")\n        \n        # Calculate forgery percentage\n        if len(mask.shape) == 3:\n            mask = mask[:, :, 0]  # Take first channel if RGB\n        \n        forged_pixels = (mask > 0).sum()\n        total_pixels = mask.size\n        forgery_ratio = forged_pixels / total_pixels * 100\n        \n        print(f\"\\n🔍 Forgery Statistics:\")\n        print(f\"  Forged pixels: {forged_pixels:,} ({forgery_ratio:.2f}%)\")\n        print(f\"  Authentic pixels: {total_pixels - forged_pixels:,} ({100-forgery_ratio:.2f}%)\")\n        \n        # Visualize\n        fig, axes = plt.subplots(1, 3, figsize=(15, 5))\n        \n        axes[0].imshow(img)\n        axes[0].set_title('Original Image')\n        axes[0].axis('off')\n        \n        axes[1].imshow(mask, cmap='gray')\n        axes[1].set_title('Ground Truth Mask')\n        axes[1].axis('off')\n        \n        # Overlay\n        overlay = img.copy()\n        if len(overlay.shape) == 2:\n            overlay = np.stack([overlay]*3, axis=-1)\n        overlay[mask > 0] = [255, 0, 0]  # Red for forged regions\n        \n        axes[2].imshow(overlay)\n        axes[2].set_title('Overlay (Red = Forged)')\n        axes[2].axis('off')\n        \n        plt.tight_layout()\n        plt.savefig('results/data_exploration_segmentation.png', dpi=100)\n        plt.show()\n        \n    return image_paths, mask_paths\n\n# Run exploration\nimage_paths, mask_paths = explore_segmentation_data(\n    \"/kaggle/input/recodai-luc-scientific-image-forgery-detection/train_images/authentic\",\n    \"/kaggle/input/recodai-luc-scientific-image-forgery-detection/train_masks\",\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-09T10:17:05.388075Z","iopub.execute_input":"2025-11-09T10:17:05.388426Z","iopub.status.idle":"2025-11-09T10:17:05.834402Z","shell.execute_reply.started":"2025-11-09T10:17:05.388401Z","shell.execute_reply":"2025-11-09T10:17:05.833162Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import numpy as np\nimport matplotlib.pyplot as plt\nfrom PIL import Image\nfrom pathlib import Path\n\ndef explore_segmentation_data(image_dir, mask_dir):\n    \"\"\"Explore segmentation dataset\"\"\"\n    print(\"=\" * 60)\n    print(\"SEGMENTATION DATASET EXPLORATION\")\n    print(\"=\" * 60)\n    \n    image_paths = sorted(list(Path(image_dir).glob('*.png')))\n    mask_paths = sorted(list(Path(mask_dir).glob('*.npy')))\n    \n    print(f\"\\n📊 Dataset Statistics:\")\n    print(f\"  Images: {len(image_paths)}\")\n    print(f\"  Masks: {len(mask_paths)}\")\n    \n    # Check first sample\n    if len(image_paths) > 0 and len(mask_paths) > 0:\n        img = np.array(Image.open(image_paths[0]))\n        mask = np.load(mask_paths[0])\n        \n        print(f\"\\n📐 Image Properties:\")\n        print(f\"  Shape: {img.shape}\")\n        print(f\"  Dtype: {img.dtype}\")\n        print(f\"  Range: [{img.min()}, {img.max()}]\")\n        \n        print(f\"\\n🎭 Mask Properties:\")\n        print(f\"  Shape: {mask.shape}\")\n        print(f\"  Dtype: {mask.dtype}\")\n        print(f\"  Unique values: {np.unique(mask)}\")\n        print(f\"  Range: [{mask.min()}, {mask.max()}]\")\n        \n        # ✅ Fix: remove extra dimensions (e.g., (1, H, W) → (H, W))\n        mask = np.squeeze(mask)\n        \n        # ✅ Fix: if mask is multi-channel (e.g., (2, H, W)), take one or merge\n        if mask.ndim == 3 and mask.shape[0] in [2, 3, 4]:\n            # Move channels to last dimension for consistency\n            mask = np.transpose(mask, (1, 2, 0))\n            # Use first channel for visualization\n            mask = mask[..., 0]\n        \n        # ✅ Fix: Resize mask if needed to match image\n        if mask.shape[:2] != img.shape[:2]:\n            print(f\"⚠️ Resizing mask from {mask.shape} to {img.shape[:2]}\")\n            mask = np.array(Image.fromarray(mask).resize(img.shape[:2][::-1]))\n        \n        # Calculate forgery percentage\n        forged_pixels = (mask > 0).sum()\n        total_pixels = mask.size\n        forgery_ratio = forged_pixels / total_pixels * 100\n        \n        print(f\"\\n🔍 Forgery Statistics:\")\n        print(f\"  Forged pixels: {forged_pixels:,} ({forgery_ratio:.2f}%)\")\n        print(f\"  Authentic pixels: {total_pixels - forged_pixels:,} ({100-forgery_ratio:.2f}%)\")\n        \n        # Visualize\n        fig, axes = plt.subplots(1, 3, figsize=(15, 5))\n        \n        axes[0].imshow(img)\n        axes[0].set_title('Original Image')\n        axes[0].axis('off')\n        \n        axes[1].imshow(mask, cmap='gray')\n        axes[1].set_title('Ground Truth Mask')\n        axes[1].axis('off')\n        \n        # ✅ Fix: ensure overlay shape consistency\n        overlay = img.copy()\n        if len(overlay.shape) == 2:\n            overlay = np.stack([overlay]*3, axis=-1)\n        \n        # Apply mask safely\n        overlay[mask > 0] = [255, 0, 0]  # Red for forged regions\n        \n        axes[2].imshow(overlay)\n        axes[2].set_title('Overlay (Red = Forged)')\n        axes[2].axis('off')\n        \n        #plt.tight_layout()\n        #plt.savefig('results/data_exploration_segmentation.png', dpi=100)\n        #plt.show()\n        \n    return image_paths, mask_paths\n# Run exploration\nimage_paths, mask_paths = explore_segmentation_data(\n    \"/kaggle/input/recodai-luc-scientific-image-forgery-detection/train_images/authentic\",\n    \"/kaggle/input/recodai-luc-scientific-image-forgery-detection/train_masks\",\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-09T10:26:29.938544Z","iopub.execute_input":"2025-11-09T10:26:29.939101Z","iopub.status.idle":"2025-11-09T10:26:30.540458Z","shell.execute_reply.started":"2025-11-09T10:26:29.939075Z","shell.execute_reply":"2025-11-09T10:26:30.539518Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import numpy as np\nimport matplotlib.pyplot as plt\nfrom PIL import Image\nfrom pathlib import Path\n\ndef explore_segmentation_data(image_dir, forged_dir, mask_dir):\n    \"\"\"Explore segmentation dataset with authentic + forged images\"\"\"\n    print(\"=\" * 60)\n    print(\"SEGMENTATION DATASET EXPLORATION\")\n    print(\"=\" * 60)\n    \n    image_paths = sorted(list(Path(image_dir).glob('*.png')))\n    forged_paths = sorted(list(Path(forged_dir).glob('*.png')))\n    mask_paths = sorted(list(Path(mask_dir).glob('*.npy')))\n    \n    print(f\"\\n📊 Dataset Statistics:\")\n    print(f\"  Authentic Images: {len(image_paths)}\")\n    print(f\"  Forged Images: {len(forged_paths)}\")\n    print(f\"  Masks: {len(mask_paths)}\")\n    \n    # Check first sample\n    if len(image_paths) > 0 and len(mask_paths) > 0 and len(forged_paths) > 0:\n        # Load data\n        img_auth = np.array(Image.open(image_paths[0]))\n        img_forged = np.array(Image.open(forged_paths[0]))\n        mask = np.load(mask_paths[0])\n        \n        print(f\"\\n📐 Image Properties:\")\n        print(f\"  Authentic Image: {img_auth.shape}, dtype={img_auth.dtype}\")\n        print(f\"  Forged Image: {img_forged.shape}, dtype={img_forged.dtype}\")\n        \n        print(f\"\\n🎭 Mask Properties:\")\n        print(f\"  Shape: {mask.shape}, dtype={mask.dtype}\")\n        print(f\"  Unique values: {np.unique(mask)}\")\n        \n        # ✅ Clean mask\n        mask = np.squeeze(mask)\n        if mask.ndim == 3 and mask.shape[0] in [2, 3, 4]:\n            mask = np.transpose(mask, (1, 2, 0))\n            mask = mask[..., 0]\n        \n        # ✅ Resize mask if needed\n        if mask.shape[:2] != img_auth.shape[:2]:\n            print(f\"⚠️ Resizing mask from {mask.shape} to {img_auth.shape[:2]}\")\n            mask = np.array(Image.fromarray(mask).resize(img_auth.shape[:2][::-1]))\n        \n        # Forgery statistics\n        forged_pixels = (mask > 0).sum()\n        total_pixels = mask.size\n        forgery_ratio = forged_pixels / total_pixels * 100\n        \n        print(f\"\\n🔍 Forgery Statistics:\")\n        print(f\"  Forged pixels: {forged_pixels:,} ({forgery_ratio:.2f}%)\")\n        \n        # ✅ Overlay creation\n        overlay = img_auth.copy()\n        if len(overlay.shape) == 2:\n            overlay = np.stack([overlay]*3, axis=-1)\n        overlay[mask > 0] = [255, 0, 0]  # red overlay\n        \n        # ===============================\n        # 🔸 Visualization (4 images)\n        # ===============================\n        fig, axes = plt.subplots(1, 4, figsize=(20, 5))\n        \n        axes[0].imshow(img_auth)\n        axes[0].set_title('Authentic Image')\n        axes[0].axis('off')\n        \n        axes[1].imshow(mask, cmap='gray')\n        axes[1].set_title('Ground Truth Mask')\n        axes[1].axis('off')\n        \n        axes[2].imshow(overlay)\n        axes[2].set_title('Overlay (Red = Forged)')\n        axes[2].axis('off')\n\n        axes[3].imshow(img_forged)\n        axes[3].set_title('Forged Image')\n        axes[3].axis('off')\n        \n        plt.tight_layout()\n        Path(\"results\").mkdir(exist_ok=True)\n        plt.savefig('results/data_exploration_segmentation.png', dpi=100)\n        plt.show()\n        \n    else:\n        print(\"❌ Missing images or masks for exploration.\")\n    \n    return image_paths, forged_paths, mask_paths\n# Run exploration\nimage_paths, forged_paths, mask_paths = explore_segmentation_data(\n    \"/kaggle/input/recodai-luc-scientific-image-forgery-detection/train_images/authentic\",\n    \"/kaggle/input/recodai-luc-scientific-image-forgery-detection/train_images/forged\",\n    \"/kaggle/input/recodai-luc-scientific-image-forgery-detection/train_masks\",\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-09T10:38:11.773138Z","iopub.execute_input":"2025-11-09T10:38:11.77348Z","iopub.status.idle":"2025-11-09T10:38:13.064849Z","shell.execute_reply.started":"2025-11-09T10:38:11.773455Z","shell.execute_reply":"2025-11-09T10:38:13.063905Z"}},"outputs":[],"execution_count":null}]}