├── .cproject ├── .gitignore ├── .metadata ├── .lock ├── .mylyn │ └── repositories.xml.zip ├── .plugins │ ├── org.eclipse.cdt.make.core │ │ ├── specs.c │ │ └── specs.cpp │ ├── org.eclipse.core.resources │ │ ├── .root │ │ │ ├── .indexes │ │ │ │ ├── history.version │ │ │ │ ├── properties.index │ │ │ │ └── properties.version │ │ │ └── 1.tree │ │ └── .safetable │ │ │ └── org.eclipse.core.resources │ ├── org.eclipse.core.runtime │ │ └── .settings │ │ │ ├── org.eclipse.cdt.ui.prefs │ │ │ ├── org.eclipse.core.resources.prefs │ │ │ ├── org.eclipse.mylyn.context.core.prefs │ │ │ ├── org.eclipse.mylyn.monitor.ui.prefs │ │ │ ├── org.eclipse.mylyn.tasks.ui.prefs │ │ │ ├── org.eclipse.rse.core.prefs │ │ │ ├── org.eclipse.rse.ui.prefs │ │ │ ├── org.eclipse.team.cvs.ui.prefs │ │ │ ├── org.eclipse.team.ui.prefs │ │ │ ├── org.eclipse.ui.ide.prefs │ │ │ ├── org.eclipse.ui.prefs │ │ │ └── org.eclipse.ui.workbench.prefs │ ├── org.eclipse.e4.workbench │ │ └── workbench.xmi │ ├── org.eclipse.linuxtools.cdt.libhover │ │ └── C │ │ │ ├── devhelp.libhover │ │ │ └── glibc_library.libhover │ ├── org.eclipse.rse.core │ │ ├── initializerMarks │ │ │ └── org.eclipse.rse.internal.core.RSELocalConnectionInitializer.mark │ │ └── profiles │ │ │ └── PRF.naibaf7-a102_0 │ │ │ ├── FP.local.files_0 │ │ │ └── node.properties │ │ │ ├── H.local_16 │ │ │ └── node.properties │ │ │ └── node.properties │ ├── org.eclipse.ui.ide │ │ └── dialog_settings.xml │ └── org.eclipse.ui.workbench │ │ └── dialog_settings.xml └── version.ini ├── .project ├── .settings └── language.settings.xml ├── 3DPhoto_Report_Zorzi_Tschopp.pdf ├── LICENSE ├── Makefile ├── P3p.cpp ├── P3p.hpp ├── P4pf.cpp ├── P4pf.hpp ├── README.txt ├── RemoteSystemsTempFiles └── .project ├── SIFT_keypoint.hpp ├── SIFT_loader.cpp ├── SIFT_loader.hpp ├── benchmark.cpp ├── benchmark.hpp ├── bundler_camera.cpp ├── bundler_camera.hpp ├── data ├── Dubrovnik6K │ ├── README.txt │ ├── README_POSE.txt │ ├── bundle │ │ ├── bundle.db.out │ │ ├── bundle.orig.out │ │ └── list.orig.txt │ ├── list.db.txt │ ├── list.query.back.txt │ ├── list.query.dimensions.txt │ ├── list.query.txt │ └── query │ │ └── README.txt ├── README.txt ├── dubrovnik6k.info └── query │ └── README.txt ├── import_export.cpp ├── import_export.hpp ├── log.hpp ├── out └── README.txt ├── p3p_testing.cpp ├── p4p_testing.cpp ├── parse_bundler.cpp ├── parse_bundler.hpp ├── pose_estimation.cpp ├── pose_utils.cpp ├── pose_utils.hpp ├── query_loader.cpp ├── query_loader.hpp ├── query_processor.cpp ├── query_processor.hpp ├── query_processor_advanced.cpp ├── query_processor_basic.cpp └── tmp ├── README.txt └── tmp.tmp /.cproject: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 27 | 28 | 29 | 30 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs and databases # 2 | ###################### 3 | *.asv 4 | *.log 5 | 6 | # OS generated files # 7 | ###################### 8 | .DS_Store 9 | .DS_Store? 10 | ._* 11 | .Spotlight-V100 12 | .Trashes 13 | ehthumbs.db 14 | Thumbs.db 15 | desktop.ini 16 | *.dSYM 17 | *.fuse* 18 | 19 | # Specific folders # 20 | #################### 21 | pose_estimation 22 | pose_estimation_dbg 23 | p3p_testing 24 | p4p_testing 25 | -------------------------------------------------------------------------------- /.metadata/.lock: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/naibaf7/pose_estimation/d1d8b5472ebc01234d0af7b77e4746f364009090/.metadata/.lock -------------------------------------------------------------------------------- /.metadata/.mylyn/repositories.xml.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/naibaf7/pose_estimation/d1d8b5472ebc01234d0af7b77e4746f364009090/.metadata/.mylyn/repositories.xml.zip -------------------------------------------------------------------------------- /.metadata/.plugins/org.eclipse.cdt.make.core/specs.c: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /.metadata/.plugins/org.eclipse.cdt.make.core/specs.cpp: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /.metadata/.plugins/org.eclipse.core.resources/.root/.indexes/history.version: -------------------------------------------------------------------------------- 1 |  -------------------------------------------------------------------------------- /.metadata/.plugins/org.eclipse.core.resources/.root/.indexes/properties.index: -------------------------------------------------------------------------------- 1 | /org.eclipse.core.resourcescontentCacheState1contentCacheTimestamp 1420508830933 -------------------------------------------------------------------------------- /.metadata/.plugins/org.eclipse.core.resources/.root/.indexes/properties.version: -------------------------------------------------------------------------------- 1 |  -------------------------------------------------------------------------------- /.metadata/.plugins/org.eclipse.core.resources/.root/1.tree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/naibaf7/pose_estimation/d1d8b5472ebc01234d0af7b77e4746f364009090/.metadata/.plugins/org.eclipse.core.resources/.root/1.tree -------------------------------------------------------------------------------- /.metadata/.plugins/org.eclipse.core.resources/.safetable/org.eclipse.core.resources: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/naibaf7/pose_estimation/d1d8b5472ebc01234d0af7b77e4746f364009090/.metadata/.plugins/org.eclipse.core.resources/.safetable/org.eclipse.core.resources -------------------------------------------------------------------------------- /.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.cdt.ui.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | spelling_locale_initialized=true 3 | useAnnotationsPrefPage=true 4 | useQuickDiffPrefPage=true 5 | -------------------------------------------------------------------------------- /.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.core.resources.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | version=1 3 | -------------------------------------------------------------------------------- /.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.mylyn.context.core.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | mylyn.attention.migrated=true 3 | -------------------------------------------------------------------------------- /.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.mylyn.monitor.ui.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | org.eclipse.mylyn.monitor.activity.tracking.enabled.checked=true 3 | -------------------------------------------------------------------------------- /.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.mylyn.tasks.ui.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | migrated.task.repositories.secure.store=true 3 | org.eclipse.mylyn.tasks.ui.filters.nonmatching=true 4 | org.eclipse.mylyn.tasks.ui.filters.nonmatching.encouraged=true 5 | -------------------------------------------------------------------------------- /.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.rse.core.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | org.eclipse.rse.systemtype.local.systemType.defaultUserId=fabian 3 | -------------------------------------------------------------------------------- /.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.rse.ui.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | org.eclipse.rse.preferences.order.connections=naibaf7-a102.Local 3 | -------------------------------------------------------------------------------- /.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.team.cvs.ui.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | pref_first_startup=false 3 | -------------------------------------------------------------------------------- /.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.team.ui.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | org.eclipse.team.ui.first_time=false 3 | -------------------------------------------------------------------------------- /.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.ui.ide.prefs: -------------------------------------------------------------------------------- 1 | PROBLEMS_FILTERS_MIGRATE=true 2 | eclipse.preferences.version=1 3 | platformState=1420508830933 4 | quickStart=false 5 | tipsAndTricks=true 6 | -------------------------------------------------------------------------------- /.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.ui.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | showIntro=false 3 | -------------------------------------------------------------------------------- /.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.ui.workbench.prefs: -------------------------------------------------------------------------------- 1 | ENABLED_DECORATORS=org.eclipse.cdt.ui.indexedFiles\:false,org.eclipse.cdt.managedbuilder.ui.excludedFile\:true,org.eclipse.cdt.managedbuilder.ui.includeFolder\:true,org.eclipse.cdt.internal.ui.CustomBuildSettingsDecorator\:true,org.eclipse.egit.ui.internal.decorators.GitLightweightDecorator\:true,org.eclipse.linuxtools.tmf.ui.trace_folder.decorator\:true,org.eclipse.linuxtools.tmf.ui.experiment_folder.decorator\:true,org.eclipse.linuxtools.tmf.ui.linked_trace.decorator\:true,org.eclipse.mylyn.context.ui.decorator.interest\:true,org.eclipse.mylyn.tasks.ui.decorators.task\:true,org.eclipse.mylyn.team.ui.changeset.decorator\:true,org.eclipse.rse.core.virtualobject.decorator\:true,org.eclipse.rse.core.binary.executable.decorator\:true,org.eclipse.rse.core.script.executable.decorator\:true,org.eclipse.rse.core.java.executable.decorator\:true,org.eclipse.rse.core.library.decorator\:true,org.eclipse.rse.core.link.decorator\:true,org.eclipse.rse.subsystems.error.decorator\:true,org.eclipse.team.cvs.ui.decorator\:true,org.eclipse.ui.LinkedResourceDecorator\:true,org.eclipse.ui.SymlinkDecorator\:true,org.eclipse.ui.VirtualResourceDecorator\:true,org.eclipse.ui.ContentTypeDecorator\:true,org.eclipse.ui.ResourceFilterDecorator\:false, 2 | eclipse.preferences.version=1 3 | -------------------------------------------------------------------------------- /.metadata/.plugins/org.eclipse.linuxtools.cdt.libhover/C/devhelp.libhover: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/naibaf7/pose_estimation/d1d8b5472ebc01234d0af7b77e4746f364009090/.metadata/.plugins/org.eclipse.linuxtools.cdt.libhover/C/devhelp.libhover -------------------------------------------------------------------------------- /.metadata/.plugins/org.eclipse.linuxtools.cdt.libhover/C/glibc_library.libhover: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/naibaf7/pose_estimation/d1d8b5472ebc01234d0af7b77e4746f364009090/.metadata/.plugins/org.eclipse.linuxtools.cdt.libhover/C/glibc_library.libhover -------------------------------------------------------------------------------- /.metadata/.plugins/org.eclipse.rse.core/initializerMarks/org.eclipse.rse.internal.core.RSELocalConnectionInitializer.mark: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/naibaf7/pose_estimation/d1d8b5472ebc01234d0af7b77e4746f364009090/.metadata/.plugins/org.eclipse.rse.core/initializerMarks/org.eclipse.rse.internal.core.RSELocalConnectionInitializer.mark -------------------------------------------------------------------------------- /.metadata/.plugins/org.eclipse.rse.core/profiles/PRF.naibaf7-a102_0/FP.local.files_0/node.properties: -------------------------------------------------------------------------------- 1 | # RSE DOM Node 2 | 00-name=naibaf7-a102\:local.files 3 | 01-type=FilterPool 4 | 03-attr.default=true 5 | 03-attr.deletable=true 6 | 03-attr.id=local.files 7 | 03-attr.nonRenamable=false 8 | 03-attr.owningParentName=null 9 | 03-attr.release=200 10 | 03-attr.singleFilterStringOnly=false 11 | 03-attr.singleFilterStringOnlyESet=false 12 | 03-attr.stringsCaseSensitive=true 13 | 03-attr.supportsDuplicateFilterStrings=false 14 | 03-attr.supportsNestedFilters=true 15 | 03-attr.type=default 16 | 06-child.00000.00-name=My Home 17 | 06-child.00000.01-type=Filter 18 | 06-child.00000.03-attr.default=false 19 | 06-child.00000.03-attr.filterType=default 20 | 06-child.00000.03-attr.id=My Home 21 | 06-child.00000.03-attr.nonChangable=false 22 | 06-child.00000.03-attr.nonDeletable=false 23 | 06-child.00000.03-attr.nonRenamable=false 24 | 06-child.00000.03-attr.promptable=false 25 | 06-child.00000.03-attr.relativeOrder=0 26 | 06-child.00000.03-attr.release=200 27 | 06-child.00000.03-attr.singleFilterStringOnly=false 28 | 06-child.00000.03-attr.stringsCaseSensitive=true 29 | 06-child.00000.03-attr.stringsNonChangable=false 30 | 06-child.00000.03-attr.supportsDuplicateFilterStrings=false 31 | 06-child.00000.03-attr.supportsNestedFilters=true 32 | 06-child.00000.06-child.00000.00-name=/home/fabian/* 33 | 06-child.00000.06-child.00000.01-type=FilterString 34 | 06-child.00000.06-child.00000.03-attr.default=false 35 | 06-child.00000.06-child.00000.03-attr.string=/home/fabian/* 36 | 06-child.00000.06-child.00000.03-attr.type=default 37 | 06-child.00001.00-name=Root 38 | 06-child.00001.01-type=Filter 39 | 06-child.00001.03-attr.default=false 40 | 06-child.00001.03-attr.filterType=default 41 | 06-child.00001.03-attr.id=Root 42 | 06-child.00001.03-attr.nonChangable=false 43 | 06-child.00001.03-attr.nonDeletable=false 44 | 06-child.00001.03-attr.nonRenamable=false 45 | 06-child.00001.03-attr.promptable=false 46 | 06-child.00001.03-attr.relativeOrder=0 47 | 06-child.00001.03-attr.release=200 48 | 06-child.00001.03-attr.singleFilterStringOnly=false 49 | 06-child.00001.03-attr.stringsCaseSensitive=true 50 | 06-child.00001.03-attr.stringsNonChangable=false 51 | 06-child.00001.03-attr.supportsDuplicateFilterStrings=false 52 | 06-child.00001.03-attr.supportsNestedFilters=true 53 | 06-child.00001.06-child.00000.00-name=/* 54 | 06-child.00001.06-child.00000.01-type=FilterString 55 | 06-child.00001.06-child.00000.03-attr.default=false 56 | 06-child.00001.06-child.00000.03-attr.string=/* 57 | 06-child.00001.06-child.00000.03-attr.type=default 58 | -------------------------------------------------------------------------------- /.metadata/.plugins/org.eclipse.rse.core/profiles/PRF.naibaf7-a102_0/H.local_16/node.properties: -------------------------------------------------------------------------------- 1 | # RSE DOM Node 2 | 00-name=Local 3 | 01-type=Host 4 | 03-attr.description= 5 | 03-attr.hostname=LOCALHOST 6 | 03-attr.offline=false 7 | 03-attr.promptable=false 8 | 03-attr.systemType=org.eclipse.rse.systemtype.local 9 | 03-attr.type=Local 10 | 06-child.00000.00-name=Local Connector Service 11 | 06-child.00000.01-type=ConnectorService 12 | 06-child.00000.03-attr.group=Local Connector Service 13 | 06-child.00000.03-attr.port=0 14 | 06-child.00000.03-attr.useSSL=false 15 | 06-child.00000.06-child.00000.00-name=Local Files 16 | 06-child.00000.06-child.00000.01-type=SubSystem 17 | 06-child.00000.06-child.00000.03-attr.hidden=false 18 | 06-child.00000.06-child.00000.03-attr.type=local.files 19 | 06-child.00000.06-child.00000.06-child.00000.00-name=naibaf7-a102___naibaf7-a102\:local.files 20 | 06-child.00000.06-child.00000.06-child.00000.01-type=FilterPoolReference 21 | 06-child.00000.06-child.00000.06-child.00000.03-attr.refID=local.files 22 | 06-child.00000.06-child.00001.00-name=Local Shells 23 | 06-child.00000.06-child.00001.01-type=SubSystem 24 | 06-child.00000.06-child.00001.03-attr.hidden=false 25 | 06-child.00000.06-child.00001.03-attr.type=local.shells 26 | -------------------------------------------------------------------------------- /.metadata/.plugins/org.eclipse.rse.core/profiles/PRF.naibaf7-a102_0/node.properties: -------------------------------------------------------------------------------- 1 | # RSE DOM Node 2 | 00-name=naibaf7-a102 3 | 01-type=Profile 4 | 03-attr.defaultPrivate=true 5 | 03-attr.isActive=true 6 | 05-ref.00000=FP.local.files_0 7 | 05-ref.00001=H.local_16 8 | -------------------------------------------------------------------------------- /.metadata/.plugins/org.eclipse.ui.ide/dialog_settings.xml: -------------------------------------------------------------------------------- 1 | 2 |
3 |
4 | 5 | 6 |
7 |
8 | 9 | 10 |
11 |
12 | -------------------------------------------------------------------------------- /.metadata/.plugins/org.eclipse.ui.workbench/dialog_settings.xml: -------------------------------------------------------------------------------- 1 | 2 |
3 |
4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 |
16 | -------------------------------------------------------------------------------- /.metadata/version.ini: -------------------------------------------------------------------------------- 1 | #Mon Mar 02 09:06:37 CET 2015 2 | org.eclipse.core.runtime=2 3 | org.eclipse.platform=4.4.0.v20140925-0400 4 | -------------------------------------------------------------------------------- /.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | pose_estimation 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.cdt.managedbuilder.core.genmakebuilder 10 | clean,full,incremental, 11 | 12 | 13 | 14 | 15 | org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder 16 | full,incremental, 17 | 18 | 19 | 20 | 21 | 22 | org.eclipse.cdt.core.cnature 23 | org.eclipse.cdt.core.ccnature 24 | org.eclipse.cdt.managedbuilder.core.managedBuildNature 25 | org.eclipse.cdt.managedbuilder.core.ScannerConfigNature 26 | 27 | 28 | -------------------------------------------------------------------------------- /.settings/language.settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /3DPhoto_Report_Zorzi_Tschopp.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/naibaf7/pose_estimation/d1d8b5472ebc01234d0af7b77e4746f364009090/3DPhoto_Report_Zorzi_Tschopp.pdf -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | CXX = g++ 2 | CXXFLAGS = -Wall -std=c++11 3 | 4 | UNAME := $(shell uname -s) 5 | ifeq ($(UNAME), Linux) 6 | LINUX := 1 7 | else ifeq ($(UNAME), Darwin) 8 | OSX := 1 9 | endif 10 | 11 | ifneq ($(OSX), 1) 12 | CXXFLAGS += -fopenmp 13 | endif 14 | 15 | CXXRUN = -O3 16 | CXXDBG = -O0 -g -DDBG 17 | 18 | FILES = P3p.cpp P4pf.cpp parse_bundler.cpp bundler_camera.cpp SIFT_loader.cpp pose_utils.cpp query_loader.cpp query_processor_basic.cpp query_processor_advanced.cpp query_processor.cpp import_export.cpp benchmark.cpp 19 | 20 | INCLUDE = 21 | LIBRARY = -lopencv_core -lopencv_highgui -lopencv_imgproc 22 | 23 | all : pose_estimation pose_estimation_dbg p3p_testing p4p_testing 24 | 25 | pose_estimation : pose_estimation.cpp $(FILES) 26 | $(CXX) $(CXXFLAGS) $(CXXRUN) $(INCLUDE) -o pose_estimation pose_estimation.cpp $(FILES) $(LIBRARY) 27 | 28 | pose_estimation_dbg : pose_estimation.cpp $(FILES) 29 | $(CXX) $(CXXFLAGS) $(CXXDBG) $(INCLUDE) -o pose_estimation_dbg pose_estimation.cpp $(FILES) $(LIBRARY) 30 | 31 | p3p_testing: p3p_testing.cpp P3p.cpp P4pf.cpp 32 | $(CXX) $(CXXFLAGS) $(CXXDBG) $(INCLUDE) -o p3p_testing p3p_testing.cpp P3p.cpp P4pf.cpp $(LIBRARY) 33 | 34 | p4p_testing: p4p_testing.cpp P4pf.cpp 35 | $(CXX) $(CXXFLAGS) $(CXXDBG) $(INCLUDE) -o p4p_testing p4p_testing.cpp P4pf.cpp $(LIBRARY) 36 | 37 | clean: 38 | rm -r pose_estimation pose_estimation_dbg p3p_testing -------------------------------------------------------------------------------- /P3p.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011, Laurent Kneip, ETH Zurich 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * * Redistributions of source code must retain the above copyright 8 | * notice, this list of conditions and the following disclaimer. 9 | * * Redistributions in binary form must reproduce the above copyright 10 | * notice, this list of conditions and the following disclaimer in the 11 | * documentation and/or other materials provided with the distribution. 12 | * * Neither the name of ETH Zurich nor the 13 | * names of its contributors may be used to endorse or promote products 14 | * derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | * DISCLAIMED. IN NO EVENT SHALL ETH ZURICH BE LIABLE FOR ANY 20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | 28 | /* 29 | * P3p.cpp 30 | * 31 | * Created on: Nov 2, 2010 32 | * Author: Laurent Kneip 33 | * Description: Compute the absolute pose of a camera using three 3D-to-2D correspondences 34 | * Reference: A Novel Parametrization of the P3P-Problem for a Direct Computation of 35 | * Absolute Camera Position and Orientation 36 | * 37 | * Input: featureVectors: 3x3 matrix with UNITARY feature vectors (each column is a vector) 38 | * worldPoints: 3x3 matrix with corresponding 3D world points (each column is a point) 39 | * solutions: 3x16 matrix that will contain the solutions 40 | * form: [ 3x1 position(solution1) 3x3 orientation(solution1) 3x1 position(solution2) 3x3 orientation(solution2) ... ] 41 | * the obtained orientation matrices are defined as transforming points from the cam to the world frame 42 | * Output: int: 0 if correct execution 43 | * -1 if world points aligned 44 | */ 45 | 46 | #include "P3p.hpp" 47 | #include 48 | #include 49 | #include 50 | #include 51 | #include 52 | #include 53 | #include 54 | #include 55 | #include 56 | #include 57 | 58 | P3p::P3p() { 59 | } 60 | 61 | P3p::~P3p() { 62 | } 63 | 64 | int P3p::computePoses(Eigen::Matrix featureVectors, 65 | Eigen::Matrix worldPoints, 66 | Eigen::Matrix & solutions) { 67 | // Extraction of world points 68 | 69 | Eigen::Matrix P1 = worldPoints.col(0); 70 | Eigen::Matrix P2 = worldPoints.col(1); 71 | Eigen::Matrix P3 = worldPoints.col(2); 72 | 73 | // Verification that world points are not colinear 74 | 75 | Eigen::Matrix temp1 = P2 - P1; 76 | Eigen::Matrix temp2 = P3 - P1; 77 | 78 | if ((temp1.cross(temp2)).norm() == 0) 79 | return -1; 80 | 81 | // Extraction of feature vectors 82 | 83 | Eigen::Matrix f1 = featureVectors.col(0); 84 | Eigen::Matrix f2 = featureVectors.col(1); 85 | Eigen::Matrix f3 = featureVectors.col(2); 86 | 87 | // Creation of intermediate camera frame 88 | 89 | Eigen::Matrix e1 = f1; 90 | Eigen::Matrix e3 = f1.cross(f2); 91 | e3 = e3 / e3.norm(); 92 | Eigen::Matrix e2 = e3.cross(e1); 93 | 94 | Eigen::Matrix T; 95 | T.row(0) = e1; 96 | T.row(1) = e2; 97 | T.row(2) = e3; 98 | 99 | f3 = T * f3; 100 | 101 | // Reinforce that f3[2] > 0 for having theta in [0;pi] 102 | 103 | if (f3(2) > 0) { 104 | f1 = featureVectors.col(1); 105 | f2 = featureVectors.col(0); 106 | f3 = featureVectors.col(2); 107 | 108 | e1 = f1; 109 | e3 = f1.cross(f2); 110 | e3 = e3 / e3.norm(); 111 | e2 = e3.cross(e1); 112 | 113 | T.row(0) = e1; 114 | T.row(1) = e2; 115 | T.row(2) = e3; 116 | 117 | f3 = T * f3; 118 | 119 | P1 = worldPoints.col(1); 120 | P2 = worldPoints.col(0); 121 | P3 = worldPoints.col(2); 122 | } 123 | 124 | // Creation of intermediate world frame 125 | Eigen::Matrix n1 = P2 - P1; 126 | n1 = n1 / n1.norm(); 127 | Eigen::Matrix n3 = n1.cross(P3 - P1); 128 | n3 = n3 / n3.norm(); 129 | Eigen::Matrix n2 = n3.cross(n1); 130 | 131 | Eigen::Matrix N; 132 | N.row(0) = n1; 133 | N.row(1) = n2; 134 | N.row(2) = n3; 135 | 136 | // Extraction of known parameters 137 | 138 | P3 = N * (P3 - P1); 139 | 140 | double d_12 = (P2 - P1).norm(); 141 | double f_1 = f3(0) / f3(2); 142 | double f_2 = f3(1) / f3(2); 143 | double p_1 = P3(0); 144 | double p_2 = P3(1); 145 | 146 | double cos_beta = f1.dot(f2); 147 | double b = 1 / (1 - pow(cos_beta, 2)) - 1; 148 | 149 | if (cos_beta < 0) 150 | b = -sqrt(b); 151 | else 152 | b = sqrt(b); 153 | 154 | // Definition of temporary variables for avoiding multiple computation 155 | 156 | double f_1_pw2 = pow(f_1, 2); 157 | double f_2_pw2 = pow(f_2, 2); 158 | double p_1_pw2 = pow(p_1, 2); 159 | double p_1_pw3 = p_1_pw2 * p_1; 160 | double p_1_pw4 = p_1_pw3 * p_1; 161 | double p_2_pw2 = pow(p_2, 2); 162 | double p_2_pw3 = p_2_pw2 * p_2; 163 | double p_2_pw4 = p_2_pw3 * p_2; 164 | double d_12_pw2 = pow(d_12, 2); 165 | double b_pw2 = pow(b, 2); 166 | 167 | // Computation of factors of 4th degree polynomial 168 | 169 | Eigen::Matrix factors; 170 | 171 | factors(0) = -f_2_pw2 * p_2_pw4 - p_2_pw4 * f_1_pw2 - p_2_pw4; 172 | 173 | factors(1) = 2 * p_2_pw3 * d_12 * b + 2 * f_2_pw2 * p_2_pw3 * d_12 * b 174 | - 2 * f_2 * p_2_pw3 * f_1 * d_12; 175 | 176 | factors(2) = -f_2_pw2 * p_2_pw2 * p_1_pw2 177 | - f_2_pw2 * p_2_pw2 * d_12_pw2 * b_pw2 178 | - f_2_pw2 * p_2_pw2 * d_12_pw2 + f_2_pw2 * p_2_pw4 179 | + p_2_pw4 * f_1_pw2 + 2 * p_1 * p_2_pw2 * d_12 180 | + 2 * f_1 * f_2 * p_1 * p_2_pw2 * d_12 * b 181 | - p_2_pw2 * p_1_pw2 * f_1_pw2 + 2 * p_1 * p_2_pw2 * f_2_pw2 * d_12 182 | - p_2_pw2 * d_12_pw2 * b_pw2 - 2 * p_1_pw2 * p_2_pw2; 183 | 184 | factors(3) = 2 * p_1_pw2 * p_2 * d_12 * b + 2 * f_2 * p_2_pw3 * f_1 * d_12 185 | - 2 * f_2_pw2 * p_2_pw3 * d_12 * b - 2 * p_1 * p_2 * d_12_pw2 * b; 186 | 187 | factors(4) = -2 * f_2 * p_2_pw2 * f_1 * p_1 * d_12 * b 188 | + f_2_pw2 * p_2_pw2 * d_12_pw2 + 2 * p_1_pw3 * d_12 189 | - p_1_pw2 * d_12_pw2 + f_2_pw2 * p_2_pw2 * p_1_pw2 - p_1_pw4 190 | - 2 * f_2_pw2 * p_2_pw2 * p_1 * d_12 + p_2_pw2 * f_1_pw2 * p_1_pw2 191 | + f_2_pw2 * p_2_pw2 * d_12_pw2 * b_pw2; 192 | 193 | // Computation of roots 194 | 195 | Eigen::Matrix realRoots; 196 | 197 | this->solveQuartic(factors, realRoots); 198 | 199 | // Backsubstitution of each solution 200 | 201 | for (int i = 0; i < 4; i++) { 202 | double cot_alpha = (-f_1 * p_1 / f_2 - realRoots(i) * p_2 + d_12 * b) 203 | / (-f_1 * realRoots(i) * p_2 / f_2 + p_1 - d_12); 204 | 205 | double cos_theta = realRoots(i); 206 | double sin_theta = sqrt(1 - pow((double) realRoots(i), 2)); 207 | double sin_alpha = sqrt(1 / (pow(cot_alpha, 2) + 1)); 208 | double cos_alpha = sqrt(1 - pow(sin_alpha, 2)); 209 | 210 | if (cot_alpha < 0) 211 | cos_alpha = -cos_alpha; 212 | 213 | Eigen::Matrix C( 214 | d_12 * cos_alpha * (sin_alpha * b + cos_alpha), 215 | cos_theta * d_12 * sin_alpha * (sin_alpha * b + cos_alpha), 216 | sin_theta * d_12 * sin_alpha * (sin_alpha * b + cos_alpha)); 217 | 218 | C = P1 + N.transpose() * C; 219 | 220 | Eigen::Matrix R; 221 | R.row(0) << -cos_alpha, 222 | -sin_alpha * cos_theta, -sin_alpha * sin_theta; 223 | R.row(1) << sin_alpha, 224 | -cos_alpha * cos_theta, -cos_alpha * sin_theta; 225 | R.row(2) << 0, -sin_theta, cos_theta; 226 | 227 | R = N.transpose() * R.transpose() * T; 228 | 229 | solutions.col(i * 4) = C; 230 | solutions.col(i * 4 + 1) = R.col(0); 231 | solutions.col(i * 4 + 2) = R.col(1); 232 | solutions.col(i * 4 + 3) = R.col(2); 233 | } 234 | 235 | return 0; 236 | } 237 | 238 | int P3p::solveQuartic(Eigen::Matrix factors, 239 | Eigen::Matrix & realRoots) { 240 | double A = factors[0]; 241 | double B = factors[1]; 242 | double C = factors[2]; 243 | double D = factors[3]; 244 | double E = factors[4]; 245 | 246 | double A_pw2 = A * A; 247 | double B_pw2 = B * B; 248 | double A_pw3 = A_pw2 * A; 249 | double B_pw3 = B_pw2 * B; 250 | double A_pw4 = A_pw3 * A; 251 | double B_pw4 = B_pw3 * B; 252 | 253 | double alpha = -3 * B_pw2 / (8 * A_pw2) + C / A; 254 | double beta = B_pw3 / (8 * A_pw3) - B * C / (2 * A_pw2) + D / A; 255 | double gamma = -3 * B_pw4 / (256 * A_pw4) + B_pw2 * C / (16 * A_pw3) 256 | - B * D / (4 * A_pw2) + E / A; 257 | 258 | double alpha_pw2 = alpha * alpha; 259 | double alpha_pw3 = alpha_pw2 * alpha; 260 | 261 | std::complex P(-alpha_pw2 / 12 - gamma, 0); 262 | std::complex Q( 263 | -alpha_pw3 / 108 + alpha * gamma / 3 - pow(beta, 2) / 8, 0); 264 | std::complex R = -Q / 2.0 265 | + sqrt(pow(Q, 2.0) / 4.0 + pow(P, 3.0) / 27.0); 266 | 267 | std::complex U = pow(R, (1.0 / 3.0)); 268 | std::complex y; 269 | 270 | if (U.real() == 0) 271 | y = -5.0 * alpha / 6.0 - pow(Q, (1.0 / 3.0)); 272 | else 273 | y = -5.0 * alpha / 6.0 - P / (3.0 * U) + U; 274 | 275 | std::complex w = sqrt(alpha + 2.0 * y); 276 | 277 | std::complex temp; 278 | 279 | temp = -B / (4.0 * A) 280 | + 0.5 * (w + sqrt(-(3.0 * alpha + 2.0 * y + 2.0 * beta / w))); 281 | realRoots(0) = temp.real(); 282 | temp = -B / (4.0 * A) 283 | + 0.5 * (w - sqrt(-(3.0 * alpha + 2.0 * y + 2.0 * beta / w))); 284 | realRoots(1) = temp.real(); 285 | temp = -B / (4.0 * A) 286 | + 0.5 * (-w + sqrt(-(3.0 * alpha + 2.0 * y - 2.0 * beta / w))); 287 | realRoots(2) = temp.real(); 288 | temp = -B / (4.0 * A) 289 | + 0.5 * (-w - sqrt(-(3.0 * alpha + 2.0 * y - 2.0 * beta / w))); 290 | realRoots(3) = temp.real(); 291 | 292 | return 0; 293 | } 294 | -------------------------------------------------------------------------------- /P3p.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011, Laurent Kneip, ETH Zurich 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * * Redistributions of source code must retain the above copyright 8 | * notice, this list of conditions and the following disclaimer. 9 | * * Redistributions in binary form must reproduce the above copyright 10 | * notice, this list of conditions and the following disclaimer in the 11 | * documentation and/or other materials provided with the distribution. 12 | * * Neither the name of ETH Zurich nor the 13 | * names of its contributors may be used to endorse or promote products 14 | * derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | * DISCLAIMED. IN NO EVENT SHALL ETH ZURICH BE LIABLE FOR ANY 20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | 28 | /* 29 | * P3p.h 30 | * 31 | * Created on: Nov 2, 2010 32 | * Author: Laurent Kneip 33 | * Description: Compute the absolute pose of a camera using three 3D-to-2D correspondences 34 | * Reference: A Novel Parametrization of the P3P-Problem for a Direct Computation of 35 | * Absolute Camera Position and Orientation 36 | * 37 | * Input: featureVectors: 3x3 matrix with UNITARY feature vectors (each column is a vector) 38 | * worldPoints: 3x3 matrix with corresponding 3D world points (each column is a point) 39 | * solutions: 3x16 matrix that will contain the solutions 40 | * form: [ 3x1 position(solution1) 3x3 orientation(solution1) 3x1 position(solution2) 3x3 orientation(solution2) ... ] 41 | * the obtained orientation matrices are defined as transforming points from the cam to the world frame 42 | * Output: int: 0 if correct execution 43 | * -1 if world points aligned 44 | */ 45 | 46 | #ifndef P3P_HPP_ 47 | #define P3P_HPP_ 48 | 49 | #include 50 | #include 51 | #include 52 | #include 53 | 54 | class P3p { 55 | public: 56 | P3p(); 57 | virtual ~P3p(); 58 | 59 | int computePoses( Eigen::Matrix featureVectors, Eigen::Matrix worldPoints, Eigen::Matrix & solutions ); 60 | int solveQuartic( Eigen::Matrix factors, Eigen::Matrix & realRoots ); 61 | }; 62 | 63 | #endif /* P3P_HPP_ */ 64 | -------------------------------------------------------------------------------- /P4pf.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * P4pf.h 3 | * 4 | * Created on: Feb 28, 2015 5 | * Author: Marco Zorzi 6 | */ 7 | 8 | #ifndef P4PF_HPP_ 9 | #define P4PF_HPP_ 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | class P4pf { 29 | public: 30 | P4pf(); 31 | virtual ~P4pf(); 32 | 33 | double signOf(double aNumber); 34 | 35 | Eigen::Matrix pointWisePower(Eigen::Matrix mat); 36 | 37 | int getRigidTransform2(Eigen::Matrix p1,Eigen::Matrix p2,bool bLeftHandSystem, std::vector>* solutions); 38 | 39 | int P4Pf_m(Eigen::Matrix m2D, Eigen::Matrix M3D, std::vector* focalLengths_m, std::vector>* rotationMatrices, std::vector>* translationVector ); 40 | 41 | int P4Pf(Eigen::Matrix m2D, Eigen::Matrix M3D, std::vector* focalLengths, std::vector>* rotationMatrices, std::vector>* translationVector ); 42 | 43 | int fillMatrix(Eigen::Matrix* matrix, int *arr, double value, int size); 44 | 45 | int p4pfcode(double glab, double glac, double glad, 46 | double glbc, double glbd, double glcd, 47 | double a1, double a2, double b1, double b2, 48 | double c1, double c2, double d1, double d2, std::vector>* solutions); 49 | 50 | double inline dabs(double a); 51 | 52 | void GJ(double *A, int rcnt, int ccnt, double tol); 53 | 54 | void p4pfmex(double *glab, double *a1, double *b1, double *c1, double *d1, Eigen::Matrix, 10, 10> *A); 55 | 56 | void CalcCoefs(double const *src1, double const *src2, double const *src3, double const *src4, double const *src5, double *dst1); 57 | 58 | 59 | }; 60 | 61 | #endif /* P4PF_HPP_ */ 62 | -------------------------------------------------------------------------------- /README.txt: -------------------------------------------------------------------------------- 1 | README for the 3D Project: Robust large scale localization 2 | 3 | Use the Makefile to compile the project. The program has command line options and should be self-explanatory. 4 | 5 | -== LIBRARIES: ==- 6 | OpenMP 7 | FLANN, Version 1.8.4 8 | OpenCV (Core, Highgui, Imgproc), Version 2.4.9 9 | 10 | 11 | -== SOURCE CODE: ==- 12 | The code is structured with the following files (excluding code we did not change or code ourselves, and those not critically relevant): 13 | -pose_estimation.cpp: Wraps all the high level functions and the command line interface. 14 | -benchmark.cpp: Contains the code for benchmarking the two approaches. 15 | -import_export.cpp: Code for result visualization and import/export. The output is Meshlab compatible. 16 | -P3p.cpp and P4pf.cpp: Code for the pose estimation calculations given 3 points with known focal length or 4 points with unknown focal length. Reprogrammed by us but with given starting code. 17 | -pose_utils.cpp: Small helper source for random functions and string modification operations. 18 | query_loader.cpp: Contains the code to load a query image with all parameters (image size, focal length, SIFT descriptors). It also contains the query class that stores final pose solutions. Additionally, the query loader can automatically grab the original images from flickr.com. 19 | -query_processor.cpp: Common class for the basic and advanced approach, including the reprojection/inlier test. 20 | -query_processor_basic.cpp: Basic approach implementation of RANSAC. 21 | -query_processor_advanced.cpp: Advanced approach, including co-occurence and backmatching. This file in which the algorithm by Y. Li et al. is implemented. 22 | 23 | 24 | -== PROJECT DATA: ==- 25 | The project data is distributed separately. It is best to use the Dubrovnik datasets, which are known to work. 26 | See here for the bundler output: 27 | http://www.cs.cornell.edu/projects/p2f/ 28 | Additionally, an INFO file (binary) of the dataset without the query poses is required. We cannot provide this file, due to its large size. 29 | 30 | It is explained in the "tmp", "out" and "data" folders README how to extract and place the data in order to get it working. 31 | -------------------------------------------------------------------------------- /RemoteSystemsTempFiles/.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | RemoteSystemsTempFiles 4 | 5 | 6 | 7 | 8 | 9 | 10 | org.eclipse.rse.ui.remoteSystemsTempNature 11 | 12 | 13 | -------------------------------------------------------------------------------- /SIFT_keypoint.hpp: -------------------------------------------------------------------------------- 1 | /*===========================================================================*\ 2 | * * 3 | * ACG Localizer * 4 | * Copyright (C) 2011 by Computer Graphics Group, RWTH Aachen * 5 | * www.rwth-graphics.de * 6 | * * 7 | *---------------------------------------------------------------------------* 8 | * This file is part of ACG Localizer * 9 | * * 10 | * ACG Localizer is free software: you can redistribute it and/or modify * 11 | * it under the terms of the GNU General Public License as published by * 12 | * the Free Software Foundation, either version 3 of the License, or * 13 | * (at your option) any later version. * 14 | * * 15 | * ACG Localizer is distributed in the hope that it will be useful, * 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 18 | * GNU General Public License for more details. * 19 | * * 20 | * You should have received a copy of the GNU General Public License * 21 | * along with ACG Localizer. If not, see . * 22 | * * 23 | \*===========================================================================*/ 24 | 25 | #ifndef SIFT_KEYPOINT_HH 26 | #define SIFT_KEYPOINT_HH 27 | 28 | /** 29 | * Simple class defining a SIFT-keypoint, excluding its descriptor. 30 | * 31 | * author : Torsten Sattler (tsattler@cs.rwth-aachen.de) 32 | * date : 11-02-2011 33 | **/ 34 | 35 | class SIFT_keypoint 36 | { 37 | public: 38 | float x; 39 | float y; 40 | float scale; 41 | float orientation; 42 | 43 | SIFT_keypoint( ) 44 | { 45 | x = y = scale = orientation = 0.0; 46 | } 47 | 48 | SIFT_keypoint( float x_, float y_, float scale_, float orientation_ ) 49 | { 50 | x = x_; 51 | y = y_; 52 | scale = scale_; 53 | orientation = orientation_; 54 | } 55 | }; 56 | 57 | enum SIFT_FORMAT{ 58 | LOWE = 0, 59 | UNDEFINED = 3 60 | }; 61 | 62 | #endif -------------------------------------------------------------------------------- /SIFT_loader.cpp: -------------------------------------------------------------------------------- 1 | /*===========================================================================*\ 2 | * * 3 | * ACG Localizer * 4 | * Copyright (C) 2011 by Computer Graphics Group, RWTH Aachen * 5 | * www.rwth-graphics.de * 6 | * * 7 | *---------------------------------------------------------------------------* 8 | * This file is part of ACG Localizer * 9 | * * 10 | * ACG Localizer is free software: you can redistribute it and/or modify * 11 | * it under the terms of the GNU General Public License as published by * 12 | * the Free Software Foundation, either version 3 of the License, or * 13 | * (at your option) any later version. * 14 | * * 15 | * ACG Localizer is distributed in the hope that it will be useful, * 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 18 | * GNU General Public License for more details. * 19 | * * 20 | * You should have received a copy of the GNU General Public License * 21 | * along with ACG Localizer. If not, see . * 22 | * * 23 | \*===========================================================================*/ 24 | 25 | #include "SIFT_loader.hpp" 26 | 27 | #include 28 | #include 29 | #include 30 | 31 | SIFT_loader::SIFT_loader() { 32 | mNbFeatures = 0; 33 | mKeypoints.clear(); 34 | mDescriptors.clear(); 35 | } 36 | 37 | SIFT_loader::~SIFT_loader() { 38 | clear_data(); 39 | } 40 | 41 | void SIFT_loader::load_features(const char *filename, SIFT_FORMAT format) { 42 | clear_data(); 43 | bool loaded = load_Lowe_features(filename); 44 | 45 | if (!loaded) 46 | std::cerr << "Could not load the features from the given file " 47 | << filename << std::endl; 48 | } 49 | 50 | bool SIFT_loader::save_features_lowe(const char *filename) { 51 | //now open the .sift file and read out the interest points 52 | // format: 53 | // 54 | // nb_keypoints size_descriptor (should be 128) 55 | // for each keypoint: 56 | // y x scale orientation(radians) 57 | // descripor( size_descriptor many unsigned char values) (6 lines with 20 values, 1 with 8 values) 58 | //the coordinates of the interest points are stored in a coordinate system in which the origin corresponds to the upper left of the image 59 | 60 | std::ofstream outstream(filename, std::ios::out); 61 | 62 | if (!outstream.is_open()) 63 | return false; 64 | 65 | // save the number of keypoints and the size of the descriptors 66 | outstream << mNbFeatures << " 128" << std::endl; 67 | 68 | // load the keypoints and their descriptors 69 | for (uint32_t i = 0; i < mNbFeatures; ++i) { 70 | outstream << mKeypoints[i].y << " " << mKeypoints[i].x << " " 71 | << mKeypoints[i].scale << " " << mKeypoints[i].orientation 72 | << std::endl; 73 | 74 | outstream << (int) mDescriptors[i][0] << " "; 75 | for (int j = 1; j < 128; ++j) { 76 | if (j % 20 == 0) 77 | outstream << std::endl; 78 | outstream << (int) mDescriptors[i][j] << " "; 79 | } 80 | outstream << std::endl; 81 | } 82 | 83 | outstream.close(); 84 | 85 | return true; 86 | } 87 | 88 | void SIFT_loader::clear_data() { 89 | for (uint32_t i = 0; i < mNbFeatures; ++i) { 90 | if (mDescriptors[i] != 0) 91 | delete[] mDescriptors[i]; 92 | mDescriptors[i] = 0; 93 | } 94 | mKeypoints.clear(); 95 | mDescriptors.clear(); 96 | } 97 | 98 | uint32_t SIFT_loader::get_nb_features() { 99 | return mNbFeatures; 100 | } 101 | 102 | std::vector& SIFT_loader::get_descriptors() { 103 | return mDescriptors; 104 | } 105 | 106 | std::vector& SIFT_loader::get_keypoints() { 107 | return mKeypoints; 108 | } 109 | 110 | bool SIFT_loader::load_Lowe_features(const char *filename) { 111 | //now open the .sift file and read out the interest points 112 | // format: 113 | // 114 | // nb_keypoints size_descriptor (should be 128) 115 | // for each keypoint: 116 | // y x scale orientation(radians) 117 | // descripor( size_descriptor many char values) (6 lines with 20 values, 1 with 8 values) 118 | //the coordinates of the interest points are stored in a coordinate system in which the origin corresponds to the upper left of the image 119 | 120 | std::ifstream instream(filename, std::ios::in); 121 | 122 | if (!instream.is_open()) 123 | return false; 124 | 125 | // read the number of keypoints and the size of the descriptors 126 | uint32_t size_descriptor; 127 | instream >> mNbFeatures >> size_descriptor; 128 | 129 | if (size_descriptor != 128) 130 | return false; 131 | 132 | // load the keypoints and their descriptors 133 | mKeypoints.resize(mNbFeatures); 134 | mDescriptors.resize(mNbFeatures, 0); 135 | 136 | double x, y, scale, orientation; 137 | unsigned int descriptor_element; 138 | 139 | for (uint32_t i = 0; i < mNbFeatures; ++i) { 140 | mDescriptors[i] = new unsigned char[128]; 141 | instream >> y >> x >> scale >> orientation; 142 | mKeypoints[i] = SIFT_keypoint(x, y, scale, orientation); 143 | 144 | // read the descriptor 145 | for (int j = 0; j < 128; ++j) { 146 | instream >> descriptor_element; 147 | mDescriptors[i][j] = (unsigned char) descriptor_element; 148 | } 149 | } 150 | 151 | instream.close(); 152 | 153 | return true; 154 | } 155 | 156 | -------------------------------------------------------------------------------- /SIFT_loader.hpp: -------------------------------------------------------------------------------- 1 | /*===========================================================================*\ 2 | * * 3 | * ACG Localizer * 4 | * Copyright (C) 2011 by Computer Graphics Group, RWTH Aachen * 5 | * www.rwth-graphics.de * 6 | * * 7 | *---------------------------------------------------------------------------* 8 | * This file is part of ACG Localizer * 9 | * * 10 | * ACG Localizer is free software: you can redistribute it and/or modify * 11 | * it under the terms of the GNU General Public License as published by * 12 | * the Free Software Foundation, either version 3 of the License, or * 13 | * (at your option) any later version. * 14 | * * 15 | * ACG Localizer is distributed in the hope that it will be useful, * 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 18 | * GNU General Public License for more details. * 19 | * * 20 | * You should have received a copy of the GNU General Public License * 21 | * along with ACG Localizer. If not, see . * 22 | * * 23 | \*===========================================================================*/ 24 | 25 | #ifndef SIFT_LOADER_HH 26 | #define SIFT_LOADER_HH 27 | 28 | /** 29 | * Class to read SIFT features from the text files generated by 30 | * David Lowe's binary ( available at http://www.cs.ubc.ca/~lowe/keypoints/). 31 | * 32 | * IMPORTANT NOTE: The SIFT loader keeps the coordinate systems of the binaries. For example, 33 | * the origin of the coordinate system used by David Lowe is in the upper left of the image. 34 | * 35 | * author : Torsten Sattler (tsattler@cs.rwth-aachen.de) 36 | * date : 09-26-2011 37 | **/ 38 | 39 | #include 40 | #include 41 | 42 | #include "SIFT_keypoint.hpp" 43 | 44 | class SIFT_loader { 45 | public: 46 | //! constructor 47 | SIFT_loader(); 48 | 49 | //! destructor 50 | ~SIFT_loader(); 51 | 52 | //! load features from a file with a given format 53 | void load_features(const char *filename, SIFT_FORMAT format); 54 | 55 | //! save the features loaded to a file in David Lowes Format 56 | bool save_features_lowe(const char *filename); 57 | 58 | //! clears all data loaded so far 59 | void clear_data(); 60 | 61 | //! returns the number of features loaded 62 | uint32_t get_nb_features(); 63 | 64 | //! get access to a vector containg the descriptors (stored as chars) 65 | std::vector& get_descriptors(); 66 | 67 | //! get the keypoints 68 | std::vector& get_keypoints(); 69 | 70 | private: 71 | 72 | std::vector mKeypoints; 73 | std::vector mDescriptors; 74 | uint32_t mNbFeatures; 75 | 76 | bool load_Lowe_features(const char *filename); 77 | 78 | }; 79 | 80 | #endif 81 | -------------------------------------------------------------------------------- /benchmark.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * benchmark.cpp 3 | * 4 | * Created on: Mar 31, 2015 5 | * Author: Fabian Tschopp 6 | */ 7 | 8 | #include "benchmark.hpp" 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include "query_loader.hpp" 14 | #include "query_processor.hpp" 15 | #include "import_export.hpp" 16 | 17 | namespace pose_estimation { 18 | 19 | void Benchmark(QueryLoader &ql, parse_bundler &golden_pb, QueryProcessor *qp) { 20 | std::ofstream out_file; 21 | out_file.open("out/benchmark.txt"); 22 | assert(out_file.is_open()); 23 | 24 | for (int i = 0; i < ql.GetQueryCount(); ++i) { 25 | Query golden = LoadGoldenQuery(golden_pb, i, 26 | "data/Dubrovnik6K/bundle/"); 27 | 28 | Query query = ql.GetQuery(i, false); 29 | 30 | std::chrono::time_point start, end; 31 | start = std::chrono::high_resolution_clock::now(); 32 | qp->Process(query); 33 | end = std::chrono::high_resolution_clock::now(); 34 | 35 | double elapsed_seconds = 36 | std::chrono::duration(end - start).count(); 37 | 38 | double position_error = (golden.camera_position() 39 | - query.camera_position()).norm(); 40 | double rotation_error = (golden.camera_rotation() 41 | - query.camera_rotation()).norm(); 42 | 43 | double focal_length_error = (golden.focal_length() 44 | - query.focal_length()); 45 | 46 | std::cout << "=================================================" 47 | << std::endl; 48 | std::cout << "Index: " << i + 1 << std::endl; 49 | std::cout << "Image size: " << query.image_width() << " x " 50 | << query.image_height() << std::endl; 51 | std::cout << "Computation time: " << elapsed_seconds << " s" 52 | << std::endl; 53 | std::cout << "Position error: " << position_error << std::endl; 54 | std::cout << "Rotation error: " << rotation_error << std::endl; 55 | std::cout << "Focal length error: " << focal_length_error << std::endl; 56 | std::cout << "=================================================" 57 | << std::endl; 58 | 59 | out_file << (i + 1) << "," << std::setprecision(12) << elapsed_seconds 60 | << "," << std::setprecision(12) << position_error << "," 61 | << std::setprecision(12) << rotation_error << "," 62 | << std::setprecision(12) << focal_length_error << std::endl; 63 | out_file.flush(); 64 | 65 | } 66 | out_file.close(); 67 | } 68 | 69 | } 70 | -------------------------------------------------------------------------------- /benchmark.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * benchmark.hpp 3 | * 4 | * Created on: Mar 31, 2015 5 | * Author: Fabian Tschopp 6 | */ 7 | 8 | #ifndef BENCHMARK_HPP_ 9 | #define BENCHMARK_HPP_ 10 | 11 | #include "benchmark.hpp" 12 | #include "query_loader.hpp" 13 | #include "query_processor.hpp" 14 | 15 | namespace pose_estimation { 16 | 17 | void Benchmark(QueryLoader &ql, parse_bundler &golden_pb, QueryProcessor *qp); 18 | 19 | } 20 | 21 | #endif /* BENCHMARK_HPP_ */ 22 | -------------------------------------------------------------------------------- /bundler_camera.cpp: -------------------------------------------------------------------------------- 1 | /*===========================================================================*\ 2 | * * 3 | * ACG Localizer * 4 | * Copyright (C) 2011-2012 by Computer Graphics Group, RWTH Aachen * 5 | * www.rwth-graphics.de * 6 | * * 7 | *---------------------------------------------------------------------------* 8 | * This file is part of ACG Localizer * 9 | * * 10 | * ACG Localizer is free software: you can redistribute it and/or modify * 11 | * it under the terms of the GNU General Public License as published by * 12 | * the Free Software Foundation, either version 3 of the License, or * 13 | * (at your option) any later version. * 14 | * * 15 | * ACG Localizer is distributed in the hope that it will be useful, * 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 18 | * GNU General Public License for more details. * 19 | * * 20 | * You should have received a copy of the GNU General Public License * 21 | * along with ACG Localizer. If not, see . * 22 | * * 23 | \*===========================================================================*/ 24 | 25 | #include "bundler_camera.hpp" 26 | 27 | bundler_camera::bundler_camera() { 28 | rotation.setIdentity(); 29 | focal_length = 1.0; 30 | kappa_1 = kappa_2 = 0.0; 31 | translation[0] = translation[1] = translation[2] = 0.0; 32 | width = height = 0; 33 | } 34 | 35 | bundler_camera::~bundler_camera() { 36 | } 37 | 38 | //----------------------------------------------------------------------------- 39 | 40 | Eigen::Matrix bundler_camera::project_f( 41 | const Eigen::Matrix &p) const { 42 | Eigen::Matrix tmp; 43 | tmp = rotation * p; 44 | tmp += translation; 45 | tmp[2] *= -1.0; 46 | for (int i = 0; i < 2; ++i) 47 | tmp[i] /= tmp[2]; 48 | 49 | double length_sqr = pow((double) tmp[0], 2.0) + pow((double) tmp[1], 2.0); 50 | // compute radial distortion term 51 | double r = 1.0 + kappa_1 * length_sqr + kappa_2 * length_sqr * length_sqr; 52 | return Eigen::Matrix(focal_length * r * tmp[0], 53 | focal_length * r * tmp[1]); 54 | } 55 | 56 | //----------------------------------------------------------------------------- 57 | 58 | Eigen::Matrix bundler_camera::project_f_undist( 59 | const Eigen::Matrix &p) const { 60 | Eigen::Matrix tmp; 61 | tmp = rotation * p; 62 | tmp += translation; 63 | tmp[2] *= -1.0; 64 | for (int i = 0; i < 2; ++i) 65 | tmp[i] /= tmp[2]; 66 | 67 | return Eigen::Matrix(focal_length * tmp[0], 68 | focal_length * tmp[1]); 69 | } 70 | 71 | //----------------------------------------------------------------------------- 72 | 73 | Eigen::Matrix bundler_camera::project_d( 74 | const Eigen::Matrix &p) const { 75 | Eigen::Matrix tmp; 76 | tmp = rotation * p; 77 | tmp += translation; 78 | tmp[2] *= -1.0; 79 | for (int i = 0; i < 2; ++i) 80 | tmp[i] /= tmp[2]; 81 | 82 | double length_sqr = pow((double) tmp[0], 2.0) + pow((double) tmp[1], 2.0); 83 | // compute radial distortion term 84 | double r = 1.0 + kappa_1 * length_sqr + kappa_2 * length_sqr * length_sqr; 85 | return Eigen::Matrix(focal_length * r * tmp[0], 86 | focal_length * r * tmp[1]); 87 | } 88 | 89 | //----------------------------------------------------------------------------- 90 | 91 | Eigen::Matrix bundler_camera::project_d_undist( 92 | const Eigen::Matrix &p) const { 93 | Eigen::Matrix tmp; 94 | tmp = rotation * p; 95 | tmp += translation; 96 | tmp[2] *= -1.0; 97 | for (int i = 0; i < 2; ++i) 98 | tmp[i] /= tmp[2]; 99 | 100 | return Eigen::Matrix(focal_length * tmp[0], 101 | focal_length * tmp[1]); 102 | } 103 | 104 | //----------------------------------------------------------------------------- 105 | 106 | Eigen::Matrix bundler_camera::get_cam_global_vec_f( 107 | const Eigen::Matrix &_local) const { 108 | Eigen::Matrix g_pos; 109 | g_pos = _local.transpose() * rotation; 110 | return Eigen::Matrix(g_pos[0], g_pos[1], g_pos[2]); 111 | } 112 | 113 | //----------------------------------------------------------------------------- 114 | 115 | Eigen::Matrix bundler_camera::get_cam_global_vec_d( 116 | const Eigen::Matrix &_local) const { 117 | Eigen::Matrix g_pos; 118 | g_pos = _local.transpose() * rotation; 119 | return g_pos; 120 | } 121 | 122 | //----------------------------------------------------------------------------- 123 | 124 | Eigen::Matrix bundler_camera::get_cam_position_f() const { 125 | Eigen::Matrix g_pos; 126 | g_pos = translation.transpose() * rotation; 127 | return Eigen::Matrix(-g_pos[0], -g_pos[1], -g_pos[2]); 128 | } 129 | 130 | //----------------------------------------------------------------------------- 131 | 132 | Eigen::Matrix bundler_camera::get_cam_position_d() const { 133 | Eigen::Matrix g_pos; 134 | g_pos = translation.transpose() * rotation; 135 | return Eigen::Matrix(-g_pos[0], -g_pos[1], -g_pos[2]); 136 | } 137 | 138 | //----------------------------------------------------------------------------- 139 | 140 | double bundler_camera::compute_reprojection_error_f( 141 | Eigen::Matrix &p, float x, float y) const { 142 | double error = 0.0; 143 | 144 | Eigen::Matrix tmp, tmp2(p[0], p[1], p[2]); 145 | tmp = tmp2.transpose() * rotation; 146 | tmp += translation; 147 | tmp[2] *= -1.0; 148 | for (int i = 0; i < 2; ++i) 149 | tmp[i] /= tmp[2]; 150 | 151 | double length_sqr = pow((double) tmp[0], 2.0) + pow((double) tmp[1], 2.0); 152 | // compute radial distortion term 153 | double r = 1.0 + kappa_1 * length_sqr + kappa_2 * length_sqr * length_sqr; 154 | 155 | Eigen::Matrix proj_point(focal_length * r * (double) tmp[0], 156 | focal_length * r * (double) tmp[1]); 157 | 158 | error += (x - proj_point[0]) * (x - proj_point[0]); 159 | error += (y - proj_point[1]) * (y - proj_point[1]); 160 | 161 | // std::cout << proj_point << " vs ( " << x << " , " << y << " ) " << std::endl; 162 | 163 | return sqrt(error); 164 | } 165 | 166 | //----------------------------------------------------------------------------- 167 | 168 | Eigen::Matrix bundler_camera::to_cam_coords_d( 169 | const Eigen::Matrix &p) const { 170 | Eigen::Matrix tmp; 171 | tmp = rotation * p; 172 | tmp += translation; 173 | 174 | return tmp; 175 | } 176 | 177 | -------------------------------------------------------------------------------- /bundler_camera.hpp: -------------------------------------------------------------------------------- 1 | /*===========================================================================*\ 2 | * * 3 | * ACG Localizer * 4 | * Copyright (C) 2011-2012 by Computer Graphics Group, RWTH Aachen * 5 | * www.rwth-graphics.de * 6 | * * 7 | *---------------------------------------------------------------------------* 8 | * This file is part of ACG Localizer * 9 | * * 10 | * ACG Localizer is free software: you can redistribute it and/or modify * 11 | * it under the terms of the GNU General Public License as published by * 12 | * the Free Software Foundation, either version 3 of the License, or * 13 | * (at your option) any later version. * 14 | * * 15 | * ACG Localizer is distributed in the hope that it will be useful, * 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 18 | * GNU General Public License for more details. * 19 | * * 20 | * You should have received a copy of the GNU General Public License * 21 | * along with ACG Localizer. If not, see . * 22 | * * 23 | \*===========================================================================*/ 24 | 25 | #ifndef BUNDLER_CAMERA_HH 26 | #define BUNDLER_CAMERA_HH 27 | 28 | /** 29 | * Class to model a Camera in a Bundler reconstruction. 30 | * 31 | * author: Torsten Sattler (tsattler@cs.rwth-aachen.de) 32 | * date : 09-26-2011 33 | **/ 34 | 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | 41 | /** 42 | * Class for storing a camera consisting of a rotation matrix, 43 | * a translation vector, a focal length value and two parameters 44 | * accounting for radial distortion 45 | * 46 | * Author: Torsten Sattler 47 | * Date: 08-02-2010 48 | **/ 49 | 50 | class bundler_camera { 51 | public: 52 | //! constructor 53 | bundler_camera(); 54 | 55 | //! destructor 56 | ~bundler_camera(); 57 | 58 | //! project a 3D point to 2D float coordinates (centered around the principal point of the camera) 59 | Eigen::Matrix project_f( 60 | const Eigen::Matrix &p) const; 61 | 62 | //! project a 3D point to 2D float coordinates (centered around the principal point of the camera), without distorting it 63 | Eigen::Matrix project_f_undist( 64 | const Eigen::Matrix &p) const; 65 | 66 | //! project a 3D point to 2D double coordinates (centered around the principal point of the camera) 67 | Eigen::Matrix project_d( 68 | const Eigen::Matrix &p) const; 69 | 70 | //! project a 3D point to 2D double coordinates (centered around the principal point of the camera), without distorting it 71 | Eigen::Matrix project_d_undist( 72 | const Eigen::Matrix &p) const; 73 | 74 | //! compute the 3D direction of the camera in world space 75 | Eigen::Matrix get_cam_global_vec_f( 76 | const Eigen::Matrix &_local) const; 77 | 78 | //! compute the 3D direction of the camera in world space 79 | Eigen::Matrix get_cam_global_vec_d( 80 | const Eigen::Matrix &_local) const; 81 | 82 | //! compute the 3D position of the camera in world space 83 | Eigen::Matrix get_cam_position_f() const; 84 | 85 | //! compute the 3D position of the camera in world space 86 | Eigen::Matrix get_cam_position_d() const; 87 | 88 | //! compute the reprojection error of a 3D point and a 2D point 89 | double compute_reprojection_error_f(Eigen::Matrix &p, float x, 90 | float y) const; 91 | 92 | //! compute the coordinates of the point in camera coordinates (remember, the camera looks down the -z axis!) 93 | Eigen::Matrix to_cam_coords_d( 94 | const Eigen::Matrix &p) const; 95 | 96 | Eigen::Matrix rotation; 97 | Eigen::Matrix translation; 98 | double focal_length; 99 | double kappa_1, kappa_2; 100 | uint32_t id; 101 | int width, height; 102 | 103 | }; 104 | 105 | #endif 106 | -------------------------------------------------------------------------------- /data/Dubrovnik6K/README.txt: -------------------------------------------------------------------------------- 1 | ===================================================== 2 | | README file for | 3 | | Cornell 3D Location Recognition Datasets | 4 | | http://www.cs.cornell.edu/projects/3Dlocation/ | 5 | | v1.0, April 2012 | 6 | ===================================================== 7 | 8 | This document describes the contents and format of the Cornell 3D 9 | Location Recognition Datasets. This dataset is designed especially 10 | for algorithms for 2D-to-3D matching, and as such includes a 3D SfM 11 | model for each dataset. 12 | 13 | If you use this dataset in a publication, please cite the paper: 14 | 15 | Yunpeng Li, Noah Snavely, and Daniel P. Huttenlocher. "Location 16 | Recognition using Prioritized Feature Matching." Proceedings of 17 | ECCV 2010. 18 | 19 | Please read the following carefully before using the dataset, as there 20 | are several important notes. *See especially the special notes on the 21 | Dubrovnik6K dataset at the end of this document.* 22 | 23 | -== I. Contents of each dataset ==- 24 | 25 | Each dataset consists of a database -- including SIFT keys a 3D 26 | structure-from-motion (SfM) model -- and a set of query images, 27 | consisting of a set of SIFT keys. Out of respect for Flickr users, we 28 | are not distributing the original images with this archive, but we can 29 | send the images separately if you require access to them. (Many of 30 | the images are available on Flickr as well.) 31 | 32 | In particular, the provided files are as follows: 33 | 34 | list.db.txt -- the list of database image files 35 | list.query.txt -- the list of query image files 36 | 37 | db/ -- directory containing *squeezed* database SIFT key files (see below) 38 | query/ -- directory containing query SIFT key files 39 | 40 | bundle/ -- directory with 3D SfM models 41 | bundle/list.orig.txt -- full list of images used to build the SfM model 42 | bundle/bundle.orig.out -- original SfM model, before removing test images 43 | bundle/bundle.db.out -- database SfM model, after removing test images 44 | (use this model for testing if you would like 45 | to use our SfM results) 46 | 47 | 48 | -== II. Description of file formats ==- 49 | 50 | This section describes file formats for each of the data types above, 51 | with special notes as appropriate. 52 | 53 | A. List files (list.db.txt, list.query.txt). 54 | 55 | List files specify filenames to images in jpg format, one per 56 | line (keep in mind that the actual jpg files are not distributed 57 | unless requested). In addition, if the focal length of the image 58 | has been estimated from Exif tags, then that is also included. 59 | 60 | Images without known focal length information are specified with 61 | a line with a single field, the image name. Example: 62 | 63 | query/10970812@N05_2553027508.jpg 64 | 65 | Images with known focal length information are specified with a 66 | line with three fields: the image name, a zero, and the Exif 67 | focal length. (The second field is always zero but may change in 68 | future datasets.) Example: 69 | 70 | query/11289373@N03_2733280477.jpg 0 1280.00000 71 | 72 | B. Key files 73 | 74 | We are providing (gzipped) SIFT key files for the database images 75 | and query images. One important note is that the database keys 76 | are *not* the original set of SIFT keys, but the set of SIFT keys 77 | after removing features that did not end up getting used for 78 | reconstruction (i.e., SIFT features that do not correspond to a 79 | point in the 3D model). We will make the *original* database key 80 | files available as a separate download (see the project webpage). 81 | 82 | The format of the key files is the same as that produced by David 83 | Lowe's SIFT extractor, described here: 84 | 85 | http://www.cs.ubc.ca/~lowe/keypoints/ 86 | 87 | C. 3D SfM models 88 | 89 | We provide two 3D SfM models, computed using Bundler. The 90 | formats of these files are described here: 91 | 92 | http://phototour.cs.washington.edu/bundler/bundler-v0.4-manual.html#S6 93 | 94 | Description of files: 95 | 96 | - bundle.orig.out: Original bundle file, containing camera 97 | parameters for all database and query images. This can be 98 | used to compare recovered poses for query images to a "gold 99 | standard". 100 | 101 | - bundle.db.out: Database bundle file with query images removed 102 | (as well as any links between points and query images). This 103 | model is used during testing, to localize new images. 104 | Because it is registered with bundle.orig.out, camera 105 | parameters for images localized to bundle.out can be directly 106 | compared with those in bundle.orig.out. However, such 107 | comparisons should be take with a grain of salt, as the scale 108 | factor for the bundle files may not be meaningful. 109 | 110 | 111 | -== III. Accessing the original photos ==- 112 | 113 | While we are not distributing the original images with this archive, 114 | there are two ways to access the originals, if you need them. If you 115 | only need a few images (e.g., to show in a publication), then you can 116 | access photos directly on Flickr as follows: each photo filename has 117 | the form _.jpg. You can access Flickr 118 | photo through the Web with a URL of the form: 119 | 120 | http://www.flickr.com/photo_zoom.gne?id= 121 | 122 | e.g.: 123 | 124 | http://www.flickr.com/photo_zoom.gne?id=2000000000 125 | 126 | If you need all of the photos (for instance, because you'd like to 127 | re-extract features), then please send a request to the email 128 | addresses below. 129 | 130 | 131 | -== IV. Special notes for the Dubrovnik6K dataset ==- 132 | 133 | This dataset consists of a single large component for the Old Town of 134 | Dubrovnik. This reconstruction is not in any particular georegistered 135 | coordinate system, but is approximately metric---i.e. 1 unit in 136 | 'bundle file coordinates' is approximately 1 meter. This scaling was 137 | performed by approximately aligning the SfM reconstruction to a map. 138 | 139 | 140 | 141 | Questions? Email snavely@cs.cornell.edu and yuli@cs.cornell.edu. 142 | -------------------------------------------------------------------------------- /data/Dubrovnik6K/README_POSE.txt: -------------------------------------------------------------------------------- 1 | In order to get this running, you should replace the empty files in bundle, db and query with the respective files of the dataset (Dubrovnik). See README.txt in this folder. 2 | -------------------------------------------------------------------------------- /data/Dubrovnik6K/bundle/bundle.db.out: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/naibaf7/pose_estimation/d1d8b5472ebc01234d0af7b77e4746f364009090/data/Dubrovnik6K/bundle/bundle.db.out -------------------------------------------------------------------------------- /data/Dubrovnik6K/bundle/bundle.orig.out: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/naibaf7/pose_estimation/d1d8b5472ebc01234d0af7b77e4746f364009090/data/Dubrovnik6K/bundle/bundle.orig.out -------------------------------------------------------------------------------- /data/Dubrovnik6K/list.query.txt: -------------------------------------------------------------------------------- 1 | query/10187676@N06_2585379578.jpg 0 659.19732 2 | query/10563098@N03_2671651535.jpg 0 1800.52957 3 | query/10970812@N05_2553025324.jpg 4 | query/10970812@N05_2553025554.jpg 5 | query/10970812@N05_2553027508.jpg 6 | query/11289373@N03_2733280477.jpg 0 1280.00000 7 | query/11289373@N03_2734119856.jpg 0 3911.11111 8 | query/11289373@N03_2734121332.jpg 0 1280.00000 9 | query/11289373@N03_2734123662.jpg 10 | query/11482024@N05_2914633702.jpg 11 | query/11694071@N07_2864319720.jpg 0 651.05909 12 | query/12370857@N04_3005463302.jpg 13 | query/12879413@N08_2690203772.jpg 14 | query/13848472@N00_2610215224.jpg 15 | query/13937036@N03_2967889278.jpg 16 | query/13977437@N00_2677447196.jpg 17 | query/14214263@N04_2535233597.jpg 18 | query/14214263@N04_2535233605.jpg 19 | query/14214263@N04_2535233609.jpg 20 | query/14459556@N03_2392897117.jpg 0 1971.83099 21 | query/14459556@N03_2394406188.jpg 0 1295.77465 22 | query/14715434@N06_2571326295.jpg 23 | query/14883837@N00_2440278685.jpg 24 | query/15579207@N00_2606721801.jpg 25 | query/16268055@N06_2659313728.jpg 0 1664.49935 26 | query/16798538@N06_1808716980.jpg 27 | query/16798538@N06_1808718702.jpg 28 | query/17082199@N02_2388728366.jpg 0 989.13952 29 | query/17082199@N02_2388804442.jpg 0 989.13952 30 | query/17586261@N02_3007799985.jpg 31 | query/17586261@N02_3008623860.jpg 32 | query/19822463@N08_2269761680.jpg 33 | query/2008_trip_2933108974.jpg 0 1622.37762 34 | query/20408181@N02_3014830595.jpg 0 2835.59322 35 | query/20932685@N02_2173913746.jpg 36 | query/21571379@N04_2710010728.jpg 37 | query/21571379@N04_2710017880.jpg 38 | query/22076511@N08_2448940275.jpg 0 1571.92982 39 | query/22114434@N04_2948045360.jpg 40 | query/22133391@N03_2667064610.jpg 0 1649.94426 41 | query/22133391@N03_2667070424.jpg 0 4080.26756 42 | query/22133391@N03_2678899424.jpg 0 1649.94426 43 | query/22133391@N03_2678929132.jpg 0 2408.02676 44 | query/22380660@N03_2895491123.jpg 0 1297.29730 45 | query/22380660@N03_2896320588.jpg 0 1297.29730 46 | query/22417886@N02_2161465651.jpg 47 | query/22417886@N02_2162265530.jpg 48 | query/22453911@N08_2158932584.jpg 49 | query/22486586@N04_2811253219.jpg 50 | query/22976908@N05_2206856901.jpg 51 | query/23039285@N07_2667831129.jpg 52 | query/23389842@N02_2910357298.jpg 0 4745.76271 53 | query/24089026@N03_2967128263.jpg 0 1297.29730 54 | query/24089026@N03_2967977142.jpg 0 1297.29730 55 | query/24089026@N03_2967980984.jpg 0 1297.29730 56 | query/24151047@N05_2464116122.jpg 57 | query/24456415@N06_2744497179.jpg 0 900.90090 58 | query/24628901@N02_2574630115.jpg 0 1613.91304 59 | query/25103127@N08_2926155203.jpg 60 | query/26084863@N06_2802076945.jpg 0 1286.71329 61 | query/26284224@N03_2489079465.jpg 0 3432.20339 62 | query/26304435@N08_2830721802.jpg 63 | query/26307256@N00_3147187431.jpg 0 2835.44304 64 | query/26307256@N00_3147483967.jpg 0 1215.18987 65 | query/26307256@N00_3147525773.jpg 0 1215.18987 66 | query/26307256@N00_3147642323.jpg 0 12827.00422 67 | query/26307256@N00_3147726763.jpg 0 3713.08017 68 | query/26307256@N00_3147997200.jpg 0 1215.18987 69 | query/26307256@N00_3148001184.jpg 0 1215.18987 70 | query/26307256@N00_3148092612.jpg 0 1215.18987 71 | query/26307256@N00_3148352036.jpg 0 1755.27426 72 | query/26307256@N00_3148386234.jpg 0 1755.27426 73 | query/26475579@N04_2501843211.jpg 74 | query/26610371@N03_2494830093.jpg 75 | query/26770207@N06_2508348054.jpg 76 | query/26770207@N06_2508359182.jpg 77 | query/26814776@N07_2514643509.jpg 78 | query/26814776@N07_2514672893.jpg 79 | query/26814776@N07_2515502486.jpg 80 | query/27126588@N04_2643344621.jpg 81 | query/27228576@N05_2546556066.jpg 0 2855.38462 82 | query/27232974@N02_2540747831.jpg 83 | query/27244689@N07_2910054459.jpg 0 1248.64865 84 | query/27308741@N08_2542184810.jpg 85 | query/27683973@N08_2847989538.jpg 86 | query/27683973@N08_2847999054.jpg 87 | query/27924067@N03_2705704477.jpg 88 | query/27970209@N03_2608778028.jpg 89 | query/28019802@N07_2644435025.jpg 90 | query/28359466@N00_2062272019.jpg 91 | query/28359466@N00_2063053126.jpg 92 | query/28518816@N05_2664348434.jpg 93 | query/28518816@N05_2664353646.jpg 94 | query/28944955@N08_2722353746.jpg 95 | query/29369339@N07_2743232591.jpg 96 | query/29369339@N07_2744068358.jpg 97 | query/29381920@N03_3144547427.jpg 98 | query/29461294@N03_2755463650.jpg 99 | query/29580323@N04_2765465719.jpg 100 | query/29580323@N04_2765467183.jpg 101 | query/29875452@N03_2986884646.jpg 0 2227.13472 102 | query/29875452@N03_2986927194.jpg 0 8415.93928 103 | query/29893353@N08_2791509233.jpg 0 1622.37762 104 | query/30035266@N02_2813717259.jpg 105 | query/30035266@N02_2814562220.jpg 106 | query/30091863@N08_2852247675.jpg 0 654.86968 107 | query/30152331@N03_2924607035.jpg 0 1750.00000 108 | query/30152331@N03_2924610367.jpg 0 1750.00000 109 | query/30152331@N03_2975625167.jpg 0 1750.00000 110 | query/30152331@N03_2976494806.jpg 0 1750.00000 111 | query/30298058@N04_2841276752.jpg 0 1606.02258 112 | query/30440278@N08_2846501979.jpg 0 1564.44444 113 | query/30540944@N07_2861784043.jpg 114 | query/30540944@N07_2861795101.jpg 115 | query/30690897@N04_3107201742.jpg 116 | query/30697648@N03_2876115281.jpg 117 | query/30910112@N07_3114164047.jpg 118 | query/31031857@N05_3014747091.jpg 0 3728.81356 119 | query/31031857@N05_3014750201.jpg 0 2711.86441 120 | query/31190480@N08_2991332085.jpg 121 | query/31789411@N00_3219359083.jpg 122 | query/31920037@N06_2983892553.jpg 123 | query/31920037@N06_2983893289.jpg 124 | query/32503543@N00_2678403562.jpg 125 | query/32591868@N05_3057663857.jpg 126 | query/32591868@N05_3058500326.jpg 127 | query/32664337@N04_3050810031.jpg 128 | query/32733033@N04_3254238421.jpg 129 | query/32807865@N00_2793428183.jpg 130 | query/32807865@N00_2793476847.jpg 131 | query/32807865@N00_2794436936.jpg 132 | query/33576593@N03_3125664749.jpg 0 1036.61972 133 | query/33576593@N03_3125666365.jpg 0 1036.61972 134 | query/33576593@N03_3125666651.jpg 0 1036.61972 135 | query/33576593@N03_3126493232.jpg 0 1036.61972 136 | query/33576593@N03_3126495692.jpg 0 1036.61972 137 | query/33884503@N05_3156025103.jpg 138 | query/39847834@N00_2593029919.jpg 0 4191.75028 139 | query/39847834@N00_2593860934.jpg 0 1716.83389 140 | query/40765745@N00_2828795206.jpg 141 | query/47615848@N00_2597720259.jpg 0 1739.13043 142 | query/47627971@N00_2731871803.jpg 143 | query/51405727@N00_2283558663.jpg 144 | query/59706944@N00_2526525608.jpg 145 | query/5n4k3_2760651317.jpg 0 3254.23729 146 | query/5pointloperist_2921626253.jpg 0 3194.44444 147 | query/60144575@N00_2271757529.jpg 148 | query/60144575@N00_2271759903.jpg 149 | query/61371939@N00_2334124522.jpg 150 | query/62047576@N00_2658832785.jpg 151 | query/66323405@N00_1892984533.jpg 0 1729.72973 152 | query/67715433@N00_2598606017.jpg 0 1622.37762 153 | query/67715433@N00_2598622711.jpg 0 1639.46869 154 | query/67715433@N00_2598624689.jpg 0 4068.31120 155 | query/67715433@N00_2598629537.jpg 0 1622.37762 156 | query/67715433@N00_2599431616.jpg 0 1639.46869 157 | query/67715433@N00_2599434360.jpg 0 1622.37762 158 | query/67715433@N00_2599451626.jpg 0 1622.37762 159 | query/67715433@N00_2599453668.jpg 0 1622.37762 160 | query/67715433@N00_2599455002.jpg 0 1639.46869 161 | query/68044247@N00_2755668077.jpg 162 | query/70109145@N00_2873427575.jpg 0 1215.18987 163 | query/70109145@N00_2874250662.jpg 0 2160.33755 164 | query/70109145@N00_2874259692.jpg 0 1350.21097 165 | query/70109145@N00_2874260468.jpg 0 1350.21097 166 | query/709913_2965924567.jpg 0 1639.63964 167 | query/709913_2965924719.jpg 0 2752.25225 168 | query/709913_2965924825.jpg 0 1670.81081 169 | query/709913_2966770108.jpg 0 1639.63964 170 | query/7145465@N07_3065208814.jpg 171 | query/7286581@N04_2243494109.jpg 172 | query/7620508@N08_2118946261.jpg 173 | query/7962394@N02_2805183168.jpg 0 2545.45455 174 | query/79945970@N00_2822482676.jpg 175 | query/80066535@N00_2413693465.jpg 176 | query/80066535@N00_2414517340.jpg 177 | query/8117903@N06_2955594865.jpg 178 | query/8117903@N06_2955597385.jpg 179 | query/8117903@N06_2955599563.jpg 180 | query/8117903@N06_2956436946.jpg 181 | query/8117903@N06_2956445004.jpg 182 | query/8223442@N02_3166679121.jpg 183 | query/8223442@N02_3166686897.jpg 184 | query/8223442@N02_3167519460.jpg 185 | query/8230219@N07_2770473807.jpg 0 1133.81944 186 | query/8230219@N07_2771321304.jpg 0 1133.81944 187 | query/8230219@N07_2771334346.jpg 0 1133.81944 188 | query/83259769@N00_3026801995.jpg 0 1485.23207 189 | query/83259769@N00_3027646588.jpg 0 1215.18987 190 | query/83259769@N00_3029678796.jpg 0 1215.18987 191 | query/84249751@N00_2754252445.jpg 0 2385.73021 192 | query/86211001@N00_3110478331.jpg 193 | query/8639779@N03_2547620149.jpg 194 | query/8639779@N03_2548444038.jpg 195 | query/8639779@N03_2548446148.jpg 196 | query/8711070@N05_2786997381.jpg 197 | query/8950619@N03_2818463457.jpg 198 | query/8950619@N03_2819280484.jpg 199 | query/9006531@N02_2932256458.jpg 0 1270.90301 200 | query/90346741@N00_2599907700.jpg 201 | query/9141420@N03_2861334094.jpg 202 | query/9492996@N07_2667667196.jpg 203 | query/97317675@N00_2736380498.jpg 204 | query/aafkeblom_2427815127.jpg 205 | query/abbedegroot_3173452926.jpg 206 | query/a_b_i_2480808497.jpg 207 | query/acidopuro_2760697350.jpg 0 833.33333 208 | query/adam_torrey_2944179011.jpg 0 1480.71979 209 | query/adam_torrey_2945068552.jpg 0 1480.71979 210 | query/adventuresinliving_2615614140.jpg 0 1215.18987 211 | query/adventuresinliving_2624173275.jpg 0 1282.70042 212 | query/aherne_2849405553.jpg 213 | query/aisipos_2756580511.jpg 0 1649.94426 214 | query/aisipos_2756583177.jpg 0 1649.94426 215 | query/ajy_2972236183.jpg 216 | query/ajy_2972253029.jpg 0 1666.66667 217 | query/ajy_2972271307.jpg 0 1666.66667 218 | query/ajy_2972275533.jpg 0 1666.66667 219 | query/ajy_2972377505.jpg 0 1666.66667 220 | query/ajy_2972407069.jpg 0 1666.66667 221 | query/ajy_2972428239.jpg 0 2472.22222 222 | query/ajy_2973128698.jpg 0 1666.66667 223 | query/ajy_2973271470.jpg 0 1666.66667 224 | query/ale_fuhrmann_2796856926.jpg 0 1611.11111 225 | query/alena_keren_2719532151.jpg 226 | query/alenmatic_1762885363.jpg 227 | query/alenmatic_1763844704.jpg 228 | query/aliaseast_2708282942.jpg 0 2252.25225 229 | query/alihodza_2671908677.jpg 0 1098.77369 230 | query/almanesiac_3113746946.jpg 231 | query/alychz_2087454537.jpg 0 3389.83051 232 | query/alychz_2088135118.jpg 0 3525.42373 233 | query/alyon_2819261352.jpg 234 | query/amandablarson_2362046164.jpg 0 1605.35117 235 | query/andrejtrost_2680033477.jpg 0 1684.21053 236 | query/andrejtrost_2680851140.jpg 0 1684.21053 237 | query/andrejtrost_2680851952.jpg 0 1684.21053 238 | query/andrewlza_2952966859.jpg 239 | query/andymac66_2955467255.jpg 240 | query/andymac66_2955506981.jpg 241 | query/andymac66_2955543019.jpg 242 | query/andymac66_2956369838.jpg 243 | query/andymac66_2956409192.jpg 244 | query/anlopelope_2944184098.jpg 0 4666.66667 245 | query/apairudin_2450099972.jpg 0 1084.74576 246 | query/apairudin_2450101856.jpg 0 1864.40678 247 | query/awelch_2536869829.jpg 0 677.96610 248 | query/awelch_2537643236.jpg 0 677.96610 249 | query/awelch_2537732544.jpg 0 881.35593 250 | query/awelch_2537746374.jpg 0 677.96610 251 | query/awelch_2542279418.jpg 0 677.96610 252 | query/baby_root_2836628775.jpg 0 1611.11111 253 | query/baby_root_2836713617.jpg 0 1611.11111 254 | query/baby_root_2836714139.jpg 0 1611.11111 255 | query/baby_root_2836763611.jpg 0 1611.11111 256 | query/baby_root_2836779257.jpg 0 1611.11111 257 | query/baby_root_2837494424.jpg 0 3833.33333 258 | query/baby_root_2837497496.jpg 0 1611.11111 259 | query/baditude_2647928113.jpg 0 1611.11111 260 | query/barneykropf_2387764960.jpg 261 | query/b__art_3269696964.jpg 0 4684.68468 262 | query/bartkowy_2739560572.jpg 263 | query/bbinee_2850440535.jpg 264 | query/beardymarcus_2860610660.jpg 265 | query/believekevin_567687584.jpg 0 1611.11111 266 | query/benjaminlloyd_2858089661.jpg 267 | query/benkamorvan_2334904219.jpg 0 4342.85714 268 | query/blagoj51_3011113342.jpg 269 | query/blase_2201736233.jpg 0 1822.78481 270 | query/bracjun_2671862062.jpg 271 | query/brenski_2963128677.jpg 0 3254.23729 272 | query/brenski_2963142695.jpg 0 1220.33898 273 | query/brenski_2963983474.jpg 0 1220.33898 274 | query/brooklynunion_2840080268.jpg 275 | query/brooklynunion_2840080736.jpg 276 | query/bustedgirl_3001577125.jpg 277 | query/bw321_3010435487.jpg 278 | query/cabolleando_2724938974.jpg 279 | query/cal11211_3011029209.jpg 0 1898.90110 280 | query/cape-to-cairo_2753512372.jpg 0 1037.83784 281 | query/captainh_2384890747.jpg 0 3050.84746 282 | query/carolinecaleb_2596940948.jpg 0 1739.13043 283 | query/carpe_diem_terry_3068709259.jpg 0 1294.79769 284 | query/catandmike_2547284032.jpg 285 | query/catlin-whatley_2847220911.jpg 286 | query/ccarv_2583552749.jpg 287 | query/cdgp_2833080487.jpg 288 | query/cezaryg82_2844001574.jpg 0 4725.73840 289 | query/chadica_2752373051.jpg 0 3963.96396 290 | query/championship_2734885247.jpg 291 | query/championship_2735713052.jpg 292 | query/chaotictraveller_2882280578.jpg 0 2056.33803 293 | query/chaotictraveller_2882315718.jpg 0 1295.77465 294 | query/charliedave_2896805088.jpg 0 1611.11111 295 | query/charliedave_2896810638.jpg 0 1611.11111 296 | query/charliedave_2897889519.jpg 0 1611.11111 297 | query/charliedave_2897901007.jpg 0 1611.11111 298 | query/charliedave_2898730608.jpg 0 1611.11111 299 | query/cherryinhove_2514326625.jpg 0 2206.89655 300 | query/chriskracht_2448830435.jpg 0 1613.91304 301 | query/christielauryn_1760875050.jpg 302 | query/completetosh_2063426542.jpg 0 1485.23207 303 | query/cozminelu_2944680581.jpg 0 3603.60360 304 | query/cozminelu_2944681521.jpg 0 2378.37838 305 | query/cozminelu_2944682055.jpg 0 2018.01802 306 | query/cre8or_3124038141.jpg 0 1606.02258 307 | query/crlsblnc_2889624421.jpg 0 1513.51351 308 | query/croatia_kayak_2008_1888840167.jpg 309 | query/croatia_kayak_2008_1889137911.jpg 310 | query/croatia_kayak_2008_1889346556.jpg 311 | query/croatie-ucpa_2698135609.jpg 312 | query/croatie-ucpa_2698933144.jpg 313 | query/croatie-ucpa_2698942380.jpg 314 | query/croatie-ucpa_2725238256.jpg 315 | query/croatie-ucpa_2731884333.jpg 0 904.34783 316 | query/dalmet_2685515646.jpg 0 1200.35305 317 | query/danzink_2839562071.jpg 0 4000.00000 318 | query/danzink_3216470526.jpg 0 2378.37838 319 | query/darioalvarez_1673730509.jpg 320 | query/darioalvarez_1673794713.jpg 321 | query/darrellpratt_2529877514.jpg 0 1355.93220 322 | query/davidmichicich_2635114205.jpg 0 12101.43885 323 | query/davidmichicich_2635116013.jpg 0 4593.54839 324 | query/davidwaugh_2938887445.jpg 0 4977.77778 325 | query/davidwaugh_2939701556.jpg 0 1208.88889 326 | query/davidwaugh_2939717766.jpg 0 4337.77778 327 | query/deeandrews_3018050615.jpg 328 | query/deltapapa_2961695071.jpg 329 | query/dhoggan_2400002165.jpg 0 791.35135 330 | query/dianamak_2748260234.jpg 0 1645.24422 331 | query/dianamak_2748264030.jpg 0 1645.24422 332 | query/diannabentley_2865428201.jpg 0 6440.67797 333 | query/diannabentley_2866277468.jpg 0 1898.30508 334 | query/djfrenchfry_2470795804.jpg 0 1613.91304 335 | query/dmjb_3031237519.jpg 0 1295.77465 336 | query/donncindy_2609414168.jpg 0 1622.37762 337 | query/drivinghome_2705038497.jpg 0 1125.00000 338 | query/drivinghome_2705040893.jpg 0 3318.75000 339 | query/drivinghome_2705042395.jpg 0 1125.00000 340 | query/drivinghome_2705861966.jpg 0 4593.75000 341 | query/drivinghome_2706230906.jpg 0 1125.00000 342 | query/drivinghome_2708411522.jpg 0 3693.75000 343 | query/drivinghome_2830089604.jpg 0 2475.00000 344 | query/drmccarty_2740449681.jpg 0 3099.09910 345 | query/drmccarty_2741289984.jpg 0 1297.29730 346 | query/dublinmessenger_2926399747.jpg 0 1297.29730 347 | query/dudumuniz_2583927855.jpg 348 | query/eaglestein_2521706127.jpg 349 | query/eaglestein_2521710481.jpg 350 | query/eaglestein_2522530642.jpg 351 | query/etep_2533545227.jpg 352 | query/etep_2535610211.jpg 353 | query/etep_2535635061.jpg 354 | query/etep_2535638795.jpg 355 | query/euridice_1560592443.jpg 0 963.21070 356 | query/euridice_1561528090.jpg 0 963.21070 357 | query/exposedframe_2780741081.jpg 0 1525.42373 358 | query/fapian_3119312148.jpg 359 | query/ferdinand-stock_2768167488.jpg 0 940.46823 360 | query/fjavier_ep_2797345428.jpg 0 4782.54545 361 | query/flegma_3148574182.jpg 0 2882.88288 362 | query/florentsolt_2483086031.jpg 0 1611.11111 363 | query/florentsolt_2483122431.jpg 0 1611.11111 364 | query/florentsolt_2483126765.jpg 0 1611.11111 365 | query/florentsolt_2483127503.jpg 0 4000.00000 366 | query/florentsolt_2483942826.jpg 0 1611.11111 367 | query/flying_chef_2865607135.jpg 368 | query/fokeyjoe_2868308398.jpg 369 | query/fokeyjoe_2868368948.jpg 0 13559.32203 370 | query/francescoroman_2460845765.jpg 0 3603.60360 371 | query/freddie_2756659035.jpg 372 | query/frencisauro_2858905077.jpg 373 | query/frencisauro_2858906249.jpg 374 | query/frencisauro_2859739850.jpg 375 | query/frosted_peppercorn_2614565900.jpg 376 | query/frosted_peppercorn_2614579846.jpg 377 | query/frosted_peppercorn_2617200826.jpg 378 | query/gatorjoe_2631307229.jpg 0 1215.18987 379 | query/gatorjoe_2631307941.jpg 0 2565.40084 380 | query/gatorjoe_2631343237.jpg 0 1215.18987 381 | query/gatorjoe_2631363701.jpg 0 4725.73840 382 | query/gatorjoe_2631366201.jpg 0 4725.73840 383 | query/gatorjoe_2632172768.jpg 0 3713.08017 384 | query/gatorjoe_2632194352.jpg 0 2025.31646 385 | query/gavinflickr_2070760743.jpg 386 | query/gavinflickr_2071553632.jpg 387 | query/gavinflickr_2071553682.jpg 388 | query/gavinflickr_2071559910.jpg 389 | query/gbagoly_2814492709.jpg 0 3257.48503 390 | query/gbewsher_2847876637.jpg 0 1645.24422 391 | query/gbewsher_2847908493.jpg 0 1645.24422 392 | query/georgeandangie_2989103966.jpg 0 964.30493 393 | query/georgiagay_2886580808.jpg 0 1611.11111 394 | query/georgiagay_2886588366.jpg 0 1611.11111 395 | query/gmrack_2961400492.jpg 0 1627.11864 396 | query/gmrack_2987350783.jpg 0 6101.69492 397 | query/gonzalvo_2917468050.jpg 0 1294.38202 398 | query/grannd_2754589790.jpg 399 | query/grannd_2754590172.jpg 400 | query/guddi_2808387344.jpg 401 | query/guidonardi_2763306945.jpg 0 1628.07018 402 | query/haigstewart_2959919202.jpg 403 | query/hangele_2826252029.jpg 0 1153.15315 404 | query/hangele_2827097612.jpg 0 7610.81081 405 | query/hardcoreharry_2676306581.jpg 0 1611.11111 406 | query/hayleyevery_2986136649.jpg 0 833.33333 407 | query/heathersills_2653334410.jpg 408 | query/hershome_2637893767.jpg 0 677.96610 409 | query/hershome_2638645390.jpg 0 13559.32203 410 | query/hiro_imz_2881367199.jpg 411 | query/hollywood2hollywood_2441309186.jpg 0 1627.11864 412 | query/honingzoet_2822681826.jpg 413 | query/hrossvt_2786618967.jpg 0 1286.71329 414 | query/hrossvt_2787479150.jpg 0 1286.71329 415 | query/iberbiz_2607973161.jpg 416 | query/iberbiz_2607985891.jpg 417 | query/iberbiz_2608852980.jpg 418 | query/ide_bradley_3080212077.jpg 419 | query/iharsten_2735530288.jpg 420 | query/issarocks_2530205928.jpg 0 686.73611 421 | query/issarocks_2530206684.jpg 0 686.73611 422 | query/jameroo_2851576811.jpg 0 1613.91304 423 | query/jameroo_2851606425.jpg 0 1613.91304 424 | query/jameroo_2851616119.jpg 0 1613.91304 425 | query/jameroo_2851768731.jpg 0 1613.91304 426 | query/jameroo_2852528692.jpg 0 2810.43478 427 | query/jameroo_2852559508.jpg 0 1613.91304 428 | query/jamesandres_2782522353.jpg 0 3728.81356 429 | query/jamesandres_2782602691.jpg 0 3728.81356 430 | query/jamesandres_2782610431.jpg 0 1898.30508 431 | query/jamesandres_2782703145.jpg 0 1627.11864 432 | query/jamesintransit_2893857766.jpg 433 | query/jamiekitson_2800596429.jpg 0 3796.61017 434 | query/jandiano_2803084115.jpg 0 2018.01802 435 | query/jandiano_2803108677.jpg 0 2018.01802 436 | query/jandiano_2803149997.jpg 0 2018.01802 437 | query/jandiano_2803933696.jpg 0 6126.12613 438 | query/jandiano_2803941032.jpg 0 2738.73874 439 | query/jdmckinn_2644984733.jpg 0 1286.71329 440 | query/jeanniearthur_2850644603.jpg 0 1729.72973 441 | query/jeanniearthur_2851496548.jpg 0 2882.88288 442 | query/jeffevansdesjarinds_2081531456.jpg 0 2361.11111 443 | query/jemanuel_2996215514.jpg 0 1611.11111 444 | query/jenni40947_2753168602.jpg 0 3555.55556 445 | query/jenni40947_2756771090.jpg 0 1208.88889 446 | query/jesshabz_2668497055.jpg 0 1611.11111 447 | query/jesshabz_2668502705.jpg 0 2361.11111 448 | query/jesshabz_2669321698.jpg 0 1611.11111 449 | query/jessicamatson_2694870087.jpg 450 | query/jesuscm_2633429043.jpg 451 | query/jhuie_1744635215.jpg 452 | query/jimmyharris_2769921801.jpg 0 4095.32215 453 | query/jlagrosas_2417951377.jpg 454 | query/jmpeters33_2508388997.jpg 0 1277.77778 455 | query/jmpeters33_2508391419.jpg 0 1277.77778 456 | query/jmpeters33_2508393919.jpg 0 1277.77778 457 | query/jmpeters33_2508398779.jpg 0 2111.11111 458 | query/jmpeters33_2508401071.jpg 0 1277.77778 459 | query/jmpeters33_2508402409.jpg 0 3000.00000 460 | query/jmpeters33_2509224122.jpg 0 1694.44444 461 | query/jmpeters33_2509226108.jpg 0 4805.55556 462 | query/joeyliao_2678846095.jpg 0 1766.26316 463 | query/jonathanwolfson_2362866700.jpg 464 | query/jonobass_3023220008.jpg 0 2160.33755 465 | query/jorti_2864265137.jpg 0 1513.51351 466 | query/juansi_2804362890.jpg 467 | query/juansi_2804375108.jpg 468 | query/jvoelker_2621886654.jpg 0 2252.25225 469 | query/karenandrobert_3241539093.jpg 470 | query/karltje_2655725049.jpg 471 | query/karpersa_2223405910.jpg 472 | query/katchapillar_2200622816.jpg 473 | query/katiecar_2834762951.jpg 0 1824.32432 474 | query/katiecar_2835600236.jpg 0 1547.92793 475 | query/kayadams_2853047051.jpg 476 | query/kayadams_2853881076.jpg 477 | query/kdeme_2733881678.jpg 478 | query/kenbondy_2643541451.jpg 479 | query/kmclark2_2411481957.jpg 0 1613.91304 480 | query/kmclark2_2411485169.jpg 0 3673.04348 481 | query/kostrowski_2576471344.jpg 482 | query/kpi_2806312783.jpg 0 1687.76371 483 | query/kpi_2807155854.jpg 0 1215.18987 484 | query/kpmst7_2685810187.jpg 0 1627.64771 485 | query/kpmst7_2685838393.jpg 0 1627.64771 486 | query/kpmst7_2685910671.jpg 0 1627.64771 487 | query/kpmst7_2685928293.jpg 0 1627.64771 488 | query/kpmst7_2685993849.jpg 0 3857.30212 489 | query/kpmst7_2686635934.jpg 0 1627.64771 490 | query/kpmst7_2686639078.jpg 0 1627.64771 491 | query/kpmst7_2686645336.jpg 0 1627.64771 492 | query/kpmst7_2686673868.jpg 0 1627.64771 493 | query/kpmst7_2686715342.jpg 0 1627.64771 494 | query/kpmst7_2686731688.jpg 0 1627.64771 495 | query/krisa_1477277371.jpg 496 | query/krissy_dougie_2929097349.jpg 497 | query/kstevens_2692571674.jpg 498 | query/kwatts_2668227540.jpg 499 | query/kwatts_2668228438.jpg 500 | query/kwatts_2668230884.jpg 501 | query/kwsdurango_2111156248.jpg 0 1801.80180 502 | query/kwsdurango_2120945945.jpg 0 1585.58559 503 | query/kwsdurango_2292564472.jpg 0 3387.38739 504 | query/kwsdurango_2519060473.jpg 0 5045.04505 505 | query/lambced_2941681414.jpg 506 | query/lastra_3060147466.jpg 0 1277.77778 507 | query/latribri_2918838558.jpg 0 1611.11111 508 | query/lecyborg_2785818187.jpg 0 1765.32399 509 | query/lecyborg_2785832793.jpg 0 1765.32399 510 | query/lecyborg_2785840825.jpg 0 1765.32399 511 | query/lecyborg_2786684840.jpg 0 1765.32399 512 | query/lecyborg_2786699682.jpg 0 1765.32399 513 | query/lecyborg_2786702838.jpg 0 1765.32399 514 | query/leebarnett_2657740793.jpg 0 1639.46869 515 | query/leebarnett_2658538426.jpg 0 1639.46869 516 | query/leebarnett_2658554594.jpg 0 1639.46869 517 | query/leisneato_2831577109.jpg 0 792.79279 518 | query/leisneato_2832428996.jpg 0 792.79279 519 | query/lena_ni_2611077429.jpg 520 | query/letdown102_2237624767.jpg 0 2092.82700 521 | query/letdown102_2238412720.jpg 0 1552.74262 522 | query/lethalpixel_2829072519.jpg 0 1945.94595 523 | query/lethalpixel_2829351713.jpg 524 | query/libertylittlebasil_2795444376.jpg 525 | query/lieselrose_2815355116.jpg 0 1729.72973 526 | query/lifejacketadventures_2118452665.jpg 527 | query/lifejacketadventures_2886026306.jpg 528 | query/lindseyporter_2104848741.jpg 529 | query/lmlucoz_2862970759.jpg 0 4756.75676 530 | query/lmlucoz_2863110179.jpg 0 1585.58559 531 | query/lmlucoz_2864030344.jpg 0 6126.12613 532 | query/lmlucoz_2866153671.jpg 0 2378.37838 533 | query/lolaborrego_2753829932.jpg 534 | query/lorigros_3194460349.jpg 0 2157.30337 535 | query/lorigros_3194471593.jpg 0 1294.38202 536 | query/lorigros_3195317792.jpg 0 3811.23596 537 | query/lorigros_3195326380.jpg 0 2660.67416 538 | query/lorsoelettrico_2860558571.jpg 539 | query/lorsoelettrico_2860565347.jpg 540 | query/lucie777_2653194968.jpg 541 | query/luxagraf_341726727.jpg 0 2296.54404 542 | query/magdamazur_2489633378.jpg 543 | query/mailbags_2999892667.jpg 0 3413.33333 544 | query/marchinzpeter_2704420169.jpg 545 | query/marchinzpeter_2704567246.jpg 546 | query/marchinzpeter_2706117913.jpg 547 | query/marchinzpeter_2717152771.jpg 548 | query/marcisler_2845704042.jpg 549 | query/marcuscook_2895385819.jpg 0 4324.32432 550 | query/maresydoats_2615870724.jpg 0 1734.26573 551 | query/martinrak_2725314207.jpg 0 709.09091 552 | query/marvinous_2505976844.jpg 553 | query/mayescobar_2788761955.jpg 0 1032.72727 554 | query/mayescobar_2789604950.jpg 0 1425.45455 555 | query/mayescobar_2789608408.jpg 0 1265.45455 556 | query/mdh_pics_2634554542.jpg 0 2458.94737 557 | query/meyrat_2926829237.jpg 0 3955.05618 558 | query/mfcnunes_2890357247.jpg 0 3027.02703 559 | query/mfcnunes_2891160308.jpg 0 1513.51351 560 | query/mfcnunes_2891193564.jpg 0 1297.29730 561 | query/mhambleton_2521523571.jpg 562 | query/mhambleton_2522380790.jpg 563 | query/michaelcowan_2822540685.jpg 0 1208.88889 564 | query/michaelcowan_2823359748.jpg 0 6044.44444 565 | query/miguelos_2897800963.jpg 566 | query/miles82_2749588628.jpg 0 1291.47982 567 | query/mkkb_2917884620.jpg 0 1613.91304 568 | query/monica_italia_2789057957.jpg 0 3857.30212 569 | query/motti82_2820427569.jpg 0 9852.63158 570 | query/murleke_2828180294.jpg 571 | query/museo_2929109935.jpg 572 | query/myrcea_2814075276.jpg 573 | query/nabekor_3236783078.jpg 574 | query/nadiaphotos_2656029287.jpg 0 2083.33333 575 | query/nadiaphotos_2656108217.jpg 0 1611.11111 576 | query/nadiaphotos_2656907166.jpg 0 1611.11111 577 | query/nadiaphotos_2656940786.jpg 0 1611.11111 578 | query/nakatsu_kaori_2968255609.jpg 0 1634.04255 579 | query/nakatsu_kaori_2969095750.jpg 0 1089.36170 580 | query/nakatsu_kaori_2969096110.jpg 0 544.68085 581 | query/neocolor_2746285721.jpg 0 1297.29730 582 | query/neocolor_2748899435.jpg 0 1513.51351 583 | query/neocolor_2749740258.jpg 0 3963.96396 584 | query/nicholaslam_2986954933.jpg 585 | query/nicoalamo_2505447536.jpg 586 | query/nishizawa_2881485069.jpg 0 1549.90789 587 | query/nives_mestrovic_2691920581.jpg 0 960.28244 588 | query/nives_mestrovic_2692733914.jpg 0 508.38482 589 | query/nives_mestrovic_2693599632.jpg 0 508.38482 590 | query/ntysall_2371369361.jpg 0 3728.81356 591 | query/ntysall_2371386747.jpg 0 1152.54237 592 | query/ntysall_2372214868.jpg 0 1152.54237 593 | query/odilolima_2961014135.jpg 0 1552.74262 594 | query/ohword_2953191028.jpg 0 648.64865 595 | query/oliviersentucq_2652335766.jpg 0 800.00000 596 | query/orangebrompton_3141308667.jpg 0 1666.66667 597 | query/oxford_andy_3011897645.jpg 0 1297.29730 598 | query/oxford_andy_3011915377.jpg 0 2666.66667 599 | query/papillonjaune_2871178991.jpg 0 2160.33755 600 | query/pat-neary_2865749869.jpg 0 1446.95652 601 | query/pat-neary_2865751827.jpg 0 1446.95652 602 | query/pat-neary_2865756671.jpg 0 1446.95652 603 | query/pat-neary_2865766511.jpg 0 1446.95652 604 | query/pat-neary_2866577328.jpg 0 2699.13043 605 | query/pat-neary_2866589928.jpg 0 1446.95652 606 | query/pat-neary_2866599144.jpg 0 1446.95652 607 | query/pat-neary_2866611846.jpg 0 2699.13043 608 | query/patrick_keogh_2860920242.jpg 0 2522.52252 609 | query/paulmsf_2889244950.jpg 0 1446.95652 610 | query/pensivelaw_2579986440.jpg 611 | query/pensivelaw_2579988842.jpg 612 | query/pepa007_1411889081.jpg 613 | query/pfmeurer_2599223511.jpg 0 1592.55814 614 | query/pfmeurer_2599252883.jpg 0 1064.18605 615 | query/pfmeurer_2600080812.jpg 0 1064.18605 616 | query/phileas_fog_2825660989.jpg 0 720.72072 617 | query/piedmont_fossil_2616409863.jpg 0 1611.11111 618 | query/pieterbiersteker_2927040834.jpg 0 3603.60360 619 | query/pinboke_2230345075.jpg 620 | query/pinboke_2231138702.jpg 621 | query/piotrr_2464345955.jpg 0 1331.68880 622 | query/piotrr_2464357107.jpg 0 1331.68880 623 | query/piotrr_2464367367.jpg 0 3030.74004 624 | query/piotrr_2465176222.jpg 0 2410.81594 625 | query/piotrr_2465177568.jpg 0 1446.48956 626 | query/piotrr_2465186748.jpg 0 1331.68880 627 | query/piotrr_2979050494.jpg 0 1331.68880 628 | query/piotrr_2979081412.jpg 0 1331.68880 629 | query/pmgoudie_2740709657.jpg 0 1288.96673 630 | query/pmgoudie_2740790829.jpg 0 1288.96673 631 | query/pthistle_2676926316.jpg 0 806.95652 632 | query/pululante_3207144473.jpg 0 1611.11111 633 | query/pzeissig_2548326810.jpg 634 | query/raeker_2997032381.jpg 635 | query/raeker_2997033225.jpg 636 | query/raildecom_3073617309.jpg 637 | query/raildecom_3073668497.jpg 638 | query/rapsak_2512193048.jpg 0 1305.55556 639 | query/rapsak_2512196766.jpg 0 1305.55556 640 | query/rapsak_2512201826.jpg 0 1305.55556 641 | query/rapsak_2514552376.jpg 0 4194.44444 642 | query/revjett_2984333479.jpg 643 | query/rhiannoncarnie_2583718430.jpg 644 | query/rich_ford_2753247827.jpg 0 1270.96205 645 | query/rich_ford_2753855867.jpg 0 1270.96205 646 | query/rietje_2059663945.jpg 0 1649.94426 647 | query/ritratti_2403991802.jpg 0 1666.66667 648 | query/robinini_2374501165.jpg 649 | query/robkille_2763126085.jpg 0 830.27027 650 | query/robkille_2763974512.jpg 0 968.64865 651 | query/rockbandit_2678394431.jpg 0 13559.32203 652 | query/rockbandit_2679202030.jpg 0 13559.32203 653 | query/rockbandit_2679203518.jpg 0 13559.32203 654 | query/rockbandit_2679213358.jpg 0 13559.32203 655 | query/rockbandit_2679217298.jpg 0 13559.32203 656 | query/rockbandit_2679274338.jpg 0 7118.64407 657 | query/rpoll_2579757353.jpg 0 1726.02740 658 | query/rpoll_2579769599.jpg 0 2684.93151 659 | query/rpoll_2579777341.jpg 0 1726.02740 660 | query/rpoll_2579899169.jpg 0 4054.79452 661 | query/rpoll_2579903723.jpg 0 2465.75342 662 | query/rpoll_2579912245.jpg 0 2684.93151 663 | query/rpoll_2580059341.jpg 0 1726.02740 664 | query/rpoll_2580099755.jpg 0 1726.02740 665 | query/rpoll_2580561806.jpg 0 1726.02740 666 | query/rpoll_2580576940.jpg 0 1726.02740 667 | query/rpoll_2580581162.jpg 0 1726.02740 668 | query/rpoll_2580584690.jpg 0 2246.57534 669 | query/rpoll_2580585362.jpg 0 2246.57534 670 | query/schadster_2367485092.jpg 0 1288.88889 671 | query/schups_2622717144.jpg 672 | query/scoleman_2829679797.jpg 673 | query/sdikarev_2529617317.jpg 0 1072.62570 674 | query/sdikarev_2529620279.jpg 0 1072.62570 675 | query/sdikarev_2529627951.jpg 0 4692.73743 676 | query/sdikarev_2529662435.jpg 0 1072.62570 677 | query/sdikarev_2529669923.jpg 0 2905.02793 678 | query/sdikarev_2529729839.jpg 0 1072.62570 679 | query/sdikarev_2530425732.jpg 0 1787.70950 680 | query/sdikarev_2530440404.jpg 0 1072.62570 681 | query/sdikarev_2530474604.jpg 0 1072.62570 682 | query/sdikarev_2530480632.jpg 0 2905.02793 683 | query/sdikarev_2530480986.jpg 0 3754.18994 684 | query/sdikarev_2530497060.jpg 0 1072.62570 685 | query/sdikarev_2530497726.jpg 0 4692.73743 686 | query/sdikarev_2530577778.jpg 0 1430.16760 687 | query/senneseth_3092517880.jpg 0 1215.18987 688 | query/shannonmicah_3083445631.jpg 689 | query/shayvdtang_2469711713.jpg 0 1761.42698 690 | query/shuebox_1515706118.jpg 0 1583.05463 691 | query/shushanhenrymoshe_2846052961.jpg 692 | query/sieburgm_1779713838.jpg 0 1761.42698 693 | query/smacss_3065133070.jpg 0 1636.36364 694 | query/smacss_3161628805.jpg 0 1618.18182 695 | query/_sml_2738520609.jpg 0 1403.89972 696 | query/_sml_2738546967.jpg 0 886.21170 697 | query/_sml_2738568859.jpg 698 | query/_sml_2738571795.jpg 699 | query/starmountaintravel_2875051879.jpg 0 1113.04348 700 | query/starmountaintravel_2875056167.jpg 0 3339.13043 701 | query/starmountaintravel_2875881820.jpg 0 3339.13043 702 | query/starmountaintravel_2875883008.jpg 0 3339.13043 703 | query/statravelers_2928696145.jpg 0 2125.87413 704 | query/stephanhofer_3116226294.jpg 705 | query/stephrog_2485242604.jpg 0 1611.11111 706 | query/stephrog_2485272824.jpg 0 1611.11111 707 | query/sthaker_2651199057.jpg 0 1694.44444 708 | query/stopwalkrun_1634176971.jpg 709 | query/straatlabs_2853490121.jpg 0 1613.91304 710 | query/stretchinlondon_2883846131.jpg 0 13559.32203 711 | query/stretchinlondon_2884684636.jpg 0 1220.33898 712 | query/stuartpinfold_2799987399.jpg 713 | query/stuartpinfold_2799991491.jpg 714 | query/stuartpinfold_2799993451.jpg 715 | query/sunzhenhua_3123482261.jpg 716 | query/sunzhenhua_3124180386.jpg 717 | query/sunzhenhua_3125138464.jpg 718 | query/sunzhenhua_3125190296.jpg 719 | query/sylvielabbe_2994110885.jpg 720 | query/sylvielabbe_2994953048.jpg 721 | query/tagois_2908122596.jpg 0 1319.95541 722 | query/taver_3136982521.jpg 0 1291.47982 723 | query/taver_3137121063.jpg 0 1291.47982 724 | query/taver_3137247125.jpg 0 1291.47982 725 | query/taver_3137398181.jpg 0 2439.46188 726 | query/taver_3137402455.jpg 0 1291.47982 727 | query/taver_3137437175.jpg 0 1291.47982 728 | query/taver_3137634393.jpg 0 1291.47982 729 | query/taver_3137652815.jpg 0 1291.47982 730 | query/taver_3137714107.jpg 0 1793.72197 731 | query/taver_3137735967.jpg 0 1291.47982 732 | query/taver_3137936728.jpg 0 1291.47982 733 | query/taver_3137958161.jpg 0 1291.47982 734 | query/taver_3138163916.jpg 0 1291.47982 735 | query/taver_3138210271.jpg 0 3946.18834 736 | query/taver_3138250108.jpg 0 1291.47982 737 | query/taver_3138254408.jpg 0 1291.47982 738 | query/taver_3138298800.jpg 0 3946.18834 739 | query/taver_3138894628.jpg 0 1291.47982 740 | query/tdgraham_1862918837.jpg 741 | query/teamwagner_1513658313.jpg 0 2162.16216 742 | query/theauroraborealis_2854508752.jpg 0 1297.29730 743 | query/the_cha_2374262821.jpg 0 1684.21053 744 | query/the_egg_uk_2639094520.jpg 0 1622.37762 745 | query/the_egg_uk_2639157828.jpg 0 5890.90909 746 | query/the_egg_uk_2639162376.jpg 0 2000.00000 747 | query/the_egg_uk_2639176936.jpg 0 1618.18182 748 | query/thepictureproject_2908958111.jpg 749 | query/thisduckhere_2671132191.jpg 0 1622.37762 750 | query/tiancat_2816480145.jpg 0 2080.71749 751 | query/tiancat_2817339082.jpg 0 1363.63636 752 | query/tifco_2749497136.jpg 0 1220.33898 753 | query/tino_du_2255241163.jpg 0 13502.10970 754 | query/tino_du_2256051826.jpg 0 7088.60759 755 | query/tino_du_2256058026.jpg 0 5063.29114 756 | query/tjl61_2669348048.jpg 757 | query/tjoyce1_3032285826.jpg 758 | query/tmartin_1486958958.jpg 759 | query/tracylouis_1855605029.jpg 0 1712.37458 760 | query/tracylouis_1856421740.jpg 0 1302.11817 761 | query/trentm_2875406101.jpg 0 1649.94426 762 | query/trentm_2875430491.jpg 0 1649.94426 763 | query/trentm_2879743851.jpg 0 3366.77815 764 | query/trentm_2888016462.jpg 0 1649.94426 765 | query/trpepsi_1476937183.jpg 0 869.56522 766 | query/trpepsi_1477799478.jpg 767 | query/twest7424_2550718931.jpg 0 3216.78322 768 | query/v98max_1845739072.jpg 769 | query/v98max_1940090205.jpg 770 | query/vanchete_2732748696.jpg 0 2420.86957 771 | query/vaniamilena_2552072414.jpg 0 1361.11111 772 | query/_vee__2860475657.jpg 773 | query/vickispics_2467307827.jpg 0 1585.58559 774 | query/vickispics_2467316953.jpg 0 3459.45946 775 | query/vincenzocostagliola_2951356942.jpg 0 777.72152 776 | query/voronov_1814336252.jpg 777 | query/voronov_1814460826.jpg 778 | query/voronov_1814689605.jpg 779 | query/voronov_1814847739.jpg 780 | query/voronov_1814958051.jpg 781 | query/vsatan_2947050692.jpg 0 1585.58559 782 | query/westie145_2993986328.jpg 783 | query/westius_2275528772.jpg 784 | query/wexy_2916157074.jpg 0 3389.83051 785 | query/wnkz_2699014867.jpg 0 1739.13043 786 | query/woodfold_2796663239.jpg 787 | query/world_citizen_3049406039.jpg 0 832.24967 788 | query/world_citizen_3049408849.jpg 0 832.24967 789 | query/world_citizen_3050241426.jpg 0 832.24967 790 | query/xaray_2879042854.jpg 0 11531.53153 791 | query/xe0us_2784444565.jpg 792 | query/xe0us_2784500137.jpg 793 | query/yobanos_2864275981.jpg 0 7457.62712 794 | query/yorkshome_2564788171.jpg 795 | query/yvonnekalawur_1950204575.jpg 0 644.44444 796 | query/yvonnekalawur_1951033818.jpg 0 644.44444 797 | query/yvonnekalawur_1951037390.jpg 0 644.44444 798 | query/zalouk_2360102129.jpg 799 | query/zeusz_3070909772.jpg 0 1155.55556 800 | query/ziggyjoanie_2717325865.jpg 801 | -------------------------------------------------------------------------------- /data/Dubrovnik6K/query/README.txt: -------------------------------------------------------------------------------- 1 | The unextracted query files belong here. 2 | -------------------------------------------------------------------------------- /data/README.txt: -------------------------------------------------------------------------------- 1 | Replace the dubrovnik6k.info (which is empty due to large size) with the actual file before running the software. 2 | -------------------------------------------------------------------------------- /data/dubrovnik6k.info: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/naibaf7/pose_estimation/d1d8b5472ebc01234d0af7b77e4746f364009090/data/dubrovnik6k.info -------------------------------------------------------------------------------- /data/query/README.txt: -------------------------------------------------------------------------------- 1 | Intermediate folder for the program to extract queries and download filckr pictures. 2 | -------------------------------------------------------------------------------- /import_export.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * import_export.cpp 3 | * 4 | * Created on: Mar 27, 2015 5 | * Author: Fabian Tschopp 6 | */ 7 | 8 | #include "import_export.hpp" 9 | #include 10 | #include "query_loader.hpp" 11 | #include 12 | #include 13 | #include 14 | #include "SIFT_keypoint.hpp" 15 | #include "parse_bundler.hpp" 16 | #include "bundler_camera.hpp" 17 | #include "query_processor.hpp" 18 | #include "pose_utils.hpp" 19 | 20 | namespace pose_estimation { 21 | 22 | // Export the SfM mesh in PLY format 23 | void ExportMesh(parse_bundler &parsebundler, std::string path, 24 | std::string filename) { 25 | std::ofstream out_file; 26 | out_file.open(path + filename + ".ply"); 27 | assert(out_file.is_open()); 28 | 29 | std::vector &sifts = parsebundler.get_feature_infos(); 30 | 31 | // Write PLY Header 32 | out_file << "ply" << std::endl; 33 | out_file << "format ascii 1.0" << std::endl; 34 | out_file << "element vertex " << sifts.size() << std::endl; 35 | out_file << "property float32 x" << std::endl; 36 | out_file << "property float32 y" << std::endl; 37 | out_file << "property float32 z" << std::endl; 38 | out_file << "property uchar red" << std::endl; 39 | out_file << "property uchar green" << std::endl; 40 | out_file << "property uchar blue" << std::endl; 41 | out_file << "end_header" << std::endl; 42 | 43 | out_file << std::fixed; 44 | 45 | for (unsigned int i = 0; i < sifts.size(); ++i) { 46 | out_file << std::setprecision(16) << sifts[i].point.x << " " 47 | << std::setprecision(16) << sifts[i].point.y << " " 48 | << std::setprecision(16) << sifts[i].point.z << " " 49 | << (int) sifts[i].point.r << " " << (int) sifts[i].point.g 50 | << " " << (int) sifts[i].point.b << std::endl; 51 | } 52 | 53 | out_file.close(); 54 | } 55 | 56 | // Load the golden model query and pose estimation for comparison 57 | Query LoadGoldenQuery(parse_bundler pb, int query_camera_id, 58 | std::string list_path) { 59 | 60 | std::ifstream queryfile; 61 | queryfile.open(list_path + "list.orig.txt"); 62 | 63 | std::string delimiter = " "; 64 | std::string line; 65 | 66 | int counter_query = 0; 67 | int counter_total = 0; 68 | int total_camera_id = 0; 69 | 70 | while (getline(queryfile, line)) { 71 | 72 | std::string name = CutStringBefore(line, "/"); 73 | 74 | if (name == "query") { 75 | ++counter_query; 76 | } 77 | ++counter_total; 78 | 79 | if (counter_query == query_camera_id + 1) { 80 | total_camera_id = counter_total; 81 | break; 82 | } 83 | } 84 | 85 | queryfile.close(); 86 | 87 | bundler_camera camera = pb.get_cameras()[total_camera_id - 1]; 88 | 89 | // We have camera position and rotation, unlike bundler, so transform: 90 | Eigen::Matrix xzflip; 91 | xzflip << -1, 0, 0, 0, 1, 0, 0, 0, -1; 92 | Eigen::Matrix rotation = camera.rotation; 93 | Eigen::Matrix position = -rotation.transpose() 94 | * camera.translation; 95 | 96 | // Convert to our own format 97 | Query query(nullptr, "", camera.focal_length); 98 | query.set_camera_position(position); 99 | rotation = (xzflip * rotation).transpose(); 100 | query.set_camera_rotation(rotation); 101 | query.set_image_width(camera.width); 102 | query.set_image_height(camera.height); 103 | 104 | return query; 105 | } 106 | 107 | void ExportCameraProjectEdges(Query &query, std::string path, 108 | std::string filename) { 109 | std::ofstream out_file_obj; 110 | out_file_obj.open(path + filename + ".obj"); 111 | assert(out_file_obj.is_open()); 112 | 113 | std::vector> &points_3d = query.fitpoints_3d(); 114 | 115 | Eigen::Matrix camera_position = query.camera_position(); 116 | 117 | out_file_obj << "o Object" << std::endl; 118 | out_file_obj << "v " << std::setprecision(16) << camera_position(0) << " " 119 | << std::setprecision(16) << camera_position(1) << " " 120 | << std::setprecision(16) << camera_position(2) << std::endl; 121 | out_file_obj << "v " << std::setprecision(16) << camera_position(0) << " " 122 | << std::setprecision(16) << camera_position(1) << " " 123 | << std::setprecision(16) << camera_position(2) << std::endl; 124 | 125 | for (unsigned int i = 0; i < points_3d.size(); ++i) { 126 | Eigen::Matrix point_3d = points_3d[i]; 127 | 128 | out_file_obj << "v " << std::setprecision(16) << point_3d(0) << " " 129 | << std::setprecision(16) << point_3d(1) << " " 130 | << std::setprecision(16) << point_3d(2) << std::endl; 131 | } 132 | 133 | out_file_obj << "s off" << std::endl; 134 | for (unsigned int i = 0; i < points_3d.size(); ++i) { 135 | out_file_obj << "f 1 " << i + 3 << " 2" << std::endl; 136 | } 137 | 138 | out_file_obj.close(); 139 | } 140 | 141 | // Export the camera pose as OBJ+MTL (wavefront obj with material) and MLP (meshlab project file) 142 | void ExportCamera(Query &query, std::string path, std::string filename) { 143 | Eigen::Matrix camera_position = query.camera_position(); 144 | Eigen::Matrix camera_rotation = query.camera_rotation(); 145 | Eigen::Matrix xzflip; 146 | xzflip << -1, 0, 0, 0, 1, 0, 0, 0, -1; 147 | Eigen::Matrix camera_rotation_xzf = xzflip 148 | * camera_rotation.transpose(); 149 | 150 | std::ofstream out_file_obj; 151 | std::ofstream out_file_mtl; 152 | std::ofstream out_file_mlp; 153 | out_file_obj.open(path + filename + ".obj"); 154 | assert(out_file_obj.is_open()); 155 | out_file_mtl.open(path + filename + ".mtl"); 156 | assert(out_file_mtl.is_open()); 157 | out_file_mlp.open(path + filename + ".mlp"); 158 | 159 | // Write obj header 160 | out_file_obj << "mtllib " << filename << ".mtl" << std::endl; 161 | out_file_obj << "o Object" << std::endl; 162 | 163 | out_file_obj << std::fixed; 164 | 165 | // Image plane vertices 166 | for (int i = 0; i < 4; ++i) { 167 | double x = 0.01 * query.image_width() * std::sin((i * 2 + 1) * M_PI / 4) 168 | / sqrt(2); 169 | double y = 0.01 * query.image_height() 170 | * std::cos((i * 2 + 1) * M_PI / 4) / sqrt(2); 171 | double z = query.focal_length() / 100.0; 172 | 173 | // Transform to world coordinates 174 | Eigen::Matrix xyz; 175 | xyz << x, y, z; 176 | xyz = camera_rotation * xyz + camera_position; 177 | x = xyz(0); 178 | y = xyz(1); 179 | z = xyz(2); 180 | 181 | float u = (0.5 + std::sin(-(i * 2 + 1) * M_PI / 4) / sqrt(2.0)); 182 | float v = (0.5 + std::cos((i * 2 + 1) * M_PI / 4) / sqrt(2.0)); 183 | out_file_obj << "v " << std::setprecision(16) << x << " " 184 | << std::setprecision(16) << y << " " << std::setprecision(16) 185 | << z << std::endl; 186 | out_file_obj << "vt " << std::setprecision(16) << u << " " 187 | << std::setprecision(16) << v << std::endl; 188 | } 189 | 190 | // Camera box vertices 191 | out_file_obj << "v " << std::setprecision(16) << camera_position(0) << " " 192 | << std::setprecision(16) << camera_position(1) << " " 193 | << std::setprecision(16) << camera_position(2) << std::endl; 194 | for (int i = 0; i < 4; ++i) { 195 | double x = 0.001 * query.image_width() 196 | * std::sin((i * 2 + 1) * M_PI / 4) / sqrt(2); 197 | double y = 0.001 * query.image_height() 198 | * std::cos((i * 2 + 1) * M_PI / 4) / sqrt(2); 199 | double z = query.focal_length() / 1000.0; 200 | 201 | // Transform to world coordinates 202 | Eigen::Matrix xyz; 203 | xyz << x, y, z; 204 | xyz = camera_rotation * xyz + camera_position; 205 | x = xyz(0); 206 | y = xyz(1); 207 | z = xyz(2); 208 | 209 | out_file_obj << "v " << std::setprecision(16) << x << " " 210 | << std::setprecision(16) << y << " " << std::setprecision(16) 211 | << z << std::endl; 212 | } 213 | 214 | out_file_obj << "g Object_Object_auv" << std::endl; 215 | out_file_obj << "usemtl Object_auv" << std::endl; 216 | out_file_obj << "s off" << std::endl; 217 | 218 | // Image plane faces 219 | out_file_obj << "f 1/1 2/2 3/3" << std::endl; 220 | out_file_obj << "f 1/1 3/3 4/4" << std::endl; 221 | 222 | // Camera box faces 223 | out_file_obj << "f 5 6 7" << std::endl; 224 | out_file_obj << "f 5 7 8" << std::endl; 225 | out_file_obj << "f 5 8 9" << std::endl; 226 | out_file_obj << "f 5 6 9" << std::endl; 227 | out_file_obj << "f 6 7 8" << std::endl; 228 | out_file_obj << "f 6 8 9" << std::endl; 229 | 230 | // Write mtl 231 | out_file_mtl << "newmtl Object_auv" << std::endl; 232 | out_file_mtl << "Ns 100.0" << std::endl; 233 | out_file_mtl << "d 1.0" << std::endl; 234 | out_file_mtl << "illum 2" << std::endl; 235 | out_file_mtl << "Kd 1.0 1.0 1.0" << std::endl; 236 | out_file_mtl << "Ka 1.0 1.0 1.0" << std::endl; 237 | out_file_mtl << "Ks 1.0 1.0 1.0" << std::endl; 238 | out_file_mtl << "Ke 0.0 0.0 0.0" << std::endl; 239 | out_file_mtl << "map_Kd " << filename << ".jpg" << std::endl; 240 | 241 | // Write mlp 242 | 243 | out_file_mlp << "" << std::endl; 244 | out_file_mlp << "" << std::endl; 245 | out_file_mlp << "" << std::endl; 246 | 247 | // The camera 248 | out_file_mlp << "" 249 | << std::endl; 250 | out_file_mlp << "" << std::endl; 278 | // The image file 279 | out_file_mlp << "" << std::endl; 281 | out_file_mlp << "" << std::endl; 282 | 283 | out_file_mlp << "" << std::endl; 284 | out_file_mlp << "" << std::endl; 285 | 286 | out_file_obj.close(); 287 | out_file_mtl.close(); 288 | out_file_mlp.close(); 289 | 290 | cv::imwrite(path + filename + ".jpg", query.image()); 291 | } 292 | 293 | } 294 | -------------------------------------------------------------------------------- /import_export.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * import_export.hpp 3 | * 4 | * Created on: Mar 27, 2015 5 | * Author: Fabian Tschopp 6 | */ 7 | 8 | #ifndef IMPORT_EXPORT_HPP_ 9 | #define IMPORT_EXPORT_HPP_ 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include "SIFT_keypoint.hpp" 16 | #include "parse_bundler.hpp" 17 | #include "bundler_camera.hpp" 18 | #include "query_processor.hpp" 19 | #include "query_loader.hpp" 20 | 21 | namespace pose_estimation { 22 | 23 | void ExportMesh(parse_bundler &parsebundler, std::string path, 24 | std::string filename); 25 | 26 | void ExportCamera(Query &query, std::string path, std::string filename); 27 | 28 | Query LoadGoldenQuery(parse_bundler pb, int query_camera_id, 29 | std::string list_file); 30 | 31 | void ExportCameraProjectEdges(Query &query, std::string path, 32 | std::string filename); 33 | 34 | } 35 | 36 | #endif /* IMPORT_EXPORT_HPP_ */ 37 | -------------------------------------------------------------------------------- /log.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * log.hpp 3 | * 4 | * Created on: Mar 21, 2015 5 | * Author: Fabian Tschopp 6 | */ 7 | 8 | #ifndef LOG_HPP_ 9 | #define LOG_HPP_ 10 | 11 | #include 12 | 13 | 14 | #ifndef DLOG 15 | #define DLOG true 16 | #endif 17 | 18 | 19 | void log(std::string info) { 20 | if (DLOG) { 21 | struct timeval tv; 22 | gettimeofday(&tv, 0); 23 | time_t now = tv.tv_sec; 24 | struct tm * now_tm = localtime(&now); 25 | char buffer[40]; 26 | strftime(buffer, sizeof(buffer), "%Y/%m/%d %H:%M:%S", now_tm); 27 | std::cout << "[" << buffer << "] -- " << info << std::endl; 28 | } 29 | } 30 | 31 | 32 | 33 | #endif /* LOG_HPP_ */ 34 | -------------------------------------------------------------------------------- /out/README.txt: -------------------------------------------------------------------------------- 1 | Program output goes here. 2 | -------------------------------------------------------------------------------- /p3p_testing.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * p3p_testing.cpp 3 | * 4 | * Created on: Mar 21, 2015 5 | * Author: Fabian Tschopp 6 | * 7 | */ 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include "P3p.hpp" 30 | #include "P4pf.hpp" 31 | 32 | void testP3p() { 33 | 34 | std::cout << "=================================" << std::endl; 35 | std::cout << "========== P3p testing ==========" << std::endl; 36 | std::cout << "=================================" << std::endl; 37 | 38 | P3p p3p; 39 | 40 | Eigen::Matrix points; 41 | 42 | points << 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0; 43 | 44 | points << 0.0, 0.0, 1.0, 10.5, 10.5, 10.5, -10.5, -9.5, -9.5; 45 | 46 | Eigen::Matrix features; 47 | 48 | features << -0.049875, -0.049875, 0.049875, 0.049875, -0.049875, -0.049875, 0.99751, 0.99751, 0.99751; 49 | 50 | Eigen::Matrix out; 51 | Eigen::Matrix golden; 52 | 53 | golden << 1.7739, 0.9917, 0.0064, -0.1281, 0.5665, 1.0000, 0.0003, -0.0066, 0.1272, 0.9993, -0.0019, 0.0372, -0.4751, 0.9952, -0.0049, 0.0977, 0.6782, 0.1283, -0.0356, 0.9911, 0.5227, 0.0066, -0.0059, 1.0000, 0.7136, -0.0366, 0.1435, 0.9890, 0.6218, -0.0977, -0.1019, 0.9900, -9.6385, 0.0018, -0.9994, -0.0361, -9.9416, 0.0003, -1.0000, -0.0059, -11.4235, -0.0072, -0.9896, 0.1434, -8.9839, 0.0051, -0.9948, -0.1019; 54 | 55 | p3p.computePoses(features, points, out); 56 | 57 | std::cout << points << std::endl; 58 | std::cout << features << std::endl; 59 | std::cout << out << std::endl; 60 | 61 | double error = (out - golden).norm(); 62 | 63 | std::cout << "Error: " << error << std::endl; 64 | 65 | assert(error < 0.15); 66 | } 67 | 68 | void testP4pf() { 69 | 70 | std::cout << "=================================" << std::endl; 71 | std::cout << "========== P4pf testing =========" << std::endl; 72 | std::cout << "=================================" << std::endl; 73 | 74 | 75 | P4pf p4pf; 76 | 77 | Eigen::Matrix feature_vectors; 78 | Eigen::Matrix world_points; 79 | std::vector focal_length_solutions; 80 | std::vector> rotation_solutions; 81 | std::vector> translation_solutions; 82 | 83 | //world_points << -2.5, 5, 2.5, 5, 10, 5, -5, 10, 5, 10, 20, -10; 84 | 85 | world_points << -5, -5, 5, 3, -3, 3, 3, 3, 3, -9, 9, 9; 86 | 87 | feature_vectors << -1, -1, 1, -1, 1, 1, -1, 1; 88 | 89 | p4pf.P4Pf_m(feature_vectors.transpose(), world_points.transpose(), &focal_length_solutions, 90 | &rotation_solutions, &translation_solutions); 91 | 92 | for (int i = 0; i < focal_length_solutions.size(); ++i) { 93 | std::cout << focal_length_solutions[i] << std::endl; 94 | std::cout << translation_solutions[i] << std::endl; 95 | std::cout << rotation_solutions[i] << std::endl; 96 | } 97 | 98 | } 99 | 100 | int main(int argc, char* argv[]) { 101 | testP3p(); 102 | testP4pf(); 103 | } 104 | -------------------------------------------------------------------------------- /p4p_testing.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * p3p_testing.cpp 3 | * 4 | * Created on: Mar 21, 2015 5 | * Author: Marco Zorzi 6 | * 7 | */ 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include "P4pf.hpp" 31 | 32 | #define DBG_TEST 0 33 | #define OUT 1 34 | 35 | void testP4p_m() { 36 | 37 | /*********** BEGIN main funciton ************/ 38 | /* 39 | % P4P + unknown focal length testing app 40 | % given a set of 4x 2D<->3D correspondences, calculate camera pose and the 41 | % camera focal length. 42 | % 43 | % by Martin Bujnak, (c)apr2008 44 | % 45 | 46 | % ground truth focal, image resolution [-0.5;0.5]x[-0.5;0.5] 47 | */ 48 | 49 | double fgt = 1.5; 50 | 51 | // general scene 52 | Eigen::Matrix M; 53 | M << -3.33639834336120, -23.35549638285873, -13.18941519576778, 6.43164913914748, 54 | 0.65948286155096, -4.90376715918747, 1.17103701629876, 0.14580433383203, 55 | -8.46658219501120, -3.99876939947909, -3.02248927651177, -22.16086539862748; 56 | 57 | Eigen::Matrix m; 58 | m << 0.11009888473695, 0.39776592879400, 0.28752996253253, -0.05017617729940, 59 | 0.03882059658299, -0.17303453640632, -0.05791310109713, 0.19297848817239; 60 | 61 | // ground truth orientation + position 62 | Eigen::Matrix Rgt; 63 | Rgt << -0.94382954756954, 0.33043272406750, 0, 64 | 0.27314119331857, 0.78018522420862, -0.56276540799790, 65 | -0.18595610677571, -0.53115462041845, -0.82661665574857; 66 | 67 | Eigen::Matrix Tgt; 68 | Tgt << 2.85817409844554, 69 | -2.17296255562889, 70 | 77.54246130780075; 71 | 72 | std::cout << M << std::endl; 73 | std::cout << m << std::endl; 74 | std::cout << Rgt << std::endl; 75 | std::cout << Tgt << std::endl; 76 | 77 | P4pf object; 78 | 79 | std::vector focalLengthsResults; 80 | std::vector> rotationMatrices; 81 | std::vector> translationResult; 82 | 83 | if (DBG_TEST) std::cout << "\n\n focalLengthsResults.size()= " << focalLengthsResults.size() <<"\n"; 84 | if (DBG_TEST) std::cout << "\n\n rotationMatrices.size()= " << rotationMatrices.size() <<"\n"; 85 | if (DBG_TEST) std::cout << "\n\n translationResult.size()= " << translationResult.size() <<"\n"; 86 | 87 | 88 | 89 | 90 | if (OUT) std::cout << "******************************************** LEAVING TESTING *********************************************\n\n"; 91 | std::chrono::milliseconds ms_start = std::chrono::duration_cast< std::chrono::milliseconds >( 92 | std::chrono::high_resolution_clock::now().time_since_epoch() ); 93 | 94 | 95 | int checkError = object.P4Pf_m(m, M, &focalLengthsResults, &rotationMatrices, &translationResult); 96 | 97 | std::chrono::milliseconds ms_stop = std::chrono::duration_cast< std::chrono::milliseconds >( 98 | std::chrono::high_resolution_clock::now().time_since_epoch() ); 99 | 100 | if (OUT) std::cout << "***************************************** RETURNED TO TESTING ******************************************\n\n"; 101 | if (OUT) std::cout << "Completed in "<< (ms_stop.count()-ms_start.count()) <<" millisecond(ms)" << "with checkError = "<< checkError <<"\n\n"; 102 | 103 | if (DBG_TEST) std::cout << "\n focalLengthsResults.size()= " << focalLengthsResults.size() <<"\n"; 104 | if (DBG_TEST) std::cout << "\n rotationMatrices.size()= " << rotationMatrices.size() <<"\n"; 105 | if (DBG_TEST) std::cout << "\n translationResult.size()= " << translationResult.size() <<"\n"; 106 | 107 | 108 | if (DBG_TEST) std::cout << "\n focalLengthsResults:\n"; 109 | for (int i = 0; i< focalLengthsResults.size(); i++) 110 | { 111 | if (DBG_TEST) std::cout << focalLengthsResults.at(i) <<"\n"; 112 | } 113 | if (DBG_TEST) std::cout<<"\n"; 114 | 115 | if (DBG_TEST) std::cout << "\n rotationMatrices:\n"; 116 | for (int i = 0; i< rotationMatrices.size(); i++) 117 | { 118 | if (DBG_TEST) std::cout << "R("< Rrel = Eigen::Matrix::Zero(3,3); 131 | Eigen::Matrix Trel = Eigen::Matrix::Zero(3,1); 132 | 133 | double dangle = -1; 134 | for (int i = 0; i< focalLengthsResults.size(); i++) 135 | { 136 | 137 | if (DBG_TEST) std::cout << "\n i = " << i<<"\n\n"; 138 | 139 | if (DBG_TEST) std::cout << "\n Rgt:\n" << Rgt <<"\n\n"; 140 | if (DBG_TEST) std::cout << "\n Rgt.inverse():\n" << Rgt.inverse() <<"\n\n"; 141 | if (DBG_TEST) std::cout << "\n rotationMatrices.at(i):\n" << rotationMatrices.at(i) <<"\n\n"; 142 | 143 | 144 | Rrel = Rgt.inverse()*rotationMatrices.at(i); 145 | if (DBG_TEST) std::cout << "\n Rrel:\n" << Rrel <<"\n\n"; 146 | 147 | Trel = Tgt - translationResult.at(i); 148 | if (DBG_TEST) std::cout << "\n Trel:\n" << Trel <<"\n\n"; 149 | 150 | if (DBG_TEST) std::cout << "Rrel.trace():\n" << Rrel.trace() <<"\n\n"; 151 | if (DBG_TEST) std::cout << "Rrel.trace() -1:\n" << Rrel.trace() -1 <<"\n\n"; 152 | if (DBG_TEST) std::cout << "(Rrel.trace() -1)/2:\n" << (Rrel.trace() -1)/2 <<"\n\n"; 153 | if (DBG_TEST) std::cout << "acos(1):\n" << acos(1) <<"\n\n"; 154 | if (DBG_TEST) std::cout << "acos(1-0.000000000001):\n" << acos(1-0.000000000001) <<"\n\n"; 155 | if (DBG_TEST) std::cout << "acos( (Rrel.trace() -1)/2 ):\n" << std::acos( (Rrel.trace() -1)/2 ) <<"\n\n"; 156 | if (DBG_TEST) std::cout << "std::norm(acos( (Rrel.trace() -1)/2 )):\n" << std::norm(std::acos( (Rrel.trace() -1)/2 )) <<"\n\n"; 157 | if (DBG_TEST) std::cout << "sqrt(std::norm(acos( (Rrel.trace() -1)/2 ))):\n" << std::sqrt(std::norm(std::acos( (Rrel.trace() -1)/2 ))) <<"\n\n"; 158 | if (DBG_TEST) std::cout << "(sqrt(std::norm(acos( (Rrel.trace() -1)/2 ))) )/M_PI*180:\n" << (std::sqrt(std::norm(std::acos( (Rrel.trace() -1)/2 ))) )/M_PI*180 <<"\n\n"; 159 | 160 | dangle = ( 161 | sqrt( 162 | std::norm( 163 | acos( 164 | (Rrel.trace() -1)/2 165 | ) 166 | ) 167 | ) 168 | )/M_PI*180; 169 | if (DBG_TEST) std::cout << "dangle:\n" << dangle <<"\n\n"; 170 | if (DBG_TEST) std::cout << "focalLengthsResults.at(i)= " << focalLengthsResults.at(i) <<"\n\n"; 171 | 172 | if (OUT) std::cout << "focal err= " << fgt-focalLengthsResults.at(i) << "\nRotation err= " << dangle << "\nTranslation err= "< M; 181 | M << -3.33639834336120, -23.35549638285873, -13.18941519576778, 6.43164913914748, 182 | 0.65948286155096, -4.90376715918747, 1.17103701629876, 0.14580433383203, 183 | -8.46658219501120, -3.99876939947909, -3.02248927651177, -22.16086539862748; 184 | 185 | Eigen::Matrix m; 186 | m << 0.11009888473695, 0.39776592879400, 0.28752996253253, -0.05017617729940, 187 | 0.03882059658299, -0.17303453640632, -0.05791310109713, 0.19297848817239; 188 | 189 | // ground truth orientation + position 190 | Eigen::Matrix Rgt; 191 | Rgt << -0.94382954756954, 0.33043272406750, 0, 192 | 0.27314119331857, 0.78018522420862, -0.56276540799790, 193 | -0.18595610677571, -0.53115462041845, -0.82661665574857; 194 | 195 | Eigen::Matrix Tgt; 196 | Tgt << 2.85817409844554, 197 | -2.17296255562889, 198 | 77.54246130780075; 199 | 200 | P4pf object; 201 | 202 | double fgt = 1.5; 203 | 204 | 205 | std::vector focalLengthsResults2; 206 | 207 | std::vector> rotationMatrices2; 208 | 209 | std::vector> translationResult2; 210 | 211 | if (DBG_TEST) std::cout << "\n\n focalLengthsResults2.size()= " << focalLengthsResults2.size() <<"\n"; 212 | if (DBG_TEST) std::cout << "\n\n rotationMatrices2.size()= " << rotationMatrices2.size() <<"\n"; 213 | if (DBG_TEST) std::cout << "\n\n translationResult2.size()= " << translationResult2.size() <<"\n"; 214 | 215 | 216 | 217 | if (OUT) std::cout << "******************************************** LEAVING TESTING *********************************************\n\n"; 218 | 219 | std::chrono::milliseconds ms_start2 = std::chrono::duration_cast< std::chrono::milliseconds >( 220 | std::chrono::high_resolution_clock::now().time_since_epoch() ); 221 | 222 | 223 | int checkError2 = object.P4Pf(m, M, &focalLengthsResults2, &rotationMatrices2, &translationResult2); 224 | 225 | std::chrono::milliseconds ms_stop2 = std::chrono::duration_cast< std::chrono::milliseconds >( 226 | std::chrono::high_resolution_clock::now().time_since_epoch() ); 227 | 228 | if (OUT) std::cout << "***************************************** RETURNED TO TESTING ******************************************\n\n"; 229 | 230 | if (OUT) std::cout << "Completed in "<< (ms_stop2.count()-ms_start2.count()) <<" millisecond(ms)" << "with checkError2 = "<< checkError2 <<"\n\n"; 231 | 232 | if (DBG_TEST) std::cout << "\n focalLengthsResults2.size()= " << focalLengthsResults2.size() <<"\n"; 233 | if (DBG_TEST) std::cout << "\n rotationMatrices2.size()= " << rotationMatrices2.size() <<"\n"; 234 | if (DBG_TEST) std::cout << "\n translationResult2.size()= " << translationResult2.size() <<"\n"; 235 | 236 | 237 | if (DBG_TEST) std::cout << "\n focalLengthsResults2:\n"; 238 | for (int i = 0; i< focalLengthsResults2.size(); i++) 239 | { 240 | if (DBG_TEST) std::cout << focalLengthsResults2.at(i) <<"\n"; 241 | } 242 | if (DBG_TEST) std::cout<<"\n"; 243 | 244 | if (DBG_TEST) std::cout << "\n rotationMatrices:\n"; 245 | for (int i = 0; i< rotationMatrices2.size(); i++) 246 | { 247 | if (DBG_TEST) std::cout << "R("< Rrel2 = Eigen::Matrix::Zero(3,3); 260 | Eigen::Matrix Trel2 = Eigen::Matrix::Zero(3,1); 261 | 262 | double dangle2 = -1; 263 | for (int i = 0; i< focalLengthsResults2.size(); i++) 264 | { 265 | 266 | if (DBG_TEST) std::cout << "\n i = " << i<<"\n\n"; 267 | 268 | if (DBG_TEST) std::cout << "\n Rgt:\n" << Rgt <<"\n\n"; 269 | if (DBG_TEST) std::cout << "\n Rgt.inverse():\n" << Rgt.inverse() <<"\n\n"; 270 | if (DBG_TEST) std::cout << "\n rotationMatrices.at(i):\n" << rotationMatrices2.at(i) <<"\n\n"; 271 | 272 | 273 | Rrel2 = Rgt.inverse()*rotationMatrices2.at(i); 274 | if (DBG_TEST) std::cout << "\n Rrel2:\n" << Rrel2 <<"\n\n"; 275 | 276 | Trel2 = Tgt - translationResult2.at(i); 277 | if (DBG_TEST) std::cout << "\n Trel2:\n" << Trel2 <<"\n\n"; 278 | 279 | dangle2 = ( 280 | sqrt( 281 | std::norm( 282 | acos( 283 | (Rrel2.trace() -1)/2 284 | ) 285 | ) 286 | ) 287 | )/M_PI*180; 288 | 289 | if (DBG_TEST) std::cout << "dangle:\n" << dangle2 <<"\n\n"; 290 | if (DBG_TEST) std::cout << "focalLengthsResults.at(i)= " << focalLengthsResults2.at(i) <<"\n\n"; 291 | if (OUT) std::cout << "focal err= " << fgt-focalLengthsResults2.at(i) << "\nRotation err= " << dangle2 << "\nTranslation err= "<. * 22 | * * 23 | \*===========================================================================*/ 24 | 25 | #include "parse_bundler.hpp" 26 | 27 | //------------------------------ 28 | 29 | parse_bundler::parse_bundler() { 30 | mNbPoints = 0; 31 | mNbCameras = 0; 32 | } 33 | 34 | //------------------------------ 35 | 36 | parse_bundler::~parse_bundler() { 37 | for (uint32_t i = 0; i < mNbPoints; ++i) { 38 | mFeatureInfos[i].view_list.clear(); 39 | mFeatureInfos[i].descriptors.clear(); 40 | } 41 | mFeatureInfos.clear(); 42 | 43 | } 44 | 45 | //------------------------------ 46 | 47 | uint32_t parse_bundler::get_number_of_points() { 48 | return mNbPoints; 49 | } 50 | 51 | //------------------------------ 52 | 53 | uint32_t parse_bundler::get_number_of_cameras() { 54 | return mNbCameras; 55 | } 56 | 57 | //------------------------------ 58 | 59 | void parse_bundler::get_points(std::vector &points) { 60 | points.reserve(mNbPoints); 61 | points.clear(); 62 | for (uint32_t i = 0; i < mNbPoints; ++i) 63 | points.push_back(point3D(mFeatureInfos[i].point)); 64 | } 65 | 66 | //------------------------------ 67 | 68 | std::vector& parse_bundler::get_feature_infos() { 69 | return mFeatureInfos; 70 | } 71 | 72 | //------------------------------ 73 | 74 | std::vector& parse_bundler::get_cameras() { 75 | return mCameras; 76 | } 77 | 78 | //------------------------------ 79 | 80 | bool parse_bundler::parse_data(const char* bundle_out_filename_, 81 | const char* image_list_filename) { 82 | //// 83 | // intialize the points and their views 84 | for (uint32_t i = 0; i < mNbPoints; ++i) { 85 | mFeatureInfos[i].view_list.clear(); 86 | mFeatureInfos[i].descriptors.clear(); 87 | } 88 | mFeatureInfos.clear(); 89 | 90 | mNbCameras = mNbPoints = 0; 91 | 92 | //// 93 | // load the Bundler file 94 | 95 | std::cout << " Parsing " << bundle_out_filename_ << std::endl; 96 | 97 | std::ifstream instream(bundle_out_filename_, std::ios::in); 98 | 99 | if (!instream.is_open()) { 100 | std::cerr << " Could not open the file " << bundle_out_filename_ 101 | << std::endl; 102 | return false; 103 | } 104 | 105 | // read the first line (containing only some information about the Bundler version) 106 | char header[4096]; 107 | instream.getline(header, 4086, '\n'); 108 | std::cout << " header of the file: " << header << std::endl; 109 | 110 | // get the number of cameras and the number of 3D points 111 | instream >> mNbCameras >> mNbPoints; 112 | 113 | mFeatureInfos.resize(mNbPoints); 114 | mCameras.resize(mNbCameras); 115 | 116 | // load the camera data 117 | std::cout << " skipping " << mNbCameras << " cameras" << std::endl; 118 | 119 | float camera_data = 0.0f; 120 | for (uint32_t i = 0; i < mNbCameras; ++i) { 121 | instream >> mCameras[i].focal_length >> mCameras[i].kappa_1 122 | >> mCameras[i].kappa_2; 123 | for (int j = 0; j < 3; ++j) 124 | instream >> mCameras[i].rotation(j, 0) >> mCameras[i].rotation(j, 1) 125 | >> mCameras[i].rotation(j, 2); 126 | instream >> mCameras[i].translation[0] >> mCameras[i].translation[1] 127 | >> mCameras[i].translation[2]; 128 | mCameras[i].id = i; 129 | } 130 | 131 | std::cout << " done " << std::endl; 132 | 133 | // load the points ... 134 | std::cout << " starting to load " << mNbPoints << " 3D points" << std::endl; 135 | int r, g, b; 136 | 137 | // .. and store for each camera which points ( index of the point in mFeatureInfos and the cameras id in the 138 | // view list) it does see. This is needed to later on load the descriptors from the .key files 139 | std::vector > > cam_feature_infos( 140 | mNbCameras); 141 | for (uint32_t i = 0; i < mNbCameras; ++i) 142 | cam_feature_infos[i].clear(); 143 | 144 | // read the 3D points together with their view lists 145 | for (uint32_t i = 0; i < mNbPoints; ++i) { 146 | // read the position 147 | instream >> mFeatureInfos[i].point.x >> mFeatureInfos[i].point.y 148 | >> mFeatureInfos[i].point.z; 149 | 150 | // read the color of the point 151 | instream >> r >> g >> b; 152 | mFeatureInfos[i].point.r = (unsigned char) r; 153 | mFeatureInfos[i].point.g = (unsigned char) g; 154 | mFeatureInfos[i].point.b = (unsigned char) b; 155 | 156 | // now, read the view list 157 | uint32_t view_list_length; 158 | instream >> view_list_length; 159 | 160 | mFeatureInfos[i].view_list.resize(view_list_length); 161 | mFeatureInfos[i].descriptors.resize(128 * view_list_length, 0); 162 | 163 | for (uint32_t j = 0; j < view_list_length; ++j) { 164 | instream >> mFeatureInfos[i].view_list[j].camera 165 | >> mFeatureInfos[i].view_list[j].key 166 | >> mFeatureInfos[i].view_list[j].x 167 | >> mFeatureInfos[i].view_list[j].y; 168 | cam_feature_infos[mFeatureInfos[i].view_list[j].camera].push_back( 169 | std::make_pair(i, j)); 170 | } 171 | } 172 | 173 | instream.close(); 174 | 175 | std::cout << " done " << std::endl; 176 | 177 | //// 178 | // if no file containing the filenames of the images in the reconstruction is specified, the we are done with loading 179 | if (image_list_filename == 0) 180 | return true; 181 | 182 | //// 183 | // read the file containing the list of images and extract the names of the keyfiles from it 184 | std::cout << " extracting names of the .key files from " 185 | << image_list_filename << std::endl; 186 | 187 | std::vector keyfilenames; 188 | keyfilenames.resize(mNbCameras); 189 | { 190 | std::ifstream instream2(image_list_filename, std::ios::in); 191 | 192 | if (!instream2.is_open()) { 193 | std::cerr << " Could not open the file " << image_list_filename 194 | << std::endl; 195 | return false; 196 | } 197 | 198 | char buffer[8192]; 199 | 200 | for (uint32_t i = 0; i < mNbCameras; ++i) { 201 | instream2.getline(buffer, 8192, '\n'); 202 | std::string strbuffer(buffer); 203 | std::stringstream sstream(strbuffer); 204 | 205 | std::string tmp; 206 | sstream >> tmp; 207 | 208 | // replace the .jpg ending with .key 209 | 210 | tmp.replace(tmp.size() - 3, 3, "key"); 211 | keyfilenames[i] = tmp; 212 | } 213 | 214 | instream2.close(); 215 | } 216 | 217 | std::cout << " done " << std::endl; 218 | 219 | //// 220 | // now load the key-files containing the SIFT keys one for one 221 | std::cout << " starting to load the keypoints from " << mNbCameras 222 | << " many images " << std::endl; 223 | 224 | // keep track on how many keypoints could not be found 225 | uint32_t missing_keypoints = 0; 226 | 227 | for (uint32_t i = 0; i < mNbCameras; ++i) { 228 | // load the .key file for that camera 229 | 230 | SIFT_loader key_loader; 231 | key_loader.load_features(keyfilenames[i].c_str(), LOWE); 232 | 233 | std::vector& descriptors = key_loader.get_descriptors(); 234 | std::vector& keypoints = key_loader.get_keypoints(); 235 | 236 | // go through the descriptors and store the ones we are interested in 237 | uint32_t nb_des = (uint32_t) cam_feature_infos[i].size(); 238 | 239 | for (uint32_t j = 0; j < nb_des; ++j) { 240 | uint32_t feature_id = cam_feature_infos[i][j].first; 241 | uint32_t view_list_id = cam_feature_infos[i][j].second; 242 | uint32_t feature_descriptor_index = view_list_id * 128; 243 | uint32_t feature_id_keyfile = 244 | mFeatureInfos[feature_id].view_list[view_list_id].key; 245 | // copy the descriptor 246 | 247 | if (feature_id_keyfile >= (uint32_t) keypoints.size()) { 248 | std::cerr << " Trying to load the descriptor for feature " 249 | << feature_id << " from camera " << i 250 | << " viewlist entry " << view_list_id 251 | << " feature id in the keyfile: " << feature_id_keyfile 252 | << " but only " << keypoints.size() << " in keyfile " 253 | << std::endl; 254 | 255 | ++missing_keypoints; 256 | 257 | for (uint32_t k = 0; k < 128; ++k) 258 | mFeatureInfos[feature_id].descriptors[feature_descriptor_index 259 | + k] = 0; 260 | 261 | // set scale and orientation of the keypoint in the view list 262 | mFeatureInfos[feature_id].view_list[view_list_id].scale = -1.0f; 263 | mFeatureInfos[feature_id].view_list[view_list_id].orientation = 264 | 0.0f; 265 | } else { 266 | for (uint32_t k = 0; k < 128; ++k) 267 | mFeatureInfos[feature_id].descriptors[feature_descriptor_index 268 | + k] = descriptors[feature_id_keyfile][k]; 269 | 270 | // set scale and orientation of the keypoint in the view list 271 | mFeatureInfos[feature_id].view_list[view_list_id].scale = 272 | keypoints[feature_id_keyfile].scale; 273 | mFeatureInfos[feature_id].view_list[view_list_id].orientation = 274 | keypoints[feature_id_keyfile].orientation; 275 | } 276 | } 277 | 278 | // clean up the reserved space 279 | uint32_t nb_keys_file = (uint32_t) key_loader.get_nb_features(); 280 | 281 | for (uint32_t j = 0; j < nb_keys_file; ++j) { 282 | if (descriptors[j] != 0) 283 | delete[] descriptors[j]; 284 | descriptors[j] = 0; 285 | } 286 | 287 | descriptors.clear(); 288 | keypoints.clear(); 289 | 290 | std::cout << " " << i + 1 << " / " << mNbCameras << std::endl; 291 | } 292 | 293 | std::cout << " Could not find " << missing_keypoints << " many keypoints" 294 | << std::endl; 295 | 296 | keyfilenames.clear(); 297 | std::cout << " done " << std::endl; 298 | 299 | return true; 300 | } 301 | 302 | //------------------------------ 303 | 304 | bool parse_bundler::load_from_binary(const char* filename, const int format) { 305 | //// 306 | // initialize the data structure for the 3D points 307 | for (uint32_t i = 0; i < mNbPoints; ++i) { 308 | mFeatureInfos[i].view_list.clear(); 309 | mFeatureInfos[i].descriptors.clear(); 310 | } 311 | mFeatureInfos.clear(); 312 | 313 | mNbCameras = mNbPoints = 0; 314 | 315 | // open file for reading 316 | std::ifstream ifs(filename, std::ios::in | std::ios::binary); 317 | if (!ifs) { 318 | std::cerr << "Cannot read file " << filename << std::endl; 319 | return false; 320 | } 321 | 322 | // read the number of cameras 323 | ifs.read((char*) &mNbCameras, sizeof(uint32_t)); 324 | 325 | // depending on the format, cameras will be loaded 326 | if (format == 1) { 327 | // load the cameras 328 | mCameras.resize(mNbCameras); 329 | for (uint32_t i = 0; i < mNbCameras; ++i) { 330 | double focal_length, kappa_1, kappa_2; 331 | int32_t width, height; 332 | double *rotation = new double[9]; 333 | double *translation = new double[3]; 334 | ifs.read((char*) &focal_length, sizeof(double)); 335 | ifs.read((char*) &kappa_1, sizeof(double)); 336 | ifs.read((char*) &kappa_2, sizeof(double)); 337 | ifs.read((char*) &width, sizeof(int32_t)); 338 | ifs.read((char*) &height, sizeof(int32_t)); 339 | ifs.read((char*) rotation, 9 * sizeof(double)); 340 | ifs.read((char*) translation, 3 * sizeof(double)); 341 | 342 | mCameras[i].focal_length = focal_length; 343 | mCameras[i].kappa_1 = kappa_1; 344 | mCameras[i].kappa_2 = kappa_2; 345 | mCameras[i].width = width; 346 | mCameras[i].height = height; 347 | for (int j = 0; j < 3; ++j) { 348 | for (int k = 0; k < 3; ++k) 349 | mCameras[i].rotation(j, k) = rotation[3 * j + k]; 350 | } 351 | for (int j = 0; j < 3; ++j) 352 | mCameras[i].translation[j] = translation[j]; 353 | 354 | delete[] rotation; 355 | delete[] translation; 356 | } 357 | } 358 | 359 | // load the points 360 | ifs.read((char*) &mNbPoints, sizeof(uint32_t)); 361 | mFeatureInfos.resize(mNbPoints); 362 | 363 | for (uint32_t i = 0; i < mNbPoints; ++i) { 364 | float *pos = new float[3]; 365 | ifs.read((char*) pos, 3 * sizeof(float)); 366 | mFeatureInfos[i].point.x = pos[0]; 367 | mFeatureInfos[i].point.y = pos[1]; 368 | mFeatureInfos[i].point.z = pos[2]; 369 | delete[] pos; 370 | pos = 0; 371 | 372 | uint32_t size_view_list = 0; 373 | ifs.read((char*) &size_view_list, sizeof(uint32_t)); 374 | mFeatureInfos[i].view_list.resize(size_view_list); 375 | mFeatureInfos[i].descriptors.resize(128 * size_view_list, 0); 376 | 377 | unsigned char *desc = new unsigned char[128]; 378 | for (uint32_t j = 0; j < size_view_list; ++j) { 379 | float x, y, scale, orientation; 380 | uint32_t cam_id; 381 | ifs.read((char*) &cam_id, sizeof(uint32_t)); 382 | ifs.read((char*) &x, sizeof(float)); 383 | ifs.read((char*) &y, sizeof(float)); 384 | ifs.read((char*) &scale, sizeof(float)); 385 | ifs.read((char*) &orientation, sizeof(float)); 386 | mFeatureInfos[i].view_list[j].camera = cam_id; 387 | mFeatureInfos[i].view_list[j].x = x; 388 | mFeatureInfos[i].view_list[j].y = y; 389 | mFeatureInfos[i].view_list[j].scale = scale; 390 | mFeatureInfos[i].view_list[j].orientation = orientation; 391 | 392 | ifs.read((char*) desc, 128 * sizeof(unsigned char)); 393 | 394 | // store the descriptor 395 | for (uint32_t k = 0; k < 128; ++k) 396 | mFeatureInfos[i].descriptors[128 * j + k] = desc[k]; 397 | } 398 | delete[] desc; 399 | } 400 | 401 | ifs.close(); 402 | 403 | return true; 404 | } 405 | 406 | //------------------------------ 407 | 408 | void parse_bundler::clear() { 409 | 410 | mNbCameras = 0; 411 | 412 | mNbPoints = (uint32_t) mFeatureInfos.size(); 413 | 414 | for (uint32_t i = 0; i < mNbPoints; ++i) { 415 | mFeatureInfos[i].view_list.clear(); 416 | mFeatureInfos[i].descriptors.clear(); 417 | } 418 | mFeatureInfos.clear(); 419 | 420 | mCameras.clear(); 421 | 422 | } 423 | -------------------------------------------------------------------------------- /parse_bundler.hpp: -------------------------------------------------------------------------------- 1 | /*===========================================================================*\ 2 | * * 3 | * ACG Localizer * 4 | * Copyright (C) 2011-2012 by Computer Graphics Group, RWTH Aachen * 5 | * www.rwth-graphics.de * 6 | * * 7 | *---------------------------------------------------------------------------* 8 | * This file is part of ACG Localizer * 9 | * * 10 | * ACG Localizer is free software: you can redistribute it and/or modify * 11 | * it under the terms of the GNU General Public License as published by * 12 | * the Free Software Foundation, either version 3 of the License, or * 13 | * (at your option) any later version. * 14 | * * 15 | * ACG Localizer is distributed in the hope that it will be useful, * 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 18 | * GNU General Public License for more details. * 19 | * * 20 | * You should have received a copy of the GNU General Public License * 21 | * along with ACG Localizer. If not, see . * 22 | * * 23 | \*===========================================================================*/ 24 | 25 | #ifndef PARSE_BUNDLER_HH 26 | #define PARSE_BUNDLER_HH 27 | 28 | /** 29 | * Parses a bundle.out file created by Bundler into a set of 30 | * 3D points and the corresponding descriptors. 31 | * 32 | * author: Torsten Sattler (tsattler@cs.rwth-aachen.de) 33 | * date : 11-08-2012 34 | **/ 35 | 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | #include 43 | #include "SIFT_keypoint.hpp" 44 | #include "SIFT_loader.hpp" 45 | #include "bundler_camera.hpp" 46 | 47 | //////////////////////////// 48 | // Simple definition of a 3D point 49 | // consisting of x,y,z coordinates 50 | // and a point color. 51 | //////////////////////////// 52 | class point3D { 53 | public: 54 | float x, y, z; 55 | 56 | unsigned char r, g, b; 57 | 58 | point3D() { 59 | x = y = z = 0.0; 60 | r = g = b = 0; 61 | } 62 | 63 | point3D(float x_, float y_, float z_) { 64 | x = x_; 65 | y = y_; 66 | z = z_; 67 | r = g = b = 0; 68 | } 69 | 70 | point3D(float x_, float y_, float z_, unsigned char r_, unsigned char g_, 71 | unsigned char b_) { 72 | x = x_; 73 | y = y_; 74 | z = z_; 75 | r = r_; 76 | g = g_; 77 | b = b_; 78 | } 79 | 80 | point3D(const point3D &other) { 81 | x = other.x; 82 | y = other.y; 83 | z = other.z; 84 | r = other.r; 85 | g = other.g; 86 | b = other.b; 87 | } 88 | 89 | void operator=(const point3D &other) { 90 | x = other.x; 91 | y = other.y; 92 | z = other.z; 93 | r = other.r; 94 | g = other.g; 95 | b = other.b; 96 | } 97 | }; 98 | 99 | //////////////////////////// 100 | // A view of a 3D point as defined by Bundler. It 101 | // contains the index of the camera the point was seen it, 102 | // the keypoint index in the .key file of that camera corresponding 103 | // to the projection of the 3D point, the x- and y-positions of that keypoint 104 | // in a reference frame where the center of the coordinate system is the center 105 | // of the cameras image, as well as the scale and orientation of that keypoint. 106 | // (see http://phototour.cs.washington.edu/bundler/bundler-v0.4-manual.html) 107 | //////////////////////////// 108 | struct view { 109 | uint32_t camera; // index of the camera this feature was detected in 110 | uint32_t key; // index of this feature in the corresponding .key file containing the cameras SIFT features 111 | float x, y; 112 | float scale; // scale at which the feature was detected as taken from the original image 113 | float orientation; // orientation of that features as detected in the image 114 | 115 | view() { 116 | camera = key = 0; 117 | x = y = 0.0; 118 | scale = 0.0f; 119 | orientation = 0.0f; 120 | } 121 | }; 122 | 123 | //////////////////////////// 124 | // Information about a reconstructed 3D point. The structure contains information about the 3D position 125 | // of the point, its color, and a list of views in which the point can be seen and the corresponding SIFT descriptors. 126 | // The descriptor for view view_list[i] is stored in descriptors[128*i]...descriptors[128*i+127] 127 | //////////////////////////// 128 | class feature_3D_info { 129 | public: 130 | point3D point; 131 | std::vector view_list; 132 | 133 | std::vector descriptors; 134 | 135 | // constructor 136 | feature_3D_info() { 137 | view_list.clear(); 138 | descriptors.clear(); 139 | } 140 | 141 | // copy constructor 142 | feature_3D_info(const feature_3D_info &other) { 143 | view_list.clear(); 144 | descriptors.clear(); 145 | view_list.resize(other.view_list.size()); 146 | descriptors.resize(other.descriptors.size()); 147 | 148 | for (uint32_t i = 0; i < (uint32_t) other.view_list.size(); ++i) { 149 | view_list[i].camera = other.view_list[i].camera; 150 | view_list[i].key = other.view_list[i].key; 151 | view_list[i].x = other.view_list[i].x; 152 | view_list[i].y = other.view_list[i].y; 153 | view_list[i].scale = other.view_list[i].scale; 154 | view_list[i].orientation = other.view_list[i].orientation; 155 | } 156 | 157 | for (uint32_t i = 0; i < (uint32_t) other.descriptors.size(); ++i) 158 | descriptors[i] = other.descriptors[i]; 159 | 160 | point = other.point; 161 | } 162 | 163 | // destructor 164 | ~feature_3D_info() { 165 | view_list.clear(); 166 | descriptors.clear(); 167 | } 168 | 169 | // reset all data 170 | void clear_data() { 171 | view_list.clear(); 172 | descriptors.clear(); 173 | } 174 | }; 175 | 176 | //////////////////////////// 177 | // Class to parse the output files generated by Bundler. 178 | // The class is able to further load the .key files of all cameras in 179 | // the reconstruction given that the .key files are not zipped (Bundler 180 | // generally uses gzip to compress the .key files). It can also 181 | // load the file format generated by Bundle2Info. 182 | //////////////////////////// 183 | class parse_bundler { 184 | public: 185 | 186 | // standard constructor 187 | parse_bundler(); 188 | 189 | // standard destructor 190 | ~parse_bundler(); 191 | 192 | // get the number of 3D points in the reconstruction 193 | uint32_t get_number_of_points(); 194 | 195 | // get the number of cameras in the reconstruction 196 | uint32_t get_number_of_cameras(); 197 | 198 | // get the actual 3D points from the loaded reconstruction 199 | void get_points(std::vector &points); 200 | 201 | // get the feature information extracted from the reconstruction 202 | std::vector& get_feature_infos(); 203 | 204 | // get the cameras included in the reconstruction 205 | std::vector& get_cameras(); 206 | 207 | // Parses the output text file generated by bundler. 208 | // Input parameters: The filename of the output file (usually bundle.out) and 209 | // the filename of the list of images (usually list.txt). 210 | bool parse_data(const char* bundle_out_filename_, 211 | const char* image_list_filename); 212 | 213 | // Load the information from a binary file constructed with Bundle2Info. 214 | // The format parameter specifies whether the binary file contains 215 | // no camera information (format=0, as generated by Bundle2Info) or does 216 | // contain camera information (format=1, for example the aachen.info file 217 | // released with the Aachen dataset from the paper 218 | // 219 | // Torsten Sattler, Tobias Weyand, Bastian Leibe, Leif Kobbelt. 220 | // Image Retrieval for Image-Based Localization Revisited. 221 | // BMVC 2012. 222 | bool load_from_binary(const char* filename, const int format); 223 | 224 | // clear the loaded data 225 | void clear(); 226 | 227 | private: 228 | 229 | std::vector mCameras; 230 | 231 | std::vector mFeatureInfos; 232 | 233 | uint32_t mNbPoints, mNbCameras; 234 | 235 | }; 236 | 237 | #endif 238 | -------------------------------------------------------------------------------- /pose_estimation.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * pose_estimation.cpp 3 | * 4 | * Created on: Feb 28, 2015 5 | * Author: Fabian Tschopp, Marco Zorzi 6 | */ 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | #ifndef __APPLE__ 22 | #include 23 | #endif 24 | 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include "P3p.hpp" 34 | #include "P4pf.hpp" 35 | #include "SIFT_keypoint.hpp" 36 | #include "parse_bundler.hpp" 37 | #include "bundler_camera.hpp" 38 | #include "query_loader.hpp" 39 | #include "query_processor.hpp" 40 | #include "log.hpp" 41 | #include "opencv2/core/core.hpp" 42 | #include "opencv2/highgui/highgui.hpp" 43 | #include "opencv2/imgproc/imgproc.hpp" 44 | #include "import_export.hpp" 45 | #include "benchmark.hpp" 46 | 47 | #define DLOG true 48 | #define INFO_DATASET "data/dubrovnik6k.info" 49 | #define GOLDEN_DATASET "data/Dubrovnik6K/bundle/bundle.orig.out" 50 | 51 | #define DATABASE_PATH "data/Dubrovnik6K/" 52 | #define QUERY_PATH "data/query/" 53 | 54 | using namespace pose_estimation; 55 | 56 | int main(int argc, char* argv[]) { 57 | 58 | // For the parallel algorithms, use 4 threads 59 | #ifndef __APPLE__ 60 | omp_set_num_threads(4); 61 | #endif 62 | 63 | // Write some log message 64 | log("Program started."); 65 | 66 | // Load the INFO file 67 | parse_bundler pb; 68 | 69 | // Load the golden reference file 70 | parse_bundler golden_pb; 71 | 72 | #pragma omp parallel sections 73 | { 74 | #pragma omp section 75 | { 76 | golden_pb.parse_data(GOLDEN_DATASET, nullptr); 77 | } 78 | #pragma omp section 79 | { 80 | pb.load_from_binary(INFO_DATASET, 1); 81 | } 82 | } 83 | 84 | log("Dataset loaded."); 85 | 86 | int processor_type; 87 | // Select the processor 88 | std::cout << "0: Basic Processor, 1: Advanced Processor: "; 89 | std::cin >> processor_type; 90 | 91 | QueryProcessor *qp; 92 | 93 | // Prepare query processor 94 | if (processor_type == 1) { 95 | qp = new QueryProcessorAdvanced(pb); 96 | } else { 97 | qp = new QueryProcessorBasic(pb); 98 | } 99 | 100 | // Prepare query loader 101 | QueryLoader ql(DATABASE_PATH, QUERY_PATH); 102 | 103 | // Load a query file 104 | int queryindex; 105 | std::string querypath; 106 | int mode; 107 | bool exit = false; 108 | 109 | // User input loop 110 | while (!exit) { 111 | 112 | std::cout 113 | << "0: Exit, 1: Export 3D Model, 2: Process query file, 3: Benchmark: "; 114 | std::cin >> mode; 115 | 116 | switch (mode) { 117 | case 0: { 118 | exit = true; 119 | break; 120 | } 121 | case 1: { 122 | ExportMesh(golden_pb, "out/", "mesh"); 123 | break; 124 | } 125 | case 2: { 126 | std::cout << "Enter a query index (1 to " << (ql.GetQueryCount()) 127 | << "): "; 128 | 129 | std::cin >> queryindex; 130 | 131 | int queryidx = std::min(std::max(queryindex - 1, 0), 132 | ql.GetQueryCount() - 1); 133 | 134 | Query golden = LoadGoldenQuery(golden_pb, queryidx, 135 | "data/Dubrovnik6K/bundle/"); 136 | 137 | Query query = ql.GetQuery(queryidx, true); 138 | 139 | bool success = qp->Process(query); 140 | 141 | std::cout << "Pose Estimation: " << std::endl; 142 | std::cout << query.focal_length() << std::endl; 143 | std::cout << query.camera_position() << std::endl; 144 | std::cout << query.camera_rotation() << std::endl; 145 | 146 | std::cout << "Pose Estimation (Golden): " << std::endl; 147 | std::cout << golden.focal_length() << std::endl; 148 | std::cout << golden.camera_position() << std::endl; 149 | std::cout << golden.camera_rotation() << std::endl; 150 | 151 | ExportCamera(query, "out/", "camera" + std::to_string(queryindex)); 152 | 153 | ExportCameraProjectEdges(query, "out/", 154 | "camera_proj" + std::to_string(queryindex)); 155 | break; 156 | } 157 | case 3: { 158 | Benchmark(ql, golden_pb, qp); 159 | break; 160 | } 161 | default: 162 | break; 163 | } 164 | } 165 | 166 | } 167 | -------------------------------------------------------------------------------- /pose_utils.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * pose_utils.cpp 3 | * 4 | * Created on: Mar 26, 2015 5 | * Author: Fabian Tschopp 6 | */ 7 | 8 | #include 9 | #include "pose_utils.hpp" 10 | #include 11 | #include 12 | 13 | namespace pose_estimation { 14 | 15 | std::vector SplitString(std::string input, std::string delimiter) { 16 | std::vector output; 17 | 18 | std::string cutline = input; 19 | 20 | size_t pos = 0; 21 | std::string token; 22 | while ((pos = cutline.find(delimiter)) != std::string::npos) { 23 | token = cutline.substr(0, pos); 24 | cutline.erase(0, pos + delimiter.length()); 25 | output.push_back(token); 26 | } 27 | 28 | output.push_back(cutline); 29 | 30 | return output; 31 | } 32 | 33 | std::string CutString(std::string input, std::string delim_from, 34 | std::string delim_to) { 35 | size_t from = input.find(delim_from); 36 | size_t to = input.find(delim_to); 37 | return input.substr(from + delim_from.length(), 38 | to - from - delim_from.length()); 39 | } 40 | 41 | std::string CutStringAfter(std::string input, std::string delim_from) { 42 | size_t from = input.find(delim_from); 43 | if (from == std::string::npos) { 44 | return input; 45 | } 46 | return input.substr(from + delim_from.length(), 47 | input.length() - from - delim_from.length()); 48 | } 49 | 50 | std::string CutStringBefore(std::string input, std::string delim_to) { 51 | size_t to = input.find(delim_to); 52 | if (to == std::string::npos) { 53 | return input; 54 | } 55 | return input.substr(0, to); 56 | } 57 | 58 | std::function GetRandomSelector(unsigned int set_size) { 59 | struct timeval start_time; 60 | gettimeofday(&start_time, NULL); 61 | #ifdef __APPLE__ 62 | std::seed_seq seq { (int)(start_time.tv_sec), (int)(start_time.tv_usec) }; 63 | #else 64 | std::seed_seq seq { start_time.tv_sec, start_time.tv_usec }; 65 | #endif 66 | std::mt19937_64 generator(seq); 67 | std::uniform_int_distribution distribution(0, set_size - 1); 68 | std::function selector = std::bind(distribution, generator); 69 | return selector; 70 | } 71 | 72 | std::function GetRandomProbability() { 73 | struct timeval start_time; 74 | gettimeofday(&start_time, NULL); 75 | #ifdef __APPLE__ 76 | std::seed_seq seq { (int)(start_time.tv_sec), (int)(start_time.tv_usec) }; 77 | #else 78 | std::seed_seq seq { start_time.tv_sec, start_time.tv_usec }; 79 | #endif 80 | std::mt19937_64 generator(seq); 81 | std::uniform_real_distribution distribution(0, 1); 82 | std::function probability = std::bind(distribution, generator); 83 | return probability; 84 | } 85 | 86 | } 87 | -------------------------------------------------------------------------------- /pose_utils.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * pose_utils.hpp 3 | * 4 | * Created on: Mar 22, 2015 5 | * Author: Fabian Tschopp 6 | */ 7 | 8 | #ifndef POSE_UTILS_HPP_ 9 | #define POSE_UTILS_HPP_ 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | namespace pose_estimation { 16 | 17 | std::vector SplitString(std::string input, std::string delimiter); 18 | 19 | std::string CutString(std::string input, std::string delim_from, 20 | std::string delim_to); 21 | 22 | std::string CutStringAfter(std::string input, std::string delim_from); 23 | 24 | std::string CutStringBefore(std::string input, std::string delim_to); 25 | 26 | std::function GetRandomSelector(unsigned int set_size); 27 | 28 | std::function GetRandomProbability(); 29 | 30 | } 31 | 32 | #endif /* POSE_UTILS_HPP_ */ 33 | -------------------------------------------------------------------------------- /query_loader.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * query_loader.cpp 3 | * 4 | * Created on: Mar 21, 2015 5 | * Author: Fabian Tschopp 6 | */ 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | #include "parse_bundler.hpp" 13 | #include "bundler_camera.hpp" 14 | 15 | #include "query_loader.hpp" 16 | #include "SIFT_keypoint.hpp" 17 | #include "pose_utils.hpp" 18 | 19 | #include "opencv2/core/core.hpp" 20 | #include "opencv2/highgui/highgui.hpp" 21 | #include "opencv2/imgproc/imgproc.hpp" 22 | 23 | namespace pose_estimation { 24 | 25 | QueryLoader::~QueryLoader() { 26 | } 27 | 28 | QueryLoader::QueryLoader(std::string database_path, std::string query_path) : 29 | database_path_(database_path), query_path_(query_path) { 30 | 31 | std::ifstream queryfile; 32 | queryfile.open(database_path + "list.query.fused.txt"); 33 | 34 | std::string delimiter = " "; 35 | std::string line; 36 | 37 | while (getline(queryfile, line)) { 38 | double focal_length = 0.0; 39 | 40 | std::vector splitline = SplitString(line, " "); 41 | 42 | int width = std::stoi(splitline[1]); 43 | int height = std::stoi(splitline[2]); 44 | 45 | if (splitline.size() == 4) { 46 | focal_length = std::stod(splitline[3]); 47 | } 48 | 49 | std::string name = CutString(splitline[0], "/", "."); 50 | 51 | if (name.length() > 0) { 52 | Query query(this, name, focal_length); 53 | query.set_image_width(width); 54 | query.set_image_height(height); 55 | queries_.push_back(query); 56 | } 57 | } 58 | 59 | queryfile.close(); 60 | } 61 | 62 | std::string QueryLoader::database_path() { 63 | return database_path_; 64 | } 65 | 66 | std::string QueryLoader::query_path() { 67 | return query_path_; 68 | } 69 | 70 | int QueryLoader::GetQueryCount() { 71 | return queries_.size(); 72 | } 73 | 74 | Query& QueryLoader::GetQuery(int index, bool load_image) { 75 | // Lazy load query image and SIFT when needed 76 | if(load_image) { 77 | queries_[index].LoadImage(); 78 | } 79 | queries_[index].LoadSIFT(); 80 | return queries_[index]; 81 | } 82 | 83 | Query::~Query() { 84 | } 85 | 86 | Query::Query() { 87 | } 88 | 89 | Query::Query(QueryLoader *query_loader, std::string query_image_name, 90 | double focal_length) : 91 | query_loader_(query_loader), query_image_name_(query_image_name), focal_length_( 92 | focal_length), image_width_(0), image_height_(0) { 93 | } 94 | 95 | bool Query::LoadImage() { 96 | 97 | std::string queryimagepath = query_loader_->query_path() + query_image_name_ 98 | + ".jpg"; 99 | 100 | std::ifstream queryimage(queryimagepath); 101 | 102 | if (queryimage.fail()) { 103 | 104 | std::string img_id = query_image_name_; 105 | unsigned int img_id_length = img_id.size() + 1; 106 | while (img_id_length > img_id.size()) { 107 | img_id_length = img_id.size(); 108 | img_id = CutStringAfter(img_id, "_"); 109 | } 110 | 111 | // Get the webpage containing the flickr image 112 | std::string wgetcommand = 113 | "wget -O tmp/tmp.tmp \"http://www.flickr.com/photo_zoom.gne?id=" 114 | + img_id + "&size=o\""; 115 | const char* wgetsystemc = wgetcommand.c_str(); 116 | system(wgetsystemc); 117 | 118 | std::ifstream tmpfile; 119 | tmpfile.open("tmp/tmp.tmp"); 120 | 121 | std::string line; 122 | 123 | bool found_image = false; 124 | 125 | while (getline(tmpfile, line)) { 126 | if (line.find("_o.jpg") != std::string::npos) { 127 | found_image = true; 128 | break; 129 | } 130 | } 131 | 132 | if (found_image) { 133 | // Extract the static image path from flickr webpage 134 | std::string static_image_url = CutString(line, "src=\"", "\">"); 135 | 136 | // Get the image itself 137 | wgetcommand = "wget -O " + queryimagepath + " " + static_image_url; 138 | wgetsystemc = wgetcommand.c_str(); 139 | system(wgetsystemc); 140 | } else { 141 | return false; 142 | } 143 | } 144 | 145 | // Actually load the image 146 | image_ = cv::imread(queryimagepath, CV_LOAD_IMAGE_COLOR); 147 | //image_width_ = image_.cols; 148 | //image_height_ = image_.rows; 149 | 150 | return true; 151 | } 152 | 153 | bool Query::LoadSIFT() { 154 | SIFT_loader siftl; 155 | 156 | std::string querypath = query_loader_->query_path() + query_image_name_ 157 | + ".key"; 158 | 159 | std::ifstream querykey(querypath); 160 | 161 | if (querykey.fail()) { 162 | // Unzip the descriptor if not existing already 163 | std::string gzipcommand = "gzip -k -d -c " 164 | + query_loader_->database_path() + "query/" + query_image_name_ 165 | + ".key.gz > " + query_loader_->query_path() + query_image_name_ 166 | + ".key"; 167 | const char* gzipsystemc = gzipcommand.c_str(); 168 | system(gzipsystemc); 169 | } 170 | 171 | // Load the query descriptors 172 | const char* querycharpath = querypath.c_str(); 173 | siftl.load_features(querycharpath, LOWE); 174 | sift_descriptors_ = siftl.get_descriptors(); 175 | sift_keypoints_ = siftl.get_keypoints(); 176 | return true; 177 | } 178 | 179 | std::vector& Query::sift_keypoints() { 180 | return sift_keypoints_; 181 | } 182 | 183 | std::vector& Query::sift_descriptors() { 184 | return sift_descriptors_; 185 | } 186 | 187 | double Query::focal_length() { 188 | return focal_length_; 189 | } 190 | 191 | Eigen::Matrix Query::camera_position() { 192 | return camera_position_; 193 | } 194 | 195 | Eigen::Matrix Query::camera_rotation() { 196 | return camera_rotation_; 197 | } 198 | 199 | void Query::set_fitpoints_2d( 200 | std::vector> fitpoints_2d) { 201 | fitpoints_2d_ = fitpoints_2d; 202 | } 203 | void Query::set_fitpoints_3d( 204 | std::vector> fitpoints_3d) { 205 | fitpoints_3d_ = fitpoints_3d; 206 | } 207 | std::vector>& Query::fitpoints_2d() { 208 | return fitpoints_2d_; 209 | } 210 | std::vector>& Query::fitpoints_3d() { 211 | return fitpoints_3d_; 212 | } 213 | 214 | 215 | void Query::set_image_width(int width) { 216 | image_width_ = width; 217 | } 218 | void Query::set_image_height(int height) { 219 | image_height_ = height; 220 | } 221 | 222 | bool Query::ComputeMatrices() { 223 | 224 | // Camera intrinsic matrix 225 | camera_matrix_ = Eigen::Matrix::Zero(3, 3); 226 | camera_matrix_(0, 0) = focal_length_; 227 | camera_matrix_(1, 1) = focal_length_; 228 | camera_matrix_(2, 2) = 1.0; 229 | camera_matrix_(0, 2) = 0.0;//image_width_ / 2; 230 | camera_matrix_(1, 2) = 0.0;//image_height_ / 2; 231 | 232 | // Inverse matrix for feature preparation 233 | camera_matrix_inv_ = camera_matrix_.inverse(); 234 | 235 | // 4 to 3 conversion identity matrix 236 | Eigen::Matrix id_mat = Eigen::Matrix::Zero(3, 237 | 4); 238 | 239 | id_mat(0, 0) = 1.0; 240 | id_mat(1, 1) = 1.0; 241 | id_mat(2, 2) = 1.0; 242 | 243 | // Camera extrinsic 244 | Eigen::Matrix rt_mat = Eigen::Matrix::Zero(4, 245 | 4); 246 | rt_mat.block(0, 0, 3, 3) = camera_rotation_; 247 | rt_mat.block(0, 3, 3, 1) = camera_position_; 248 | rt_mat(3, 3) = 1; 249 | 250 | // We have to take the inverse of the RT-matrix because rotation and translation are world->camera. 251 | proj_matrix_ = camera_matrix_ * id_mat * rt_mat.inverse(); 252 | 253 | return true; 254 | } 255 | 256 | void Query::set_camera_position(Eigen::Matrix position) { 257 | camera_position_ = position; 258 | } 259 | 260 | void Query::set_camera_rotation(Eigen::Matrix rotation) { 261 | camera_rotation_ = rotation; 262 | } 263 | 264 | void Query::set_focal_length(double focal_length) { 265 | focal_length_ = focal_length; 266 | } 267 | 268 | Eigen::Matrix Query::camera_matrix() { 269 | return camera_matrix_; 270 | } 271 | 272 | Eigen::Matrix Query::camera_matrix_inv() { 273 | return camera_matrix_inv_; 274 | } 275 | 276 | Eigen::Matrix Query::proj_matrix() { 277 | return proj_matrix_; 278 | } 279 | 280 | cv::Mat& Query::image() { 281 | return image_; 282 | } 283 | 284 | int Query::image_width() { 285 | return image_width_; 286 | } 287 | 288 | int Query::image_height() { 289 | return image_height_; 290 | } 291 | 292 | } 293 | -------------------------------------------------------------------------------- /query_loader.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * query_loader.hpp 3 | * 4 | * Created on: Mar 21, 2015 5 | * Author: Fabian Tschopp 6 | */ 7 | 8 | #ifndef QUERY_LOADER_HPP_ 9 | #define QUERY_LOADER_HPP_ 10 | 11 | #include 12 | #include 13 | #include "opencv2/core/core.hpp" 14 | #include "opencv2/highgui/highgui.hpp" 15 | #include "opencv2/imgproc/imgproc.hpp" 16 | #include 17 | #include 18 | #include 19 | #include "SIFT_keypoint.hpp" 20 | #include "parse_bundler.hpp" 21 | #include "bundler_camera.hpp" 22 | 23 | namespace pose_estimation { 24 | 25 | // Forward declaration 26 | class Query; 27 | class QueryLoader; 28 | 29 | // Query class 30 | class Query { 31 | public: 32 | Query(); 33 | Query(QueryLoader *query_loader, std::string query_image, 34 | double focal_length); 35 | virtual ~Query(); 36 | bool LoadImage(); 37 | bool LoadSIFT(); 38 | bool ComputeMatrices(); 39 | double focal_length(); 40 | Eigen::Matrix camera_position(); 41 | Eigen::Matrix camera_rotation(); 42 | void set_camera_position(Eigen::Matrix position); 43 | void set_camera_rotation(Eigen::Matrix rotation); 44 | void set_focal_length(double focal_length); 45 | std::vector& sift_keypoints(); 46 | std::vector& sift_descriptors(); 47 | Eigen::Matrix camera_matrix(); 48 | Eigen::Matrix camera_matrix_inv(); 49 | Eigen::Matrix proj_matrix(); 50 | cv::Mat& image(); 51 | int image_width(); 52 | int image_height(); 53 | void set_image_width(int width); 54 | void set_image_height(int height); 55 | void set_fitpoints_2d(std::vector> fitpoints_2d); 56 | void set_fitpoints_3d(std::vector> fitpoints_3d); 57 | std::vector>& fitpoints_2d(); 58 | std::vector>& fitpoints_3d(); 59 | private: 60 | QueryLoader *query_loader_; 61 | std::string query_image_name_; 62 | double focal_length_; 63 | Eigen::Matrix camera_position_; 64 | Eigen::Matrix camera_rotation_; 65 | Eigen::Matrix camera_matrix_; 66 | Eigen::Matrix camera_matrix_inv_; 67 | Eigen::Matrix proj_matrix_; 68 | std::vector sift_keypoints_; 69 | std::vector sift_descriptors_; 70 | cv::Mat image_; 71 | int image_width_; 72 | int image_height_; 73 | std::vector> fitpoints_2d_; 74 | std::vector> fitpoints_3d_; 75 | }; 76 | 77 | // QueryLoader class 78 | class QueryLoader { 79 | public: 80 | QueryLoader(std::string database_path, std::string query_path); 81 | virtual ~QueryLoader(); 82 | std::string database_path(); 83 | std::string query_path(); 84 | Query& GetQuery(int index, bool load_image); 85 | int GetQueryCount(); 86 | 87 | private: 88 | std::string database_path_; 89 | std::string query_path_; 90 | std::vector queries_; 91 | }; 92 | 93 | } 94 | 95 | #endif /* QUERY_LOADER_HPP_ */ 96 | -------------------------------------------------------------------------------- /query_processor.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * query_processor.cpp 3 | * 4 | * Created on: Mar 23, 2015 5 | * Author: Fabian Tschopp, Marco Zorzi 6 | */ 7 | 8 | #include "query_processor.hpp" 9 | #include "query_loader.hpp" 10 | #include "P3p.hpp" 11 | #include "P4pf.hpp" 12 | #include 13 | #include 14 | #include 15 | #include "pose_utils.hpp" 16 | #include 17 | #include 18 | #include 19 | 20 | namespace pose_estimation { 21 | 22 | SiftMatch::SiftMatch(unsigned int lindex_p, unsigned int mindex_p, 23 | float distance_p) : 24 | lindex(lindex_p), mindex(mindex_p), distance(distance_p) { 25 | } 26 | 27 | SiftMatch::SiftMatch() : 28 | lindex(0), mindex(0), distance(0.0) { 29 | } 30 | 31 | QueryProcessor::QueryProcessor(parse_bundler &parsebundler) : 32 | parsebundler_(parsebundler) { 33 | 34 | } 35 | 36 | bool QueryProcessor::BundleAdjust(Query &query, 37 | std::vector &fitted_matches, 38 | std::vector &sift_keypoints, 39 | std::vector &sifts) { 40 | // TODO Levenberg Marquardt for 1 camera pose 41 | // TODO Write-back directly into query 42 | // TODO This is optional, if there is enough time to do it. 43 | return true; 44 | } 45 | 46 | bool QueryProcessor::Project(Query &query, 47 | std::vector> &fitpoints_2d, 48 | std::vector> &fitpoints_3d, 49 | std::vector &matches, 50 | std::vector &sift_keypoints, 51 | std::vector &sifts) { 52 | 53 | fitpoints_2d.resize(matches.size()); 54 | fitpoints_3d.resize(matches.size()); 55 | 56 | Eigen::Matrix proj_matrix = query.proj_matrix(); 57 | 58 | // Reproject in parallel 59 | #pragma omp parallel for 60 | for (unsigned int i = 0; i < matches.size(); ++i) { 61 | 62 | SiftMatch match = matches[i]; 63 | 64 | SIFT_keypoint keypoint = sift_keypoints[match.lindex]; 65 | point3D point = sifts[match.mindex].point; 66 | 67 | // Load 3D point 68 | Eigen::Matrix point3d; 69 | point3d << point.x, point.y, point.z, 1.0; 70 | 71 | // Load 2D point 72 | Eigen::Matrix point2d; 73 | point2d << -(keypoint.x - (double) (query.image_width()) / 2.0), -(keypoint.y 74 | - (double) (query.image_height()) / 2.0), 1.0; 75 | 76 | // Projection 77 | Eigen::Matrix point2d_proj = proj_matrix * point3d; 78 | 79 | fitpoints_3d[i] = (point3d.block(0, 0, 3, 1)); 80 | 81 | fitpoints_2d[i] = ((point2d_proj / point2d_proj(2)).block(0, 0, 2, 1)); 82 | 83 | } 84 | 85 | return true; 86 | } 87 | 88 | std::vector QueryProcessor::TestHypothesis(Query &query, 89 | std::vector &matches, 90 | std::vector &sift_keypoints, 91 | std::vector &sifts, double match_eps, 92 | double &fit_quality) { 93 | 94 | fit_quality = 0; 95 | 96 | std::vector fits; 97 | 98 | std::vector> fitpoints_2d; 99 | std::vector> fitpoints_3d; 100 | Project(query, fitpoints_2d, fitpoints_3d, matches, query.sift_keypoints(), 101 | (*sifts_)); 102 | 103 | for (unsigned int i = 0; i < matches.size(); ++i) { 104 | 105 | SiftMatch match = matches[i]; 106 | 107 | SIFT_keypoint keypoint = sift_keypoints[match.lindex]; 108 | 109 | // Load 2D point 110 | Eigen::Matrix point2d; 111 | point2d << -(keypoint.x - (double) (query.image_width()) / 2.0), -(keypoint.y 112 | - (double) (query.image_height()) / 2.0); 113 | 114 | // Load 2d reproject point 115 | Eigen::Matrix point2d_proj; 116 | point2d_proj = fitpoints_2d[i]; 117 | 118 | // Reprojection 2 norm error 119 | double match_dist = (point2d - point2d_proj).norm(); 120 | 121 | if (match_dist < match_eps) { 122 | fits.push_back(match); 123 | } 124 | } 125 | 126 | int width = query.image_width(); 127 | int height = query.image_height(); 128 | 129 | Eigen::MatrixXf fit_area(height, width); 130 | Eigen::MatrixXf match_area(height, width); 131 | 132 | fit_area.setZero(); 133 | match_area.setZero(); 134 | 135 | int cover_area = std::ceil((float) (query.image_width()) / 20.0); 136 | 137 | #pragma omp parallel for 138 | for (unsigned int i = 0; i < fits.size(); ++i) { 139 | SiftMatch &match = fits[i]; 140 | SIFT_keypoint &keypoint = sift_keypoints[match.lindex]; 141 | int x = rint(keypoint.x); 142 | int y = rint(keypoint.y); 143 | 144 | int start_x = std::max(0, std::min(x - cover_area / 2, width - 1)); 145 | int start_y = std::max(0, std::min(y - cover_area / 2, height - 1)); 146 | int stop_x = std::max(0, std::min(x + cover_area / 2, width - 1)); 147 | int stop_y = std::max(0, std::min(y + cover_area / 2, height - 1)); 148 | 149 | if (start_y < stop_y && start_x < stop_x) { 150 | fit_area.block(start_y, start_x, stop_y - start_y, stop_x - start_x).setOnes(); 151 | } 152 | } 153 | 154 | #pragma omp parallel for 155 | for (unsigned int i = 0; i < matches.size(); ++i) { 156 | SiftMatch &match = matches[i]; 157 | SIFT_keypoint &keypoint = sift_keypoints[match.lindex]; 158 | int x = rint(keypoint.x); 159 | int y = rint(keypoint.y); 160 | 161 | int start_x = std::max(0, std::min(x - cover_area / 2, width - 1)); 162 | int start_y = std::max(0, std::min(y - cover_area / 2, height - 1)); 163 | int stop_x = std::max(0, std::min(x + cover_area / 2, width - 1)); 164 | int stop_y = std::max(0, std::min(y + cover_area / 2, height - 1)); 165 | 166 | if (start_y < stop_y && start_x < stop_x) { 167 | match_area.block(start_y, start_x, stop_y - start_y, stop_x - start_x).setOnes(); 168 | } 169 | } 170 | 171 | float fit_area_val = fit_area.sum(); 172 | float match_area_val = match_area.sum(); 173 | 174 | fit_quality = fit_area_val / match_area_val; 175 | 176 | return fits; 177 | } 178 | 179 | } 180 | -------------------------------------------------------------------------------- /query_processor.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * query_processor.hpp 3 | * 4 | * Created on: Mar 23, 2015 5 | * Author: Fabian Tschopp, Marco Zorzi 6 | */ 7 | 8 | #ifndef QUERY_PROCESSOR_HPP_ 9 | #define QUERY_PROCESSOR_HPP_ 10 | 11 | #include "parse_bundler.hpp" 12 | #include "query_loader.hpp" 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | namespace pose_estimation { 19 | 20 | struct SiftMatch { 21 | // Index in the match list 22 | unsigned int lindex; 23 | // Index of the FLANN matching 24 | unsigned int mindex; 25 | // Distance 26 | float distance; 27 | // Set of cameras for efficient set intersection 28 | std::set camset; 29 | SiftMatch(); 30 | SiftMatch(unsigned int lindex_p, unsigned int mindex_p, float distance_p); 31 | }; 32 | 33 | class QueryProcessor { 34 | public: 35 | QueryProcessor(parse_bundler &parsebundler); 36 | virtual bool Process(Query &query) = 0; 37 | std::vector TestHypothesis(Query &query, 38 | std::vector &matches, 39 | std::vector &sift_keypoints, 40 | std::vector &sifts, double match_eps, double &fit_quality); 41 | bool BundleAdjust(Query &query, std::vector &fitted_matches, 42 | std::vector &sift_keypoints, 43 | std::vector &sifts); 44 | bool Project(Query &query, 45 | std::vector> &fitpoints_2d, 46 | std::vector> &fitpoints_3d, 47 | std::vector &matches, 48 | std::vector &sift_keypoints, 49 | std::vector &sifts); 50 | protected: 51 | parse_bundler &parsebundler_; 52 | flann::Index>* flann_index_; 53 | std::vector features_; 54 | flann::Matrix dataset_; 55 | std::vector *sifts_; 56 | }; 57 | 58 | class QueryProcessorBasic: public QueryProcessor { 59 | public: 60 | QueryProcessorBasic(parse_bundler &parsebundler); 61 | bool Process(Query &query); 62 | private: 63 | 64 | }; 65 | 66 | class QueryProcessorAdvanced: public QueryProcessor { 67 | public: 68 | QueryProcessorAdvanced(parse_bundler &parsebundler); 69 | bool Process(Query &query); 70 | bool Backmatching(std::vector &good_matches, 71 | flann::Matrix &queryset); 72 | private: 73 | }; 74 | 75 | } 76 | 77 | #endif /* QUERY_PROCESSOR_HPP_ */ 78 | -------------------------------------------------------------------------------- /query_processor_advanced.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * query_processor_advanced.cpp 3 | * 4 | * Created on: Apr 13, 2015 5 | * Author: Fabian Tschopp, Marco Zorzi 6 | */ 7 | 8 | #include "query_processor.hpp" 9 | #include "query_loader.hpp" 10 | #include "P3p.hpp" 11 | #include "P4pf.hpp" 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include "pose_utils.hpp" 18 | #include 19 | #include 20 | #include 21 | 22 | namespace pose_estimation { 23 | 24 | QueryProcessorAdvanced::QueryProcessorAdvanced(parse_bundler &parsebundler) : 25 | QueryProcessor(parsebundler) { 26 | 27 | sifts_ = &(parsebundler_.get_feature_infos()); 28 | 29 | features_ = std::vector(sifts_->size() * 128); 30 | 31 | // Collect features and apply averaging 32 | #pragma omp parallel for 33 | for (unsigned int i = 0; i < sifts_->size(); ++i) { 34 | for (int j = 0; j < 128; ++j) { 35 | features_[i * 128 + j] = 0; 36 | } 37 | for (unsigned int k = 0; k < ((*sifts_)[i].descriptors.size() / 128); 38 | ++k) { 39 | for (int j = 0; j < 128; ++j) { 40 | // 128*k stride, 128 descriptors/stride (j) and i separate features 41 | features_[i * 128 + j] += (float) (*sifts_)[i].descriptors[j 42 | + 128 * k]; 43 | } 44 | } 45 | for (int j = 0; j < 128; ++j) { 46 | features_[i * 128 + j] /= (float) ((*sifts_)[i].descriptors.size() 47 | / 128); 48 | } 49 | } 50 | 51 | dataset_ = flann::Matrix(&features_[0], sifts_->size(), 128); 52 | 53 | flann_index_ = new flann::Index>(dataset_, 54 | flann::KDTreeIndexParams(4)); 55 | flann_index_->buildIndex(); 56 | } 57 | 58 | struct PriorityFeature { 59 | unsigned int index; 60 | float priority; 61 | PriorityFeature(unsigned int index_p, float priority_p); 62 | }; 63 | 64 | PriorityFeature::PriorityFeature(unsigned int index_p, float priority_p) : 65 | index(index_p), priority(priority_p) { 66 | } 67 | 68 | struct PriorityOrder { 69 | bool operator()(const PriorityFeature& lhs, 70 | const PriorityFeature& rhs) const { 71 | return lhs.priority < rhs.priority; 72 | } 73 | }; 74 | 75 | bool QueryProcessorAdvanced::Backmatching(std::vector &good_matches, 76 | flann::Matrix &queryset) { 77 | 78 | // Build a new FLANN KDTree based on image features 79 | flann::Index> flann_queryindex(queryset, 80 | flann::KDTreeIndexParams(4)); 81 | flann_queryindex.buildIndex(); 82 | 83 | // Number of nearest neighbors to look for 84 | int nn = 2; 85 | // Number of backmatches to be achieved 86 | unsigned int N = 100; 87 | // Lowe's ratio test value 88 | float ratio = 0.7; 89 | // Dynamic priorities booster 90 | float w = 10; 91 | 92 | flann::Matrix indices(new int[nn], 1, nn); 93 | flann::Matrix dists(new float[nn], 1, nn); 94 | 95 | std::vector backmatches; 96 | 97 | unsigned int t = 0; 98 | 99 | std::priority_queue, 100 | PriorityOrder> queue; 101 | std::priority_queue, 102 | PriorityOrder> new_queue; 103 | 104 | // Determine maximum priority from view graph to boost the good matches to the top of the queue 105 | float max_priority = 0; 106 | for (unsigned int i = 0; i < sifts_->size(); ++i) { 107 | int viewlist_size = (*sifts_)[i].view_list.size(); 108 | max_priority = std::max(max_priority, (float) viewlist_size); 109 | } 110 | 111 | std::cout << "Max priority is " << max_priority << std::endl; 112 | 113 | // Fill in the queue 114 | for (unsigned int i = 0; i < sifts_->size(); ++i) { 115 | int viewlist_size = (*sifts_)[i].view_list.size(); 116 | PriorityFeature feature(i, viewlist_size); 117 | // Boost the good matches to the top of the queue 118 | for (unsigned int j = 0; j < good_matches.size(); ++j) { 119 | if (good_matches[j].mindex == i) { 120 | feature.priority += max_priority; 121 | } 122 | } 123 | queue.push(feature); 124 | } 125 | 126 | std::map increase_views; 127 | //std::vector increase_views; 128 | 129 | std::cout << "Starting backmatching" << std::endl; 130 | while (t < 500 * N && backmatches.size() < N) { 131 | 132 | std::vector backfeatures(128); 133 | 134 | // Prioritized picking of a 3D feature point 135 | PriorityFeature prio_feature = queue.top(); 136 | queue.pop(); 137 | #pragma omp parallel for 138 | for (int i = 0; i < 128; ++i) { 139 | backfeatures[i] = features_[128 * prio_feature.index + i]; 140 | } 141 | 142 | //std::cout << "FLANN search of feature " << prio_feature.index 143 | // << " with priority " << prio_feature.priority << std::endl; 144 | flann::Matrix backquery(&backfeatures[0], 1, 128); 145 | flann_queryindex.knnSearch(backquery, indices, dists, nn, 146 | flann::SearchParams(128)); 147 | 148 | // Ratio test and accept/reject the backmatch 149 | if ((dists.ptr()[0] / dists.ptr()[1] < ratio)) { 150 | SiftMatch backmatch(indices.ptr()[0], prio_feature.index, 151 | dists.ptr()[0]); 152 | backmatches.push_back(backmatch); 153 | // Add all views to those that we have to increase in priority 154 | int viewlist_size = (*sifts_)[prio_feature.index].view_list.size(); 155 | for (int i = 0; i < viewlist_size; ++i) { 156 | increase_views[(*sifts_)[prio_feature.index].view_list[i].camera]++; 157 | } 158 | } 159 | 160 | // Update priority queue according to choices, every 100 steps (excluding the first one) 161 | if (t != 0 && t % 100 == 0) { 162 | std::cout << "Backmatching step " << t << ", set size " 163 | << backmatches.size() << std::endl; 164 | // Process every element in the queue (in parallel) 165 | #pragma omp parallel 166 | { 167 | while (true) { 168 | PriorityFeature feature(0, 0); 169 | bool empty = false; 170 | #pragma omp critical (queuepop) 171 | { 172 | if (queue.empty()) { 173 | empty = true; 174 | } else { 175 | feature = queue.top(); 176 | queue.pop(); 177 | } 178 | } 179 | if (empty) { 180 | break; 181 | } 182 | int viewlist_size = 183 | (*sifts_)[feature.index].view_list.size(); 184 | for (std::map::iterator i = 185 | increase_views.begin(); i != increase_views.end(); 186 | ++i) { 187 | for (int j = 0; j < viewlist_size; ++j) { 188 | if ((*sifts_)[feature.index].view_list[j].camera 189 | == (*i).first) { 190 | feature.priority += w * (*i).second 191 | / (float) viewlist_size; 192 | } 193 | } 194 | } 195 | #pragma omp critical (queuepush) 196 | { 197 | new_queue.push(feature); 198 | } 199 | } 200 | #pragma omp barrier 201 | } 202 | // Employ the updated queue 203 | std::swap(queue, new_queue); 204 | } 205 | ++t; 206 | } 207 | std::cout << "Backmatching search done, inserting into good matches" 208 | << std::endl; 209 | 210 | //good_matches.clear(); 211 | for (unsigned int i = 0; i < backmatches.size(); ++i) { 212 | // Remove feature duplicates in backmatches 213 | bool is_duplicate = false; 214 | for (unsigned int j = 0; j < good_matches.size(); ++j) { 215 | if (backmatches[i].lindex == good_matches[j].lindex) { 216 | is_duplicate = true; 217 | } 218 | } 219 | // Copy to good matches 220 | if (!is_duplicate) { 221 | // Fill in the camera set 222 | SiftMatch match = backmatches[i]; 223 | for (unsigned int v = 0; 224 | v < (*sifts_)[match.mindex].view_list.size(); ++v) { 225 | match.camset.insert( 226 | (*sifts_)[match.mindex].view_list[v].camera); 227 | } 228 | good_matches.push_back(match); 229 | } 230 | } 231 | 232 | std::cout << "Backmatching done, new good matches size is " 233 | << good_matches.size() << std::endl; 234 | 235 | // Cleanup and return 236 | return true; 237 | } 238 | 239 | bool QueryProcessorAdvanced::Process(Query &query) { 240 | 241 | Query query_copy = query; 242 | 243 | std::vector &sifts = query_copy.sift_descriptors(); 244 | 245 | std::vector features(sifts.size() * 128); 246 | 247 | #pragma omp parallel for 248 | for (unsigned int i = 0; i < sifts.size(); ++i) { 249 | for (int j = 0; j < 128; ++j) { 250 | features[i * 128 + j] = (float) sifts[i][j]; 251 | } 252 | } 253 | 254 | // FLANN kd-tree nearest neighbor search 255 | int nn = 2; 256 | 257 | flann::Matrix queryset(&features[0], sifts.size(), 128); 258 | 259 | flann::Matrix indices(new int[queryset.rows * nn], queryset.rows, nn); 260 | flann::Matrix dists(new float[queryset.rows * nn], queryset.rows, 261 | nn); 262 | 263 | flann_index_->knnSearch(queryset, indices, dists, nn, 264 | flann::SearchParams(128)); 265 | 266 | // Matches that have been correct by SIFT matching 267 | std::vector good_matches; 268 | // Matches that have been correct by reprojection 269 | std::vector fitted_matches; 270 | 271 | // Lowe's ratio test 272 | float ratio = 0.9; 273 | for (unsigned int i = 0; i < sifts.size(); ++i) { 274 | if ((dists.ptr()[i * nn] / dists.ptr()[i * nn + 1] < ratio)) { 275 | // Create a SiftMatch 276 | SiftMatch match(i, indices.ptr()[i * nn], dists.ptr()[i * nn]); 277 | // Fill in the camera set 278 | for (unsigned int v = 0; 279 | v < (*sifts_)[match.mindex].view_list.size(); ++v) { 280 | match.camset.insert( 281 | (*sifts_)[match.mindex].view_list[v].camera); 282 | } 283 | good_matches.push_back(match); 284 | } 285 | } 286 | 287 | std::cout << " good_matches.size(): " << good_matches.size() << std::endl; 288 | 289 | P3p p3p; 290 | P4pf p4pf; 291 | 292 | bool p4pfmode = query_copy.focal_length() == 0.0; 293 | 294 | // RANSAC 295 | // Maximum ransac steps 296 | unsigned int max_ransac_steps = 100; 297 | // L2-pixel distance for inliers 298 | double inlier_eps = 0.5; 299 | // Fraction of good matches as inliers to stop RANSAC 300 | unsigned int inlier_divisor = 10; 301 | // Total amount of good matches as inliers to stop RANSAC 302 | unsigned int inlier_absolute = 12; 303 | // Step counter 304 | unsigned int steps = 0; 305 | // Hyposet size 306 | unsigned int hyposet = 0; 307 | // Hypothesis quality 308 | double hypoquality = 0; 309 | 310 | // Random sample selector 311 | std::function rand = GetRandomSelector(good_matches.size()); 312 | 313 | // Random probability selector (for improved RANSAC with co-occurence prior) 314 | std::function prob = GetRandomProbability(); 315 | 316 | // Compute initial matrices of the camera (based on image size and focal length) 317 | if (p4pfmode) { 318 | // Some "educated guess" on the focal length to get a good inverse camera intrinsic matrix 319 | query_copy.set_focal_length(query_copy.image_height() / 2); 320 | } 321 | query_copy.ComputeMatrices(); 322 | 323 | // Boolean for backmatching 324 | bool tried_backmatching = false; 325 | 326 | // Exit if good model is found or maximum algorithm steps reached 327 | while (steps < max_ransac_steps) { 328 | 329 | // Select 3 points for the camera position hypothesis (4 for P4pf) 330 | //this is what they call K, the subset of of M. M is good_matches 331 | std::vector selectset; 332 | //Create intersection set 333 | 334 | std::set intersect; 335 | 336 | // Deterministic upper bound for the selection 337 | int zero_check_count = 0; 338 | int zero_check_limit = 200; 339 | 340 | for (unsigned int i = 0; i < (p4pfmode == true ? 4 : 3); ++i) { 341 | bool valid_choice = false; 342 | 343 | int zero_check = 0; 344 | while (!valid_choice) { 345 | 346 | std::set s_camset; 347 | SiftMatch select; 348 | 349 | // First element of the couple to give to RANSAC 350 | do { 351 | // Extracted randomly from good matches 352 | select = good_matches[rand()]; 353 | //Now we have a valid match 354 | s_camset = select.camset; 355 | // We want that more than 5 cameras have seen the first point chosen (i == 0) 356 | if (i == 0) { 357 | intersect = s_camset; 358 | } 359 | } while (i == 0 && s_camset.size() < 5); 360 | 361 | valid_choice = true; 362 | for (unsigned int j = 0; j < selectset.size(); ++j) { 363 | SiftMatch opponent = selectset[j]; 364 | if (select.lindex == opponent.lindex) { 365 | valid_choice = false; 366 | } 367 | } 368 | 369 | // Co-occurence check for i > 0 (points after the first one) 370 | if (valid_choice && i > 0) { 371 | //we get here with at least one element in selectset, no duplicates 372 | std::set check; 373 | std::set_intersection(s_camset.begin(), s_camset.end(), 374 | intersect.begin(), intersect.end(), 375 | std::inserter(check, check.begin())); 376 | 377 | #ifdef DBG 378 | std::cout << "s_camset.size()= " << s_camset.size() << std::endl; 379 | std::cout << "intersect.size()= " << intersect.size() << std::endl; 380 | std::cout << "check.size()= " << check.size() << std::endl; 381 | #endif 382 | 383 | if (check.size() == 0 384 | && zero_check_count <= zero_check_limit) { 385 | zero_check++; 386 | valid_choice = false; 387 | } else { 388 | float ratio = (float) (check.size()) 389 | / (std::min(intersect.size(), s_camset.size())); 390 | // 75% acceptance probability pre-multiplier at check.size() == k (==5) 391 | float k = 5; 392 | ratio *= 1.0 / (1.0 + exp(-(check.size() / k))); 393 | float temp = prob(); 394 | 395 | // Accept everything to get to a deterministic upper bound solution 396 | if (zero_check_count > zero_check_limit) { 397 | ratio = 1.0; 398 | } 399 | 400 | #ifdef DBG 401 | std::cout << "GetRandomProbability()= " << temp << std::endl; 402 | std::cout << "ratio= " << ratio << std::endl; 403 | #endif 404 | 405 | if (ratio > temp) { 406 | #ifdef DBG 407 | std::cout << "Point accepted!" << std::endl; 408 | #endif 409 | 410 | valid_choice = true; 411 | intersect = check; 412 | } else { 413 | valid_choice = false; 414 | #ifdef DBG 415 | std::cout << "Point not accepted" << std::endl; 416 | #endif 417 | } 418 | } 419 | } 420 | 421 | if (valid_choice) { 422 | selectset.push_back(select); 423 | } 424 | 425 | if (zero_check > 30) { 426 | #ifdef DBG 427 | std::cout << "wooops, Zerocheck failed" << std::endl; 428 | #endif 429 | // Reset loop, new first point gets chosen 430 | i = -1; 431 | selectset.clear(); 432 | intersect.clear(); 433 | valid_choice = true; 434 | zero_check_count++; 435 | } 436 | } 437 | #ifdef DBG 438 | std::cout << "\nEnded While valid choice\n\n"; 439 | #endif 440 | } 441 | #ifdef DBG 442 | std::cout << "Selectset.size(): " << selectset.size() << std::endl; 443 | #endif 444 | 445 | if (p4pfmode) { 446 | // P4pf case 447 | Eigen::Matrix feature_vectors; 448 | Eigen::Matrix world_points; 449 | std::vector focal_length_solutions; 450 | std::vector> rotation_solutions; 451 | std::vector> translation_solutions; 452 | 453 | for (int i = 0; i < 4; ++i) { 454 | SiftMatch match = selectset[i]; 455 | 456 | SIFT_keypoint keypoint = 457 | query_copy.sift_keypoints()[match.lindex]; 458 | 459 | point3D point = (*sifts_)[match.mindex].point; 460 | 461 | Eigen::Matrix feature; 462 | feature 463 | << -(keypoint.x 464 | - (double) (query_copy.image_width()) / 2.0), -(keypoint.y 465 | - (double) (query_copy.image_height()) / 2.0), query_copy.focal_length(); 466 | 467 | feature_vectors.col(i) = feature.block(0, 0, 2, 1); 468 | 469 | // The 3D point 470 | Eigen::Matrix world_point; 471 | world_point << point.x, point.y, point.z; 472 | world_points.col(i) = world_point; 473 | } 474 | 475 | p4pf.P4Pf_m(feature_vectors, world_points, &focal_length_solutions, 476 | &rotation_solutions, &translation_solutions); 477 | 478 | // Test the proposed solutions 479 | for (unsigned int i = 0; i < focal_length_solutions.size(); ++i) { 480 | double focal_length = focal_length_solutions[i]; 481 | Eigen::Matrix translation = 482 | translation_solutions[i]; 483 | Eigen::Matrix rotation = rotation_solutions[i]; 484 | 485 | Eigen::Matrix camera_position = 486 | -rotation.transpose() * translation; 487 | Eigen::Matrix camera_rotation = 488 | rotation.transpose(); 489 | 490 | query_copy.set_focal_length(focal_length); 491 | query_copy.set_camera_position(camera_position); 492 | query_copy.set_camera_rotation(camera_rotation); 493 | 494 | // Compute the camera and projection matrix 495 | query_copy.ComputeMatrices(); 496 | 497 | double new_hypoquality = 0; 498 | std::vector fitmatch_vec = TestHypothesis(query_copy, 499 | good_matches, query_copy.sift_keypoints(), (*sifts_), 500 | inlier_eps, new_hypoquality); 501 | 502 | unsigned int new_hyposet = fitmatch_vec.size(); 503 | 504 | if (new_hypoquality > hypoquality) { 505 | // New hypothesis was better than the old one 506 | hypoquality = new_hypoquality; 507 | hyposet = new_hyposet; 508 | std::cout << "New hyposet size: " << hyposet 509 | << ", with quality " << hypoquality << std::endl; 510 | // Transfer solution from working copy to original query 511 | query.set_focal_length(query_copy.focal_length()); 512 | query.set_camera_position(query_copy.camera_position()); 513 | query.set_camera_rotation(query_copy.camera_rotation()); 514 | fitted_matches = fitmatch_vec; 515 | } 516 | } 517 | 518 | } else { 519 | // P3p case 520 | Eigen::Matrix feature_vectors; 521 | Eigen::Matrix world_points; 522 | Eigen::Matrix solutions; 523 | 524 | for (int i = 0; i < 3; ++i) { 525 | 526 | SiftMatch match = selectset[i]; 527 | 528 | SIFT_keypoint keypoint = 529 | query_copy.sift_keypoints()[match.lindex]; 530 | 531 | point3D point = (*sifts_)[match.mindex].point; 532 | 533 | Eigen::Matrix feature; 534 | feature 535 | << -(keypoint.x 536 | - (double) (query_copy.image_width()) / 2.0), -(keypoint.y 537 | - (double) (query_copy.image_height()) / 2.0), query_copy.focal_length(); 538 | 539 | feature.normalize(); 540 | 541 | feature_vectors.col(i) = feature; 542 | Eigen::Matrix world_point; 543 | world_point << point.x, point.y, point.z; 544 | world_points.col(i) = world_point; 545 | } 546 | 547 | p3p.computePoses(feature_vectors, world_points, solutions); 548 | 549 | // Test the 4 proposed solutions 550 | for (int i = 0; i < 4; ++i) { 551 | Eigen::Matrix camera_position = solutions.block(0, 552 | i * 4, 3, 1); 553 | Eigen::Matrix camera_rotation = solutions.block(0, 554 | i * 4 + 1, 3, 3); 555 | 556 | query_copy.set_camera_position(camera_position); 557 | query_copy.set_camera_rotation(camera_rotation); 558 | 559 | // Compute the camera and projection matrix 560 | query_copy.ComputeMatrices(); 561 | 562 | double new_hypoquality = 0; 563 | std::vector fitmatch_vec = TestHypothesis(query_copy, 564 | good_matches, query_copy.sift_keypoints(), (*sifts_), 565 | inlier_eps, new_hypoquality); 566 | 567 | unsigned int new_hyposet = fitmatch_vec.size(); 568 | 569 | if (new_hypoquality > hypoquality) { 570 | // New hypothesis was better than the old one 571 | hypoquality = new_hypoquality; 572 | hyposet = new_hyposet; 573 | std::cout << "New hyposet size: " << hyposet 574 | << ", with quality " << hypoquality << std::endl; 575 | // Transfer solution from working copy to original query 576 | query.set_camera_position(query_copy.camera_position()); 577 | query.set_camera_rotation(query_copy.camera_rotation()); 578 | fitted_matches = fitmatch_vec; 579 | } 580 | } 581 | } 582 | 583 | // Increase the RANSAC step counter 584 | ++steps; 585 | 586 | // If the RANSAC steps are used up and no solution is found, we can try backmatching and reset the RANSAC steps 587 | if (!tried_backmatching 588 | && hyposet < good_matches.size() / inlier_divisor 589 | && hyposet < inlier_absolute && steps == max_ransac_steps) { 590 | 591 | // Augment the good matches by doing backmatching: 592 | Backmatching(good_matches, queryset); 593 | 594 | // Replace the random function, because good_matches size has changed 595 | rand = GetRandomSelector(good_matches.size()); 596 | 597 | // Reset RANSAC steps 598 | steps = 0; 599 | 600 | // Reset hyposet 601 | // hyposet = 0; 602 | // hypoquality = 0; 603 | 604 | // Backmatching applied, mark as true 605 | tried_backmatching = true; 606 | } 607 | } 608 | 609 | // Compute final solution on the original query 610 | query.ComputeMatrices(); 611 | 612 | // Refine with Bundle adjustment 613 | BundleAdjust(query, fitted_matches, query.sift_keypoints(), (*sifts_)); 614 | 615 | // Reproject the fitted matches and store in the query 616 | std::vector> fitpoints_2d; 617 | std::vector> fitpoints_3d; 618 | Project(query, fitpoints_2d, fitpoints_3d, fitted_matches, 619 | query.sift_keypoints(), (*sifts_)); 620 | query.set_fitpoints_2d(fitpoints_2d); 621 | query.set_fitpoints_3d(fitpoints_3d); 622 | 623 | return true; 624 | } 625 | 626 | } 627 | 628 | -------------------------------------------------------------------------------- /query_processor_basic.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * query_processor_basic.cpp 3 | * 4 | * Created on: Apr 13, 2015 5 | * Author: Fabian Tschopp, Marco Zorzi 6 | */ 7 | 8 | #include "query_processor.hpp" 9 | #include "query_loader.hpp" 10 | #include "P3p.hpp" 11 | #include "P4pf.hpp" 12 | #include 13 | #include 14 | #include 15 | #include "pose_utils.hpp" 16 | #include 17 | #include 18 | #include 19 | 20 | namespace pose_estimation { 21 | 22 | QueryProcessorBasic::QueryProcessorBasic(parse_bundler &parsebundler) : 23 | QueryProcessor(parsebundler) { 24 | 25 | sifts_ = &(parsebundler_.get_feature_infos()); 26 | 27 | features_ = std::vector(sifts_->size() * 128); 28 | 29 | // Collect features and apply averaging 30 | #pragma omp parallel for 31 | for (unsigned int i = 0; i < sifts_->size(); ++i) { 32 | for (int j = 0; j < 128; ++j) { 33 | features_[i * 128 + j] = 0; 34 | } 35 | for (unsigned int k = 0; k < ((*sifts_)[i].descriptors.size() / 128); 36 | ++k) { 37 | for (int j = 0; j < 128; ++j) { 38 | // 128*k stride, 128 descriptors/stride (j) and i separate features 39 | features_[i * 128 + j] += (float) (*sifts_)[i].descriptors[j 40 | + 128 * k]; 41 | } 42 | } 43 | for (int j = 0; j < 128; ++j) { 44 | features_[i * 128 + j] /= (float) ((*sifts_)[i].descriptors.size() 45 | / 128); 46 | } 47 | } 48 | 49 | dataset_ = flann::Matrix(&features_[0], sifts_->size(), 128); 50 | 51 | flann_index_ = new flann::Index>(dataset_, 52 | flann::KDTreeIndexParams(4)); 53 | flann_index_->buildIndex(); 54 | 55 | } 56 | 57 | bool QueryProcessorBasic::Process(Query &query) { 58 | 59 | Query query_copy = query; 60 | 61 | std::vector &sifts = query_copy.sift_descriptors(); 62 | 63 | std::vector features(sifts.size() * 128); 64 | 65 | #pragma omp parallel for 66 | for (unsigned int i = 0; i < sifts.size(); ++i) { 67 | for (int j = 0; j < 128; ++j) { 68 | features[i * 128 + j] = (float) sifts[i][j]; 69 | } 70 | } 71 | 72 | // FLANN kd-tree nearest neighbor search 73 | int nn = 2; 74 | 75 | flann::Matrix queryset(&features[0], sifts.size(), 128); 76 | 77 | flann::Matrix indices(new int[queryset.rows * nn], queryset.rows, nn); 78 | flann::Matrix dists(new float[queryset.rows * nn], queryset.rows, 79 | nn); 80 | 81 | flann_index_->knnSearch(queryset, indices, dists, nn, 82 | flann::SearchParams(128)); 83 | 84 | // Matches that have been correct by SIFT matching 85 | std::vector good_matches; 86 | // Matches that have been correct by reprojection 87 | std::vector fitted_matches; 88 | 89 | // Lowe's ratio test 90 | float ratio = 0.7; 91 | for (unsigned int i = 0; i < sifts.size(); ++i) { 92 | SiftMatch match(i, indices.ptr()[i * nn], dists.ptr()[i * nn]); 93 | if ((dists.ptr()[i * nn] / dists.ptr()[i * nn + 1] < ratio)) { 94 | good_matches.push_back(match); 95 | } 96 | } 97 | 98 | std::cout << good_matches.size() << std::endl; 99 | 100 | P3p p3p; 101 | P4pf p4pf; 102 | 103 | bool p4pfmode = query_copy.focal_length() == 0.0; 104 | 105 | // RANSAC 106 | // Maximum ransac steps 107 | unsigned int max_ransac_steps = 10000; 108 | // L2-pixel distance for inliers 109 | double inlier_eps = 0.5; 110 | // Fraction of good matches as inliers to stop RANSAC 111 | unsigned int inlier_divisor = 10; 112 | // Total amount of good matches as inliers to stop RANSAC 113 | unsigned int inlier_absolute = 12; 114 | // Step counter 115 | unsigned int steps = 0; 116 | // Hyposet size 117 | unsigned int hyposet = 0; 118 | // Hypothesis quality 119 | double hypoquality = 0; 120 | 121 | // Random sample selector 122 | std::function rand = GetRandomSelector(good_matches.size()); 123 | 124 | // Compute initial matrices of the camera (based on image size and focal length) 125 | if (p4pfmode) { 126 | // Some "educated guess" on the focal length to get a good inverse camera intrinsic matrix 127 | query_copy.set_focal_length(query_copy.image_height() / 2); 128 | } 129 | query_copy.ComputeMatrices(); 130 | 131 | // Exit if good model is found or maximum algorithm steps reached 132 | while (hyposet < good_matches.size() / inlier_divisor 133 | && steps < max_ransac_steps && hyposet < inlier_absolute) { 134 | 135 | // Select 3 points for the camera position hypothesis (4 for P4pf) 136 | std::vector selectset; 137 | for (unsigned int i = 0; i < (p4pfmode == true ? 4 : 3); ++i) { 138 | bool valid_choice = false; 139 | while (!valid_choice) { 140 | SiftMatch select = good_matches[rand()]; 141 | valid_choice = true; 142 | for (unsigned int j = 0; j < selectset.size(); ++j) { 143 | SiftMatch opponent = selectset[j]; 144 | if (select.lindex == opponent.lindex) { 145 | valid_choice = false; 146 | } 147 | } 148 | if (valid_choice) { 149 | selectset.push_back(select); 150 | } 151 | } 152 | } 153 | 154 | if (p4pfmode) { 155 | // P4pf case 156 | Eigen::Matrix feature_vectors; 157 | Eigen::Matrix world_points; 158 | std::vector focal_length_solutions; 159 | std::vector> rotation_solutions; 160 | std::vector> translation_solutions; 161 | 162 | for (int i = 0; i < 4; ++i) { 163 | 164 | SiftMatch match = selectset[i]; 165 | 166 | SIFT_keypoint keypoint = 167 | query_copy.sift_keypoints()[match.lindex]; 168 | 169 | point3D point = (*sifts_)[match.mindex].point; 170 | 171 | Eigen::Matrix feature; 172 | feature 173 | << -(keypoint.x 174 | - (double) (query_copy.image_width()) / 2.0), -(keypoint.y 175 | - (double) (query_copy.image_height()) / 2.0), query_copy.focal_length(); 176 | 177 | feature_vectors.col(i) = feature.block(0, 0, 2, 1); 178 | 179 | // The 3D point 180 | Eigen::Matrix world_point; 181 | world_point << point.x, point.y, point.z; 182 | world_points.col(i) = world_point; 183 | } 184 | 185 | p4pf.P4Pf_m(feature_vectors, world_points, &focal_length_solutions, 186 | &rotation_solutions, &translation_solutions); 187 | 188 | // Test the proposed solutions 189 | for (unsigned int i = 0; i < focal_length_solutions.size(); ++i) { 190 | double focal_length = focal_length_solutions[i]; 191 | Eigen::Matrix translation = 192 | translation_solutions[i]; 193 | Eigen::Matrix rotation = rotation_solutions[i]; 194 | 195 | Eigen::Matrix camera_position = 196 | -rotation.transpose() * translation; 197 | Eigen::Matrix camera_rotation = 198 | rotation.transpose(); 199 | 200 | query_copy.set_focal_length(focal_length); 201 | query_copy.set_camera_position(camera_position); 202 | query_copy.set_camera_rotation(camera_rotation); 203 | 204 | // Compute the camera and projection matrix 205 | query_copy.ComputeMatrices(); 206 | 207 | double new_hypoquality = 0; 208 | std::vector fitmatch_vec = TestHypothesis(query_copy, 209 | good_matches, query_copy.sift_keypoints(), (*sifts_), 210 | inlier_eps, new_hypoquality); 211 | 212 | unsigned int new_hyposet = fitmatch_vec.size(); 213 | 214 | if (new_hypoquality > hypoquality) { 215 | // New hypothesis was better than the old one 216 | hypoquality = new_hypoquality; 217 | hyposet = new_hyposet; 218 | std::cout << "New hyposet size: " << hyposet 219 | << ", with quality " << hypoquality << std::endl; 220 | // Transfer solution from working copy to original query 221 | query.set_focal_length(query_copy.focal_length()); 222 | query.set_camera_position(query_copy.camera_position()); 223 | query.set_camera_rotation(query_copy.camera_rotation()); 224 | fitted_matches = fitmatch_vec; 225 | } 226 | } 227 | 228 | } else { 229 | // P3p case 230 | Eigen::Matrix feature_vectors; 231 | Eigen::Matrix world_points; 232 | Eigen::Matrix solutions; 233 | 234 | for (int i = 0; i < 3; ++i) { 235 | 236 | SiftMatch match = selectset[i]; 237 | 238 | SIFT_keypoint keypoint = 239 | query_copy.sift_keypoints()[match.lindex]; 240 | 241 | point3D point = (*sifts_)[match.mindex].point; 242 | 243 | Eigen::Matrix feature; 244 | feature 245 | << -(keypoint.x 246 | - (double) (query_copy.image_width()) / 2.0), -(keypoint.y 247 | - (double) (query_copy.image_height()) / 2.0), query_copy.focal_length(); 248 | 249 | feature.normalize(); 250 | 251 | feature_vectors.col(i) = feature; 252 | Eigen::Matrix world_point; 253 | world_point << point.x, point.y, point.z; 254 | world_points.col(i) = world_point; 255 | } 256 | 257 | p3p.computePoses(feature_vectors, world_points, solutions); 258 | 259 | // Test the 4 proposed solutions 260 | for (int i = 0; i < 4; ++i) { 261 | Eigen::Matrix camera_position = solutions.block(0, 262 | i * 4, 3, 1); 263 | Eigen::Matrix camera_rotation = solutions.block(0, 264 | i * 4 + 1, 3, 3); 265 | 266 | query_copy.set_camera_position(camera_position); 267 | query_copy.set_camera_rotation(camera_rotation); 268 | 269 | // Compute the camera and projection matrix 270 | query_copy.ComputeMatrices(); 271 | 272 | double new_hypoquality = 0; 273 | std::vector fitmatch_vec = TestHypothesis(query_copy, 274 | good_matches, query_copy.sift_keypoints(), (*sifts_), 275 | inlier_eps, new_hypoquality); 276 | 277 | unsigned int new_hyposet = fitmatch_vec.size(); 278 | 279 | if (new_hypoquality > hypoquality) { 280 | // New hypothesis was better than the old one 281 | hypoquality = new_hypoquality; 282 | hyposet = new_hyposet; 283 | std::cout << "New hyposet size: " << hyposet 284 | << ", with quality " << hypoquality << std::endl; 285 | // Transfer solution from working copy to original query 286 | query.set_camera_position(query_copy.camera_position()); 287 | query.set_camera_rotation(query_copy.camera_rotation()); 288 | fitted_matches = fitmatch_vec; 289 | } 290 | } 291 | } 292 | ++steps; 293 | } 294 | 295 | // Compute final solution on the original query 296 | query.ComputeMatrices(); 297 | 298 | // Refine with Bundle adjustment 299 | BundleAdjust(query, fitted_matches, query.sift_keypoints(), (*sifts_)); 300 | 301 | // Reproject the fitted matches and store in the query 302 | std::vector> fitpoints_2d; 303 | std::vector> fitpoints_3d; 304 | Project(query, fitpoints_2d, fitpoints_3d, fitted_matches, 305 | query.sift_keypoints(), (*sifts_)); 306 | query.set_fitpoints_2d(fitpoints_2d); 307 | query.set_fitpoints_3d(fitpoints_3d); 308 | 309 | return true; 310 | } 311 | 312 | } 313 | -------------------------------------------------------------------------------- /tmp/README.txt: -------------------------------------------------------------------------------- 1 | Temporary folder for the program. 2 | --------------------------------------------------------------------------------