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__":