{"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":"nvidiaTeslaT4","dataSources":[{"sourceId":113558,"databundleVersionId":14174843,"sourceType":"competition"},{"sourceId":4534,"sourceType":"modelInstanceVersion","modelInstanceId":3326,"modelId":986}],"dockerImageVersionId":31154,"isInternetEnabled":false,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import os\nimport json\nimport cv2\nimport numpy as np\nimport pandas as pd\nfrom pathlib import Path\nfrom PIL import Image\nimport matplotlib.pyplot as plt\nfrom tqdm import tqdm\n\n# Define configurable threshold\nTHRESHOLD = 1.15\n\n# Define the RLE encoder\ndef rle_encode(mask: np.ndarray, fg_val: int = 1) -> str:\n    # Flatten mask in Fortran order\n    pixels = mask.T.flatten()\n    \n    # Find foreground indices\n    dots = np.where(pixels == fg_val)[0]\n    \n    # Return authentic if no foreground\n    if len(dots) == 0:\n        return \"authentic\"\n    \n    # Initialize run-length list\n    run_lengths = []\n    prev = -2\n    \n    # Compute run-length encoding\n    for b in dots:\n        if b > prev + 1:\n            run_lengths.extend((b + 1, 0))\n        run_lengths[-1] += 1\n        prev = b\n    \n    # Return as JSON string\n    return json.dumps([int(x) for x in run_lengths])\n\n# Define example pipeline (replace model logic here)\ndef pipeline_final(pil_img: Image.Image):\n    # Convert PIL to NumPy array\n    img = np.array(pil_img)\n    \n    # Convert to grayscale\n    gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)\n    \n    # Compute a fake \"forgery\" confidence metric\n    mean_intensity = gray.mean() / 255.0\n    \n    # Create a dummy mask\n    mask = (gray > gray.mean()).astype(np.uint8)\n    \n    # Prepare debug info\n    dbg = {\n        \"mean_inside\": mean_intensity,\n        \"area\": mask.sum(),\n        \"thr\": THRESHOLD\n    }\n    \n    # Apply threshold to decide authenticity\n    if mean_intensity > THRESHOLD:\n        label = \"forged\"\n    else:\n        label = \"authentic\"\n    \n    # Return label, mask, and debug info\n    return label, mask, dbg\n\n# Define main inference function\ndef main():\n    # Define paths\n    TEST_DIR = \"/kaggle/input/recodai-luc-scientific-image-forgery-detection/test_images\"\n    SAMPLE_SUB = \"/kaggle/input/recodai-luc-scientific-image-forgery-detection/sample_submission.csv\"\n    OUT_PATH = \"submission.csv\"\n\n    # Initialize output rows\n    rows = []\n\n    # Run inference on test images\n    for f in tqdm(sorted(os.listdir(TEST_DIR)), desc=\"Inference on Test Set\"):\n        pil = Image.open(Path(TEST_DIR) / f).convert(\"RGB\")\n        \n        # Get prediction and mask from pipeline\n        label, mask, dbg = pipeline_final(pil)\n        \n        # Ensure mask format\n        if mask is not None:\n            mask = np.array(mask, dtype=np.uint8)\n        else:\n            mask = np.zeros(pil.size[::-1], np.uint8)\n        \n        # Encode annotation\n        if label == \"authentic\":\n            annot = \"authentic\"\n        else:\n            annot = rle_encode((mask > 0).astype(np.uint8))\n        \n        # Append result row\n        rows.append({\n            \"case_id\": Path(f).stem,\n            \"annotation\": annot,\n            \"area\": int(dbg.get(\"area\", mask.sum())),\n            \"mean\": float(dbg.get(\"mean_inside\", 0.0)),\n            \"thr\": float(dbg.get(\"thr\", 0.0))\n        })\n    \n    # Create submission dataframe\n    sub = pd.DataFrame(rows)\n    ss = pd.read_csv(SAMPLE_SUB)\n    \n    # Ensure consistent case_id type\n    ss[\"case_id\"] = ss[\"case_id\"].astype(str)\n    sub[\"case_id\"] = sub[\"case_id\"].astype(str)\n    \n    # Merge with sample submission\n    final = ss[[\"case_id\"]].merge(sub, on=\"case_id\", how=\"left\")\n    final[\"annotation\"] = final[\"annotation\"].fillna(\"authentic\")\n    \n    # Save submission file\n    final[[\"case_id\", \"annotation\"]].to_csv(OUT_PATH, index=False)\n    print(f\"\\nSaved submission file: {OUT_PATH}\")\n    print(final.head(10))\n\n    # Run visualization\n    visualize_results(TEST_DIR)\n\n# Define visualization function\ndef visualize_results(test_dir: str):\n    # Select sample images\n    sample_files = sorted(os.listdir(test_dir))[:5]\n\n    # Visualize results for a few images\n    for f in sample_files:\n        pil = Image.open(Path(test_dir) / f).convert(\"RGB\")\n        label, mask, dbg = pipeline_final(pil)\n        \n        # Ensure mask format\n        if mask is not None:\n            mask = np.array(mask, dtype=np.uint8)\n        else:\n            mask = np.zeros(pil.size[::-1], np.uint8)\n        \n        # Print image information\n        print(f\"{'🔴' if label == 'forged' else '🟢'} {f}: {label} | area={mask.sum()} mean={dbg.get('mean_inside', 0):.3f}\")\n        \n        # Display authentic or forged images\n        if label == \"authentic\":\n            plt.figure(figsize=(5, 5))\n            plt.imshow(pil)\n            plt.title(f\"{f} — Authentic\")\n            plt.axis(\"off\")\n            plt.show()\n        else:\n            plt.figure(figsize=(10, 5))\n            plt.subplot(1, 2, 1)\n            plt.imshow(pil)\n            plt.title(\"Original\")\n            plt.axis(\"off\")\n            \n            plt.subplot(1, 2, 2)\n            plt.imshow(pil)\n            plt.imshow(mask, alpha=0.45, cmap=\"Blues\")\n            plt.title(\"Predicted Mask\")\n            plt.axis(\"off\")\n            plt.show()\n\n# Call main function\nif __name__ == \"__main__\":\n    main()","metadata":{"_uuid":"1ab37b6f-c4ee-418b-91bc-32a5ea5d69d6","_cell_guid":"f7cc3a0d-c0e0-4f26-9e81-a03e93660026","trusted":true,"collapsed":false,"jupyter":{"outputs_hidden":false}},"outputs":[],"execution_count":null}]}