diff --git a/INSTRUCTIONS.md b/INSTRUCTIONS.md index 79e279e..f0c91ab 100644 --- a/INSTRUCTIONS.md +++ b/INSTRUCTIONS.md @@ -15,17 +15,20 @@ the computed results make sense. - [VLFeat](http://www.vlfeat.org/) toolbox for Matlab - [COLMAP](https://github.com/colmap/colmap): + git clone https://github.com/ahojnnes/local-feature-evaluation.git git clone https://github.com/colmap/colmap - cp path/to/local-feature-evaluation/colmap-tools/* colmap/src/tools - mkdir colmap/build - cd colmap/build - cmake .. -DTEST_ENABLED=OFF - make -j + cd colmap + git checkout 58d966c + cp ../local-feature-evaluation/colmap-tools/* src/tools + mkdir build + cd build + cmake .. -DTESTS_ENABLED=OFF + make 2. **Download the datasets:** - mkdir local-feature-evaluation - cd local-feature-evaluation + mkdir datasets + cd datasets wget http://cvg.ethz.ch/research/local-feature-evaluation/Databases.tar.gz wget http://cvg.ethz.ch/research/local-feature-evaluation/Strecha-Fountain.zip @@ -47,7 +50,7 @@ the computed results make sense. unzip South-Building.zip tar xvf images.Madrid_Metropolis.tar tar xvf images.Gendarmenmarkt.tar - mv home/wilsonkl/projects/SfM_Init/dataset_images/Gendarmenmarkt Gendarmenmarkt + mv home/wilsonkl/projects/SfM_Init/dataset_images/Gendarmenmarkt/images Gendarmenmarkt/images rm -r home tar xvf images.Madrid_Metropolis.tar tar xvf images.Tower_of_London.tar @@ -59,35 +62,43 @@ the computed results make sense. tar xfvz ../../oxbuild_images.tgz cd ../.. -4. **Run the evaluation:** +4. **Download and extract keypoints:** + + If you evaluate just a feature descriptor without a feature detection + component, you should use the provided SIFT keypoints: + + wget http://cvg.ethz.ch/research/local-feature-evaluation/Keypoints.tar.gz + tar xvfz Keypoints.tar.gz + +5. **Run the evaluation:** You can now run the evaluation scripts for every dataset by first running the matching pipeline using the Matlab script ``scripts/matching_pipeline.m``. All locations that require changes by you (the user) are marked with ``TODO`` in the Matlab script. - After finishing the matching pipeline, run the reconstruction using: + After finishing the matching pipeline, run the reconstruction using: - python scripts/reconstruction_pipeline.py \ - --dataset_path path/to/Fountain \ - --colmap_path path/to/colmap/build/src/exe + python scripts/reconstruction_pipeline.py \ + --dataset_path datasets/Fountain \ + --colmap_path colmap/build/src/exe - At the end of the reconstruction pipeline output, you should see all - relevant statistics of the benchmark. For example: + At the end of the reconstruction pipeline output, you should see all + relevant statistics of the benchmark. For example: - ============================================================================== - Raw statistics - ============================================================================== - {'num_images': 11, 'num_inlier_pairs': 55, 'num_inlier_matches': 120944} - {'num_reg_images': 11, 'num_sparse_points': 14472, 'num_observations': 68838, 'mean_track_length': 4.756633, 'num_observations_per_image': 6258.0, 'mean_reproj_error': 0.384562, 'num_dense_points': 298634} + ============================================================================== + Raw statistics + ============================================================================== + {'num_images': 11, 'num_inlier_pairs': 55, 'num_inlier_matches': 120944} + {'num_reg_images': 11, 'num_sparse_points': 14472, 'num_observations': 68838, 'mean_track_length': 4.756633, 'num_observations_per_image': 6258.0, 'mean_reproj_error': 0.384562, 'num_dense_points': 298634} - ============================================================================== - Formatted statistics - ============================================================================== - Fountain | METHOD | 11 | 11 | 14472 | 68838 | 4.756633 | 6258.0 | 0.384562 | 298634 | | | | | 55 | 120944 + ============================================================================== + Formatted statistics + ============================================================================== + | Fountain | METHOD | 11 | 11 | 14472 | 68838 | 4.756633 | 6258.0 | 0.384562 | 298634 | | | | | 55 | 120944 | - Alternatively, you can find more details about each individual step in the - pipeline scripts above in the detailed instructions below. + Alternatively, you can find more details about each individual step in the + pipeline scripts above in the detailed instructions below. Detailed Instructions @@ -271,7 +282,7 @@ Detailed Instructions 1. From the command-line: - ./colmap/build/src/exe/mapper \ + ./colmap/build/src/exe/colmap mapper \ --database_path path/to/Fountain/database.db \ --image_path path/to/Fountain/images \ --export_path path/to/Fountain/sparse @@ -295,17 +306,17 @@ Detailed Instructions determined previously (in this case it is the 0-th model): mkdir -p path/to/Fountain/dense/0 - ./colmap/build/src/exe/image_undistorter \ + ./colmap/build/src/exe/colmap image_undistorter \ --image_path path/to/Fountain/images \ --input_path path/to/Fountain/sparse/0 \ - --export_path path/to/Fountain/dense/0 - ./colmap/build/src/exe/dense_stereo \ + --export_path path/to/Fountain/dense/0 \ + --max_image_size 1200 + ./colmap/build/src/exe/colmap patch_match_stereo \ --workspace_path path/to/Fountain/dense/0 \ - --DenseStereo.geom_consistency false \ - --DenseStereo.max_image_size 1000 - ./colmap/build/src/exe/dense_fuser \ + --PatchMatchStereo.geom_consistency false + ./colmap/build/src/exe/colmap stereo_fusion \ --workspace_path path/to/Fountain/dense/0 \ - --DenseFusion.min_num_pixels 5 \ + --StereoFusion.min_num_pixels 5 \ --input_type photometric \ --output_path path/to/Fountain/dense/0/fused.ply diff --git a/README.md b/README.md index 00d681b..5b9e70e 100644 --- a/README.md +++ b/README.md @@ -19,86 +19,89 @@ benchmark by Balntas and Lenc et al. presented at CVPR 2017. Benchmark Results ----------------- -This list is updated with the latest benchmark results. If you want to submit -your own results, please open a new issue or pull request in this repository. -Note that the below table extends to the right and alternatively can be viewed -in a code or text editor. +This list is updated with the latest benchmark results. Note that the results +differ from the original paper, since they were updated with the latest COLMAP +version. Numbers of some of the features are still missing for the latest COLMAP +version and will be added shortly after recomputing them (marked with ***). If +you want to submit your own results, please open a new issue or pull request in +this repository. Note that the below table extends to the right and +alternatively can be viewed in a code or text editor. **Metrics:** | Dataset | Method | # Images | # Reg. Images | # Sparse Points | # Observations | Track Length | Obs. Per Image | Reproj. Error [px] | # Dense Points | Dense Error [2cm] | Dense Error [10cm] | Mean Pose Error [m] | Median Pose Error [m] | # Inlier Pairs | # Inlier Matches | |:------------------|:---------|---------:|--------------:|----------------:|---------------:|-------------:|---------------:|-------------------:|---------------:|------------------:|-------------------:|--------------------:|----------------------:|---------------:|-----------------:| -| Fountain | SIFT | 11 | 11 | 10004 | 44923 | 4.49050 | 4083.91 | 0.298179 | 2970239 | 0.7678 | 0.8970 | 0.002412 | 0.002412 | 49 | 76644 | -| | SIFT-PCA | | 11 | 14608 | 70058 | 4.79587 | 6368.91 | 0.389404 | 3021445 | 0.7677 | 0.8969 | 0.002413 | 0.002413 | 55 | 124066 | -| | DSP-SIFT | | 11 | 14785 | 71041 | 4.80494 | 6458.27 | 0.410291 | 2999187 | 0.7677 | 0.8970 | 0.002413 | 0.002413 | 54 | 129122 | -| | ConvOpt | | 11 | 14179 | 67308 | 4.74702 | 6118.91 | 0.370262 | 2999376 | 0.7677 | 0.8971 | 0.002413 | 0.002413 | 55 | 114343 | -| | TFeat | | 11 | 13696 | 64110 | 4.68093 | 5828.18 | 0.352238 | 2969328 | 0.7677 | 0.8969 | 0.002412 | 0.002412 | 54 | 103260 | -| | DeepDesc | | 11 | 13519 | 61478 | 4.54753 | 5588.91 | 0.353349 | 2972715 | 0.7677 | 0.8969 | 0.002413 | 0.002413 | 55 | 93708 | -| | LIFT | | 11 | 10172 | 46272 | 4.54896 | 4206.55 | 0.594498 | 3019888 | 0.7678 | 0.8969 | 0.002413 | 0.002413 | 55 | 83318 | +| Fountain | SIFT | 11 | 11 | 14722 | 70631 | 4.79765 | 6421.00 | 0.392893 | 292609 | | | | | 55 | 127734 | +| | SIFT-PCA | | 11 | 14281 | 67776 | 4.74588 | 6161.45 | 0.379411 | 295870 | | | | | 55 | 117257 | +| | DSP-SIFT | | 11 | 14867 | 71153 | 4.78596 | 6468.45 | 0.414944 | 293789 | | | | | 55 | 130820 | +| | ConvOpt | | 11 | 14717 | 70614 | 4.79812 | 6419.45 | 0.393435 | 296522 | | | | | 55 | 127540 | +| *** | TFeat | | 11 | 13696 | 64110 | 4.68093 | 5828.18 | 0.352238 | 2969328 | 0.7677 | 0.8969 | 0.002412 | 0.002412 | 54 | 103260 | +| *** | DeepDesc | | 11 | 13519 | 61478 | 4.54753 | 5588.91 | 0.353349 | 2972715 | 0.7677 | 0.8969 | 0.002413 | 0.002413 | 55 | 93708 | +| *** | LIFT | | 11 | 10172 | 46272 | 4.54896 | 4206.55 | 0.594498 | 3019888 | 0.7678 | 0.8969 | 0.002413 | 0.002413 | 55 | 83318 | | | | | | | | | | | | | | | | | | -| Herzjesu | SIFT | 8 | 8 | 4916 | 19684 | 4.00407 | 2460.50 | 0.319120 | 2373266 | 0.5737 | 0.7307 | 0.003533 | 0.003533 | 27 | 28955 | -| | SIFT-PCA | | 8 | 7433 | 31116 | 4.18620 | 3889.50 | 0.421221 | 2372268 | 0.5735 | 0.7306 | 0.003534 | 0.003534 | 28 | 47384 | -| | DSP-SIFT | | 8 | 7760 | 32494 | 4.18737 | 4061.75 | 0.447413 | 2376744 | 0.5734 | 0.7305 | 0.003533 | 0.003533 | 28 | 50613 | -| | ConvOpt | | 8 | 6939 | 28638 | 4.12711 | 3579.75 | 0.396862 | 2375340 | 0.5737 | 0.7306 | 0.003533 | 0.003533 | 28 | 42199 | -| | TFeat | | 8 | 6606 | 27021 | 4.09037 | 3377.62 | 0.381651 | 2377038 | 0.5734 | 0.7304 | 0.003533 | 0.003533 | 28 | 38573 | -| | DeepDesc | | 8 | 6418 | 25139 | 3.91695 | 3142.38 | 0.379522 | 2380244 | 0.5734 | 0.7307 | 0.003533 | 0.003533 | 28 | 34591 | -| | LIFT | | 8 | 7834 | 30925 | 3.94754 | 3865.62 | 0.625963 | 2375055 | 0.5738 | 0.7308 | 0.003533 | 0.003533 | 28 | 46090 | +| Herzjesu | SIFT | 8 | 8 | 7502 | 31670 | 4.22154 | 3958.75 | 0.431632 | 241347 | | | | | 28 | 48965 | +| | SIFT-PCA | | 8 | 7161 | 29735 | 4.15235 | 3716.87 | 0.409061 | 245291 | | | | | 28 | 44443 | +| | DSP-SIFT | | 8 | 7769 | 32809 | 4.22306 | 4101.12 | 0.459535 | 238122 | | | | | 28 | 51893 | +| | ConvOpt | | 8 | 4957 | 20227 | 4.08049 | 2528.37 | 0.387640 | 242262 | | | | | 26 | 27830 | +| *** | TFeat | | 8 | 6606 | 27021 | 4.09037 | 3377.62 | 0.381651 | 2377038 | 0.5734 | 0.7304 | 0.003533 | 0.003533 | 28 | 38573 | +| *** | DeepDesc | | 8 | 6418 | 25139 | 3.91695 | 3142.38 | 0.379522 | 2380244 | 0.5734 | 0.7307 | 0.003533 | 0.003533 | 28 | 34591 | +| *** | LIFT | | 8 | 7834 | 30925 | 3.94754 | 3865.62 | 0.625963 | 2375055 | 0.5738 | 0.7308 | 0.003533 | 0.003533 | 28 | 46090 | | | | | | | | | | | | | | | | | | -| South Building | SIFT | 128 | 128 | 62780 | 353939 | 5.63777 | 2765.15 | 0.424381 | 1972543 | | | | | 1851 | 1003336 | -| | SIFT-PCA | | 128 | 107674 | 650117 | 6.03783 | 5079.04 | 0.540539 | 1993853 | | | | | 3916 | 2019148 | -| | DSP-SIFT | | 128 | 110394 | 664533 | 6.01965 | 5191.66 | 0.569184 | 1994432 | | | | | 3769 | 2079511 | -| | ConvOpt | | 128 | 103602 | 617078 | 5.95624 | 4820.92 | 0.510579 | 2007852 | | | | | 4640 | 1856409 | -| | TFeat | | 128 | 94589 | 566687 | 5.99105 | 4427.24 | 0.486924 | 1960970 | | | | | 3156 | 1567873 | -| | DeepDesc | | 128 | 101154 | 558997 | 5.52620 | 4367.16 | 0.483270 | 2002399 | | | | | 6034 | 1463340 | -| | LIFT | | 128 | 74607 | 399254 | 5.35143 | 3119.17 | 0.776213 | 1975540 | | | | | 3441 | 1168942 | +| South-Building | SIFT | 128 | 128 | 108124 | 653975 | 6.04838 | 5109.18 | 0.545747 | 2141964 | | | | | 3822 | 2036024 | +| | SIFT-PCA | | 128 | 105612 | 632145 | 5.98554 | 4938.63 | 0.531500 | 2090915 | | | | | 3979 | 1927873 | +| | DSP-SIFT | | 128 | 112719 | 666808 | 5.91566 | 5209.43 | 0.580537 | 2141873 | | | | | 3958 | 2076833 | +| | ConvOpt | | 128 | 62306 | 397579 | 6.38107 | 3106.08 | 0.487924 | 2117221 | | | | | 1901 | 984762 | +| *** | TFeat | | 128 | 94589 | 566687 | 5.99105 | 4427.24 | 0.486924 | 1960970 | | | | | 3156 | 1567873 | +| *** | DeepDesc | | 128 | 101154 | 558997 | 5.52620 | 4367.16 | 0.483270 | 2002399 | | | | | 6034 | 1463340 | +| *** | LIFT | | 128 | 74607 | 399254 | 5.35143 | 3119.17 | 0.776213 | 1975540 | | | | | 3441 | 1168942 | | | | | | | | | | | | | | | | | | -| Madrid Metropolis | SIFT | 1344 | 440 | 62729 | 416727 | 6.64329 | 947.107 | 0.525606 | 435563 | | | | | 14343 | 1740200 | -| | SIFT-PCA | | 465 | 119244 | 702936 | 5.89494 | 1511.69 | 0.569103 | 537758 | | | | | 27664 | 3597662 | -| | DSP-SIFT | | 476 | 107028 | 681222 | 6.36490 | 1431.14 | 0.639809 | 570224 | | | | | 21127 | 3155358 | -| | ConvOpt | | 455 | 115134 | 634011 | 5.50672 | 1393.43 | 0.568558 | 561697 | | | | | 29765 | 3148104 | -| | TFeat | | 439 | 90274 | 512470 | 5.67683 | 1167.36 | 0.538515 | 522327 | | | | | 18450 | 2135644 | -| | DeepDesc | | 377 | 68110 | 348061 | 5.11028 | 923.239 | 0.526658 | 516535 | | | | | 19782 | 1570887 | -| | LIFT | | 430 | 52755 | 337392 | 6.39545 | 784.633 | 0.758943 | 450562 | | | | | 13337 | 1498051 | +| Madrid Metropolis | SIFT | 1344 | 500 | 116088 | 733745 | 6.32053 | 1467.49 | 0.605330 | 1822434 | | | | | 227092 | 6969437 | +| | SIFT-PCA | | 469 | 111090 | 645437 | 5.81003 | 1376.19 | 0.586054 | 1571584 | | | | | 644573 | 13970478 | +| | DSP-SIFT | | 467 | 99514 | 649704 | 6.52877 | 1391.22 | 0.660135 | 1643614 | | | | | 135215 | 4586807 | +| | ConvOpt | | 348 | 40749 | 213176 | 5.23144 | 612.57 | 0.534638 | 1251705 | | | | | 665669 | 12531539 | +| *** | TFeat | | 439 | 90274 | 512470 | 5.67683 | 1167.36 | 0.538515 | 522327 | | | | | 18450 | 2135644 | +| *** | DeepDesc | | 377 | 68110 | 348061 | 5.11028 | 923.239 | 0.526658 | 516535 | | | | | 19782 | 1570887 | +| *** | LIFT | | 430 | 52755 | 337392 | 6.39545 | 784.633 | 0.758943 | 450562 | | | | | 13337 | 1498051 | | | | | | | | | | | | | | | | | | -| Gendarmenmarkt | SIFT | 1463 | 950 | 169900 | 1010545 | 5.94788 | 1063.73 | 0.639777 | 1104976 | | | | | 28683 | 3292693 | -| | SIFT-PCA | | 953 | 272118 | 1477833 | 5.43085 | 1550.72 | 0.692133 | 1240706 | | | | | 43413 | 5137545 | -| | DSP-SIFT | | 975 | 321846 | 1732034 | 5.38156 | 1776.45 | 0.735691 | 1505886 | | | | | 56470 | 7648903 | -| | ConvOpt | | 945 | 341591 | 1601383 | 4.68801 | 1694.59 | 0.696203 | 1342513 | | | | | 56905 | 6525056 | -| | TFeat | | 953 | 297266 | 1445049 | 4.86113 | 1516.32 | 0.660397 | 1181279 | | | | | 39115 | 4685369 | -| | DeepDesc | | 809 | 244925 | 949216 | 3.87554 | 1173.32 | 0.681721 | 921231 | | | | | 31134 | 2849341 | -| | LIFT | | 942 | 180746 | 964485 | 5.33613 | 1023.87 | 0.830989 | 1386731 | | | | | 27879 | 2495028 | +| Gendarmenmarkt | SIFT | 1463 | 1035 | 338972 | 1872308 | 5.52348 | 1809.00 | 0.699118 | 4225031 | | | | | 321854 | 12625310 | +| | SIFT-PCA | | 975 | 349217 | 1690464 | 4.84072 | 1733.80 | 0.701904 | 3649260 | | | | | 822997 | 20321433 | +| | DSP-SIFT | | 979 | 293209 | 1577921 | 5.38155 | 1611.76 | 0.749714 | 2600189 | | | | | 265575 | 9315075 | +| | ConvOpt | | 772 | 178859 | 694211 | 3.88133 | 899.23 | 0.723822 | 2955105 | | | | | 811724 | 15583270 | +| *** | TFeat | | 953 | 297266 | 1445049 | 4.86113 | 1516.32 | 0.660397 | 1181279 | | | | | 39115 | 4685369 | +| *** | DeepDesc | | 809 | 244925 | 949216 | 3.87554 | 1173.32 | 0.681721 | 921231 | | | | | 31134 | 2849341 | +| *** | LIFT | | 942 | 180746 | 964485 | 5.33613 | 1023.87 | 0.830989 | 1386731 | | | | | 27879 | 2495028 | | | | | | | | | | | | | | | | | | -| Tower of London | SIFT | 1576 | 702 | 142746 | 963821 | 6.75200 | 1372.96 | 0.530041 | 1126600 | | | | | 18716 | 3211444 | -| | SIFT-PCA | | 692 | 137800 | 1090091 | 7.91067 | 1575.28 | 0.601250 | 1124538 | | | | | 12154 | 2455869 | -| | DSP-SIFT | | 755 | 236598 | 1761435 | 7.44484 | 2333.03 | 0.638131 | 1143471 | | | | | 33500 | 8056825 | -| | ConvOpt | | 719 | 274987 | 1732771 | 6.30128 | 2409.97 | 0.617079 | 1129334 | | | | | 39941 | 7542856 | -| | TFeat | | 714 | 206142 | 1424696 | 6.91124 | 1995.37 | 0.572171 | 1182746 | | | | | 28388 | 5333355 | -| | DeepDesc | | 551 | 196990 | 964750 | 4.89746 | 1750.91 | 0.545235 | 653579 | | | | | 25658 | 2745700 | -| | LIFT | | 715 | 147851 | 1045724 | 7.07282 | 1462.55 | 0.721916 | 729060 | | | | | 23058 | 4079252 | +| Tower of London | SIFT | 1576 | 804 | 239951 | 1863301 | 7.76534 | 2317.53 | 0.615406 | 3050252 | | | | | 165097 | 11249925 | +| | SIFT-PCA | | 693 | 220381 | 1491686 | 6.76866 | 2152.50 | 0.602057 | 2518677 | | | | | 558173 | 14605601 | +| | DSP-SIFT | | 799 | 267906 | 1940752 | 7.24415 | 2428.97 | 0.655440 | 2946702 | | | | | 260963 | 12750104 | +| | ConvOpt | | 537 | 143397 | 788855 | 5.50119 | 1469.00 | 0.580207 | 2448215 | | | | | 742322 | 14648025 | +| *** | TFeat | | 714 | 206142 | 1424696 | 6.91124 | 1995.37 | 0.572171 | 1182746 | | | | | 28388 | 5333355 | +| *** | DeepDesc | | 551 | 196990 | 964750 | 4.89746 | 1750.91 | 0.545235 | 653579 | | | | | 25658 | 2745700 | +| *** | LIFT | | 715 | 147851 | 1045724 | 7.07282 | 1462.55 | 0.721916 | 729060 | | | | | 23058 | 4079252 | | | | | | | | | | | | | | | | | | -| Alamo | SIFT | 2915 | 743 | 120713 | 1384696 | 11.47100 | 1863.66 | 0.535782 | 611874 | | | | | 23526 | 7671821 | -| | SIFT-PCA | | 746 | 108553 | 1377035 | 12.68540 | 1845.89 | 0.550041 | 564223 | | | | | 12766 | 4669536 | -| | DSP-SIFT | | 754 | 144341 | 1815879 | 12.58050 | 2408.33 | 0.657329 | 629061 | | | | | 16925 | 10115750 | -| | ConvOpt | | 703 | 102044 | 1001340 | 9.81283 | 1424.38 | 0.479573 | 452541 | | | | | 3962 | 850327 | -| | TFeat | | 683 | 127642 | 1443116 | 11.30600 | 2112.91 | 0.521289 | 648970 | | | | | 16764 | 6356806 | -| | DeepDesc | | 665 | 152537 | 1207394 | 7.91542 | 1815.63 | 0.479996 | 607091 | | | | | 16691 | 4196845 | -| | LIFT | | 768 | 112984 | 1477294 | 13.07520 | 1923.56 | 0.734686 | 607487 | | | | | 23432 | 9117444 | +| Alamo | SIFT | 2915 | 963 | 198433 | 2437084 | 12.28164 | 2530.72 | 0.647271 | 3737516 | | | | | 64068 | 21263831 | +| | SIFT-PCA | | 921 | 197723 | 2279339 | 11.52791 | 2474.85 | 0.626812 | 3256364 | | | | | 143747 | 20145150 | +| | DSP-SIFT | | 961 | 223192 | 2564659 | 11.49082 | 2668.73 | 0.712005 | 3815012 | | | | | 79973 | 23375984 | +| | ConvOpt | | 684 | 110261 | 1167754 | 10.59081 | 1707.24 | 0.537849 | 2546861 | | | | | 168383 | 8065721 | +| *** | TFeat | | 683 | 127642 | 1443116 | 11.30600 | 2112.91 | 0.521289 | 648970 | | | | | 16764 | 6356806 | +| *** | DeepDesc | | 665 | 152537 | 1207394 | 7.91542 | 1815.63 | 0.479996 | 607091 | | | | | 16691 | 4196845 | +| *** | LIFT | | 768 | 112984 | 1477294 | 13.07520 | 1923.56 | 0.734686 | 607487 | | | | | 23432 | 9117444 | | | | | | | | | | | | | | | | | | -| Roman Forum | SIFT | 2364 | 1407 | 242192 | 1805253 | 7.45381 | 1283.05 | 0.610871 | 3097439 | | | | | 25447 | 6063636 | -| | SIFT-PCA | | 1463 | 244556 | 1834598 | 7.50175 | 1254.00 | 0.613003 | 2799238 | | | | | 16437 | 4322039 | -| | DSP-SIFT | | 1583 | 372573 | 2879238 | 7.72798 | 1818.85 | 0.708828 | 3748342 | | | | | 26416 | 9685465 | -| | ConvOpt | | 1376 | 195305 | 1173254 | 6.00729 | 852.66 | 0.553454 | 3043274 | | | | | 11921 | 2111787 | -| | TFeat | | 1450 | 271902 | 1963303 | 7.22063 | 1354.00 | 0.608724 | 3477858 | | | | | 19828 | 5584122 | -| | DeepDesc | | 1173 | 174532 | 1275633 | 7.30887 | 1087.49 | 0.602312 | 2434123 | | | | | 9831 | 1834623 | -| | LIFT | | 1434 | 220026 | 1608740 | 7.31159 | 1121.85 | 0.748830 | 2898383 | | | | | 17322 | 4732050 | +| Roman Forum | SIFT | 2364 | 1679 | 433152 | 3603662 | 8.31962 | 2146.31 | 0.708420 | 9630170 | | | | | 76547 | 16424472 | +| | SIFT-PCA | | 1663 | 434317 | 3267075 | 7.52232 | 1964.56 | 0.674920 | 9379870 | | | | | 151694 | 15134227 | +| | DSP-SIFT | | 1644 | 464792 | 3653745 | 7.86103 | 2222.47 | 0.749306 | 9429283 | | | | | 100827 | 16469792 | +| | ConvOpt | | 1282 | 182922 | 1263324 | 6.90635 | 985.43 | 0.627904 | 7404163 | | | | | 158940 | 6151296 | +| *** | TFeat | | 1450 | 271902 | 1963303 | 7.22063 | 1354.00 | 0.608724 | 3477858 | | | | | 19828 | 5584122 | +| *** | DeepDesc | | 1173 | 174532 | 1275633 | 7.30887 | 1087.49 | 0.602312 | 2434123 | | | | | 9831 | 1834623 | +| *** | LIFT | | 1434 | 220026 | 1608740 | 7.31159 | 1121.85 | 0.748830 | 2898383 | | | | | 17322 | 4732050 | | | | | | | | | | | | | | | | | | -| Cornell | SIFT | 6514 | 4999 | 1010544 | 6317214 | 6.25130 | 1263.70 | 0.527172 | 12970087 | | | 1.536723 | 0.792612 | 71919 | 25603366 | -| | SIFT-PCA | | 3049 | 640553 | 4335971 | 6.76911 | 1422.10 | 0.544811 | 6135281 | | | 11.498496 | 1.087624 | 26498 | 13793332 | -| | DSP-SIFT | | 4946 | 1177916 | 7233500 | 6.14093 | 1462.49 | 0.674990 | 11066753 | | | 2.942793 | 1.001049 | 73922 | 26150621 | -| | ConvOpt | | 1986 | 632613 | 4747658 | 7.50484 | 2390.56 | 0.569796 | 5321472 | | | 5.823939 | 0.903555 | 42129 | 18615334 | -| | TFeat | | 5428 | 1499117 | 9830787 | 6.55772 | 1811.13 | 0.587575 | 15605086 | | | 2.125709 | 0.593038 | 89927 | 40640025 | -| | DeepDesc | | 3489 | 1225780 | 6977970 | 5.69268 | 1999.99 | 0.552574 | 10159770 | | | 3.831561 | 0.695395 | 73973 | 28845684 | -| | LIFT | | 3798 | 1455732 | 7377320 | 5.06777 | 1942.42 | 0.712310 | 10512321 | | | 3.113213 | 0.712312 | 81231 | 39812312 | +| Cornell | SIFT | 6514 | 6073 | 1847141 | 12865681 | 6.96518 | 2118.50 | 0.660522 | 35232209 | | | | | 227478 | 61428156 | +| | SIFT-PCA | | 6010 | 1856258 | 12307131 | 6.63007 | 2047.77 | 0.643796 | 35263104 | | | | | 417668 | 59874790 | +| | DSP-SIFT | | 6069 | 2071407 | 13671952 | 6.60032 | 2252.75 | 0.708143 | 35449395 | | | | | 283503 | 64364585 | +| | ConvOpt | | 5009 | 938316 | 6082683 | 6.48255 | 1214.35 | 0.570824 | 30619302 | | | | | 353461 | 25017605 | +| *** | TFeat | | 5428 | 1499117 | 9830787 | 6.55772 | 1811.13 | 0.587575 | 15605086 | | | 2.125709 | 0.593038 | 89927 | 40640025 | +| *** | DeepDesc | | 3489 | 1225780 | 6977970 | 5.69268 | 1999.99 | 0.552574 | 10159770 | | | 3.831561 | 0.695395 | 73973 | 28845684 | +| *** | LIFT | | 3798 | 1455732 | 7377320 | 5.06777 | 1942.42 | 0.712310 | 10512321 | | | 3.113213 | 0.712312 | 81231 | 39812312 | **Runtime:** diff --git a/colmap-tools/vocab_tree_retriever_float.cc b/colmap-tools/vocab_tree_retriever_float.cc index 53cc03f..7ff6835 100644 --- a/colmap-tools/vocab_tree_retriever_float.cc +++ b/colmap-tools/vocab_tree_retriever_float.cc @@ -14,7 +14,8 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -#include "base/feature.h" +#include "base/database.h" +#include "feature/types.h" #include "retrieval/visual_index.h" #include "util/logging.h" #include "util/misc.h" @@ -81,7 +82,6 @@ void QueryImagesInVisualIndex(const std::string& descriptor_path, VisualIndexType::QueryOptions query_options; query_options.max_num_images = num_images; - query_options.max_num_verifications = 0; std::unordered_map image_id_to_image; image_id_to_image.reserve(images.size()); diff --git a/data/sift-pca.mat b/data/sift-pca.mat new file mode 100644 index 0000000..5272bfd Binary files /dev/null and b/data/sift-pca.mat differ diff --git a/scripts/approximate_matching.m b/scripts/approximate_matching.m index d2b8aeb..63d792d 100644 --- a/scripts/approximate_matching.m +++ b/scripts/approximate_matching.m @@ -4,12 +4,12 @@ ' --database_path ' DATABASE_PATH ... ' --descriptor_path ' DESCRIPTOR_PATH ... ' --vocab_tree_path ' VOCAB_TREE_PATH]; -fprintf('Running %s\n', command); +fprintf('Running command: %s\n', command); % Note that if this command fails to execute here, you can simply run the % command manually from the shell as well. [status, output] = system(command); -assert(status == 0, 'Image retrieval failed'); +assert(status == 0, 'Image retrieval failed, run the above command manually.'); retrieval_result_path = fullfile(DATASET_PATH, 'retrieval.txt') fid = fopen(retrieval_result_path); @@ -41,7 +41,7 @@ retrieved_image_name = retrieval_results{2}; retrieved_image_name = retrieved_image_name(13:end); retrieved_image_idxs = [retrieved_image_idxs, ... - image_name_to_idx(retrieved_image_name)]; + image_name_to_idx(retrieved_image_name)]; tline = fgets(fid); end diff --git a/scripts/feature_extraction_convopt.py b/scripts/feature_extraction_convopt.py new file mode 100644 index 0000000..4e21784 --- /dev/null +++ b/scripts/feature_extraction_convopt.py @@ -0,0 +1,81 @@ +import os +import cv2 +import time +import argparse +import numpy as np + + +def parse_args(): + parser = argparse.ArgumentParser() + parser.add_argument("--dataset_path", required=True, + help="Path to the dataset, e.g., path/to/Fountain") + args = parser.parse_args() + return args + + +def read_matrix(path, dtype): + with open(path, "rb") as fid: + shape = np.fromfile(fid, count=2, dtype=np.int32) + matrix = np.fromfile(fid, count=shape[0] * shape[1], dtype=dtype) + return matrix.reshape(shape) + + +def write_matrix(path, matrix): + with open(path, "wb") as fid: + shape = np.array(matrix.shape, dtype=np.int32) + shape.tofile(fid) + matrix.tofile(fid) + + +def main(): + args = parse_args() + + if not os.path.exists(os.path.join(args.dataset_path, "descriptors")): + os.makedirs(os.path.join(args.dataset_path, "descriptors")) + + convopt = cv2.xfeatures2d_VGG.create(scale_factor=6.75) + + image_names = os.listdir(os.path.join(args.dataset_path, "images")) + + for i, image_name in enumerate(image_names): + + keypoints_path = os.path.join(args.dataset_path, "keypoints", + image_name + ".bin") + if not os.path.exists(keypoints_path): + continue + + print("Computing features for {} [{}/{}]".format( + image_name, i + 1, len(image_names)), end="") + + start_time = time.time() + + descriptors_path = os.path.join(args.dataset_path, "descriptors", + image_name + ".bin") + if os.path.exists(descriptors_path): + print(" -> skipping, already exist") + continue + + image = cv2.imread(os.path.join(args.dataset_path, + "images", image_name), + cv2.IMREAD_GRAYSCALE) + + opencv_keypoints = [] + for keypoint in read_matrix(keypoints_path, np.float32): + opencv_keypoint = cv2.KeyPoint() + opencv_keypoint.pt = (keypoint[0], keypoint[1]) + opencv_keypoint.size = keypoint[2] + opencv_keypoint.angle = keypoint[3] + opencv_keypoints.append(opencv_keypoint) + + descriptors = convopt.compute(image, opencv_keypoints) + + if descriptors is None: + descriptors = np.zeros((0, 120), dtype=np.float32) + + write_matrix(descriptors_path, descriptors.astype(np.float32)) + + print(" in {:.3f}s".format(time.time() - start_time)) + + +if __name__ == "__main__": + main() diff --git a/scripts/feature_extraction_dsp_sift.m b/scripts/feature_extraction_dsp_sift.m new file mode 100644 index 0000000..97d7352 --- /dev/null +++ b/scripts/feature_extraction_dsp_sift.m @@ -0,0 +1,69 @@ +DSP_MIN_SCALE = 1 / 6; +DSP_MAX_SCALE = 3; +DSP_NUM_SCALES = 10; + +pool = gcp('nocreate'); +if isempty(pool) + pool = parpool(maxNumCompThreads()); +end + +parfor i = 1:num_images + fprintf('Computing features for %s [%d/%d]', ... + image_names{i}, i, num_images); + + if exist(keypoint_paths{i}, 'file') ... + && exist(descriptor_paths{i}, 'file') + fprintf(' -> skipping, already exist\n'); + continue; + end + + tic; + + % Read the image for keypoint detection, patch extraction and + % descriptor computation. + image = imread(image_paths{i}); + if ismatrix(image) + image = single(image); + else + image = single(rgb2gray(image)); + end + + % Read the pre-computed SIFT keypoints. + keypoints = read_keypoints(keypoint_paths{i}); + + % Compute the descriptors for the detected keypoints. + if size(keypoints, 1) == 0 + descriptors = zeros(0, 128); + else + % Create DSP keypoints, sampled around the standard SIFT detections. + num_keypoints = size(keypoints, 1); + dsp_keypoints = zeros(4, num_keypoints, DSP_NUM_SCALES); + dsp_scale_idx = 1; + for dsp_scale = linspace(DSP_MIN_SCALE, DSP_MAX_SCALE, DSP_NUM_SCALES) + dsp_keypoints([1 2 4],:,dsp_scale_idx) = keypoints(:,[1 2 4])'; + dsp_keypoints(3,:,dsp_scale_idx) = dsp_scale * keypoints(:,3)'; + dsp_scale_idx = dsp_scale_idx + 1; + end + + % Transpose to VLFeat format. + dsp_keypoints = reshape(dsp_keypoints, ... + [4, num_keypoints * DSP_NUM_SCALES]); + + % Extract the descriptors from the DSP keypoints. + [~, descriptors] = vl_covdet(image, 'Frames', dsp_keypoints, ... + 'Descriptor', 'SIFT'); + + % Aggregate the descriptors across all scales. + descriptors = reshape(descriptors, ... + [128, num_keypoints, DSP_NUM_SCALES]); + descriptors = mean(double(descriptors), 3)'; + end + + % Make sure that each keypoint has one descriptor. + assert(size(keypoints, 1) == size(descriptors, 1)); + + % Write the descriptors to disk for matching. + write_descriptors(descriptor_paths{i}, descriptors); + + fprintf(' in %.3fs\n', toc); +end diff --git a/scripts/feature_extraction.m b/scripts/feature_extraction_root_sift.m similarity index 53% rename from scripts/feature_extraction.m rename to scripts/feature_extraction_root_sift.m index dc052f7..d56ea17 100644 --- a/scripts/feature_extraction.m +++ b/scripts/feature_extraction_root_sift.m @@ -24,30 +24,20 @@ image = single(rgb2gray(image)); end - % TODO: Replace this with your keypoint detector. The resultding - % keypoints matrix should have shape N x 4, where each row - % contains the keypoint properties x, y, scale, orientation. - % Note that only x and y are necessary for the reconstruction - % benchmark while scale and orientation are only used for - % extracting local patches around each detected keypoint. - % If you implement your own keypoint detector and patch - % extractor, then you can simply set scale and orientation to 0. - % Here, we simply detect SIFT keypoints using VLFeat. - % keypoints = vl_sift(image)'; - % write_keypoints(keypoint_paths{i}, keypoints); + % Read the pre-computed SIFT keypoints. keypoints = read_keypoints(keypoint_paths{i}); - % Extract the local patches for all keypoints. - patches = extract_patches(image, keypoints, PATCH_RADIUS); - - % TODO: Compute the descriptors for the extracted patches. Here, we - % simply compute SIFT descriptors for all patches using VLFeat. + % Compute the descriptors for the detected keypoints. if size(keypoints, 1) == 0 descriptors = zeros(0, 128); else + % Extract the local patches for all keypoints. + patches = extract_patches(image, keypoints, PATCH_RADIUS); + % Extract the descriptors from the patches. [~, descriptors] = vl_covdet(image, 'Frames', keypoints', ... 'Descriptor', 'SIFT'); - descriptors = descriptors'; + % L1-root-normalization to obtain rootSIFT descriptors. + descriptors = sqrt(descriptors ./ sum(abs(descriptors), 1))'; end % Make sure that each keypoint has one descriptor. diff --git a/scripts/feature_extraction_sift_pca.m b/scripts/feature_extraction_sift_pca.m new file mode 100644 index 0000000..2ec4682 --- /dev/null +++ b/scripts/feature_extraction_sift_pca.m @@ -0,0 +1,56 @@ +% Note that for PCA-SIFT, the descriptor dimension changes and you have to set +% kDescDim = 128 in the colmap-tools source code. + +load(fullfile(fileparts(mfilename('fullpath')), '../data/pca-sift.mat')); + +pool = gcp('nocreate'); +if isempty(pool) + pool = parpool(maxNumCompThreads()); +end + +parfor i = 1:num_images + fprintf('Computing features for %s [%d/%d]', ... + image_names{i}, i, num_images); + + if exist(keypoint_paths{i}, 'file') ... + && exist(descriptor_paths{i}, 'file') + fprintf(' -> skipping, already exist\n'); + continue; + end + + tic; + + % Read the image for keypoint detection, patch extraction and + % descriptor computation. + image = imread(image_paths{i}); + if ismatrix(image) + image = single(image); + else + image = single(rgb2gray(image)); + end + + % Read the pre-computed SIFT keypoints. + keypoints = read_keypoints(keypoint_paths{i}); + + % Compute the descriptors for the detected keypoints. + if size(keypoints, 1) == 0 + descriptors = zeros(0, 80); + else + % Extract the local patches for all keypoints. + patches = extract_patches(image, keypoints, PATCH_RADIUS); + % Extract the descriptors from the patches. + [~, descriptors] = vl_covdet(image, 'Frames', keypoints', ... + 'Descriptor', 'SIFT'); + % Perform PCA-SIFT projection and extract top 80 principal components. + descriptors = pca_sift_eigvecs * double(descriptors); + descriptors = single(data.descriptors(1:80,:))'; + end + + % Make sure that each keypoint has one descriptor. + assert(size(keypoints, 1) == size(descriptors, 1)); + + % Write the descriptors to disk for matching. + write_descriptors(descriptor_paths{i}, descriptors); + + fprintf(' in %.3fs\n', toc); +end diff --git a/scripts/match_descriptors.m b/scripts/match_descriptors.m index 8c8641c..4bc380e 100644 --- a/scripts/match_descriptors.m +++ b/scripts/match_descriptors.m @@ -21,6 +21,7 @@ idxs1 = gpuArray(single(1:size(descriptors1, 1))); [first_dists12, idxs12] = min(dists, [], 2); [~, idxs21] = min(dists, [], 1); +idxs121 = idxs21(idxs12); % Find the second best matches. dists(sub2ind(size(dists), idxs1, idxs12')) = single(realmax('single')); @@ -30,7 +31,7 @@ dist_ratios12 = sqrt(first_dists12) ./ sqrt(second_dists12); % Enforce the ratio test constraint and mutual nearest neighbors. -mask = (dist_ratios12' <= max_dist_ratio) & (idxs1 == idxs21(idxs12)); +mask = (dist_ratios12(:) <= max_dist_ratio) & (idxs1(:) == idxs121(:)); idxs1 = idxs1(mask); idxs2 = idxs12(mask); diff --git a/scripts/matching_pipeline.m b/scripts/matching_pipeline.m index eb02620..d2d21e9 100644 --- a/scripts/matching_pipeline.m +++ b/scripts/matching_pipeline.m @@ -4,83 +4,92 @@ clear; clc; -%% Set the pipeline parameters. - -% TODO: Change this to where your dataset is stored. This directory should -% contain an "images" folder and a "database.db" file. -DATASET_PATH = 'path/to/Fountain'; - -% TODO: Change this to where VLFeat is located. -VLFEAT_PATH = 'path/to/vlfeat-0.9.20'; - -% Radius of local patches around each keypoint. -PATCH_RADIUS = 32; - -% Whether to run matching on GPU. -MATCH_GPU = gpuDeviceCount() > 0; - -% Number of images to match in one block. -MATCH_BLOCK_SIZE = 50; - -% Maximum distance ratio between first and second best matches. -MATCH_MAX_DIST_RATIO = 0.8; - -% Mnimum number of matches between two images. -MIN_NUM_MATCHES = 15; - -%% Setup the pipeline environment. - -run(fullfile(VLFEAT_PATH, 'toolbox/vl_setup')); - -IMAGE_PATH = fullfile(DATASET_PATH, 'images'); -KEYPOINT_PATH = fullfile(DATASET_PATH, 'keypoints'); -DESCRIPTOR_PATH = fullfile(DATASET_PATH, 'descriptors'); -MATCH_PATH = fullfile(DATASET_PATH, 'matches'); -DATABASE_PATH = fullfile(DATASET_PATH, 'database.db'); - -%% Create the output directories. - -if ~exist(KEYPOINT_PATH, 'dir') - mkdir(KEYPOINT_PATH); -end -if ~exist(DESCRIPTOR_PATH, 'dir') - mkdir(DESCRIPTOR_PATH); -end -if ~exist(MATCH_PATH, 'dir') - mkdir(MATCH_PATH); -end - -%% Extract the image names and paths. - -image_files = dir(IMAGE_PATH); -num_images = length(image_files) - 2; -image_names = cell(num_images, 1); -image_paths = cell(num_images, 1); -keypoint_paths = cell(num_images, 1); -descriptor_paths = cell(num_images, 1); -for i = 3:length(image_files) - image_name = image_files(i).name; - image_names{i-2} = image_name; - image_paths{i-2} = fullfile(IMAGE_PATH, image_name); - keypoint_paths{i-2} = fullfile(KEYPOINT_PATH, [image_name '.bin']); - descriptor_paths{i-2} = fullfile(DESCRIPTOR_PATH, [image_name '.bin']); -end - -%% Compute the keypoints and descriptors. - -feature_extraction - -%% Match the descriptors. -% -% NOTE: - You must exhaustively match Fountain, Herzjesu, South Building, -% Madrid Metropolis, Gendarmenmarkt, and Tower of London. -% - You must approximately match Alamo, Roman Forum, Cornell. - -if num_images < 2000 - exhaustive_matching -else - % TODO: Change this to where you saved the vocabulary tree that was - % built using the features of the Oxford5k dataset. - VOCAB_TREE_PATH = 'path/to/Oxford5k/vocab-tree.bin'; - approximate_matching +DATASET_NAMES = {'Fountain', 'Herzjesu', 'South-Building', ... + 'Madrid_Metropolis', 'Gendarmenmarkt', 'Tower_of_London', ... + 'Oxford5k', 'Alamo', 'Roman_Forum', 'ArtsQuad_dataset'}; + +for i = 1:length(DATASET_NAMES) + %% Set the pipeline parameters. + + % TODO: Change this to where your dataset is stored. This directory should + % contain an "images" folder and a "database.db" file. + DATASET_PATH = ['datasets/' DATASET_NAMES{i}]; + + % TODO: Change this to where VLFeat is located. + VLFEAT_PATH = 'vlfeat-0.9.20'; + + % TODO: Change this to where the COLMAP build directory is located. + COLMAP_PATH = 'colmap/build'; + + % Radius of local patches around each keypoint. + PATCH_RADIUS = 32; + + % Whether to run matching on GPU. + MATCH_GPU = gpuDeviceCount() > 0; + + % Number of images to match in one block. + MATCH_BLOCK_SIZE = 50; + + % Maximum distance ratio between first and second best matches. + MATCH_MAX_DIST_RATIO = 0.8; + + % Mnimum number of matches between two images. + MIN_NUM_MATCHES = 15; + + %% Setup the pipeline environment. + + run(fullfile(VLFEAT_PATH, 'toolbox/vl_setup')); + + IMAGE_PATH = fullfile(DATASET_PATH, 'images'); + KEYPOINT_PATH = fullfile(DATASET_PATH, 'keypoints'); + DESCRIPTOR_PATH = fullfile(DATASET_PATH, 'descriptors'); + MATCH_PATH = fullfile(DATASET_PATH, 'matches'); + DATABASE_PATH = fullfile(DATASET_PATH, 'database.db'); + + %% Create the output directories. + + if ~exist(KEYPOINT_PATH, 'dir') + mkdir(KEYPOINT_PATH); + end + if ~exist(DESCRIPTOR_PATH, 'dir') + mkdir(DESCRIPTOR_PATH); + end + if ~exist(MATCH_PATH, 'dir') + mkdir(MATCH_PATH); + end + + %% Extract the image names and paths. + + image_files = dir(IMAGE_PATH); + num_images = length(image_files) - 2; + image_names = cell(num_images, 1); + image_paths = cell(num_images, 1); + keypoint_paths = cell(num_images, 1); + descriptor_paths = cell(num_images, 1); + for i = 3:length(image_files) + image_name = image_files(i).name; + image_names{i-2} = image_name; + image_paths{i-2} = fullfile(IMAGE_PATH, image_name); + keypoint_paths{i-2} = fullfile(KEYPOINT_PATH, [image_name '.bin']); + descriptor_paths{i-2} = fullfile(DESCRIPTOR_PATH, [image_name '.bin']); + end + + %% TODO: Compute the keypoints and descriptors. + + feature_extraction_root_sift + % feature_extraction_pca_sift + % etc. + + %% Match the descriptors. + % + % NOTE: - You must exhaustively match Fountain, Herzjesu, South Building, + % Madrid Metropolis, Gendarmenmarkt, and Tower of London. + % - You must approximately match Alamo, Roman Forum, Cornell. + + if num_images < 2000 + exhaustive_matching + else + VOCAB_TREE_PATH = fullfile(DATASET_PATH, 'Oxford5k/vocab-tree.bin'); + approximate_matching + end end diff --git a/scripts/reconstruction_pipeline.py b/scripts/reconstruction_pipeline.py index a277f7b..1b683da 100644 --- a/scripts/reconstruction_pipeline.py +++ b/scripts/reconstruction_pipeline.py @@ -47,10 +47,20 @@ def import_matches(args): connection = sqlite3.connect(os.path.join(args.dataset_path, "database.db")) cursor = connection.cursor() + cursor.execute("SELECT name FROM sqlite_master " + "WHERE type='table' AND name='inlier_matches';") + try: + inlier_matches_table_exists = bool(next(cursor)[0]) + except StopIteration: + inlier_matches_table_exists = False + cursor.execute("DELETE FROM keypoints;") cursor.execute("DELETE FROM descriptors;") cursor.execute("DELETE FROM matches;") - cursor.execute("DELETE FROM inlier_matches;") + if inlier_matches_table_exists: + cursor.execute("DELETE FROM inlier_matches;") + else: + cursor.execute("DELETE FROM two_view_geometries;") connection.commit() images = {} @@ -79,6 +89,7 @@ def import_matches(args): connection.commit() image_pairs = [] + image_pair_ids = set() for match_path in glob.glob(os.path.join(args.dataset_path, "matches/*---*.bin")): image_name1, image_name2 = \ @@ -87,6 +98,9 @@ def import_matches(args): print("Importing matches for", image_name1, "---", image_name2) image_id1, image_id2 = images[image_name1], images[image_name2] image_pair_id = image_ids_to_pair_id(image_id1, image_id2) + if image_pair_id in image_pair_ids: + continue + image_pair_ids.add(image_pair_id) matches = read_matrix(match_path, np.uint32) assert matches.shape[1] == 2 if IS_PYTHON3: @@ -106,7 +120,8 @@ def import_matches(args): cursor.close() connection.close() - subprocess.call([os.path.join(args.colmap_path, "matches_importer"), + subprocess.call([os.path.join(args.colmap_path, "colmap"), + "matches_importer", "--database_path", os.path.join(args.dataset_path, "database.db"), "--match_list_path", @@ -119,10 +134,10 @@ def import_matches(args): cursor.execute("SELECT count(*) FROM images;") num_images = next(cursor)[0] - cursor.execute("SELECT count(*) FROM inlier_matches WHERE rows > 0;") + cursor.execute("SELECT count(*) FROM two_view_geometries WHERE rows > 0;") num_inlier_pairs = next(cursor)[0] - cursor.execute("SELECT sum(rows) FROM inlier_matches WHERE rows > 0;") + cursor.execute("SELECT sum(rows) FROM two_view_geometries WHERE rows > 0;") num_inlier_matches = next(cursor)[0] cursor.close() @@ -146,7 +161,8 @@ def reconstruct(args): # Run the sparse reconstruction. - subprocess.call([os.path.join(args.colmap_path, "mapper"), + subprocess.call([os.path.join(args.colmap_path, "colmap"), + "mapper", "--database_path", database_path, "--image_path", image_path, "--export_path", sparse_path, @@ -163,7 +179,8 @@ def reconstruct(args): largest_model = None largest_model_num_images = 0 for model in models: - subprocess.call([os.path.join(args.colmap_path, "model_converter"), + subprocess.call([os.path.join(args.colmap_path, "colmap"), + "model_converter", "--input_path", os.path.join(sparse_path, model), "--output_path", os.path.join(sparse_path, model), "--output_type", "TXT"]) @@ -185,24 +202,27 @@ def reconstruct(args): if not os.path.exists(workspace_path): os.makedirs(workspace_path) - subprocess.call([os.path.join(args.colmap_path, "image_undistorter"), + subprocess.call([os.path.join(args.colmap_path, "colmap"), + "image_undistorter", "--image_path", image_path, "--input_path", largest_model_path, "--output_path", workspace_path, "--max_image_size", "1200"]) - subprocess.call([os.path.join(args.colmap_path, "dense_stereo"), + subprocess.call([os.path.join(args.colmap_path, "colmap"), + "patch_match_stereo", "--workspace_path", workspace_path, - "--DenseStereo.geom_consistency", "false"]) + "--PatchMatchStereo.geom_consistency", "false"]) - subprocess.call([os.path.join(args.colmap_path, "dense_fuser"), + subprocess.call([os.path.join(args.colmap_path, "colmap"), + "stereo_fusion", "--workspace_path", workspace_path, "--input_type", "photometric", "--output_path", os.path.join(workspace_path, "fused.ply"), - "--DenseFusion.min_num_pixels", "5"]) + "--StereoFusion.min_num_pixels", "5"]) stats = subprocess.check_output( - [os.path.join(args.colmap_path, "model_analyzer"), + [os.path.join(args.colmap_path, "colmap"), "model_analyzer", "--path", largest_model_path]) stats = stats.decode().split("\n") @@ -254,7 +274,7 @@ def main(): print(78 * "=") print("Formatted statistics") print(78 * "=") - print(" | ".join( + print("| " + " | ".join( map(str, [os.path.basename(args.dataset_path), "METHOD", matching_stats["num_images"], @@ -270,7 +290,7 @@ def main(): "", "", matching_stats["num_inlier_pairs"], - matching_stats["num_inlier_matches"]]))) + matching_stats["num_inlier_matches"]])) + " |") if __name__ == "__main__":