{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.11.11","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"none","dataSources":[{"sourceId":91498,"databundleVersionId":11655853,"sourceType":"competition"}],"dockerImageVersionId":31040,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"!pip install -q mediapy","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"execution":{"iopub.status.busy":"2025-05-22T00:58:27.898829Z","iopub.execute_input":"2025-05-22T00:58:27.899409Z","iopub.status.idle":"2025-05-22T00:58:32.044581Z","shell.execute_reply.started":"2025-05-22T00:58:27.899351Z","shell.execute_reply":"2025-05-22T00:58:32.043302Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"%cd /kaggle/working/\n!rm -rf /kaggle/working/Hierarchical-Localization\n!git clone --quiet --recursive https://github.com/cvg/Hierarchical-Localization/\n%cd /kaggle/working/Hierarchical-Localization\n!pip install -e .\n\nfrom hloc import extract_features, match_features, reconstruction, visualization, pairs_from_exhaustive\nfrom hloc.visualization import plot_images, read_image\nfrom hloc.utils import viz_3d\n\n%cd /kaggle/working/","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-22T00:58:32.046765Z","iopub.execute_input":"2025-05-22T00:58:32.047081Z","iopub.status.idle":"2025-05-22T01:00:32.571696Z","shell.execute_reply.started":"2025-05-22T00:58:32.047050Z","shell.execute_reply":"2025-05-22T01:00:32.570316Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"<a id=\"2\"></a>\n<h1 style='background:#000000;border:0; color:black;\n    box-shadow: 10px 10px 5px 0px rgba(0,0,0,0.75);\n    transform: rotateX(10deg);\n    '><center style='color: #17E8C4;'>IMPORT IMPORTANT LIBRARIES</center></h1>","metadata":{}},{"cell_type":"code","source":"# Standard Libraries\nimport os\nimport random\nfrom pathlib import Path\n\n# Data Handling\nimport pandas as pd\nimport numpy as np\n\n# Image Processing\nimport cv2\nfrom PIL import Image\n\n# Visualization\nimport matplotlib.pyplot as plt\nimport plotly.express as px\nfrom matplotlib import cm\n\n# Media & Display\nimport mediapy\n\n# 3D Reconstruction / SfM\nimport pycolmap","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-22T01:00:32.573651Z","iopub.execute_input":"2025-05-22T01:00:32.574136Z","iopub.status.idle":"2025-05-22T01:00:34.343957Z","shell.execute_reply.started":"2025-05-22T01:00:32.574079Z","shell.execute_reply":"2025-05-22T01:00:34.343080Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"<a id=\"2\"></a>\n<h1 style='background:#000000;border:0; color:black;\n    box-shadow: 10px 10px 5px 0px rgba(0,0,0,0.75);\n    transform: rotateX(10deg);\n    '><center style='color: #17E8C4;'>DATA LOADING</center></h1>","metadata":{}},{"cell_type":"code","source":"# Loading train_path file\ntrain_path = \"/kaggle/input/image-matching-challenge-2025/train\" ","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-22T01:00:34.344923Z","iopub.execute_input":"2025-05-22T01:00:34.345414Z","iopub.status.idle":"2025-05-22T01:00:34.350048Z","shell.execute_reply.started":"2025-05-22T01:00:34.345390Z","shell.execute_reply":"2025-05-22T01:00:34.349087Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_labels = pd.read_csv(\"/kaggle/input/image-matching-challenge-2025/train_labels.csv\")\ntrain_labels","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-22T01:00:34.352625Z","iopub.execute_input":"2025-05-22T01:00:34.352955Z","iopub.status.idle":"2025-05-22T01:00:34.446568Z","shell.execute_reply.started":"2025-05-22T01:00:34.352930Z","shell.execute_reply":"2025-05-22T01:00:34.445534Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"<a id=\"2\"></a>\n<h1 style='background:#000000;border:0; color:black;\n    box-shadow: 10px 10px 5px 0px rgba(0,0,0,0.75);\n    transform: rotateX(10deg);\n    '><center style='color: #17E8C4;'>EDA</center></h1>","metadata":{}},{"cell_type":"code","source":"train_labels.head()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-22T01:00:34.447622Z","iopub.execute_input":"2025-05-22T01:00:34.448000Z","iopub.status.idle":"2025-05-22T01:00:34.458644Z","shell.execute_reply.started":"2025-05-22T01:00:34.447968Z","shell.execute_reply":"2025-05-22T01:00:34.457593Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_labels.info","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-22T01:00:34.459762Z","iopub.execute_input":"2025-05-22T01:00:34.460029Z","iopub.status.idle":"2025-05-22T01:00:34.482265Z","shell.execute_reply.started":"2025-05-22T01:00:34.460009Z","shell.execute_reply":"2025-05-22T01:00:34.481425Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_labels.shape","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-22T01:00:34.483140Z","iopub.execute_input":"2025-05-22T01:00:34.483443Z","iopub.status.idle":"2025-05-22T01:00:34.503102Z","shell.execute_reply.started":"2025-05-22T01:00:34.483422Z","shell.execute_reply":"2025-05-22T01:00:34.502205Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_labels.describe().round(2).T","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-22T01:00:34.504154Z","iopub.execute_input":"2025-05-22T01:00:34.504409Z","iopub.status.idle":"2025-05-22T01:00:34.547590Z","shell.execute_reply.started":"2025-05-22T01:00:34.504389Z","shell.execute_reply":"2025-05-22T01:00:34.546666Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_labels.groupby(\"dataset\")[\"scene\"].nunique()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-22T01:00:34.548608Z","iopub.execute_input":"2025-05-22T01:00:34.548948Z","iopub.status.idle":"2025-05-22T01:00:34.562830Z","shell.execute_reply.started":"2025-05-22T01:00:34.548926Z","shell.execute_reply":"2025-05-22T01:00:34.561802Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"<a id=\"2\"></a>\n<h1 style='background:#000000;border:0; color:black;\n    box-shadow: 10px 10px 5px 0px rgba(0,0,0,0.75);\n    transform: rotateX(10deg);\n    '><center style='color: #17E8C4;'>DISTRIBUTION OF IMAGES</center></h1>","metadata":{}},{"cell_type":"code","source":"# Assuming train_labels is already loaded as a DataFrame\ndataset_counts = train_labels[\"dataset\"].value_counts()\n\n# Generate rainbow colors based on the number of datasets\ncolors = cm.rainbow(np.linspace(0, 1, len(dataset_counts)))\n\n# Plot with rainbow colors\nplt.figure(figsize=(12, 7))\ndataset_counts.plot(kind='bar', color=colors, edgecolor='black')\n\n# Plot formatting\nplt.title('Distribution of Images Across Datasets', fontsize=16, fontweight='bold')\nplt.xlabel('Dataset', fontsize=14)\nplt.ylabel('Number of Images', fontsize=14)\nplt.xticks(rotation=60, ha='right', fontsize=12)  \nplt.yticks(fontsize=12)\nplt.grid(axis='y', linestyle='--', alpha=0.7)\n\n# Display plot\nplt.tight_layout()\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-22T01:00:34.564221Z","iopub.execute_input":"2025-05-22T01:00:34.564553Z","iopub.status.idle":"2025-05-22T01:00:35.060168Z","shell.execute_reply.started":"2025-05-22T01:00:34.564533Z","shell.execute_reply":"2025-05-22T01:00:35.059022Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"<a id=\"2\"></a>\n<h1 style='background:#000000;border:0; color:black;\n    box-shadow: 10px 10px 5px 0px rgba(0,0,0,0.75);\n    transform: rotateX(10deg);\n    '><center style='color: #17E8C4;'>PLOTTING RANDOM IMAGES</center></h1>","metadata":{}},{"cell_type":"code","source":"def plot_random_images(scene_name, base_path=\"/kaggle/input/image-matching-challenge-2025/train\"):\n    scene_path = os.path.join(base_path, scene_name)\n    image_filenames = [f for f in os.listdir(scene_path) if f.endswith(('.png', '.jpg', '.jpeg'))]\n    random_images = random.sample(image_filenames, min(5, len(image_filenames)))\n    fig, axes = plt.subplots(1, len(random_images), figsize=(15, 5))\n    if len(random_images) == 1:\n        axes = [axes]\n\n    for ax, img_filename in zip(axes, random_images):\n        img_path = os.path.join(scene_path, img_filename)\n        img = Image.open(img_path)\n        ax.imshow(img)\n        ax.set_title(img_filename, fontsize=10)\n        ax.axis('off')\n    plt.tight_layout()\n    plt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-22T01:00:35.061351Z","iopub.execute_input":"2025-05-22T01:00:35.061660Z","iopub.status.idle":"2025-05-22T01:00:35.070917Z","shell.execute_reply.started":"2025-05-22T01:00:35.061638Z","shell.execute_reply":"2025-05-22T01:00:35.069948Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"plot_random_images(\"pt_sacrecoeur_trevi_tajmahal\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-22T01:00:35.071918Z","iopub.execute_input":"2025-05-22T01:00:35.072234Z","iopub.status.idle":"2025-05-22T01:00:36.490452Z","shell.execute_reply.started":"2025-05-22T01:00:35.072207Z","shell.execute_reply":"2025-05-22T01:00:36.489151Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"plot_random_images(\"amy_gardens\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-22T01:00:36.493461Z","iopub.execute_input":"2025-05-22T01:00:36.493832Z","iopub.status.idle":"2025-05-22T01:00:37.769418Z","shell.execute_reply.started":"2025-05-22T01:00:36.493807Z","shell.execute_reply":"2025-05-22T01:00:37.767859Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"plot_random_images(\"imc2023_heritage\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-22T01:00:37.770527Z","iopub.execute_input":"2025-05-22T01:00:37.770826Z","iopub.status.idle":"2025-05-22T01:00:49.042454Z","shell.execute_reply.started":"2025-05-22T01:00:37.770805Z","shell.execute_reply":"2025-05-22T01:00:49.041443Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"plot_random_images(\"fbk_vineyard\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-22T01:00:49.043713Z","iopub.execute_input":"2025-05-22T01:00:49.044038Z","iopub.status.idle":"2025-05-22T01:00:50.018972Z","shell.execute_reply.started":"2025-05-22T01:00:49.044016Z","shell.execute_reply":"2025-05-22T01:00:50.017658Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"plot_random_images(\"pt_piazzasanmarco_grandplace\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-22T01:00:50.020565Z","iopub.execute_input":"2025-05-22T01:00:50.021089Z","iopub.status.idle":"2025-05-22T01:00:51.076525Z","shell.execute_reply.started":"2025-05-22T01:00:50.021055Z","shell.execute_reply":"2025-05-22T01:00:51.075258Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"plot_random_images(\"imc2024_lizard_pond\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-22T01:00:51.077875Z","iopub.execute_input":"2025-05-22T01:00:51.078214Z","iopub.status.idle":"2025-05-22T01:00:52.561726Z","shell.execute_reply.started":"2025-05-22T01:00:51.078190Z","shell.execute_reply":"2025-05-22T01:00:52.560629Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_thresholds_path = \"../input/image-matching-challenge-2025/train_thresholds.csv\"\ntrain_thresholds = pd.read_csv(train_thresholds_path)\ntrain_thresholds.head() ","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-22T01:00:52.563242Z","iopub.execute_input":"2025-05-22T01:00:52.563553Z","iopub.status.idle":"2025-05-22T01:00:52.579788Z","shell.execute_reply.started":"2025-05-22T01:00:52.563530Z","shell.execute_reply":"2025-05-22T01:00:52.578756Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Describe thresholds data\ntrain_thresholds.describe().round(2).T","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-22T01:00:52.581152Z","iopub.execute_input":"2025-05-22T01:00:52.581569Z","iopub.status.idle":"2025-05-22T01:00:52.606415Z","shell.execute_reply.started":"2025-05-22T01:00:52.581536Z","shell.execute_reply":"2025-05-22T01:00:52.605574Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"<a id=\"2\"></a>\n<h1 style='background:#000000;border:0; color:black;\n    box-shadow: 10px 10px 5px 0px rgba(0,0,0,0.75);\n    transform: rotateX(10deg);\n    '><center style='color: #17E8C4;'>DISTRIBUTION OF SIMILARITY THRESHOLDS</center></h1>","metadata":{}},{"cell_type":"code","source":"import matplotlib.pyplot as plt\nimport numpy as np\nfrom matplotlib import cm\nfrom matplotlib.colors import Normalize\n\n# Step 1: Convert the \"thresholds\" column into a list of lists (split by \";\")\nthreshold_lists = train_thresholds[\"thresholds\"].apply(lambda x: list(map(float, x.split(\";\"))))\n\n# Step 2: Flatten the list\nall_thresholds = np.concatenate(threshold_lists.values)\n\n# Step 3: Create histogram data\ncounts, bins = np.histogram(all_thresholds, bins=30)\n\n# Normalize the bin centers for color mapping\nnorm = Normalize(vmin=min(bins), vmax=max(bins))\ncolors = cm.rainbow(norm((bins[:-1] + bins[1:]) / 2))\n\n# Step 4: Plot the colored histogram manually using bar\nplt.figure(figsize=(10, 6))\nfor i in range(len(bins) - 1):\n    plt.bar(bins[i], counts[i], width=bins[i+1]-bins[i], color=colors[i], edgecolor='black', align='edge')\n\n# Step 5: Formatting\nplt.xlabel(\"Score Threshold\", fontsize=12)\nplt.ylabel(\"Count\", fontsize=12)\nplt.title(\"Distribution of Similarity Thresholds\", fontsize=14, fontweight='bold')\nplt.grid(axis='y', linestyle='--', alpha=0.7)\nplt.tight_layout()\nplt.show()\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-22T01:00:52.607442Z","iopub.execute_input":"2025-05-22T01:00:52.607785Z","iopub.status.idle":"2025-05-22T01:00:52.905233Z","shell.execute_reply.started":"2025-05-22T01:00:52.607762Z","shell.execute_reply":"2025-05-22T01:00:52.904211Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"<a id=\"2\"></a>\n<h1 style='background:#000000;border:0; color:black;\n    box-shadow: 10px 10px 5px 0px rgba(0,0,0,0.75);\n    transform: rotateX(10deg);\n    '><center style='color: #17E8C4;'>RANDOM IMAGE MATCHING</center></h1>","metadata":{}},{"cell_type":"code","source":"# Scene and image selection\nscene_name = \"fountain\"\nscene_df = train_labels[train_labels[\"scene\"] == scene_name]\ndataset_name = scene_df[\"dataset\"].values[0]\nscene_images = scene_df[\"image\"].sample(n=2, random_state=42).values  # Random 2 images\n\n# Set image directory\nscene_path = os.path.join(train_path, dataset_name)\n\n# Initialize the figure\nfig, axes = plt.subplots(1, len(scene_images), figsize=(12, 6))\n\nfor i, img_name in enumerate(scene_images):\n    img_path = os.path.join(scene_path, img_name)\n\n    if not os.path.exists(img_path):\n        print(f\"Warning: Image {img_path} not found.\")\n        continue\n\n    img = cv2.imread(img_path, cv2.IMREAD_GRAYSCALE)\n\n    if img is None:\n        print(f\"Error reading image: {img_path}\")\n        continue\n\n    axes[i].imshow(img, cmap=\"gray\")\n    axes[i].set_title(f\"{img_name}\", fontsize=12)\n    axes[i].axis(\"off\")\n\n# Styling\nplt.suptitle(f\"Scene: {scene_name.capitalize()} (Random 2 Images)\", fontsize=16, fontweight=\"bold\")\nplt.tight_layout()\nplt.subplots_adjust(top=0.85)\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-22T01:00:52.906306Z","iopub.execute_input":"2025-05-22T01:00:52.906659Z","iopub.status.idle":"2025-05-22T01:00:53.936135Z","shell.execute_reply.started":"2025-05-22T01:00:52.906629Z","shell.execute_reply":"2025-05-22T01:00:53.935052Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"<a id=\"2\"></a>\n<h1 style='background:#000000;border:0; color:black;\n    box-shadow: 10px 10px 5px 0px rgba(0,0,0,0.75);\n    transform: rotateX(10deg);\n    '><center style='color: #17E8C4;'>IMAGE MATCHING TECHNIQUE</center></h1>","metadata":{}},{"cell_type":"code","source":"# Parameters\nscene_name = \"fountain\"\nnum_matches_to_display = 50\nrandom_state = 42\n\n# Get image filenames and dataset\nscene_df = train_labels[train_labels[\"scene\"] == scene_name]\ndataset_name = scene_df[\"dataset\"].values[0]\nscene_images = scene_df[\"image\"].sample(n=2, random_state=random_state).values\n\n# Build image paths\nimg1_path = os.path.join(train_path, dataset_name, scene_images[0])\nimg2_path = os.path.join(train_path, dataset_name, scene_images[1])\n\n# Load images in grayscale\nimg1 = cv2.imread(img1_path, cv2.IMREAD_GRAYSCALE)\nimg2 = cv2.imread(img2_path, cv2.IMREAD_GRAYSCALE)\n\n# Validate loading\nif img1 is None or img2 is None:\n    raise FileNotFoundError(\"One or both images could not be loaded. Check paths.\")\n\n# ORB Detector\norb = cv2.ORB_create(nfeatures=1000)\n\n# Detect keypoints and descriptors\nkp1, des1 = orb.detectAndCompute(img1, None)\nkp2, des2 = orb.detectAndCompute(img2, None)\n\n# Brute Force Matcher (Hamming for ORB)\nbf = cv2.BFMatcher(cv2.NORM_HAMMING, crossCheck=True)\nmatches = bf.match(des1, des2)\n\n# Sort by distance\nmatches = sorted(matches, key=lambda x: x.distance)\n\n# Draw top N matches\nmatched_img = cv2.drawMatches(\n    img1, kp1, img2, kp2, matches[:num_matches_to_display], None,\n    flags=cv2.DrawMatchesFlags_NOT_DRAW_SINGLE_POINTS\n)\n\n# Plot\nplt.figure(figsize=(14, 7))\nplt.imshow(matched_img, cmap='gray')\nplt.title(f\"ORB Feature Matching (Top {num_matches_to_display} Matches)\\nScene: {scene_name.capitalize()}\")\nplt.axis(\"off\")\nplt.tight_layout()\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-22T01:00:53.937144Z","iopub.execute_input":"2025-05-22T01:00:53.937423Z","iopub.status.idle":"2025-05-22T01:00:55.471170Z","shell.execute_reply.started":"2025-05-22T01:00:53.937403Z","shell.execute_reply":"2025-05-22T01:00:55.470071Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"<a id=\"2\"></a>\n<h1 style='background:#000000;border:0; color:black;\n    box-shadow: 10px 10px 5px 0px rgba(0,0,0,0.75);\n    transform: rotateX(10deg);\n    '><center style='color: #17E8C4;'>SUBMISSION</center></h1>","metadata":{}},{"cell_type":"code","source":"# Load sample submission template\nsubmission_path = \"/kaggle/input/image-matching-challenge-2025/sample_submission.csv\"\nsample_submission = pd.read_csv(submission_path)\n\n# Define dummy values\nidentity_matrix = \"1;0;0;0;1;0;0;0;1\"   # 3x3 identity matrix (row-major)\nzero_vector = \"0;0;0\"                  # zero translation vector\n\n# Fill the columns with dummy values\nsample_submission[\"rotation_matrix\"] = identity_matrix\nsample_submission[\"translation_vector\"] = zero_vector\n\n# Save the submission file\noutput_file = \"submission.csv\"\nsample_submission.to_csv(output_file, index=False)\n\nprint(f\"Dummy submission file saved as: {output_file}\")\nprint(f\"Entries: {len(sample_submission)} | Format: Identity rotation, zero translation\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-22T01:00:55.472245Z","iopub.execute_input":"2025-05-22T01:00:55.472550Z","iopub.status.idle":"2025-05-22T01:00:55.537919Z","shell.execute_reply.started":"2025-05-22T01:00:55.472528Z","shell.execute_reply":"2025-05-22T01:00:55.536939Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null}]}