{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.10.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":91498,"databundleVersionId":11655853,"sourceType":"competition"}],"dockerImageVersionId":30918,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"# <center style=\"font-family: consolas; font-size: 32px; font-weight: bold;\"> 📸 Image Matching Challenge - 📊 Exploratory Data Analysis</center>\n<p><center style=\"color:#949494; font-family: consolas; font-size: 20px;\">Reconstruct 3D scenes from 2D images over six different domains</center></p>\n\n***\n\nThe objectives of this competition are to:\n- Construct precise 3D maps using sets of images in diverse scenarios and environments by developing **a model to generate accurate spatial representations, regardless of the source domain** \n    - The process of reconstructing a 3D model of an environment from a collection of images is called **Structure from Motion (SfM)**. \n    - These images are often captured by trained operators or with additional sensor data. \n    - This ensures homogeneous, high-quality data. \n- Explore various image sources in more realistic and applicable scenarios: images can be taken from drones 🤖, amidst dense forests 🌲, during nighttime 🌙\n    - It’s much more difficult to build 3D models from assorted images, the real-world examples that the organizers put together for this competition.\n \n\nFor this, the organizers have designated 6 categories of images with distinct challenges:\n- 🏛️ **Phototourism and historical preservation**: different viewpoints, sensor types, time of day/year, and occlusions. Ancient historical sites add a unique set of challenges\n\n- ☀️ **Night vs day and temporal changes**: combination of day and night photographs, including poor lighting, or photographs taken months or years apart, in different weather\n\n- ✈️ **Aerial and mixed aerial-ground**: images from drones, featuring arbitrary in-plane rotations, matched against similar images and also images taken from the ground\n\n- ♻️ **Repeated structures**: symmetrical objects require details to disambiguate perspective\n\n- 🌲 **Natural environments**: highly non-regular structures such as trees and foliage\n\n- 🪞 **Transparencies and reflections**: objects like glassware are lacking in texture and create reflections and specularities which pose a different set of problems\n\n\nInspired by [this notebook](https://www.kaggle.com/code/asarvazyan/eda-imc-interact-w-3d-plots-locations) from previous year's edition of the competition.","metadata":{}},{"cell_type":"markdown","source":"<a id=\"0\"></a>\n# Install & Import dependencies","metadata":{"_kg_hide-input":false}},{"cell_type":"code","source":"!pip install -q mediapy","metadata":{"_kg_hide-input":true,"_kg_hide-output":true,"execution":{"iopub.status.busy":"2025-04-01T21:40:18.979767Z","iopub.execute_input":"2025-04-01T21:40:18.980129Z","iopub.status.idle":"2025-04-01T21:40:31.357432Z","shell.execute_reply.started":"2025-04-01T21:40:18.980093Z","shell.execute_reply":"2025-04-01T21:40:31.356190Z"},"trusted":true},"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":{"_kg_hide-input":true,"_kg_hide-output":true,"execution":{"iopub.status.busy":"2025-04-01T21:40:31.358848Z","iopub.execute_input":"2025-04-01T21:40:31.359167Z","iopub.status.idle":"2025-04-01T21:41:14.718417Z","shell.execute_reply.started":"2025-04-01T21:40:31.359138Z","shell.execute_reply":"2025-04-01T21:41:14.717241Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from pathlib import Path\n\nimport cv2\nimport mediapy\nimport pandas as pd\nimport plotly.express as px\nimport pycolmap\nimport os\nimport random\nfrom PIL import Image\nimport matplotlib.pyplot as plt","metadata":{"_kg_hide-input":true,"_kg_hide-output":true,"execution":{"iopub.status.busy":"2025-04-01T21:41:14.720862Z","iopub.execute_input":"2025-04-01T21:41:14.721322Z","iopub.status.idle":"2025-04-01T21:41:16.314158Z","shell.execute_reply.started":"2025-04-01T21:41:14.721261Z","shell.execute_reply":"2025-04-01T21:41:16.313307Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"<a id=\"1\"></a>\n# Dataset Overview","metadata":{}},{"cell_type":"markdown","source":"- `[train/test]/*/images`: A batch of images all taken near the same location. Some of training datasets may also contain a folder named images_full with additional images. The published test folder comprises a subset of the church scene from train and is provided solely for example purposes. The training data usually has a sequential capture ordering and significant image-to-image content overlap while the test set has limited image-to-image overlap and the image ordering is randomized.\n\n- `train/*/LICENSE.txt`: The license for this dataset.\n\n- `train/train_labels.csv`: A list of images in these datasets, with ground truths.","metadata":{}},{"cell_type":"markdown","source":"### 1️⃣ Lets inspect `train/train_labels.csv`","metadata":{}},{"cell_type":"markdown","source":"- `dataset`: The unique identifier for the dataset.\n- `scene`: The unique identifier for the scene.\n- `image_path`: The image filename, including the path.\n- `rotation_matrix`: The first target column. A 3x3 matrix, flattened into a vector in row-major convention, with values separated by `;`.\n- `translation_vector`: The second target column. A 3-D dimensional vector, with values separated by ;.","metadata":{}},{"cell_type":"code","source":"train_labels = pd.read_csv(\"/kaggle/input/image-matching-challenge-2025/train_labels.csv\")\ntrain_labels","metadata":{"execution":{"iopub.status.busy":"2025-04-01T21:41:46.895176Z","iopub.execute_input":"2025-04-01T21:41:46.895588Z","iopub.status.idle":"2025-04-01T21:41:46.943213Z","shell.execute_reply.started":"2025-04-01T21:41:46.895549Z","shell.execute_reply":"2025-04-01T21:41:46.942075Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"### 2️⃣ What is the relationship between datasets and scenes?","metadata":{}},{"cell_type":"code","source":"train_labels.groupby(\"dataset\")[\"scene\"].nunique()","metadata":{"execution":{"iopub.status.busy":"2025-04-01T21:41:53.888761Z","iopub.execute_input":"2025-04-01T21:41:53.889136Z","iopub.status.idle":"2025-04-01T21:41:53.906082Z","shell.execute_reply.started":"2025-04-01T21:41:53.889106Z","shell.execute_reply":"2025-04-01T21:41:53.904786Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"### 3️⃣ What is the distribution of the datasets?","metadata":{}},{"cell_type":"code","source":"dataset_counts = train_labels[\"dataset\"].value_counts()\n\nplt.figure(figsize=(12, 7))\ndataset_counts.plot(kind='bar', color='skyblue', edgecolor='black')\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)\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2025-04-01T22:09:39.528141Z","iopub.execute_input":"2025-04-01T22:09:39.528563Z","iopub.status.idle":"2025-04-01T22:09:39.881547Z","shell.execute_reply.started":"2025-04-01T22:09:39.528533Z","shell.execute_reply":"2025-04-01T22:09:39.880501Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"<a id=\"2\"></a>\n# Exploring each dataset","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()\n","metadata":{"_kg_hide-input":true,"_kg_hide-output":true,"execution":{"iopub.status.busy":"2025-04-01T22:11:15.891375Z","iopub.execute_input":"2025-04-01T22:11:15.892342Z","iopub.status.idle":"2025-04-01T22:11:15.899898Z","shell.execute_reply.started":"2025-04-01T22:11:15.892272Z","shell.execute_reply":"2025-04-01T22:11:15.898571Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"<a id=\"stairs\"></a>\n## 1️⃣ stairs","metadata":{}},{"cell_type":"code","source":"plot_random_images(\"stairs\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-01T22:11:44.011727Z","iopub.execute_input":"2025-04-01T22:11:44.012093Z","iopub.status.idle":"2025-04-01T22:11:45.826436Z","shell.execute_reply.started":"2025-04-01T22:11:44.012066Z","shell.execute_reply":"2025-04-01T22:11:45.825382Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"<a id=\"pt_stpeters_stpauls\"></a>\n## 2️⃣ pt_stpeters_stpauls","metadata":{}},{"cell_type":"code","source":"plot_random_images(\"pt_stpeters_stpauls\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-01T22:12:31.807575Z","iopub.execute_input":"2025-04-01T22:12:31.807954Z","iopub.status.idle":"2025-04-01T22:12:33.027165Z","shell.execute_reply.started":"2025-04-01T22:12:31.807925Z","shell.execute_reply":"2025-04-01T22:12:33.026115Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"<a id=\"pt_sacrecoeur_trevi_tajmahal\"></a>\n## 3️⃣ pt_sacrecoeur_trevi_tajmahal","metadata":{}},{"cell_type":"code","source":"plot_random_images(\"pt_sacrecoeur_trevi_tajmahal\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-01T22:12:53.855555Z","iopub.execute_input":"2025-04-01T22:12:53.855992Z","iopub.status.idle":"2025-04-01T22:12:55.369238Z","shell.execute_reply.started":"2025-04-01T22:12:53.855964Z","shell.execute_reply":"2025-04-01T22:12:55.368026Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"<a id=\"pt_piazzasanmarco_grandplace\"></a>\n## 4️⃣ pt_piazzasanmarco_grandplace","metadata":{}},{"cell_type":"code","source":"plot_random_images(\"pt_piazzasanmarco_grandplace\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-01T22:13:16.015409Z","iopub.execute_input":"2025-04-01T22:13:16.015832Z","iopub.status.idle":"2025-04-01T22:13:17.451779Z","shell.execute_reply.started":"2025-04-01T22:13:16.015803Z","shell.execute_reply":"2025-04-01T22:13:17.450606Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"<a id=\"pt_brandenburg_british_buckingham\"></a>\n## 5️⃣ pt_brandenburg_british_buckingham","metadata":{}},{"cell_type":"code","source":"plot_random_images(\"pt_brandenburg_british_buckingham\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-01T22:13:43.326838Z","iopub.execute_input":"2025-04-01T22:13:43.327224Z","iopub.status.idle":"2025-04-01T22:13:44.659672Z","shell.execute_reply.started":"2025-04-01T22:13:43.327195Z","shell.execute_reply":"2025-04-01T22:13:44.658631Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"<a id=\"imc2024_lizard_pond\"></a>\n## 6️⃣ imc2024_lizard_pond","metadata":{}},{"cell_type":"code","source":"plot_random_images(\"imc2024_lizard_pond\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-01T22:13:58.757103Z","iopub.execute_input":"2025-04-01T22:13:58.758053Z","iopub.status.idle":"2025-04-01T22:14:00.128415Z","shell.execute_reply.started":"2025-04-01T22:13:58.758017Z","shell.execute_reply":"2025-04-01T22:14:00.127198Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"<a id=\"imc2024_dioscuri_baalshamin\"></a>\n## 7️⃣ imc2024_dioscuri_baalshamin","metadata":{}},{"cell_type":"code","source":"plot_random_images(\"imc2024_dioscuri_baalshamin\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-01T22:14:18.815585Z","iopub.execute_input":"2025-04-01T22:14:18.815966Z","iopub.status.idle":"2025-04-01T22:14:21.989218Z","shell.execute_reply.started":"2025-04-01T22:14:18.815937Z","shell.execute_reply":"2025-04-01T22:14:21.988218Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"<a id=\"imc2023_theather_imc2024_church\"></a>\n## 8️⃣ imc2023_theather_imc2024_church","metadata":{}},{"cell_type":"code","source":"plot_random_images(\"imc2023_theather_imc2024_church\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-01T22:16:51.713416Z","iopub.execute_input":"2025-04-01T22:16:51.713723Z","iopub.status.idle":"2025-04-01T22:16:53.100921Z","shell.execute_reply.started":"2025-04-01T22:16:51.713698Z","shell.execute_reply":"2025-04-01T22:16:53.099756Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"<a id=\"imc2023_heritage\"></a>\n## 9️⃣ imc2023_heritage","metadata":{}},{"cell_type":"code","source":"plot_random_images(\"imc2023_heritage\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-01T22:16:37.560555Z","iopub.execute_input":"2025-04-01T22:16:37.560947Z","iopub.status.idle":"2025-04-01T22:16:51.711735Z","shell.execute_reply.started":"2025-04-01T22:16:37.560918Z","shell.execute_reply":"2025-04-01T22:16:51.710597Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"<a id=\"imc2023_haiper\"></a>\n## 1️⃣0️⃣ imc2023_haiper","metadata":{}},{"cell_type":"code","source":"plot_random_images(\"imc2023_haiper\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-01T22:16:27.144681Z","iopub.execute_input":"2025-04-01T22:16:27.145064Z","iopub.status.idle":"2025-04-01T22:16:30.224904Z","shell.execute_reply.started":"2025-04-01T22:16:27.145035Z","shell.execute_reply":"2025-04-01T22:16:30.223753Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"<a id=\"fbk_vineyard\"></a>\n## 1️⃣1️⃣ fbk_vineyard","metadata":{}},{"cell_type":"code","source":"plot_random_images(\"fbk_vineyard\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-01T22:16:07.921337Z","iopub.execute_input":"2025-04-01T22:16:07.922224Z","iopub.status.idle":"2025-04-01T22:16:09.521356Z","shell.execute_reply.started":"2025-04-01T22:16:07.922185Z","shell.execute_reply":"2025-04-01T22:16:09.520200Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"<a id=\"amy_gardens\"></a>\n## 1️⃣2️⃣ amy_gardens","metadata":{}},{"cell_type":"code","source":"plot_random_images(\"amy_gardens\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-01T22:16:14.165551Z","iopub.execute_input":"2025-04-01T22:16:14.165908Z","iopub.status.idle":"2025-04-01T22:16:15.422386Z","shell.execute_reply.started":"2025-04-01T22:16:14.165882Z","shell.execute_reply":"2025-04-01T22:16:15.420653Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"<a id=\"ETs\"></a>\n## 1️⃣3️⃣ ETs","metadata":{}},{"cell_type":"code","source":"plot_random_images(\"ETs\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-01T22:19:58.269269Z","iopub.execute_input":"2025-04-01T22:19:58.269690Z","iopub.status.idle":"2025-04-01T22:19:59.335934Z","shell.execute_reply.started":"2025-04-01T22:19:58.269662Z","shell.execute_reply":"2025-04-01T22:19:59.334833Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Work in progress!","metadata":{}},{"cell_type":"markdown","source":"❤️ Thank you for taking the time to read through my notebook. I hope you found it interesting and informative. If you have any feedback or suggestions for improvement, please don't hesitate to let me know in the comments.","metadata":{}}]}