{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"# This Python 3 environment comes with many helpful analytics libraries installed\n# It is defined by the kaggle/python Docker image: https://github.com/kaggle/docker-python\n# For example, here's several helpful packages to load\n\nimport matplotlib.pyplot as plt\nimport numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\n\nimport matplotlib.image as mpimg\nimport cv2\n\n\n# Input data files are available in the read-only \"../input/\" directory\n# For example, running this (by clicking run or pressing Shift+Enter) will list all files under the input directory\n\nimport os\nfor dirname, _, filenames in os.walk('/kaggle/input'):\n    for filename in filenames:\n        print(os.path.join(dirname, filename))\n\n# You can write up to 20GB to the current directory (/kaggle/working/) that gets preserved as output when you create a version using \"Save & Run All\" \n# You can also write temporary files to /kaggle/temp/, but they won't be saved outside of the current session","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2023-06-03T15:05:48.199396Z","iopub.execute_input":"2023-06-03T15:05:48.199801Z","iopub.status.idle":"2023-06-03T15:05:50.930881Z","shell.execute_reply.started":"2023-06-03T15:05:48.199768Z","shell.execute_reply":"2023-06-03T15:05:50.929762Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"**################## Data Exploration #########################** ","metadata":{}},{"cell_type":"markdown","source":"The train_labels.csv file will be saved in \"train_labels_df\"","metadata":{}},{"cell_type":"code","source":"train_labels_df = pd.read_csv(\"/kaggle/input/image-matching-challenge-2023/train/train_labels.csv\")","metadata":{"execution":{"iopub.status.busy":"2023-06-03T15:05:50.933335Z","iopub.execute_input":"2023-06-03T15:05:50.933713Z","iopub.status.idle":"2023-06-03T15:05:50.959462Z","shell.execute_reply.started":"2023-06-03T15:05:50.933682Z","shell.execute_reply":"2023-06-03T15:05:50.958594Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_labels_df.head()","metadata":{"execution":{"iopub.status.busy":"2023-06-03T15:05:50.965689Z","iopub.execute_input":"2023-06-03T15:05:50.966049Z","iopub.status.idle":"2023-06-03T15:05:51.001167Z","shell.execute_reply.started":"2023-06-03T15:05:50.966018Z","shell.execute_reply":"2023-06-03T15:05:50.999622Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_labels_df.describe()","metadata":{"execution":{"iopub.status.busy":"2023-06-03T15:05:51.002848Z","iopub.execute_input":"2023-06-03T15:05:51.003729Z","iopub.status.idle":"2023-06-03T15:05:51.039472Z","shell.execute_reply.started":"2023-06-03T15:05:51.003693Z","shell.execute_reply":"2023-06-03T15:05:51.038563Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"**What about Dataset?**","metadata":{}},{"cell_type":"code","source":"dataset_counts = train_labels_df['dataset'].value_counts(normalize=True)\n\nplt.figure(figsize=(5, 5))\nplt.pie(dataset_counts, labels=dataset_counts.index, autopct='%1.2f%%', startangle=45, wedgeprops=dict(width=0.4))\nplt.axis('equal')  # Aspecto circular\nplt.title('\"Dataset\" composition')\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2023-06-03T15:05:51.040996Z","iopub.execute_input":"2023-06-03T15:05:51.041767Z","iopub.status.idle":"2023-06-03T15:05:51.290814Z","shell.execute_reply.started":"2023-06-03T15:05:51.041732Z","shell.execute_reply":"2023-06-03T15:05:51.289375Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"**What about Scene?**","metadata":{}},{"cell_type":"code","source":"dataset_counts = train_labels_df['scene'].value_counts(normalize=True)\n\nplt.figure(figsize=(5, 5))\nplt.pie(dataset_counts, labels=dataset_counts.index, autopct='%1.2f%%', startangle=45, wedgeprops=dict(width=0.4))\nplt.axis('equal')  # Aspecto circular\nplt.title('\"Scene\" composition')\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2023-06-03T15:05:51.293123Z","iopub.execute_input":"2023-06-03T15:05:51.293937Z","iopub.status.idle":"2023-06-03T15:05:51.554834Z","shell.execute_reply.started":"2023-06-03T15:05:51.293883Z","shell.execute_reply":"2023-06-03T15:05:51.553416Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"**\"What about Dataset:heritage\"?**","metadata":{}},{"cell_type":"code","source":"# Distribution of images per scene\ncontingency_table = pd.crosstab(train_labels_df['dataset'], train_labels_df['scene'])\n\n# Configuración de estilo\nplt.style.use('seaborn-whitegrid')\ncolors = ['#ff796f', '#e0ec59', '#36addf', '#316e89', '#9753aa', '#79b45c', '#ed4c40']\n\n# Crear gráfico de barras apiladas\nfig, ax = plt.subplots(figsize=(10, 6))\ncontingency_table.plot(kind='bar', stacked=True, color=colors, ax=ax)\n\n# Configuración del gráfico\nax.set_xlabel('Dataset', fontsize=12)\nax.set_ylabel('Count', fontsize=12)\nax.set_title('Proportions of Dataset by Scene', fontsize=14, fontweight='bold')\n\n# Ajustar margen\nplt.tight_layout()\n\n# Mostrar el gráfico\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2023-06-03T15:05:51.557038Z","iopub.execute_input":"2023-06-03T15:05:51.557930Z","iopub.status.idle":"2023-06-03T15:05:52.123679Z","shell.execute_reply.started":"2023-06-03T15:05:51.557876Z","shell.execute_reply":"2023-06-03T15:05:52.122625Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"**Process Dataset**","metadata":{}},{"cell_type":"code","source":"submission_data = pd.read_csv('/kaggle/input/image-matching-challenge-2023/sample_submission.csv')\nsubmission_data.head()\n\n","metadata":{"execution":{"iopub.status.busy":"2023-06-03T15:05:52.125233Z","iopub.execute_input":"2023-06-03T15:05:52.125869Z","iopub.status.idle":"2023-06-03T15:05:52.144652Z","shell.execute_reply.started":"2023-06-03T15:05:52.125839Z","shell.execute_reply":"2023-06-03T15:05:52.143895Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"data = train_labels_df.loc[(train_labels_df['dataset'] == 'haiper') & (train_labels_df['scene'] == 'fountain')]\ndisplay(data.columns.tolist())","metadata":{"execution":{"iopub.status.busy":"2023-06-03T15:05:52.148271Z","iopub.execute_input":"2023-06-03T15:05:52.148978Z","iopub.status.idle":"2023-06-03T15:05:52.158025Z","shell.execute_reply.started":"2023-06-03T15:05:52.148946Z","shell.execute_reply":"2023-06-03T15:05:52.157295Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"paths = []\nfiles = []\n\n# Lista de rutas de las imágenes\nfor dirname, _, filenames in os.walk('/kaggle/input/image-matching-challenge-2023/train/haiper/fountain/images'):\n  for filename in filenames:\n    paths+= [(os.path.join(dirname, filename))]\n    files+= [filename]\n    \n# Mostrar las imágenes\nfig, axs = plt.subplots(4,6, figsize=(12,12))\nfor i, ax in enumerate(axs.flat):\n  if i < len(paths):\n    img = mpimg.imread(paths[i])\n    ax.imshow(img)\n  ax.axis('off')\n\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2023-06-03T15:05:52.159375Z","iopub.execute_input":"2023-06-03T15:05:52.159880Z","iopub.status.idle":"2023-06-03T15:06:02.521951Z","shell.execute_reply.started":"2023-06-03T15:05:52.159852Z","shell.execute_reply":"2023-06-03T15:06:02.519610Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Lista para almacenar los keypoints y descriptores de las imágenes anteriores\nprev_keypoints = []\nprev_descriptors = None\n\n# Función para estimar la matriz de rotación y el vector de traslación\ndef estimate_pose(image_path):\n    global prev_keypoints, prev_descriptors\n    \n    # Cargar la imagen\n    image = cv2.imread(image_path)\n    \n    # Convertir la imagen a escala de grises\n    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)\n    \n    # Detectar características visuales en la imagen utilizando ORB\n    orb = cv2.ORB_create()\n    keypoints, descriptors = orb.detectAndCompute(gray, None)\n    \n    # Verificar si hay descriptores válidos\n    if descriptors is None:\n        return None, None\n    \n    # Verificar si hay descriptores anteriores\n    if prev_descriptors is not None:\n        # Emparejar características con la imagen anterior\n        bf = cv2.BFMatcher(cv2.NORM_HAMMING, crossCheck=True)\n        matches = bf.match(descriptors, prev_descriptors)\n        \n        # Ordenar los emparejamientos por distancia\n        matches = sorted(matches, key=lambda x: x.distance)\n        \n        # Obtener los puntos de interés emparejados en la imagen actual y en la imagen anterior\n        matched_points_current = np.float32([keypoints[m.queryIdx].pt for m in matches]).reshape(-1, 1, 2)\n        matched_points_prev = np.float32([prev_keypoints[m.trainIdx].pt for m in matches]).reshape(-1, 1, 2)\n        \n        # Estimar la matriz de transformación utilizando RANSAC\n        _, mask = cv2.findHomography(matched_points_prev, matched_points_current, cv2.RANSAC, 5.0)\n        \n        # Filtrar los puntos emparejados utilizando el resultado del RANSAC\n        matched_points_current = matched_points_current[mask.ravel() == 1]\n        matched_points_prev = matched_points_prev[mask.ravel() == 1]\n        \n        # Estimar la matriz de rotación y el vector de traslación utilizando la matriz de transformación\n        essential_matrix, _ = cv2.findEssentialMat(matched_points_prev, matched_points_current, focal=1.0, pp=(0, 0))\n        _, rotation_matrix, translation_vector, _ = cv2.recoverPose(essential_matrix, matched_points_prev, matched_points_current)\n        \n        # Actualizar los keypoints y descriptores anteriores\n        prev_keypoints = keypoints\n        prev_descriptors = descriptors\n        \n        # Devolver la matriz de rotación y el vector de traslación estimados\n        return rotation_matrix, translation_vector\n    \n    # Actualizar los keypoints y descriptores anteriores\n    prev_keypoints = keypoints\n    prev_descriptors = descriptors\n    \n    # Si no hay descriptores anteriores, devolver valores nulos\n    return None, None\n\n\n# Lista de rutas de las imágenes se corrió líneas arriba las listas paths = [] y files = [].\n\n# Estimar los vectores de rotación y traslación para cada imagen\nfor i, image_path in enumerate(paths):\n    rotation_matrix, translation_vector = estimate_pose(image_path)\n    \n    # Imprimir los resultados\n    print(f\"Imagen {i+1}:\")\n    print(\"Matriz de Rotación:\")\n    print(rotation_matrix)\n    print(\"Vector de Traslación:\")\n    print(translation_vector)\n    print(\"--------------------\")","metadata":{"execution":{"iopub.status.busy":"2023-06-03T15:31:07.356067Z","iopub.execute_input":"2023-06-03T15:31:07.356530Z","iopub.status.idle":"2023-06-03T15:31:11.701564Z","shell.execute_reply.started":"2023-06-03T15:31:07.356480Z","shell.execute_reply":"2023-06-03T15:31:11.700338Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}