{"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":"gpu","dataSources":[{"sourceId":71885,"databundleVersionId":8143495,"sourceType":"competition"},{"sourceId":7884485,"sourceType":"datasetVersion","datasetId":4628051},{"sourceId":7884725,"sourceType":"datasetVersion","datasetId":4628331},{"sourceId":8539410,"sourceType":"datasetVersion","datasetId":5101247},{"sourceId":8560092,"sourceType":"datasetVersion","datasetId":5075608},{"sourceId":8794891,"sourceType":"datasetVersion","datasetId":5288222}],"dockerImageVersionId":30699,"isInternetEnabled":false,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"# Install dependency","metadata":{"_uuid":"a911e3c6-6d34-476f-af70-76dd2fac67e3","_cell_guid":"7ae7d42a-f603-4f70-ab64-2a76f283bd2a","trusted":true}},{"cell_type":"code","source":"!pip install --no-index /kaggle/input/imc2024-packages-lightglue-rerun-kornia/* --no-deps","metadata":{"_uuid":"05ca7f86-8a6f-4478-a551-c8f51f380dd0","_cell_guid":"5c9e8633-ec8b-4d77-96a6-5770570d4c13","collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2024-10-09T15:19:47.473084Z","iopub.execute_input":"2024-10-09T15:19:47.473504Z","iopub.status.idle":"2024-10-09T15:19:51.928256Z","shell.execute_reply.started":"2024-10-09T15:19:47.473477Z","shell.execute_reply":"2024-10-09T15:19:51.927026Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!mkdir -p /root/.cache/torch\n!cp -r /kaggle/input/hierarchical-localization/hub /root/.cache/torch\n!cp -r /kaggle/input/sfd2-semantic-guidedfeaturedetectionanddescription/weights ./","metadata":{"_uuid":"893cc524-db5a-4b16-9cfa-6a252852b824","_cell_guid":"106ca542-a56f-4510-b51d-fef171458a03","collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2024-10-09T15:19:51.930511Z","iopub.execute_input":"2024-10-09T15:19:51.930849Z","iopub.status.idle":"2024-10-09T15:20:14.719637Z","shell.execute_reply.started":"2024-10-09T15:19:51.930818Z","shell.execute_reply":"2024-10-09T15:20:14.718212Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import sys\nsys.path.append(\"/kaggle/input/hierarchical-localization\")\nsys.path.append(\"/kaggle/input/hierarchical-localization/third_party\")\nsys.path.append(\"/kaggle/input/sfd2-semantic-guidedfeaturedetectionanddescription\")","metadata":{"_uuid":"9750cb3f-173c-48cf-a85d-b32f9badcc0d","_cell_guid":"342a9f77-960e-4f92-bebe-31101a8439de","collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2024-10-09T15:20:14.721362Z","iopub.execute_input":"2024-10-09T15:20:14.721755Z","iopub.status.idle":"2024-10-09T15:20:14.727562Z","shell.execute_reply.started":"2024-10-09T15:20:14.721716Z","shell.execute_reply":"2024-10-09T15:20:14.726542Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import tqdm, tqdm.notebook\ntqdm.tqdm = tqdm.notebook.tqdm  # notebook-friendly progress bars\nfrom pathlib import Path\n\nfrom hloc import (\n    pairs_from_exhaustive, pairs_from_retrieval, \n    extract_features, \n    match_features, match_dense, \n    reconstruction, \n    visualization, \n)\nfrom hloc.visualization import plot_images, read_image\nfrom hloc.utils import viz_3d\n\nimport extract_localization as extract_features_sfd2\n\nimport pycolmap\nimport gc\nimport numpy as np\nfrom copy import deepcopy","metadata":{"_uuid":"1bc471ae-bbad-4345-8f33-59e00f488656","_cell_guid":"5727006c-e4c3-4217-a454-a64fc2a60a43","collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2024-10-09T15:20:14.729803Z","iopub.execute_input":"2024-10-09T15:20:14.730119Z","iopub.status.idle":"2024-10-09T15:20:21.647401Z","shell.execute_reply.started":"2024-10-09T15:20:14.730095Z","shell.execute_reply":"2024-10-09T15:20:21.646421Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Preprocess","metadata":{"_uuid":"29d56477-e8c3-4bc5-9cc2-8f46d213e6fa","_cell_guid":"2a21ed78-2737-4a1e-ace0-3f486f704f64","trusted":true}},{"cell_type":"code","source":"# Rotation Correction, Color Correction, etc.","metadata":{"_uuid":"52da76fb-996b-48e9-9734-f5442e08e964","_cell_guid":"4170634d-b9c5-4c92-bea7-2fd2b7afcb13","collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2024-10-09T15:20:21.648857Z","iopub.execute_input":"2024-10-09T15:20:21.649293Z","iopub.status.idle":"2024-10-09T15:20:21.653227Z","shell.execute_reply.started":"2024-10-09T15:20:21.649266Z","shell.execute_reply":"2024-10-09T15:20:21.652166Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# SfM Pipeline","metadata":{"_uuid":"51e90ea1-2eb8-4018-9fac-6535ee9064f8","_cell_guid":"4230468a-acf9-44a2-a1a0-5942f0216f52","trusted":true}},{"cell_type":"code","source":"config = {\n    \"retrieval_conf\": \"netvlad\", # {\"dir\", \"netvlad\", \"openibl\", \"eigenplaces\"}\n    \"feature_conf\": \"aliked-n16-rot\", # {\"superpoint_aachen\", \"superpoint_max\", \"superpoint_inloc\", \"r2d2\", \"d2net-ss\", \"sift\", \"sosnet\", \"disk\", \"aliked-n16-rot\", \"aliked-n32\"}\n    \"feature_conf_sfd2\": \"ressegnetv2-20220810-wapv2-sd2mfsf-uspg-0001-n4096-r1024\", \n    \"match_method\": \"dense\", # {\"feature\", \"dense\"}\n    \"matcher_conf_feature\": \"aliked+lightglue\", # {\"superpoint+lightglue\", \"disk+lightglue\", \"superglue\", \"superglue-fast\", \"NN-superpoint\", \"NN-ratio\", \"NN-mutual\", \"adalam\", \"aliked+lightglue\"}\n    \"matcher_conf_dense\": \"loftr\", # {\"loftr\", \"loftr_aachen\", \"loftr_superpoint\"}\n}","metadata":{"_uuid":"c9a50f11-6f8a-4b61-af22-baf248074e2e","_cell_guid":"fc3861c7-2790-484d-8fe4-fd966587e2d8","collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2024-10-09T15:20:21.654447Z","iopub.execute_input":"2024-10-09T15:20:21.654745Z","iopub.status.idle":"2024-10-09T15:20:21.663930Z","shell.execute_reply.started":"2024-10-09T15:20:21.654720Z","shell.execute_reply":"2024-10-09T15:20:21.663002Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"extract_features.confs[config[\"retrieval_conf\"]]","metadata":{"_uuid":"8d874940-7375-4513-aa79-1f6eed8356e2","_cell_guid":"6fd605cd-7b08-4887-b846-b57393727e9c","collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2024-10-09T15:20:21.664963Z","iopub.execute_input":"2024-10-09T15:20:21.665265Z","iopub.status.idle":"2024-10-09T15:20:21.675581Z","shell.execute_reply.started":"2024-10-09T15:20:21.665242Z","shell.execute_reply":"2024-10-09T15:20:21.674739Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"extract_features.confs[config[\"feature_conf\"]]","metadata":{"_uuid":"ab3764d7-0e87-4d9e-a055-666c4b65e47e","_cell_guid":"5fe21c28-908b-4a35-97d5-848c25fec722","collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2024-10-09T15:20:21.676870Z","iopub.execute_input":"2024-10-09T15:20:21.677156Z","iopub.status.idle":"2024-10-09T15:20:21.685235Z","shell.execute_reply.started":"2024-10-09T15:20:21.677134Z","shell.execute_reply":"2024-10-09T15:20:21.684388Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"match_features.confs[config[\"matcher_conf_feature\"]]","metadata":{"_uuid":"ecf46f99-fffc-4490-b1a1-82ac42aa1f94","_cell_guid":"b57661b3-97b9-44cf-b0d8-e2448beb7698","collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2024-10-09T15:20:21.686264Z","iopub.execute_input":"2024-10-09T15:20:21.686519Z","iopub.status.idle":"2024-10-09T15:20:21.694707Z","shell.execute_reply.started":"2024-10-09T15:20:21.686498Z","shell.execute_reply":"2024-10-09T15:20:21.693802Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"match_dense.confs[config[\"matcher_conf_dense\"]]","metadata":{"_uuid":"6eb8a5ef-b7af-401a-bbeb-82154031dbe5","_cell_guid":"2a3acfb0-40d2-42db-b0ae-a250ae47f2eb","collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2024-10-09T15:20:21.698639Z","iopub.execute_input":"2024-10-09T15:20:21.698919Z","iopub.status.idle":"2024-10-09T15:20:21.704940Z","shell.execute_reply.started":"2024-10-09T15:20:21.698897Z","shell.execute_reply":"2024-10-09T15:20:21.704044Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def sfm_pipeline(images: Path, outputs: Path, config: dict):\n    \"\"\" Pipeline of Structure from Motion \"\"\"\n    \n    # Set configures\n    # Output paths\n    sfm_pairs = outputs / str(\"pairs-\" + config[\"retrieval_conf\"] + \".txt\")\n    sfm_dir = outputs / config[\"feature_conf\"]\n    # Global descriptors : {\"dir\", \"netvlad\", \"openibl\", \"eigenplaces\"}\n    retrieval_conf = extract_features.confs[config[\"retrieval_conf\"]]\n    # Local descriptors : {\"superpoint_aachen\", \"superpoint_max\", \"superpoint_inloc\", \"r2d2\", \"d2net-ss\", \"sift\", \"sosnet\", \"disk\", \"aliked-n16-rot\", \"aliked-n32\"}\n    feature_conf = extract_features.confs[config[\"feature_conf\"]]\n    # feature_conf['model']['detection_threshold'] = 0.1\n    # feature_conf['model']['nms_radius'] = 1\n    \n    # SFD2: Semantic-guided Feature Detection and Description\n    # feature_conf = extract_features_sfd2.confs[config[\"feature_conf_sfd2\"]]\n    \n    # Get image pairs\n    if len(image_paths) <= -1:\n        print(\"Get exhaustive pairs.\")\n        outputs.mkdir(parents=True, exist_ok=True)\n        sfm_pairs.touch(exist_ok=True)\n        pairs_from_exhaustive.main(sfm_pairs, image_list=[p.relative_to(images).as_posix() for p in (images).iterdir()])\n        \n        # retrieval_path = extract_features.main(retrieval_conf, images, outputs)\n        # pairs_from_exhaustive.main(sfm_pairs, features=retrieval_path)\n    else:\n        print(\"Get retrieval pairs.\")\n        retrieval_path = extract_features.main(retrieval_conf, images, outputs)\n        pairs_from_retrieval.main(retrieval_path, sfm_pairs, num_matched=10)\n    \n    # Match\n    if(config[\"match_method\"]==\"dense\"):\n        # Match : {\"loftr\", \"loftr_aachen\", \"loftr_superpoint\"}\n        matcher_conf = match_dense.confs[config[\"matcher_conf_dense\"]]\n        # Match dense\n        feature_path, match_path = match_dense.main(matcher_conf, sfm_pairs, images, export_dir=outputs)\n        \n    else:\n        # Match : {\"superpoint+lightglue\", \"disk+lightglue\", \"superglue\", \"superglue-fast\", \"NN-superpoint\", \"NN-ratio\", \"NN-mutual\", \"adalam\", \"aliked+lightglue\"}\n        matcher_conf = match_features.confs[config[\"matcher_conf_feature\"]]\n        matcher_conf['max_error'] = 2\n        matcher_conf['cell_size'] = 6\n        \n        # \"outdoor\" is better than \"indoor\"\n        # if((config[\"matcher_conf_feature\"]==\"superglue\") & (config[\"feature_conf\"]==\"superpoint_inloc\")):\n        #    matcher_conf['model']['weights'] = \"indoor\"\n        \n        # Extract features and match\n        feature_path = extract_features.main(feature_conf, images, outputs)\n        # feature_path = extract_features_sfd2.main(feature_conf, images, outputs)\n        match_path = match_features.main(matcher_conf, sfm_pairs, feature_conf[\"output\"], outputs)\n    \n    # Reconstruct\n    model = reconstruction.main(sfm_dir, images, sfm_pairs, feature_path, match_path,\n                                # camera_mode=pycolmap.CameraMode.SINGLE, 　# default : pycolmap.CameraMode.AUTO\n                                # skip_geometric_verification=True,\n                                # min_match_score=0.5,\n                                # image_options=dict(camera_model=\"SIMPLE_PINHOLE\",\n                                #                   ),\n                                # mapper_options=dict(min_num_matches=5,\n                                #                     max_num_models=3,\n                                #                     min_model_size=2,\n                                #                     mapper=dict(max_reg_trials=10,\n                                #                                init_min_tri_angle=4,\n                                #                                abs_pose_min_num_inliers=5),\n                                #                     triangulation=dict(create_max_angle_error=10,\n                                #                                       re_max_trials=10,\n                                #                                       min_angle=0.1,\n                                #                                       ),\n                                #                    )\n                               )\n    # Save\n    model.write_text(outputs)\n    \n    return model","metadata":{"_uuid":"4545da9b-459b-4ff8-9f84-7e35e51289e3","_cell_guid":"c3e986d8-a772-4508-9cf8-577b691a0a2e","collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2024-10-09T15:20:21.706457Z","iopub.execute_input":"2024-10-09T15:20:21.706792Z","iopub.status.idle":"2024-10-09T15:20:21.720640Z","shell.execute_reply.started":"2024-10-09T15:20:21.706769Z","shell.execute_reply":"2024-10-09T15:20:21.719708Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Functions for submission","metadata":{"_uuid":"eaff483b-0550-4bef-b2b7-e0f57169dad4","_cell_guid":"905451e9-0071-41af-879a-29a6e4d29c1e","trusted":true}},{"cell_type":"code","source":"def arr_to_str(a):\n    \"\"\"Returns ;-separated string representing the input\"\"\"\n    return \";\".join([str(x) for x in a.reshape(-1)])","metadata":{"_uuid":"47df3c2a-aad6-4ce5-bfab-0e844211ae17","_cell_guid":"eb416090-f311-448f-8fa3-aca3610582cc","collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2024-10-09T15:20:21.723708Z","iopub.execute_input":"2024-10-09T15:20:21.724433Z","iopub.status.idle":"2024-10-09T15:20:21.731915Z","shell.execute_reply.started":"2024-10-09T15:20:21.724401Z","shell.execute_reply":"2024-10-09T15:20:21.731094Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def parse_sample_submission(\n    base_path: Path,\n) -> dict[dict[str, list[Path]]]:\n    \"\"\"Construct a dict describing the test data as \n    \n    {\"dataset\": {\"scene\": [<image paths>]}}\n    \"\"\"\n    data_dict = {}\n    with open(base_path / \"sample_submission.csv\", \"r\") as f:\n        for i, l in enumerate(f):\n            # Skip header\n            if i == 0:\n                print(\"header:\", l)\n\n            if l and i > 0:\n                image_path, dataset, scene, _, _ = l.strip().split(',')\n                if dataset not in data_dict:\n                    data_dict[dataset] = {}\n                if scene not in data_dict[dataset]:\n                    data_dict[dataset][scene] = []\n                data_dict[dataset][scene].append(Path(base_path / image_path))\n\n    for dataset in data_dict:\n        for scene in data_dict[dataset]:\n            print(f\"{dataset} / {scene} -> {len(data_dict[dataset][scene])} images\")\n\n    return data_dict","metadata":{"_uuid":"1ef42aaa-cb91-4bcc-b655-e2ee62a4ae29","_cell_guid":"f55919da-f46e-4742-a63d-5f4d92bf9fab","collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2024-10-09T15:20:21.733031Z","iopub.execute_input":"2024-10-09T15:20:21.733342Z","iopub.status.idle":"2024-10-09T15:20:21.744071Z","shell.execute_reply.started":"2024-10-09T15:20:21.733318Z","shell.execute_reply":"2024-10-09T15:20:21.743213Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def create_submission(\n    results: dict,\n    data_dict: dict[dict[str, list[Path]]],\n    base_path: Path,\n) -> None:\n    \"\"\"Prepare a submission file\"\"\"\n    \n    with open(\"/kaggle/working/submission.csv\", \"w\") as f:\n        f.write(\"image_path,dataset,scene,rotation_matrix,translation_vector\\n\")\n        \n        for dataset in data_dict:\n            # Only write results for datasets with images that have results \n            if dataset in results:\n                res = results[dataset]\n            else:\n                res = {}\n            \n            # Same for scenes\n            for scene in data_dict[dataset]:\n                if scene in res:\n                    scene_res = res[scene]\n                else:\n                    scene_res = {\"R\":{}, \"t\":{}}\n                    \n                # Write the row with rotation and translation matrices\n                for image in data_dict[dataset][scene]:\n                    if image in scene_res:\n                        print(image)\n                        R = scene_res[image][\"R\"].reshape(-1)\n                        T = scene_res[image][\"t\"].reshape(-1)\n                    else:\n                        R = np.eye(3).reshape(-1)\n                        T = np.zeros((3))\n                    image_path = str(image.relative_to(base_path))\n                    f.write(f\"{image_path},{dataset},{scene},{arr_to_str(R)},{arr_to_str(T)}\\n\")","metadata":{"_uuid":"4f846faa-64a1-45d9-8677-de00df4998b5","_cell_guid":"10982cd1-3db7-4e3e-8fb8-01c74efa4bfd","collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2024-10-09T15:20:21.745227Z","iopub.execute_input":"2024-10-09T15:20:21.745540Z","iopub.status.idle":"2024-10-09T15:20:21.755315Z","shell.execute_reply.started":"2024-10-09T15:20:21.745516Z","shell.execute_reply":"2024-10-09T15:20:21.754373Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Main","metadata":{"_uuid":"070eea5f-b4a9-423c-ac8e-de0fdaae1454","_cell_guid":"b6d5aece-4a0c-44ac-b230-27dd898bc52f","trusted":true}},{"cell_type":"code","source":"import tqdm, tqdm.notebook\ntqdm.tqdm = tqdm.notebook.tqdm  # notebook-friendly progress bars\nfrom pathlib import Path\n\nfrom hloc import (\n    pairs_from_exhaustive, pairs_from_retrieval, \n    extract_features, \n    match_features, match_dense, \n    reconstruction, \n    visualization, \n)\nfrom hloc.visualization import plot_images, read_image\nfrom hloc.utils import viz_3d\n\nimport extract_localization as extract_features_sfd2\n\nimport pycolmap\nimport gc\nimport numpy as np\nfrom copy import deepcopy\n\n# Configuration\nconfig = {\n    \"retrieval_conf\": \"netvlad\",\n    \"feature_conf\": \"aliked-n16-rot\",\n    \"feature_conf_sfd2\": \"ressegnetv2-20220810-wapv2-sd2mfsf-uspg-0001-n4096-r1024\", \n    \"match_method\": \"dense\",\n    \"matcher_conf_feature\": \"aliked+lightglue\",\n    \"matcher_conf_dense\": \"loftr\",\n}\n\ndef sfm_pipeline(images: Path, outputs: Path, config: dict):\n    \"\"\" Pipeline of Structure from Motion \"\"\"\n    \n    # Set configures\n    # Output paths\n    sfm_pairs = outputs / str(\"pairs-\" + config[\"retrieval_conf\"] + \".txt\")\n    sfm_dir = outputs / config[\"feature_conf\"]\n    # Global descriptors\n    retrieval_conf = extract_features.confs[config[\"retrieval_conf\"]]\n    # Local descriptors\n    feature_conf = extract_features.confs[config[\"feature_conf\"]]\n    \n    # Get image pairs\n    print(\"Get retrieval pairs.\")\n    retrieval_path = extract_features.main(retrieval_conf, images, outputs)\n    pairs_from_retrieval.main(retrieval_path, sfm_pairs, num_matched=10)\n    \n    # Match\n    if(config[\"match_method\"]==\"dense\"):\n        matcher_conf = match_dense.confs[config[\"matcher_conf_dense\"]]\n        feature_path, match_path = match_dense.main(matcher_conf, sfm_pairs, images, export_dir=outputs)\n    else:\n        matcher_conf = match_features.confs[config[\"matcher_conf_feature\"]]\n        matcher_conf['max_error'] = 2\n        matcher_conf['cell_size'] = 6\n        \n        feature_path = extract_features.main(feature_conf, images, outputs)\n        match_path = match_features.main(matcher_conf, sfm_pairs, feature_conf[\"output\"], outputs)\n    \n    # Reconstruct\n    model = reconstruction.main(sfm_dir, images, sfm_pairs, feature_path, match_path)\n    \n    # Save\n    model.write_text(outputs)\n    \n    return model\n\ndef parse_custom_dataset(dataset_path: Path) -> dict:\n    data_dict = {\"custom_dataset\": {\"custom_scene\": []}}\n    \n    for image_file in sorted(dataset_path.glob(\"*.jpg\")):\n        data_dict[\"custom_dataset\"][\"custom_scene\"].append(image_file)\n    \n    print(f\"Custom dataset: {len(data_dict['custom_dataset']['custom_scene'])} images\")\n    return data_dict\n\n# Main execution\ndataset_path = Path(\"/kaggle/input/finaldata\")  # Update this path\noutput_path = Path(\"/kaggle/working/\")  # Update this path\n\ndata_dict = parse_custom_dataset(dataset_path)\nresults = {}\n\nfor dataset in data_dict:\n    if dataset not in results:\n        results[dataset] = {}\n\n    for scene in data_dict[dataset]:\n        images_dir = data_dict[dataset][scene][0].parent\n        results[dataset][scene] = {}\n        image_paths = data_dict[dataset][scene]\n        print(f\"Got {len(image_paths)} images\")\n        \n        try:\n            images = Path(images_dir)\n            outputs = Path(output_path) / dataset / scene\n            \n            # SfM pipeline\n            model = sfm_pipeline(images=images, outputs=outputs, config=config)\n            \n            for k, im in model.images.items():\n                key = images_dir / im.name\n                results[dataset][scene][key] = {}\n                results[dataset][scene][key][\"R\"] = deepcopy(im.cam_from_world.rotation.matrix())\n                results[dataset][scene][key][\"t\"] = deepcopy(np.array(im.cam_from_world.translation))\n                \n            print(f\"Registered: {dataset} / {scene} -> {len(results[dataset][scene])} images\")\n            print(f\"Total: {dataset} / {scene} -> {len(data_dict[dataset][scene])} images\")\n            \n            gc.collect()\n            \n        except Exception as e:\n            print(f\"Error processing {dataset}/{scene}: {e}\")","metadata":{"_uuid":"617ef53a-1078-4ab3-9886-52d22b2da326","_cell_guid":"2f1eddb6-97f2-4ae6-9edf-3940dda7d4c4","collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2024-10-09T15:20:21.756649Z","iopub.execute_input":"2024-10-09T15:20:21.756909Z","iopub.status.idle":"2024-10-09T15:33:20.469353Z","shell.execute_reply.started":"2024-10-09T15:20:21.756886Z","shell.execute_reply":"2024-10-09T15:33:20.468397Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Visualize","metadata":{"_uuid":"a5f6cc90-b3a4-4479-ae66-0c975f1fe982","_cell_guid":"f19ae818-e940-427d-92fa-7483838fafdc","trusted":true}},{"cell_type":"code","source":"fig = viz_3d.init_figure()\nviz_3d.plot_reconstruction(fig, model, color='rgba(255,0,0,0.5)', name=\"mapping\", points_rgb=True)\nfig.show()","metadata":{"_uuid":"40bdaea6-e73d-489e-88e7-6b445bbb7370","_cell_guid":"43c0ccaf-4018-475e-b097-e82db2ed586e","collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2024-10-09T15:33:20.470581Z","iopub.execute_input":"2024-10-09T15:33:20.471086Z","iopub.status.idle":"2024-10-09T15:33:22.616123Z","shell.execute_reply.started":"2024-10-09T15:33:20.471060Z","shell.execute_reply":"2024-10-09T15:33:22.615204Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"visualization.visualize_sfm_2d(model, images, color_by='visibility', n=5)","metadata":{"_uuid":"29feadbe-8845-4442-872b-38352b14ab2a","_cell_guid":"5cb77030-0d5c-4681-9202-2fc46cdb67b3","collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2024-10-09T15:33:22.617672Z","iopub.execute_input":"2024-10-09T15:33:22.617981Z","iopub.status.idle":"2024-10-09T15:33:41.217355Z","shell.execute_reply.started":"2024-10-09T15:33:22.617954Z","shell.execute_reply":"2024-10-09T15:33:41.216440Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"visualization.visualize_sfm_2d(model, images, color_by=\"track_length\", n=5)","metadata":{"_uuid":"0163f0bb-9257-481f-b4a2-77da92848a91","_cell_guid":"387837b4-a722-4285-a845-b0472de19626","collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2024-10-09T15:33:41.218728Z","iopub.execute_input":"2024-10-09T15:33:41.219067Z","iopub.status.idle":"2024-10-09T15:33:59.254196Z","shell.execute_reply.started":"2024-10-09T15:33:41.219033Z","shell.execute_reply":"2024-10-09T15:33:59.253250Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"visualization.visualize_sfm_2d(model, images, color_by=\"depth\", n=5)","metadata":{"_uuid":"e72b0fae-3aaf-4698-b3d0-5349e89f905e","_cell_guid":"ee5fd3fa-29d0-4c25-b570-463f16bea70f","collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2024-10-09T15:33:59.255898Z","iopub.execute_input":"2024-10-09T15:33:59.256301Z","iopub.status.idle":"2024-10-09T15:34:17.793166Z","shell.execute_reply.started":"2024-10-09T15:33:59.256265Z","shell.execute_reply":"2024-10-09T15:34:17.792357Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# import h5py\n# from hloc.utils.read_write_model import read_model\n\n# cameras, images, points3D = read_model('/kaggle/working/outputs/church/church/aliked-n16-rot', ext='.bin')\n# features = h5py.File(\"/kaggle/working/outputs/church/church/feats-aliked-n16-rot.h5\", \"r\")\n# print(len(images))\n# for id_ in images:\n#     n_model = len(images[id_].point3D_ids)\n#     name = images[id_].name\n#     n_feats = features[name]['keypoints'].__array__().shape[0]\n#     print(name, id_, n_model, n_feats)","metadata":{"_uuid":"d2eeaf8b-3135-481a-9cb4-358609093ef3","_cell_guid":"9238ca03-c6c5-457d-97e8-10346a16797f","collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2024-10-09T15:34:17.794228Z","iopub.execute_input":"2024-10-09T15:34:17.794511Z","iopub.status.idle":"2024-10-09T15:34:17.798731Z","shell.execute_reply.started":"2024-10-09T15:34:17.794486Z","shell.execute_reply":"2024-10-09T15:34:17.797857Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# matches = h5py.File(\"/kaggle/working/outputs/church/church/feats-aliked-n16-rot_matches-aliked-lightglue_pairs-netvlad.h5\", \"r\")\n\n# for id_ in images:\n#     name = images[id_].name\n#     try:\n#         for matched in matches[name]:\n#             n_matches = matches[name][matched]['matches0'].__array__().shape[0]\n#             score_matches = matches[name][matched]['matching_scores0'].__array__().mean()\n#             print(id_, name, matched, n_matches, score_matches)\n#     except:\n#         print('error', name)","metadata":{"_uuid":"8f276a56-c348-4ddf-8b20-6fd3b51a8df1","_cell_guid":"31d53db1-1322-4f1b-ac8f-a00054993528","collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2024-10-09T15:34:17.800001Z","iopub.execute_input":"2024-10-09T15:34:17.800428Z","iopub.status.idle":"2024-10-09T15:34:17.810782Z","shell.execute_reply.started":"2024-10-09T15:34:17.800395Z","shell.execute_reply":"2024-10-09T15:34:17.809974Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!ls /kaggle/input/finaldata","metadata":{"_uuid":"eb8d9da9-e0aa-4b24-a9b0-214915aec361","_cell_guid":"344d9cf7-0e7a-48bf-a116-2a588344b229","collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2024-10-09T15:34:17.811767Z","iopub.execute_input":"2024-10-09T15:34:17.812033Z","iopub.status.idle":"2024-10-09T15:34:18.849195Z","shell.execute_reply.started":"2024-10-09T15:34:17.812011Z","shell.execute_reply":"2024-10-09T15:34:18.848007Z"},"trusted":true},"execution_count":null,"outputs":[]}]}