vendor: OpenCV 5.0.0 snapshot at 755e50675d97db9b7d449d8bd6b09888646f6c6e
@@ -0,0 +1,179 @@
|
||||
set(OPENCV_MODULE_IS_PART_OF_WORLD FALSE)
|
||||
set(the_description "SFM algorithms")
|
||||
|
||||
|
||||
### LIBMV LIGHT EXTERNAL DEPENDENCIES ###
|
||||
|
||||
find_package(Ceres QUIET)
|
||||
|
||||
if(NOT Gflags_FOUND) # Ceres find gflags on the own, so separate search isn't necessary
|
||||
find_package(Gflags QUIET)
|
||||
endif()
|
||||
if(NOT (Glog_FOUND OR glog_FOUND)) # Ceres find glog on the own, so separate search isn't necessary
|
||||
find_package(Glog QUIET)
|
||||
endif()
|
||||
|
||||
if(NOT Gflags_FOUND OR NOT (Glog_FOUND OR glog_FOUND))
|
||||
# try local search scripts
|
||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake")
|
||||
if(NOT Gflags_FOUND)
|
||||
find_package(Gflags QUIET)
|
||||
endif()
|
||||
if(NOT (Glog_FOUND OR glog_FOUND))
|
||||
find_package(Glog QUIET)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(NOT DEFINED GFLAGS_INCLUDE_DIRS AND DEFINED GFLAGS_INCLUDE_DIR)
|
||||
set(GFLAGS_INCLUDE_DIRS "${GFLAGS_INCLUDE_DIR}")
|
||||
endif()
|
||||
if(NOT GFLAGS_LIBRARIES AND TARGET gflags::gflags)
|
||||
set(GFLAGS_LIBRARIES gflags::gflags)
|
||||
elseif(NOT GFLAGS_LIBRARIES AND TARGET gflags)
|
||||
set(GFLAGS_LIBRARIES gflags)
|
||||
endif()
|
||||
if(NOT DEFINED GLOG_INCLUDE_DIRS AND DEFINED GLOG_INCLUDE_DIR)
|
||||
set(GLOG_INCLUDE_DIRS "${GLOG_INCLUDE_DIR}")
|
||||
endif()
|
||||
if(NOT GLOG_LIBRARIES AND TARGET glog::glog)
|
||||
set(GLOG_LIBRARIES glog::glog)
|
||||
endif()
|
||||
|
||||
if((gflags_FOUND OR Gflags_FOUND OR GFLAGS_FOUND OR GFLAGS_INCLUDE_DIRS) AND (glog_FOUND OR Glog_FOUND OR GLOG_FOUND OR GLOG_INCLUDE_DIRS))
|
||||
set(__cache_key "${GLOG_INCLUDE_DIRS} ~ ${GFLAGS_INCLUDE_DIRS} ~ ${GLOG_LIBRARIES} ~ ${GFLAGS_LIBRARIES}")
|
||||
if(NOT DEFINED SFM_GLOG_GFLAGS_TEST_CACHE_KEY OR NOT (SFM_GLOG_GFLAGS_TEST_CACHE_KEY STREQUAL __cache_key))
|
||||
set(__fname "${CMAKE_CURRENT_LIST_DIR}/cmake/checks/check_glog_gflags.cpp")
|
||||
try_compile(
|
||||
SFM_GLOG_GFLAGS_TEST "${CMAKE_BINARY_DIR}" "${__fname}"
|
||||
CMAKE_FLAGS "-DINCLUDE_DIRECTORIES:STRING=${GLOG_INCLUDE_DIRS};${GFLAGS_INCLUDE_DIRS}"
|
||||
LINK_LIBRARIES ${GLOG_LIBRARIES} ${GFLAGS_LIBRARIES}
|
||||
OUTPUT_VARIABLE __output
|
||||
)
|
||||
if(NOT SFM_GLOG_GFLAGS_TEST)
|
||||
file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log
|
||||
"Failed compilation check: ${__fname}\n"
|
||||
"${__output}\n\n"
|
||||
)
|
||||
endif()
|
||||
set(SFM_GLOG_GFLAGS_TEST "${SFM_GLOG_GFLAGS_TEST}" CACHE INTERNAL "")
|
||||
set(SFM_GLOG_GFLAGS_TEST_CACHE_KEY "${__cache_key}" CACHE INTERNAL "")
|
||||
message(STATUS "Checking SFM glog/gflags deps... ${SFM_GLOG_GFLAGS_TEST}")
|
||||
endif()
|
||||
unset(__cache_key)
|
||||
set(SFM_DEPS_OK "${SFM_GLOG_GFLAGS_TEST}")
|
||||
else()
|
||||
set(SFM_DEPS_OK FALSE)
|
||||
endif()
|
||||
|
||||
if(NOT HAVE_EIGEN OR NOT SFM_DEPS_OK)
|
||||
set(DISABLE_MSG "Module opencv_sfm disabled because the following dependencies are not found:")
|
||||
if(NOT HAVE_EIGEN)
|
||||
set(DISABLE_MSG "${DISABLE_MSG} Eigen")
|
||||
endif()
|
||||
if(NOT SFM_DEPS_OK)
|
||||
set(DISABLE_MSG "${DISABLE_MSG} Glog/Gflags")
|
||||
endif()
|
||||
message(STATUS ${DISABLE_MSG})
|
||||
ocv_module_disable(sfm)
|
||||
endif()
|
||||
|
||||
|
||||
### LIBMV LIGHT DEFINITIONS ###
|
||||
|
||||
set(LIBMV_LIGHT_INCLUDES
|
||||
"${CMAKE_CURRENT_LIST_DIR}/src/libmv_light"
|
||||
"${OpenCV_SOURCE_DIR}/include/opencv"
|
||||
"${GLOG_INCLUDE_DIRS}"
|
||||
"${GFLAGS_INCLUDE_DIRS}"
|
||||
)
|
||||
|
||||
set(LIBMV_LIGHT_LIBS
|
||||
opencv.sfm.correspondence
|
||||
opencv.sfm.multiview
|
||||
opencv.sfm.numeric
|
||||
${GLOG_LIBRARIES}
|
||||
${GFLAGS_LIBRARIES}
|
||||
)
|
||||
|
||||
if(Ceres_FOUND)
|
||||
add_definitions("-DCERES_FOUND=1")
|
||||
list(APPEND LIBMV_LIGHT_LIBS opencv.sfm.simple_pipeline)
|
||||
if(Ceres_VERSION VERSION_LESS 2.0.0)
|
||||
list(APPEND LIBMV_LIGHT_INCLUDES "${CERES_INCLUDE_DIRS}")
|
||||
endif()
|
||||
else()
|
||||
add_definitions("-DCERES_FOUND=0")
|
||||
message(STATUS "CERES support is disabled. Ceres Solver for reconstruction API is required.")
|
||||
endif()
|
||||
|
||||
### CREATE OPENCV SFM MODULE ###
|
||||
|
||||
ocv_add_module(sfm
|
||||
opencv_core
|
||||
opencv_geometry
|
||||
opencv_features
|
||||
opencv_xfeatures2d
|
||||
opencv_imgcodecs
|
||||
WRAP python
|
||||
)
|
||||
|
||||
add_definitions(/DGLOG_NO_ABBREVIATED_SEVERITIES) # avoid ERROR macro conflict in glog (ceres dependency)
|
||||
|
||||
if(WIN32)
|
||||
# Avoid error due to min/max being already defined as a macro
|
||||
add_definitions(-DNOMINMAX)
|
||||
endif(WIN32)
|
||||
|
||||
ocv_warnings_disable(CMAKE_CXX_FLAGS
|
||||
-Wundef
|
||||
-Wshadow
|
||||
-Wsign-compare
|
||||
-Wmissing-declarations
|
||||
-Wunused-but-set-variable
|
||||
-Wunused-parameter
|
||||
-Wunused-function
|
||||
-Wsuggest-override
|
||||
)
|
||||
|
||||
ocv_include_directories( ${LIBMV_LIGHT_INCLUDES} )
|
||||
ocv_module_include_directories()
|
||||
|
||||
# source files
|
||||
FILE(GLOB OPENCV_SFM_SRC src/*.cpp)
|
||||
|
||||
# define the header files (make the headers appear in IDEs.)
|
||||
FILE(GLOB OPENCV_SFM_HDRS include/opencv2/sfm.hpp include/opencv2/sfm/*.hpp)
|
||||
|
||||
ocv_set_module_sources(HEADERS ${OPENCV_SFM_HDRS}
|
||||
SOURCES ${OPENCV_SFM_SRC})
|
||||
|
||||
ocv_create_module()
|
||||
|
||||
|
||||
### BUILD libmv_light ###
|
||||
|
||||
if(NOT CMAKE_VERSION VERSION_LESS 2.8.11) # See ocv_target_include_directories() implementation
|
||||
if(TARGET ${the_module})
|
||||
get_target_property(__include_dirs ${the_module} INCLUDE_DIRECTORIES)
|
||||
include_directories(${__include_dirs})
|
||||
endif()
|
||||
endif()
|
||||
#include_directories(${OCV_TARGET_INCLUDE_DIRS_${the_module}})
|
||||
add_subdirectory("${CMAKE_CURRENT_LIST_DIR}/src/libmv_light" "${CMAKE_CURRENT_BINARY_DIR}/src/libmv")
|
||||
|
||||
ocv_target_link_libraries(${the_module} ${LIBMV_LIGHT_LIBS})
|
||||
|
||||
|
||||
### CREATE OPENCV SFM TESTS ###
|
||||
|
||||
ocv_add_accuracy_tests()
|
||||
if(Ceres_FOUND AND TARGET opencv_test_sfm)
|
||||
ocv_target_link_libraries(opencv_test_sfm ${CERES_LIBRARIES})
|
||||
endif ()
|
||||
|
||||
|
||||
### CREATE OPENCV SFM SAMPLES ###
|
||||
|
||||
if(Ceres_FOUND)
|
||||
ocv_add_samples(opencv_viz)
|
||||
endif ()
|
||||
@@ -0,0 +1,118 @@
|
||||
Structure From Motion module
|
||||
============================
|
||||
|
||||
This module contains algorithms to perform 3d reconstruction from 2d images. The core of the module is a light version of [Libmv](https://developer.blender.org/project/profile/59), which is a Library for Multiview Reconstruction (or LMV) divided into different modules (correspondence/numeric/multiview/simple_pipeline) that allow to resolve part of the SfM process.
|
||||
|
||||
|
||||
Dependencies
|
||||
------------
|
||||
|
||||
Before compiling, take a look at the following details in order to give a proper use of the Structure from Motion module. **Advice:** The module is only available for Linux/GNU systems.
|
||||
|
||||
In addition, it depends on some open source libraries:
|
||||
|
||||
- [Eigen](http://eigen.tuxfamily.org/index.php?title=Main_Page) 3.2.2 or later. **Required**
|
||||
- [Google Log](http://code.google.com/p/google-glog) 0.3.1 or later. **Required**
|
||||
- [Google Flags](http://code.google.com/p/gflags). **Required**
|
||||
- [Ceres Solver](http://ceres-solver.org). Needed by the reconstruction API in order to solve part of the Bundle Adjustment plus the points Intersect. If Ceres Solver is not installed on your system, the reconstruction funcionality will be disabled. **Recommended**
|
||||
|
||||
Installation
|
||||
------------
|
||||
**Required Dependencies**
|
||||
|
||||
In case you are on [Ubuntu](http://www.ubuntu.com/) you can simply install the required dependencies by typing the following command.
|
||||
|
||||
sudo apt-get install libeigen3-dev libgflags-dev libgoogle-glog-dev
|
||||
|
||||
**Ceres Solver**
|
||||
|
||||
Start by installing all the dependencies.
|
||||
|
||||
# CMake
|
||||
sudo apt-get install cmake
|
||||
# google-glog + gflags
|
||||
sudo apt-get install libgoogle-glog-dev
|
||||
# BLAS & LAPACK
|
||||
sudo apt-get install libatlas-base-dev
|
||||
# Eigen3
|
||||
sudo apt-get install libeigen3-dev
|
||||
# SuiteSparse and CXSparse (optional)
|
||||
# - If you want to build Ceres as a *static* library (the default)
|
||||
# you can use the SuiteSparse package in the main Ubuntu package
|
||||
# repository:
|
||||
sudo apt-get install libsuitesparse-dev
|
||||
# - However, if you want to build Ceres as a *shared* library, you must
|
||||
# add the following PPA:
|
||||
sudo add-apt-repository ppa:bzindovic/suitesparse-bugfix-1319687
|
||||
sudo apt-get update
|
||||
sudo apt-get install libsuitesparse-dev
|
||||
|
||||
We are now ready to build, test, and install Ceres.
|
||||
|
||||
git clone https://ceres-solver.googlesource.com/ceres-solver
|
||||
cd ceres-solver
|
||||
mkdir build && cd build
|
||||
cmake ..
|
||||
make -j4
|
||||
make test
|
||||
sudo make install
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
**trajectory_reconstruction.cpp**
|
||||
|
||||
This program shows the camera trajectory reconstruction capabilities in the OpenCV Structure From Motion (SFM) module. It loads a file with the tracked 2d points over all the frames which are embedded into a vector of 2d points array, where each inner array represents a different frame. Every frame is composed by a list of 2d points which e.g. the first point in frame 1 is the same point in frame 2. If there is no point in a frame the assigned value will be (-1,-1).
|
||||
|
||||
To run this example you can type the following command in the opencv binaries directory specifying the file path in your system and the camera intrinsics (in this case the tracks file was obtained using Blender Motion module).
|
||||
|
||||
./example_sfm_trajectory_reconstruction tracks_file.txt 1914 640 360
|
||||
|
||||
Finally, the script reconstructs the given set of tracked points and show the result using the OpenCV 3D visualizer (viz). On the image below, it's shown a screenshot with the result you should obtain running the "desktop_tracks.txt" found inside the samples directory.
|
||||
|
||||
<p align="center">
|
||||
<img src="doc/pics/desktop_trajectory.png" width="400" height="300">
|
||||
</p>
|
||||
|
||||
**scene_reconstruction.cpp**
|
||||
|
||||
This program shows the multiview scene reconstruction capabilities in the OpenCV Structure From Motion (SFM) module. It calls the recontruction API using the overloaded signature for real images. In this case the script loads a file which provides a list with all the image paths that we want to reconstruct. Internally, this script extract and compute the sparse 2d features using DAISY descriptors which are matched using FlannBasedMatcher to finally build the tracks structure.
|
||||
|
||||
To run this example you can type the following command in the opencv binaries directory specifying the file path and the camera intrinsics.
|
||||
|
||||
./example_sfm_scene_reconstruction image_paths_file.txt 350 240 360
|
||||
|
||||
This sample shows the estimated camera trajectory plus the sparse 3D reconstruction using the the OpenCV 3D visualizer (viz).
|
||||
|
||||
On the next pictures, it's shown a screenshot where you can see the used images as input from the "Temple of the Dioskouroi" [1] and the obtained result after running the reconstruction API.
|
||||
|
||||
<p align="center">
|
||||
<img src="doc/pics/temple_input.jpg" width="800" height="200">
|
||||
</p>
|
||||
<p align="center">
|
||||
<img src="doc/pics/temple_reconstruction.jpg" width="400" height="250">
|
||||
</p>
|
||||
|
||||
On the next pictures, it's shown a screenshot where you can see the used images as input from la Sagrada Familia (BCN) [2] which you can find in the samples directory and the obtained result after running the reconstruction API.
|
||||
|
||||
<p align="center">
|
||||
<img src="doc/pics/sagrada_familia_input.jpg" width="700" height="250">
|
||||
</p>
|
||||
<p align="center">
|
||||
<img src="doc/pics/sagrada_familia_reconstruction.jpg" width="400" height="250">
|
||||
</p>
|
||||
|
||||
|
||||
[1] [http://vision.middlebury.edu/mview/data](http://vision.middlebury.edu/mview/data)
|
||||
|
||||
[2] Penate Sanchez, A. and Moreno-Noguer, F. and Andrade Cetto, J. and Fleuret, F. (2014). LETHA: *Learning from High Quality Inputs for 3D Pose Estimation in Low Quality Images*. Proceedings of the International Conference on 3D vision (3DV). [[URL]](http://www.iri.upc.edu/research/webprojects/pau/datasets/sagfam)
|
||||
|
||||
|
||||
Future Work
|
||||
-----------
|
||||
|
||||
* Update signatures documentation.
|
||||
* Add prototype for dense reconstruction once is working (DAISY paper implementation).
|
||||
* Decide which functions are kept since most of them are the same in calib3d.
|
||||
* Finish to implement computeOrientation().
|
||||
* Find a good features matchig algorithm for reconstruction() in case we provide pure images for autocalibration (look into OpenMVG).
|
||||
@@ -0,0 +1,606 @@
|
||||
# Ceres Solver - A fast non-linear least squares minimizer
|
||||
# Copyright 2015 Google Inc. All rights reserved.
|
||||
# http://ceres-solver.org/
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright notice,
|
||||
# this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
# * Neither the name of Google Inc. nor the names of its contributors may be
|
||||
# used to endorse or promote products derived from this software without
|
||||
# specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
# Author: alexs.mac@gmail.com (Alex Stewart)
|
||||
#
|
||||
|
||||
# FindGflags.cmake - Find Google gflags logging library.
|
||||
#
|
||||
# This module will attempt to find gflags, either via an exported CMake
|
||||
# configuration (generated by gflags >= 2.1 which are built with CMake), or
|
||||
# by performing a standard search for all gflags components. The order of
|
||||
# precedence for these two methods of finding gflags is controlled by:
|
||||
# GFLAGS_PREFER_EXPORTED_GFLAGS_CMAKE_CONFIGURATION.
|
||||
#
|
||||
# This module defines the following variables:
|
||||
#
|
||||
# GFLAGS_FOUND: TRUE iff gflags is found.
|
||||
# GFLAGS_INCLUDE_DIRS: Include directories for gflags.
|
||||
# GFLAGS_LIBRARIES: Libraries required to link gflags.
|
||||
# GFLAGS_NAMESPACE: The namespace in which gflags is defined. In versions of
|
||||
# gflags < 2.1, this was google, for versions >= 2.1 it is
|
||||
# by default gflags, although can be configured when building
|
||||
# gflags to be something else (i.e. google for legacy
|
||||
# compatibility).
|
||||
#
|
||||
# The following variables control the behaviour of this module when an exported
|
||||
# gflags CMake configuration is not found.
|
||||
#
|
||||
# GFLAGS_PREFER_EXPORTED_GFLAGS_CMAKE_CONFIGURATION: TRUE/FALSE, iff TRUE then
|
||||
# then prefer using an exported CMake configuration
|
||||
# generated by gflags >= 2.1 over searching for the
|
||||
# gflags components manually. Otherwise (FALSE)
|
||||
# ignore any exported gflags CMake configurations and
|
||||
# always perform a manual search for the components.
|
||||
# Default: TRUE iff user does not define this variable
|
||||
# before we are called, and does NOT specify either
|
||||
# GFLAGS_INCLUDE_DIR_HINTS or GFLAGS_LIBRARY_DIR_HINTS
|
||||
# otherwise FALSE.
|
||||
# GFLAGS_INCLUDE_DIR_HINTS: List of additional directories in which to
|
||||
# search for gflags includes, e.g: /timbuktu/include.
|
||||
# GFLAGS_LIBRARY_DIR_HINTS: List of additional directories in which to
|
||||
# search for gflags libraries, e.g: /timbuktu/lib.
|
||||
#
|
||||
# The following variables are also defined by this module, but in line with
|
||||
# CMake recommended FindPackage() module style should NOT be referenced directly
|
||||
# by callers (use the plural variables detailed above instead). These variables
|
||||
# do however affect the behaviour of the module via FIND_[PATH/LIBRARY]() which
|
||||
# are NOT re-called (i.e. search for library is not repeated) if these variables
|
||||
# are set with valid values _in the CMake cache_. This means that if these
|
||||
# variables are set directly in the cache, either by the user in the CMake GUI,
|
||||
# or by the user passing -DVAR=VALUE directives to CMake when called (which
|
||||
# explicitly defines a cache variable), then they will be used verbatim,
|
||||
# bypassing the HINTS variables and other hard-coded search locations.
|
||||
#
|
||||
# GFLAGS_INCLUDE_DIR: Include directory for gflags, not including the
|
||||
# include directory of any dependencies.
|
||||
# GFLAGS_LIBRARY: gflags library, not including the libraries of any
|
||||
# dependencies.
|
||||
|
||||
# Reset CALLERS_CMAKE_FIND_LIBRARY_PREFIXES to its value when FindGflags was
|
||||
# invoked, necessary for MSVC.
|
||||
macro(GFLAGS_RESET_FIND_LIBRARY_PREFIX)
|
||||
if (MSVC)
|
||||
set(CMAKE_FIND_LIBRARY_PREFIXES "${CALLERS_CMAKE_FIND_LIBRARY_PREFIXES}")
|
||||
endif (MSVC)
|
||||
endmacro(GFLAGS_RESET_FIND_LIBRARY_PREFIX)
|
||||
|
||||
# Called if we failed to find gflags or any of it's required dependencies,
|
||||
# unsets all public (designed to be used externally) variables and reports
|
||||
# error message at priority depending upon [REQUIRED/QUIET/<NONE>] argument.
|
||||
macro(GFLAGS_REPORT_NOT_FOUND REASON_MSG)
|
||||
unset(GFLAGS_FOUND)
|
||||
unset(GFLAGS_INCLUDE_DIRS)
|
||||
unset(GFLAGS_LIBRARIES)
|
||||
# Do not use unset, as we want to keep GFLAGS_NAMESPACE in the cache,
|
||||
# but simply clear its value.
|
||||
set(GFLAGS_NAMESPACE "" CACHE STRING
|
||||
"gflags namespace (google or gflags)" FORCE)
|
||||
|
||||
# Make results of search visible in the CMake GUI if gflags has not
|
||||
# been found so that user does not have to toggle to advanced view.
|
||||
mark_as_advanced(CLEAR GFLAGS_INCLUDE_DIR
|
||||
GFLAGS_LIBRARY
|
||||
GFLAGS_NAMESPACE)
|
||||
|
||||
gflags_reset_find_library_prefix()
|
||||
|
||||
# Note <package>_FIND_[REQUIRED/QUIETLY] variables defined by FindPackage()
|
||||
# use the camelcase library name, not uppercase.
|
||||
if (Gflags_FIND_QUIETLY)
|
||||
message(STATUS "Failed to find gflags - " ${REASON_MSG} ${ARGN})
|
||||
elseif (Gflags_FIND_REQUIRED)
|
||||
message(FATAL_ERROR "Failed to find gflags - " ${REASON_MSG} ${ARGN})
|
||||
else()
|
||||
# Neither QUIETLY nor REQUIRED, use no priority which emits a message
|
||||
# but continues configuration and allows generation.
|
||||
message("-- Failed to find gflags - " ${REASON_MSG} ${ARGN})
|
||||
endif ()
|
||||
return()
|
||||
endmacro(GFLAGS_REPORT_NOT_FOUND)
|
||||
|
||||
# Verify that all variable names passed as arguments are defined (can be empty
|
||||
# but must be defined) or raise a fatal error.
|
||||
macro(GFLAGS_CHECK_VARS_DEFINED)
|
||||
foreach(CHECK_VAR ${ARGN})
|
||||
if (NOT DEFINED ${CHECK_VAR})
|
||||
if(NOT Gflags_FIND_REQUIRED)
|
||||
gflags_report_not_found("Ceres Bug: ${CHECK_VAR} is not defined.")
|
||||
else()
|
||||
message(FATAL_ERROR "Ceres Bug: ${CHECK_VAR} is not defined.")
|
||||
endif()
|
||||
endif()
|
||||
endforeach()
|
||||
endmacro(GFLAGS_CHECK_VARS_DEFINED)
|
||||
|
||||
# Use check_cxx_source_compiles() to compile trivial test programs to determine
|
||||
# the gflags namespace. This works on all OSs except Windows. If using Visual
|
||||
# Studio, it fails because msbuild forces check_cxx_source_compiles() to use
|
||||
# CMAKE_BUILD_TYPE=Debug for the test project, which usually breaks detection
|
||||
# because MSVC requires that the test project use the same build type as gflags,
|
||||
# which would normally be built in Release.
|
||||
#
|
||||
# Defines: GFLAGS_NAMESPACE in the caller's scope with the detected namespace,
|
||||
# which is blank (empty string, will test FALSE is CMake conditionals)
|
||||
# if detection failed.
|
||||
function(GFLAGS_CHECK_GFLAGS_NAMESPACE_USING_TRY_COMPILE)
|
||||
# Verify that all required variables are defined.
|
||||
gflags_check_vars_defined(
|
||||
GFLAGS_INCLUDE_DIR GFLAGS_LIBRARY)
|
||||
# Ensure that GFLAGS_NAMESPACE is always unset on completion unless
|
||||
# we explicitly set if after having the correct namespace.
|
||||
set(GFLAGS_NAMESPACE "" PARENT_SCOPE)
|
||||
|
||||
include(CheckCXXSourceCompiles)
|
||||
# Setup include path & link library for gflags for CHECK_CXX_SOURCE_COMPILES.
|
||||
set(CMAKE_REQUIRED_INCLUDES ${GFLAGS_INCLUDE_DIR})
|
||||
set(CMAKE_REQUIRED_LIBRARIES ${GFLAGS_LIBRARY} ${GFLAGS_LINK_LIBRARIES})
|
||||
# First try the (older) google namespace. Note that the output variable
|
||||
# MUST be unique to the build type as otherwise the test is not repeated as
|
||||
# it is assumed to have already been performed.
|
||||
check_cxx_source_compiles(
|
||||
"#include <gflags/gflags.h>
|
||||
int main(int argc, char * argv[]) {
|
||||
google::ParseCommandLineFlags(&argc, &argv, true);
|
||||
return 0;
|
||||
}"
|
||||
GFLAGS_IN_GOOGLE_NAMESPACE)
|
||||
if (GFLAGS_IN_GOOGLE_NAMESPACE)
|
||||
set(GFLAGS_NAMESPACE google PARENT_SCOPE)
|
||||
return()
|
||||
endif()
|
||||
|
||||
# Try (newer) gflags namespace instead. Note that the output variable
|
||||
# MUST be unique to the build type as otherwise the test is not repeated as
|
||||
# it is assumed to have already been performed.
|
||||
set(CMAKE_REQUIRED_INCLUDES ${GFLAGS_INCLUDE_DIR})
|
||||
set(CMAKE_REQUIRED_LIBRARIES ${GFLAGS_LIBRARY} ${GFLAGS_LINK_LIBRARIES})
|
||||
check_cxx_source_compiles(
|
||||
"#include <gflags/gflags.h>
|
||||
int main(int argc, char * argv[]) {
|
||||
gflags::ParseCommandLineFlags(&argc, &argv, true);
|
||||
return 0;
|
||||
}"
|
||||
GFLAGS_IN_GFLAGS_NAMESPACE)
|
||||
if (GFLAGS_IN_GFLAGS_NAMESPACE)
|
||||
set(GFLAGS_NAMESPACE gflags PARENT_SCOPE)
|
||||
return()
|
||||
endif (GFLAGS_IN_GFLAGS_NAMESPACE)
|
||||
endfunction(GFLAGS_CHECK_GFLAGS_NAMESPACE_USING_TRY_COMPILE)
|
||||
|
||||
# Use regex on the gflags headers to attempt to determine the gflags namespace.
|
||||
# Checks both gflags.h (contained namespace on versions < 2.1.2) and
|
||||
# gflags_declare.h, which contains the namespace on versions >= 2.1.2.
|
||||
# In general, this method should only be used when
|
||||
# GFLAGS_CHECK_GFLAGS_NAMESPACE_USING_TRY_COMPILE() cannot be used, or has
|
||||
# failed.
|
||||
#
|
||||
# Defines: GFLAGS_NAMESPACE in the caller's scope with the detected namespace,
|
||||
# which is blank (empty string, will test FALSE is CMake conditionals)
|
||||
# if detection failed.
|
||||
function(GFLAGS_CHECK_GFLAGS_NAMESPACE_USING_REGEX)
|
||||
# Verify that all required variables are defined.
|
||||
gflags_check_vars_defined(GFLAGS_INCLUDE_DIR)
|
||||
# Ensure that GFLAGS_NAMESPACE is always undefined on completion unless
|
||||
# we explicitly set if after having the correct namespace.
|
||||
set(GFLAGS_NAMESPACE "" PARENT_SCOPE)
|
||||
|
||||
# Scan gflags.h to identify what namespace gflags was built with. On
|
||||
# versions of gflags < 2.1.2, gflags.h was configured with the namespace
|
||||
# directly, on >= 2.1.2, gflags.h uses the GFLAGS_NAMESPACE #define which
|
||||
# is defined in gflags_declare.h, we try each location in turn.
|
||||
set(GFLAGS_HEADER_FILE ${GFLAGS_INCLUDE_DIR}/gflags/gflags.h)
|
||||
if (NOT EXISTS ${GFLAGS_HEADER_FILE})
|
||||
gflags_report_not_found(
|
||||
"Could not find file: ${GFLAGS_HEADER_FILE} "
|
||||
"containing namespace information in gflags install located at: "
|
||||
"${GFLAGS_INCLUDE_DIR}.")
|
||||
endif()
|
||||
file(READ ${GFLAGS_HEADER_FILE} GFLAGS_HEADER_FILE_CONTENTS)
|
||||
|
||||
string(REGEX MATCH "namespace [A-Za-z]+"
|
||||
GFLAGS_NAMESPACE "${GFLAGS_HEADER_FILE_CONTENTS}")
|
||||
string(REGEX REPLACE "namespace ([A-Za-z]+)" "\\1"
|
||||
GFLAGS_NAMESPACE "${GFLAGS_NAMESPACE}")
|
||||
|
||||
if (NOT GFLAGS_NAMESPACE)
|
||||
gflags_report_not_found(
|
||||
"Failed to extract gflags namespace from header file: "
|
||||
"${GFLAGS_HEADER_FILE}.")
|
||||
endif (NOT GFLAGS_NAMESPACE)
|
||||
|
||||
if (GFLAGS_NAMESPACE STREQUAL "google" OR
|
||||
GFLAGS_NAMESPACE STREQUAL "gflags")
|
||||
# Found valid gflags namespace from gflags.h.
|
||||
set(GFLAGS_NAMESPACE "${GFLAGS_NAMESPACE}" PARENT_SCOPE)
|
||||
return()
|
||||
endif()
|
||||
|
||||
# Failed to find gflags namespace from gflags.h, gflags is likely a new
|
||||
# version, check gflags_declare.h, which in newer versions (>= 2.1.2) contains
|
||||
# the GFLAGS_NAMESPACE #define, which is then referenced in gflags.h.
|
||||
set(GFLAGS_DECLARE_FILE ${GFLAGS_INCLUDE_DIR}/gflags/gflags_declare.h)
|
||||
if (NOT EXISTS ${GFLAGS_DECLARE_FILE})
|
||||
gflags_report_not_found(
|
||||
"Could not find file: ${GFLAGS_DECLARE_FILE} "
|
||||
"containing namespace information in gflags install located at: "
|
||||
"${GFLAGS_INCLUDE_DIR}.")
|
||||
endif()
|
||||
file(READ ${GFLAGS_DECLARE_FILE} GFLAGS_DECLARE_FILE_CONTENTS)
|
||||
|
||||
string(REGEX MATCH "#define GFLAGS_NAMESPACE [A-Za-z]+"
|
||||
GFLAGS_NAMESPACE "${GFLAGS_DECLARE_FILE_CONTENTS}")
|
||||
string(REGEX REPLACE "#define GFLAGS_NAMESPACE ([A-Za-z]+)" "\\1"
|
||||
GFLAGS_NAMESPACE "${GFLAGS_NAMESPACE}")
|
||||
|
||||
if (NOT GFLAGS_NAMESPACE)
|
||||
gflags_report_not_found(
|
||||
"Failed to extract gflags namespace from declare file: "
|
||||
"${GFLAGS_DECLARE_FILE}.")
|
||||
endif (NOT GFLAGS_NAMESPACE)
|
||||
|
||||
if (GFLAGS_NAMESPACE STREQUAL "google" OR
|
||||
GFLAGS_NAMESPACE STREQUAL "gflags")
|
||||
# Found valid gflags namespace from gflags.h.
|
||||
set(GFLAGS_NAMESPACE "${GFLAGS_NAMESPACE}" PARENT_SCOPE)
|
||||
return()
|
||||
endif()
|
||||
endfunction(GFLAGS_CHECK_GFLAGS_NAMESPACE_USING_REGEX)
|
||||
|
||||
# -----------------------------------------------------------------
|
||||
# By default, if the user has expressed no preference for using an exported
|
||||
# gflags CMake configuration over performing a search for the installed
|
||||
# components, and has not specified any hints for the search locations, then
|
||||
# prefer a gflags exported configuration if available.
|
||||
if (NOT DEFINED GFLAGS_PREFER_EXPORTED_GFLAGS_CMAKE_CONFIGURATION
|
||||
AND NOT GFLAGS_INCLUDE_DIR_HINTS
|
||||
AND NOT GFLAGS_LIBRARY_DIR_HINTS)
|
||||
message(STATUS "No preference for use of exported gflags CMake configuration "
|
||||
"set, and no hints for include/library directories provided. "
|
||||
"Defaulting to preferring an installed/exported gflags CMake configuration "
|
||||
"if available.")
|
||||
set(GFLAGS_PREFER_EXPORTED_GFLAGS_CMAKE_CONFIGURATION TRUE)
|
||||
endif()
|
||||
|
||||
# Wrap into function because gflags_report_not_found() uses "return" statement
|
||||
function(__find_exported_gflags)
|
||||
# Try to find an exported CMake configuration for gflags, as generated by
|
||||
# gflags versions >= 2.1.
|
||||
#
|
||||
# We search twice, s/t we can invert the ordering of precedence used by
|
||||
# find_package() for exported package build directories, and installed
|
||||
# packages (found via CMAKE_SYSTEM_PREFIX_PATH), listed as items 6) and 7)
|
||||
# respectively in [1].
|
||||
#
|
||||
# By default, exported build directories are (in theory) detected first, and
|
||||
# this is usually the case on Windows. However, on OS X & Linux, the install
|
||||
# path (/usr/local) is typically present in the PATH environment variable
|
||||
# which is checked in item 4) in [1] (i.e. before both of the above, unless
|
||||
# NO_SYSTEM_ENVIRONMENT_PATH is passed). As such on those OSs installed
|
||||
# packages are usually detected in preference to exported package build
|
||||
# directories.
|
||||
#
|
||||
# To ensure a more consistent response across all OSs, and as users usually
|
||||
# want to prefer an installed version of a package over a locally built one
|
||||
# where both exist (esp. as the exported build directory might be removed
|
||||
# after installation), we first search with NO_CMAKE_PACKAGE_REGISTRY which
|
||||
# means any build directories exported by the user are ignored, and thus
|
||||
# installed directories are preferred. If this fails to find the package
|
||||
# we then research again, but without NO_CMAKE_PACKAGE_REGISTRY, so any
|
||||
# exported build directories will now be detected.
|
||||
#
|
||||
# To prevent confusion on Windows, we also pass NO_CMAKE_BUILDS_PATH (which
|
||||
# is item 5) in [1]), to not preferentially use projects that were built
|
||||
# recently with the CMake GUI to ensure that we always prefer an installed
|
||||
# version if available.
|
||||
#
|
||||
# [1] http://www.cmake.org/cmake/help/v2.8.11/cmake.html#command:find_package
|
||||
find_package(gflags QUIET
|
||||
NO_MODULE
|
||||
NO_CMAKE_PACKAGE_REGISTRY
|
||||
NO_CMAKE_BUILDS_PATH)
|
||||
if (gflags_FOUND)
|
||||
message(STATUS "Found installed version of gflags: ${gflags_DIR}")
|
||||
else(gflags_FOUND)
|
||||
# Failed to find an installed version of gflags, repeat search allowing
|
||||
# exported build directories.
|
||||
message(STATUS "Failed to find installed gflags CMake configuration, "
|
||||
"searching for gflags build directories exported with CMake.")
|
||||
# Again pass NO_CMAKE_BUILDS_PATH, as we know that gflags is exported and
|
||||
# do not want to treat projects built with the CMake GUI preferentially.
|
||||
find_package(gflags QUIET
|
||||
NO_MODULE
|
||||
NO_CMAKE_BUILDS_PATH)
|
||||
if (gflags_FOUND)
|
||||
message(STATUS "Found exported gflags build directory: ${gflags_DIR}")
|
||||
endif(gflags_FOUND)
|
||||
endif(gflags_FOUND)
|
||||
|
||||
set(FOUND_INSTALLED_GFLAGS_CMAKE_CONFIGURATION ${gflags_FOUND})
|
||||
|
||||
# gflags v2.1 - 2.1.2 shipped with a bug in their gflags-config.cmake [1]
|
||||
# whereby gflags_LIBRARIES = "gflags", but there was no imported target
|
||||
# called "gflags", they were called: gflags[_nothreads]-[static/shared].
|
||||
# As this causes linker errors when gflags is not installed in a location
|
||||
# on the current library paths, detect if this problem is present and
|
||||
# fix it.
|
||||
#
|
||||
# [1] https://github.com/gflags/gflags/issues/110
|
||||
if (gflags_FOUND)
|
||||
# NOTE: This is not written as additional conditions in the outer
|
||||
# if (gflags_FOUND) as the NOT TARGET "${gflags_LIBRARIES}"
|
||||
# condition causes problems if gflags is not found.
|
||||
if (${gflags_VERSION} VERSION_LESS 2.1.3 AND
|
||||
NOT TARGET "${gflags_LIBRARIES}")
|
||||
message(STATUS "Detected broken gflags install in: ${gflags_DIR}, "
|
||||
"version: ${gflags_VERSION} <= 2.1.2 which defines gflags_LIBRARIES = "
|
||||
"${gflags_LIBRARIES} which is not an imported CMake target, see: "
|
||||
"https://github.com/gflags/gflags/issues/110. Attempting to fix by "
|
||||
"detecting correct gflags target.")
|
||||
# Ordering here expresses preference for detection, specifically we do not
|
||||
# want to use the _nothreads variants if the full library is available.
|
||||
list(APPEND CHECK_GFLAGS_IMPORTED_TARGET_NAMES
|
||||
gflags-shared gflags-static
|
||||
gflags_nothreads-shared gflags_nothreads-static)
|
||||
foreach(CHECK_GFLAGS_TARGET ${CHECK_GFLAGS_IMPORTED_TARGET_NAMES})
|
||||
if (TARGET ${CHECK_GFLAGS_TARGET})
|
||||
message(STATUS "Found valid gflags target: ${CHECK_GFLAGS_TARGET}, "
|
||||
"updating gflags_LIBRARIES.")
|
||||
set(gflags_LIBRARIES ${CHECK_GFLAGS_TARGET})
|
||||
break()
|
||||
endif()
|
||||
endforeach()
|
||||
if (NOT TARGET ${gflags_LIBRARIES})
|
||||
message(STATUS "Failed to fix detected broken gflags install in: "
|
||||
"${gflags_DIR}, version: ${gflags_VERSION} <= 2.1.2, none of the "
|
||||
"imported targets for gflags: ${CHECK_GFLAGS_IMPORTED_TARGET_NAMES} "
|
||||
"are defined. Will continue with a manual search for gflags "
|
||||
"components. We recommend you build/install a version of gflags > "
|
||||
"2.1.2 (or master).")
|
||||
set(FOUND_INSTALLED_GFLAGS_CMAKE_CONFIGURATION FALSE)
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if (FOUND_INSTALLED_GFLAGS_CMAKE_CONFIGURATION)
|
||||
message(STATUS "Detected gflags version: ${gflags_VERSION}")
|
||||
if(NOT DEFINED GFLAGS_FOUND AND DEFINED gflags_FOUND)
|
||||
set(GFLAGS_FOUND ${gflags_FOUND})
|
||||
endif()
|
||||
if(NOT DEFINED GFLAGS_INCLUDE_DIR AND DEFINED gflags_INCLUDE_DIR)
|
||||
set(GFLAGS_INCLUDE_DIR ${gflags_INCLUDE_DIR})
|
||||
endif()
|
||||
if(NOT DEFINED GFLAGS_LIBRARY AND DEFINED gflags_LIBRARIES)
|
||||
set(GFLAGS_LIBRARY ${gflags_LIBRARIES})
|
||||
endif()
|
||||
|
||||
if(NOT DEFINED GFLAGS_INCLUDE_DIR)
|
||||
gflags_report_not_found("GFLAGS_INCLUDE_DIR is missing")
|
||||
endif()
|
||||
|
||||
# gflags does not export the namespace in their CMake configuration, so
|
||||
# use our function to determine what it should be, as it can be either
|
||||
# gflags or google dependent upon version & configuration.
|
||||
#
|
||||
# NOTE: We use the regex method to determine the namespace here, as
|
||||
# check_cxx_source_compiles() will not use imported targets, which
|
||||
# is what gflags will be in this case.
|
||||
gflags_check_gflags_namespace_using_regex()
|
||||
|
||||
if (NOT GFLAGS_NAMESPACE)
|
||||
gflags_report_not_found(
|
||||
"Failed to determine gflags namespace using regex for gflags "
|
||||
"version: ${gflags_VERSION} exported here: ${gflags_DIR} using CMake.")
|
||||
endif (NOT GFLAGS_NAMESPACE)
|
||||
else (FOUND_INSTALLED_GFLAGS_CMAKE_CONFIGURATION)
|
||||
gflags_report_not_found("Failed to find an installed/exported CMake configuration "
|
||||
"for gflags, will perform search for installed gflags components.")
|
||||
endif (FOUND_INSTALLED_GFLAGS_CMAKE_CONFIGURATION)
|
||||
|
||||
set(GFLAGS_FOUND "${GFLAGS_FOUND}" PARENT_SCOPE)
|
||||
set(GFLAGS_INCLUDE_DIR "${GFLAGS_INCLUDE_DIR}" PARENT_SCOPE)
|
||||
set(GFLAGS_LIBRARY "${GFLAGS_LIBRARY}" PARENT_SCOPE)
|
||||
set(GFLAGS_NAMESPACE "${GFLAGS_NAMESPACE}" PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
if (GFLAGS_PREFER_EXPORTED_GFLAGS_CMAKE_CONFIGURATION)
|
||||
__find_exported_gflags()
|
||||
endif(GFLAGS_PREFER_EXPORTED_GFLAGS_CMAKE_CONFIGURATION)
|
||||
|
||||
if (NOT GFLAGS_FOUND)
|
||||
# Either failed to find an exported gflags CMake configuration, or user
|
||||
# told us not to use one. Perform a manual search for all gflags components.
|
||||
|
||||
# Handle possible presence of lib prefix for libraries on MSVC, see
|
||||
# also GFLAGS_RESET_FIND_LIBRARY_PREFIX().
|
||||
if (MSVC)
|
||||
# Preserve the caller's original values for CMAKE_FIND_LIBRARY_PREFIXES
|
||||
# s/t we can set it back before returning.
|
||||
set(CALLERS_CMAKE_FIND_LIBRARY_PREFIXES "${CMAKE_FIND_LIBRARY_PREFIXES}")
|
||||
# The empty string in this list is important, it represents the case when
|
||||
# the libraries have no prefix (shared libraries / DLLs).
|
||||
set(CMAKE_FIND_LIBRARY_PREFIXES "lib" "" "${CMAKE_FIND_LIBRARY_PREFIXES}")
|
||||
endif (MSVC)
|
||||
|
||||
# Search user-installed locations first, so that we prefer user installs
|
||||
# to system installs where both exist.
|
||||
list(APPEND GFLAGS_CHECK_INCLUDE_DIRS
|
||||
/usr/local/include
|
||||
/usr/local/homebrew/include # Mac OS X
|
||||
/opt/local/var/macports/software # Mac OS X.
|
||||
/opt/local/include
|
||||
/usr/include)
|
||||
list(APPEND GFLAGS_CHECK_PATH_SUFFIXES
|
||||
gflags/include # Windows (for C:/Program Files prefix).
|
||||
gflags/Include ) # Windows (for C:/Program Files prefix).
|
||||
|
||||
list(APPEND GFLAGS_CHECK_LIBRARY_DIRS
|
||||
/usr/local/lib
|
||||
/usr/local/homebrew/lib # Mac OS X.
|
||||
/opt/local/lib
|
||||
/usr/lib)
|
||||
list(APPEND GFLAGS_CHECK_LIBRARY_SUFFIXES
|
||||
gflags/lib # Windows (for C:/Program Files prefix).
|
||||
gflags/Lib ) # Windows (for C:/Program Files prefix).
|
||||
|
||||
# Search supplied hint directories first if supplied.
|
||||
find_path(GFLAGS_INCLUDE_DIR
|
||||
NAMES gflags/gflags.h
|
||||
PATHS ${GFLAGS_INCLUDE_DIR_HINTS}
|
||||
${GFLAGS_CHECK_INCLUDE_DIRS}
|
||||
PATH_SUFFIXES ${GFLAGS_CHECK_PATH_SUFFIXES})
|
||||
if (NOT GFLAGS_INCLUDE_DIR OR
|
||||
NOT EXISTS ${GFLAGS_INCLUDE_DIR})
|
||||
gflags_report_not_found(
|
||||
"Could not find gflags include directory, set GFLAGS_INCLUDE_DIR "
|
||||
"to directory containing gflags/gflags.h")
|
||||
endif (NOT GFLAGS_INCLUDE_DIR OR
|
||||
NOT EXISTS ${GFLAGS_INCLUDE_DIR})
|
||||
|
||||
find_library(GFLAGS_LIBRARY NAMES gflags gflags_debug gflags_nothreads gflags_nothreads_debug
|
||||
PATHS ${GFLAGS_LIBRARY_DIR_HINTS}
|
||||
${GFLAGS_CHECK_LIBRARY_DIRS}
|
||||
PATH_SUFFIXES ${GFLAGS_CHECK_LIBRARY_SUFFIXES})
|
||||
if (NOT GFLAGS_LIBRARY OR
|
||||
NOT EXISTS ${GFLAGS_LIBRARY})
|
||||
gflags_report_not_found(
|
||||
"Could not find gflags library, set GFLAGS_LIBRARY "
|
||||
"to full path to libgflags.")
|
||||
endif (NOT GFLAGS_LIBRARY OR
|
||||
NOT EXISTS ${GFLAGS_LIBRARY})
|
||||
|
||||
# gflags typically requires a threading library (which is OS dependent), note
|
||||
# that this defines the CMAKE_THREAD_LIBS_INIT variable. If we are able to
|
||||
# detect threads, we assume that gflags requires it.
|
||||
find_package(Threads QUIET)
|
||||
set(GFLAGS_LINK_LIBRARIES ${CMAKE_THREAD_LIBS_INIT})
|
||||
# On Windows (including MinGW), the Shlwapi library is used by gflags if
|
||||
# available.
|
||||
if (WIN32)
|
||||
include(CheckIncludeFileCXX)
|
||||
check_include_file_cxx("shlwapi.h" HAVE_SHLWAPI)
|
||||
if (HAVE_SHLWAPI)
|
||||
list(APPEND GFLAGS_LINK_LIBRARIES shlwapi.lib)
|
||||
endif(HAVE_SHLWAPI)
|
||||
endif (WIN32)
|
||||
|
||||
# Mark internally as found, then verify. GFLAGS_REPORT_NOT_FOUND() unsets
|
||||
# if called.
|
||||
set(GFLAGS_FOUND TRUE)
|
||||
|
||||
# Identify what namespace gflags was built with.
|
||||
if (GFLAGS_INCLUDE_DIR AND NOT GFLAGS_NAMESPACE)
|
||||
# To handle Windows peculiarities / CMake bugs on MSVC we try two approaches
|
||||
# to detect the gflags namespace:
|
||||
#
|
||||
# 1) Try to use check_cxx_source_compiles() to compile a trivial program
|
||||
# with the two choices for the gflags namespace.
|
||||
#
|
||||
# 2) [In the event 1) fails] Use regex on the gflags headers to try to
|
||||
# determine the gflags namespace. Whilst this is less robust than 1),
|
||||
# it does avoid any interaction with msbuild.
|
||||
gflags_check_gflags_namespace_using_try_compile()
|
||||
|
||||
if (NOT GFLAGS_NAMESPACE)
|
||||
# Failed to determine gflags namespace using check_cxx_source_compiles()
|
||||
# method, try and obtain it using regex on the gflags headers instead.
|
||||
message(STATUS "Failed to find gflags namespace using using "
|
||||
"check_cxx_source_compiles(), trying namespace regex instead, "
|
||||
"this is expected on Windows.")
|
||||
gflags_check_gflags_namespace_using_regex()
|
||||
|
||||
if (NOT GFLAGS_NAMESPACE)
|
||||
gflags_report_not_found(
|
||||
"Failed to determine gflags namespace either by "
|
||||
"check_cxx_source_compiles(), or namespace regex.")
|
||||
endif (NOT GFLAGS_NAMESPACE)
|
||||
endif (NOT GFLAGS_NAMESPACE)
|
||||
endif (GFLAGS_INCLUDE_DIR AND NOT GFLAGS_NAMESPACE)
|
||||
|
||||
# Make the GFLAGS_NAMESPACE a cache variable s/t the user can view it, and could
|
||||
# overwrite it in the CMake GUI.
|
||||
set(GFLAGS_NAMESPACE "${GFLAGS_NAMESPACE}" CACHE STRING
|
||||
"gflags namespace (google or gflags)" FORCE)
|
||||
|
||||
# gflags does not seem to provide any record of the version in its
|
||||
# source tree, thus cannot extract version.
|
||||
|
||||
# Catch case when caller has set GFLAGS_NAMESPACE in the cache / GUI
|
||||
# with an invalid value.
|
||||
if (GFLAGS_NAMESPACE AND
|
||||
NOT GFLAGS_NAMESPACE STREQUAL "google" AND
|
||||
NOT GFLAGS_NAMESPACE STREQUAL "gflags")
|
||||
gflags_report_not_found(
|
||||
"Caller defined GFLAGS_NAMESPACE:"
|
||||
" ${GFLAGS_NAMESPACE} is not valid, not google or gflags.")
|
||||
endif ()
|
||||
# Catch case when caller has set GFLAGS_INCLUDE_DIR in the cache / GUI and
|
||||
# thus FIND_[PATH/LIBRARY] are not called, but specified locations are
|
||||
# invalid, otherwise we would report the library as found.
|
||||
if (GFLAGS_INCLUDE_DIR AND
|
||||
NOT EXISTS ${GFLAGS_INCLUDE_DIR}/gflags/gflags.h)
|
||||
gflags_report_not_found(
|
||||
"Caller defined GFLAGS_INCLUDE_DIR:"
|
||||
" ${GFLAGS_INCLUDE_DIR} does not contain gflags/gflags.h header.")
|
||||
endif (GFLAGS_INCLUDE_DIR AND
|
||||
NOT EXISTS ${GFLAGS_INCLUDE_DIR}/gflags/gflags.h)
|
||||
# TODO: This regex for gflags library is pretty primitive, we use lowercase
|
||||
# for comparison to handle Windows using CamelCase library names, could
|
||||
# this check be better?
|
||||
string(TOLOWER "${GFLAGS_LIBRARY}" LOWERCASE_GFLAGS_LIBRARY)
|
||||
if (GFLAGS_LIBRARY AND
|
||||
NOT "${LOWERCASE_GFLAGS_LIBRARY}" MATCHES ".*gflags[^/]*")
|
||||
gflags_report_not_found(
|
||||
"Caller defined GFLAGS_LIBRARY: "
|
||||
"${GFLAGS_LIBRARY} does not match gflags.")
|
||||
endif (GFLAGS_LIBRARY AND
|
||||
NOT "${LOWERCASE_GFLAGS_LIBRARY}" MATCHES ".*gflags[^/]*")
|
||||
|
||||
gflags_reset_find_library_prefix()
|
||||
|
||||
endif(NOT GFLAGS_FOUND)
|
||||
|
||||
# Set standard CMake FindPackage variables if found.
|
||||
if (GFLAGS_FOUND)
|
||||
set(GFLAGS_INCLUDE_DIRS ${GFLAGS_INCLUDE_DIR})
|
||||
set(GFLAGS_LIBRARIES ${GFLAGS_LIBRARY} ${GFLAGS_LINK_LIBRARIES})
|
||||
endif (GFLAGS_FOUND)
|
||||
|
||||
# Handle REQUIRED / QUIET optional arguments.
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(Gflags DEFAULT_MSG
|
||||
GFLAGS_INCLUDE_DIRS GFLAGS_LIBRARIES GFLAGS_NAMESPACE)
|
||||
|
||||
# Only mark internal variables as advanced if we found gflags, otherwise
|
||||
# leave them visible in the standard GUI for the user to set manually.
|
||||
if (GFLAGS_FOUND)
|
||||
mark_as_advanced(FORCE GFLAGS_INCLUDE_DIR
|
||||
GFLAGS_LIBRARY
|
||||
GFLAGS_NAMESPACE
|
||||
gflags_DIR) # Autogenerated by find_package(gflags)
|
||||
endif (GFLAGS_FOUND)
|
||||
@@ -0,0 +1,210 @@
|
||||
# Ceres Solver - A fast non-linear least squares minimizer
|
||||
# Copyright 2015 Google Inc. All rights reserved.
|
||||
# http://ceres-solver.org/
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright notice,
|
||||
# this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
# * Neither the name of Google Inc. nor the names of its contributors may be
|
||||
# used to endorse or promote products derived from this software without
|
||||
# specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
# Author: alexs.mac@gmail.com (Alex Stewart)
|
||||
#
|
||||
|
||||
# FindGlog.cmake - Find Google glog logging library.
|
||||
#
|
||||
# This module defines the following variables:
|
||||
#
|
||||
# GLOG_FOUND: TRUE iff glog is found.
|
||||
# GLOG_INCLUDE_DIRS: Include directories for glog.
|
||||
# GLOG_LIBRARIES: Libraries required to link glog.
|
||||
#
|
||||
# The following variables control the behaviour of this module:
|
||||
#
|
||||
# GLOG_INCLUDE_DIR_HINTS: List of additional directories in which to
|
||||
# search for glog includes, e.g: /timbuktu/include.
|
||||
# GLOG_LIBRARY_DIR_HINTS: List of additional directories in which to
|
||||
# search for glog libraries, e.g: /timbuktu/lib.
|
||||
#
|
||||
# The following variables are also defined by this module, but in line with
|
||||
# CMake recommended FindPackage() module style should NOT be referenced directly
|
||||
# by callers (use the plural variables detailed above instead). These variables
|
||||
# do however affect the behaviour of the module via FIND_[PATH/LIBRARY]() which
|
||||
# are NOT re-called (i.e. search for library is not repeated) if these variables
|
||||
# are set with valid values _in the CMake cache_. This means that if these
|
||||
# variables are set directly in the cache, either by the user in the CMake GUI,
|
||||
# or by the user passing -DVAR=VALUE directives to CMake when called (which
|
||||
# explicitly defines a cache variable), then they will be used verbatim,
|
||||
# bypassing the HINTS variables and other hard-coded search locations.
|
||||
#
|
||||
# GLOG_INCLUDE_DIR: Include directory for glog, not including the
|
||||
# include directory of any dependencies.
|
||||
# GLOG_LIBRARY: glog library, not including the libraries of any
|
||||
# dependencies.
|
||||
|
||||
# Reset CALLERS_CMAKE_FIND_LIBRARY_PREFIXES to its value when
|
||||
# FindGlog was invoked.
|
||||
macro(GLOG_RESET_FIND_LIBRARY_PREFIX)
|
||||
if (MSVC)
|
||||
set(CMAKE_FIND_LIBRARY_PREFIXES "${CALLERS_CMAKE_FIND_LIBRARY_PREFIXES}")
|
||||
endif (MSVC)
|
||||
endmacro(GLOG_RESET_FIND_LIBRARY_PREFIX)
|
||||
|
||||
# Called if we failed to find glog or any of it's required dependencies,
|
||||
# unsets all public (designed to be used externally) variables and reports
|
||||
# error message at priority depending upon [REQUIRED/QUIET/<NONE>] argument.
|
||||
macro(GLOG_REPORT_NOT_FOUND REASON_MSG)
|
||||
unset(GLOG_FOUND)
|
||||
unset(GLOG_INCLUDE_DIRS)
|
||||
unset(GLOG_LIBRARIES)
|
||||
# Make results of search visible in the CMake GUI if glog has not
|
||||
# been found so that user does not have to toggle to advanced view.
|
||||
mark_as_advanced(CLEAR GLOG_INCLUDE_DIR
|
||||
GLOG_LIBRARY)
|
||||
|
||||
glog_reset_find_library_prefix()
|
||||
|
||||
# Note <package>_FIND_[REQUIRED/QUIETLY] variables defined by FindPackage()
|
||||
# use the camelcase library name, not uppercase.
|
||||
if (Glog_FIND_QUIETLY)
|
||||
message(STATUS "Failed to find glog - " ${REASON_MSG} ${ARGN})
|
||||
elseif (Glog_FIND_REQUIRED)
|
||||
message(FATAL_ERROR "Failed to find glog - " ${REASON_MSG} ${ARGN})
|
||||
else()
|
||||
# Neither QUIETLY nor REQUIRED, use no priority which emits a message
|
||||
# but continues configuration and allows generation.
|
||||
message("-- Failed to find glog - " ${REASON_MSG} ${ARGN})
|
||||
endif ()
|
||||
return()
|
||||
endmacro(GLOG_REPORT_NOT_FOUND)
|
||||
|
||||
# Handle possible presence of lib prefix for libraries on MSVC, see
|
||||
# also GLOG_RESET_FIND_LIBRARY_PREFIX().
|
||||
if (MSVC)
|
||||
# Preserve the caller's original values for CMAKE_FIND_LIBRARY_PREFIXES
|
||||
# s/t we can set it back before returning.
|
||||
set(CALLERS_CMAKE_FIND_LIBRARY_PREFIXES "${CMAKE_FIND_LIBRARY_PREFIXES}")
|
||||
# The empty string in this list is important, it represents the case when
|
||||
# the libraries have no prefix (shared libraries / DLLs).
|
||||
set(CMAKE_FIND_LIBRARY_PREFIXES "lib" "" "${CMAKE_FIND_LIBRARY_PREFIXES}")
|
||||
endif (MSVC)
|
||||
|
||||
# Search user-installed locations first, so that we prefer user installs
|
||||
# to system installs where both exist.
|
||||
list(APPEND GLOG_CHECK_INCLUDE_DIRS
|
||||
/usr/local/include
|
||||
/usr/local/homebrew/include # Mac OS X
|
||||
/opt/local/var/macports/software # Mac OS X.
|
||||
/opt/local/include
|
||||
/usr/include)
|
||||
# Windows (for C:/Program Files prefix).
|
||||
list(APPEND GLOG_CHECK_PATH_SUFFIXES
|
||||
glog/include
|
||||
glog/Include
|
||||
Glog/include
|
||||
Glog/Include)
|
||||
|
||||
list(APPEND GLOG_CHECK_LIBRARY_DIRS
|
||||
/usr/local/lib
|
||||
/usr/local/homebrew/lib # Mac OS X.
|
||||
/opt/local/lib
|
||||
/usr/lib)
|
||||
# Windows (for C:/Program Files prefix).
|
||||
list(APPEND GLOG_CHECK_LIBRARY_SUFFIXES
|
||||
glog/lib
|
||||
glog/Lib
|
||||
Glog/lib
|
||||
Glog/Lib)
|
||||
|
||||
# Search supplied hint directories first if supplied.
|
||||
find_path(GLOG_INCLUDE_DIR
|
||||
NAMES glog/logging.h
|
||||
PATHS ${GLOG_INCLUDE_DIR_HINTS}
|
||||
${GLOG_CHECK_INCLUDE_DIRS}
|
||||
PATH_SUFFIXES ${GLOG_CHECK_PATH_SUFFIXES})
|
||||
if (NOT GLOG_INCLUDE_DIR OR
|
||||
NOT EXISTS ${GLOG_INCLUDE_DIR})
|
||||
glog_report_not_found(
|
||||
"Could not find glog include directory, set GLOG_INCLUDE_DIR "
|
||||
"to directory containing glog/logging.h")
|
||||
endif (NOT GLOG_INCLUDE_DIR OR
|
||||
NOT EXISTS ${GLOG_INCLUDE_DIR})
|
||||
|
||||
find_library(GLOG_LIBRARY NAMES glog glogd
|
||||
PATHS ${GLOG_LIBRARY_DIR_HINTS}
|
||||
${GLOG_CHECK_LIBRARY_DIRS}
|
||||
PATH_SUFFIXES ${GLOG_CHECK_LIBRARY_SUFFIXES})
|
||||
if (NOT GLOG_LIBRARY OR
|
||||
NOT EXISTS ${GLOG_LIBRARY})
|
||||
glog_report_not_found(
|
||||
"Could not find glog library, set GLOG_LIBRARY "
|
||||
"to full path to libglog.")
|
||||
endif (NOT GLOG_LIBRARY OR
|
||||
NOT EXISTS ${GLOG_LIBRARY})
|
||||
|
||||
# Mark internally as found, then verify. GLOG_REPORT_NOT_FOUND() unsets
|
||||
# if called.
|
||||
set(GLOG_FOUND TRUE)
|
||||
|
||||
# Glog does not seem to provide any record of the version in its
|
||||
# source tree, thus cannot extract version.
|
||||
|
||||
# Catch case when caller has set GLOG_INCLUDE_DIR in the cache / GUI and
|
||||
# thus FIND_[PATH/LIBRARY] are not called, but specified locations are
|
||||
# invalid, otherwise we would report the library as found.
|
||||
if (GLOG_INCLUDE_DIR AND
|
||||
NOT EXISTS ${GLOG_INCLUDE_DIR}/glog/logging.h)
|
||||
glog_report_not_found(
|
||||
"Caller defined GLOG_INCLUDE_DIR:"
|
||||
" ${GLOG_INCLUDE_DIR} does not contain glog/logging.h header.")
|
||||
endif (GLOG_INCLUDE_DIR AND
|
||||
NOT EXISTS ${GLOG_INCLUDE_DIR}/glog/logging.h)
|
||||
# TODO: This regex for glog library is pretty primitive, we use lowercase
|
||||
# for comparison to handle Windows using CamelCase library names, could
|
||||
# this check be better?
|
||||
string(TOLOWER "${GLOG_LIBRARY}" LOWERCASE_GLOG_LIBRARY)
|
||||
if (GLOG_LIBRARY AND
|
||||
NOT "${LOWERCASE_GLOG_LIBRARY}" MATCHES ".*glog[^/]*")
|
||||
glog_report_not_found(
|
||||
"Caller defined GLOG_LIBRARY: "
|
||||
"${GLOG_LIBRARY} does not match glog.")
|
||||
endif (GLOG_LIBRARY AND
|
||||
NOT "${LOWERCASE_GLOG_LIBRARY}" MATCHES ".*glog[^/]*")
|
||||
|
||||
# Set standard CMake FindPackage variables if found.
|
||||
if (GLOG_FOUND)
|
||||
set(GLOG_INCLUDE_DIRS ${GLOG_INCLUDE_DIR})
|
||||
set(GLOG_LIBRARIES ${GLOG_LIBRARY})
|
||||
endif (GLOG_FOUND)
|
||||
|
||||
glog_reset_find_library_prefix()
|
||||
|
||||
# Handle REQUIRED / QUIET optional arguments.
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(Glog DEFAULT_MSG
|
||||
GLOG_INCLUDE_DIRS GLOG_LIBRARIES)
|
||||
|
||||
# Only mark internal variables as advanced if we found glog, otherwise
|
||||
# leave them visible in the standard GUI for the user to set manually.
|
||||
if (GLOG_FOUND)
|
||||
mark_as_advanced(FORCE GLOG_INCLUDE_DIR
|
||||
GLOG_LIBRARY)
|
||||
endif (GLOG_FOUND)
|
||||
@@ -0,0 +1,7 @@
|
||||
#include <glog/logging.h>
|
||||
#include <gflags/gflags.h>
|
||||
int main()
|
||||
{
|
||||
(void)(0);
|
||||
return 0;
|
||||
}
|
||||
|
After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 90 KiB |
|
After Width: | Height: | Size: 29 KiB |
|
After Width: | Height: | Size: 28 KiB |
|
After Width: | Height: | Size: 20 KiB |
|
After Width: | Height: | Size: 17 KiB |
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
* Software License Agreement (BSD License)
|
||||
*
|
||||
* Copyright (c) 2009, Willow Garage, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer in the documentation and/or other materials provided
|
||||
* with the distribution.
|
||||
* * Neither the name of Willow Garage, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __OPENCV_SFM_HPP__
|
||||
#define __OPENCV_SFM_HPP__
|
||||
|
||||
#include <opencv2/sfm/conditioning.hpp>
|
||||
#include <opencv2/sfm/fundamental.hpp>
|
||||
#include <opencv2/sfm/io.hpp>
|
||||
#include <opencv2/sfm/numeric.hpp>
|
||||
#include <opencv2/sfm/projection.hpp>
|
||||
#include <opencv2/sfm/triangulation.hpp>
|
||||
#if CERES_FOUND
|
||||
#include <opencv2/sfm/reconstruct.hpp>
|
||||
#include <opencv2/sfm/simple_pipeline.hpp>
|
||||
#endif
|
||||
|
||||
/** @defgroup sfm Structure From Motion
|
||||
|
||||
The opencv_sfm module contains algorithms to perform 3d reconstruction
|
||||
from 2d images.\n
|
||||
The core of the module is based on a light version of
|
||||
[Libmv](https://developer.blender.org/project/profile/59) originally
|
||||
developed by Sameer Agarwal and Keir Mierle.
|
||||
|
||||
__Whats is libmv?__ \n
|
||||
libmv, also known as the Library for Multiview Reconstruction (or LMV),
|
||||
is the computer vision backend for Blender's motion tracking abilities.
|
||||
Unlike other vision libraries with general ambitions, libmv is focused
|
||||
on algorithms for match moving, specifically targeting [Blender](https://developer.blender.org) as the
|
||||
primary customer. Dense reconstruction, reconstruction from unorganized
|
||||
photo collections, image recognition, and other tasks are not a focus
|
||||
of libmv.
|
||||
|
||||
__Development__ \n
|
||||
libmv is officially under the Blender umbrella, and so is developed
|
||||
on developer.blender.org. The [source repository](https://developer.blender.org/diffusion/LMV) can get checked out
|
||||
independently from Blender.
|
||||
|
||||
This module has been originally developed as a project for Google Summer of Code 2012-2015.
|
||||
|
||||
@note
|
||||
- Notice that it is compiled only when Eigen, GLog and GFlags are correctly installed.\n
|
||||
Check installation instructions in the following tutorial: @ref tutorial_sfm_installation
|
||||
|
||||
@{
|
||||
@defgroup conditioning Conditioning
|
||||
@defgroup fundamental Fundamental
|
||||
@defgroup io Input/Output
|
||||
@defgroup numeric Numeric
|
||||
@defgroup projection Projection
|
||||
@defgroup robust Robust Estimation
|
||||
@defgroup triangulation Triangulation
|
||||
|
||||
@defgroup reconstruction Reconstruction
|
||||
|
||||
@note
|
||||
- Notice that it is compiled only when Ceres Solver is correctly installed.\n
|
||||
Check installation instructions in the following tutorial: @ref tutorial_sfm_installation
|
||||
|
||||
@defgroup simple_pipeline Simple Pipeline
|
||||
|
||||
@note
|
||||
- Notice that it is compiled only when Ceres Solver is correctly installed.\n
|
||||
Check installation instructions in the following tutorial: @ref tutorial_sfm_installation
|
||||
@}
|
||||
*/
|
||||
|
||||
#endif
|
||||
|
||||
/* End of file. */
|
||||
@@ -0,0 +1,123 @@
|
||||
/*
|
||||
* Software License Agreement (BSD License)
|
||||
*
|
||||
* Copyright (c) 2009, Willow Garage, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer in the documentation and/or other materials provided
|
||||
* with the distribution.
|
||||
* * Neither the name of Willow Garage, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __OPENCV_CONDITIONING_HPP__
|
||||
#define __OPENCV_CONDITIONING_HPP__
|
||||
|
||||
#include <opencv2/core.hpp>
|
||||
|
||||
namespace cv
|
||||
{
|
||||
namespace sfm
|
||||
{
|
||||
|
||||
//! @addtogroup conditioning
|
||||
//! @{
|
||||
|
||||
/** Point conditioning (non isotropic).
|
||||
@param points Input vector of N-dimensional points.
|
||||
@param T Output 3x3 transformation matrix.
|
||||
|
||||
Computes the transformation matrix such that the two principal moments of the set of points are equal to unity,
|
||||
forming an approximately symmetric circular cloud of points of radius 1 about the origin.\n
|
||||
Reference: @cite HartleyZ00 4.4.4 pag.109
|
||||
*/
|
||||
CV_EXPORTS_W
|
||||
void
|
||||
preconditionerFromPoints( InputArray points,
|
||||
OutputArray T );
|
||||
|
||||
/** @brief Point conditioning (isotropic).
|
||||
@param points Input vector of N-dimensional points.
|
||||
@param T Output 3x3 transformation matrix.
|
||||
|
||||
Computes the transformation matrix such that each coordinate direction will be scaled equally,
|
||||
bringing the centroid to the origin with an average centroid \f$(1,1,1)^T\f$.\n
|
||||
Reference: @cite HartleyZ00 4.4.4 pag.107.
|
||||
*/
|
||||
CV_EXPORTS_W
|
||||
void
|
||||
isotropicPreconditionerFromPoints( InputArray points,
|
||||
OutputArray T );
|
||||
|
||||
/** @brief Apply Transformation to points.
|
||||
@param points Input vector of N-dimensional points.
|
||||
@param T Input 3x3 transformation matrix such that \f$x = T*X\f$, where \f$X\f$ are the points to transform and \f$x\f$ the transformed points.
|
||||
@param transformed_points Output vector of N-dimensional transformed points.
|
||||
*/
|
||||
CV_EXPORTS_W
|
||||
void
|
||||
applyTransformationToPoints( InputArray points,
|
||||
InputArray T,
|
||||
OutputArray transformed_points );
|
||||
|
||||
/** @brief This function normalizes points (non isotropic).
|
||||
@param points Input vector of N-dimensional points.
|
||||
@param normalized_points Output vector of the same N-dimensional points but with mean 0 and average norm \f$\sqrt{2}\f$.
|
||||
@param T Output 3x3 transform matrix such that \f$x = T*X\f$, where \f$X\f$ are the points to normalize and \f$x\f$ the normalized points.
|
||||
|
||||
Internally calls @ref preconditionerFromPoints in order to get the scaling matrix before applying @ref applyTransformationToPoints.
|
||||
This operation is an essential step before applying the DLT algorithm in order to consider the result as optimal.\n
|
||||
Reference: @cite HartleyZ00 4.4.4 pag.109
|
||||
*/
|
||||
CV_EXPORTS_W
|
||||
void
|
||||
normalizePoints( InputArray points,
|
||||
OutputArray normalized_points,
|
||||
OutputArray T );
|
||||
|
||||
/** @brief This function normalizes points. (isotropic).
|
||||
@param points Input vector of N-dimensional points.
|
||||
@param normalized_points Output vector of the same N-dimensional points but with mean 0 and average norm \f$\sqrt{2}\f$.
|
||||
@param T Output 3x3 transform matrix such that \f$x = T*X\f$, where \f$X\f$ are the points to normalize and \f$x\f$ the normalized points.
|
||||
|
||||
Internally calls @ref preconditionerFromPoints in order to get the scaling matrix before applying @ref applyTransformationToPoints.
|
||||
This operation is an essential step before applying the DLT algorithm in order to consider the result as optimal.\n
|
||||
Reference: @cite HartleyZ00 4.4.4 pag.107.
|
||||
*/
|
||||
CV_EXPORTS_W
|
||||
void
|
||||
normalizeIsotropicPoints( InputArray points,
|
||||
OutputArray normalized_points,
|
||||
OutputArray T );
|
||||
|
||||
//! @} sfm
|
||||
|
||||
} /* namespace sfm */
|
||||
} /* namespace cv */
|
||||
|
||||
#endif
|
||||
|
||||
/* End of file. */
|
||||
@@ -0,0 +1,225 @@
|
||||
/*
|
||||
* Software License Agreement (BSD License)
|
||||
*
|
||||
* Copyright (c) 2009, Willow Garage, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer in the documentation and/or other materials provided
|
||||
* with the distribution.
|
||||
* * Neither the name of Willow Garage, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __OPENCV_SFM_FUNDAMENTAL_HPP__
|
||||
#define __OPENCV_SFM_FUNDAMENTAL_HPP__
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include <opencv2/core.hpp>
|
||||
|
||||
namespace cv
|
||||
{
|
||||
namespace sfm
|
||||
{
|
||||
|
||||
//! @addtogroup fundamental
|
||||
//! @{
|
||||
|
||||
/** @brief Get projection matrices from Fundamental matrix
|
||||
@param F Input 3x3 fundamental matrix.
|
||||
@param P1 Output 3x4 one possible projection matrix.
|
||||
@param P2 Output 3x4 another possible projection matrix.
|
||||
*/
|
||||
CV_EXPORTS_W
|
||||
void
|
||||
projectionsFromFundamental( InputArray F,
|
||||
OutputArray P1,
|
||||
OutputArray P2 );
|
||||
|
||||
/** @brief Get Fundamental matrix from Projection matrices.
|
||||
@param P1 Input 3x4 first projection matrix.
|
||||
@param P2 Input 3x4 second projection matrix.
|
||||
@param F Output 3x3 fundamental matrix.
|
||||
*/
|
||||
CV_EXPORTS_W
|
||||
void
|
||||
fundamentalFromProjections( InputArray P1,
|
||||
InputArray P2,
|
||||
OutputArray F );
|
||||
|
||||
/** @brief Estimate the fundamental matrix between two dataset of 2D point (image coords space).
|
||||
@param x1 Input 2xN Array of 2D points in view 1.
|
||||
@param x2 Input 2xN Array of 2D points in view 2.
|
||||
@param F Output 3x3 fundamental matrix.
|
||||
|
||||
Uses the normalized 8-point fundamental matrix solver.
|
||||
Reference: @cite HartleyZ00 11.2 pag.281 (x1 = x, x2 = x')
|
||||
*/
|
||||
CV_EXPORTS_W
|
||||
void
|
||||
normalizedEightPointSolver( InputArray x1,
|
||||
InputArray x2,
|
||||
OutputArray F );
|
||||
|
||||
/** @brief Computes the relative camera motion between two cameras.
|
||||
@param R1 Input 3x3 first camera rotation matrix.
|
||||
@param t1 Input 3x1 first camera translation vector.
|
||||
@param R2 Input 3x3 second camera rotation matrix.
|
||||
@param t2 Input 3x1 second camera translation vector.
|
||||
@param R Output 3x3 relative rotation matrix.
|
||||
@param t Output 3x1 relative translation vector.
|
||||
|
||||
Given the motion parameters of two cameras, computes the motion parameters
|
||||
of the second one assuming the first one to be at the origin.
|
||||
If T1 and T2 are the camera motions, the computed relative motion is \f$T = T_2 T_1^{-1}\f$
|
||||
*/
|
||||
CV_EXPORTS_W
|
||||
void
|
||||
relativeCameraMotion( InputArray R1,
|
||||
InputArray t1,
|
||||
InputArray R2,
|
||||
InputArray t2,
|
||||
OutputArray R,
|
||||
OutputArray t );
|
||||
|
||||
/** Get Motion (R's and t's ) from Essential matrix.
|
||||
@param E Input 3x3 essential matrix.
|
||||
@param Rs Output vector of 3x3 rotation matrices.
|
||||
@param ts Output vector of 3x1 translation vectors.
|
||||
|
||||
Reference: @cite HartleyZ00 9.6 pag 259 (Result 9.19)
|
||||
*/
|
||||
CV_EXPORTS_W
|
||||
void
|
||||
motionFromEssential( InputArray E,
|
||||
OutputArrayOfArrays Rs,
|
||||
OutputArrayOfArrays ts );
|
||||
|
||||
/** Choose one of the four possible motion solutions from an essential matrix.
|
||||
@param Rs Input vector of 3x3 rotation matrices.
|
||||
@param ts Input vector of 3x1 translation vectors.
|
||||
@param K1 Input 3x3 first camera matrix \f$K = \vecthreethree{f_x}{0}{c_x}{0}{f_y}{c_y}{0}{0}{1}\f$.
|
||||
@param x1 Input 2x1 vector with first 2d point.
|
||||
@param K2 Input 3x3 second camera matrix. The parameters are similar to K1.
|
||||
@param x2 Input 2x1 vector with second 2d point.
|
||||
|
||||
Decides the right solution by checking that the triangulation of a match
|
||||
x1--x2 lies in front of the cameras. Return index of the right solution or -1 if no solution.
|
||||
|
||||
Reference: See @cite HartleyZ00 9.6 pag 259 (9.6.3 Geometrical interpretation of the 4 solutions).
|
||||
*/
|
||||
CV_EXPORTS_W
|
||||
int motionFromEssentialChooseSolution( InputArrayOfArrays Rs,
|
||||
InputArrayOfArrays ts,
|
||||
InputArray K1,
|
||||
InputArray x1,
|
||||
InputArray K2,
|
||||
InputArray x2 );
|
||||
|
||||
/** @brief Get Essential matrix from Fundamental and Camera matrices.
|
||||
@param E Input 3x3 essential matrix.
|
||||
@param K1 Input 3x3 first camera matrix \f$K = \vecthreethree{f_x}{0}{c_x}{0}{f_y}{c_y}{0}{0}{1}\f$.
|
||||
@param K2 Input 3x3 second camera matrix. The parameters are similar to K1.
|
||||
@param F Output 3x3 fundamental matrix.
|
||||
|
||||
Reference: @cite HartleyZ00 9.6 pag 257 (formula 9.12) or http://ai.stanford.edu/~birch/projective/node20.html
|
||||
*/
|
||||
CV_EXPORTS_W
|
||||
void
|
||||
fundamentalFromEssential( InputArray E,
|
||||
InputArray K1,
|
||||
InputArray K2,
|
||||
OutputArray F );
|
||||
|
||||
/** @brief Get Essential matrix from Fundamental and Camera matrices.
|
||||
@param F Input 3x3 fundamental matrix.
|
||||
@param K1 Input 3x3 first camera matrix \f$K = \vecthreethree{f_x}{0}{c_x}{0}{f_y}{c_y}{0}{0}{1}\f$.
|
||||
@param K2 Input 3x3 second camera matrix. The parameters are similar to K1.
|
||||
@param E Output 3x3 essential matrix.
|
||||
|
||||
Reference: @cite HartleyZ00 9.6 pag 257 (formula 9.12)
|
||||
*/
|
||||
CV_EXPORTS_W
|
||||
void
|
||||
essentialFromFundamental( InputArray F,
|
||||
InputArray K1,
|
||||
InputArray K2,
|
||||
OutputArray E );
|
||||
|
||||
/** @brief Get Essential matrix from Motion (R's and t's ).
|
||||
@param R1 Input 3x3 first camera rotation matrix.
|
||||
@param t1 Input 3x1 first camera translation vector.
|
||||
@param R2 Input 3x3 second camera rotation matrix.
|
||||
@param t2 Input 3x1 second camera translation vector.
|
||||
@param E Output 3x3 essential matrix.
|
||||
|
||||
Reference: @cite HartleyZ00 9.6 pag 257 (formula 9.12)
|
||||
*/
|
||||
CV_EXPORTS_W
|
||||
void
|
||||
essentialFromRt( InputArray R1,
|
||||
InputArray t1,
|
||||
InputArray R2,
|
||||
InputArray t2,
|
||||
OutputArray E );
|
||||
|
||||
/** @brief Normalizes the Fundamental matrix.
|
||||
@param F Input 3x3 fundamental matrix.
|
||||
@param F_normalized Output 3x3 normalized fundamental matrix.
|
||||
|
||||
By default divides the fundamental matrix by its L2 norm.
|
||||
*/
|
||||
CV_EXPORTS_W
|
||||
void
|
||||
normalizeFundamental( InputArray F,
|
||||
OutputArray F_normalized );
|
||||
|
||||
/** @brief Computes Absolute or Exterior Orientation (Pose Estimation) between 2 sets of 3D point.
|
||||
@param x1 Input first 3xN or 2xN array of points.
|
||||
@param x2 Input second 3xN or 2xN array of points.
|
||||
@param R Output 3x3 computed rotation matrix.
|
||||
@param t Output 3x1 computed translation vector.
|
||||
@param s Output computed scale factor.
|
||||
|
||||
Find the best transformation such that xp=projection*(s*R*x+t) (same as Pose Estimation, ePNP).
|
||||
The routines below are only for the orthographic case for now.
|
||||
*/
|
||||
CV_EXPORTS_W
|
||||
void
|
||||
computeOrientation( InputArrayOfArrays x1,
|
||||
InputArrayOfArrays x2,
|
||||
OutputArray R,
|
||||
OutputArray t,
|
||||
double s );
|
||||
|
||||
//! @} sfm
|
||||
|
||||
} /* namespace sfm */
|
||||
} /* namespace cv */
|
||||
|
||||
#endif
|
||||
|
||||
/* End of file. */
|
||||
@@ -0,0 +1,88 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2015, OpenCV Foundation, all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#ifndef __OPENCV_SFM_IO_HPP__
|
||||
#define __OPENCV_SFM_IO_HPP__
|
||||
|
||||
#include <opencv2/core.hpp>
|
||||
|
||||
namespace cv
|
||||
{
|
||||
namespace sfm
|
||||
{
|
||||
|
||||
//! @addtogroup io
|
||||
//! @{
|
||||
|
||||
/** @brief Different supported file formats.
|
||||
*/
|
||||
enum {
|
||||
SFM_IO_BUNDLER = 0,
|
||||
SFM_IO_VISUALSFM = 1,
|
||||
SFM_IO_OPENSFM = 2,
|
||||
SFM_IO_OPENMVG = 3,
|
||||
SFM_IO_THEIASFM = 4
|
||||
};
|
||||
|
||||
/** @brief Import a reconstruction file.
|
||||
@param file The path to the file.
|
||||
@param Rs Output vector of 3x3 rotations of the camera
|
||||
@param Ts Output vector of 3x1 translations of the camera.
|
||||
@param Ks Output vector of 3x3 instrinsics of the camera.
|
||||
@param points3d Output array with 3d points. Is 3 x N.
|
||||
@param file_format The format of the file to import.
|
||||
|
||||
The function supports reconstructions from Bundler.
|
||||
*/
|
||||
CV_EXPORTS_W
|
||||
void
|
||||
importReconstruction(const cv::String &file, OutputArrayOfArrays Rs,
|
||||
OutputArrayOfArrays Ts, OutputArrayOfArrays Ks,
|
||||
OutputArrayOfArrays points3d, int file_format = SFM_IO_BUNDLER);
|
||||
|
||||
//! @} sfm
|
||||
|
||||
} /* namespace sfm */
|
||||
} /* namespace cv */
|
||||
|
||||
#endif
|
||||
|
||||
/* End of file. */
|
||||
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* Software License Agreement (BSD License)
|
||||
*
|
||||
* Copyright (c) 2009, Willow Garage, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer in the documentation and/or other materials provided
|
||||
* with the distribution.
|
||||
* * Neither the name of Willow Garage, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __OPENCV_SFM_NUMERIC_HPP__
|
||||
#define __OPENCV_SFM_NUMERIC_HPP__
|
||||
|
||||
#include <opencv2/core.hpp>
|
||||
|
||||
namespace cv
|
||||
{
|
||||
namespace sfm
|
||||
{
|
||||
|
||||
//! @addtogroup numeric
|
||||
//! @{
|
||||
|
||||
/** @brief Computes the mean and variance of a given matrix along its rows.
|
||||
@param A Input NxN matrix.
|
||||
@param mean Output Nx1 matrix with computed mean.
|
||||
@param variance Output Nx1 matrix with computed variance.
|
||||
|
||||
It computes in the same way as woud do @ref reduce but with \a Variance function.
|
||||
*/
|
||||
CV_EXPORTS_W
|
||||
void
|
||||
meanAndVarianceAlongRows( InputArray A,
|
||||
OutputArray mean,
|
||||
OutputArray variance );
|
||||
|
||||
/** @brief Returns the 3x3 skew symmetric matrix of a vector.
|
||||
@param x Input 3x1 vector.
|
||||
|
||||
Reference: @cite HartleyZ00, p581, equation (A4.5).
|
||||
*/
|
||||
CV_EXPORTS_W
|
||||
Mat
|
||||
skew( InputArray x );
|
||||
|
||||
///** @brief Returns the skew anti-symmetric matrix of a vector.
|
||||
// @param x Input 3x3 matrix.
|
||||
//*/
|
||||
//CV_EXPORTS
|
||||
//Matx33d
|
||||
//skewMat( const Vec3d &x );
|
||||
//
|
||||
///** @brief Returns the skew anti-symmetric matrix of a vector with only the first two (independent) lines.
|
||||
// @param x Input 3x3 matrix.
|
||||
//*/
|
||||
//CV_EXPORTS
|
||||
//Matx33d
|
||||
//skewMatMinimal( const Vec3d &x );
|
||||
|
||||
//! @} numeric
|
||||
|
||||
} /* namespace sfm */
|
||||
} /* namespace cv */
|
||||
|
||||
#endif
|
||||
|
||||
/* End of file. */
|
||||
@@ -0,0 +1,106 @@
|
||||
/*
|
||||
* Software License Agreement (BSD License)
|
||||
*
|
||||
* Copyright (c) 2009, Willow Garage, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer in the documentation and/or other materials provided
|
||||
* with the distribution.
|
||||
* * Neither the name of Willow Garage, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __OPENCV_PROJECTION_HPP__
|
||||
#define __OPENCV_PROJECTION_HPP__
|
||||
|
||||
#include <opencv2/core.hpp>
|
||||
|
||||
namespace cv
|
||||
{
|
||||
namespace sfm
|
||||
{
|
||||
|
||||
//! @addtogroup projection
|
||||
//! @{
|
||||
|
||||
/** @brief Converts point coordinates from homogeneous to euclidean pixel coordinates. E.g., ((x,y,z)->(x/z, y/z))
|
||||
@param src Input vector of N-dimensional points.
|
||||
@param dst Output vector of N-1-dimensional points.
|
||||
*/
|
||||
CV_EXPORTS_W
|
||||
void
|
||||
homogeneousToEuclidean(InputArray src, OutputArray dst);
|
||||
|
||||
/** @brief Converts points from Euclidean to homogeneous space. E.g., ((x,y)->(x,y,1))
|
||||
@param src Input vector of N-dimensional points.
|
||||
@param dst Output vector of N+1-dimensional points.
|
||||
*/
|
||||
CV_EXPORTS_W
|
||||
void
|
||||
euclideanToHomogeneous(InputArray src, OutputArray dst);
|
||||
|
||||
/** @brief Get projection matrix P from K, R and t.
|
||||
@param K Input 3x3 camera matrix \f$K = \vecthreethree{f_x}{0}{c_x}{0}{f_y}{c_y}{0}{0}{1}\f$.
|
||||
@param R Input 3x3 rotation matrix.
|
||||
@param t Input 3x1 translation vector.
|
||||
@param P Output 3x4 projection matrix.
|
||||
|
||||
This function estimate the projection matrix by solving the following equation: \f$P = K * [R|t]\f$
|
||||
|
||||
*/
|
||||
CV_EXPORTS_W
|
||||
void
|
||||
projectionFromKRt(InputArray K, InputArray R, InputArray t, OutputArray P);
|
||||
|
||||
/** @brief Get K, R and t from projection matrix P, decompose using the RQ decomposition.
|
||||
@param P Input 3x4 projection matrix.
|
||||
@param K Output 3x3 camera matrix \f$K = \vecthreethree{f_x}{0}{c_x}{0}{f_y}{c_y}{0}{0}{1}\f$.
|
||||
@param R Output 3x3 rotation matrix.
|
||||
@param t Output 3x1 translation vector.
|
||||
|
||||
Reference: @cite HartleyZ00 A4.1.1 pag.579
|
||||
*/
|
||||
CV_EXPORTS_W
|
||||
void
|
||||
KRtFromProjection( InputArray P, OutputArray K, OutputArray R, OutputArray t );
|
||||
|
||||
/** @brief Returns the depth of a point transformed by a rigid transform.
|
||||
@param R Input 3x3 rotation matrix.
|
||||
@param t Input 3x1 translation vector.
|
||||
@param X Input 3x1 or 4x1 vector with the 3d point.
|
||||
*/
|
||||
CV_EXPORTS_W
|
||||
double
|
||||
depth( InputArray R, InputArray t, InputArray X);
|
||||
|
||||
//! @} sfm
|
||||
|
||||
} /* namespace sfm */
|
||||
} /* namespace cv */
|
||||
|
||||
#endif
|
||||
|
||||
/* End of file. */
|
||||
@@ -0,0 +1,143 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2015, OpenCV Foundation, all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#ifndef __OPENCV_SFM_RECONSTRUCT_HPP__
|
||||
#define __OPENCV_SFM_RECONSTRUCT_HPP__
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
#include <opencv2/core.hpp>
|
||||
|
||||
namespace cv
|
||||
{
|
||||
namespace sfm
|
||||
{
|
||||
|
||||
//! @addtogroup reconstruction
|
||||
//! @{
|
||||
|
||||
#if defined(CV_DOXYGEN) || defined(CERES_FOUND)
|
||||
|
||||
/** @brief Reconstruct 3d points from 2d correspondences while performing autocalibration.
|
||||
@param points2d Input vector of vectors of 2d points (the inner vector is per image).
|
||||
@param Ps Output vector with the 3x4 projections matrices of each image.
|
||||
@param points3d Output array with estimated 3d points.
|
||||
@param K Input/Output camera matrix \f$K = \vecthreethree{f_x}{0}{c_x}{0}{f_y}{c_y}{0}{0}{1}\f$. Input parameters used as initial guess.
|
||||
@param is_projective if true, the cameras are supposed to be projective.
|
||||
|
||||
This method calls below signature and extracts projection matrices from estimated K, R and t.
|
||||
|
||||
@note
|
||||
- Tracks must be as precise as possible. It does not handle outliers and is very sensible to them.
|
||||
*/
|
||||
CV_EXPORTS
|
||||
void
|
||||
reconstruct(InputArrayOfArrays points2d, OutputArray Ps, OutputArray points3d, InputOutputArray K,
|
||||
bool is_projective = false);
|
||||
|
||||
/** @brief Reconstruct 3d points from 2d correspondences while performing autocalibration.
|
||||
@param points2d Input vector of vectors of 2d points (the inner vector is per image).
|
||||
@param Rs Output vector of 3x3 rotations of the camera.
|
||||
@param Ts Output vector of 3x1 translations of the camera.
|
||||
@param points3d Output array with estimated 3d points.
|
||||
@param K Input/Output camera matrix \f$K = \vecthreethree{f_x}{0}{c_x}{0}{f_y}{c_y}{0}{0}{1}\f$. Input parameters used as initial guess.
|
||||
@param is_projective if true, the cameras are supposed to be projective.
|
||||
|
||||
Internally calls libmv simple pipeline routine with some default parameters by instatiating SFMLibmvEuclideanReconstruction class.
|
||||
|
||||
@note
|
||||
- Tracks must be as precise as possible. It does not handle outliers and is very sensible to them.
|
||||
- To see a working example for camera motion reconstruction, check the following tutorial: @ref tutorial_sfm_trajectory_estimation.
|
||||
*/
|
||||
CV_EXPORTS
|
||||
void
|
||||
reconstruct(InputArrayOfArrays points2d, OutputArray Rs, OutputArray Ts, InputOutputArray K,
|
||||
OutputArray points3d, bool is_projective = false);
|
||||
|
||||
/** @brief Reconstruct 3d points from 2d images while performing autocalibration.
|
||||
@param images a vector of string with the images paths.
|
||||
@param Ps Output vector with the 3x4 projections matrices of each image.
|
||||
@param points3d Output array with estimated 3d points.
|
||||
@param K Input/Output camera matrix \f$K = \vecthreethree{f_x}{0}{c_x}{0}{f_y}{c_y}{0}{0}{1}\f$. Input parameters used as initial guess.
|
||||
@param is_projective if true, the cameras are supposed to be projective.
|
||||
|
||||
This method calls below signature and extracts projection matrices from estimated K, R and t.
|
||||
|
||||
@note
|
||||
- The images must be ordered as they were an image sequence. Additionally, each frame should be as close as posible to the previous and posterior.
|
||||
- For now DAISY features are used in order to compute the 2d points tracks and it only works for 3-4 images.
|
||||
*/
|
||||
CV_EXPORTS
|
||||
void
|
||||
reconstruct(const std::vector<String> images, OutputArray Ps, OutputArray points3d,
|
||||
InputOutputArray K, bool is_projective = false);
|
||||
|
||||
/** @brief Reconstruct 3d points from 2d images while performing autocalibration.
|
||||
@param images a vector of string with the images paths.
|
||||
@param Rs Output vector of 3x3 rotations of the camera.
|
||||
@param Ts Output vector of 3x1 translations of the camera.
|
||||
@param points3d Output array with estimated 3d points.
|
||||
@param K Input/Output camera matrix \f$K = \vecthreethree{f_x}{0}{c_x}{0}{f_y}{c_y}{0}{0}{1}\f$. Input parameters used as initial guess.
|
||||
@param is_projective if true, the cameras are supposed to be projective.
|
||||
|
||||
Internally calls libmv simple pipeline routine with some default parameters by instatiating SFMLibmvEuclideanReconstruction class.
|
||||
|
||||
@note
|
||||
- The images must be ordered as they were an image sequence. Additionally, each frame should be as close as posible to the previous and posterior.
|
||||
- For now DAISY features are used in order to compute the 2d points tracks and it only works for 3-4 images.
|
||||
- To see a working example for scene reconstruction, check the following tutorial: @ref tutorial_sfm_scene_reconstruction.
|
||||
*/
|
||||
CV_EXPORTS
|
||||
void
|
||||
reconstruct(const std::vector<String> images, OutputArray Rs, OutputArray Ts,
|
||||
InputOutputArray K, OutputArray points3d, bool is_projective = false);
|
||||
|
||||
#endif /* CV_DOXYGEN || CERES_FOUND */
|
||||
|
||||
//! @} sfm
|
||||
|
||||
} /* namespace cv */
|
||||
} /* namespace sfm */
|
||||
|
||||
#endif
|
||||
|
||||
/* End of file. */
|
||||
@@ -0,0 +1,106 @@
|
||||
/*
|
||||
* Software License Agreement (BSD License)
|
||||
*
|
||||
* Copyright (c) 2009, Willow Garage, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer in the documentation and/or other materials provided
|
||||
* with the distribution.
|
||||
* * Neither the name of Willow Garage, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __OPENCV_SFM_ROBUST_HPP__
|
||||
#define __OPENCV_SFM_ROBUST_HPP__
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
#include <opencv2/core.hpp>
|
||||
|
||||
namespace cv
|
||||
{
|
||||
namespace sfm
|
||||
{
|
||||
|
||||
//! @addtogroup robust
|
||||
//! @{
|
||||
|
||||
/** @brief Estimate robustly the fundamental matrix between two dataset of 2D point (image coords space).
|
||||
@param x1 Input 2xN Array of 2D points in view 1.
|
||||
@param x2 Input 2xN Array of 2D points in view 2.
|
||||
@param max_error maximum error (in pixels).
|
||||
@param F Output 3x3 fundamental matrix such that \f$x_2^T F x_1=0\f$.
|
||||
@param inliers Output 1xN vector that contains the indexes of the detected inliers.
|
||||
@param outliers_probability outliers probability (in ]0,1[).
|
||||
The number of iterations is controlled using the following equation:
|
||||
\f$k = \frac{log(1-p)}{log(1.0 - w^n )}\f$ where \f$k\f$, \f$w\f$ and \f$n\f$ are the number of
|
||||
iterations, the inliers ratio and minimun number of selected independent samples.
|
||||
The more this value is high, the less the function selects ramdom samples.
|
||||
|
||||
The fundamental solver relies on the 8 point solution. Returns the best error (in pixels), associated to the solution F.
|
||||
*/
|
||||
CV_EXPORTS_W
|
||||
double
|
||||
fundamentalFromCorrespondences8PointRobust( InputArray x1,
|
||||
InputArray x2,
|
||||
double max_error,
|
||||
OutputArray F,
|
||||
OutputArray inliers,
|
||||
double outliers_probability = 1e-2 );
|
||||
|
||||
/** @brief Estimate robustly the fundamental matrix between two dataset of 2D point (image coords space).
|
||||
@param x1 Input 2xN Array of 2D points in view 1.
|
||||
@param x2 Input 2xN Array of 2D points in view 2.
|
||||
@param max_error maximum error (in pixels).
|
||||
@param F Output 3x3 fundamental matrix such that \f$x_2^T F x_1=0\f$.
|
||||
@param inliers Output 1xN vector that contains the indexes of the detected inliers.
|
||||
@param outliers_probability outliers probability (in ]0,1[).
|
||||
The number of iterations is controlled using the following equation:
|
||||
\f$k = \frac{log(1-p)}{log(1.0 - w^n )}\f$ where \f$k\f$, \f$w\f$ and \f$n\f$ are the number of
|
||||
iterations, the inliers ratio and minimun number of selected independent samples.
|
||||
The more this value is high, the less the function selects ramdom samples.
|
||||
|
||||
The fundamental solver relies on the 7 point solution. Returns the best error (in pixels), associated to the solution F.
|
||||
*/
|
||||
CV_EXPORTS_W
|
||||
double
|
||||
fundamentalFromCorrespondences7PointRobust( InputArray x1,
|
||||
InputArray x2,
|
||||
double max_error,
|
||||
OutputArray F,
|
||||
OutputArray inliers,
|
||||
double outliers_probability = 1e-2 );
|
||||
|
||||
//! @} sfm
|
||||
|
||||
} /* namespace cv */
|
||||
} /* namespace sfm */
|
||||
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif
|
||||
|
||||
/* End of file. */
|
||||
@@ -0,0 +1,294 @@
|
||||
/*
|
||||
* Software License Agreement (BSD License)
|
||||
*
|
||||
* Copyright (c) 2009, Willow Garage, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer in the documentation and/or other materials provided
|
||||
* with the distribution.
|
||||
* * Neither the name of Willow Garage, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __OPENCV_SFM_SIMPLE_PIPELINE_HPP__
|
||||
#define __OPENCV_SFM_SIMPLE_PIPELINE_HPP__
|
||||
|
||||
#include <opencv2/core.hpp>
|
||||
|
||||
namespace cv
|
||||
{
|
||||
namespace sfm
|
||||
{
|
||||
|
||||
//! @addtogroup simple_pipeline
|
||||
//! @{
|
||||
|
||||
/** @brief Different camera models that libmv supports.
|
||||
*/
|
||||
enum {
|
||||
SFM_DISTORTION_MODEL_POLYNOMIAL = 0, // LIBMV_DISTORTION_MODEL_POLYNOMIAL
|
||||
SFM_DISTORTION_MODEL_DIVISION = 1, // LIBMV_DISTORTION_MODEL_DIVISION
|
||||
};
|
||||
|
||||
/** @brief Data structure describing the camera model and its parameters.
|
||||
@param _distortion_model Type of camera model.
|
||||
@param _focal_length_x focal length of the camera (in pixels).
|
||||
@param _focal_length_y focal length of the camera (in pixels).
|
||||
@param _principal_point_x principal point of the camera in the x direction (in pixels).
|
||||
@param _principal_point_y principal point of the camera in the y direction (in pixels).
|
||||
@param _polynomial_k1 radial distortion parameter.
|
||||
@param _polynomial_k2 radial distortion parameter.
|
||||
@param _polynomial_k3 radial distortion parameter.
|
||||
@param _polynomial_p1 radial distortion parameter.
|
||||
@param _polynomial_p2 radial distortion parameter.
|
||||
|
||||
Is assumed that modern cameras have their principal point in the image center.\n
|
||||
In case that the camera model was SFM_DISTORTION_MODEL_DIVISION, it's only needed to provide
|
||||
_polynomial_k1 and _polynomial_k2 which will be assigned as division distortion parameters.
|
||||
*/
|
||||
class CV_EXPORTS_W_SIMPLE libmv_CameraIntrinsicsOptions
|
||||
{
|
||||
public:
|
||||
CV_WRAP
|
||||
libmv_CameraIntrinsicsOptions(const int _distortion_model=0,
|
||||
const double _focal_length_x=0,
|
||||
const double _focal_length_y=0,
|
||||
const double _principal_point_x=0,
|
||||
const double _principal_point_y=0,
|
||||
const double _polynomial_k1=0,
|
||||
const double _polynomial_k2=0,
|
||||
const double _polynomial_k3=0,
|
||||
const double _polynomial_p1=0,
|
||||
const double _polynomial_p2=0)
|
||||
: distortion_model(_distortion_model),
|
||||
image_width(2*_principal_point_x),
|
||||
image_height(2*_principal_point_y),
|
||||
focal_length_x(_focal_length_x),
|
||||
focal_length_y(_focal_length_y),
|
||||
principal_point_x(_principal_point_x),
|
||||
principal_point_y(_principal_point_y),
|
||||
polynomial_k1(_polynomial_k1),
|
||||
polynomial_k2(_polynomial_k2),
|
||||
polynomial_k3(_polynomial_k3),
|
||||
division_k1(_polynomial_p1),
|
||||
division_k2(_polynomial_p2)
|
||||
{
|
||||
if ( _distortion_model == SFM_DISTORTION_MODEL_DIVISION )
|
||||
{
|
||||
division_k1 = _polynomial_k1;
|
||||
division_k2 = _polynomial_k2;
|
||||
}
|
||||
}
|
||||
|
||||
// Common settings of all distortion models.
|
||||
CV_PROP_RW int distortion_model;
|
||||
CV_PROP_RW int image_width, image_height;
|
||||
CV_PROP_RW double focal_length_x;
|
||||
CV_PROP_RW double focal_length_y;
|
||||
CV_PROP_RW double principal_point_x, principal_point_y;
|
||||
|
||||
// Radial distortion model.
|
||||
CV_PROP_RW double polynomial_k1, polynomial_k2, polynomial_k3;
|
||||
CV_PROP_RW double polynomial_p1, polynomial_p2;
|
||||
|
||||
// Division distortion model.
|
||||
CV_PROP_RW double division_k1, division_k2;
|
||||
};
|
||||
|
||||
|
||||
/** @brief All internal camera parameters that libmv is able to refine.
|
||||
*/
|
||||
enum { SFM_REFINE_FOCAL_LENGTH = (1 << 0), // libmv::BUNDLE_FOCAL_LENGTH
|
||||
SFM_REFINE_PRINCIPAL_POINT = (1 << 1), // libmv::BUNDLE_PRINCIPAL_POINT
|
||||
SFM_REFINE_RADIAL_DISTORTION_K1 = (1 << 2), // libmv::BUNDLE_RADIAL_K1
|
||||
SFM_REFINE_RADIAL_DISTORTION_K2 = (1 << 4), // libmv::BUNDLE_RADIAL_K2
|
||||
};
|
||||
|
||||
|
||||
/** @brief Data structure describing the reconstruction options.
|
||||
@param _keyframe1 first keyframe used in order to initialize the reconstruction.
|
||||
@param _keyframe2 second keyframe used in order to initialize the reconstruction.
|
||||
@param _refine_intrinsics camera parameter or combination of parameters to refine.
|
||||
@param _select_keyframes allows to select automatically the initial keyframes. If 1 then autoselection is enabled. If 0 then is disabled.
|
||||
@param _verbosity_level verbosity logs level for Glog. If -1 then logs are disabled, otherwise the log level will be the input integer.
|
||||
*/
|
||||
class CV_EXPORTS_W_SIMPLE libmv_ReconstructionOptions
|
||||
{
|
||||
public:
|
||||
CV_WRAP
|
||||
libmv_ReconstructionOptions(const int _keyframe1=1,
|
||||
const int _keyframe2=2,
|
||||
const int _refine_intrinsics=1,
|
||||
const int _select_keyframes=1,
|
||||
const int _verbosity_level=-1)
|
||||
: keyframe1(_keyframe1), keyframe2(_keyframe2),
|
||||
refine_intrinsics(_refine_intrinsics),
|
||||
select_keyframes(_select_keyframes),
|
||||
verbosity_level(_verbosity_level) {}
|
||||
|
||||
CV_PROP_RW int keyframe1, keyframe2;
|
||||
CV_PROP_RW int refine_intrinsics;
|
||||
CV_PROP_RW int select_keyframes;
|
||||
CV_PROP_RW int verbosity_level;
|
||||
};
|
||||
|
||||
|
||||
/** @brief base class BaseSFM declares a common API that would be used in a typical scene reconstruction scenario
|
||||
*/
|
||||
class CV_EXPORTS_W BaseSFM
|
||||
{
|
||||
public:
|
||||
virtual ~BaseSFM() {};
|
||||
|
||||
CV_WRAP
|
||||
virtual void run(InputArrayOfArrays points2d) = 0;
|
||||
|
||||
CV_WRAP
|
||||
virtual void run(InputArrayOfArrays points2d, InputOutputArray K, OutputArray Rs,
|
||||
OutputArray Ts, OutputArray points3d) = 0;
|
||||
|
||||
virtual void run(const std::vector<String> &images) = 0;
|
||||
virtual void run(const std::vector<String> &images, InputOutputArray K, OutputArray Rs,
|
||||
OutputArray Ts, OutputArray points3d) = 0;
|
||||
|
||||
CV_WRAP virtual double getError() const = 0;
|
||||
CV_WRAP virtual void getPoints(OutputArray points3d) = 0;
|
||||
CV_WRAP virtual cv::Mat getIntrinsics() const = 0;
|
||||
CV_WRAP virtual void getCameras(OutputArray Rs, OutputArray Ts) = 0;
|
||||
|
||||
CV_WRAP
|
||||
virtual void
|
||||
setReconstructionOptions(const libmv_ReconstructionOptions &libmv_reconstruction_options) = 0;
|
||||
|
||||
CV_WRAP
|
||||
virtual void
|
||||
setCameraIntrinsicOptions(const libmv_CameraIntrinsicsOptions &libmv_camera_intrinsics_options) = 0;
|
||||
};
|
||||
|
||||
/** @brief SFMLibmvEuclideanReconstruction class provides an interface with the Libmv Structure From Motion pipeline.
|
||||
*/
|
||||
class CV_EXPORTS_W SFMLibmvEuclideanReconstruction : public BaseSFM
|
||||
{
|
||||
public:
|
||||
/** @brief Calls the pipeline in order to perform Eclidean reconstruction.
|
||||
@param points2d Input vector of vectors of 2d points (the inner vector is per image).
|
||||
|
||||
@note
|
||||
- Tracks must be as precise as possible. It does not handle outliers and is very sensible to them.
|
||||
*/
|
||||
CV_WRAP
|
||||
virtual void run(InputArrayOfArrays points2d) CV_OVERRIDE = 0;
|
||||
|
||||
/** @brief Calls the pipeline in order to perform Eclidean reconstruction.
|
||||
@param points2d Input vector of vectors of 2d points (the inner vector is per image).
|
||||
@param K Input/Output camera matrix \f$K = \vecthreethree{f_x}{0}{c_x}{0}{f_y}{c_y}{0}{0}{1}\f$. Input parameters used as initial guess.
|
||||
@param Rs Output vector of 3x3 rotations of the camera.
|
||||
@param Ts Output vector of 3x1 translations of the camera.
|
||||
@param points3d Output array with estimated 3d points.
|
||||
|
||||
@note
|
||||
- Tracks must be as precise as possible. It does not handle outliers and is very sensible to them.
|
||||
*/
|
||||
CV_WRAP
|
||||
virtual void run(InputArrayOfArrays points2d, InputOutputArray K, OutputArray Rs,
|
||||
OutputArray Ts, OutputArray points3d) CV_OVERRIDE = 0;
|
||||
|
||||
/** @brief Calls the pipeline in order to perform Eclidean reconstruction.
|
||||
@param images a vector of string with the images paths.
|
||||
|
||||
@note
|
||||
- The images must be ordered as they were an image sequence. Additionally, each frame should be as close as posible to the previous and posterior.
|
||||
- For now DAISY features are used in order to compute the 2d points tracks and it only works for 3-4 images.
|
||||
*/
|
||||
virtual void run(const std::vector<String> &images) CV_OVERRIDE = 0;
|
||||
|
||||
/** @brief Calls the pipeline in order to perform Eclidean reconstruction.
|
||||
@param images a vector of string with the images paths.
|
||||
@param K Input/Output camera matrix \f$K = \vecthreethree{f_x}{0}{c_x}{0}{f_y}{c_y}{0}{0}{1}\f$. Input parameters used as initial guess.
|
||||
@param Rs Output vector of 3x3 rotations of the camera.
|
||||
@param Ts Output vector of 3x1 translations of the camera.
|
||||
@param points3d Output array with estimated 3d points.
|
||||
|
||||
@note
|
||||
- The images must be ordered as they were an image sequence. Additionally, each frame should be as close as posible to the previous and posterior.
|
||||
- For now DAISY features are used in order to compute the 2d points tracks and it only works for 3-4 images.
|
||||
*/
|
||||
virtual void run(const std::vector<String> &images, InputOutputArray K, OutputArray Rs,
|
||||
OutputArray Ts, OutputArray points3d) CV_OVERRIDE = 0;
|
||||
|
||||
/** @brief Returns the computed reprojection error.
|
||||
*/
|
||||
CV_WRAP
|
||||
virtual double getError() const CV_OVERRIDE = 0;
|
||||
|
||||
/** @brief Returns the estimated 3d points.
|
||||
@param points3d Output array with estimated 3d points.
|
||||
*/
|
||||
CV_WRAP
|
||||
virtual void getPoints(OutputArray points3d) CV_OVERRIDE = 0;
|
||||
|
||||
/** @brief Returns the refined camera calibration matrix.
|
||||
*/
|
||||
CV_WRAP
|
||||
virtual cv::Mat getIntrinsics() const CV_OVERRIDE = 0;
|
||||
|
||||
/** @brief Returns the estimated camera extrinsic parameters.
|
||||
@param Rs Output vector of 3x3 rotations of the camera.
|
||||
@param Ts Output vector of 3x1 translations of the camera.
|
||||
*/
|
||||
CV_WRAP
|
||||
virtual void getCameras(OutputArray Rs, OutputArray Ts) CV_OVERRIDE = 0;
|
||||
|
||||
/** @brief Setter method for reconstruction options.
|
||||
@param libmv_reconstruction_options struct with reconstruction options such as initial keyframes,
|
||||
automatic keyframe selection, parameters to refine and the verbosity level.
|
||||
*/
|
||||
CV_WRAP
|
||||
virtual void
|
||||
setReconstructionOptions(const libmv_ReconstructionOptions &libmv_reconstruction_options) CV_OVERRIDE = 0;
|
||||
|
||||
/** @brief Setter method for camera intrinsic options.
|
||||
@param libmv_camera_intrinsics_options struct with camera intrinsic options such as camera model and
|
||||
the internal camera parameters.
|
||||
*/
|
||||
CV_WRAP
|
||||
virtual void
|
||||
setCameraIntrinsicOptions(const libmv_CameraIntrinsicsOptions &libmv_camera_intrinsics_options) CV_OVERRIDE = 0;
|
||||
|
||||
/** @brief Creates an instance of the SFMLibmvEuclideanReconstruction class. Initializes Libmv. */
|
||||
static Ptr<SFMLibmvEuclideanReconstruction>
|
||||
create(const libmv_CameraIntrinsicsOptions &camera_instrinsic_options=libmv_CameraIntrinsicsOptions(),
|
||||
const libmv_ReconstructionOptions &reconstruction_options=libmv_ReconstructionOptions());
|
||||
};
|
||||
|
||||
//! @} sfm
|
||||
|
||||
} /* namespace cv */
|
||||
} /* namespace sfm */
|
||||
|
||||
#endif
|
||||
|
||||
/* End of file. */
|
||||
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Software License Agreement (BSD License)
|
||||
*
|
||||
* Copyright (c) 2009, Willow Garage, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer in the documentation and/or other materials provided
|
||||
* with the distribution.
|
||||
* * Neither the name of Willow Garage, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __OPENCV_SFM_TRIANGULATION_HPP__
|
||||
#define __OPENCV_SFM_TRIANGULATION_HPP__
|
||||
|
||||
#include <opencv2/core.hpp>
|
||||
|
||||
namespace cv
|
||||
{
|
||||
namespace sfm
|
||||
{
|
||||
|
||||
//! @addtogroup triangulation
|
||||
//! @{
|
||||
|
||||
/** @brief Reconstructs bunch of points by triangulation.
|
||||
@param points2d Input vector of vectors of 2d points (the inner vector is per image). Has to be 2 X N.
|
||||
@param projection_matrices Input vector with 3x4 projections matrices of each image.
|
||||
@param points3d Output array with computed 3d points. Is 3 x N.
|
||||
|
||||
Triangulates the 3d position of 2d correspondences between several images.
|
||||
Reference: Internally it uses DLT method @cite HartleyZ00 12.2 pag.312
|
||||
*/
|
||||
CV_EXPORTS_W
|
||||
void
|
||||
triangulatePoints(InputArrayOfArrays points2d, InputArrayOfArrays projection_matrices,
|
||||
OutputArray points3d);
|
||||
|
||||
//! @} sfm
|
||||
|
||||
} /* namespace sfm */
|
||||
} /* namespace cv */
|
||||
|
||||
#endif
|
||||
|
||||
/* End of file. */
|
||||
@@ -0,0 +1,63 @@
|
||||
642.00 415.00 643.03 417.76 644.27 419.38 646.46 418.84 646.97 421.63 646.11 422.53 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00
|
||||
683.00 134.00 683.39 135.78 684.46 136.37 685.65 135.53 683.91 138.36 680.94 138.20 677.61 139.01 675.47 139.49 674.54 137.65 673.67 136.83 671.58 137.38 670.32 138.06 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00
|
||||
370.00 173.00 370.44 174.72 371.19 175.38 372.25 175.17 370.86 178.49 368.39 179.64 365.41 181.18 363.57 181.86 362.55 180.14 361.51 179.14 359.57 179.75 358.40 180.38 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00
|
||||
550.00 137.00 550.17 138.71 551.03 139.34 551.93 138.87 550.34 141.86 547.60 142.26 544.40 143.37 542.42 143.88 541.47 142.14 540.42 141.14 538.41 141.82 537.19 142.47 536.69 144.31 536.54 146.24 536.71 146.61 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00
|
||||
315.00 423.00 315.49 425.51 316.26 426.61 318.21 426.09 318.20 429.37 317.00 431.42 315.32 433.13 313.47 434.74 312.58 433.40 312.17 432.01 310.59 432.52 309.39 433.36 308.95 434.93 308.86 437.33 308.77 437.69 309.92 439.31 311.20 442.22 311.59 444.07 313.20 445.47 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00
|
||||
447.00 425.00 447.67 427.64 448.62 428.92 450.68 428.26 450.89 431.40 449.94 433.07 448.49 434.17 446.76 435.69 445.93 434.32 445.48 432.97 444.07 433.41 442.98 434.20 442.58 435.90 442.68 438.31 442.63 438.81 443.95 440.75 445.69 443.45 446.68 444.43 448.85 444.32 450.85 444.57 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00
|
||||
770.00 422.00 771.40 424.94 772.93 426.73 775.46 426.02 776.31 428.68 775.32 429.02 773.45 428.70 771.51 429.69 770.39 428.29 769.88 427.05 768.20 427.11 767.00 427.60 767.16 429.64 767.82 432.38 767.91 433.04 770.07 435.52 772.57 438.82 773.56 440.83 776.14 443.53 778.26 445.12 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00
|
||||
161.00 421.00 161.34 423.40 162.20 424.21 164.30 423.79 164.09 427.29 162.82 429.88 160.79 432.33 158.75 434.05 157.96 432.72 157.56 431.39 155.93 431.93 154.56 432.87 154.02 434.35 153.82 436.57 153.69 436.81 154.94 438.08 156.16 440.98 156.35 442.78 158.37 443.32 140.51 442.90 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00
|
||||
624.00 25.00 624.10 26.45 624.89 26.56 625.11 26.18 622.65 29.17 618.99 29.10 615.16 30.29 613.20 30.52 612.09 28.44 610.88 27.61 608.61 28.39 607.30 28.99 606.75 31.20 606.41 32.75 606.46 33.20 608.00 36.00 608.11 38.07 608.11 39.91 609.62 41.88 609.53 44.08 609.00 47.00 610.61 48.98 609.12 49.93 606.48 51.16 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00
|
||||
30.00 416.00 30.29 418.21 31.18 418.91 33.65 418.44 33.03 422.10 31.08 425.29 28.53 428.24 25.85 430.21 25.06 428.82 24.57 427.55 22.51 428.18 20.80 429.13 19.99 430.58 19.55 432.68 19.42 432.76 20.77 433.77 22.03 436.56 22.09 438.31 23.65 439.86 24.88 441.43 23.72 443.07 24.36 442.71 24.64 442.42 21.78 442.39 21.57 443.17 21.87 443.82 19.44 443.76 19.68 442.03 22.61 439.14 20.63 438.22 20.65 436.36 19.45 433.59 15.99 430.31 11.61 426.11 8.54 422.84 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00
|
||||
777.00 212.00 777.68 214.04 779.00 214.82 780.82 214.12 779.68 216.56 777.21 216.04 773.88 216.38 771.82 217.18 770.79 215.43 769.89 214.41 767.59 214.86 766.32 215.66 766.02 217.46 766.10 219.53 766.24 220.03 768.28 222.57 769.48 225.07 770.28 226.99 772.73 229.12 773.75 231.09 773.32 234.04 775.29 236.84 775.10 238.42 772.71 239.65 773.54 242.81 774.09 246.58 772.62 249.66 774.23 250.75 774.93 247.79 771.34 245.32 770.59 242.49 767.62 239.99 762.37 235.52 757.49 232.61 754.22 231.28 752.53 230.80 755.63 232.20 756.17 232.74 755.53 237.41 762.52 240.66 772.69 238.60 785.24 241.10 765.24 240.06 777.53 241.97 784.93 245.87 790.32 244.58 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00
|
||||
390.00 311.00 390.58 313.20 391.55 314.15 393.23 313.72 392.86 317.02 391.33 318.39 389.23 319.83 387.44 321.04 386.58 319.49 386.10 318.33 384.49 318.89 383.39 319.64 383.07 321.32 383.17 323.47 383.15 323.83 384.61 325.72 385.87 328.50 386.22 330.31 387.83 332.32 389.00 334.30 388.38 336.54 389.47 337.86 389.54 338.66 387.44 339.10 387.77 341.07 388.25 343.55 386.72 344.89 387.45 344.84 388.94 342.28 386.73 340.66 386.36 338.34 384.70 335.84 381.09 331.82 377.30 328.00 374.63 325.59 373.16 324.03 375.72 324.52 376.85 324.99 375.87 329.25 380.71 331.87 389.11 330.58 398.59 332.50 407.75 335.34 415.26 337.58 423.16 342.11 427.69 342.89 431.40 344.15 433.69 346.54 430.79 345.63 429.65 344.49 426.54 340.07 419.56 336.13 416.19 338.57 414.11 339.37 409.17 341.59 403.33 340.00 398.77 337.54 393.54 336.44 387.45 336.70 379.78 337.71 375.45 338.41 375.14 339.35 374.26 341.13 375.55 345.10 380.43 349.56 386.77 352.83 392.30 356.10 397.48 358.19 403.47 357.77 406.85 356.91 411.93 355.67 417.29 354.84 422.53 354.94 429.97 355.07 434.45 353.77 437.03 357.21 440.63 362.90 442.82 366.46 446.44 370.32 449.30 370.26 449.24 372.63 451.52 375.67 454.06 378.88 455.95 381.05 455.94 383.84 453.18 385.20 449.14 385.04 445.16 382.79 441.06 384.90 436.89 383.40 432.14 382.24 427.74 379.61 420.97 374.47 415.81 372.38 412.55 370.64 410.68 372.15 411.36 376.29 413.92 376.80 418.37 377.23 422.68 376.31
|
||||
120.00 302.00 120.37 303.97 121.30 304.58 123.04 304.44 122.25 308.05 120.28 310.43 117.59 312.74 115.41 313.98 114.48 312.43 113.79 311.26 111.74 311.94 110.37 312.74 109.85 314.19 109.73 316.12 109.68 316.13 111.19 317.64 112.35 320.34 112.47 322.02 114.22 323.66 115.28 325.35 114.44 326.91 115.61 327.00 115.53 327.07 113.01 327.14 113.22 328.26 113.55 329.46 111.67 329.48 112.46 328.14 113.90 325.60 111.15 324.58 110.58 322.56 108.52 320.04 104.29 316.41 99.86 312.21 96.70 309.29 94.95 306.87 97.63 306.55 98.49 306.56 96.75 310.48 102.12 311.50 111.42 310.28 121.68 311.51 131.47 312.69 139.33 313.95 147.16 318.71 151.28 319.94 154.48 321.87 155.81 325.77 151.53 327.21 149.55 325.99 145.14 322.91 136.52 320.52 131.58 323.16 128.25 324.27 121.54 325.99 114.24 324.04 108.40 320.98 101.74 319.14 93.86 319.00 84.25 319.94 78.68 320.24 77.54 321.37 75.85 321.69 76.68 324.05 81.57 327.73 88.18 331.26 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00
|
||||
95.00 19.00 95.25 20.57 96.08 20.82 96.40 21.68 94.33 25.32 90.57 27.24 86.69 29.18 84.38 29.23 82.81 27.12 81.19 26.14 78.76 26.75 77.20 27.26 76.81 29.14 76.75 30.68 76.86 30.73 78.98 33.43 79.60 35.93 80.00 37.89 82.03 39.99 82.41 42.07 82.23 43.27 84.49 43.94 83.07 43.90 80.43 44.23 81.50 45.96 81.20 47.06 79.64 46.75 80.78 45.23 78.28 43.02 73.17 41.81 70.25 39.37 64.93 36.10 57.39 31.49 51.24 26.55 46.19 23.29 44.14 21.40 46.23 21.87 43.75 22.73 42.89 26.91 49.70 27.86 57.06 28.34 67.71 31.63 77.03 33.42 84.32 36.26 90.12 41.91 90.80 41.72 91.80 45.09 87.31 48.16 78.45 47.20 74.31 44.47 62.33 38.39 49.88 35.12 42.74 35.67 36.13 34.71 25.85 33.23 15.53 26.96 6.44 21.74 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00
|
||||
515.00 311.00 515.69 313.27 516.75 314.39 518.51 313.88 518.29 316.94 516.86 317.81 514.75 318.75 513.01 319.87 512.20 318.34 511.67 317.30 510.07 317.86 509.01 318.50 508.79 320.27 508.97 322.48 509.04 322.90 510.62 325.03 511.95 327.83 512.30 329.81 514.14 331.82 515.36 333.95 514.94 336.41 516.14 338.31 516.22 339.51 514.25 340.13 514.75 342.44 515.38 345.52 514.03 347.49 514.75 348.01 516.35 345.37 514.22 343.41 513.83 340.98 512.28 338.54 508.68 334.35 504.85 330.67 502.25 328.62 500.79 327.44 503.55 328.23 504.86 328.95 504.15 333.33 509.28 336.53 517.97 335.32 527.94 337.51 537.56 341.10 545.55 343.82 554.15 348.20 559.24 348.62 563.34 349.53 566.21 351.14 563.47 349.06 562.56 347.95 559.59 342.92 552.65 338.23 549.58 340.32 547.87 340.92 543.21 343.33 537.47 341.93 533.18 339.61 528.06 338.89 522.17 339.28 514.57 340.20 510.47 341.08 510.43 341.91 509.83 344.28 511.54 348.90 516.95 353.66 523.80 356.81 529.93 359.45 535.68 360.77 542.15 358.86 545.96 356.77 533.33 354.55 538.72 353.35 544.40 352.87 552.42 352.39 557.08 350.72 560.11 353.56 564.36 359.33 567.17 362.27 571.35 365.69 574.68 364.78 574.78 367.37 577.65 371.16 580.74 374.71 582.98 377.05 583.49 379.54 581.04 380.64 577.36 379.83 573.28 378.19 569.55 381.16 565.57 380.13 560.95 378.87 556.75 376.31 550.38 370.54 544.72 369.29 541.70 367.70 539.91 370.11 541.57 373.64 544.70 373.60 548.86 374.95 553.69 374.21
|
||||
173.00 193.00 173.42 194.84 174.41 195.44 175.64 195.60 174.45 199.20 172.09 201.14 169.02 203.19 167.01 203.89 165.87 202.33 165.10 201.36 163.05 202.08 161.69 202.63 161.20 204.34 161.26 206.14 161.29 206.16 162.98 208.26 164.10 210.83 164.24 212.49 166.08 214.26 166.85 216.07 166.12 217.74 167.73 218.21 167.29 218.19 164.91 218.42 165.50 220.04 165.81 221.31 164.01 221.48 165.17 220.36 165.43 217.89 162.00 216.88 160.85 214.65 157.92 212.08 152.94 208.26 148.28 203.84 144.82 200.99 143.22 198.88 145.62 198.79 145.53 199.23 144.10 203.37 150.01 204.33 158.26 203.62 168.02 205.73 177.27 207.50 184.73 209.38 191.79 214.28 194.72 214.65 197.18 217.01 196.81 220.38 191.28 220.67 189.26 219.02 182.94 214.94 173.66 212.30 168.81 214.22 164.97 214.71 157.93 215.85 150.67 212.62 144.52 209.29 137.82 206.85 129.62 206.39 119.83 206.50 114.48 206.32 112.92 207.23 111.63 207.33 113.20 210.09 117.59 214.15 123.55 217.85 127.17 222.10 130.67 225.07 133.92 227.54 135.17 228.08 138.91 228.17 142.34 228.63 149.99 226.04 155.48 227.39 158.64 226.74 158.96 231.98 161.64 236.86 158.46 245.48 164.52 245.24 164.74 246.54 164.30 248.57 166.17 249.79 168.26 251.33 168.52 253.48 166.76 255.69 161.60 256.82 155.55 255.87 150.26 252.72 145.02 251.94 139.55 248.12 133.74 245.76 126.88 241.77 122.61 232.95 115.59 230.25 111.42 227.36 109.63 227.06 105.27 233.07 110.60 230.86 115.13 230.85 118.28 228.32
|
||||
675.00 282.00 675.69 284.21 676.97 285.34 678.73 284.56 678.20 287.40 676.46 287.51 674.03 287.97 672.20 288.92 671.19 287.31 670.63 286.26 668.91 286.73 667.65 287.41 667.49 289.19 667.75 291.41 667.85 291.99 669.65 294.32 671.04 296.96 671.67 298.87 673.67 300.99 674.98 303.17 674.48 306.06 675.99 308.57 676.01 310.09 673.80 311.04 674.44 313.82 675.16 317.48 673.79 320.12 674.78 321.27 676.16 318.54 673.42 316.29 672.73 313.61 670.78 311.16 666.44 306.74 661.96 303.45 659.12 301.73 657.49 301.05 660.46 302.36 661.72 303.18 660.71 307.59 666.75 311.33 676.21 309.96 687.30 312.51 698.24 316.63 707.33 319.78 717.17 323.79 722.67 323.67 727.54 324.20 730.51 324.49 727.20 320.93 726.38 319.74 722.61 313.72 714.85 308.40 711.63 310.23 709.91 310.39 704.91 312.65 698.82 311.10 694.16 309.20 688.74 308.68 682.18 309.11 674.01 309.94 669.66 310.79 669.70 311.43 669.35 314.52 671.64 319.69 677.89 324.59 685.52 327.29 692.10 329.13 698.26 329.15 704.64 325.23 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00
|
||||
433.00 64.00 433.04 65.52 433.72 65.92 434.04 65.83 431.94 69.06 428.71 69.68 425.33 71.22 423.29 71.50 422.07 69.49 420.90 68.56 418.69 69.21 417.28 69.88 416.79 71.81 416.53 73.56 416.57 73.95 418.03 76.45 418.47 78.92 418.48 80.78 419.88 82.77 419.92 84.85 419.40 87.06 420.98 88.55 419.68 89.25 417.06 90.10 417.49 92.50 416.70 94.82 414.83 96.08 415.40 95.31 413.35 92.35 408.70 90.57 406.18 87.66 401.68 84.62 395.42 80.12 389.93 76.21 385.47 73.80 383.30 72.49 384.38 73.00 382.24 73.57 380.23 78.21 385.21 78.95 391.26 77.32 399.53 79.56 407.33 81.26 413.59 83.23 418.55 86.71 419.73 85.25 421.06 86.75 418.16 87.36 411.23 84.86 408.51 82.32 400.32 75.27 391.06 71.67 385.52 72.25 380.94 71.40 373.34 71.61 366.16 67.05 359.56 63.44 352.60 60.60 343.53 59.89 334.44 59.67 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00
|
||||
259.00 313.00 259.52 315.16 260.47 315.94 262.22 315.68 261.74 319.13 260.10 321.09 257.83 322.94 255.99 324.24 255.19 322.64 254.66 321.52 252.93 322.18 251.76 322.88 251.38 324.48 251.40 326.54 251.40 326.69 252.93 328.48 254.12 331.23 254.39 332.94 256.03 334.79 257.10 336.64 256.43 338.56 257.57 339.34 257.61 339.72 255.47 340.00 255.80 341.52 256.26 343.37 254.66 344.13 255.41 343.50 256.95 340.90 254.80 339.61 254.39 337.49 252.79 334.95 249.22 331.15 245.41 327.08 242.76 324.48 241.21 322.51 243.85 322.60 245.01 322.88 243.79 326.97 248.75 328.85 257.43 327.57 267.05 329.20 276.32 331.29 283.85 332.98 291.61 337.71 296.05 338.72 299.57 340.32 301.57 343.52 298.35 343.78 297.03 342.63 293.73 338.90 286.49 335.70 282.64 338.28 280.23 339.28 274.85 341.37 268.74 339.70 263.91 336.93 258.44 335.59 251.90 335.68 243.87 336.73 239.28 337.24 238.75 338.28 237.63 339.42 238.82 342.67 243.55 346.76 249.88 350.19 255.38 353.91 260.44 356.72 266.42 357.86 269.78 357.99 274.80 357.49 280.13 357.39 285.41 358.12 292.83 358.84 297.27 358.18 299.72 362.20 303.01 367.68 305.05 371.68 308.38 375.75 311.14 376.46 310.79 378.88 312.83 381.24 314.98 383.80 316.63 385.91 316.32 388.98 313.20 390.56 308.81 390.77 304.59 388.34 300.09 389.50 295.60 387.43 290.53 386.35 285.93 383.53 278.99 378.45 273.55 376.16 270.09 374.19 267.92 375.02 268.29 378.99 270.69 379.84 274.98 380.09 279.33 378.79
|
||||
221.00 76.00 221.06 77.69 221.92 77.98 222.42 78.43 220.50 81.93 217.16 83.46 213.76 85.32 211.76 85.54 210.48 83.54 209.21 82.55 206.85 83.33 205.53 83.92 204.94 85.81 204.83 87.35 204.96 87.54 206.57 90.01 207.13 92.45 207.31 94.39 208.94 96.25 209.32 98.26 208.92 99.93 210.65 100.69 209.51 101.07 207.01 101.51 207.47 103.31 207.23 104.91 205.43 105.14 206.33 103.98 204.55 101.49 200.10 100.11 197.65 97.62 193.33 94.75 186.94 90.25 181.51 86.01 177.14 83.13 175.06 81.37 176.74 81.68 174.87 82.39 173.24 86.60 178.89 87.38 185.70 86.85 194.82 89.37 203.04 91.00 209.74 93.20 215.25 98.00 216.43 97.61 217.70 100.26 214.65 102.47 207.31 101.52 204.04 99.33 195.09 93.55 184.39 90.47 178.46 91.66 173.20 91.16 164.58 90.92 156.54 86.20 149.41 82.13 141.72 78.85 131.57 77.58 121.57 76.86 115.79 76.10 113.12 76.48 110.79 76.59 112.61 79.77 116.16 83.76 120.19 87.58 121.64 91.91 123.41 94.39 122.57 96.60 121.61 96.19 123.08 96.29 123.67 96.54 126.06 97.97 129.62 98.89 129.27 99.18 128.52 104.70 130.02 109.31 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00
|
||||
772.00 30.00 772.11 31.49 773.27 31.50 773.90 30.58 771.00 33.45 767.01 32.74 762.75 33.72 760.48 34.08 759.58 32.01 758.31 31.20 755.74 31.99 754.34 32.72 753.65 34.82 753.29 36.60 753.61 37.14 755.29 39.64 755.52 41.69 755.56 43.68 757.35 45.50 757.41 47.75 756.82 50.80 758.88 53.31 757.32 54.60 754.50 56.19 755.22 59.51 754.49 62.84 752.53 65.69 753.83 65.35 752.04 61.49 747.04 58.95 744.65 55.67 739.83 52.43 733.24 47.94 727.85 45.03 723.40 43.39 721.60 42.66 723.35 43.26 721.20 43.50 719.23 48.47 725.83 48.70 734.22 44.85 745.15 46.01 755.57 47.08 764.21 47.87 771.22 48.67 774.29 44.89 777.25 44.35 774.67 40.87 768.57 36.32 767.73 32.86 760.24 23.32 751.62 19.42 747.23 18.94 743.66 17.55 736.19 17.90 730.32 13.54 724.84 10.84 718.65 9.18 709.18 9.03 700.10 9.72 695.51 8.79 693.76 8.54 692.95 11.12 695.31 14.37 699.19 16.34 703.30 15.67 704.62 15.06 705.56 9.65 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00
|
||||
64.00 140.00 64.48 141.67 65.44 142.05 66.73 142.49 65.16 146.19 62.24 148.39 58.71 150.58 56.64 151.16 55.39 149.43 54.17 148.38 51.70 149.08 50.31 149.59 49.78 151.16 49.75 152.77 49.82 152.81 51.90 154.75 52.87 157.35 53.19 159.02 55.31 160.75 56.16 162.61 55.67 163.77 57.64 163.95 56.90 163.86 54.47 163.92 55.55 165.14 55.79 165.98 54.23 165.61 55.84 164.19 55.34 161.98 51.28 161.12 49.75 158.92 46.06 156.12 40.15 152.27 35.01 147.72 30.93 144.70 29.35 142.39 32.42 142.50 31.79 142.99 30.39 146.94 37.52 147.60 46.35 147.55 57.32 149.84 67.18 151.17 75.29 153.15 82.51 158.57 84.86 159.11 87.21 162.02 85.61 165.84 78.31 166.48 75.74 164.63 67.65 160.68 56.77 158.41 50.86 160.29 45.96 160.39 37.59 160.78 29.04 156.74 21.60 152.91 13.68 149.86 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00
|
||||
-1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 25.00 231.00 15.92 230.53 5.37 230.83 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00
|
||||
-1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 38.00 104.00 27.57 102.66 16.48 101.72 10.27 100.90 7.91 101.69 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00
|
||||
-1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 777.00 421.00 770.60 421.28 762.12 421.59 757.39 422.63 758.15 423.23 758.30 426.64 761.08 433.03 768.96 439.21 778.99 443.01 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00
|
||||
-1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 170.00 430.00 163.34 430.21 154.69 431.76 149.25 432.53 148.78 433.67 147.40 434.51 147.46 437.30 152.21 441.19 159.56 443.97 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00
|
||||
-1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 750.00 22.00 740.51 22.00 731.23 23.11 726.72 22.32 725.39 22.15 724.92 24.90 727.48 28.38 731.81 30.53 736.55 29.78 738.45 29.08 740.43 23.64 740.02 16.66 739.56 9.59 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00
|
||||
-1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 40.00 410.00 31.95 410.03 21.51 411.82 14.93 412.35 13.88 413.67 11.96 413.93 12.02 415.88 17.18 419.24 24.52 422.51 31.15 426.70 37.04 430.64 45.00 433.54 49.57 435.38 55.85 435.42 62.79 436.19 69.05 437.68 78.25 438.92 84.10 438.78 86.88 443.46 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00
|
||||
-1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 743.00 246.00 735.82 246.33 727.12 247.32 722.92 248.02 722.87 248.45 722.32 251.81 725.24 256.86 731.70 261.26 739.13 263.20 745.38 264.30 751.06 263.12 756.53 258.15 759.59 253.63 765.12 249.62 770.53 246.15 776.56 243.53 784.97 240.98 789.16 237.10 792.05 239.14 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00
|
||||
-1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 327.00 147.00 318.69 146.58 309.96 146.87 304.85 146.64 302.89 147.37 301.22 148.39 302.48 151.93 305.83 155.73 310.10 158.62 312.16 161.78 314.30 162.78 315.25 162.75 315.15 160.96 316.86 159.62 318.47 158.69 320.93 158.39 324.69 158.26 324.82 156.98 324.38 161.53 326.05 166.11 325.26 169.44 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00
|
||||
-1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 521.00 374.00 515.21 374.41 507.87 375.31 503.79 376.30 503.81 377.12 503.37 379.61 504.95 384.23 510.42 389.16 517.41 392.50 524.01 395.43 530.01 397.22 537.26 395.52 541.43 393.91 547.27 392.26 553.58 390.83 559.75 390.42 568.18 390.15 573.58 388.46 577.30 391.04 581.77 397.24 585.07 400.49 589.40 404.24 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00
|
||||
-1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 182.00 193.00 173.52 192.45 164.23 192.72 159.09 192.50 157.43 193.40 155.77 193.91 157.18 196.88 161.18 200.72 166.39 204.34 169.43 208.31 172.86 210.87 175.23 212.80 175.98 212.75 178.92 212.30 181.68 212.40 185.10 213.26 190.45 214.01 191.90 213.87 192.41 218.78 194.59 223.71 194.50 227.67 196.64 231.60 196.64 232.49 195.34 234.88 197.51 236.31 199.35 238.33 199.27 240.12 197.20 242.34 192.21 243.59 185.76 242.26 180.39 239.13 175.68 238.45 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00
|
||||
-1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 413.00 32.00 403.77 31.13 394.56 30.94 389.31 30.07 386.66 30.15 384.90 31.32 385.86 34.74 388.30 38.03 390.75 39.97 390.89 42.18 390.70 41.22 388.55 39.35 386.26 36.04 385.91 33.16 385.16 31.04 385.32 29.60 386.83 28.19 384.18 26.17 382.39 30.47 382.10 34.56 379.44 37.28 379.68 39.71 376.50 38.45 375.22 40.72 377.09 41.66 377.73 42.81 376.44 43.82 372.66 43.71 366.46 43.20 359.35 38.96 354.31 34.96 350.55 33.22 344.19 27.82 337.55 23.67 330.63 16.53 321.83 8.90 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00
|
||||
-1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 580.00 51.00 571.27 50.61 562.52 51.03 557.75 50.33 555.78 50.37 554.66 52.44 556.24 55.95 559.36 58.86 562.79 59.68 563.92 60.56 564.73 57.76 563.72 53.55 562.31 48.54 562.87 44.04 562.88 40.37 563.97 37.18 566.31 34.22 564.54 30.47 563.10 33.81 563.37 37.24 561.29 38.89 562.09 40.31 559.70 37.69 559.07 40.34 561.80 41.65 563.43 42.88 562.95 43.40 560.10 42.86 554.63 42.11 548.73 37.85 544.88 34.64 542.21 34.30 536.87 29.44 531.35 25.55 525.49 19.03 517.81 12.00 512.73 8.17 510.06 5.64 508.63 6.47 508.39 7.48 509.41 5.68 -1.00 -1.00 -1.00 -1.00
|
||||
-1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 360.00 281.00 353.35 281.06 345.24 281.91 341.07 282.48 340.25 283.36 339.07 284.88 340.37 288.61 345.01 292.96 350.65 296.02 355.32 299.36 359.49 301.05 364.24 301.01 366.59 300.08 370.93 298.90 375.21 298.15 379.42 298.19 386.10 298.43 389.47 297.16 391.11 300.84 394.37 306.34 395.66 309.76 398.42 313.39 400.48 313.44 400.03 315.96 402.26 318.57 404.45 321.39 405.77 323.37 405.32 326.02 401.60 327.14 397.08 326.68 392.76 324.27 388.74 325.76 384.52 323.65 379.38 322.38 374.45 319.15 367.24 313.77 361.81 311.54 358.79 309.65 356.69 310.86 357.28 314.62 359.35 314.93 363.71 315.30 367.57 313.68
|
||||
-1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 656.00 149.00 648.15 149.00 639.60 149.78 635.33 149.59 634.25 150.10 633.55 152.79 635.80 157.15 640.37 160.74 645.91 161.94 649.35 162.98 652.56 160.80 654.57 156.37 655.55 151.65 658.50 147.46 661.05 143.81 664.44 140.64 669.47 138.05 670.67 134.18 671.18 136.69 673.45 140.95 673.46 142.34 676.17 144.26 676.13 141.44 675.93 144.38 679.61 146.76 682.38 149.19 683.65 150.10 682.44 150.44 678.20 150.35 673.26 147.53 669.63 145.32 667.11 147.82 662.85 144.71 657.90 142.18 653.06 137.95 645.72 131.76 640.93 129.38 638.43 127.21 637.42 129.49 638.22 131.68 640.24 129.74 645.63 129.18 637.19 121.84
|
||||
-1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 538.00 253.00 531.21 253.25 523.16 254.20 518.75 254.70 518.13 255.47 517.22 257.78 518.99 262.21 523.68 266.47 529.67 268.99 534.20 271.40 538.45 271.65 542.59 269.19 544.70 266.70 548.63 264.17 552.61 262.08 557.11 260.71 563.46 259.71 566.26 257.28 567.70 260.28 570.87 265.37 571.97 268.04 575.30 271.11 576.69 269.66 576.39 272.33 579.24 275.70 582.04 278.97 583.55 280.66 583.02 282.58 579.49 283.08 575.09 281.87 571.32 279.77 567.72 282.61 563.53 280.81 558.54 278.90 553.90 275.88 546.76 270.48 541.72 268.52 538.68 266.77 537.41 268.71 538.25 272.28 540.50 271.74 545.32 271.94 549.05 270.52
|
||||
-1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 679.00 349.00 672.77 349.44 664.86 350.25 660.66 351.25 660.97 351.93 660.70 354.97 663.00 360.41 669.32 365.59 677.30 368.62 684.45 370.78 691.12 371.51 698.59 368.00 703.04 365.02 709.38 362.32 716.13 359.96 722.90 358.86 732.39 357.81 738.20 355.25 742.30 357.29 747.82 363.48 726.41 366.50 731.29 370.34 735.41 368.42 736.30 370.61 740.08 375.40 744.17 379.89 747.32 382.27 748.46 384.45 745.90 385.40 741.80 384.47 737.81 382.58 734.34 386.50 730.18 386.07 725.27 384.53 720.63 382.47 713.17 376.80 707.43 375.36 704.40 373.75 703.06 376.75 704.64 381.46 708.23 381.42 714.01 381.93 719.53 382.39
|
||||
-1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 311.00 396.00 304.88 396.19 297.07 397.43 292.40 398.17 292.07 399.22 290.98 400.69 291.70 404.22 296.35 408.71 302.82 412.14 308.89 415.71 314.32 418.58 321.34 419.04 325.43 419.01 330.86 418.18 336.79 417.82 342.45 418.32 350.35 418.86 355.55 417.92 358.57 421.47 362.07 427.37 364.61 431.43 368.20 435.55 371.69 436.19 371.72 438.48 373.40 441.46 376.28 443.70 380.83 444.01 390.21 441.17 387.57 442.83 383.64 442.99 379.49 440.90 375.14 442.48 370.54 441.14 365.67 440.16 351.71 444.04 342.13 441.38 336.62 439.15 333.23 437.36 330.90 438.33 331.14 442.70 334.05 443.34 338.44 443.43 342.63 443.16
|
||||
-1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 190.00 73.00 180.36 72.03 170.65 71.38 165.05 70.76 162.48 71.22 160.37 71.53 161.66 74.62 164.77 78.49 168.44 82.04 169.61 86.12 170.66 87.83 169.89 89.49 168.64 88.58 169.58 88.02 170.19 88.04 171.91 88.86 175.04 89.63 173.86 89.55 172.95 94.70 173.91 99.36 172.29 103.44 173.51 107.19 171.26 107.73 169.52 109.83 171.47 110.61 172.33 111.85 171.36 113.75 167.72 114.64 160.96 114.86 153.23 112.02 147.07 107.97 142.28 105.40 135.24 100.41 127.71 97.02 119.90 90.40 109.86 83.29 105.36 67.48 100.62 86.46 98.10 86.94 98.01 89.37 95.93 77.21 102.26 65.69 101.37 73.15
|
||||
-1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 449.00 159.00 441.11 158.74 432.48 159.21 427.88 159.00 426.26 159.76 424.80 161.44 426.19 165.23 429.77 169.12 434.30 171.42 436.84 174.03 439.22 173.99 440.60 172.33 440.60 169.57 442.73 167.18 444.60 165.31 447.37 164.17 451.30 163.09 451.95 161.04 451.79 164.73 453.41 169.40 452.82 172.21 454.88 175.06 454.20 174.14 452.98 176.71 455.59 178.74 457.30 181.07 457.56 182.51 455.76 183.75 451.18 184.23 445.51 182.03 440.95 179.20 437.44 179.95 432.47 176.59 426.73 174.21 421.28 169.50 413.55 163.37 408.11 160.48 404.64 157.93 402.99 159.33 403.22 162.14 404.54 161.14 408.54 160.91 411.20 157.91
|
||||
-1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 130.00 314.00 122.39 313.90 112.96 314.82 107.57 315.06 106.44 316.21 104.73 316.61 105.60 319.16 110.35 322.97 116.66 326.43 121.69 330.59 126.56 333.89 131.91 336.29 134.60 337.12 139.40 337.10 144.51 337.60 149.42 338.73 156.64 339.85 160.58 339.68 162.10 344.23 164.85 349.32 166.41 353.73 169.21 357.91 171.34 359.33 170.33 361.75 171.80 363.19 173.51 365.16 174.61 367.24 173.54 370.35 169.40 371.99 163.78 372.30 159.12 369.66 153.44 369.57 148.21 366.78 141.79 365.57 136.43 362.31 128.36 357.11 122.10 354.65 117.57 352.26 114.76 352.27 114.89 356.00 116.87 356.80 121.33 356.91 125.56 355.08
|
||||
-1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 614.00 30.00 611.92 29.16 613.21 29.49 610.60 29.97 608.51 34.87 614.19 35.08 620.95 31.89 630.37 33.49 639.18 34.73 646.27 35.95 651.69 37.63 653.59 34.40 655.49 34.64 652.13 32.22 645.67 28.19 643.99 24.78 636.01 15.66 627.46 11.77 622.64 11.41 618.55 10.12 611.12 10.20 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00
|
||||
-1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 32.00 296.00 30.12 293.50 33.05 292.92 33.80 292.95 31.83 296.75 37.67 297.45 47.56 296.20 58.33 297.30 68.67 298.22 76.87 299.26 84.84 304.04 88.93 305.21 92.01 307.28 92.98 311.56 87.80 313.46 85.62 312.15 80.59 309.27 70.99 307.24 65.49 309.99 61.69 311.02 54.13 312.66 46.05 310.55 39.54 307.31 32.05 305.18 23.42 305.05 12.68 305.93 6.28 306.07 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00
|
||||
-1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 780.00 430.00 778.26 429.61 782.01 431.58 784.83 433.13 784.80 437.35 791.24 443.38 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00
|
||||
-1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 215.00 27.00 212.77 25.44 213.73 25.89 210.93 26.68 209.31 31.12 214.62 31.78 220.60 30.97 229.29 33.77 237.00 35.31 243.15 37.64 247.74 42.14 248.18 41.23 248.84 43.71 244.34 45.34 236.30 43.46 232.64 40.54 222.30 33.82 211.57 30.44 205.16 30.91 199.27 29.88 190.45 29.04 181.86 23.37 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00
|
||||
-1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 523.00 193.00 521.10 192.06 523.32 192.82 522.73 193.30 521.15 197.89 526.61 199.97 534.14 198.23 543.52 200.24 552.52 202.86 559.97 205.08 567.20 208.62 570.38 207.58 573.32 208.62 573.41 208.75 568.63 206.46 567.25 204.74 561.91 198.44 553.67 194.47 549.97 196.02 547.04 195.90 540.80 197.40 534.72 194.47 529.75 192.12 523.81 190.72 516.46 190.81 508.12 191.61 503.83 191.77 502.55 192.30 501.33 194.36 503.14 198.59 507.40 202.59 512.53 204.81 516.12 206.97 519.34 206.53 521.83 204.14 522.53 200.85 525.53 198.12 528.31 195.78 532.34 194.65 537.36 193.49 539.38 191.04 539.08 193.99 541.45 198.58 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00
|
||||
-1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 68.00 419.00 66.12 416.48 68.91 415.52 70.68 415.19 68.95 419.12 73.44 420.29 83.72 418.24 94.46 418.55 104.74 419.36 112.73 419.87 121.24 424.24 126.64 426.03 130.58 427.46 133.36 431.80 130.69 434.22 129.02 433.28 126.41 430.73 119.01 428.41 114.09 431.59 111.25 433.26 105.15 435.75 98.01 434.91 92.47 431.91 86.00 430.58 78.66 430.83 69.08 432.73 62.87 433.43 62.12 434.79 60.30 435.21 60.39 437.57 65.32 441.14 72.10 443.95 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00
|
||||
-1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 542.00 351.00 540.60 349.84 543.34 350.92 544.92 351.73 544.27 356.01 549.36 359.66 558.34 358.52 568.49 360.92 578.49 364.74 586.71 367.74 595.69 372.22 601.09 372.96 605.52 373.68 608.81 375.26 606.47 372.84 605.65 371.71 602.86 366.69 596.04 361.44 593.01 363.56 591.46 364.28 586.87 366.64 581.22 365.39 576.79 363.23 571.81 362.50 565.99 362.91 558.47 363.79 554.38 364.74 554.49 365.55 554.04 368.20 555.74 373.03 561.42 378.05 568.70 381.38 575.37 383.97 581.48 385.32 588.61 383.19 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00
|
||||
-1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 230.00 350.00 228.23 348.00 230.56 347.99 231.61 348.23 230.14 352.34 234.52 354.45 243.11 353.15 252.37 354.70 261.46 356.84 268.46 358.72 275.84 363.82 280.19 365.29 283.68 366.63 285.56 370.41 282.37 370.94 280.55 370.33 277.15 367.11 269.46 364.47 265.15 367.47 262.53 368.54 256.79 371.00 250.39 369.49 245.24 366.74 239.34 365.56 232.49 365.75 223.96 367.13 218.74 367.87 217.92 369.32 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00
|
||||
-1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 400.00 198.00 399.34 196.87 399.70 197.10 400.41 197.85 397.39 202.07 402.88 203.90 409.54 202.25 419.52 204.62 427.80 206.90 434.75 208.98 441.41 213.06 445.47 212.88 447.03 214.13 449.38 215.91 441.69 213.87 439.90 212.23 434.93 206.71 426.00 203.03 421.97 204.81 418.42 204.87 415.80 206.91 408.59 203.93 401.56 200.90 394.52 199.09 386.96 198.94 380.32 199.84 375.55 199.93 375.43 200.86 371.04 201.90 373.42 205.87 377.30 209.90 383.42 212.92 387.44 215.92 386.89 216.15 392.36 215.87 393.63 214.08 395.57 212.16 399.22 210.95 398.63 209.96 408.55 210.18 404.91 207.89 408.78 212.24 411.64 217.20 400.82 219.20 409.34 223.16 403.16 222.06 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00
|
||||
-1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 227.00 207.00 225.27 205.18 227.32 205.46 227.12 205.77 225.40 209.95 230.89 211.35 238.62 210.25 247.84 212.31 256.81 214.21 263.90 216.07 270.61 220.73 273.55 220.92 276.00 222.92 275.88 225.66 270.33 225.55 268.37 223.88 262.48 219.31 253.64 216.51 248.96 218.53 245.30 218.89 238.35 220.28 231.64 217.30 225.51 214.14 210.95 207.72 202.66 207.31 193.82 207.83 188.77 207.84 187.43 208.80 185.34 209.34 186.91 212.62 190.93 216.40 195.98 219.62 199.54 223.61 202.86 226.05 205.70 227.66 206.42 227.20 209.76 226.83 212.84 226.82 216.73 227.66 222.18 228.55 223.98 228.00 224.44 232.64 226.51 237.56 226.48 241.61 229.51 245.56 229.37 246.57 218.73 240.76 230.55 250.48 233.07 252.65 233.37 254.65 220.49 248.51 226.62 257.90 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00
|
||||
-1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 776.00 36.00 774.38 35.47 776.64 35.98 774.53 36.24 772.72 41.24 780.17 41.31 789.60 37.07 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00
|
||||
-1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 90.00 186.00 88.43 183.74 91.25 183.67 91.06 184.13 89.61 188.22 96.02 188.97 104.61 188.46 114.92 190.50 124.70 191.87 132.41 193.72 139.63 198.69 142.58 199.32 145.14 201.89 144.52 205.46 138.35 206.04 136.10 204.54 129.29 200.56 119.43 198.21 113.87 200.30 109.88 200.65 102.42 201.62 94.55 198.40 87.97 194.98 80.92 192.33 71.78 191.88 61.85 191.95 56.40 191.74 61.70 195.63 60.35 195.70 62.20 197.95 60.13 199.14 66.11 203.12 70.04 207.75 74.11 211.07 77.52 214.21 78.66 215.13 82.54 215.61 86.42 216.53 90.64 218.18 97.21 219.74 99.58 220.19 100.91 225.37 103.52 230.19 103.72 234.62 106.38 238.80 106.84 240.50 106.01 242.82 108.13 243.54 109.56 245.10 110.24 247.17 107.89 249.67 102.78 251.02 96.15 250.14 97.18 249.11 85.33 245.43 79.05 241.73 78.75 242.56 72.61 237.99 62.73 232.30 55.80 229.23 51.56 226.14 49.45 226.59 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00
|
||||
-1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 377.00 330.00 375.50 328.44 378.04 328.92 379.19 329.43 378.19 333.64 382.97 336.33 391.38 335.05 400.89 336.97 410.06 339.83 417.54 342.06 425.45 346.62 430.01 347.44 433.76 348.65 436.15 351.06 433.24 350.16 432.14 349.03 429.06 344.64 422.10 340.62 418.72 343.09 416.66 343.89 411.72 346.18 405.91 344.60 401.35 342.14 396.13 341.08 390.02 341.30 382.39 342.37 378.03 343.03 377.67 343.94 376.78 345.78 378.14 349.72 382.96 354.34 389.35 357.59 394.83 360.80 400.12 362.90 406.13 362.54 409.57 361.66 414.64 360.41 420.04 359.57 425.30 359.64 432.73 359.73 437.30 358.49 439.92 361.83 443.57 367.61 445.78 371.17 449.37 375.02 452.29 374.94 452.28 377.39 454.51 380.49 457.05 383.73 459.01 385.88 459.07 388.71 456.27 390.06 452.24 389.97 448.30 387.67 444.14 389.85 440.05 388.39 435.24 387.25 430.91 384.65 424.12 379.51 418.91 377.43 415.65 375.66 413.79 377.19 414.45 381.36 417.03 381.90 421.45 382.31 425.78 381.43
|
||||
-1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 487.00 39.00 484.60 37.72 485.54 38.32 482.94 38.74 480.82 43.53 485.71 44.06 491.85 41.78 500.23 43.80 507.98 45.31 514.27 46.84 519.12 49.64 520.34 47.33 521.46 48.29 517.76 47.33 511.15 44.18 508.70 41.06 500.27 32.80 491.23 28.92 485.95 28.99 481.40 27.84 473.80 27.84 466.98 22.79 460.56 19.10 453.90 16.45 444.72 15.72 435.66 15.50 430.36 14.45 427.80 14.53 426.12 15.85 427.07 19.19 429.44 22.39 431.81 23.89 431.77 25.69 431.22 23.91 428.63 21.46 426.34 17.62 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00
|
||||
-1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 761.00 250.00 759.55 249.62 762.94 251.08 763.93 251.87 763.02 256.42 770.07 259.96 780.56 258.01 792.94 260.47 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00
|
||||
-1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 91.00 66.00 89.02 63.98 91.03 64.39 89.22 65.12 87.96 69.27 94.26 70.10 101.69 70.04 111.73 72.85 120.59 74.48 127.78 76.92 133.62 82.24 134.78 82.13 136.20 85.06 132.69 88.02 124.74 87.44 121.09 85.07 110.88 79.55 99.50 76.54 92.79 77.53 87.01 76.90 77.60 76.31 68.40 70.94 60.22 66.50 51.68 62.69 40.23 60.80 28.75 59.26 22.28 58.27 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00
|
||||
-1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 345.00 30.00 342.61 28.66 343.32 29.05 340.51 29.67 338.47 34.30 343.38 34.81 348.91 33.33 357.19 35.73 364.56 37.26 370.42 39.19 374.76 42.87 375.46 41.15 375.94 42.91 371.85 43.34 364.42 40.87 361.12 37.87 351.65 30.33 341.75 26.66 335.89 26.98 330.51 25.80 322.36 25.29 314.59 19.84 307.56 15.78 300.19 12.57 290.40 11.35 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00
|
||||
-1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 663.00 359.00 661.29 358.34 664.18 359.94 665.82 360.90 665.19 365.14 670.26 361.71 681.13 381.73 675.87 368.42 686.96 373.20 697.06 384.59 707.05 388.50 713.24 388.63 718.15 388.52 722.20 389.63 718.70 380.66 717.90 379.42 714.94 373.90 724.29 378.65 721.21 380.87 702.77 370.11 698.16 372.60 692.06 371.48 704.03 381.14 682.00 369.11 675.78 369.62 667.84 370.45 665.95 388.30 663.82 372.42 665.92 392.27 667.97 398.47 674.06 401.31 682.02 404.51 688.20 397.57 694.20 393.53 702.05 390.45 705.99 383.63 713.20 385.11 720.21 383.14 727.06 382.19 735.96 377.19 742.89 379.21 747.19 381.25 753.92 392.41 757.97 395.38 762.19 393.48 767.91 397.30 768.87 399.37 772.88 404.38 777.39 409.50 781.24 412.77 782.47 414.45 780.24 415.80 775.89 414.26 771.58 412.42 767.96 417.29 763.38 416.52 758.35 415.70 753.54 413.57 745.36 407.85 754.36 405.68 750.85 404.39 734.80 408.43 751.34 411.84 755.17 412.09 746.27 413.76 752.37 413.63
|
||||
-1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 689.00 125.00 687.42 124.42 689.50 125.28 688.53 125.68 687.01 130.51 693.27 132.04 701.76 129.16 712.51 131.06 722.51 133.26 731.27 134.99 738.75 137.01 742.46 134.61 745.71 134.67 745.20 132.74 739.41 128.70 738.89 126.42 732.75 118.44 724.37 114.40 720.56 114.84 717.60 114.20 710.90 115.38 705.04 112.27 699.89 109.91 694.24 108.80 685.92 108.81 677.20 109.72 672.79 109.56 671.76 109.64 671.13 112.46 673.68 116.48 678.25 119.71 683.55 120.22 686.41 120.65 689.36 117.37 690.58 111.95 690.87 106.43 693.45 101.32 695.57 97.12 698.41 93.22 703.11 89.70 703.52 85.27 703.43 87.60 705.23 91.05 704.67 92.11 707.16 93.16 706.65 89.98 706.42 92.88 710.58 94.93 713.55 96.89 714.43 97.34 712.61 97.14 708.50 96.75 703.23 93.29 700.19 91.26 697.96 92.84 693.72 89.31 688.80 86.25 683.96 81.34 676.53 75.27 671.83 72.53 669.73 70.26 668.94 72.59 669.69 73.85 671.80 71.27 677.20 69.89 680.90 65.97
|
||||
565.39 158.71 565.66 160.57 566.63 161.19 567.62 160.60 566.31 163.62 563.69 163.93 560.57 164.91 558.56 165.60 557.57 163.83 556.62 162.91 554.81 163.39 553.64 164.05 553.21 165.86 553.14 167.87 553.26 168.25 554.78 170.64 555.59 173.11 555.69 175.01 557.42 176.97 558.09 179.08 557.39 181.54 558.85 183.63 558.30 184.55 555.77 185.48 556.39 188.06 556.19 191.06 554.49 193.08 555.35 193.12 554.93 190.08 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00
|
||||
599.62 147.64 599.96 149.41 600.75 150.09 601.86 149.43 600.34 152.44 597.67 152.56 594.58 153.53 592.41 154.14 591.52 152.33 590.63 151.41 588.57 152.02 587.38 152.68 586.79 154.59 586.80 156.49 586.91 156.89 588.49 159.35 589.14 161.73 589.41 163.56 590.94 165.58 591.53 167.72 590.99 170.34 592.62 172.44 591.87 173.52 589.44 174.44 589.85 177.29 589.69 180.26 588.05 182.36 588.83 182.46 588.44 179.35 584.53 177.28 582.84 174.46 579.50 171.58 574.07 167.31 569.27 163.92 565.59 161.99 563.67 161.12 565.74 161.74 564.86 162.29 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00
|
||||
@@ -0,0 +1,26 @@
|
||||
792.80 84.80 791.74 83.65 791.76 81.20 791.58 78.70 791.66 76.45 792.60 75.41 792.67 76.34 792.28 76.21 792.85 75.18 793.84 74.14 794.37 73.66 793.82 73.72 792.67 74.06 791.89 75.28 791.90 75.26 791.72 75.16 791.39 76.00 791.40 76.00 792.00 75.65 792.01 76.81 791.35 78.53 790.81 79.46 789.68 80.70 788.35 82.22 786.65 82.82 784.74 83.20 782.65 83.97 779.66 84.00 777.29 84.90 775.37 85.20 772.74 85.36 770.56 85.46 767.64 84.59 765.73 83.22 762.85 81.18 760.83 79.14 758.37 77.64 755.18 75.99 753.39 74.80 751.13 74.48 748.64 74.13 746.19 73.99 743.58 73.92 741.24 73.86 739.17 73.93 736.62 74.01 734.15 73.91 731.68 73.75 729.41 73.24 727.43 72.70 725.75 71.78 725.75 70.78 722.63 71.42 717.63 70.42 713.18 69.59 711.23 68.55 707.41 68.61 703.39 68.61 699.65 67.56 695.58 67.55 692.12 67.09 688.08 66.71 684.08 66.71 680.07 66.37 676.52 65.79 672.69 66.29 668.21 66.33 664.22 66.31 660.33 65.37 656.15 65.75 652.66 65.72 649.84 64.69 649.50 64.25 649.23 65.25 651.19 66.30 655.40 66.39 659.40 66.62 663.35 66.71 665.88 66.38 662.52 66.66 656.36 66.59 651.36 66.59 647.37 67.26 641.81 68.78 635.48 70.05 630.48 71.05 627.14 72.72 621.56 74.61 615.09 76.00 608.37 77.91 601.38 79.30 596.06 80.78 593.44 82.20 593.23 82.73 593.56 82.59 591.74 83.78 587.84 84.70 585.45 84.33 583.69 83.74 583.28 83.84 581.28 83.84 577.86 83.13 574.88 81.26 565.90 79.35 570.05 80.90 566.16 80.22 560.78 79.80 554.95 80.38 550.84 80.27 548.76 79.72 546.55 79.41 537.78 77.48 537.78 77.48 538.21 76.97 539.68 75.94 542.22 75.57 545.64 75.43 550.09 75.30 555.55 74.42 560.31 74.16 559.05 73.45 557.15 73.79 561.42 72.67 563.91 72.42 562.15 72.83 560.42 73.00 561.52 73.37 561.82 75.35 561.31 76.78 566.84 77.91 571.35 80.37 572.93 81.93 575.42 83.92 575.79 85.60 572.35 88.08 568.65 89.70 565.18 91.01 562.55 93.10 559.12 94.94 557.12 96.94 555.67 98.80 554.78 100.84 552.37 102.40 549.28 104.93 547.78 107.17 548.31 108.93 549.59 110.98 550.10 112.54 548.74 113.67 545.56 114.76 543.23 116.11 542.09 117.37 542.53 118.39 541.50 119.20 538.55 120.53 534.67 121.86 529.83 122.33 523.78 123.09 518.80 123.59 515.39 124.18 510.42 124.17 502.82 124.23 495.56 124.92 489.34 125.30 482.92 124.88 476.48 124.72 470.76 124.67 465.68 124.28 461.64 124.58 458.15 124.98 455.36 124.87 453.88 124.88 453.01 125.05 451.92 125.56 450.35 126.31 448.85 126.78 447.50 127.25 446.28 127.31 443.81 127.40 440.16 127.83 437.50 127.98 436.19 128.14 435.08 128.15 433.21 127.61 430.30 127.25 428.07 127.16 427.00 126.69 427.24 126.27 428.18 125.58 429.58 124.75 430.96 123.26 432.16 122.10 432.67 120.06 431.92 118.87 430.89 118.39 429.35 116.91 428.42 116.10 426.77 115.93 424.82 115.35 423.21 115.80 421.57 115.96 420.52 116.40 418.65 119.78 416.55 120.79 415.46 120.34 413.95 118.34 411.77 114.80 409.30 111.22 404.60 108.64 400.66 107.10 397.81 105.45 395.68 104.85 392.22 104.72 388.23 105.45 383.13 105.95 377.59 107.44 372.21 110.68 368.79 112.73 363.79 114.73 357.51 119.05 354.60 123.05 350.74 127.54 346.82 133.08 342.66 137.98 339.53 139.36 335.96 136.54 333.63 131.52 331.71 128.11 330.13 126.63 328.48 124.17 326.66 122.17 326.12 120.58 325.03 117.42 323.50 113.41 322.72 109.69 321.66 105.77 320.38 103.88 318.94 102.60 316.88 101.12 315.14 100.40 311.48 101.14 309.32 101.41 307.04 101.59 305.53 103.99 302.75 107.58 300.32 109.29 297.65 108.78 292.82 106.84 288.64 106.67 285.78 107.12
|
||||
-1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 566.40 427.20 567.28 425.92 567.43 426.42 567.21 426.06 567.63 424.60 569.03 423.50 569.59 422.67 569.33 422.74 568.53 423.10 567.99 424.18 568.10 424.05 567.89 423.82 567.68 424.59 567.73 424.56 568.14 424.08 568.17 425.41 567.75 427.35 567.40 428.71 566.63 430.26 565.30 431.79 564.14 432.83 562.54 433.51 560.38 434.60 557.78 434.95 555.50 435.99 553.81 436.62 551.41 437.09 549.35 437.24 546.67 436.80 545.07 435.70 542.98 434.38 541.54 432.70 539.65 431.67 537.13 430.51 536.16 430.08 534.63 430.14 532.81 430.14 531.30 430.29 529.59 430.65 528.24 430.90 526.91 431.44 525.09 431.74 523.03 432.04 521.17 432.08 519.80 431.78 518.79 431.77 518.62 431.27 520.38 430.75 518.42 431.82 515.16 431.66 512.61 431.67 512.71 431.08 510.96 431.96 508.60 432.54 506.74 432.47 504.50 432.90 502.74 433.14 500.20 433.31 497.61 434.30 495.35 434.53 493.22 434.42 491.25 435.11 488.41 436.05 485.84 436.51 483.49 436.27 481.30 437.14 480.07 437.57 479.54 437.27 481.16 437.62 482.76 439.18 486.62 440.38 492.29 440.84 498.72 441.60 505.05 442.93 509.90 443.06 508.62 443.89 504.59 444.62 502.09 445.42 500.81 446.78 498.15 448.77 495.29 450.74 493.78 452.46 492.81 454.56 490.27 456.87 486.61 458.96 482.35 461.53 477.70 463.52 474.38 465.08 473.57 466.55 474.83 467.38 476.25 467.54 475.68 468.60 472.71 469.60 470.65 469.19 469.68 468.82 469.94 469.22 469.11 469.21 466.46 468.74 464.45 467.51 463.71 467.94 463.06 468.33 461.58 468.62 458.90 469.57 456.22 471.09 455.03 472.42 455.93 472.68 456.55 473.18 458.02 473.16 458.77 473.37 460.41 473.02 462.49 472.37 465.40 471.72 468.83 470.84 473.17 470.43 478.52 468.96 483.37 468.17 482.73 467.11 482.06 466.93 486.79 465.09 489.71 464.06 487.52 463.71 485.70 462.65 487.73 461.71 488.95 462.59 489.83 462.87 496.70 462.81 502.83 463.89 505.38 464.16 508.84 465.11 509.78 465.57 506.92 466.69 503.67 467.26 501.33 467.68 500.08 468.67 498.29 469.71 498.04 470.81 498.39 471.98 498.76 473.03 498.05 473.98 496.08 475.88 496.03 477.31 497.48 478.73 499.89 480.02 501.41 481.61 501.60 482.76 500.49 483.96 500.11 485.83 501.55 487.41 504.56 489.00 506.49 490.45 506.48 492.19 504.96 494.08 502.53 495.05 498.94 496.49 496.67 497.56 495.21 499.20 492.35 499.57 487.11 500.65 482.14 502.09 477.90 503.20 473.30 503.70 468.94 503.92 465.21 504.56 462.36 504.96 460.22 505.80 458.45 506.58 457.30 507.25 457.47 508.12 458.08 508.52 458.11 509.62 457.52 510.68 457.47 511.73 457.37 512.66 457.39 513.00 456.19 513.42 454.30 514.41 453.25 514.76 453.37 514.99 453.44 515.03 452.48 514.96 450.98 514.90 449.82 514.77 449.90 514.35 451.46 513.84 453.29 512.93 455.31 512.52 457.25 510.65 458.88 509.77 460.14 507.88 460.70 506.48 460.87 506.04 460.79 504.46 461.41 503.76 461.75 503.38 462.34 502.46 462.84 502.62 463.17 502.82 463.69 503.23 464.44 506.03 464.42 506.55 464.37 506.10 464.00 503.94 463.21 500.31 462.01 496.69 458.34 494.33 455.68 492.82 454.27 490.89 452.96 490.22 450.59 490.21 448.06 490.57 444.83 490.70 440.06 492.58 436.01 495.52 434.69 497.22 431.95 499.11 427.03 503.16 425.96 506.92 423.39 511.27 420.99 516.69 418.57 521.48 417.37 522.43 415.67 519.03 414.18 513.77 412.83 510.69 411.84 509.15 410.62 506.63 409.55 504.96 408.81 503.37 408.28 500.02 407.45 496.04 407.23 492.46 407.06 488.65 406.33 486.80 405.41 485.73 404.30 484.28 403.35 483.75 400.55 484.30 399.79 484.42 398.65 484.34 397.53 486.66 395.36 490.35 394.04 491.79 392.40 490.78 388.99 488.84 385.85 488.32 384.60 488.42
|
||||
933.72 457.11 932.27 455.82 932.00 453.48 931.88 450.86 931.93 448.61 932.81 447.67 933.10 448.41 932.60 448.33 933.23 447.39 934.37 446.30 935.01 445.73 934.90 445.80 934.25 445.95 933.95 447.13 934.13 447.15 934.11 447.22 934.12 448.23 934.37 448.57 934.91 448.66 935.36 450.19 935.41 452.21 935.55 453.61 935.13 455.25 934.46 457.13 933.88 458.28 932.61 459.13 931.17 460.49 929.13 461.28 927.46 462.58 926.36 463.70 924.68 464.44 923.06 465.08 920.90 465.08 919.91 464.30 918.46 462.76 917.51 461.38 916.17 460.33 914.26 459.31 913.89 458.63 912.84 458.54 911.76 458.80 910.49 459.09 909.67 459.36 908.73 459.87 907.90 460.72 907.11 461.35 905.70 461.85 904.74 462.51 903.77 462.86 903.64 463.08 904.03 462.74 906.27 462.35 905.41 463.37 902.91 462.84 900.96 462.25 901.78 461.48 900.90 461.64 899.26 461.73 898.42 461.33 896.72 461.52 896.00 461.56 894.08 461.60 892.27 462.47 890.94 462.65 889.63 462.73 888.00 463.84 886.15 464.26 884.50 464.88 882.97 464.67 881.15 465.42 880.79 465.71 880.76 465.13 883.14 465.19 885.31 466.28 889.65 467.94 896.24 468.45 903.27 469.05 910.38 469.80 915.98 469.81 915.04 470.37 911.75 470.34 909.75 469.88 909.09 470.36 906.91 470.73 904.23 470.74 903.20 470.78 902.65 472.14 900.58 473.12 897.11 473.91 893.54 475.38 889.49 476.53 886.42 477.48 885.76 479.22 887.59 480.04 889.49 480.82 888.99 482.29 886.33 483.73 884.38 484.04 883.75 484.36 884.43 485.04 883.67 485.25 881.37 485.48 879.68 484.26 879.56 484.17 879.49 484.12 878.66 483.58 876.65 482.57 874.61 482.01 874.32 481.42 875.63 479.64 876.69 478.44 878.50 477.12 879.37 476.32 880.94 475.68 883.14 474.87 885.64 474.65 888.63 474.52 892.77 474.26 897.70 473.70 902.07 472.92 900.86 471.20 899.43 470.21 903.60 467.78 905.66 466.29 902.89 466.07 899.75 464.78 900.84 463.27 900.85 462.78 900.75 461.67 906.49 459.66 911.17 459.44 912.72 459.07 915.02 459.16 915.04 458.99 911.14 459.52 907.04 459.46 903.62 459.07 901.33 459.17 898.77 458.82 897.58 458.39 897.21 458.28 896.86 458.80 895.56 458.56 893.21 459.56 892.71 460.88 894.13 462.14 896.36 463.92 898.17 465.64 898.34 466.10 897.31 466.73 897.45 467.97 899.44 468.45 903.06 469.22 905.48 469.52 905.85 470.25 904.93 471.08 903.00 471.61 900.05 472.36 898.30 472.89 897.24 474.39 895.00 474.88 890.08 475.37 885.49 476.93 881.66 478.06 877.61 478.79 873.63 479.17 870.19 479.43 867.59 479.63 865.61 480.33 864.23 481.46 863.49 481.76 864.14 482.53 865.25 483.56 865.50 485.06 865.40 486.48 865.49 487.54 865.54 488.32 865.64 489.20 864.70 489.54 863.23 489.92 861.66 489.95 861.77 490.16 861.87 490.42 861.16 490.42 859.34 490.41 858.41 490.42 858.40 490.31 859.54 490.14 861.15 489.96 863.24 489.78 864.74 488.70 866.10 488.36 867.12 486.70 867.34 485.44 867.25 484.31 866.46 482.63 866.72 481.10 866.59 479.51 866.58 477.16 866.69 476.04 866.68 474.94 866.90 474.61 867.02 475.65 866.22 474.99 865.72 473.96 865.12 470.89 863.47 466.52 861.74 462.18 857.70 459.46 854.41 457.55 852.33 455.23 850.70 454.45 847.74 453.96 844.83 453.35 840.89 452.73 835.99 453.86 830.92 456.44 828.93 456.86 825.87 457.32 820.40 460.18 818.77 463.21 815.69 466.36 812.79 470.88 810.00 474.69 808.17 474.62 805.64 469.92 803.69 464.29 802.06 461.39 800.76 459.82 799.02 456.98 797.72 455.36 796.79 453.97 796.08 450.40 794.63 445.95 794.28 441.84 793.60 437.49 792.46 435.29 791.51 433.14 790.00 430.87 788.81 429.46 785.68 429.00 784.31 427.84 782.78 426.54 781.23 428.22 778.68 430.98 776.65 430.91 774.37 428.13 770.22 424.75 766.21 422.40 764.00 420.80
|
||||
566.36 604.29 565.03 602.47 564.46 599.61 564.21 596.31 564.21 593.77 565.09 592.06 565.22 592.64 564.37 592.21 564.85 590.79 566.12 589.38 566.49 588.63 566.25 588.65 565.44 589.05 564.84 590.26 564.82 590.09 564.38 589.85 564.09 590.69 563.99 590.64 563.98 590.16 563.88 591.56 563.27 593.59 562.70 595.00 561.73 596.54 560.22 598.21 558.87 599.25 557.04 599.94 554.63 601.10 551.72 601.68 549.12 602.83 547.11 603.40 544.43 604.01 542.06 604.35 539.11 603.84 537.35 602.93 535.32 601.59 533.54 600.03 531.32 598.75 528.78 597.85 527.85 597.28 526.24 597.34 524.01 597.35 522.10 597.62 520.29 598.22 518.73 598.48 517.00 598.94 515.01 599.28 512.72 599.60 510.35 599.63 508.38 599.34 506.99 599.20 506.47 598.75 507.85 598.38 505.79 599.27 502.24 599.04 499.82 599.10 499.87 598.60 498.04 599.56 495.53 600.22 493.69 600.04 491.28 600.68 489.48 600.93 486.51 601.03 483.80 602.06 481.40 602.26 478.92 602.26 476.48 603.09 473.44 603.88 470.78 604.44 468.27 604.23 465.83 605.21 464.18 605.69 463.52 605.29 464.98 605.63 466.39 607.13 469.61 608.09 475.04 608.48 481.23 609.45 487.53 610.75 492.33 610.90 490.79 611.90 486.75 612.59 484.39 613.33 483.45 614.83 481.15 616.82 478.69 618.74 477.55 620.45 476.88 622.46 474.54 624.87 471.00 627.04 466.92 629.58 462.44 631.68 459.45 633.65 458.21 635.11 459.32 635.98 460.31 636.12 459.47 637.21 456.16 638.30 453.44 637.64 452.33 637.42 452.41 637.75 451.09 637.81 448.23 637.42 445.94 636.28 445.20 636.46 444.45 637.21 443.31 637.88 441.16 638.74 439.01 640.69 438.32 641.87 439.68 642.68 440.92 643.22 442.54 643.36 443.83 643.44 445.20 643.17 447.18 642.14 450.00 641.29 452.95 640.56 457.22 639.51 462.01 638.24 466.97 637.08 466.61 635.95 466.45 635.52 471.32 633.48 474.66 631.97 472.51 631.16 470.78 629.70 473.19 628.43 475.05 629.00 476.60 628.67 484.04 628.04 490.86 628.72 493.98 628.89 497.56 629.40 499.12 629.41 496.49 630.25 493.45 630.37 491.67 630.40 490.75 631.50 489.49 631.94 489.95 632.81 490.72 633.77 491.26 634.37 490.91 635.01 489.30 636.71 489.23 638.22 490.74 639.20 492.76 640.62 494.24 641.99 494.40 643.11 493.12 644.75 493.00 646.26 494.63 648.27 497.50 650.09 499.65 651.63 499.75 653.64 498.23 655.58 495.73 656.49 492.44 658.34 489.99 659.64 488.07 661.01 484.76 661.81 479.37 663.08 474.14 665.00 469.39 665.93 464.44 666.31 459.86 667.26 455.90 667.90 452.77 668.33 450.31 669.40 448.29 670.42 446.65 671.25 446.56 671.91 446.67 672.68 446.35 673.99 445.40 675.13 445.10 676.26 444.67 677.15 444.30 677.88 443.09 678.41 441.48 679.24 439.99 679.56 439.95 680.09 439.75 680.34 438.70 680.27 436.88 680.23 435.41 680.09 435.30 679.46 436.52 678.96 437.68 678.38 439.39 677.44 440.63 675.97 441.92 674.55 442.79 672.63 443.36 671.50 443.55 670.50 443.29 669.29 444.04 667.99 444.47 667.53 445.43 667.05 446.31 667.12 446.96 667.18 447.86 667.36 448.78 670.01 449.14 670.58 449.25 669.99 449.14 668.06 448.66 664.46 447.65 660.55 444.00 658.02 441.25 656.26 439.90 654.29 438.46 653.59 436.13 653.38 433.75 653.78 430.62 653.86 426.00 655.76 422.03 658.68 421.13 660.29 418.53 662.29 413.98 666.43 413.16 670.27 410.71 674.66 408.34 680.19 406.25 684.42 405.31 685.33 403.82 682.52 402.38 677.20 400.97 673.64 399.68 671.87 398.64 669.48 397.31 667.46 396.24 665.82 395.57 662.85 394.85 658.72 394.63 655.18 394.63 651.31 393.92 649.31 393.32 647.85 392.61 646.78 392.10 645.89 389.45 646.83 389.01 646.88 388.32 646.72 387.21 649.01 385.23 652.45 384.32 653.77 383.43 652.69 380.35 650.67 377.79 649.81 377.05 649.82
|
||||
949.21 607.23 947.63 606.11 947.13 603.99 946.57 601.06 946.47 598.92 947.30 597.69 947.39 598.53 946.67 598.57 947.13 597.59 947.95 596.56 948.53 595.92 948.36 596.08 947.69 596.28 947.43 597.59 947.49 597.62 947.35 597.84 947.26 598.90 947.32 599.45 947.56 599.54 947.70 601.25 947.73 603.28 947.74 604.83 947.51 606.66 946.57 608.71 945.64 609.92 944.62 610.91 943.01 612.46 940.79 613.29 938.86 614.93 937.53 616.05 935.66 617.12 933.99 617.96 931.59 618.00 930.30 617.63 928.89 616.06 927.87 615.00 926.26 614.06 924.31 613.19 923.79 612.75 923.02 612.77 921.32 613.15 920.26 613.54 919.09 614.05 918.10 615.02 916.93 615.86 915.85 616.76 914.36 617.63 912.74 618.47 911.71 619.11 911.12 619.59 911.46 619.59 913.40 619.56 912.19 620.61 909.74 620.39 907.86 620.03 908.71 619.61 907.81 620.03 906.23 620.55 905.40 620.12 903.77 620.64 902.98 621.01 900.92 621.57 898.97 622.64 897.41 623.11 895.80 623.62 894.13 624.89 892.09 625.84 890.08 626.58 888.26 626.79 886.58 627.92 885.83 628.49 885.69 628.22 887.93 628.61 890.04 630.28 894.13 631.99 900.30 633.10 907.22 634.21 914.25 635.38 919.38 635.88 918.78 636.92 915.35 637.12 913.69 636.97 913.03 637.61 911.51 638.18 909.50 638.38 908.62 638.71 908.25 640.05 906.42 641.54 903.50 642.48 900.11 644.39 896.42 645.84 893.37 647.12 892.48 649.07 894.04 650.49 895.23 651.46 894.55 653.30 891.83 655.02 889.35 655.58 888.07 656.25 888.45 657.20 887.75 657.54 885.14 658.00 883.18 657.33 882.95 657.50 882.98 657.91 882.31 657.44 880.96 657.18 879.66 657.12 879.77 656.52 881.80 655.22 883.61 654.48 885.68 653.12 887.22 652.67 888.53 652.12 890.46 651.20 892.90 650.79 895.59 650.77 899.42 650.60 903.77 650.06 907.99 649.30 907.31 647.18 906.14 646.01 910.33 643.37 912.55 641.64 909.74 640.66 906.83 638.99 907.93 636.81 908.53 635.70 908.94 633.96 915.39 631.61 920.73 630.76 922.71 629.79 925.23 629.44 925.42 628.68 921.60 628.98 917.70 628.54 914.65 627.50 912.71 627.26 910.64 626.51 910.07 626.02 910.03 625.52 909.97 625.72 908.98 625.21 906.85 626.21 906.36 627.22 907.58 628.65 909.54 630.66 910.89 632.60 911.28 633.24 910.38 634.53 910.58 635.80 912.81 637.11 916.62 638.22 919.14 639.14 919.83 640.07 918.95 641.68 917.07 642.48 914.35 643.77 912.48 644.94 911.36 646.89 908.77 648.24 903.84 649.32 899.13 651.30 894.98 653.22 890.51 654.51 886.30 655.31 882.96 656.47 879.80 657.34 877.73 658.46 876.38 659.94 875.26 661.28 875.49 662.38 876.29 663.90 876.23 666.10 875.42 668.21 875.44 669.50 875.32 670.83 875.08 672.28 874.14 672.89 872.34 673.54 870.86 674.01 870.76 674.76 870.58 675.30 869.72 675.71 867.78 676.06 866.11 676.55 865.72 676.79 866.64 676.93 867.81 677.14 869.16 677.26 870.08 676.76 870.95 676.54 871.61 675.14 871.72 673.70 871.49 672.97 870.67 671.56 870.91 670.06 871.08 668.70 871.72 666.61 872.23 665.40 872.35 664.37 872.81 664.00 873.53 665.11 873.30 664.61 873.07 663.79 872.31 661.37 871.10 657.03 869.72 652.59 865.54 649.45 861.92 647.77 859.99 645.40 858.40 644.29 855.28 643.98 852.37 643.72 848.69 643.03 843.77 644.33 838.99 646.80 837.51 647.28 834.72 648.08 829.76 651.21 828.29 654.37 825.62 657.79 823.10 662.71 820.63 666.05 819.04 666.20 816.84 662.49 814.80 656.91 812.82 653.03 811.24 651.54 809.83 649.03 807.97 647.12 806.82 646.09 805.77 643.02 804.64 638.40 803.99 634.58 803.56 629.99 802.96 627.19 801.86 625.17 800.96 622.81 799.94 621.27 797.21 620.70 796.59 619.45 795.24 617.87 794.15 619.55 791.81 622.06 790.24 621.90 788.70 619.20 785.27 615.35 781.74 612.48 780.40 610.45
|
||||
953.34 258.56 952.24 257.43 952.25 255.42 952.18 252.76 952.20 250.76 953.31 249.38 953.79 250.36 953.26 250.42 953.77 249.43 955.14 248.39 955.62 247.93 955.49 247.97 954.51 248.41 954.14 249.36 954.30 249.35 954.37 249.46 954.39 250.31 954.79 250.64 955.49 250.55 955.96 252.02 955.89 253.77 955.90 254.93 955.45 256.39 954.66 257.97 953.77 258.91 952.48 259.40 951.00 260.43 948.96 260.96 947.27 262.08 946.09 263.00 944.17 263.48 942.59 263.91 940.58 263.49 939.48 262.52 937.69 260.48 936.47 259.02 934.95 257.56 932.73 256.19 931.88 255.31 930.70 254.89 929.21 254.88 927.88 254.90 926.39 254.87 925.26 255.00 924.35 255.46 923.08 255.59 921.70 255.86 920.46 256.21 919.45 256.14 918.97 255.74 918.83 255.25 920.61 254.51 918.88 254.91 915.73 254.07 913.25 253.00 913.21 251.69 911.40 251.52 908.89 251.30 907.20 250.32 904.68 250.19 903.47 249.81 900.93 249.41 898.51 249.77 896.64 249.41 894.65 248.92 892.61 249.46 890.08 249.49 887.86 249.60 885.36 249.12 883.09 249.18 881.55 248.99 880.65 247.93 882.41 247.31 883.64 247.92 887.32 248.99 893.29 249.00 899.69 248.15 905.69 248.12 910.40 247.45 908.93 247.49 904.37 247.06 901.28 246.39 899.26 246.39 895.59 246.46 891.15 246.42 888.49 246.25 886.83 246.96 883.44 247.87 878.55 248.32 873.61 249.71 868.67 250.25 864.85 251.18 863.43 252.24 864.80 252.84 866.44 253.07 865.66 254.22 862.74 255.34 861.05 255.48 860.28 255.42 860.56 255.50 859.53 255.51 857.11 255.20 855.12 253.71 854.21 253.23 853.24 252.59 851.04 251.44 847.55 250.01 843.75 249.08 841.76 247.94 841.57 245.99 841.29 244.28 841.76 242.69 841.73 241.65 842.87 240.75 844.69 239.87 847.24 239.37 850.40 239.17 854.62 239.12 859.67 238.43 864.41 237.95 865.25 237.95 863.35 237.32 867.29 235.36 869.33 234.62 866.57 234.77 863.67 234.31 864.21 233.32 863.75 233.76 862.81 233.73 867.68 232.70 871.76 233.19 872.87 233.45 874.88 234.45 874.77 235.01 870.41 236.50 866.19 237.22 862.38 237.27 859.37 238.12 856.16 238.46 854.20 238.78 852.77 239.29 851.91 240.21 849.84 240.39 846.69 241.92 845.73 243.37 846.71 244.80 848.70 246.38 850.08 247.83 849.52 248.37 847.71 248.78 846.99 249.35 847.58 249.49 849.91 249.77 850.90 249.46 849.97 249.59 847.67 250.28 844.57 250.29 840.30 250.30 837.30 250.30 835.39 250.79 831.95 250.75 826.07 250.58 820.56 251.19 815.89 251.74 810.95 251.51 805.90 251.03 801.69 250.69 798.02 250.28 795.26 250.25 793.13 250.70 791.60 250.31 791.14 250.28 791.63 250.34 791.63 251.34 790.70 252.28 790.31 252.60 789.90 252.86 789.47 253.20 788.05 252.86 785.37 252.86 783.40 252.41 782.81 252.14 782.42 252.02 781.05 251.52 778.83 251.04 777.21 250.68 776.65 250.00 777.60 249.37 779.15 248.84 780.59 248.08 782.11 246.68 783.48 245.80 784.07 243.87 783.68 242.25 782.95 241.12 781.70 239.13 781.21 237.28 779.80 235.90 778.44 233.75 777.44 232.75 776.44 231.75 775.37 231.27 774.16 232.80 772.16 232.36 771.16 231.36 769.58 228.64 767.50 224.24 765.15 219.81 760.45 216.90 756.64 215.03 754.44 212.61 752.11 211.50 748.51 211.02 744.62 210.75 740.18 210.25 734.11 211.46 728.47 213.97 725.59 214.53 718.04 214.41 711.37 217.64 708.82 220.66 704.73 224.21 700.86 228.95 696.94 232.50 694.37 232.56 691.10 228.54 688.78 222.88 686.90 219.29 685.22 217.73 683.33 214.73 681.89 212.95 680.97 211.39 679.96 207.92 678.40 203.42 677.52 199.37 676.61 194.92 675.40 192.57 673.84 190.59 671.55 188.46 669.98 186.96 666.11 186.87 664.03 186.02 661.62 185.03 659.66 187.05 656.66 190.06 653.92 190.55 650.67 188.51 646.01 185.67 641.15 183.79 638.07 183.01
|
||||
781.62 244.15 780.31 243.06 780.31 240.52 779.97 237.89 780.04 235.66 781.13 234.24 781.15 235.16 780.77 235.11 781.24 234.05 782.61 232.90 783.07 232.44 782.59 232.44 781.59 232.68 780.98 234.00 781.08 233.92 780.95 233.72 780.83 234.45 780.94 234.89 781.34 234.51 781.41 235.94 780.95 237.69 780.49 239.16 779.86 240.28 778.47 241.91 777.36 242.51 775.89 243.02 773.52 244.03 770.88 244.52 768.71 245.50 767.10 246.10 764.60 246.43 762.60 246.75 759.91 246.27 758.28 245.11 755.86 243.05 754.21 241.42 752.21 239.91 749.42 238.69 747.94 238.17 746.30 237.67 744.31 237.66 742.34 237.56 740.03 237.70 738.48 238.04 737.06 238.45 734.99 238.40 732.81 238.61 730.74 238.68 728.83 238.65 727.34 238.22 726.70 237.75 727.71 237.30 725.20 237.78 721.22 237.30 717.45 236.45 716.92 235.46 713.88 235.81 710.58 235.82 707.76 235.40 704.66 235.50 702.21 235.18 698.81 235.12 695.34 235.67 692.65 235.33 689.73 234.88 686.98 235.70 683.47 236.09 680.12 236.05 677.21 235.42 673.64 236.18 671.14 236.51 669.76 235.39 670.30 235.32 671.03 236.33 673.94 237.49 678.88 237.77 684.16 238.04 689.35 238.60 693.31 238.33 690.81 238.86 685.53 238.95 682.04 238.98 678.98 239.77 674.72 241.15 669.75 242.10 666.45 243.04 664.11 244.55 660.14 246.22 654.68 247.75 649.09 249.81 643.23 251.12 638.80 252.64 636.89 254.15 637.62 254.68 638.40 255.13 637.20 255.83 633.69 256.83 631.37 256.67 629.93 256.21 630.14 256.43 628.53 256.42 625.32 256.17 622.92 254.63 621.39 254.27 619.86 254.27 617.20 253.89 612.98 253.53 608.47 254.09 605.93 253.93 604.97 253.43 604.36 253.15 604.31 252.24 604.29 251.81 605.30 251.33 607.08 250.33 609.65 249.88 612.72 249.27 617.19 249.28 622.61 248.29 627.10 247.57 626.03 246.61 624.60 246.30 629.07 244.40 631.69 243.94 629.29 243.94 627.16 243.79 628.65 243.32 629.05 244.33 628.87 244.92 634.89 245.17 639.48 246.72 641.30 247.55 643.87 249.03 644.30 249.67 640.80 251.65 637.02 252.53 633.82 253.20 631.50 254.67 628.65 255.70 627.24 257.17 626.35 258.22 625.65 260.13 624.06 260.90 620.93 262.84 620.11 264.77 621.16 266.28 622.88 268.04 623.93 269.54 622.86 270.80 620.40 271.45 619.30 273.03 619.29 274.11 620.78 275.06 621.41 275.88 619.92 276.89 616.83 278.39 613.05 278.82 608.02 279.74 604.52 280.31 601.48 281.32 597.48 281.32 590.79 281.68 584.79 282.68 579.27 283.17 573.73 282.98 567.85 282.84 562.92 283.22 558.91 283.21 555.50 283.22 552.57 283.70 550.30 283.85 549.72 283.91 549.31 284.34 548.72 285.18 547.42 286.28 546.69 286.71 545.74 287.23 545.00 287.43 542.84 287.54 540.26 287.70 537.74 287.90 537.02 287.88 536.29 287.84 534.79 287.38 532.24 287.01 530.58 286.86 529.85 286.28 530.53 285.82 531.86 285.20 533.37 284.20 534.76 282.72 535.97 281.59 536.68 279.53 536.07 278.18 535.55 277.62 534.55 275.62 534.02 274.57 532.95 274.03 531.80 272.75 530.89 272.54 529.91 272.68 529.65 272.82 528.65 275.82 526.98 276.01 525.99 275.15 524.84 273.10 522.81 269.18 520.80 265.25 516.56 262.26 512.74 261.05 510.55 258.89 508.55 257.89 505.41 257.10 501.48 258.17 497.22 257.62 491.56 259.54 486.57 262.63 484.34 263.67 479.82 265.47 473.82 269.47 471.63 272.82 467.63 277.82 464.45 282.21 460.45 287.21 458.45 287.21 455.45 284.21 453.45 279.21 451.45 276.21 450.45 273.21 448.45 272.21 447.45 269.21 446.45 268.21 445.45 264.21 443.45 260.21 443.45 256.21 442.45 253.21 441.45 250.21 439.70 248.89 438.40 246.95 436.50 246.32 432.53 246.54 435.98 238.05 433.48 238.62 428.48 247.62 425.47 251.61 423.47 252.61 421.34 250.61 416.34 249.61 411.42 248.67 420.02 249.38
|
||||
756.00 403.00 754.85 401.73 754.70 399.14 754.47 396.23 754.57 393.92 755.53 392.74 755.96 393.42 755.44 393.30 755.97 392.00 757.30 390.99 757.90 390.52 757.69 390.46 756.89 390.84 756.47 391.90 756.61 391.84 756.57 391.74 756.44 392.70 756.75 392.81 757.12 392.62 757.40 394.01 757.15 396.00 757.13 397.44 756.59 398.86 755.59 400.49 754.47 401.59 753.05 402.20 751.38 403.44 748.93 403.97 747.00 405.17 745.62 405.88 743.47 406.62 741.73 407.02 739.30 406.62 738.04 405.66 736.21 404.11 735.10 402.63 733.39 401.33 731.18 400.32 730.33 399.75 729.17 399.66 727.44 399.71 726.12 399.88 724.81 400.30 723.65 400.60 722.50 401.06 721.09 401.53 719.50 401.99 718.00 402.16 716.74 402.19 716.14 402.21 716.12 401.85 718.10 401.25 716.44 402.26 713.39 401.82 711.00 401.39 711.33 400.52 709.79 401.17 707.70 401.70 705.99 401.02 703.98 401.58 702.37 401.72 700.03 401.80 697.96 402.61 695.85 402.65 693.88 402.62 692.13 403.51 689.60 404.09 687.45 404.62 685.41 404.38 683.20 404.99 682.17 405.36 681.60 405.01 683.56 405.01 685.15 406.40 689.07 407.82 695.10 408.19 701.69 408.86 708.02 409.51 713.03 409.51 711.76 410.50 707.79 410.69 705.32 410.69 704.04 411.64 701.07 413.02 698.08 413.99 696.72 414.96 695.62 416.19 693.01 418.20 689.01 419.50 684.99 421.51 680.26 422.87 677.06 424.28 676.10 425.70 677.52 426.61 679.07 426.68 678.35 427.98 675.86 429.11 673.53 429.16 672.80 429.08 673.23 429.26 672.24 429.28 669.84 429.30 667.82 427.98 667.24 428.02 666.83 428.57 665.15 428.09 662.75 427.92 659.72 428.39 658.71 428.66 659.62 428.09 660.02 427.61 661.25 427.00 661.97 426.81 663.34 426.36 665.33 425.32 668.29 424.86 671.35 424.56 675.69 424.10 680.77 423.17 685.36 422.56 684.48 420.93 683.37 420.47 687.72 418.25 690.10 417.31 687.70 416.84 685.42 416.02 686.90 415.02 687.16 415.35 687.35 415.19 693.67 414.10 699.03 414.65 700.98 415.00 703.82 415.58 704.06 415.89 700.58 416.91 697.00 417.32 694.03 417.32 692.12 418.04 689.91 418.33 688.95 419.00 688.79 419.61 688.79 420.61 687.41 420.87 685.18 422.44 684.92 423.90 686.21 425.29 688.39 426.92 690.07 428.48 690.02 429.35 688.78 430.40 688.27 431.68 689.96 432.75 693.02 433.99 694.82 434.57 694.80 435.99 693.00 437.31 690.72 438.03 687.25 438.93 684.83 440.34 683.52 440.99 680.82 441.61 675.35 442.51 670.38 443.84 666.32 444.87 661.90 445.34 657.19 445.46 653.81 445.99 650.40 446.38 648.43 446.87 646.69 447.83 645.71 448.24 645.92 448.78 646.53 449.71 646.58 450.72 646.01 452.17 646.01 452.92 646.00 453.70 645.92 454.39 644.66 454.58 642.85 455.02 641.45 455.30 641.48 455.41 641.39 455.49 640.44 455.46 638.68 455.44 637.59 455.32 637.58 454.87 638.84 454.45 640.32 454.08 642.36 453.49 643.99 452.32 645.65 451.62 646.71 449.70 646.88 448.39 646.89 447.61 646.28 446.04 646.59 444.76 646.61 443.90 646.54 442.37 646.53 441.93 646.66 441.50 646.74 441.54 646.97 443.82 646.27 443.87 646.00 443.04 645.38 440.70 644.07 436.93 642.48 432.85 638.41 430.11 635.31 428.34 633.64 426.31 631.99 425.37 629.48 425.34 626.38 425.24 622.44 425.10 617.84 426.59 613.22 429.50 611.39 430.48 607.93 432.07 602.68 435.62 601.15 439.12 598.32 443.01 595.74 448.00 592.83 452.01 591.31 452.76 589.00 449.08 587.32 443.61 585.80 440.11 584.42 438.62 582.96 436.12 581.96 434.12 580.93 432.83 580.35 429.71 579.13 425.35 578.84 421.43 578.27 417.47 577.27 415.47 576.35 413.60 574.93 411.85 573.93 410.85 570.74 411.15 569.55 410.78 568.06 410.18 566.78 412.16 564.24 415.65 562.45 416.36 560.31 414.87 556.31 412.15 552.80 411.07 550.72 410.46
|
||||
985.73 366.51 984.55 365.44 984.44 363.35 984.13 360.86 984.21 358.79 985.17 357.69 985.45 358.59 985.06 358.69 985.61 357.66 986.81 356.75 987.41 356.25 987.27 356.31 986.46 356.47 986.08 357.75 986.26 357.80 986.26 357.86 986.26 358.86 986.71 359.18 987.28 359.25 987.77 360.74 987.77 362.66 987.89 363.86 987.59 365.45 986.82 367.27 986.10 368.16 985.08 369.07 983.47 370.18 981.35 370.80 979.73 372.17 978.69 373.20 976.86 373.85 975.37 374.39 973.30 374.36 972.29 373.52 970.74 371.70 969.72 370.13 968.22 369.16 966.18 367.79 965.65 367.00 964.58 366.80 963.17 366.79 962.12 366.93 960.95 367.04 959.97 367.51 959.09 368.02 958.10 368.49 956.73 369.10 955.63 369.52 954.67 369.66 954.27 369.71 954.58 369.29 956.61 368.82 955.31 369.34 952.35 368.82 950.30 367.85 950.75 366.79 949.35 366.72 947.34 366.69 946.06 365.68 944.09 365.71 942.86 365.44 940.83 365.43 938.79 365.96 937.16 365.79 935.32 365.70 933.58 366.51 931.36 366.88 929.42 367.16 927.43 366.70 925.43 367.10 924.47 367.11 923.91 366.07 926.03 365.74 927.87 366.79 931.89 368.02 938.20 368.36 944.86 368.66 951.75 368.97 956.76 368.48 955.69 368.80 951.64 368.43 949.07 367.56 947.71 367.77 944.71 367.77 941.21 367.66 939.19 367.43 938.18 368.21 935.41 369.17 931.35 369.54 927.07 370.89 922.42 371.65 919.05 372.56 917.99 374.11 919.47 374.70 920.93 375.26 920.45 376.75 917.69 378.16 915.73 378.51 915.20 378.59 915.49 379.10 914.66 379.13 912.22 379.14 910.22 378.14 909.61 377.73 909.21 377.27 907.67 376.13 905.17 374.71 902.39 373.78 901.13 372.53 901.50 370.61 902.14 368.95 902.98 367.15 903.52 366.15 904.79 365.23 906.81 364.26 909.36 363.82 912.42 363.68 916.57 363.55 921.59 363.08 926.11 362.62 924.57 360.77 922.86 359.84 926.87 357.81 928.64 356.48 925.65 356.48 922.65 355.48 923.31 354.08 923.10 353.96 922.43 353.11 927.60 351.47 932.12 351.39 933.21 351.24 935.31 351.66 935.11 351.70 930.77 352.75 926.39 353.17 922.71 352.77 919.82 353.17 916.79 353.03 915.10 352.86 914.23 352.86 913.57 353.46 911.57 353.46 908.76 354.64 908.03 355.90 909.09 357.34 911.16 359.02 912.56 360.59 912.44 361.01 910.86 361.63 910.67 362.47 911.93 362.69 914.87 363.12 916.46 363.04 916.17 363.28 914.49 364.10 911.84 364.11 908.18 364.35 905.61 364.77 904.22 365.48 901.26 365.73 895.51 365.91 890.40 366.86 885.94 367.74 881.43 367.76 876.66 367.83 872.66 367.83 869.44 367.74 866.83 367.98 864.91 368.51 863.76 368.71 863.85 369.09 864.37 369.52 864.42 370.86 863.80 371.94 863.73 372.53 863.31 373.31 863.29 373.84 861.64 373.84 859.44 373.88 857.62 373.68 857.30 373.64 857.19 373.66 855.72 373.53 853.82 373.09 852.23 373.00 851.67 372.62 852.81 372.05 854.20 371.69 855.65 371.56 857.22 370.35 858.40 369.61 858.91 367.81 858.69 366.04 857.77 365.06 856.78 363.06 856.74 361.13 855.81 359.58 854.95 357.31 854.35 355.81 853.48 354.59 852.86 354.19 852.27 355.21 850.76 354.40 849.76 353.40 848.38 350.64 846.52 346.13 844.14 341.66 839.47 338.56 835.78 336.50 833.48 333.91 831.26 332.75 827.66 332.29 823.90 331.88 819.39 331.05 813.53 332.18 808.37 334.56 805.65 334.74 801.34 335.45 795.31 338.34 793.25 340.95 789.27 344.51 785.79 349.00 782.29 352.16 779.65 352.23 776.71 348.22 774.72 342.39 772.62 338.74 770.84 337.12 769.25 334.14 767.77 332.12 766.80 330.59 765.74 327.36 764.24 322.77 763.47 318.66 762.55 314.07 761.42 311.41 759.77 309.43 757.82 307.34 756.39 305.39 752.63 305.05 750.63 304.05 748.78 302.49 746.82 304.37 743.92 306.60 741.55 306.84 738.68 304.38 734.11 300.98 729.37 298.55 726.82 296.58
|
||||
667.20 232.00 665.89 230.59 665.78 228.06 665.40 225.12 665.46 222.69 666.16 221.52 666.34 222.27 665.68 222.13 666.19 220.87 667.22 219.90 667.54 219.36 666.94 219.40 665.74 219.86 664.90 221.03 664.78 220.96 664.37 220.78 663.88 221.65 663.88 221.65 663.99 221.19 663.83 222.65 662.86 224.53 662.05 225.58 660.75 226.99 659.13 228.55 657.16 229.33 655.09 229.67 652.42 230.56 649.27 230.62 646.29 231.61 644.08 232.01 641.07 232.32 638.30 232.44 635.20 231.55 632.79 230.48 629.77 228.59 627.47 226.81 624.81 225.21 621.37 223.94 619.42 222.96 616.90 222.94 614.18 222.83 611.53 222.85 608.56 223.05 606.01 223.34 603.55 223.75 600.88 223.71 597.81 223.68 594.81 223.68 592.10 223.25 589.65 222.84 587.80 222.41 587.83 221.89 584.36 222.65 579.23 222.12 574.64 221.75 572.64 221.13 568.89 221.65 564.51 221.97 560.87 221.35 556.58 221.84 553.08 221.76 548.69 221.64 544.31 222.10 540.35 221.92 536.33 221.41 532.54 222.27 528.04 222.80 523.66 222.91 519.53 222.35 515.24 222.95 511.71 223.40 509.29 222.73 508.93 222.76 508.61 224.08 510.74 225.28 514.86 225.70 519.20 226.47 523.20 227.47 526.18 227.51 522.79 228.01 516.78 228.56 511.88 229.02 508.52 230.48 503.43 232.37 497.83 234.39 493.77 236.38 490.49 238.32 485.84 240.49 479.42 242.83 473.12 245.48 466.28 247.25 460.93 248.89 458.30 250.78 458.38 251.36 458.74 251.37 456.56 252.70 452.59 253.60 449.71 253.11 447.74 252.67 447.25 252.87 445.23 252.83 441.57 252.00 438.57 250.48 436.34 250.60 433.84 251.09 430.49 251.00 425.56 251.54 420.50 253.06 417.06 253.91 415.49 254.29 414.24 254.55 413.79 254.57 413.64 254.50 414.23 254.07 416.18 252.89 418.73 252.31 422.25 251.78 427.07 251.22 432.52 250.11 437.46 249.60 436.38 248.75 435.29 249.11 439.98 247.89 443.18 247.41 441.65 247.38 440.25 246.98 442.24 246.98 443.14 248.83 444.10 250.23 450.52 251.16 456.16 253.48 458.67 254.98 462.04 256.95 463.12 258.29 460.08 260.25 456.76 261.74 453.90 262.86 451.89 264.89 449.39 266.67 448.36 268.74 447.82 270.74 447.63 272.77 445.95 274.29 442.93 276.75 442.16 278.81 443.11 280.79 444.60 282.53 445.26 284.46 444.04 285.66 441.01 287.16 439.23 288.83 438.69 290.80 439.59 292.53 439.19 293.84 436.75 295.61 433.27 297.49 428.65 298.44 423.16 299.39 418.52 300.30 414.96 301.19 409.95 301.31 402.51 301.76 395.42 302.77 389.17 303.20 382.72 302.75 376.24 303.00 370.61 303.11 365.73 303.05 361.76 303.24 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00
|
||||
-1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 526.82 248.92 523.90 248.48 522.24 248.15 521.64 248.24 519.65 248.24 516.28 247.58 513.40 245.82 511.34 245.95 509.22 246.12 505.88 245.88 501.32 246.01 496.25 247.22 493.11 247.53 491.80 247.59 490.60 247.54 490.42 247.03 490.14 246.90 490.94 246.24 492.60 245.34 495.23 244.83 498.42 244.28 503.06 243.88 508.52 242.87 513.45 242.24 512.26 241.30 510.92 241.43 515.52 240.12 518.49 239.57 516.65 239.73 514.92 239.43 516.58 239.36 517.45 240.92 517.89 242.01 524.17 242.83 529.48 244.85 531.67 246.03 534.69 248.00 535.51 249.08 532.19 251.26 528.77 252.31 525.73 253.34 523.54 255.19 520.95 256.68 519.50 258.68 518.92 260.29 518.49 262.24 516.71 263.64 513.68 266.06 512.89 267.95 513.63 269.78 515.21 271.47 515.92 273.26 514.79 274.61 512.09 275.80 510.29 277.26 509.78 278.91 510.85 280.43 510.71 281.41 508.52 282.87 505.12 284.55 500.67 285.22 495.17 286.30 490.76 287.31 487.48 288.07 482.93 288.04 475.36 288.69 468.37 289.73 462.50 290.09 456.31 289.93 449.84 289.91 444.47 290.00 439.68 289.89 435.91 290.15 432.56 290.82 429.87 290.85 428.59 291.15 428.12 291.44 427.09 292.17 425.42 292.97 423.82 293.48 422.88 294.21 421.86 294.40 419.52 294.69 416.50 295.20 413.73 295.43 412.70 295.45 411.74 295.43 409.87 295.14 407.34 294.93 405.20 294.70 404.27 294.11 404.53 293.70 405.70 292.90 406.78 291.98 408.98 291.61 410.22 290.22 410.72 288.21 410.21 286.89 409.52 286.14 408.34 284.68 407.84 283.64 406.74 283.35 405.50 282.77 404.45 283.18 403.65 283.32 403.15 283.86 402.18 287.01 400.65 287.93 399.71 287.32 398.33 285.39 396.65 281.74 394.47 277.92 389.99 275.34 386.42 273.68 383.99 271.95 381.96 271.07 378.62 271.10 375.11 271.61 370.57 272.13 365.03 273.79 359.96 276.84 357.23 278.70 353.11 280.75 346.90 285.02 344.78 289.00 340.97 293.42 337.48 299.23 333.93 303.64 331.52 304.87 328.62 302.01 326.56 296.92 324.62 293.46 323.19 291.82 321.58 289.33 320.08 287.39 319.16 285.45 318.24 282.42 316.76 278.39 316.26 274.54 315.38 270.78 314.35 268.80 312.86 267.46 311.21 266.19 309.78 265.23 306.29 265.99 304.68 266.35 302.80 266.34 301.45 268.59 298.89 272.09 296.96 273.53 294.64 272.84 290.62 270.90 286.55 270.50 284.53 270.85
|
||||
1020.54 126.01 1019.42 125.09 1019.52 123.11 1019.38 120.55 1019.46 118.52 1020.43 117.39 1020.76 118.28 1020.35 118.48 1020.85 117.47 1022.11 116.59 1022.63 116.01 1022.32 116.04 1021.36 116.32 1020.53 117.27 1020.67 117.25 1020.69 117.42 1020.66 118.30 1020.98 118.70 1021.72 118.29 1022.14 119.68 1022.03 121.23 1021.98 122.22 1021.17 123.23 1020.18 124.75 1019.25 125.33 1017.76 125.86 1016.13 126.63 1013.70 126.78 1011.95 127.84 1010.85 128.41 1008.65 128.58 1006.89 128.77 1004.86 128.30 1003.50 126.96 1001.19 124.52 999.74 122.67 998.12 121.30 995.36 119.41 994.33 118.34 992.52 117.37 990.70 116.88 988.93 116.57 986.92 116.09 985.31 115.97 983.87 116.08 982.26 115.97 980.48 115.89 978.72 115.54 977.41 115.38 976.40 114.83 975.45 113.67 976.57 112.38 974.19 112.42 970.07 110.93 966.65 109.54 965.68 107.52 962.64 106.67 959.64 106.23 956.74 104.37 953.69 103.83 951.25 102.84 947.83 102.19 944.62 101.82 941.90 100.92 939.27 100.28 937.38 100.28 933.87 99.82 930.80 99.47 927.78 98.47 924.17 97.78 921.41 96.78 919.61 95.21 919.73 93.94 920.32 94.37 922.98 94.62 928.06 94.28 933.04 93.46 938.00 92.75 941.40 91.21 938.85 91.14 933.12 89.86 928.58 88.67 925.31 88.34 919.83 87.89 914.13 87.61 909.71 87.22 906.58 87.34 902.03 88.22 895.77 88.07 889.74 89.06 883.43 89.44 878.14 89.69 876.18 90.70 876.53 90.79 877.54 90.80 875.86 91.66 872.80 92.56 870.48 92.44 869.40 92.40 869.13 92.31 867.33 91.66 864.56 91.23 861.60 88.91 859.45 87.70 857.47 86.73 854.54 85.31 850.41 84.21 844.41 82.21 840.60 79.82 839.10 77.65 837.08 75.60 836.46 73.55 835.84 72.50 836.15 71.32 837.66 70.32 839.71 69.50 842.36 69.42 846.56 69.35 852.44 69.30 856.61 68.62 854.70 67.53 852.32 67.15 855.58 65.38 858.08 65.63 855.65 66.22 852.73 66.36 852.95 66.30 851.98 67.26 850.54 67.64 854.82 67.57 858.34 68.76 858.89 69.77 861.26 72.10 860.59 72.87 856.13 74.93 851.35 76.54 847.29 77.27 844.25 79.21 839.70 79.51 837.17 80.67 835.10 81.55 833.67 83.25 830.42 83.47 826.72 85.39 825.26 87.11 825.38 88.80 827.13 90.48 827.47 91.81 826.22 92.42 823.22 92.42 821.14 92.86 820.45 92.71 820.86 92.55 820.65 92.13 817.86 91.81 814.19 92.17 809.65 91.60 803.47 91.17 798.32 90.42 795.29 90.45 791.22 90.31 783.22 89.31 775.50 89.02 769.90 88.95 763.32 87.84 756.66 86.79 751.06 86.13 745.64 85.08 741.77 84.72 738.02 84.30 735.50 83.65 733.98 83.21 732.91 82.70 731.65 82.81 730.24 83.54 728.80 83.41 727.23 83.27 726.51 83.28 723.15 82.45 719.73 82.32 716.31 81.49 715.13 81.46 713.43 80.59 710.93 79.52 708.34 79.17 705.66 78.42 704.20 77.48 703.85 76.59 704.45 75.73 705.61 74.87 706.76 73.57 706.55 71.63 706.55 69.63 705.56 68.18 704.31 67.24 702.21 65.38 700.10 63.13 697.20 61.36 695.11 60.13 692.82 59.35 690.24 58.31 688.59 58.38 684.82 58.32 681.80 58.27 679.61 56.98 677.43 54.42 674.53 50.19 671.24 45.83 666.05 42.87 661.72 40.93 658.11 38.58 655.00 37.39 650.71 37.04 645.85 36.94 639.91 36.46 633.51 37.99 627.16 40.43 623.13 41.61 617.52 42.83 609.86 46.08 606.15 49.42 601.17 53.26 596.27 58.46 591.32 62.18 587.57 62.62 583.31 58.77 580.43 53.20 578.00 49.51 575.95 47.89 573.42 44.87 571.82 42.88 570.68 41.02 569.23 37.63 567.38 33.10 566.17 29.13 564.76 24.84 563.21 22.45 561.24 20.55 558.53 18.48 556.59 17.15 552.46 17.23 549.46 16.73 546.59 16.30 544.16 18.22 540.66 21.58 537.74 22.54 534.28 21.07 528.94 18.55 523.39 17.11 520.39 17.11
|
||||
1141.19 172.07 1140.06 171.44 1140.19 169.53 1140.06 167.35 1140.43 165.32 1141.32 164.34 1141.78 165.35 1141.29 165.56 1141.89 164.59 1143.30 163.89 1143.81 163.35 1143.64 163.37 1142.65 163.51 1142.17 164.41 1142.57 164.40 1142.69 164.61 1142.71 165.51 1143.22 165.98 1144.21 165.95 1144.73 167.39 1144.78 168.85 1144.90 169.57 1144.70 170.95 1144.16 172.46 1143.33 173.17 1142.32 173.68 1141.00 174.65 1138.98 175.11 1137.45 176.07 1136.59 176.77 1134.89 177.11 1133.56 177.55 1131.74 177.07 1130.97 176.09 1129.27 173.99 1128.26 171.90 1126.82 170.38 1124.73 168.66 1124.18 167.26 1122.90 166.54 1121.44 166.05 1120.28 165.72 1118.86 165.21 1117.91 165.20 1117.06 165.21 1116.09 165.21 1114.76 165.28 1113.77 165.26 1112.90 164.96 1112.40 164.50 1112.62 163.46 1114.68 162.39 1113.11 162.01 1109.86 160.53 1107.10 158.76 1107.26 156.82 1105.03 155.86 1102.70 154.86 1100.75 152.94 1098.38 151.95 1096.82 150.85 1094.57 150.11 1092.12 149.69 1090.20 148.71 1088.25 147.70 1086.04 147.73 1083.42 147.06 1081.32 146.46 1078.82 145.37 1076.42 144.74 1074.72 143.49 1073.56 141.56 1075.12 140.12 1076.04 139.95 1079.57 140.01 1085.75 139.31 1091.90 138.32 1097.90 136.79 1102.57 135.46 1100.57 134.95 1095.88 133.41 1091.88 131.41 1089.69 130.53 1085.14 129.14 1080.12 127.69 1076.41 126.31 1074.47 126.17 1070.37 126.08 1065.21 125.35 1059.24 125.83 1054.30 125.57 1050.30 125.83 1048.64 126.34 1049.76 126.55 1051.42 126.50 1050.59 127.54 1047.59 128.54 1045.59 128.54 1044.75 128.41 1044.82 128.32 1043.96 127.70 1041.82 127.39 1039.54 125.38 1038.55 124.19 1037.42 122.65 1034.58 120.23 1030.59 117.40 1025.82 114.94 1023.54 111.84 1022.28 108.45 1021.53 105.40 1020.58 102.41 1021.32 100.54 1020.70 99.24 1022.81 97.73 1025.17 97.17 1027.57 97.36 1031.57 97.36 1037.30 96.82 1041.38 96.75 1039.50 95.48 1035.87 94.90 1039.55 92.98 1040.76 92.51 1038.34 93.26 1035.32 93.25 1034.53 92.46 1033.49 93.21 1031.34 93.05 1033.75 91.68 1037.51 92.28 1037.72 92.56 1038.72 93.56 1037.84 94.74 1033.59 96.90 1027.77 97.93 1024.77 97.93 1020.54 99.07 1016.42 99.22 1012.65 99.35 1010.69 99.69 1007.77 100.61 1005.77 100.61 1001.96 102.10 1000.58 103.18 1000.69 104.63 1002.64 105.97 1003.54 107.19 1002.40 107.12 1000.35 106.66 998.35 106.66 998.14 106.66 999.63 105.66 999.96 104.05 998.31 102.90 994.88 102.19 991.23 101.04 985.91 99.94 982.06 98.76 979.25 98.11 975.37 96.90 968.49 95.71 961.93 95.24 956.84 94.89 950.96 93.52 945.22 92.11 940.03 90.81 935.50 89.37 932.09 88.40 928.92 87.43 926.63 86.25 925.66 85.25 925.18 84.52 924.63 84.56 923.45 84.76 922.44 84.30 921.35 83.97 920.61 83.60 918.24 82.78 914.98 81.90 911.99 80.81 910.63 79.97 909.68 79.15 907.64 78.12 904.82 77.13 902.48 76.11 901.28 75.02 901.16 73.75 901.72 72.76 902.90 71.74 903.53 69.73 904.61 68.66 904.62 66.16 903.14 63.97 901.49 62.38 897.41 59.51 895.72 56.98 893.22 54.71 890.30 51.74 887.75 49.77 885.15 48.12 882.93 47.14 880.08 47.82 876.74 46.81 874.80 45.30 872.26 41.88 869.39 37.33 866.00 32.56 860.35 29.13 855.75 26.72 852.10 24.03 848.83 22.50 844.43 21.77 839.17 20.87 833.21 19.85 826.41 20.81 819.96 22.80 815.19 22.87 809.29 23.34 801.47 25.77 797.44 28.25 791.91 31.40 786.84 35.72 781.46 38.65 777.44 38.24 773.08 33.87 769.91 27.74 767.43 23.94 765.28 22.05 762.77 19.06 760.67 16.79 759.30 15.17 757.78 11.66 755.78 7.66 754.41 3.65 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00
|
||||
1192.10 481.88 1190.62 481.06 1190.22 479.51 1189.85 477.15 1189.91 475.35 1190.69 474.41 1191.03 475.52 1190.50 475.75 1190.95 475.15 1192.09 474.36 1192.75 473.88 1192.65 474.03 1192.04 474.15 1191.81 475.38 1191.99 475.62 1192.03 475.93 1192.09 477.06 1192.59 477.74 1193.26 478.26 1193.93 479.93 1194.28 481.83 1194.71 483.29 1194.69 484.92 1194.39 486.87 1193.87 488.02 1193.00 488.95 1191.88 490.50 1190.01 491.43 1188.75 493.00 1187.88 494.37 1186.49 495.38 1185.25 496.36 1183.38 496.68 1182.81 496.22 1181.63 494.53 1180.99 493.34 1179.79 492.44 1178.27 491.33 1178.17 490.65 1177.51 490.28 1176.62 490.46 1175.91 490.94 1175.30 491.08 1174.69 491.98 1174.29 493.02 1173.76 493.78 1172.86 494.78 1172.11 495.70 1171.78 496.37 1171.85 496.83 1172.68 496.85 1175.33 496.86 1174.83 497.54 1172.64 496.91 1171.40 496.03 1172.62 495.07 1172.10 494.89 1170.86 494.70 1170.43 493.62 1169.52 493.43 1168.97 493.38 1167.54 493.51 1166.25 494.18 1165.45 494.28 1164.35 494.60 1163.28 495.75 1161.82 495.94 1160.71 496.51 1159.32 496.53 1158.22 496.97 1158.04 496.83 1158.44 496.10 1161.31 496.16 1163.91 497.27 1168.71 498.60 1175.83 499.57 1183.63 500.31 1191.59 500.77 1197.63 500.83 1197.38 501.18 1194.28 500.42 1192.55 499.20 1192.18 498.78 1190.24 497.78 1187.85 496.42 1186.86 495.37 1186.59 495.85 1184.69 496.10 1181.64 495.88 1178.15 496.94 1174.36 497.41 1171.64 498.28 1171.18 500.07 1173.19 501.44 1175.15 502.98 1174.98 505.04 1172.52 506.82 1170.65 507.95 1170.25 508.85 1171.10 509.89 1170.67 510.35 1168.52 510.79 1167.10 510.03 1167.25 509.82 1167.67 509.19 1167.19 507.49 1165.76 505.35 1164.29 503.32 1164.38 500.80 1166.31 497.75 1167.84 495.20 1169.70 492.70 1170.87 490.94 1172.44 490.00 1174.46 488.93 1176.95 488.65 1179.71 488.93 1183.60 489.23 1188.28 489.30 1192.49 489.28 1190.68 487.28 1188.70 485.67 1192.30 483.08 1193.92 481.57 1190.03 480.92 1186.25 479.36 1186.25 477.22 1185.34 475.83 1184.14 473.46 1189.07 470.57 1193.10 469.30 1193.81 468.00 1195.27 467.91 1194.40 467.29 1189.48 467.46 1184.44 467.04 1180.30 466.06 1177.17 465.62 1173.77 464.38 1171.94 463.02 1170.85 462.03 1169.85 461.89 1167.98 461.00 1165.18 461.63 1164.37 462.49 1165.37 464.05 1167.64 466.14 1169.45 467.90 1169.64 468.30 1168.96 468.64 1169.45 469.31 1171.89 469.17 1175.86 469.12 1178.79 468.60 1179.50 468.36 1178.84 468.77 1177.07 468.56 1174.48 468.49 1172.94 468.49 1172.36 469.71 1170.39 470.21 1165.60 470.42 1161.21 471.42 1157.68 472.73 1153.71 473.34 1149.78 473.67 1146.62 473.96 1143.96 474.00 1142.17 474.49 1141.14 474.96 1140.70 475.35 1141.50 475.84 1142.50 476.84 1143.26 478.71 1143.29 480.23 1143.71 481.06 1143.83 482.14 1144.21 483.21 1143.21 483.58 1141.56 483.50 1140.04 483.39 1140.06 483.44 1140.10 483.97 1139.31 484.06 1137.38 484.04 1136.22 484.25 1135.94 484.06 1136.98 484.27 1138.29 484.55 1140.05 484.83 1141.41 484.29 1142.59 483.95 1143.09 482.48 1142.80 480.69 1142.25 479.14 1141.25 477.14 1141.05 474.75 1140.40 472.36 1139.99 468.81 1139.40 466.35 1139.06 464.37 1138.66 462.58 1138.06 462.36 1136.91 460.73 1135.92 459.04 1134.55 455.68 1132.57 450.85 1130.20 445.80 1125.33 442.29 1121.38 440.22 1118.98 437.23 1116.60 435.82 1113.14 434.87 1109.14 433.90 1104.43 432.25 1098.53 433.01 1093.06 434.42 1090.50 433.88 1086.49 433.74 1080.34 435.06 1078.18 437.01 1074.21 439.83 1070.69 442.99 1067.26 445.28 1064.92 444.52 1061.76 439.71 1059.25 433.76 1057.01 430.06 1054.94 428.56 1052.97 425.61 1051.34 423.66 1050.13 422.04 1048.81 418.46 1047.33 413.54 1046.28 408.92 1045.39 404.05 1044.12 401.14 1042.60 398.29 1040.66 395.18 1039.33 392.49 1035.64 391.13 1033.70 388.94 1031.49 386.22 1029.49 387.07 1026.12 388.37 1023.36 386.92 1020.31 382.93 1015.24 377.89 1010.33 373.84 1007.15 370.08
|
||||
1138.70 311.08 1137.66 310.36 1137.58 308.42 1137.45 306.24 1137.65 304.36 1138.70 303.33 1139.03 304.36 1138.70 304.52 1139.49 303.68 1140.78 302.90 1141.51 302.28 1141.40 302.44 1140.73 302.49 1140.31 303.45 1140.73 303.56 1140.84 303.77 1141.02 304.82 1141.66 305.33 1142.53 305.53 1143.17 307.00 1143.53 308.72 1143.97 309.84 1143.94 311.38 1143.49 313.07 1143.07 314.12 1142.20 314.77 1141.11 316.16 1139.36 316.74 1138.14 318.02 1137.53 319.04 1135.99 319.69 1134.97 320.34 1133.32 320.41 1132.71 319.58 1131.43 317.67 1130.88 316.16 1129.73 315.01 1128.11 313.61 1127.99 312.63 1127.22 312.13 1126.28 312.04 1125.47 311.99 1124.79 311.92 1124.28 312.26 1123.79 312.87 1123.29 313.26 1122.61 313.73 1122.08 314.22 1121.81 314.39 1121.99 314.39 1122.88 313.88 1125.58 313.29 1124.83 313.35 1122.54 312.32 1120.97 311.13 1122.01 309.64 1121.14 309.07 1119.72 308.50 1118.97 307.07 1117.68 306.38 1117.16 305.97 1115.63 305.74 1114.31 305.81 1113.34 305.40 1112.33 305.09 1111.21 305.74 1109.55 305.51 1108.38 305.34 1107.06 304.80 1105.72 304.83 1105.26 304.19 1105.37 302.82 1108.01 302.14 1110.50 302.55 1115.06 303.23 1122.22 303.26 1129.63 303.03 1137.11 302.49 1142.98 301.77 1142.43 301.69 1138.90 300.53 1136.64 298.97 1135.66 298.22 1132.99 297.12 1129.69 295.52 1128.08 294.26 1127.26 294.43 1124.80 294.41 1121.20 293.90 1117.18 294.43 1113.10 294.52 1110.08 295.08 1109.61 296.08 1111.66 296.76 1114.03 297.39 1114.03 298.86 1111.98 300.24 1110.50 300.79 1110.45 301.03 1111.31 301.48 1110.86 301.45 1109.00 301.39 1107.74 300.14 1107.63 299.33 1107.64 298.28 1106.42 296.16 1104.10 293.53 1101.52 291.21 1100.47 288.43 1101.34 285.16 1101.74 282.20 1102.57 279.63 1103.34 277.81 1104.74 276.75 1106.72 275.54 1109.25 275.15 1112.35 275.31 1116.37 275.46 1121.37 275.46 1125.98 275.29 1124.10 273.63 1121.93 272.47 1125.39 270.17 1127.03 269.14 1123.55 269.21 1119.85 268.41 1119.78 266.86 1118.58 266.54 1116.93 265.36 1121.24 262.98 1124.86 262.36 1125.25 261.71 1126.69 262.09 1125.80 262.16 1120.95 263.24 1116.00 263.39 1111.73 263.02 1108.39 263.02 1104.80 262.45 1102.54 261.58 1100.99 261.20 1099.84 261.28 1097.67 260.78 1094.63 261.56 1093.73 262.47 1094.76 263.86 1097.14 265.37 1099.00 266.57 1099.00 266.58 1098.00 266.58 1097.94 266.59 1099.47 265.78 1102.96 264.83 1105.01 263.78 1105.01 262.78 1103.80 262.45 1101.70 261.51 1098.35 260.91 1096.50 260.28 1095.50 260.28 1093.55 259.78 1088.53 259.39 1083.93 259.53 1080.49 259.92 1076.53 259.50 1072.44 258.90 1069.10 258.47 1066.17 257.52 1064.27 257.43 1063.08 257.12 1062.53 256.37 1063.11 255.89 1064.11 255.89 1064.94 257.04 1065.00 257.98 1065.00 257.98 1065.19 258.10 1065.96 258.44 1064.75 258.27 1062.81 257.39 1061.39 256.78 1061.24 256.24 1061.24 256.24 1060.67 255.45 1059.09 254.78 1057.77 254.32 1057.60 253.62 1058.91 252.94 1060.65 252.81 1062.66 252.18 1064.66 250.66 1066.18 250.18 1067.11 248.31 1066.37 246.35 1066.28 244.64 1065.18 242.30 1064.74 239.67 1063.67 237.28 1062.38 233.79 1061.32 231.30 1060.28 229.51 1059.28 227.85 1057.97 227.90 1055.98 225.91 1055.18 224.39 1053.90 220.98 1051.85 216.38 1049.00 211.50 1044.31 207.78 1040.31 205.78 1038.33 203.12 1036.11 201.50 1032.11 200.50 1028.39 199.23 1023.50 197.89 1017.69 198.56 1012.10 200.17 1008.47 199.45 1004.45 199.02 997.65 201.38 994.97 202.94 990.32 205.29 986.59 208.92 982.57 211.66 979.55 211.08 975.92 206.29 973.27 200.52 971.48 196.69 969.93 194.98 968.36 191.79 966.71 189.15 965.92 187.95 964.37 184.30 963.45 179.19 962.51 175.62 961.02 170.06 959.44 167.40 957.85 164.71 956.08 162.36 954.28 160.25 949.74 158.65 947.88 157.46 945.12 155.06 942.12 156.07 939.20 158.58 935.43 157.79 931.67 154.94 926.10 151.19 920.59 148.42 916.82 145.61
|
||||
318.19 303.95 317.37 301.96 317.77 298.87 317.77 295.92 318.27 293.40 319.37 291.92 319.86 292.40 319.88 291.91 320.78 290.45 322.36 289.15 323.05 288.63 322.99 288.61 322.36 289.04 321.86 290.19 322.31 290.11 322.19 289.72 322.13 290.27 322.53 290.14 323.05 289.27 323.31 290.33 322.88 292.17 322.40 293.19 321.80 294.66 320.68 295.99 319.48 296.91 318.01 297.29 316.04 298.22 313.51 298.38 311.44 299.10 309.91 299.28 307.70 299.61 305.72 299.59 303.26 298.58 301.92 297.53 299.82 296.46 298.37 294.84 296.55 293.50 294.10 292.57 293.14 292.09 292.00 292.20 290.28 292.08 288.86 292.19 287.32 292.76 286.08 293.14 284.95 293.40 283.46 293.53 282.10 293.66 280.55 293.24 279.66 292.86 279.19 292.85 279.35 292.61 281.35 292.21 279.84 293.61 276.84 293.61 274.44 294.06 274.92 294.12 273.22 295.49 271.29 296.40 269.68 296.41 267.67 297.10 266.48 297.64 264.39 297.74 262.26 298.74 260.33 298.90 258.79 298.96 257.21 300.03 254.82 300.93 252.85 301.39 251.01 301.17 249.31 302.44 248.32 303.44 248.24 303.36 250.40 304.17 252.51 305.90 256.97 306.87 263.62 307.55 270.32 308.86 276.80 310.88 281.84 311.33 281.04 312.72 277.44 313.75 274.99 315.18 274.24 317.21 271.67 320.13 268.69 322.93 267.32 325.53 266.90 328.30 264.57 331.27 261.00 334.21 257.00 337.20 252.40 339.26 249.40 341.75 248.93 343.29 250.88 344.05 252.91 344.09 252.85 345.51 250.38 345.98 248.97 345.09 248.59 344.65 249.57 345.08 249.02 345.11 246.98 344.40 245.41 343.35 244.91 343.63 244.42 344.64 242.98 345.23 240.05 346.75 237.08 349.29 235.53 351.27 236.07 352.73 236.57 354.37 237.73 355.23 238.79 356.10 240.60 356.00 243.00 355.35 246.13 354.91 250.05 354.41 255.00 353.52 260.56 352.39 265.80 351.90 265.08 351.59 264.09 352.07 269.09 350.86 272.14 350.29 270.39 349.58 268.70 348.76 270.61 348.91 271.89 350.51 272.91 351.60 279.72 352.77 285.59 355.02 288.28 356.07 291.77 357.58 293.17 358.41 290.30 360.08 287.48 361.13 285.36 362.13 283.98 364.04 282.35 365.86 282.04 367.98 282.56 369.94 283.14 371.54 282.70 372.90 281.16 375.39 281.29 376.88 283.42 378.29 286.26 379.45 288.26 380.89 288.80 382.27 287.77 383.81 287.77 385.81 289.41 387.95 292.41 389.95 294.78 391.86 294.79 394.16 293.79 396.16 291.75 397.16 288.77 398.95 286.90 400.41 286.26 401.64 284.17 402.17 279.47 403.37 275.00 404.85 271.69 405.50 268.17 405.59 264.28 406.26 261.34 407.19 259.08 407.57 257.61 408.13 256.63 409.11 256.16 409.41 256.97 409.94 258.18 410.47 258.87 411.40 258.97 412.13 259.50 413.12 259.84 413.93 260.48 414.30 259.77 414.71 258.36 415.86 257.73 416.48 258.28 416.95 258.93 416.94 258.85 416.78 257.86 416.75 257.31 416.67 257.94 416.22 260.32 416.04 262.73 415.14 265.73 414.14 268.63 414.61 270.73 415.10 272.67 413.21 273.91 412.30 274.75 411.90 275.35 410.92 276.46 410.36 277.03 410.47 277.78 410.70 278.50 411.60 279.39 412.29 280.35 412.88 281.18 416.44 281.42 418.06 282.02 417.69 282.19 416.05 281.82 413.04 281.22 410.02 278.07 407.64 275.71 406.25 274.81 404.80 274.21 404.30 272.29 404.34 270.26 405.33 267.26 405.90 263.26 407.88 259.40 410.95 258.47 413.42 256.10 415.93 251.47 420.47 250.80 424.51 248.57 429.35 246.50 435.21 244.36 440.08 243.31 441.66 242.00 440.51 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00
|
||||
888.03 187.52 886.91 186.47 886.94 184.09 886.70 181.69 886.81 179.51 887.91 178.23 888.10 179.26 887.63 179.20 888.30 178.16 889.48 177.18 889.98 176.64 889.57 176.72 888.72 176.97 888.21 178.11 888.21 178.11 888.14 178.14 887.97 179.07 888.40 179.04 888.96 178.99 889.23 180.32 888.89 182.08 888.51 183.09 888.06 184.39 887.08 185.91 885.85 186.56 884.36 187.08 882.52 188.10 880.09 188.53 878.19 189.40 876.84 189.96 874.44 190.41 872.60 190.62 870.10 190.21 868.79 189.05 866.69 187.08 865.14 185.08 863.15 183.65 860.62 182.12 859.46 181.14 857.71 180.68 855.78 180.56 854.29 180.23 852.31 180.25 850.78 180.31 849.43 180.52 847.54 180.70 845.64 180.77 844.02 180.81 842.46 180.50 841.33 180.02 840.64 179.35 841.65 178.42 839.37 178.87 835.37 177.94 831.94 176.93 831.19 175.51 828.64 175.44 825.54 175.23 823.09 174.19 819.84 174.11 817.38 173.55 814.16 173.15 811.16 173.37 808.25 173.00 805.69 172.39 802.87 172.86 799.34 172.88 796.47 172.92 793.60 171.99 790.32 172.14 787.89 172.11 786.29 170.77 786.75 170.29 787.59 170.91 790.59 171.91 795.74 171.96 801.24 171.86 806.40 171.81 810.24 170.99 807.79 171.11 802.75 170.82 798.68 170.40 795.73 170.81 791.31 171.31 785.91 171.59 782.25 171.79 779.51 172.88 775.11 173.94 769.58 174.98 764.19 176.49 758.19 177.26 753.72 178.31 751.71 179.49 752.31 179.99 753.32 179.98 751.99 181.08 749.97 181.43 746.71 182.01 745.58 181.71 745.59 181.83 744.11 181.58 741.13 181.16 738.93 179.54 737.08 178.89 735.45 178.46 732.46 177.57 729.41 176.30 723.53 176.11 720.60 175.29 719.32 173.89 718.19 172.78 717.85 171.31 717.62 170.66 720.86 170.39 720.16 168.82 722.55 168.35 725.52 168.28 730.10 167.89 736.70 167.33 741.57 167.04 741.13 165.85 737.90 164.45 740.71 163.63 744.62 163.02 741.81 163.49 737.98 163.33 739.01 162.93 738.48 163.94 738.50 164.55 742.91 164.28 746.68 164.26 748.48 166.57 750.50 168.11 750.57 169.09 746.57 171.09 742.57 172.09 740.59 172.62 735.68 174.13 732.68 175.13 730.34 176.02 729.21 177.11 728.11 178.67 725.77 179.49 722.38 181.51 721.58 183.05 722.69 184.69 723.91 186.47 724.63 187.08 724.07 187.85 721.34 189.23 719.71 190.15 719.62 190.69 720.90 190.90 721.88 190.97 720.13 191.56 716.22 192.36 712.01 192.90 706.75 193.11 702.78 193.11 699.71 192.33 696.89 192.28 689.86 192.32 683.21 193.08 677.99 193.35 672.25 193.01 666.39 192.54 661.31 192.36 656.91 191.80 653.51 191.79 650.53 191.90 648.14 191.89 647.19 191.92 646.83 191.95 646.39 192.46 644.99 193.48 643.93 193.74 642.97 194.13 642.27 194.09 639.92 194.08 636.86 194.10 634.26 193.94 633.27 193.90 632.44 193.72 630.62 193.09 628.18 192.62 626.08 192.19 625.05 191.69 625.43 191.18 626.67 190.26 628.09 189.56 629.18 188.11 630.42 187.02 630.91 185.02 630.11 183.44 629.13 182.44 627.70 180.78 626.70 179.31 625.09 178.42 623.31 176.83 621.75 176.30 620.32 175.89 619.28 175.95 617.53 178.29 615.54 178.35 614.73 177.21 612.67 175.14 610.31 171.23 607.90 166.98 602.89 164.18 598.97 162.34 596.42 160.30 594.07 159.25 590.34 158.98 586.19 159.12 581.19 159.12 575.22 160.47 569.64 163.47 566.58 164.41 561.63 165.90 555.14 169.56 552.15 173.08 548.15 177.08 544.08 182.55 539.78 186.43 536.85 186.96 533.69 183.37 531.25 177.99 529.18 174.41 527.50 172.75 525.55 170.23 524.16 168.07 524.02 166.01 522.15 163.33 520.49 158.64 519.49 154.76 518.48 150.73 517.26 148.45 515.39 146.65 513.34 144.81 511.65 143.58 507.62 143.77 505.54 143.65 503.17 143.15 501.25 145.29 498.35 148.71 495.80 149.71 492.76 148.26 488.15 145.95 483.18 144.87 480.32 144.61
|
||||
433.75 206.25 432.83 204.51 433.17 201.69 433.23 198.79 433.52 196.21 434.66 195.00 434.84 195.56 434.84 195.22 435.52 193.77 437.05 192.74 437.80 192.11 437.36 192.22 436.36 192.69 436.00 193.99 436.29 193.86 436.02 193.57 435.87 194.32 436.20 194.21 436.65 193.51 436.92 194.82 436.22 196.63 435.26 197.65 434.59 199.07 433.39 200.50 431.94 201.40 430.19 201.85 428.05 202.60 425.43 203.00 423.02 203.59 421.32 203.91 418.83 204.28 416.66 204.28 413.98 203.31 412.09 202.21 409.57 200.72 407.91 199.22 405.53 197.73 403.06 196.82 401.45 196.21 399.88 196.26 397.98 196.14 395.89 196.26 393.60 196.85 392.36 197.31 390.87 197.78 388.80 197.80 386.84 197.93 384.85 197.66 383.30 197.42 382.49 197.47 381.77 197.10 383.10 196.94 380.78 197.96 377.19 197.95 373.85 198.22 373.37 198.24 370.91 199.39 368.11 200.11 365.67 200.09 363.18 201.06 360.85 201.28 358.20 201.63 355.08 202.35 352.55 202.54 350.10 202.54 347.81 203.53 344.73 204.50 341.98 204.76 339.44 204.75 336.97 205.84 335.23 206.70 334.17 206.61 335.32 207.33 336.65 208.91 340.47 210.37 346.33 210.99 352.27 212.39 357.66 213.99 362.18 214.62 360.33 215.73 355.83 216.78 352.57 217.97 350.73 219.96 347.17 222.54 343.29 225.31 340.82 227.84 339.45 230.56 336.05 233.45 331.43 235.99 326.43 239.00 321.36 241.23 317.47 243.38 316.20 245.37 317.93 246.15 319.36 246.33 318.46 247.58 315.73 248.17 314.05 247.55 313.44 247.16 313.69 247.56 312.69 247.56 310.33 246.91 308.47 245.55 307.58 246.05 306.25 246.67 303.90 247.24 300.36 248.61 296.25 250.75 293.96 252.30 293.50 253.48 293.43 254.90 294.02 255.63 294.57 256.12 295.79 256.01 298.16 255.19 301.45 255.15 305.32 254.61 310.18 254.06 315.85 252.90 320.65 252.45 320.07 252.02 318.89 252.62 323.49 251.48 326.48 251.08 325.10 250.74 323.53 250.26 325.31 250.42 326.42 252.21 326.87 253.46 333.65 254.86 339.19 257.07 341.62 258.58 345.03 260.20 346.27 261.38 343.26 263.39 340.17 264.50 337.72 265.76 335.98 267.86 334.09 269.76 333.38 271.91 333.51 273.82 333.99 275.85 332.69 277.38 330.71 279.89 330.40 281.76 332.06 283.29 334.32 284.77 336.24 286.48 336.25 287.91 334.72 289.47 333.81 291.30 334.42 293.46 336.83 295.49 338.19 297.14 337.27 299.46 335.64 301.48 332.99 302.54 328.93 304.08 326.50 305.57 324.77 306.61 322.02 307.03 316.40 308.11 311.35 309.65 307.39 310.23 302.83 310.26 298.36 310.77 294.76 311.34 291.71 311.65 289.51 312.35 287.76 313.10 286.83 313.52 287.14 314.07 287.66 314.59 287.92 315.39 287.55 316.18 287.54 317.06 287.51 317.81 287.68 318.25 286.53 318.77 284.60 319.78 283.43 320.39 283.83 320.88 283.82 320.90 283.24 320.84 281.70 320.84 280.90 320.72 281.36 320.62 282.96 320.11 285.23 319.48 287.66 318.53 290.33 316.96 292.47 315.69 294.20 313.83 294.82 313.01 295.28 312.56 295.33 311.48 295.86 311.01 295.64 311.23 295.66 311.23 295.89 312.17 296.46 312.90 296.56 313.71 296.81 317.18 296.04 318.50 296.50 318.26 296.09 316.69 295.42 313.68 294.34 310.48 290.91 308.22 288.23 306.83 287.11 305.60 285.81 304.80 283.47 304.90 281.06 305.93 277.42 306.56 273.44 308.54 269.18 311.78 267.52 314.03 264.49 316.47 259.27 320.79 257.52 325.04 254.84 329.85 251.98 335.42 248.98 340.42 247.29 342.12 244.93 339.54 242.93 334.54 241.93 331.54 241.21 330.40 239.21 327.40 239.21 326.40 239.10 324.45 238.20 321.53 237.38 318.43 237.42 314.60 236.43 311.59 235.43 309.59 234.43 308.59 234.62 308.46 233.62 307.46 230.97 308.72 229.97 309.72 228.23 309.93 227.26 312.56 224.54 316.45 222.68 318.41 221.39 318.41 217.51 317.22 213.58 317.24 211.92 318.29
|
||||
654.98 492.15 653.67 490.42 653.49 487.74 653.30 484.84 653.36 482.32 653.99 480.89 654.16 481.47 653.74 481.19 654.16 479.85 655.52 478.64 655.98 478.00 655.78 478.11 654.94 478.40 654.37 479.51 654.48 479.37 654.22 479.26 653.98 480.19 653.98 480.19 654.23 479.86 654.32 481.20 653.93 483.30 653.65 484.76 652.87 486.14 651.57 487.93 650.41 489.00 648.85 489.71 646.74 490.76 644.11 491.43 641.88 492.48 640.12 493.22 637.82 493.94 635.63 494.24 632.94 493.80 631.35 492.76 629.35 491.45 627.79 489.87 625.87 488.61 623.41 487.64 622.55 487.12 621.02 487.16 619.19 487.23 617.67 487.47 615.90 487.85 614.44 488.21 613.19 488.83 611.45 489.27 609.37 489.59 607.32 489.74 605.78 489.64 604.80 489.63 604.66 489.24 606.17 488.69 604.39 489.76 600.88 489.48 598.40 489.42 598.52 488.75 596.84 489.55 594.39 490.02 592.78 489.84 590.47 490.37 588.82 490.59 586.11 490.69 583.42 491.72 581.17 491.92 578.97 491.87 576.78 492.71 574.01 493.68 571.55 494.17 569.26 493.98 566.91 494.71 565.41 495.35 564.82 494.79 566.64 495.15 568.04 496.57 571.60 497.98 577.38 498.48 583.67 499.15 589.95 500.42 594.71 500.53 593.40 501.33 589.29 501.97 586.87 502.49 585.58 503.71 582.94 505.54 580.25 507.18 578.65 508.35 577.85 510.22 575.39 512.34 571.54 514.34 567.37 516.65 562.74 518.49 559.50 520.13 558.36 521.61 559.74 522.56 560.77 522.71 560.16 523.85 557.11 525.04 554.57 524.78 553.62 524.67 553.73 524.98 552.68 525.09 549.76 524.85 547.67 523.45 547.12 523.66 546.63 524.29 544.97 524.55 542.58 525.13 540.18 526.34 539.13 527.25 540.22 527.37 540.97 527.54 542.52 527.40 543.36 527.34 544.83 526.92 546.94 525.77 549.58 525.29 552.90 524.72 557.21 523.88 562.26 522.83 567.01 521.74 566.29 520.53 565.46 520.01 570.29 518.03 573.31 516.72 570.92 516.28 568.95 514.96 570.94 514.02 571.83 514.36 573.01 514.35 580.00 513.71 585.84 514.35 588.50 514.47 591.59 515.01 592.60 515.09 589.50 516.43 586.36 516.59 583.97 516.59 582.50 517.50 580.60 518.19 580.42 518.88 580.64 519.58 580.92 520.77 580.31 521.19 578.21 523.11 578.08 524.40 579.45 525.61 581.50 527.34 582.97 528.69 582.99 529.79 581.96 531.00 581.56 532.55 583.01 534.35 585.99 536.00 587.89 536.93 587.81 538.67 586.49 540.56 583.95 541.34 580.37 542.93 577.99 544.08 576.18 545.51 573.34 546.15 567.72 547.33 562.61 548.82 558.13 549.93 553.48 550.33 548.85 550.88 544.92 551.72 541.90 552.04 539.52 552.67 537.62 553.95 536.16 554.47 536.19 555.20 536.49 556.10 536.32 557.20 535.68 558.62 535.53 559.46 535.30 560.51 535.05 561.08 533.67 561.42 531.77 562.29 530.47 562.61 530.45 562.87 530.23 563.08 529.23 563.05 527.32 562.96 526.20 562.88 526.05 562.54 527.20 561.99 528.75 561.32 530.51 560.78 531.94 559.19 533.45 558.42 534.24 556.50 534.67 555.06 534.74 554.40 534.31 552.90 535.00 551.88 535.21 551.32 535.63 550.16 536.06 550.10 536.38 550.05 536.84 550.23 537.59 552.70 537.46 553.22 537.30 552.49 536.69 550.33 535.82 546.64 534.39 542.80 530.68 540.08 527.60 538.52 526.31 536.51 524.72 535.62 522.28 535.51 519.60 535.77 516.00 535.81 511.41 537.42 507.00 540.48 505.56 541.74 502.76 543.48 497.82 547.55 496.48 551.33 493.92 555.47 491.45 560.89 488.96 565.17 487.56 565.90 485.74 562.76 484.38 557.10 482.69 553.91 481.52 552.31 480.25 549.77 478.92 547.84 478.09 546.27 477.49 543.21 476.41 539.00 476.09 535.24 475.92 531.34 475.16 529.36 474.20 527.85 473.25 526.31 472.24 525.53 469.40 525.95 468.68 525.87 467.41 525.56 466.43 527.77 464.18 531.23 462.76 532.30 461.14 531.07 457.82 528.72 454.73 527.68 453.43 527.47
|
||||
656.00 592.80 654.52 590.94 654.07 588.06 653.73 585.26 653.72 582.72 654.42 581.11 654.54 581.73 653.90 581.38 654.28 579.81 655.51 578.49 655.92 577.88 655.69 577.80 654.88 578.06 654.26 579.29 654.31 579.01 653.98 578.89 653.66 579.77 653.64 579.75 653.63 579.52 653.58 581.02 653.16 582.98 652.63 584.59 651.66 586.34 650.39 587.99 649.07 589.33 647.23 590.18 645.10 591.23 642.40 591.92 640.00 593.02 638.00 594.02 635.59 594.61 633.23 594.97 630.27 594.58 628.66 593.87 626.68 592.49 624.99 591.03 622.83 590.09 620.40 589.08 619.42 588.40 617.96 588.55 615.88 588.68 613.98 589.12 612.27 589.58 610.78 590.01 609.16 590.65 607.13 591.05 604.94 591.64 602.66 592.01 600.67 591.95 599.74 591.87 599.16 591.33 600.53 591.03 598.56 592.05 595.32 591.87 592.82 591.87 592.89 591.20 591.20 592.02 588.77 592.64 586.91 592.63 584.60 593.12 582.68 593.44 580.01 593.50 577.24 594.59 574.80 594.95 572.32 594.96 569.88 595.88 567.11 596.87 564.47 597.42 561.89 597.23 559.44 598.15 557.96 598.97 557.12 598.46 558.56 598.97 560.20 599.96 563.27 601.52 568.95 601.76 575.15 602.59 581.37 603.95 586.02 604.29 584.53 605.40 580.51 605.95 578.15 606.34 577.05 607.72 574.59 609.62 572.03 611.18 570.96 612.61 569.90 614.55 567.55 616.82 564.18 618.70 560.12 621.08 555.63 623.04 552.27 624.84 551.20 626.46 551.99 627.36 553.22 627.60 552.07 628.81 548.99 629.90 546.15 629.84 544.83 629.80 544.81 630.31 543.58 630.32 540.51 630.24 538.29 628.83 537.75 629.07 536.98 629.90 535.76 630.32 533.58 630.88 531.45 632.49 530.88 633.24 532.08 633.53 533.45 634.07 535.13 633.84 536.10 633.87 537.63 633.29 539.52 632.33 542.24 631.63 545.10 630.82 549.26 630.01 554.02 628.64 558.69 627.81 558.28 626.19 558.00 625.65 562.74 623.43 565.74 621.94 563.42 621.09 561.53 619.66 563.84 618.32 565.15 618.54 566.75 617.92 574.11 616.83 580.39 617.27 583.26 617.28 586.71 617.55 587.70 617.44 584.89 618.51 581.93 618.34 579.80 618.12 578.40 619.08 577.09 619.39 577.15 619.89 577.86 620.36 578.18 621.42 577.76 621.51 575.81 623.30 575.71 624.60 576.80 625.86 578.75 627.33 580.30 628.82 580.35 630.00 579.10 631.26 578.75 632.98 580.43 634.85 583.32 636.50 585.36 637.79 585.43 639.51 584.02 641.48 581.49 642.78 578.05 644.20 575.57 645.67 573.57 647.21 570.34 648.02 564.80 649.30 559.54 650.86 554.67 652.34 549.62 652.93 544.91 653.74 540.90 654.70 537.70 654.92 535.17 655.86 533.03 657.07 531.43 658.03 531.35 658.86 531.40 659.76 530.95 660.94 529.76 662.48 529.44 663.69 529.20 664.65 528.75 665.27 527.20 666.07 525.40 666.90 524.08 667.15 523.86 667.50 523.38 667.84 522.37 667.73 520.37 667.74 518.79 667.78 518.43 667.54 519.65 666.89 520.64 666.37 522.28 665.55 523.35 664.09 524.56 663.07 525.15 661.40 525.48 659.90 525.46 659.25 525.11 657.63 525.68 656.47 526.03 655.87 526.75 654.62 527.37 654.73 527.93 654.67 528.61 654.55 529.40 657.28 529.44 657.81 529.44 656.97 529.15 654.48 528.42 650.55 527.19 646.62 523.33 643.95 520.33 642.56 518.74 640.70 517.40 639.25 514.73 639.23 512.11 639.52 509.03 639.28 504.32 640.65 500.00 644.01 498.59 645.99 496.05 647.17 491.30 651.09 490.15 655.16 487.56 659.38 485.13 664.71 482.83 669.14 481.82 669.68 480.04 666.21 478.48 661.05 476.82 657.78 475.54 656.16 474.26 653.62 472.96 651.46 471.72 650.33 471.14 646.62 470.10 642.72 469.75 638.91 469.65 635.15 469.01 632.96 468.36 631.54 467.35 630.17 466.74 629.36 464.11 629.56 463.47 629.63 462.59 629.46 461.57 630.99 459.45 634.44 458.39 635.92 457.39 633.92 454.09 631.65 451.38 630.89 450.40 630.28
|
||||
807.45 580.79 806.12 579.45 805.49 576.74 805.05 573.93 804.95 571.51 805.81 570.17 805.93 571.05 805.20 570.87 805.65 569.58 806.56 568.52 807.06 567.86 806.73 567.93 806.26 568.14 805.76 569.19 805.79 569.17 805.52 569.02 805.15 570.08 805.19 570.45 805.43 570.26 805.56 571.84 805.25 574.05 805.04 575.65 804.34 577.58 803.42 579.23 802.13 580.70 800.72 581.49 798.86 582.73 796.26 583.57 794.29 584.94 792.66 585.89 790.44 586.84 788.40 587.46 785.69 587.36 784.23 586.79 782.33 585.35 781.16 583.82 779.31 582.80 777.10 581.85 776.15 581.53 775.06 581.57 773.12 581.99 771.56 582.31 770.33 582.77 768.78 583.49 767.46 584.15 765.96 584.82 764.18 585.48 762.06 586.06 760.48 586.17 759.69 586.65 759.62 586.36 761.07 586.28 759.63 587.27 756.36 586.98 754.19 586.88 754.59 586.20 753.11 586.92 750.93 587.47 749.43 586.95 747.47 587.67 746.11 587.81 743.52 588.22 741.01 589.44 739.03 589.82 736.93 589.85 734.76 591.04 732.13 591.96 729.73 592.67 727.47 592.55 725.35 593.53 724.21 594.14 723.62 593.70 725.36 594.15 726.79 595.69 730.60 597.06 736.15 597.96 742.57 598.82 749.10 600.13 754.06 600.35 752.94 601.19 748.87 601.70 746.65 601.86 745.92 602.88 743.64 604.05 741.11 604.98 739.86 605.79 739.27 607.48 737.08 609.18 733.37 610.70 729.58 612.76 725.28 614.38 722.03 615.96 720.91 617.92 722.04 618.83 723.12 619.44 722.12 620.94 719.19 622.34 716.43 622.57 715.31 622.64 715.36 623.27 714.22 623.58 711.22 623.58 709.03 622.69 708.63 622.93 708.34 623.40 707.02 623.32 705.15 623.38 703.25 624.24 702.85 624.54 704.33 623.85 705.83 623.46 707.47 622.80 708.60 622.48 709.90 622.13 711.86 621.05 714.38 620.60 717.36 620.11 721.25 619.50 725.89 618.57 730.53 617.76 729.58 615.83 728.74 614.79 733.32 612.33 735.90 611.12 733.28 609.99 730.91 608.61 732.88 606.84 733.56 606.46 734.54 605.45 741.52 603.63 747.05 603.71 749.56 603.22 752.56 603.35 753.13 602.89 749.78 603.52 746.41 603.28 743.85 602.80 742.02 603.10 740.02 603.07 739.83 602.93 739.85 602.95 740.03 603.56 739.51 603.52 737.43 604.89 736.96 606.24 737.82 607.71 739.83 609.38 741.45 611.04 741.51 611.94 740.07 613.25 739.94 614.70 741.94 616.14 745.06 617.75 747.23 618.68 747.43 620.23 746.24 621.84 743.79 622.76 740.27 624.12 737.86 625.50 736.33 627.32 733.21 628.15 727.86 629.27 722.57 631.20 717.89 632.64 713.09 633.53 708.58 634.08 704.48 635.11 701.34 635.69 698.77 636.71 696.85 638.15 695.40 639.05 695.38 640.06 695.46 641.10 695.32 642.74 694.28 644.68 694.06 645.72 693.52 647.10 693.18 647.84 691.81 648.62 689.93 649.44 688.57 649.48 688.44 649.80 687.84 650.48 686.53 650.50 684.41 650.67 683.01 650.87 682.52 650.75 683.58 650.58 684.36 650.18 686.08 649.68 686.73 648.91 687.93 648.27 688.55 646.43 688.58 645.01 688.47 644.30 687.62 642.72 688.14 641.32 688.26 640.51 688.59 638.62 688.84 638.23 689.23 637.82 689.66 637.72 690.48 639.55 690.10 639.59 689.74 638.53 688.98 635.95 688.18 631.62 686.49 627.37 682.40 624.52 679.28 622.82 677.50 620.79 675.48 620.07 672.94 619.71 669.92 619.58 666.41 619.18 661.61 620.16 656.98 623.41 655.37 624.58 652.68 625.26 647.50 629.13 646.37 632.64 643.56 636.31 640.82 641.65 638.36 645.62 637.15 646.16 635.15 642.16 633.12 636.56 631.11 633.44 629.71 631.95 628.52 629.15 626.64 627.56 625.66 625.99 624.65 622.47 623.83 618.16 623.14 614.26 622.86 610.05 621.86 608.05 621.22 606.15 619.90 604.32 619.45 602.75 616.49 602.85 615.52 602.42 614.69 601.48 613.24 603.41 610.98 606.57 609.84 607.00 608.54 604.35 604.93 601.41 601.91 599.85 600.61 598.54
|
||||
914.61 501.71 913.24 500.38 912.64 498.11 912.44 495.42 912.41 493.23 913.41 491.94 913.52 492.96 913.04 492.91 913.40 491.65 914.50 490.74 914.94 490.13 914.98 490.26 914.15 490.48 913.70 491.62 913.86 491.63 913.66 491.69 913.71 492.78 914.11 493.23 914.57 493.28 914.79 494.76 914.79 496.76 914.78 498.22 914.65 499.97 913.77 501.82 912.72 502.90 911.68 503.87 910.35 505.17 908.09 506.05 906.25 507.36 905.10 508.51 903.26 509.28 901.62 510.04 899.27 509.92 898.23 509.26 896.64 507.67 895.74 506.44 894.38 505.31 892.44 504.43 892.06 503.80 890.95 503.74 889.61 504.07 888.50 504.41 887.32 504.67 886.33 505.26 885.33 506.18 884.28 506.75 882.80 507.34 881.75 508.06 880.49 508.50 880.26 508.72 880.45 508.51 882.88 508.23 881.53 509.13 878.93 508.80 877.15 508.33 878.02 507.44 876.83 507.86 874.98 508.22 873.87 507.60 872.48 508.03 871.17 508.21 869.17 508.50 867.38 509.29 865.77 509.48 864.24 509.62 862.74 510.92 860.65 511.50 858.79 512.15 857.12 512.09 855.20 512.90 854.51 513.34 854.57 512.76 856.49 512.98 858.66 514.19 862.75 515.84 868.98 516.57 876.03 517.44 882.99 518.15 888.46 518.23 887.56 518.99 883.84 519.05 881.82 518.79 881.24 519.52 879.19 520.13 876.62 520.30 875.60 520.40 875.06 521.87 873.06 522.87 869.80 524.13 865.76 525.73 861.86 526.84 858.97 528.24 858.28 529.78 859.66 530.90 861.33 531.52 860.76 533.25 858.01 534.60 856.04 535.15 854.94 535.48 855.54 535.94 854.67 536.23 852.22 536.40 850.29 535.55 849.93 535.56 849.94 535.62 849.12 535.18 847.42 534.40 845.53 534.24 845.18 533.60 846.51 532.41 847.71 531.33 849.39 530.10 850.40 529.35 852.11 528.92 854.11 527.92 856.57 527.50 859.50 527.32 863.55 527.10 868.37 526.57 872.76 525.95 871.76 524.11 870.32 522.73 874.61 520.39 876.97 519.04 873.88 518.47 871.11 517.20 872.28 515.42 872.52 514.97 872.41 513.72 878.63 511.86 883.68 511.56 885.60 511.06 888.03 511.14 888.02 510.86 884.17 511.41 880.22 511.28 877.04 510.66 875.03 510.67 872.40 510.37 871.69 510.00 871.39 509.93 871.14 510.39 869.87 510.20 867.61 511.34 867.17 512.58 868.17 513.85 870.46 515.71 872.33 517.39 872.37 518.03 871.40 518.89 871.61 520.19 873.61 521.15 877.17 522.12 879.41 522.46 879.71 523.36 878.90 524.59 876.81 525.16 873.77 526.20 871.76 527.12 870.57 528.65 867.98 529.32 863.09 530.14 858.31 531.57 854.46 533.17 849.95 533.75 845.59 534.28 842.37 534.98 839.37 535.43 837.38 536.05 835.80 537.40 834.81 537.94 835.46 538.82 836.46 539.82 836.40 541.67 835.91 543.31 836.09 544.32 836.09 545.32 836.07 546.32 834.77 546.66 833.03 547.05 831.71 547.20 831.73 547.48 831.67 547.97 830.72 548.11 829.06 548.12 827.72 548.28 827.53 548.19 828.54 548.14 829.93 547.85 831.63 547.72 832.97 546.83 834.55 546.53 834.83 544.91 835.09 543.48 834.89 542.54 834.22 540.93 834.60 539.42 834.59 538.06 834.52 535.88 834.86 534.78 834.91 533.82 835.19 533.43 835.57 534.87 834.77 534.30 834.50 533.36 833.19 530.71 831.58 526.48 830.03 522.10 826.03 519.10 822.93 517.25 821.11 514.96 819.22 513.85 816.34 513.50 813.19 513.20 809.36 512.59 803.76 513.82 799.53 516.26 798.14 516.74 794.45 517.65 789.09 520.66 787.68 523.76 784.48 527.25 781.75 532.04 779.47 535.50 777.91 535.59 774.74 531.52 772.59 525.98 771.88 522.43 770.31 520.95 768.61 518.15 767.44 516.44 766.39 515.14 765.17 511.73 763.87 507.26 763.02 503.35 762.81 498.86 762.04 496.51 761.03 494.50 759.46 492.29 758.71 490.78 755.58 490.50 754.34 489.30 753.14 488.20 751.38 489.74 749.22 492.55 747.30 492.54 744.70 489.88 740.75 486.70 737.23 484.27 735.50 482.52
|
||||
771.03 553.78 769.60 552.14 769.15 549.42 768.82 546.47 768.77 543.96 769.51 542.69 769.63 543.33 769.06 543.33 769.46 541.64 770.60 540.73 771.10 540.16 770.83 540.36 770.07 540.30 769.62 541.37 769.64 541.34 769.37 541.46 769.13 542.40 769.15 542.57 769.38 542.47 769.47 543.83 769.22 546.06 768.96 547.80 768.27 549.61 767.23 551.32 766.02 552.48 764.47 553.35 762.54 554.37 759.98 555.51 757.84 556.61 756.21 557.39 753.91 558.39 751.86 558.84 749.24 558.56 747.78 557.83 745.93 556.48 744.54 555.02 742.60 553.98 740.37 552.97 739.54 552.56 738.17 552.69 736.37 552.87 734.87 553.32 733.38 553.66 732.00 554.63 730.60 555.03 729.01 555.48 727.11 556.17 725.21 556.62 723.62 556.72 722.76 556.98 722.47 556.62 724.09 556.65 722.45 557.38 719.26 557.00 717.00 556.96 717.26 556.50 715.68 557.01 713.53 557.53 711.91 557.41 709.85 557.78 708.21 558.28 705.65 558.48 703.18 559.37 701.11 559.70 698.99 559.65 696.80 560.65 694.23 561.49 691.76 562.35 689.40 562.21 687.21 563.18 685.90 563.73 685.34 563.32 687.09 563.71 688.60 565.09 692.17 566.39 697.87 567.28 704.27 567.77 710.80 569.22 715.56 569.30 714.24 570.40 710.29 570.76 708.06 570.90 707.02 572.20 704.58 573.31 702.01 574.39 700.72 575.37 699.79 577.20 697.46 579.08 694.01 580.72 690.03 582.78 685.60 584.40 682.27 586.12 681.24 587.77 682.29 588.44 683.44 589.04 682.54 590.51 679.44 591.93 676.86 591.96 675.63 592.25 675.80 592.65 674.70 593.16 671.79 592.88 669.69 591.86 669.02 592.15 668.53 592.62 667.38 592.71 665.25 592.70 663.25 593.70 662.63 593.75 663.93 593.58 665.10 593.29 666.60 592.66 667.74 592.53 669.11 591.94 671.08 590.96 673.65 590.37 676.58 589.71 680.63 589.19 685.42 588.12 690.03 587.47 689.18 585.57 688.46 584.54 693.04 582.14 695.80 581.06 693.24 579.92 690.85 578.82 692.69 577.27 693.70 576.92 694.58 576.39 701.44 574.70 707.19 574.97 709.66 574.61 712.58 575.12 713.28 574.64 710.10 575.31 706.55 575.36 703.98 574.95 702.47 575.41 700.56 575.43 700.19 575.53 700.40 576.06 700.58 576.88 699.60 576.99 697.60 578.42 697.26 579.75 698.46 581.26 700.48 582.78 701.91 584.37 701.91 585.52 700.77 586.55 700.51 588.35 702.13 589.58 705.30 591.11 707.35 592.23 707.41 593.68 706.00 595.36 703.52 596.28 700.14 597.46 697.82 599.04 696.02 600.61 692.99 601.58 687.57 602.44 682.35 604.03 677.78 605.54 672.86 606.16 668.22 606.73 664.29 607.64 661.05 608.32 658.57 609.36 656.58 610.47 655.18 611.10 655.14 612.27 655.34 612.94 655.10 614.65 654.21 616.25 654.02 617.19 653.58 618.45 653.21 619.29 651.86 619.67 650.04 620.48 648.48 620.78 648.32 621.06 647.97 621.47 646.84 621.29 644.81 621.34 643.37 621.38 642.98 621.36 643.95 620.92 645.14 620.55 646.63 619.92 647.84 618.71 648.80 618.22 649.50 616.35 649.64 614.85 649.58 613.95 648.85 612.51 649.26 611.34 649.41 610.22 649.75 609.14 650.29 608.27 650.55 607.79 650.83 607.98 651.46 609.86 651.19 610.11 650.86 609.63 650.42 606.86 649.27 602.52 647.81 598.29 643.81 595.47 640.55 593.80 638.81 592.11 637.15 591.04 634.41 590.34 631.54 590.51 628.00 590.30 623.02 591.55 618.53 594.54 617.08 596.09 614.19 596.74 609.07 600.52 607.80 604.33 605.06 608.20 602.41 613.25 599.88 617.75 598.50 618.37 596.58 614.31 594.80 608.83 592.94 605.66 591.49 604.12 590.24 601.34 588.71 599.90 587.64 598.20 586.76 594.81 585.80 590.43 585.31 586.54 584.99 582.43 584.12 580.78 583.35 578.67 582.21 576.75 581.36 575.63 578.52 575.87 577.65 575.33 576.61 574.23 575.37 576.53 573.05 579.89 571.82 580.35 570.31 578.02 566.84 575.38 563.75 573.70 562.36 573.02
|
||||
-1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 396.90 459.98 397.89 458.31 398.39 458.76 398.23 458.28 398.93 456.43 400.53 455.18 401.30 454.54 401.21 454.40 400.67 454.88 400.58 455.98 400.85 455.73 400.79 455.42 400.76 456.02 401.07 455.92 401.73 455.14 402.00 456.14 401.76 458.08 401.68 459.24 400.99 460.66 400.08 462.20 398.96 463.26 397.89 463.76 395.98 464.66 393.76 465.19 391.94 465.95 390.57 466.43 388.68 466.80 387.00 466.80 384.74 465.94 383.58 465.34 382.04 464.16 380.84 462.55 379.28 461.17 377.25 460.24 376.80 459.72 375.89 459.87 374.43 459.75 373.41 459.85 372.59 460.30 371.68 460.67 371.05 460.90 369.83 461.27 368.63 461.34 367.63 461.13 366.88 460.62 366.90 460.63 367.55 460.36 370.18 460.01 369.12 460.95 366.91 460.85 365.26 461.19 366.54 461.09 365.57 462.17 364.12 462.75 363.40 463.02 361.98 463.53 361.38 464.03 359.85 464.29 358.34 465.24 356.98 465.29 355.88 465.41 354.91 466.35 353.22 467.20 351.66 467.61 350.42 467.44 349.16 468.60 348.97 469.12 349.57 469.14 352.29 469.65 355.19 471.37 359.69 472.35 366.78 472.45 374.26 473.79 381.71 475.16 387.56 475.55 387.19 476.71 384.14 477.67 382.72 478.71 382.56 480.62 381.03 483.09 379.18 485.45 378.71 487.45 378.70 489.57 377.28 492.38 374.69 494.90 371.49 497.48 367.72 499.57 365.41 501.55 365.37 503.13 367.69 503.66 369.90 503.65 370.01 504.66 368.08 505.44 366.42 504.79 366.41 504.27 367.30 504.70 366.90 504.70 364.92 504.18 363.91 502.76 363.83 503.28 363.85 504.20 363.15 504.85 361.21 506.16 359.21 508.15 358.93 509.70 360.43 510.75 362.02 512.09 364.02 512.56 365.24 513.07 367.03 513.04 369.66 512.16 372.96 511.80 376.49 511.24 381.05 510.32 386.41 509.05 391.47 508.20 390.79 507.39 390.28 507.46 394.93 505.84 397.93 504.88 395.52 504.08 393.67 503.12 395.67 502.65 397.07 503.42 398.06 503.96 405.16 503.97 411.18 505.31 413.95 505.59 417.41 506.49 418.59 506.66 415.71 508.00 412.87 508.36 410.76 508.86 409.37 510.23 408.37 511.23 408.39 512.57 409.23 513.69 410.14 515.10 409.83 515.68 408.35 517.67 408.94 519.13 410.91 520.11 413.82 521.37 416.11 522.52 416.88 523.58 416.59 524.99 416.94 526.54 419.52 528.35 423.31 530.35 426.32 531.85 427.32 533.81 426.83 535.78 425.41 536.63 423.23 538.38 422.19 539.60 421.69 541.10 420.22 541.71 416.09 543.12 412.25 544.94 409.42 545.59 405.96 546.16 402.86 546.74 400.27 547.73 398.64 548.19 397.49 548.88 396.62 550.03 396.64 550.55 397.82 551.28 399.16 552.07 400.04 553.19 400.27 554.23 401.15 555.26 401.69 556.18 402.36 556.84 402.18 557.12 401.38 558.14 400.82 558.44 401.74 558.78 402.53 559.16 402.45 558.93 401.49 558.74 401.29 558.61 402.16 558.29 404.28 557.71 406.69 556.76 409.66 556.24 412.10 554.80 414.45 553.83 416.27 551.88 417.61 550.81 418.63 550.37 419.27 549.16 420.60 548.61 421.58 548.25 423.06 547.72 424.08 548.27 425.15 548.78 426.66 549.10 427.67 552.24 428.45 553.18 428.93 552.71 429.35 551.12 429.34 547.55 428.91 544.23 425.74 541.83 423.75 540.33 422.78 538.90 422.05 538.14 419.97 538.29 417.98 538.76 414.88 539.13 410.33 541.10 406.67 544.26 405.16 546.18 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00
|
||||
304.33 468.99 303.55 466.90 303.70 463.65 303.92 460.62 304.31 457.90 305.47 456.37 306.04 456.78 305.85 456.10 306.81 454.58 308.36 452.98 309.25 452.32 309.13 452.30 308.58 452.65 308.29 453.76 308.70 453.53 308.70 453.04 308.65 453.64 308.92 453.27 309.39 452.43 309.53 453.44 309.26 455.34 308.89 456.68 308.22 457.94 307.23 459.42 306.16 460.28 304.66 460.70 302.95 461.46 300.50 461.80 298.51 462.56 297.06 462.81 294.95 463.14 293.12 463.00 290.66 462.15 289.45 461.18 287.71 460.26 286.59 458.61 284.95 457.29 282.82 456.31 282.27 455.81 281.25 455.83 279.71 455.49 278.45 455.61 277.46 456.21 276.42 456.53 275.45 456.82 274.31 456.92 273.05 456.90 271.71 456.55 270.95 456.00 270.86 455.78 271.42 455.41 273.82 454.94 272.75 455.98 270.24 456.03 268.75 456.50 269.74 456.44 268.84 457.75 267.36 458.51 266.42 458.53 265.05 459.30 264.35 459.73 262.71 459.79 260.87 460.76 259.58 460.85 258.25 460.83 257.31 461.68 255.57 462.46 253.84 462.85 252.59 462.72 251.32 463.85 250.89 464.66 251.42 464.38 254.11 465.23 256.70 466.63 261.58 467.54 268.48 467.67 275.96 469.08 283.00 470.67 288.95 471.13 288.52 472.20 285.44 473.36 283.91 474.56 283.65 476.52 282.01 479.23 280.20 481.84 279.81 484.36 279.91 486.87 278.44 489.71 275.73 492.42 272.40 495.23 268.64 497.56 266.23 499.73 266.18 501.44 268.31 501.95 270.68 501.88 270.62 502.92 268.63 503.57 267.10 502.58 266.84 502.22 267.77 502.29 267.59 502.29 265.42 501.73 264.13 500.50 264.13 500.92 264.18 501.86 263.35 502.53 261.60 504.15 259.54 506.68 258.94 508.61 260.40 510.09 261.82 511.64 263.68 512.51 265.21 513.20 267.11 513.15 269.54 512.34 272.80 511.80 276.52 511.11 281.25 510.32 286.70 508.83 291.72 508.16 291.21 507.43 290.68 507.88 295.74 506.35 298.81 505.43 296.86 504.54 295.14 503.48 297.35 503.20 298.87 504.35 300.07 504.91 307.57 505.49 313.74 507.12 316.75 507.90 320.31 508.80 321.73 509.31 319.24 510.76 316.30 511.27 314.50 511.90 313.52 513.58 312.29 514.78 312.66 516.61 313.53 518.04 314.61 519.24 314.43 520.45 313.13 522.41 313.77 523.80 315.77 524.80 318.75 525.92 321.00 527.14 321.90 528.39 321.46 529.82 321.87 531.62 324.19 533.69 327.99 535.58 330.93 537.16 331.85 539.36 331.39 541.45 330.04 542.52 327.70 544.23 326.49 545.81 326.04 546.98 324.40 547.58 320.28 549.05 316.37 550.67 313.21 551.54 309.81 551.73 306.58 552.41 304.04 553.33 302.17 553.86 301.09 554.58 300.22 555.56 300.13 556.02 301.20 556.83 302.63 557.31 303.36 558.17 303.56 559.22 304.19 560.03 304.79 560.92 305.49 561.39 305.18 561.99 304.25 563.07 303.89 563.55 304.76 563.98 305.59 564.06 305.58 563.87 304.58 563.87 304.33 563.68 305.09 563.38 307.36 562.89 309.67 562.06 312.48 561.08 315.11 559.52 317.42 558.33 319.34 556.45 320.63 555.58 321.62 555.13 322.22 554.03 323.64 553.50 324.64 553.50 326.07 553.48 327.30 554.29 328.40 554.78 329.68 555.29 331.10 558.60 331.92 559.81 332.63 559.46 333.16 557.80 333.15 554.65 332.73 551.49 329.85 549.26 327.77 547.79 327.07 546.25 326.56 545.56 324.85 545.76 323.19 546.51 320.53 546.96 316.56 548.81 313.27 551.94 312.75 554.00 310.73 556.57 306.59 560.91 306.32 565.00 304.32 569.52 302.60 575.19 300.81 580.17 300.36 581.46 299.26 578.85 298.48 573.94 297.55 570.79 296.77 569.31 296.25 567.14 295.32 565.21 294.97 563.68 294.97 560.68 294.36 557.22 294.40 553.71 294.50 550.38 294.14 548.72 293.72 547.78 293.09 546.89 292.53 546.75 290.08 547.81 289.64 548.44 288.88 548.96 287.92 551.59 286.10 555.52 285.26 557.55 284.10 557.36 281.06 556.17 278.48 556.20 277.35 557.13
|
||||
353.36 58.97 353.12 57.14 353.64 54.61 354.21 51.62 354.80 49.19 356.12 47.63 357.15 48.19 357.49 47.85 358.55 46.69 360.18 45.60 361.27 44.97 361.24 45.06 360.66 45.68 360.22 47.10 360.79 47.02 361.19 46.60 361.73 47.18 362.40 46.88 363.38 46.23 364.53 47.11 364.05 49.23 363.58 50.75 363.62 51.70 363.14 52.88 362.54 53.74 361.74 54.16 360.28 55.32 358.28 55.86 357.25 56.29 356.71 56.34 354.82 57.01 353.58 57.00 351.96 56.00 351.14 54.95 349.12 54.02 348.05 52.65 346.91 51.31 345.06 50.23 344.21 50.05 343.52 50.09 342.03 50.22 341.31 50.24 340.29 50.61 339.50 51.25 339.18 51.19 338.28 51.93 337.69 52.23 336.80 52.60 337.31 51.68 337.61 51.94 338.09 51.73 340.70 51.79 339.79 52.96 337.34 53.13 335.17 54.03 335.83 53.90 334.40 55.36 333.23 55.94 331.82 56.41 330.61 57.05 329.76 57.84 328.47 58.35 327.10 59.24 325.90 59.97 325.41 59.38 324.43 61.01 323.11 61.84 321.18 62.72 320.85 62.47 319.38 63.73 318.89 64.67 318.89 65.67 321.08 66.59 324.81 67.51 329.52 69.29 337.00 69.36 343.00 72.36 349.01 74.36 355.66 74.31 355.09 75.68 351.10 76.67 348.31 78.67 348.53 79.76 344.81 83.36 341.79 85.88 340.79 87.88 338.85 91.75 337.03 93.70 333.03 96.70 329.27 98.56 324.58 101.24 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00 -1.00
|
||||
@@ -0,0 +1,4 @@
|
||||
resized_IMG_2889.jpg
|
||||
resized_IMG_2890.jpg
|
||||
resized_IMG_2891.jpg
|
||||
resized_IMG_2892.jpg
|
||||
|
After Width: | Height: | Size: 156 KiB |
|
After Width: | Height: | Size: 159 KiB |
|
After Width: | Height: | Size: 166 KiB |
|
After Width: | Height: | Size: 206 KiB |
@@ -0,0 +1,309 @@
|
||||
1.0200000e+02
|
||||
1.3565461e+02 -2.1840103e+01 1.9819526e+02 -1.0170771e+01
|
||||
1.3632370e+02 1.2187567e+01 1.9869165e+02 1.9780392e+01
|
||||
1.3659126e+02 4.6222740e+01 1.9946641e+02 4.9773407e+01
|
||||
1.3618322e+02 8.0487054e+01 1.9890466e+02 7.9833292e+01
|
||||
1.3618923e+02 1.1488794e+02 1.9924137e+02 1.1009794e+02
|
||||
1.3557352e+02 1.4888312e+02 1.9854904e+02 1.4019595e+02
|
||||
1.0460796e+02 -2.2508578e+01 1.7365956e+02 -1.0556587e+01
|
||||
1.0465313e+02 1.1736607e+01 1.7395584e+02 1.9691431e+01
|
||||
1.0478526e+02 4.6460713e+01 1.7458636e+02 5.0252516e+01
|
||||
1.0457158e+02 8.0953990e+01 1.7417263e+02 8.0783049e+01
|
||||
1.0459174e+02 1.1535848e+02 1.7444097e+02 1.1115772e+02
|
||||
1.0437634e+02 1.5019535e+02 1.7410457e+02 1.4160445e+02
|
||||
7.2535504e+01 -2.3201340e+01 1.4849881e+02 -1.1138970e+01
|
||||
7.2558710e+01 1.1594239e+01 1.4863036e+02 1.9607124e+01
|
||||
7.2628399e+01 4.6604103e+01 1.4918117e+02 5.0626676e+01
|
||||
7.2525945e+01 8.1233985e+01 1.4858668e+02 8.1245004e+01
|
||||
7.2287421e+01 1.1627549e+02 1.4859441e+02 1.1210216e+02
|
||||
7.1969831e+01 1.5120192e+02 1.4853599e+02 1.4321231e+02
|
||||
3.9773632e+01 -2.3602728e+01 1.2246578e+02 -1.1551178e+01
|
||||
4.0144464e+01 1.1556425e+01 1.2268584e+02 1.9586701e+01
|
||||
4.0447929e+01 4.6670400e+01 1.2334768e+02 5.0749467e+01
|
||||
3.9626964e+01 8.2028161e+01 1.2265015e+02 8.2021137e+01
|
||||
3.9514609e+01 1.1716629e+02 1.2252761e+02 1.1321018e+02
|
||||
3.9423381e+01 1.5227031e+02 1.2248098e+02 1.4436653e+02
|
||||
6.8546879e+00 -2.4418765e+01 9.6014444e+01 -1.1984500e+01
|
||||
7.2574490e+00 1.1396253e+01 9.6609162e+01 1.9608204e+01
|
||||
7.3284311e+00 4.6698371e+01 9.6687887e+01 5.0849626e+01
|
||||
6.5433913e+00 8.2169734e+01 9.6408732e+01 8.2744839e+01
|
||||
6.4800159e+00 1.1766813e+02 9.5872017e+01 1.1424657e+02
|
||||
6.4791015e+00 1.5343124e+02 9.6082919e+01 1.4602665e+02
|
||||
-2.6558934e+01 -2.4640903e+01 6.8995111e+01 -1.2555627e+01
|
||||
-2.6499960e+01 1.0829206e+01 6.9518077e+01 1.9526829e+01
|
||||
-2.6586633e+01 4.6747549e+01 6.9532848e+01 5.1400625e+01
|
||||
-2.7122409e+01 8.2779745e+01 6.9228731e+01 8.3212654e+01
|
||||
-2.7385173e+01 1.1841828e+02 6.9078117e+01 1.1529126e+02
|
||||
-2.7461512e+01 1.5443854e+02 6.9167034e+01 1.4739623e+02
|
||||
-6.0759788e+01 -2.5584288e+01 4.1583311e+01 -1.2965988e+01
|
||||
-6.1347509e+01 1.0630597e+01 4.1541133e+01 1.9556284e+01
|
||||
-6.1562412e+01 4.6764284e+01 4.1226148e+01 5.1769646e+01
|
||||
-6.1554706e+01 8.3050630e+01 4.1329061e+01 8.4151474e+01
|
||||
-6.1746894e+01 1.1932705e+02 4.1119768e+01 1.1640925e+02
|
||||
-6.1871649e+01 1.5566108e+02 4.1440242e+01 1.4913669e+02
|
||||
-9.6614546e+01 -2.5864918e+01 1.2549031e+01 -1.3519330e+01
|
||||
-9.6654949e+01 1.0570803e+01 1.2551417e+01 1.9505076e+01
|
||||
-9.7135252e+01 4.6926792e+01 1.2380775e+01 5.1955423e+01
|
||||
-9.7376300e+01 8.3781084e+01 1.2426714e+01 8.5042035e+01
|
||||
-9.7294524e+01 1.2029188e+02 1.2560996e+01 1.1785493e+02
|
||||
-9.7539254e+01 1.5707802e+02 1.2462437e+01 1.5042962e+02
|
||||
-9.8505492e+01 -1.6361335e+02 -1.3630076e+02 -1.5228957e+02
|
||||
-9.8546116e+01 -1.4949510e+02 -1.3618931e+02 -1.3877090e+02
|
||||
-9.8728409e+01 -1.3541719e+02 -1.3653833e+02 -1.2526451e+02
|
||||
-9.8794674e+01 -1.2135899e+02 -1.3654775e+02 -1.1162840e+02
|
||||
-9.9016295e+01 -1.0711728e+02 -1.3661742e+02 -9.8041445e+01
|
||||
-9.9178368e+01 -9.3059874e+01 -1.3679150e+02 -8.4335285e+01
|
||||
-1.1251654e+02 -1.6450504e+02 -1.4910087e+02 -1.5326354e+02
|
||||
-1.1245267e+02 -1.5047783e+02 -1.4882490e+02 -1.3973736e+02
|
||||
-1.1251829e+02 -1.3630654e+02 -1.4923631e+02 -1.2608675e+02
|
||||
-1.1264220e+02 -1.2222459e+02 -1.4937956e+02 -1.1255550e+02
|
||||
-1.1270267e+02 -1.0790924e+02 -1.4948916e+02 -9.8785792e+01
|
||||
-1.1283560e+02 -9.3795606e+01 -1.4971112e+02 -8.4963177e+01
|
||||
-1.2631101e+02 -1.6543112e+02 -1.6174075e+02 -1.5431046e+02
|
||||
-1.2623416e+02 -1.5139519e+02 -1.6170397e+02 -1.4096352e+02
|
||||
-1.2640168e+02 -1.3728845e+02 -1.6184356e+02 -1.2698410e+02
|
||||
-1.2652703e+02 -1.2306434e+02 -1.6210896e+02 -1.1336062e+02
|
||||
-1.2665368e+02 -1.0868052e+02 -1.6230640e+02 -9.9509215e+01
|
||||
-1.2672292e+02 -9.4349594e+01 -1.6252543e+02 -8.5845064e+01
|
||||
-1.4013932e+02 -1.6653733e+02 -1.7471300e+02 -1.5540299e+02
|
||||
-1.4026713e+02 -1.5236959e+02 -1.7471518e+02 -1.4189690e+02
|
||||
-1.4028912e+02 -1.3838655e+02 -1.7485014e+02 -1.2822890e+02
|
||||
-1.4060449e+02 -1.2374255e+02 -1.7509545e+02 -1.1422046e+02
|
||||
-1.4058667e+02 -1.0930583e+02 -1.7522061e+02 -1.0032104e+02
|
||||
-1.4070093e+02 -9.4997511e+01 -1.7561372e+02 -8.6661780e+01
|
||||
-1.5398443e+02 -1.6740996e+02 -1.8768269e+02 -1.5659464e+02
|
||||
-1.5406324e+02 -1.5332849e+02 -1.8776973e+02 -1.4302072e+02
|
||||
-1.5442798e+02 -1.3897887e+02 -1.8815877e+02 -1.2909606e+02
|
||||
-1.5446011e+02 -1.2462435e+02 -1.8818723e+02 -1.1512541e+02
|
||||
-1.5457604e+02 -1.1006693e+02 -1.8844448e+02 -1.0115724e+02
|
||||
-1.5472241e+02 -9.5985074e+01 -1.8855533e+02 -8.7470802e+01
|
||||
-1.6827308e+02 -1.6839068e+02 -2.0131646e+02 -1.5770454e+02
|
||||
-1.6830325e+02 -1.5419519e+02 -2.0125869e+02 -1.4408292e+02
|
||||
-1.6849131e+02 -1.3975338e+02 -2.0144343e+02 -1.3007771e+02
|
||||
-1.6856150e+02 -1.2521708e+02 -2.0148004e+02 -1.1610880e+02
|
||||
-1.6862721e+02 -1.1091631e+02 -2.0163825e+02 -1.0205420e+02
|
||||
-1.6877598e+02 -9.6558432e+01 -2.0170395e+02 -8.8164557e+01
|
||||
-1.8252897e+02 -1.6936038e+02 -2.1470075e+02 -1.5885911e+02
|
||||
-1.8248901e+02 -1.5508723e+02 -2.1456502e+02 -1.4512083e+02
|
||||
-1.8259150e+02 -1.4061469e+02 -2.1471396e+02 -1.3108421e+02
|
||||
-1.8263321e+02 -1.2623806e+02 -2.1476969e+02 -1.1711428e+02
|
||||
-1.8306648e+02 -1.1171650e+02 -2.1512165e+02 -1.0292363e+02
|
||||
-1.8320429e+02 -9.7225508e+01 -2.1541221e+02 -8.8875520e+01
|
||||
-1.9705983e+02 -1.7033925e+02 -2.2851382e+02 -1.6013800e+02
|
||||
-1.9724930e+02 -1.5580169e+02 -2.2852055e+02 -1.4617309e+02
|
||||
-1.9720787e+02 -1.4143932e+02 -2.2848484e+02 -1.3215955e+02
|
||||
-1.9742033e+02 -1.2687768e+02 -2.2856255e+02 -1.1809495e+02
|
||||
-1.9745757e+02 -1.1245588e+02 -2.2864574e+02 -1.0384620e+02
|
||||
-1.9766865e+02 -9.7816323e+01 -2.2928057e+02 -8.9824935e+01
|
||||
-2.1161336e+02 -1.7120575e+02 -2.4245331e+02 -1.6121824e+02
|
||||
-2.1162545e+02 -1.5682027e+02 -2.4242890e+02 -1.4728707e+02
|
||||
-2.1180027e+02 -1.4215400e+02 -2.4248723e+02 -1.3317135e+02
|
||||
-2.1181616e+02 -1.2770807e+02 -2.4251854e+02 -1.1902442e+02
|
||||
-2.1230706e+02 -1.1306155e+02 -2.4260610e+02 -1.0476462e+02
|
||||
-2.1230218e+02 -9.8630005e+01 -2.4305346e+02 -9.0630093e+01
|
||||
1.0200000e+02
|
||||
1.0200000e+02
|
||||
1.3565461e+02 -2.1840103e+01
|
||||
1.3632370e+02 1.2187567e+01
|
||||
1.3659126e+02 4.6222740e+01
|
||||
1.3618322e+02 8.0487054e+01
|
||||
1.3618923e+02 1.1488794e+02
|
||||
1.3557352e+02 1.4888312e+02
|
||||
1.0460796e+02 -2.2508578e+01
|
||||
1.0465313e+02 1.1736607e+01
|
||||
1.0478526e+02 4.6460713e+01
|
||||
1.0457158e+02 8.0953990e+01
|
||||
1.0459174e+02 1.1535848e+02
|
||||
1.0437634e+02 1.5019535e+02
|
||||
7.2535504e+01 -2.3201340e+01
|
||||
7.2558710e+01 1.1594239e+01
|
||||
7.2628399e+01 4.6604103e+01
|
||||
7.2525945e+01 8.1233985e+01
|
||||
7.2287421e+01 1.1627549e+02
|
||||
7.1969831e+01 1.5120192e+02
|
||||
3.9773632e+01 -2.3602728e+01
|
||||
4.0144464e+01 1.1556425e+01
|
||||
4.0447929e+01 4.6670400e+01
|
||||
3.9626964e+01 8.2028161e+01
|
||||
3.9514609e+01 1.1716629e+02
|
||||
3.9423381e+01 1.5227031e+02
|
||||
6.8546879e+00 -2.4418765e+01
|
||||
7.2574490e+00 1.1396253e+01
|
||||
7.3284311e+00 4.6698371e+01
|
||||
6.5433913e+00 8.2169734e+01
|
||||
6.4800159e+00 1.1766813e+02
|
||||
6.4791015e+00 1.5343124e+02
|
||||
-2.6558934e+01 -2.4640903e+01
|
||||
-2.6499960e+01 1.0829206e+01
|
||||
-2.6586633e+01 4.6747549e+01
|
||||
-2.7122409e+01 8.2779745e+01
|
||||
-2.7385173e+01 1.1841828e+02
|
||||
-2.7461512e+01 1.5443854e+02
|
||||
-6.0759788e+01 -2.5584288e+01
|
||||
-6.1347509e+01 1.0630597e+01
|
||||
-6.1562412e+01 4.6764284e+01
|
||||
-6.1554706e+01 8.3050630e+01
|
||||
-6.1746894e+01 1.1932705e+02
|
||||
-6.1871649e+01 1.5566108e+02
|
||||
-9.6614546e+01 -2.5864918e+01
|
||||
-9.6654949e+01 1.0570803e+01
|
||||
-9.7135252e+01 4.6926792e+01
|
||||
-9.7376300e+01 8.3781084e+01
|
||||
-9.7294524e+01 1.2029188e+02
|
||||
-9.7539254e+01 1.5707802e+02
|
||||
-9.8505492e+01 -1.6361335e+02
|
||||
-9.8546116e+01 -1.4949510e+02
|
||||
-9.8728409e+01 -1.3541719e+02
|
||||
-9.8794674e+01 -1.2135899e+02
|
||||
-9.9016295e+01 -1.0711728e+02
|
||||
-9.9178368e+01 -9.3059874e+01
|
||||
-1.1251654e+02 -1.6450504e+02
|
||||
-1.1245267e+02 -1.5047783e+02
|
||||
-1.1251829e+02 -1.3630654e+02
|
||||
-1.1264220e+02 -1.2222459e+02
|
||||
-1.1270267e+02 -1.0790924e+02
|
||||
-1.1283560e+02 -9.3795606e+01
|
||||
-1.2631101e+02 -1.6543112e+02
|
||||
-1.2623416e+02 -1.5139519e+02
|
||||
-1.2640168e+02 -1.3728845e+02
|
||||
-1.2652703e+02 -1.2306434e+02
|
||||
-1.2665368e+02 -1.0868052e+02
|
||||
-1.2672292e+02 -9.4349594e+01
|
||||
-1.4013932e+02 -1.6653733e+02
|
||||
-1.4026713e+02 -1.5236959e+02
|
||||
-1.4028912e+02 -1.3838655e+02
|
||||
-1.4060449e+02 -1.2374255e+02
|
||||
-1.4058667e+02 -1.0930583e+02
|
||||
-1.4070093e+02 -9.4997511e+01
|
||||
-1.5398443e+02 -1.6740996e+02
|
||||
-1.5406324e+02 -1.5332849e+02
|
||||
-1.5442798e+02 -1.3897887e+02
|
||||
-1.5446011e+02 -1.2462435e+02
|
||||
-1.5457604e+02 -1.1006693e+02
|
||||
-1.5472241e+02 -9.5985074e+01
|
||||
-1.6827308e+02 -1.6839068e+02
|
||||
-1.6830325e+02 -1.5419519e+02
|
||||
-1.6849131e+02 -1.3975338e+02
|
||||
-1.6856150e+02 -1.2521708e+02
|
||||
-1.6862721e+02 -1.1091631e+02
|
||||
-1.6877598e+02 -9.6558432e+01
|
||||
-1.8252897e+02 -1.6936038e+02
|
||||
-1.8248901e+02 -1.5508723e+02
|
||||
-1.8259150e+02 -1.4061469e+02
|
||||
-1.8263321e+02 -1.2623806e+02
|
||||
-1.8306648e+02 -1.1171650e+02
|
||||
-1.8320429e+02 -9.7225508e+01
|
||||
-1.9705983e+02 -1.7033925e+02
|
||||
-1.9724930e+02 -1.5580169e+02
|
||||
-1.9720787e+02 -1.4143932e+02
|
||||
-1.9742033e+02 -1.2687768e+02
|
||||
-1.9745757e+02 -1.1245588e+02
|
||||
-1.9766865e+02 -9.7816323e+01
|
||||
-2.1161336e+02 -1.7120575e+02
|
||||
-2.1162545e+02 -1.5682027e+02
|
||||
-2.1180027e+02 -1.4215400e+02
|
||||
-2.1181616e+02 -1.2770807e+02
|
||||
-2.1230706e+02 -1.1306155e+02
|
||||
-2.1230218e+02 -9.8630005e+01
|
||||
1.9819526e+02 -1.0170771e+01
|
||||
1.9869165e+02 1.9780392e+01
|
||||
1.9946641e+02 4.9773407e+01
|
||||
1.9890466e+02 7.9833292e+01
|
||||
1.9924137e+02 1.1009794e+02
|
||||
1.9854904e+02 1.4019595e+02
|
||||
1.7365956e+02 -1.0556587e+01
|
||||
1.7395584e+02 1.9691431e+01
|
||||
1.7458636e+02 5.0252516e+01
|
||||
1.7417263e+02 8.0783049e+01
|
||||
1.7444097e+02 1.1115772e+02
|
||||
1.7410457e+02 1.4160445e+02
|
||||
1.4849881e+02 -1.1138970e+01
|
||||
1.4863036e+02 1.9607124e+01
|
||||
1.4918117e+02 5.0626676e+01
|
||||
1.4858668e+02 8.1245004e+01
|
||||
1.4859441e+02 1.1210216e+02
|
||||
1.4853599e+02 1.4321231e+02
|
||||
1.2246578e+02 -1.1551178e+01
|
||||
1.2268584e+02 1.9586701e+01
|
||||
1.2334768e+02 5.0749467e+01
|
||||
1.2265015e+02 8.2021137e+01
|
||||
1.2252761e+02 1.1321018e+02
|
||||
1.2248098e+02 1.4436653e+02
|
||||
9.6014444e+01 -1.1984500e+01
|
||||
9.6609162e+01 1.9608204e+01
|
||||
9.6687887e+01 5.0849626e+01
|
||||
9.6408732e+01 8.2744839e+01
|
||||
9.5872017e+01 1.1424657e+02
|
||||
9.6082919e+01 1.4602665e+02
|
||||
6.8995111e+01 -1.2555627e+01
|
||||
6.9518077e+01 1.9526829e+01
|
||||
6.9532848e+01 5.1400625e+01
|
||||
6.9228731e+01 8.3212654e+01
|
||||
6.9078117e+01 1.1529126e+02
|
||||
6.9167034e+01 1.4739623e+02
|
||||
4.1583311e+01 -1.2965988e+01
|
||||
4.1541133e+01 1.9556284e+01
|
||||
4.1226148e+01 5.1769646e+01
|
||||
4.1329061e+01 8.4151474e+01
|
||||
4.1119768e+01 1.1640925e+02
|
||||
4.1440242e+01 1.4913669e+02
|
||||
1.2549031e+01 -1.3519330e+01
|
||||
1.2551417e+01 1.9505076e+01
|
||||
1.2380775e+01 5.1955423e+01
|
||||
1.2426714e+01 8.5042035e+01
|
||||
1.2560996e+01 1.1785493e+02
|
||||
1.2462437e+01 1.5042962e+02
|
||||
-1.3630076e+02 -1.5228957e+02
|
||||
-1.3618931e+02 -1.3877090e+02
|
||||
-1.3653833e+02 -1.2526451e+02
|
||||
-1.3654775e+02 -1.1162840e+02
|
||||
-1.3661742e+02 -9.8041445e+01
|
||||
-1.3679150e+02 -8.4335285e+01
|
||||
-1.4910087e+02 -1.5326354e+02
|
||||
-1.4882490e+02 -1.3973736e+02
|
||||
-1.4923631e+02 -1.2608675e+02
|
||||
-1.4937956e+02 -1.1255550e+02
|
||||
-1.4948916e+02 -9.8785792e+01
|
||||
-1.4971112e+02 -8.4963177e+01
|
||||
-1.6174075e+02 -1.5431046e+02
|
||||
-1.6170397e+02 -1.4096352e+02
|
||||
-1.6184356e+02 -1.2698410e+02
|
||||
-1.6210896e+02 -1.1336062e+02
|
||||
-1.6230640e+02 -9.9509215e+01
|
||||
-1.6252543e+02 -8.5845064e+01
|
||||
-1.7471300e+02 -1.5540299e+02
|
||||
-1.7471518e+02 -1.4189690e+02
|
||||
-1.7485014e+02 -1.2822890e+02
|
||||
-1.7509545e+02 -1.1422046e+02
|
||||
-1.7522061e+02 -1.0032104e+02
|
||||
-1.7561372e+02 -8.6661780e+01
|
||||
-1.8768269e+02 -1.5659464e+02
|
||||
-1.8776973e+02 -1.4302072e+02
|
||||
-1.8815877e+02 -1.2909606e+02
|
||||
-1.8818723e+02 -1.1512541e+02
|
||||
-1.8844448e+02 -1.0115724e+02
|
||||
-1.8855533e+02 -8.7470802e+01
|
||||
-2.0131646e+02 -1.5770454e+02
|
||||
-2.0125869e+02 -1.4408292e+02
|
||||
-2.0144343e+02 -1.3007771e+02
|
||||
-2.0148004e+02 -1.1610880e+02
|
||||
-2.0163825e+02 -1.0205420e+02
|
||||
-2.0170395e+02 -8.8164557e+01
|
||||
-2.1470075e+02 -1.5885911e+02
|
||||
-2.1456502e+02 -1.4512083e+02
|
||||
-2.1471396e+02 -1.3108421e+02
|
||||
-2.1476969e+02 -1.1711428e+02
|
||||
-2.1512165e+02 -1.0292363e+02
|
||||
-2.1541221e+02 -8.8875520e+01
|
||||
-2.2851382e+02 -1.6013800e+02
|
||||
-2.2852055e+02 -1.4617309e+02
|
||||
-2.2848484e+02 -1.3215955e+02
|
||||
-2.2856255e+02 -1.1809495e+02
|
||||
-2.2864574e+02 -1.0384620e+02
|
||||
-2.2928057e+02 -8.9824935e+01
|
||||
-2.4245331e+02 -1.6121824e+02
|
||||
-2.4242890e+02 -1.4728707e+02
|
||||
-2.4248723e+02 -1.3317135e+02
|
||||
-2.4251854e+02 -1.1902442e+02
|
||||
-2.4260610e+02 -1.0476462e+02
|
||||
-2.4305346e+02 -9.0630093e+01
|
||||
@@ -0,0 +1,80 @@
|
||||
#include <opencv2/sfm.hpp>
|
||||
#include <opencv2/viz.hpp>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
using namespace std;
|
||||
using namespace cv;
|
||||
using namespace cv::sfm;
|
||||
|
||||
static void help() {
|
||||
cout
|
||||
<< "\n---------------------------------------------------------------------------\n"
|
||||
<< " This program shows how to import a reconstructed scene in the \n"
|
||||
<< " OpenCV Structure From Motion (SFM) module.\n"
|
||||
<< " Usage:\n"
|
||||
<< " example_sfm_import_reconstruction <path_to_file>\n"
|
||||
<< " where: file_path is the absolute path file into your system which contains\n"
|
||||
<< " the reconstructed scene. \n"
|
||||
<< "---------------------------------------------------------------------------\n\n"
|
||||
<< endl;
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
/// Read input parameters
|
||||
|
||||
if ( argc != 2 ) {
|
||||
help();
|
||||
exit(0);
|
||||
}
|
||||
|
||||
/// Immport a reconstructed scene
|
||||
|
||||
vector<Mat> Rs, Ts, Ks, points3d;
|
||||
importReconstruction(argv[1], Rs, Ts, Ks, points3d, SFM_IO_BUNDLER);
|
||||
|
||||
|
||||
/// Create 3D windows
|
||||
|
||||
viz::Viz3d window("Coordinate Frame");
|
||||
window.setWindowSize(Size(500,500));
|
||||
window.setWindowPosition(Point(150,150));
|
||||
window.setBackgroundColor(); // black by default
|
||||
|
||||
|
||||
/// Create the pointcloud
|
||||
|
||||
vector<Vec3d> point_cloud;
|
||||
for (int i = 0; i < points3d.size(); ++i){
|
||||
point_cloud.push_back(Vec3f(points3d[i]));
|
||||
}
|
||||
|
||||
|
||||
/// Recovering cameras
|
||||
|
||||
vector<Affine3d> path;
|
||||
for (size_t i = 0; i < Rs.size(); ++i)
|
||||
path.push_back(Affine3d(Rs[i], Ts[i]));
|
||||
|
||||
|
||||
/// Create and show widgets
|
||||
|
||||
viz::WCloud cloud_widget(point_cloud, viz::Color::green());
|
||||
viz::WTrajectory trajectory(path, viz::WTrajectory::FRAMES, 0.5);
|
||||
viz::WTrajectoryFrustums frustums(path, Vec2f(0.889484, 0.523599), 0.5,
|
||||
viz::Color::yellow());
|
||||
|
||||
window.showWidget("point_cloud", cloud_widget);
|
||||
window.showWidget("cameras", trajectory);
|
||||
window.showWidget("frustums", frustums);
|
||||
|
||||
|
||||
/// Wait for key 'q' to close the window
|
||||
cout << endl << "Press 'q' to close each windows ... " << endl;
|
||||
|
||||
window.spin();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,165 @@
|
||||
#include <opencv2/sfm.hpp>
|
||||
#include <opencv2/viz.hpp>
|
||||
#include <opencv2/geometry.hpp>
|
||||
#include <opencv2/core.hpp>
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
|
||||
using namespace std;
|
||||
using namespace cv;
|
||||
using namespace cv::sfm;
|
||||
|
||||
const String keys =
|
||||
"{help h usage ? help | | Help message }"
|
||||
"{f | 1428 | focal value }"
|
||||
"{x | 640 | cx is the image principal point x coordinates in pixels. }"
|
||||
"{y | 480 | cy is the image principal point y coordinates in pixels. }"
|
||||
"{@arg1 | | empty = simulate data saved in myMatchdata.yml}";
|
||||
|
||||
|
||||
int main (int argc,char **argv)
|
||||
{
|
||||
CommandLineParser parser(argc, argv, keys);
|
||||
|
||||
if (parser.has("help"))
|
||||
{
|
||||
parser.printMessage();
|
||||
return 0;
|
||||
}
|
||||
String nomFic = parser.get<String>(0);
|
||||
vector<Mat> pt2d1;
|
||||
vector<Mat> pt3d1;
|
||||
Matx33d K = Matx33d( 1428, 0, 640, 0, 1428, 480, 0, 0, 1);
|
||||
if (parser.has("f"))
|
||||
{
|
||||
K(0, 0) = parser.get<double>("f");
|
||||
K(1, 1) = K(0, 0);
|
||||
}
|
||||
if (parser.has("x"))
|
||||
{
|
||||
K(0, 2) = parser.get<double>("x");
|
||||
}
|
||||
if (parser.has("y"))
|
||||
{
|
||||
K(1, 2) = parser.get<double>("y");
|
||||
}
|
||||
if (nomFic.length() == 0)
|
||||
{
|
||||
pt2d1.push_back((Mat_<double>(1, 216) << 1028.8265208422474, 630.75473327994234, 1029.9623410162367, 628.67047008772204, 1033.8855507029073, 621.47126573077719, 1040.2650684237346, 609.76466439182002, 1048.4800533196403, 594.6899271796392, 1057.67755340346, 577.81224590213685, 1066.8749263994853, 560.93479783444945, 1075.089582891565, 545.86066325288073, 1081.4687057168005, 534.15478655886807, 1085.3916118364564, 526.95613925626117, 1028.8265208422474, 630.75473327994234, 1042.6210649116142, 635.77913663139668, 1058.2767721615944, 635.11272797936954, 1074.21275121699, 628.62501281049708, 1088.716306279503, 616.8526564146573, 1100.1695865815918, 600.99217884301265, 1107.2898612349959, 582.76830122534409, 1109.3232390659123, 564.19410174213567, 1106.1411114771274, 547.27816766005208, 1098.2204929066636, 533.75129537641021, 1028.8265208422474, 630.75473327994234, 1050.5113416641682, 639.95427767176307, 1073.3794629073186, 643.13787002982929, 1095.0866253501956, 639.79458913165013, 1113.2950809989484, 630.12478679472406, 1125.9859344083973, 615.07531788451263, 1131.7541276864013, 596.24975639745298, 1130.013945179634, 575.69850980844853, 1121.0638497359391, 555.63225549034769, 1106.0019832556338, 538.12528756263589, 1028.8265208422474, 630.75473327994234, 1050.5557099545015, 639.56953663873571, 1073.1937204909029, 642.36511438018294, 1094.4753756517703, 638.78182172965023, 1112.2243137486491, 629.11764825424234, 1124.6020757977692, 614.32040578935505, 1130.3280000880559, 595.89479610377475, 1128.832027152311, 575.73304654345543, 1120.3140614945582, 555.89461970733043, 1105.7028037736306, 538.37099193358495, 1028.8265208422474, 630.75473327994234, 1042.8631608146595, 634.84707689081199, 1058.2584967688865, 633.36513780784253, 1073.5201808839392, 626.49673981988565, 1087.1901914406481, 614.93311570256458, 1097.9739086020063, 599.79440917844522, 1104.8505533469176, 582.52462490041466, 1107.1601342595291, 564.76447800316646, 1104.6630875159808, 548.20938486875832, 1097.5686227034093, 534.45972996765431, 1028.8265208422474, 630.75473327994234, 1030.5094451565753, 627.66651801138744, 1034.7710087258772, 619.84642439779543, 1041.1508028774458, 608.13931580035444, 1049.0276032399836, 593.68515708397672, 1057.6775534034603, 577.81224590213697, 1066.3273911603369, 561.93954098969016, 1074.203893598404, 547.48592897341746, 1080.5833098120127, 535.77951390317128, 1084.8445528041379, 527.96000855806108, 1028.8265208422474, 630.75473327994234, 1018.1741780167231, 620.74342676475555, 1011.5526455838799, 606.87287620359348, 1009.432325764166, 590.53374347926467, 1011.8840276047719, 573.23767041426277, 1018.6183086835936, 556.50494178862834, 1029.0286987776246, 541.7778391792624, 1042.2318549174643, 530.34751728162291, 1057.1072904756345, 523.28067419880733, 1072.346767864846, 521.33634501543634, 1028.8265208422474, 630.75473327994234, 1010.4101690965293, 616.63109420608566, 996.9054207091491, 599.07749404652373, 989.41722948906693, 579.80687553297571, 988.48495091991276, 560.59034617421696, 994.09748444298839, 543.12852698707104, 1005.7283601637679, 528.95005419427048, 1022.3782374179993, 519.32551513551607, 1042.6242747915535, 515.18516094478298, 1064.6864339428105, 517.0345166093, 1028.8265208422474, 630.75473327994234, 1010.1203860471132, 616.86908165559817, 996.19985447065733, 599.3243841996026, 988.33023759751575, 579.83863843873178, 987.19255503865372, 560.26867143621132, 992.84977172120693, 542.44788416870733, 1004.7580535827984, 528.03740660115034, 1021.816137753751, 518.39418344227761, 1042.44951185794, 514.45808391571939, 1064.7294016570784, 516.66192071592866, 1028.8265208422474, 630.75473327994234, 1017.5350185621438, 621.43804766425978, 1010.129091420788, 607.7697751504603, 1007.3782941632923, 591.07535887445397, 1009.5887692661379, 573.00838401730766, 1016.5588223557643, 555.38146636509168, 1027.592783283955, 539.971750817464, 1041.5742740659934, 528.32676718803498, 1057.0896910577135, 521.59772432873001, 1072.5841040247224, 520.42261009954859, 1023.6872850276745, 501.48463396235769, 1021.7363061422241, 497.10356942867941, 1149.394888427619, 563.63353085150766, 1144.1773056475884, 564.44012449568231, 975.13608212288557, 590.57245094776658, 970.39817079227953, 591.3048914910305, 1095.4493161212483, 662.63147754605677, 1093.3004875390534, 657.80612717419194));
|
||||
pt2d1.push_back((Mat_<double>(1, 216) << 1067.8928935365691, 683.58145840030193, 1068.4581827905051, 681.10599202818446, 1071.882360816011, 673.41459952541288, 1077.8853119590685, 661.16770635223315, 1085.8867161323376, 645.56367742058092, 1095.0583596138767, 628.22462933245185, 1104.4226038828747, 611.0007252018562, 1112.9805870843823, 595.7267800366983, 1119.8434591346158, 583.9821639253181, 1124.339246882791, 576.90376658902449, 1067.8928935365691, 683.58145840030193, 1081.7151834279362, 688.66941795050138, 1097.428138122013, 687.9235640959464, 1113.4424085464443, 681.21495349585223, 1128.0331376073316, 669.10149841032887, 1139.5697153845745, 652.81908590227658, 1146.7592402475202, 634.14365737410071, 1148.8421591563374, 615.14204082571655, 1145.6886794245606, 597.86975221760406, 1137.7775035660395, 584.09118932755541, 1067.8928935365691, 683.58145840030193, 1090.2068754511652, 693.25377638834675, 1113.7045025864693, 696.73875324851565, 1135.9666313492651, 693.47911129723286, 1154.5812316896593, 683.65703206786213, 1167.4712118672201, 668.23587408124456, 1173.2032121184857, 648.86845178433623, 1171.1998404776273, 627.67681432581799, 1161.8014456750811, 606.95060334736809, 1146.1703105477263, 588.83599644775961, 1067.8928935365691, 683.58145840030193, 1090.6099121354423, 693.06659141864566, 1114.2030661855272, 696.34057932339863, 1136.2995604798953, 692.98103060973449, 1154.6227836605078, 683.25516008272655, 1167.2593380673673, 668.11880460810607, 1172.8939515366988, 649.12207352093083, 1170.9695166353083, 628.23058679082555, 1161.7434641884424, 607.59086467825603, 1146.2344983602861, 589.28038302494531, 1067.8928935365691, 683.58145840030193, 1082.895229343043, 688.25541702053886, 1099.1987117243582, 687.16019827974128, 1115.2184652848321, 680.44120103891714, 1129.416340908339, 668.77583871340801, 1140.4400477713136, 653.29998233232993, 1147.2414182318191, 635.49918384908153, 1149.1674409826339, 617.07431697162906, 1146.0193774849595, 599.79068436161003, 1138.0759557114482, 585.31963542080052, 1067.8928935365691, 683.58145840030193, 1070.16214258433, 680.7438161718253, 1074.9706987700099, 673.01147203970811, 1081.8081309064039, 661.22558916810021, 1090.0119148330264, 646.53931741824908, 1098.8284111281616, 630.3077464747771, 1107.4681971595389, 613.98627365569405, 1115.1570019568696, 599.03595733299926, 1121.1859294113658, 586.82933555112163, 1124.9644691622577, 578.54988864786185, 1067.8928935365691, 683.58145840030193, 1057.2452316565234, 673.379002774985, 1050.6581082937757, 659.2168370609121, 1048.5949446531069, 642.51881388549361, 1051.1173521145827, 624.83125168341883, 1057.9265533613118, 607.70769426216475, 1068.4082059460577, 592.62090547512094, 1081.6734323750627, 580.88938431356303, 1096.5986443721899, 573.60396841771808, 1111.8743379295613, 571.54415939325634, 1067.8928935365691, 683.58145840030193, 1048.9111776957698, 668.87652125259319, 1034.9508983701969, 650.70004084883863, 1027.1453920233062, 630.82629923276181, 1026.0481077210379, 611.07674253688992, 1031.6521368358715, 593.18993840091048, 1043.4286548389177, 578.721352989053, 1060.3705768160517, 568.95955884346415, 1081.0406285772904, 564.84568295355064, 1103.6344924420018, 566.88907690249778, 1067.8928935365691, 683.58145840030193, 1048.265471923263, 668.91569517314667, 1033.5708399191926, 650.56828363936381, 1025.1325099110034, 630.33712363016298, 1023.6682637307592, 610.14373701169086, 1029.2596225384095, 591.86797037808185, 1041.3659575359936, 577.19994258568397, 1058.8746289112819, 567.51082846526663, 1080.1834791017463, 563.7425119513822, 1103.3167108254768, 566.31844609073255, 1067.8928935365691, 683.58145840030193, 1055.6725753643061, 673.55353662991126, 1047.4617229934086, 659.1230163588009, 1044.1023768200268, 641.69608789417691, 1045.9539738614085, 622.99882697990961, 1052.846211261882, 604.90058468392704, 1064.0913680793378, 589.21585788732568, 1078.5566817649235, 577.50998282342039, 1094.7877055131692, 570.93429704431423, 1111.1655984212562, 570.11146605475471, 1068.8704743613182, 554.53428611501374, 1063.9450442024581, 548.49498043087226, 1197.081473717712, 618.60987666117319, 1194.8324071076543, 621.05020507745462, 1019.7936007286088, 645.91900575138266, 1012.1103123788265, 644.99848015359839, 1142.5378403469267, 720.52183104654694, 1143.3339670100315, 717.27046330120515));
|
||||
pt2d1.push_back((Mat_<double>(1, 216) << 1106.5208711485714, 741.50000049355288, 1106.4689494686579, 738.58802914804187, 1109.3501259102466, 730.34841486744574, 1114.939395472757, 717.50083145458598, 1122.7004345574444, 701.30948584821124, 1131.8323058505634, 683.45951438933207, 1141.3637728209014, 665.85274339228056, 1150.2798129066516, 650.35860912193448, 1157.654291765783, 638.57201851568459, 1162.7613665256426, 631.62736960308541, 1106.5208711485714, 741.50000049355288, 1120.3576643153483, 746.66233373712521, 1136.1131687270374, 745.83122124275212, 1152.1907277068667, 738.87977804315722, 1166.8548613344165, 726.38981283804787, 1178.4639850307283, 709.64090998541531, 1185.7167117214517, 690.46542969064296, 1187.8489642622787, 670.98913405384258, 1184.7299946431201, 653.31896453575837, 1176.8394080426426, 639.25639203125183, 1106.5208711485714, 741.50000049355288, 1129.4905019784496, 751.70595049127405, 1153.6411068866935, 755.53315567927564, 1176.4749364071429, 752.37245531571841, 1195.5026704255715, 742.38555549078183, 1208.5876644980842, 726.55387522300271, 1214.2690551999476, 706.58461409952679, 1211.9804962119542, 684.67907150122062, 1202.1079825941652, 663.21439810764696, 1185.881631332802, 644.41676223228831, 1106.5208711485714, 741.50000049355288, 1130.2816201445758, 751.73986447744915, 1154.8819119236368, 755.55485038277197, 1177.8340777125179, 752.45173594258813, 1196.7548671941956, 742.66256661276918, 1209.6520720905519, 727.15148776331444, 1215.1755732276433, 707.51891694710991, 1212.7846911708384, 685.81227694750123, 1202.8005491756587, 664.27533636692294, 1186.3390344595209, 645.08180588222297, 1106.5208711485714, 741.50000049355288, 1122.5515511825249, 746.82761962544794, 1139.8201658767964, 746.16917289632045, 1156.642272397497, 739.62184522445341, 1171.3937108991886, 727.84689043988749, 1182.6609656186304, 711.99730827543624, 1189.3680088375486, 693.60494724925832, 1190.8715188535589, 674.43800530797739, 1187.0188831430844, 656.34006932374371, 1178.1651450666627, 641.06195459560911, 1106.5208711485714, 741.50000049355288, 1109.4213665179313, 738.942490402668, 1114.8156966255365, 731.30875824877501, 1122.1395480082178, 719.4356479964805, 1130.6861646984178, 704.49107197154171, 1139.6704433829484, 687.86024331609917, 1148.2865730511819, 671.03948954728151, 1155.7605151950252, 655.53708703172401, 1161.4009144024665, 642.77508963113996, 1164.6516661899932, 633.98548023803164, 1106.5208711485714, 741.50000049355288, 1095.888877842398, 731.08056490025206, 1089.3443232179313, 716.58925490028514, 1087.3431873190796, 699.48748020128835, 1089.937488126664, 681.36098683620844, 1096.8188118655555, 663.80115866765982, 1107.3648302571987, 648.31526172567021, 1120.681335602038, 636.25236401317989, 1135.6422893941292, 628.72976171505582, 1150.9381011214252, 626.54880853087161, 1106.5208711485714, 741.50000049355288, 1086.9477908605254, 726.14040693438278, 1072.5091441840091, 707.26334098821826, 1064.3682972296936, 686.71212108746306, 1063.0935246982247, 666.36508530578703, 1068.6822113164806, 648.00384056426958, 1080.6029742421242, 633.21424662976324, 1097.8407506285969, 623.30494885594453, 1118.9437256647429, 619.22864040167235, 1142.0832991181603, 621.49783517673097, 1106.5208711485714, 741.50000049355288, 1085.9189387790498, 725.95804717534497, 1070.4046077909045, 706.71063351618943, 1061.3626385909047, 685.64500727464826, 1059.549001127127, 664.75501330148461, 1065.0641315983587, 645.97246665572288, 1077.3704640568426, 631.01993557205321, 1095.343720015409, 621.28440625154815, 1117.3537917095414, 617.70965704428454, 1141.3772373302338, 620.70804205286834, 1106.5208711485714, 741.50000049355288, 1093.3103773516757, 730.67511576758284, 1084.2404067245163, 715.39246043362039, 1080.2297722966712, 697.14833333534295, 1081.6938714349671, 677.74938750464776, 1088.495147990049, 659.12783056614569, 1099.9542841662278, 643.13940976689821, 1114.9219559561584, 631.3690047401102, 1131.9020534613658, 624.96787278972988, 1149.2100735166773, 624.54142364562324, 1114.1024784807053, 612.6686031148048, 1105.9543529343073, 604.7786513745275, 1244.9176353203754, 678.98321712381755, 1245.9389065801597, 683.26656884018348, 1064.520450250835, 706.63622233985939, 1053.6455115183364, 703.86051265866729, 1189.8275589862967, 784.15460376850683, 1193.8651240470415, 782.69395098725897));
|
||||
pt2d1.push_back((Mat_<double>(1, 216) << 1144.6799579195197, 804.85899215438599, 1143.9597472311048, 801.45615222480399, 1146.2503200861136, 792.60170439960677, 1151.386286071991, 779.08209481052711, 1158.8789841666487, 762.23526759569415, 1167.957314892026, 743.81648237240574, 1177.657733666761, 725.78466435057828, 1186.9489788693654, 710.04721863137911, 1194.8661499864766, 698.21586121499172, 1200.6267024845697, 691.42197303837008, 1144.6799579195197, 804.85899215438599, 1158.5160739755199, 810.10631154210353, 1174.2977751685303, 809.18138778719697, 1190.4224268078813, 801.96015724971016, 1205.1456152938981, 789.05154254676324, 1216.8166600457232, 771.78394697171677, 1224.1273841627517, 752.05222572939851, 1226.3102367191289, 732.0470826384385, 1223.2335679010871, 713.93204578873952, 1215.376869789915, 699.54958368383143, 1144.6799579195197, 804.85899215438599, 1168.3332071698312, 815.66789965943553, 1193.1618112391507, 819.88352114929296, 1216.5854258231366, 816.83848261960554, 1236.0342158693431, 806.67141829418438, 1249.3105318879079, 790.38368889584854, 1254.92684751455, 769.74291033211875, 1252.330717581191, 747.03849451679321, 1241.9576878712512, 724.7450099106378, 1225.109494772335, 705.177970657694, 1144.6799579195197, 804.85899215438599, 1169.5447851179513, 815.95139840664217, 1195.2086826047205, 820.37993340617243, 1219.0611600029742, 817.57108829243498, 1238.605316677829, 807.71657371010372, 1251.7658930832661, 791.7891565109727, 1257.1576739275433, 771.44529738176789, 1254.2601956732801, 748.82407495030088, 1243.4649305830681, 726.27843321336979, 1225.9926200811412, 706.09026769440447, 1144.6799579195197, 804.85899215438599, 1161.8072909486764, 810.9249341669306, 1180.1035632795956, 810.7623449423071, 1197.7769433694077, 804.41329276974238, 1213.1107066800409, 792.5200045942355, 1224.626156823643, 776.25416293527189, 1231.2188869718441, 757.19944867026038, 1232.2582618308122, 737.19980624497805, 1227.6436061825525, 718.18700644127875, 1217.8136555014084, 702.00135723624044, 1144.6799579195197, 804.85899215438599, 1148.2612968149381, 802.61772678180284, 1154.2845901355347, 795.09682785773452, 1162.1272674987097, 783.12790359244525, 1171.035004578737, 767.89531033708806, 1180.1893147778871, 750.81817309729092, 1188.7677202470613, 733.43896315551581, 1195.9978206416067, 717.31910595095633, 1201.2087481750307, 703.93620386281168, 1203.8829751426558, 694.57641320455878, 1144.6799579195197, 804.85899215438599, 1134.0766538615242, 794.19448914447923, 1127.584774582986, 779.3321377296553, 1125.6522337408283, 761.77581066097287, 1128.3209196636617, 743.15606804803065, 1135.2723715693394, 725.1073696646489, 1145.8760897302259, 709.17612599424615, 1159.2327097052976, 696.74575827982142, 1174.2144083283906, 688.96281915046029, 1189.5127519988655, 686.65228386928698, 1144.6799579195197, 804.85899215438599, 1124.4883354349502, 788.76090455651968, 1109.547762062879, 769.09425243127066, 1101.0533286546779, 747.7801985433922, 1099.5888286190609, 726.76145800702534, 1105.1559446592012, 707.86849548781618, 1117.2204078289783, 692.72166042370679, 1134.7588182648435, 682.65212106839897, 1156.3046068679428, 678.62503280920305, 1180.0048170075729, 681.15544828245538, 1144.6799579195197, 804.85899215438599, 1123.0464597501648, 788.32957894410936, 1106.6639980337086, 768.06956086618607, 1096.9817867117599, 746.06641911856377, 1094.7953883438952, 724.39507335235191, 1100.2243802196886, 705.04563010868708, 1112.7339384999332, 689.77708373051098, 1131.1877106190773, 679.99409033671179, 1153.927194801212, 676.64226390655654, 1178.880585595097, 680.12095613471126, 1144.6799579195197, 804.85899215438599, 1130.41286742641, 793.13671275341562, 1120.4256525013209, 776.89686510578474, 1115.7184694561788, 757.73673975171107, 1116.7653977109392, 737.55291853289179, 1123.4628768709858, 718.34752415560683, 1135.1402594330102, 702.02205640044758, 1150.6312849068274, 690.18296980545597, 1168.3971891437905, 683.98124215966754, 1186.6859081512343, 684.00282795803957, 1159.415146412372, 676.26466184556671, 1147.7678313863694, 666.28917121633128, 1292.9367505963062, 745.16752616362146, 1297.5680689427561, 751.55157573423412, 1109.3491796675462, 773.14941258639658, 1095.005989177668, 768.27146044210917, 1237.3558368456218, 854.00307602051817, 1244.9713572637831, 854.60076819605888));
|
||||
|
||||
for (int i = 0; i<pt2d1.size(); i++)
|
||||
pt2d1[i] = pt2d1[i].reshape(1, 108).t();
|
||||
FileStorage fs("myMatchdata.yml",FileStorage::WRITE);
|
||||
fs<<"ptTrack"<<pt2d1;
|
||||
}
|
||||
else
|
||||
{
|
||||
FileStorage fs("myMatchdata.yml", FileStorage::READ);
|
||||
if (fs.isOpened())
|
||||
{
|
||||
if (!fs["ptTrack"].empty())
|
||||
{
|
||||
fs["ptTrack"]>>pt2d1;
|
||||
}
|
||||
else
|
||||
{
|
||||
cout<<"node ptTrack not found!\n";
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
cout << "File not found!\n";
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
vector<Mat> Rs_est1, ts_est1;
|
||||
Mat Kr(K);
|
||||
reconstruct(pt2d1, Rs_est1, ts_est1, Kr, pt3d1, true);
|
||||
|
||||
// Print output
|
||||
|
||||
cout << "\n----------------------------\n" << endl;
|
||||
cout << "Reconstruction: " << endl;
|
||||
cout << "============================" << endl;
|
||||
cout << "Estimated 3D points: " << pt3d1.size() << endl;
|
||||
cout << "Estimated cameras: " << Rs_est1.size() << endl;
|
||||
cout << "Refined intrinsics: " << endl << K << endl << endl;
|
||||
vector<Mat> pt3d2;
|
||||
vector<Mat> Rs_est2, ts_est2;
|
||||
if (nomFic == "")
|
||||
{
|
||||
vector<Mat> pt2d2(pt2d1.size());
|
||||
for (int i = 0; i<pt2d2.size(); i++)
|
||||
pt2d2[i] = pt2d1[i] / 2 - 50;
|
||||
reconstruct(pt2d2, Rs_est2, ts_est2, Kr, pt3d2, true);
|
||||
}
|
||||
|
||||
cout << "3D Visualization: " << endl;
|
||||
cout << "============================" << endl;
|
||||
/// Create 3D windows
|
||||
viz::Viz3d window("Coordinate Frame");
|
||||
window.setWindowSize(Size(500, 500));
|
||||
window.setWindowPosition(Point(150, 150));
|
||||
window.setBackgroundColor(); // black by default
|
||||
// Create the pointcloud
|
||||
cout << "Recovering points ... ";
|
||||
// recover estimated points3d
|
||||
vector<Vec3f> point_cloud_est;
|
||||
vector<Vec3b> color;
|
||||
for (int i = 0; i < pt3d1.size(); ++i)
|
||||
{
|
||||
point_cloud_est.push_back(Vec3f(pt3d1[i]));
|
||||
color.push_back(Vec3b(0, 255, 0));
|
||||
}
|
||||
for (int i = 0; i < pt3d2.size(); ++i)
|
||||
{
|
||||
point_cloud_est.push_back(Vec3f(pt3d2[i]));
|
||||
color.push_back(Vec3b(255, 0, 0));
|
||||
}
|
||||
cout << "[DONE]" << endl;
|
||||
/// Recovering cameras
|
||||
cout << "Recovering cameras ... ";
|
||||
vector<Affine3d> path;
|
||||
for (size_t i = 0; i < Rs_est1.size(); ++i)
|
||||
path.push_back(Affine3d(Rs_est1[i], ts_est1[i]));
|
||||
for (size_t i = 0; i < Rs_est2.size(); ++i)
|
||||
path.push_back(Affine3d(Rs_est2[i], ts_est2[i]));
|
||||
cout << "[DONE]" << endl;
|
||||
/// Add the pointcloud
|
||||
if (point_cloud_est.size() > 0)
|
||||
{
|
||||
cout << "Rendering points ... ";
|
||||
viz::WCloud cloud_widget(point_cloud_est, color);
|
||||
window.showWidget("point_cloud", cloud_widget);
|
||||
cout << "[DONE]" << endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
cout << "Cannot render points: Empty pointcloud" << endl;
|
||||
}
|
||||
/// Add cameras
|
||||
if (path.size() > 0)
|
||||
{
|
||||
cout << "Rendering Cameras ... ";
|
||||
window.showWidget("cameras_frames_and_lines", viz::WTrajectory(path, viz::WTrajectory::BOTH, 0.1, viz::Color::green()));
|
||||
window.showWidget("cameras_frustums", viz::WTrajectoryFrustums(path, K, 0.1, viz::Color::yellow()));
|
||||
window.setViewerPose(path[0]);
|
||||
cout << "[DONE]" << endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
cout << "Cannot render the cameras: Empty path" << endl;
|
||||
}
|
||||
|
||||
/// Wait for key 'q' to close the window
|
||||
cout << endl << "Press 'q' to close each windows ... " << endl;
|
||||
window.spin();
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,126 @@
|
||||
#include <opencv2/sfm.hpp>
|
||||
#include <opencv2/core.hpp>
|
||||
#include <opencv2/viz.hpp>
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
|
||||
using namespace std;
|
||||
using namespace cv;
|
||||
using namespace cv::sfm;
|
||||
|
||||
static void help() {
|
||||
cout
|
||||
<< "\n------------------------------------------------------------------\n"
|
||||
<< " This program shows the two view reconstruction capabilities in the \n"
|
||||
<< " OpenCV Structure From Motion (SFM) module.\n"
|
||||
<< " It uses the following data from the VGG datasets at ...\n"
|
||||
<< " Usage:\n"
|
||||
<< " reconv2_pts.txt \n "
|
||||
<< " where the first line has the number of points and each subsequent \n"
|
||||
<< " line has entries for matched points as: \n"
|
||||
<< " x1 y1 x2 y2 \n"
|
||||
<< "------------------------------------------------------------------\n\n"
|
||||
<< endl;
|
||||
}
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
// Do projective reconstruction
|
||||
bool is_projective = true;
|
||||
|
||||
// Read 2D points from text file
|
||||
|
||||
Mat_<double> x1, x2;
|
||||
int npts;
|
||||
|
||||
if (argc < 2) {
|
||||
help();
|
||||
exit(0);
|
||||
} else {
|
||||
ifstream myfile(argv[1]);
|
||||
if (!myfile.is_open()) {
|
||||
cout << "Unable to read file: " << argv[1] << endl;
|
||||
exit(0);
|
||||
|
||||
} else {
|
||||
string line;
|
||||
|
||||
// Read number of points
|
||||
getline(myfile, line);
|
||||
npts = (int) atof(line.c_str());
|
||||
|
||||
x1 = Mat_<double>(2, npts);
|
||||
x2 = Mat_<double>(2, npts);
|
||||
|
||||
// Read the point coordinates
|
||||
for (int i = 0; i < npts; ++i) {
|
||||
getline(myfile, line);
|
||||
stringstream s(line);
|
||||
string cord;
|
||||
|
||||
s >> cord;
|
||||
x1(0, i) = atof(cord.c_str());
|
||||
s >> cord;
|
||||
x1(1, i) = atof(cord.c_str());
|
||||
|
||||
s >> cord;
|
||||
x2(0, i) = atof(cord.c_str());
|
||||
s >> cord;
|
||||
x2(1, i) = atof(cord.c_str());
|
||||
|
||||
}
|
||||
|
||||
myfile.close();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// Call the reconstruction function
|
||||
|
||||
std::vector < Mat_<double> > points2d;
|
||||
points2d.push_back(x1);
|
||||
points2d.push_back(x2);
|
||||
Matx33d K_estimated;
|
||||
Mat_<double> points3d_estimated;
|
||||
std::vector < cv::Mat > Ps_estimated;
|
||||
|
||||
reconstruct(points2d, Ps_estimated, points3d_estimated, K_estimated, is_projective);
|
||||
|
||||
|
||||
// Print output
|
||||
|
||||
cout << endl;
|
||||
cout << "Projection Matrix of View 1: " << endl;
|
||||
cout << "============================ " << endl;
|
||||
cout << Ps_estimated[0] << endl << endl;
|
||||
cout << "Projection Matrix of View 2: " << endl;
|
||||
cout << "============================ " << endl;
|
||||
cout << Ps_estimated[1] << endl << endl;
|
||||
|
||||
|
||||
// Display 3D points using VIZ module
|
||||
|
||||
// Create the pointcloud
|
||||
std::vector<cv::Vec3f> point_cloud;
|
||||
for (int i = 0; i < npts; ++i) {
|
||||
cv::Vec3f point3d((float) points3d_estimated(0, i),
|
||||
(float) points3d_estimated(1, i),
|
||||
(float) points3d_estimated(2, i));
|
||||
point_cloud.push_back(point3d);
|
||||
}
|
||||
|
||||
// Create a 3D window
|
||||
viz::Viz3d myWindow("Coordinate Frame");
|
||||
|
||||
/// Add coordinate axes
|
||||
myWindow.showWidget("Coordinate Widget", viz::WCoordinateSystem());
|
||||
|
||||
viz::WCloud cloud_widget(point_cloud, viz::Color::green());
|
||||
|
||||
myWindow.showWidget("cloud", cloud_widget);
|
||||
myWindow.spin();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,159 @@
|
||||
#include <opencv2/sfm.hpp>
|
||||
#include <opencv2/viz.hpp>
|
||||
#include <opencv2/geometry.hpp>
|
||||
#include <opencv2/core.hpp>
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
|
||||
using namespace std;
|
||||
using namespace cv;
|
||||
using namespace cv::sfm;
|
||||
|
||||
static void help() {
|
||||
cout
|
||||
<< "\n------------------------------------------------------------------------------------\n"
|
||||
<< " This program shows the multiview reconstruction capabilities in the \n"
|
||||
<< " OpenCV Structure From Motion (SFM) module.\n"
|
||||
<< " It reconstruct a scene from a set of 2D images \n"
|
||||
<< " Usage:\n"
|
||||
<< " example_sfm_scene_reconstruction <path_to_file> <f> <cx> <cy>\n"
|
||||
<< " where: path_to_file is the file absolute path into your system which contains\n"
|
||||
<< " the list of images to use for reconstruction. \n"
|
||||
<< " f is the focal length in pixels. \n"
|
||||
<< " cx is the image principal point x coordinates in pixels. \n"
|
||||
<< " cy is the image principal point y coordinates in pixels. \n"
|
||||
<< "------------------------------------------------------------------------------------\n\n"
|
||||
<< endl;
|
||||
}
|
||||
|
||||
|
||||
static int getdir(const string _filename, vector<String> &files)
|
||||
{
|
||||
ifstream myfile(_filename.c_str());
|
||||
if (!myfile.is_open()) {
|
||||
cout << "Unable to read file: " << _filename << endl;
|
||||
exit(0);
|
||||
} else {;
|
||||
size_t found = _filename.find_last_of("/\\");
|
||||
string line_str, path_to_file = _filename.substr(0, found);
|
||||
while ( getline(myfile, line_str) )
|
||||
files.push_back(path_to_file+string("/")+line_str);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
// Read input parameters
|
||||
|
||||
if ( argc != 5 )
|
||||
{
|
||||
help();
|
||||
exit(0);
|
||||
}
|
||||
|
||||
// Parse the image paths
|
||||
|
||||
vector<String> images_paths;
|
||||
getdir( argv[1], images_paths );
|
||||
|
||||
|
||||
// Build intrinsics
|
||||
|
||||
float f = atof(argv[2]),
|
||||
cx = atof(argv[3]), cy = atof(argv[4]);
|
||||
|
||||
Matx33d K = Matx33d( f, 0, cx,
|
||||
0, f, cy,
|
||||
0, 0, 1);
|
||||
|
||||
|
||||
/// Reconstruct the scene using the 2d images
|
||||
|
||||
bool is_projective = true;
|
||||
vector<Mat> Rs_est, ts_est, points3d_estimated;
|
||||
reconstruct(images_paths, Rs_est, ts_est, K, points3d_estimated, is_projective);
|
||||
|
||||
|
||||
// Print output
|
||||
|
||||
cout << "\n----------------------------\n" << endl;
|
||||
cout << "Reconstruction: " << endl;
|
||||
cout << "============================" << endl;
|
||||
cout << "Estimated 3D points: " << points3d_estimated.size() << endl;
|
||||
cout << "Estimated cameras: " << Rs_est.size() << endl;
|
||||
cout << "Refined intrinsics: " << endl << K << endl << endl;
|
||||
cout << "3D Visualization: " << endl;
|
||||
cout << "============================" << endl;
|
||||
|
||||
|
||||
/// Create 3D windows
|
||||
|
||||
viz::Viz3d window("Coordinate Frame");
|
||||
window.setWindowSize(Size(500,500));
|
||||
window.setWindowPosition(Point(150,150));
|
||||
window.setBackgroundColor(); // black by default
|
||||
|
||||
// Create the pointcloud
|
||||
cout << "Recovering points ... ";
|
||||
|
||||
// recover estimated points3d
|
||||
vector<Vec3f> point_cloud_est;
|
||||
for (int i = 0; i < points3d_estimated.size(); ++i)
|
||||
point_cloud_est.push_back(Vec3f(points3d_estimated[i]));
|
||||
|
||||
cout << "[DONE]" << endl;
|
||||
|
||||
|
||||
/// Recovering cameras
|
||||
cout << "Recovering cameras ... ";
|
||||
|
||||
vector<Affine3d> path;
|
||||
for (size_t i = 0; i < Rs_est.size(); ++i)
|
||||
path.push_back(Affine3d(Rs_est[i],ts_est[i]));
|
||||
|
||||
cout << "[DONE]" << endl;
|
||||
|
||||
|
||||
/// Add the pointcloud
|
||||
if ( point_cloud_est.size() > 0 )
|
||||
{
|
||||
cout << "Rendering points ... ";
|
||||
|
||||
viz::WCloud cloud_widget(point_cloud_est, viz::Color::green());
|
||||
window.showWidget("point_cloud", cloud_widget);
|
||||
|
||||
cout << "[DONE]" << endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
cout << "Cannot render points: Empty pointcloud" << endl;
|
||||
}
|
||||
|
||||
|
||||
/// Add cameras
|
||||
if ( path.size() > 0 )
|
||||
{
|
||||
cout << "Rendering Cameras ... ";
|
||||
|
||||
window.showWidget("cameras_frames_and_lines", viz::WTrajectory(path, viz::WTrajectory::BOTH, 0.1, viz::Color::green()));
|
||||
window.showWidget("cameras_frustums", viz::WTrajectoryFrustums(path, K, 0.1, viz::Color::yellow()));
|
||||
|
||||
window.setViewerPose(path[0]);
|
||||
|
||||
cout << "[DONE]" << endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
cout << "Cannot render the cameras: Empty path" << endl;
|
||||
}
|
||||
|
||||
/// Wait for key 'q' to close the window
|
||||
cout << endl << "Press 'q' to close each windows ... " << endl;
|
||||
|
||||
window.spin();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,244 @@
|
||||
#include <opencv2/core.hpp>
|
||||
#include <opencv2/sfm.hpp>
|
||||
#include <opencv2/viz.hpp>
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
|
||||
using namespace std;
|
||||
using namespace cv;
|
||||
using namespace cv::sfm;
|
||||
|
||||
static void help() {
|
||||
cout
|
||||
<< "\n------------------------------------------------------------------\n"
|
||||
<< " This program shows the camera trajectory reconstruction capabilities\n"
|
||||
<< " in the OpenCV Structure From Motion (SFM) module.\n"
|
||||
<< " \n"
|
||||
<< " Usage:\n"
|
||||
<< " example_sfm_trajectory_reconstruction <path_to_tracks_file> <f> <cx> <cy>\n"
|
||||
<< " where: is the tracks file absolute path into your system. \n"
|
||||
<< " \n"
|
||||
<< " The file must have the following format: \n"
|
||||
<< " row1 : x1 y1 x2 y2 ... x36 y36 for track 1\n"
|
||||
<< " row2 : x1 y1 x2 y2 ... x36 y36 for track 2\n"
|
||||
<< " etc\n"
|
||||
<< " \n"
|
||||
<< " i.e. a row gives the 2D measured position of a point as it is tracked\n"
|
||||
<< " through frames 1 to 36. If there is no match found in a view then x\n"
|
||||
<< " and y are -1.\n"
|
||||
<< " \n"
|
||||
<< " Each row corresponds to a different point.\n"
|
||||
<< " \n"
|
||||
<< " f is the focal length in pixels. \n"
|
||||
<< " cx is the image principal point x coordinates in pixels. \n"
|
||||
<< " cy is the image principal point y coordinates in pixels. \n"
|
||||
<< "------------------------------------------------------------------\n\n"
|
||||
<< endl;
|
||||
}
|
||||
|
||||
|
||||
/* Build the following structure data
|
||||
*
|
||||
* frame1 frame2 frameN
|
||||
* track1 | (x11,y11) | -> | (x12,y12) | -> | (x1N,y1N) |
|
||||
* track2 | (x21,y11) | -> | (x22,y22) | -> | (x2N,y2N) |
|
||||
* trackN | (xN1,yN1) | -> | (xN2,yN2) | -> | (xNN,yNN) |
|
||||
*
|
||||
*
|
||||
* In case a marker (x,y) does not appear in a frame its
|
||||
* values will be (-1,-1).
|
||||
*/
|
||||
|
||||
static void parser_2D_tracks(const String &_filename, std::vector<Mat> &points2d )
|
||||
{
|
||||
ifstream myfile(_filename.c_str());
|
||||
|
||||
if (!myfile.is_open())
|
||||
{
|
||||
cout << "Unable to read file: " << _filename << endl;
|
||||
exit(0);
|
||||
|
||||
} else {
|
||||
|
||||
double x, y;
|
||||
string line_str;
|
||||
int n_frames = 0, n_tracks = 0;
|
||||
|
||||
// extract data from text file
|
||||
|
||||
vector<vector<Vec2d> > tracks;
|
||||
for ( ; getline(myfile,line_str); ++n_tracks)
|
||||
{
|
||||
istringstream line(line_str);
|
||||
|
||||
vector<Vec2d> track;
|
||||
for ( n_frames = 0; line >> x >> y; ++n_frames)
|
||||
{
|
||||
if ( x > 0 && y > 0)
|
||||
track.push_back(Vec2d(x,y));
|
||||
else
|
||||
track.push_back(Vec2d(-1));
|
||||
}
|
||||
tracks.push_back(track);
|
||||
}
|
||||
|
||||
// embed data in reconstruction api format
|
||||
|
||||
for (int i = 0; i < n_frames; ++i)
|
||||
{
|
||||
Mat_<double> frame(2, n_tracks);
|
||||
|
||||
for (int j = 0; j < n_tracks; ++j)
|
||||
{
|
||||
frame(0,j) = tracks[j][i][0];
|
||||
frame(1,j) = tracks[j][i][1];
|
||||
}
|
||||
points2d.push_back(Mat(frame));
|
||||
}
|
||||
|
||||
myfile.close();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/* Keyboard callback to control 3D visualization
|
||||
*/
|
||||
|
||||
bool camera_pov = false;
|
||||
|
||||
static void keyboard_callback(const viz::KeyboardEvent &event, void* cookie)
|
||||
{
|
||||
if ( event.action == 0 &&!event.symbol.compare("s") )
|
||||
camera_pov = !camera_pov;
|
||||
}
|
||||
|
||||
|
||||
/* Sample main code
|
||||
*/
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
// Read input parameters
|
||||
|
||||
if ( argc != 5 )
|
||||
{
|
||||
help();
|
||||
exit(0);
|
||||
}
|
||||
|
||||
// Read 2D points from text file
|
||||
std::vector<Mat> points2d;
|
||||
parser_2D_tracks( argv[1], points2d );
|
||||
|
||||
// Set the camera calibration matrix
|
||||
const double f = atof(argv[2]),
|
||||
cx = atof(argv[3]), cy = atof(argv[4]);
|
||||
|
||||
Matx33d K = Matx33d( f, 0, cx,
|
||||
0, f, cy,
|
||||
0, 0, 1);
|
||||
|
||||
/// Reconstruct the scene using the 2d correspondences
|
||||
|
||||
bool is_projective = true;
|
||||
vector<Mat> Rs_est, ts_est, points3d_estimated;
|
||||
reconstruct(points2d, Rs_est, ts_est, K, points3d_estimated, is_projective);
|
||||
|
||||
// Print output
|
||||
|
||||
cout << "\n----------------------------\n" << endl;
|
||||
cout << "Reconstruction: " << endl;
|
||||
cout << "============================" << endl;
|
||||
cout << "Estimated 3D points: " << points3d_estimated.size() << endl;
|
||||
cout << "Estimated cameras: " << Rs_est.size() << endl;
|
||||
cout << "Refined intrinsics: " << endl << K << endl << endl;
|
||||
|
||||
cout << "3D Visualization: " << endl;
|
||||
cout << "============================" << endl;
|
||||
|
||||
|
||||
/// Create 3D windows
|
||||
viz::Viz3d window_est("Estimation Coordinate Frame");
|
||||
window_est.setBackgroundColor(); // black by default
|
||||
window_est.registerKeyboardCallback(&keyboard_callback);
|
||||
|
||||
// Create the pointcloud
|
||||
cout << "Recovering points ... ";
|
||||
|
||||
// recover estimated points3d
|
||||
vector<Vec3f> point_cloud_est;
|
||||
for (int i = 0; i < points3d_estimated.size(); ++i)
|
||||
point_cloud_est.push_back(Vec3f(points3d_estimated[i]));
|
||||
|
||||
cout << "[DONE]" << endl;
|
||||
|
||||
|
||||
/// Recovering cameras
|
||||
cout << "Recovering cameras ... ";
|
||||
|
||||
vector<Affine3d> path_est;
|
||||
for (size_t i = 0; i < Rs_est.size(); ++i)
|
||||
path_est.push_back(Affine3d(Rs_est[i],ts_est[i]));
|
||||
|
||||
cout << "[DONE]" << endl;
|
||||
|
||||
/// Add cameras
|
||||
cout << "Rendering Trajectory ... ";
|
||||
|
||||
/// Wait for key 'q' to close the window
|
||||
cout << endl << "Press: " << endl;
|
||||
cout << " 's' to switch the camera pov" << endl;
|
||||
cout << " 'q' to close the windows " << endl;
|
||||
|
||||
|
||||
if ( path_est.size() > 0 )
|
||||
{
|
||||
// animated trajectory
|
||||
int idx = 0, forw = -1, n = static_cast<int>(path_est.size());
|
||||
|
||||
while(!window_est.wasStopped())
|
||||
{
|
||||
/// Render points as 3D cubes
|
||||
for (size_t i = 0; i < point_cloud_est.size(); ++i)
|
||||
{
|
||||
Vec3d point = point_cloud_est[i];
|
||||
Affine3d point_pose(Mat::eye(3,3,CV_64F), point);
|
||||
|
||||
char buffer[50];
|
||||
sprintf (buffer, "%d", static_cast<int>(i));
|
||||
|
||||
viz::WCube cube_widget(Point3f(0.1,0.1,0.0), Point3f(0.0,0.0,-0.1), true, viz::Color::blue());
|
||||
cube_widget.setRenderingProperty(viz::LINE_WIDTH, 2.0);
|
||||
window_est.showWidget("Cube"+String(buffer), cube_widget, point_pose);
|
||||
}
|
||||
|
||||
Affine3d cam_pose = path_est[idx];
|
||||
|
||||
viz::WCameraPosition cpw(0.25); // Coordinate axes
|
||||
viz::WCameraPosition cpw_frustum(K, 0.3, viz::Color::yellow()); // Camera frustum
|
||||
|
||||
if ( camera_pov )
|
||||
window_est.setViewerPose(cam_pose);
|
||||
else
|
||||
{
|
||||
// render complete trajectory
|
||||
window_est.showWidget("cameras_frames_and_lines_est", viz::WTrajectory(path_est, viz::WTrajectory::PATH, 1.0, viz::Color::green()));
|
||||
|
||||
window_est.showWidget("CPW", cpw, cam_pose);
|
||||
window_est.showWidget("CPW_FRUSTUM", cpw_frustum, cam_pose);
|
||||
}
|
||||
|
||||
// update trajectory index (spring effect)
|
||||
forw *= (idx==n || idx==0) ? -1: 1; idx += forw;
|
||||
|
||||
// frame rate 1s
|
||||
window_est.spinOnce(1, true);
|
||||
window_est.removeAllWidgets();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,187 @@
|
||||
/*
|
||||
* Software License Agreement (BSD License)
|
||||
*
|
||||
* Copyright (c) 2009, Willow Garage, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer in the documentation and/or other materials provided
|
||||
* with the distribution.
|
||||
* * Neither the name of Willow Garage, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "precomp.hpp"
|
||||
|
||||
// Eigen
|
||||
#include <Eigen/Core>
|
||||
|
||||
// OpenCV
|
||||
#include <opencv2/core/eigen.hpp>
|
||||
#include <opencv2/sfm/conditioning.hpp>
|
||||
|
||||
// libmv headers
|
||||
#include "libmv/multiview/conditioning.h"
|
||||
|
||||
namespace cv
|
||||
{
|
||||
namespace sfm
|
||||
{
|
||||
|
||||
template<typename T>
|
||||
void
|
||||
preconditionerFromPoints( const Mat_<T> &_points,
|
||||
Mat_<T> _Tr )
|
||||
{
|
||||
libmv::Mat points;
|
||||
libmv::Mat3 Tr;
|
||||
|
||||
cv2eigen( _points, points );
|
||||
|
||||
libmv::PreconditionerFromPoints( points, &Tr );
|
||||
|
||||
eigen2cv( Tr, _Tr );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
preconditionerFromPoints( InputArray _points,
|
||||
OutputArray _T )
|
||||
{
|
||||
const Mat points = _points.getMat();
|
||||
const int depth = points.depth();
|
||||
CV_Assert((points.dims == 2 || points.dims == 3) && (depth == CV_32F || depth == CV_64F));
|
||||
|
||||
_T.create(3, 3, depth);
|
||||
|
||||
Mat T = _T.getMat();
|
||||
|
||||
if ( depth == CV_32F )
|
||||
{
|
||||
preconditionerFromPoints<float>(points, T);
|
||||
}
|
||||
else
|
||||
{
|
||||
preconditionerFromPoints<double>(points, T);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void
|
||||
isotropicPreconditionerFromPoints( const Mat_<T> &_points,
|
||||
Mat_<T> _T )
|
||||
{
|
||||
libmv::Mat points;
|
||||
libmv::Mat3 Tr;
|
||||
|
||||
cv2eigen( _points, points );
|
||||
|
||||
libmv::IsotropicPreconditionerFromPoints( points, &Tr );
|
||||
|
||||
eigen2cv( Tr, _T );
|
||||
}
|
||||
|
||||
void
|
||||
isotropicPreconditionerFromPoints( InputArray _points,
|
||||
OutputArray _T )
|
||||
{
|
||||
const Mat points = _points.getMat();
|
||||
const int depth = points.depth();
|
||||
CV_Assert((points.dims == 2 || points.dims == 3) && (depth == CV_32F || depth == CV_64F));
|
||||
|
||||
_T.create(3, 3, depth);
|
||||
|
||||
Mat T = _T.getMat();
|
||||
|
||||
if ( depth == CV_32F )
|
||||
{
|
||||
isotropicPreconditionerFromPoints<float>(points, T);
|
||||
}
|
||||
else
|
||||
{
|
||||
isotropicPreconditionerFromPoints<double>(points, T);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void
|
||||
applyTransformationToPoints( const Mat_<T> &_points,
|
||||
const Mat_<T> &_T,
|
||||
Mat_<T> _transformed_points )
|
||||
{
|
||||
libmv::Mat points, transformed_points;
|
||||
libmv::Mat3 Tr;
|
||||
|
||||
cv2eigen( _points, points );
|
||||
cv2eigen( _T, Tr );
|
||||
|
||||
libmv::ApplyTransformationToPoints( points, Tr, &transformed_points );
|
||||
|
||||
eigen2cv( transformed_points, _transformed_points );
|
||||
}
|
||||
|
||||
void
|
||||
applyTransformationToPoints( InputArray _points,
|
||||
InputArray _T,
|
||||
OutputArray _transformed_points )
|
||||
{
|
||||
const Mat points = _points.getMat(), T = _T.getMat();
|
||||
const int depth = points.depth();
|
||||
CV_Assert((points.dims == 2 || points.dims == 3) && T.size() == Size(3,3) && (depth == CV_32F || depth == CV_64F));
|
||||
|
||||
_transformed_points.create(points.size(), depth);
|
||||
|
||||
Mat transformed_points = _transformed_points.getMat();
|
||||
|
||||
if ( depth == CV_32F )
|
||||
{
|
||||
applyTransformationToPoints<float>(points, T, transformed_points);
|
||||
}
|
||||
else
|
||||
{
|
||||
applyTransformationToPoints<double>(points, T, transformed_points);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
normalizePoints( InputArray points,
|
||||
OutputArray normalized_points,
|
||||
OutputArray T )
|
||||
{
|
||||
preconditionerFromPoints(points, T);
|
||||
applyTransformationToPoints(points, T, normalized_points);
|
||||
}
|
||||
|
||||
void
|
||||
normalizeIsotropicPoints( InputArray points,
|
||||
OutputArray normalized_points,
|
||||
OutputArray T )
|
||||
{
|
||||
isotropicPreconditionerFromPoints(points, T);
|
||||
applyTransformationToPoints(points, T, normalized_points);
|
||||
}
|
||||
|
||||
} /* namespace sfm */
|
||||
} /* namespace cv */
|
||||
@@ -0,0 +1,595 @@
|
||||
/*
|
||||
* Software License Agreement (BSD License)
|
||||
*
|
||||
* Copyright (c) 2009, Willow Garage, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer in the documentation and/or other materials provided
|
||||
* with the distribution.
|
||||
* * Neither the name of Willow Garage, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "precomp.hpp"
|
||||
|
||||
// Eigen
|
||||
#include <Eigen/Core>
|
||||
|
||||
// OpenCV
|
||||
#include <opencv2/core/eigen.hpp>
|
||||
#include <opencv2/sfm/projection.hpp>
|
||||
#include <opencv2/sfm/triangulation.hpp>
|
||||
#include <opencv2/sfm/fundamental.hpp>
|
||||
#include <opencv2/sfm/numeric.hpp>
|
||||
#include <opencv2/sfm/conditioning.hpp>
|
||||
|
||||
// libmv headers
|
||||
#include "libmv/multiview/fundamental.h"
|
||||
|
||||
#include <iostream>
|
||||
using namespace std;
|
||||
|
||||
namespace cv
|
||||
{
|
||||
namespace sfm
|
||||
{
|
||||
template<typename T>
|
||||
void
|
||||
projectionsFromFundamental( const Mat_<T> &F,
|
||||
Mat_<T> P1,
|
||||
Mat_<T> P2 )
|
||||
{
|
||||
P1 << 1, 0, 0, 0,
|
||||
0, 1, 0, 0,
|
||||
0, 0, 1, 0;
|
||||
|
||||
Vec<T,3> e2;
|
||||
cv::SVD::solveZ(F.t(), e2);
|
||||
|
||||
Mat_<T> P2cols = skew(e2) * F;
|
||||
for(char j=0;j<3;++j) {
|
||||
for(char i=0;i<3;++i)
|
||||
P2(j,i) = P2cols(j,i);
|
||||
P2(j,3) = e2(j);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
projectionsFromFundamental( InputArray _F,
|
||||
OutputArray _P1,
|
||||
OutputArray _P2 )
|
||||
{
|
||||
const Mat F = _F.getMat();
|
||||
const int depth = F.depth();
|
||||
CV_Assert(F.cols == 3 && F.rows == 3 && (depth == CV_32F || depth == CV_64F));
|
||||
|
||||
_P1.create(3, 4, depth);
|
||||
_P2.create(3, 4, depth);
|
||||
|
||||
Mat P1 = _P1.getMat(), P2 = _P2.getMat();
|
||||
|
||||
// type
|
||||
if( depth == CV_32F )
|
||||
{
|
||||
projectionsFromFundamental<float>(F, P1, P2);
|
||||
}
|
||||
else
|
||||
{
|
||||
projectionsFromFundamental<double>(F, P1, P2);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void
|
||||
fundamentalFromProjections( const Mat_<T> &P1,
|
||||
const Mat_<T> &P2,
|
||||
Mat_<T> F )
|
||||
{
|
||||
Mat_<T> X[3];
|
||||
vconcat( P1.row(1), P1.row(2), X[0] );
|
||||
vconcat( P1.row(2), P1.row(0), X[1] );
|
||||
vconcat( P1.row(0), P1.row(1), X[2] );
|
||||
|
||||
Mat_<T> Y[3];
|
||||
vconcat( P2.row(1), P2.row(2), Y[0] );
|
||||
vconcat( P2.row(2), P2.row(0), Y[1] );
|
||||
vconcat( P2.row(0), P2.row(1), Y[2] );
|
||||
|
||||
Mat_<T> XY;
|
||||
for (int i = 0; i < 3; ++i)
|
||||
for (int j = 0; j < 3; ++j)
|
||||
{
|
||||
vconcat(X[j], Y[i], XY);
|
||||
F(i, j) = determinant(XY);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
fundamentalFromProjections( InputArray _P1,
|
||||
InputArray _P2,
|
||||
OutputArray _F )
|
||||
{
|
||||
const Mat P1 = _P1.getMat(), P2 = _P2.getMat();
|
||||
const int depth = P1.depth();
|
||||
CV_Assert((P1.cols == 4 && P1.rows == 3) && P1.rows == P2.rows && P1.cols == P2.cols);
|
||||
CV_Assert((depth == CV_32F || depth == CV_64F) && depth == P2.depth());
|
||||
|
||||
_F.create(3, 3, depth);
|
||||
|
||||
Mat F = _F.getMat();
|
||||
|
||||
// type
|
||||
if( depth == CV_32F )
|
||||
{
|
||||
fundamentalFromProjections<float>(P1, P2, F);
|
||||
}
|
||||
else
|
||||
{
|
||||
fundamentalFromProjections<double>(P1, P2, F);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void
|
||||
normalizedEightPointSolver( const Mat_<T> &_x1,
|
||||
const Mat_<T> &_x2,
|
||||
Mat_<T> _F )
|
||||
{
|
||||
libmv::Mat x1, x2;
|
||||
libmv::Mat3 F;
|
||||
|
||||
cv2eigen(_x1, x1);
|
||||
cv2eigen(_x2, x2);
|
||||
|
||||
libmv::NormalizedEightPointSolver(x1, x2, &F);
|
||||
|
||||
eigen2cv(F, _F);
|
||||
}
|
||||
|
||||
void
|
||||
normalizedEightPointSolver( InputArray _x1, InputArray _x2, OutputArray _F )
|
||||
{
|
||||
const Mat x1 = _x1.getMat(), x2 = _x2.getMat();
|
||||
const int depth = x1.depth();
|
||||
CV_Assert(x1.dims == 2 && x1.dims == x2.dims && (depth == CV_32F || depth == CV_64F));
|
||||
|
||||
_F.create(3, 3, depth);
|
||||
|
||||
Mat F = _F.getMat();
|
||||
|
||||
// type
|
||||
if( depth == CV_32F )
|
||||
{
|
||||
normalizedEightPointSolver<float>(x1, x2, F);
|
||||
}
|
||||
else
|
||||
{
|
||||
normalizedEightPointSolver<double>(x1, x2, F);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void
|
||||
relativeCameraMotion( const Mat_<T> &R1,
|
||||
const Mat_<T> &t1,
|
||||
const Mat_<T> &R2,
|
||||
const Mat_<T> &t2,
|
||||
Mat_<T> R,
|
||||
Mat_<T> t )
|
||||
{
|
||||
R = R2 * R1.t();
|
||||
t = t2 - R * t1;
|
||||
}
|
||||
|
||||
void
|
||||
relativeCameraMotion( InputArray _R1, InputArray _t1, InputArray _R2,
|
||||
InputArray _t2, OutputArray _R, OutputArray _t )
|
||||
{
|
||||
const Mat R1 = _R1.getMat(), t1 = _t1.getMat(), R2 = _R2.getMat(), t2 = _t2.getMat();
|
||||
const int depth = R1.depth();
|
||||
CV_Assert((R1.cols == 3 && R1.rows == 3) && (R1.size() == R2.size()));
|
||||
CV_Assert((t1.cols == 1 && t1.rows == 3) && (t1.size() == t2.size()));
|
||||
CV_Assert((depth == CV_32F || depth == CV_64F) && depth == R2.depth() && depth == t1.depth() && depth == t2.depth());
|
||||
|
||||
_R.create(3, 3, depth);
|
||||
_t.create(3, 1, depth);
|
||||
|
||||
Mat R = _R.getMat(), t = _t.getMat();
|
||||
|
||||
// type
|
||||
if( depth == CV_32F )
|
||||
{
|
||||
relativeCameraMotion<float>(R1, t1, R2, t2, R, t);
|
||||
}
|
||||
else
|
||||
{
|
||||
relativeCameraMotion<double>(R1, t1, R2, t2, R, t);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void
|
||||
motionFromEssential( const Mat_<T> &_E,
|
||||
std::vector<Mat> &_Rs,
|
||||
std::vector<Mat> &_ts )
|
||||
{
|
||||
libmv::Mat3 E;
|
||||
std::vector < libmv::Mat3 > Rs;
|
||||
std::vector < libmv::Vec3 > ts;
|
||||
|
||||
cv2eigen(_E, E);
|
||||
|
||||
libmv::MotionFromEssential(E, &Rs, &ts);
|
||||
|
||||
_Rs.clear();
|
||||
_ts.clear();
|
||||
|
||||
int n = Rs.size();
|
||||
CV_Assert(ts.size() == n);
|
||||
|
||||
for ( int i = 0; i < n; ++i )
|
||||
{
|
||||
Mat_<T> R_temp, t_temp;
|
||||
|
||||
eigen2cv(Rs[i], R_temp);
|
||||
_Rs.push_back(R_temp);
|
||||
|
||||
eigen2cv(ts[i], t_temp);
|
||||
_ts.push_back(t_temp);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
motionFromEssential( InputArray _E, OutputArrayOfArrays _Rs,
|
||||
OutputArrayOfArrays _ts )
|
||||
{
|
||||
const Mat E = _E.getMat();
|
||||
const int depth = E.depth(), cn = 4;
|
||||
CV_Assert(E.cols == 3 && E.rows == 3 && (depth == CV_32F || depth == CV_64F));
|
||||
|
||||
_Rs.create(cn, 1, depth);
|
||||
_ts.create(cn, 1, depth);
|
||||
for (int i = 0; i < cn; ++i)
|
||||
{
|
||||
_Rs.create(Size(3,3), depth, i);
|
||||
_ts.create(Size(3,1), depth, i);
|
||||
}
|
||||
|
||||
std::vector<Mat> Rs, ts;
|
||||
_Rs.getMatVector(Rs);
|
||||
_ts.getMatVector(ts);
|
||||
|
||||
// type
|
||||
if( depth == CV_32F )
|
||||
{
|
||||
motionFromEssential<float>(E, Rs, ts);
|
||||
}
|
||||
else
|
||||
{
|
||||
motionFromEssential<double>(E, Rs, ts);
|
||||
}
|
||||
|
||||
for (int i = 0; i < cn; ++i)
|
||||
{
|
||||
Rs[i].copyTo(_Rs.getMatRef(i));
|
||||
ts[i].copyTo(_ts.getMatRef(i));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
int motionFromEssentialChooseSolution( const std::vector<Mat> &Rs,
|
||||
const std::vector<Mat> &ts,
|
||||
const Mat_<T> &K1,
|
||||
const Mat_<T> &x1,
|
||||
const Mat_<T> &K2,
|
||||
const Mat_<T> &x2 )
|
||||
{
|
||||
Mat_<T> P1, P2, R1 = Mat_<T>::eye(3,3);
|
||||
|
||||
T val = static_cast<T>(0.0);
|
||||
Vec<T,3> t1(val, val, val);
|
||||
|
||||
projectionFromKRt(K1, R1, t1, P1);
|
||||
|
||||
std::vector<Mat_<T> > points2d;
|
||||
points2d.push_back(x1);
|
||||
points2d.push_back(x2);
|
||||
|
||||
for ( int i = 0; i < 4; ++i )
|
||||
{
|
||||
const Mat_<T> R2 = Rs[i];
|
||||
const Vec<T,3> t2 = ts[i];
|
||||
projectionFromKRt(K2, R2, t2, P2);
|
||||
|
||||
std::vector<Mat_<T> > Ps;
|
||||
Ps.push_back(P1);
|
||||
Ps.push_back(P2);
|
||||
|
||||
Vec<T,3> X;
|
||||
triangulatePoints(points2d, Ps, X);
|
||||
|
||||
T d1 = depth(R1, t1, X);
|
||||
T d2 = depth(R2, t2, X);
|
||||
|
||||
// Test if point is front to the two cameras.
|
||||
if ( d1 > 0 && d2 > 0 )
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int motionFromEssentialChooseSolution( InputArrayOfArrays _Rs,
|
||||
InputArrayOfArrays _ts,
|
||||
InputArray _K1,
|
||||
InputArray _x1,
|
||||
InputArray _K2,
|
||||
InputArray _x2 )
|
||||
{
|
||||
std::vector<Mat> Rs, ts;
|
||||
_Rs.getMatVector(Rs);
|
||||
_ts.getMatVector(ts);
|
||||
const Mat K1 = _K1.getMat(), x1 = _x1.getMat(), K2 = _K2.getMat(), x2 = _x2.getMat();
|
||||
const int depth = K1.depth();
|
||||
CV_Assert( Rs.size() == 4 && ts.size() == 4 );
|
||||
CV_Assert((K1.cols == 3 && K1.rows == 3) && (K1.size() == K2.size()));
|
||||
CV_Assert((x1.cols == 1 && x1.rows == 2) && (x1.size() == x2.size()));
|
||||
CV_Assert((depth == CV_32F || depth == CV_64F) && depth == K2.depth() && depth == x1.depth() && depth == x2.depth());
|
||||
|
||||
int solution = 0;
|
||||
|
||||
// type
|
||||
if( depth == CV_32F )
|
||||
{
|
||||
solution = motionFromEssentialChooseSolution<float>(Rs, ts, K1, x1, K2, x2);
|
||||
}
|
||||
else
|
||||
{
|
||||
solution = motionFromEssentialChooseSolution<double>(Rs, ts, K1, x1, K2, x2);
|
||||
}
|
||||
|
||||
return solution;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void
|
||||
fundamentalFromEssential( const Mat_<T> &E,
|
||||
const Mat_<T> &K1,
|
||||
const Mat_<T> &K2,
|
||||
Mat_<T> F )
|
||||
{
|
||||
F = K2.inv().t() * E * K1.inv();
|
||||
}
|
||||
|
||||
void
|
||||
fundamentalFromEssential( InputArray _E,
|
||||
InputArray _K1,
|
||||
InputArray _K2,
|
||||
OutputArray _F )
|
||||
{
|
||||
const Mat E = _E.getMat(), K1 = _K1.getMat(), K2 = _K2.getMat();
|
||||
const int depth = E.depth();
|
||||
CV_Assert(E.cols == 3 && E.rows == 3 && E.size() == _K1.size() && E.size() == _K2.size() && (depth == CV_32F || depth == CV_64F));
|
||||
|
||||
_F.create(3, 3, depth);
|
||||
|
||||
Mat F = _F.getMat();
|
||||
|
||||
// type
|
||||
if( depth == CV_32F )
|
||||
{
|
||||
fundamentalFromEssential<float>(E, K1, K2, F);
|
||||
}
|
||||
else
|
||||
{
|
||||
fundamentalFromEssential<double>(E, K1, K2, F);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void
|
||||
essentialFromFundamental( const Mat_<T> &F,
|
||||
const Mat_<T> &K1,
|
||||
const Mat_<T> &K2,
|
||||
Mat_<T> E )
|
||||
{
|
||||
E = K2.t() * F * K1;
|
||||
}
|
||||
|
||||
void
|
||||
essentialFromFundamental( InputArray _F,
|
||||
InputArray _K1,
|
||||
InputArray _K2,
|
||||
OutputArray _E )
|
||||
{
|
||||
const Mat F = _F.getMat(), K1 = _K1.getMat(), K2 = _K2.getMat();
|
||||
const int depth = F.depth();
|
||||
CV_Assert(F.cols == 3 && F.rows == 3 && F.size() == _K1.size() && F.size() == _K2.size() && (depth == CV_32F || depth == CV_64F));
|
||||
|
||||
_E.create(3, 3, depth);
|
||||
|
||||
Mat E = _E.getMat();
|
||||
|
||||
// type
|
||||
if( depth == CV_32F )
|
||||
{
|
||||
essentialFromFundamental<float>(F, K1, K2, E);
|
||||
}
|
||||
else
|
||||
{
|
||||
essentialFromFundamental<double>(F, K1, K2, E);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void
|
||||
essentialFromRt( const Mat_<T> &_R1,
|
||||
const Mat_<T> &_t1,
|
||||
const Mat_<T> &_R2,
|
||||
const Mat_<T> &_t2,
|
||||
Mat_<T> _E )
|
||||
{
|
||||
libmv::Mat3 E;
|
||||
libmv::Mat3 R1, R2;
|
||||
libmv::Vec3 t1, t2;
|
||||
|
||||
cv2eigen( _R1, R1 );
|
||||
cv2eigen( _t1, t1 );
|
||||
cv2eigen( _R2, R2 );
|
||||
cv2eigen( _t2, t2 );
|
||||
|
||||
libmv::EssentialFromRt( R1, t1, R2, t2, &E );
|
||||
|
||||
eigen2cv( E, _E );
|
||||
}
|
||||
|
||||
void
|
||||
essentialFromRt( InputArray _R1,
|
||||
InputArray _t1,
|
||||
InputArray _R2,
|
||||
InputArray _t2,
|
||||
OutputArray _E )
|
||||
{
|
||||
const Mat R1 = _R1.getMat(), t1 = _t1.getMat(), R2 = _R2.getMat(), t2 = _t2.getMat();
|
||||
const int depth = R1.depth();
|
||||
CV_Assert((R1.cols == 3 && R1.rows == 3) && (R1.size() == R2.size()));
|
||||
CV_Assert((t1.cols == 1 && t1.rows == 3) && (t1.size() == t2.size()));
|
||||
CV_Assert((depth == CV_32F || depth == CV_64F) && depth == R2.depth() && depth == t1.depth() && depth == t2.depth());
|
||||
|
||||
_E.create(3, 3, depth);
|
||||
|
||||
Mat E = _E.getMat();
|
||||
|
||||
// type
|
||||
if( depth == CV_32F )
|
||||
{
|
||||
essentialFromRt<float>(R1, t1, R2, t2, E);
|
||||
}
|
||||
else
|
||||
{
|
||||
essentialFromRt<double>(R1, t1, R2, t2, E);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void
|
||||
normalizeFundamental( const Mat_<T> &F, Mat_<T> F_normalized )
|
||||
{
|
||||
F_normalized = F * (1.0/norm(F,NORM_L2)); // Frobenius Norm
|
||||
|
||||
if ( F_normalized(2,2) < 0 )
|
||||
{
|
||||
F_normalized *= -1;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
normalizeFundamental( InputArray _F,
|
||||
OutputArray _F_normalized )
|
||||
{
|
||||
const Mat F = _F.getMat();
|
||||
const int depth = F.depth();
|
||||
CV_Assert(F.cols == 3 && F.rows == 3 && (depth == CV_32F || depth == CV_64F));
|
||||
|
||||
_F_normalized.create(3, 3, depth);
|
||||
|
||||
Mat F_normalized = _F_normalized.getMat();
|
||||
|
||||
// type
|
||||
if( depth == CV_32F )
|
||||
{
|
||||
normalizeFundamental<float>(F, F_normalized);
|
||||
}
|
||||
else
|
||||
{
|
||||
normalizeFundamental<double>(F, F_normalized);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void
|
||||
computeOrientation( const Mat_<T> &x1,
|
||||
const Mat_<T> &x2,
|
||||
Mat_<T> R,
|
||||
Mat_<T> t,
|
||||
T s )
|
||||
{
|
||||
Mat_<T> rr, rl, rt, lt;
|
||||
normalizePoints(x1, rr, rt);
|
||||
normalizePoints(x2, rl, lt);
|
||||
|
||||
Mat_<T> rrBar, rlBar, rVar, lVar;
|
||||
meanAndVarianceAlongRows(rr, rrBar, rVar);
|
||||
meanAndVarianceAlongRows(rl, rlBar, lVar);
|
||||
|
||||
Mat_<T> rrp, rlp;
|
||||
rrp = rr - repeat(rrBar, x1.rows, x1.cols);
|
||||
rlp = rl - repeat(rlBar, x2.rows, x2.cols);
|
||||
|
||||
// TODO: finish implementation
|
||||
// https://github.com/vrabaud/sfm_toolbox/blob/master/sfm/computeOrientation.m#L44
|
||||
}
|
||||
|
||||
void
|
||||
computeOrientation( InputArrayOfArrays _x1,
|
||||
InputArrayOfArrays _x2,
|
||||
OutputArray _R,
|
||||
OutputArray _t,
|
||||
double s )
|
||||
{
|
||||
const Mat x1 = _x1.getMat(), x2 = _x2.getMat();
|
||||
const int depth = x1.depth();
|
||||
CV_Assert(x1.size() == x2.size() && (depth == CV_32F || depth == CV_64F));
|
||||
|
||||
_R.create(3, 3, depth);
|
||||
_t.create(3, 1, depth);
|
||||
|
||||
Mat R = _R.getMat(), t = _t.getMat();
|
||||
|
||||
// type
|
||||
if( depth == CV_32F )
|
||||
{
|
||||
computeOrientation<float>(x1, x2, R, t, s);
|
||||
}
|
||||
else
|
||||
{
|
||||
computeOrientation<double>(x1, x2, R, t, s);
|
||||
}
|
||||
}
|
||||
|
||||
} /* namespace sfm */
|
||||
} /* namespace cv */
|
||||
@@ -0,0 +1,92 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2015, OpenCV Foundation, all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#include <opencv2/sfm/io.hpp>
|
||||
#include "io/io_bundler.h"
|
||||
|
||||
namespace cv
|
||||
{
|
||||
namespace sfm
|
||||
{
|
||||
|
||||
void
|
||||
importReconstruction(const cv::String &file, OutputArrayOfArrays _Rs,
|
||||
OutputArrayOfArrays _Ts, OutputArrayOfArrays _Ks,
|
||||
OutputArrayOfArrays _points3d, int file_format) {
|
||||
|
||||
std::vector<Matx33d> Rs, Ks;
|
||||
std::vector<Vec3d> Ts, points3d;
|
||||
|
||||
if (file_format == SFM_IO_BUNDLER) {
|
||||
readBundlerFile(file, Rs, Ts, Ks, points3d);
|
||||
} else if (file_format == SFM_IO_VISUALSFM) {
|
||||
CV_Error(Error::StsNotImplemented, "The requested function/feature is not implemented");
|
||||
} else if (file_format == SFM_IO_OPENSFM) {
|
||||
CV_Error(Error::StsNotImplemented, "The requested function/feature is not implemented");
|
||||
} else if (file_format == SFM_IO_OPENMVG) {
|
||||
CV_Error(Error::StsNotImplemented, "The requested function/feature is not implemented");
|
||||
} else if (file_format == SFM_IO_THEIASFM) {
|
||||
CV_Error(Error::StsNotImplemented, "The requested function/feature is not implemented");
|
||||
} else {
|
||||
CV_Error(Error::StsBadArg, "The file format one of SFM_IO_BUNDLER, SFM_IO_VISUALSFM, SFM_IO_OPENSFM, SFM_IO_OPENMVG or SFM_IO_THEIASFM");
|
||||
}
|
||||
|
||||
const size_t num_cameras = Rs.size();
|
||||
const size_t num_points = points3d.size();
|
||||
|
||||
_Rs.create(num_cameras, 1, CV_64F);
|
||||
_Ts.create(num_cameras, 1, CV_64F);
|
||||
_Ks.create(num_cameras, 1, CV_64F);
|
||||
_points3d.create(num_points, 1, CV_64F);
|
||||
|
||||
for (size_t i = 0; i < num_cameras; ++i) {
|
||||
Mat(Rs[i]).copyTo(_Rs.getMatRef(i));
|
||||
Mat(Ts[i]).copyTo(_Ts.getMatRef(i));
|
||||
Mat(Ks[i]).copyTo(_Ks.getMatRef(i));
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < num_points; ++i)
|
||||
Mat(points3d[i]).copyTo(_points3d.getMatRef(i));
|
||||
}
|
||||
|
||||
|
||||
} /* namespace sfm */
|
||||
} /* namespace cv */
|
||||
@@ -0,0 +1,189 @@
|
||||
/*
|
||||
Based on TheiaSfM library.
|
||||
https://github.com/sweeneychris/TheiaSfM/blob/master/src/theia/io/read_bundler_files.cc
|
||||
|
||||
Adapted by Edgar Riba <edgar.riba@gmail.com>
|
||||
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <opencv2/core.hpp>
|
||||
|
||||
// The bundle files contain the estimated scene and camera geometry have the
|
||||
// following format:
|
||||
// # Bundle file v0.3
|
||||
// <num_cameras> <num_points> [two integers]
|
||||
// <camera1>
|
||||
// <camera2>
|
||||
// ...
|
||||
// <cameraN>
|
||||
// <point1>
|
||||
// <point2>
|
||||
// ...
|
||||
// <pointM>
|
||||
// Each camera entry <cameraI> contains the estimated camera intrinsics and
|
||||
// extrinsics, and has the form:
|
||||
// <f> <k1> <k2> [the focal length, followed by two radial distortion
|
||||
// coeffs]
|
||||
// <R> [a 3x3 matrix representing the camera rotation]
|
||||
// <t> [a 3-vector describing the camera translation]
|
||||
// The cameras are specified in the order they appear in the list of images.
|
||||
//
|
||||
// Each point entry has the form:
|
||||
// <position> [a 3-vector describing the 3D position of the point]
|
||||
// <color> [a 3-vector describing the RGB color of the point]
|
||||
// <view list> [a list of views the point is visible in]
|
||||
//
|
||||
// The view list begins with the length of the list (i.e., the number of cameras
|
||||
// the point is visible in). The list is then given as a list of quadruplets
|
||||
// <camera> <key> <x> <y>, where <camera> is a camera index, <key> the index of
|
||||
// the SIFT keypoint where the point was detected in that camera, and <x> and
|
||||
// <y> are the detected positions of that keypoint. Both indices are 0-based
|
||||
// (e.g., if camera 0 appears in the list, this corresponds to the first camera
|
||||
// in the scene file and the first image in "list.txt"). The pixel positions are
|
||||
// floating point numbers in a coordinate system where the origin is the center
|
||||
// of the image, the x-axis increases to the right, and the y-axis increases
|
||||
// towards the top of the image. Thus, (-w/2, -h/2) is the lower-left corner of
|
||||
// the image, and (w/2, h/2) is the top-right corner (where w and h are the
|
||||
// width and height of the image).
|
||||
static bool readBundlerFile(const std::string &file,
|
||||
std::vector<cv::Matx33d> &Rs,
|
||||
std::vector<cv::Vec3d> &Ts,
|
||||
std::vector<cv::Matx33d> &Ks,
|
||||
std::vector<cv::Vec3d> &points3d) {
|
||||
|
||||
// Read in num cameras, num points.
|
||||
std::ifstream ifs(file.c_str(), std::ios::in);
|
||||
if (!ifs.is_open()) {
|
||||
std::cout << "Cannot read the file from " << file << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
const cv::Matx33d bundler_to_opencv(1, 0, 0, 0, -1, 0, 0, 0, -1);
|
||||
|
||||
std::string header_string;
|
||||
std::getline(ifs, header_string);
|
||||
|
||||
// If the first line starts with '#' then it is a comment, so skip it!
|
||||
if (header_string[0] == '#') {
|
||||
std::getline(ifs, header_string);
|
||||
}
|
||||
const char* p = header_string.c_str();
|
||||
char* p2;
|
||||
const int num_cameras = strtol(p, &p2, 10);
|
||||
|
||||
p = p2;
|
||||
const int num_points = strtol(p, &p2, 10);
|
||||
|
||||
// Read in the camera params.
|
||||
for (int i = 0; i < num_cameras; i++) {
|
||||
// Read in focal length, radial distortion.
|
||||
std::string internal_params;
|
||||
std::getline(ifs, internal_params);
|
||||
p = internal_params.c_str();
|
||||
const double focal_length = strtod(p, &p2);
|
||||
p = p2;
|
||||
//const double k1 = strtod(p, &p2);
|
||||
p = p2;
|
||||
//const double k2 = strtod(p, &p2);
|
||||
p = p2;
|
||||
|
||||
cv::Matx33d intrinsics;
|
||||
intrinsics(0,0) = intrinsics(1,1) = focal_length;
|
||||
Ks.push_back(intrinsics);
|
||||
|
||||
// Read in rotation (row-major).
|
||||
cv::Matx33d rotation;
|
||||
for (int r = 0; r < 3; r++) {
|
||||
std::string rotation_row;
|
||||
std::getline(ifs, rotation_row);
|
||||
p = rotation_row.c_str();
|
||||
|
||||
for (int c = 0; c < 3; c++) {
|
||||
rotation(r, c) = strtod(p, &p2);
|
||||
p = p2;
|
||||
}
|
||||
}
|
||||
|
||||
std::string translation_string;
|
||||
std::getline(ifs, translation_string);
|
||||
p = translation_string.c_str();
|
||||
cv::Vec3d translation;
|
||||
for (int j = 0; j < 3; j++) {
|
||||
translation(j) = strtod(p, &p2);
|
||||
p = p2;
|
||||
}
|
||||
|
||||
rotation = bundler_to_opencv * rotation;
|
||||
translation = bundler_to_opencv * translation;
|
||||
|
||||
cv::Matx33d rotation_t = rotation.t();
|
||||
translation = -1.0 * rotation_t * translation;
|
||||
|
||||
Rs.push_back(rotation);
|
||||
Ts.push_back(translation);
|
||||
|
||||
if ((i + 1) % 100 == 0 || i == num_cameras - 1) {
|
||||
std::cout << "\r Loading parameters for camera " << i + 1 << " / "
|
||||
<< num_cameras << std::flush;
|
||||
}
|
||||
}
|
||||
std::cout << std::endl;
|
||||
|
||||
// Read in each 3D point and correspondences.
|
||||
for (int i = 0; i < num_points; i++) {
|
||||
// Read position.
|
||||
std::string position_str;
|
||||
std::getline(ifs, position_str);
|
||||
p = position_str.c_str();
|
||||
cv::Vec3d position;
|
||||
for (int j = 0; j < 3; j++) {
|
||||
position(j) = strtod(p, &p2);
|
||||
p = p2;
|
||||
}
|
||||
points3d.push_back(position);
|
||||
|
||||
// Read color.
|
||||
std::string color_str;
|
||||
std::getline(ifs, color_str);
|
||||
p = color_str.c_str();
|
||||
cv::Vec3d color;
|
||||
for (int j = 0; j < 3; j++) {
|
||||
color(j) = static_cast<double>(strtol(p, &p2, 10)) / 255.0;
|
||||
p = p2;
|
||||
}
|
||||
|
||||
// Read viewlist.
|
||||
std::string view_list_string;
|
||||
std::getline(ifs, view_list_string);
|
||||
p = view_list_string.c_str();
|
||||
const int num_views = strtol(p, &p2, 10);
|
||||
p = p2;
|
||||
|
||||
// Reserve the view list for this 3D point.
|
||||
for (int j = 0; j < num_views; j++) {
|
||||
// Camera key x y
|
||||
//const int camera_index = strtol(p, &p2, 10);
|
||||
p = p2;
|
||||
// Returns the index of the sift descriptor in the camera for this track.
|
||||
strtol(p, &p2, 10);
|
||||
p = p2;
|
||||
//const float x_pos = strtof(p, &p2);
|
||||
p = p2;
|
||||
//const float y_pos = strtof(p, &p2);
|
||||
p = p2;
|
||||
|
||||
}
|
||||
|
||||
if ((i + 1) % 100 == 0 || i == num_points - 1) {
|
||||
std::cout << "\r Loading 3D points " << i + 1 << " / " << num_points
|
||||
<< std::flush;
|
||||
}
|
||||
}
|
||||
|
||||
std::cout << std::endl;
|
||||
ifs.close();
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -0,0 +1,446 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2015, OpenCV Foundation, all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#ifndef __OPENCV_SFM_LIBMV_CAPI__
|
||||
#define __OPENCV_SFM_LIBMV_CAPI__
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "libmv/logging/logging.h"
|
||||
|
||||
#include "libmv/correspondence/feature.h"
|
||||
#include "libmv/correspondence/feature_matching.h"
|
||||
#include "libmv/correspondence/matches.h"
|
||||
#include "libmv/correspondence/nRobustViewMatching.h"
|
||||
|
||||
#include "libmv/simple_pipeline/bundle.h"
|
||||
#include "libmv/simple_pipeline/camera_intrinsics.h"
|
||||
#include "libmv/simple_pipeline/keyframe_selection.h"
|
||||
#include "libmv/simple_pipeline/initialize_reconstruction.h"
|
||||
#include "libmv/simple_pipeline/pipeline.h"
|
||||
#include "libmv/simple_pipeline/reconstruction_scale.h"
|
||||
#include "libmv/simple_pipeline/tracks.h"
|
||||
#include "gflags/gflags.h"
|
||||
|
||||
using namespace cv;
|
||||
using namespace cv::sfm;
|
||||
using namespace libmv;
|
||||
|
||||
using namespace google;
|
||||
|
||||
namespace gflags {}
|
||||
using namespace gflags;
|
||||
|
||||
////////////////////////////////////////
|
||||
// Based on 'libmv_capi' (blender API)
|
||||
///////////////////////////////////////
|
||||
|
||||
struct libmv_Reconstruction {
|
||||
EuclideanReconstruction reconstruction;
|
||||
/* Used for per-track average error calculation after reconstruction */
|
||||
Tracks tracks;
|
||||
std::shared_ptr<CameraIntrinsics> intrinsics;
|
||||
double error;
|
||||
bool is_valid;
|
||||
};
|
||||
|
||||
|
||||
//////////////////////////////////////
|
||||
// Based on 'libmv_capi' (blender API)
|
||||
/////////////////////////////////////
|
||||
|
||||
static void libmv_initLogging(const char* argv0) {
|
||||
// Make it so FATAL messages are always print into console.
|
||||
char severity_fatal[32];
|
||||
static int initLog=0;
|
||||
snprintf(severity_fatal, sizeof(severity_fatal), "%d",
|
||||
GLOG_FATAL);
|
||||
|
||||
if (!initLog)
|
||||
InitGoogleLogging(argv0);
|
||||
initLog=1;
|
||||
SetCommandLineOption("logtostderr", "1");
|
||||
SetCommandLineOption("v", "0");
|
||||
SetCommandLineOption("stderrthreshold", severity_fatal);
|
||||
SetCommandLineOption("minloglevel", severity_fatal);
|
||||
}
|
||||
|
||||
static void libmv_startDebugLogging(void) {
|
||||
SetCommandLineOption("logtostderr", "1");
|
||||
SetCommandLineOption("v", "2");
|
||||
SetCommandLineOption("stderrthreshold", "1");
|
||||
SetCommandLineOption("minloglevel", "0");
|
||||
}
|
||||
|
||||
static void libmv_setLoggingVerbosity(int verbosity) {
|
||||
char val[10];
|
||||
snprintf(val, sizeof(val), "%d", verbosity);
|
||||
SetCommandLineOption("v", val);
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Based on the 'selectTwoKeyframesBasedOnGRICAndVariance()' function from 'libmv_capi' (blender API)
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/* Select the two keyframes that give a lower reprojection error
|
||||
*/
|
||||
|
||||
static bool selectTwoKeyframesBasedOnGRICAndVariance(
|
||||
Tracks& tracks,
|
||||
Tracks& normalized_tracks,
|
||||
CameraIntrinsics& camera_intrinsics,
|
||||
int& keyframe1,
|
||||
int& keyframe2) {
|
||||
|
||||
libmv::vector<int> keyframes;
|
||||
|
||||
/* Get list of all keyframe candidates first. */
|
||||
SelectKeyframesBasedOnGRICAndVariance(normalized_tracks,
|
||||
camera_intrinsics,
|
||||
keyframes);
|
||||
|
||||
if (keyframes.size() < 2) {
|
||||
LG << "Not enough keyframes detected by GRIC";
|
||||
return false;
|
||||
} else if (keyframes.size() == 2) {
|
||||
keyframe1 = keyframes[0];
|
||||
keyframe2 = keyframes[1];
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Now choose two keyframes with minimal reprojection error after initial
|
||||
* reconstruction choose keyframes with the least reprojection error after
|
||||
* solving from two candidate keyframes.
|
||||
*
|
||||
* In fact, currently libmv returns single pair only, so this code will
|
||||
* not actually run. But in the future this could change, so let's stay
|
||||
* prepared.
|
||||
*/
|
||||
int previous_keyframe = keyframes[0];
|
||||
double best_error = std::numeric_limits<double>::max();
|
||||
for (int i = 1; i < keyframes.size(); i++) {
|
||||
EuclideanReconstruction reconstruction;
|
||||
int current_keyframe = keyframes[i];
|
||||
libmv::vector<Marker> keyframe_markers =
|
||||
normalized_tracks.MarkersForTracksInBothImages(previous_keyframe,
|
||||
current_keyframe);
|
||||
|
||||
Tracks keyframe_tracks(keyframe_markers);
|
||||
|
||||
/* get a solution from two keyframes only */
|
||||
EuclideanReconstructTwoFrames(keyframe_markers, &reconstruction);
|
||||
EuclideanBundle(keyframe_tracks, &reconstruction);
|
||||
EuclideanCompleteReconstruction(keyframe_tracks,
|
||||
&reconstruction,
|
||||
NULL);
|
||||
|
||||
double current_error = EuclideanReprojectionError(tracks,
|
||||
reconstruction,
|
||||
camera_intrinsics);
|
||||
|
||||
LG << "Error between " << previous_keyframe
|
||||
<< " and " << current_keyframe
|
||||
<< ": " << current_error;
|
||||
|
||||
if (current_error < best_error) {
|
||||
best_error = current_error;
|
||||
keyframe1 = previous_keyframe;
|
||||
keyframe2 = current_keyframe;
|
||||
}
|
||||
|
||||
previous_keyframe = current_keyframe;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Based on the 'libmv_cameraIntrinsicsFillFromOptions()' function from 'libmv_capi' (blender API)
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/* Fill the camera intrinsics parameters given the camera instrinsics
|
||||
* options values.
|
||||
*/
|
||||
|
||||
static void libmv_cameraIntrinsicsFillFromOptions(
|
||||
const libmv_CameraIntrinsicsOptions* camera_intrinsics_options,
|
||||
CameraIntrinsics* camera_intrinsics) {
|
||||
camera_intrinsics->SetFocalLength(camera_intrinsics_options->focal_length_x,
|
||||
camera_intrinsics_options->focal_length_y);
|
||||
|
||||
camera_intrinsics->SetPrincipalPoint(
|
||||
camera_intrinsics_options->principal_point_x,
|
||||
camera_intrinsics_options->principal_point_y);
|
||||
|
||||
camera_intrinsics->SetImageSize(camera_intrinsics_options->image_width,
|
||||
camera_intrinsics_options->image_height);
|
||||
|
||||
switch (camera_intrinsics_options->distortion_model) {
|
||||
case SFM_DISTORTION_MODEL_POLYNOMIAL:
|
||||
{
|
||||
PolynomialCameraIntrinsics *polynomial_intrinsics =
|
||||
static_cast<PolynomialCameraIntrinsics*>(camera_intrinsics);
|
||||
|
||||
polynomial_intrinsics->SetRadialDistortion(
|
||||
camera_intrinsics_options->polynomial_k1,
|
||||
camera_intrinsics_options->polynomial_k2,
|
||||
camera_intrinsics_options->polynomial_k3);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case SFM_DISTORTION_MODEL_DIVISION:
|
||||
{
|
||||
DivisionCameraIntrinsics *division_intrinsics =
|
||||
static_cast<DivisionCameraIntrinsics*>(camera_intrinsics);
|
||||
|
||||
division_intrinsics->SetDistortion(
|
||||
camera_intrinsics_options->division_k1,
|
||||
camera_intrinsics_options->division_k2);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
assert(!"Unknown distortion model");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Based on the 'libmv_cameraIntrinsicsCreateFromOptions()' function from 'libmv_capi' (blender API)
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/* Create the camera intrinsics model given the camera instrinsics
|
||||
* options values.
|
||||
*/
|
||||
|
||||
static
|
||||
std::shared_ptr<CameraIntrinsics> libmv_cameraIntrinsicsCreateFromOptions(
|
||||
const libmv_CameraIntrinsicsOptions* camera_intrinsics_options) {
|
||||
std::shared_ptr<CameraIntrinsics> camera_intrinsics;
|
||||
switch (camera_intrinsics_options->distortion_model) {
|
||||
case SFM_DISTORTION_MODEL_POLYNOMIAL:
|
||||
camera_intrinsics = std::make_shared<PolynomialCameraIntrinsics>();
|
||||
break;
|
||||
case SFM_DISTORTION_MODEL_DIVISION:
|
||||
camera_intrinsics = std::make_shared<DivisionCameraIntrinsics>();
|
||||
break;
|
||||
default:
|
||||
assert(!"Unknown distortion model");
|
||||
}
|
||||
libmv_cameraIntrinsicsFillFromOptions(camera_intrinsics_options,
|
||||
camera_intrinsics.get());
|
||||
return camera_intrinsics;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Based on the 'libmv_getNormalizedTracks()' function from 'libmv_capi' (blender API)
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/* Normalizes the tracks given the camera intrinsics parameters
|
||||
*/
|
||||
|
||||
static void
|
||||
libmv_getNormalizedTracks(const libmv::Tracks &tracks,
|
||||
const libmv::CameraIntrinsics &camera_intrinsics,
|
||||
libmv::Tracks *normalized_tracks) {
|
||||
libmv::vector<libmv::Marker> markers = tracks.AllMarkers();
|
||||
for (int i = 0; i < markers.size(); ++i) {
|
||||
libmv::Marker &marker = markers[i];
|
||||
camera_intrinsics.InvertIntrinsics(marker.x, marker.y,
|
||||
&marker.x, &marker.y);
|
||||
normalized_tracks->Insert(marker.image,
|
||||
marker.track,
|
||||
marker.x, marker.y,
|
||||
marker.weight);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Based on the 'libmv_solveRefineIntrinsics()' function from 'libmv_capi' (blender API)
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/* Refine the final solution using Bundle Adjustment
|
||||
*/
|
||||
|
||||
static void libmv_solveRefineIntrinsics(
|
||||
const Tracks &tracks,
|
||||
const int refine_intrinsics,
|
||||
const int bundle_constraints,
|
||||
EuclideanReconstruction* reconstruction,
|
||||
CameraIntrinsics* intrinsics) {
|
||||
/* only a few combinations are supported but trust the caller/ */
|
||||
int bundle_intrinsics = 0;
|
||||
|
||||
if (refine_intrinsics & SFM_REFINE_FOCAL_LENGTH) {
|
||||
bundle_intrinsics |= libmv::BUNDLE_FOCAL_LENGTH;
|
||||
}
|
||||
if (refine_intrinsics & SFM_REFINE_PRINCIPAL_POINT) {
|
||||
bundle_intrinsics |= libmv::BUNDLE_PRINCIPAL_POINT;
|
||||
}
|
||||
if (refine_intrinsics & SFM_REFINE_RADIAL_DISTORTION_K1) {
|
||||
bundle_intrinsics |= libmv::BUNDLE_RADIAL_K1;
|
||||
}
|
||||
if (refine_intrinsics & SFM_REFINE_RADIAL_DISTORTION_K2) {
|
||||
bundle_intrinsics |= libmv::BUNDLE_RADIAL_K2;
|
||||
}
|
||||
|
||||
EuclideanBundleCommonIntrinsics(tracks,
|
||||
bundle_intrinsics,
|
||||
bundle_constraints,
|
||||
reconstruction,
|
||||
intrinsics);
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// Based on the 'finishReconstruction()' function from 'libmv_capi' (blender API)
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/* Finish the reconstrunction and computes the final reprojection error
|
||||
*/
|
||||
|
||||
static void finishReconstruction(
|
||||
const Tracks &tracks,
|
||||
const CameraIntrinsics &camera_intrinsics,
|
||||
libmv_Reconstruction *libmv_reconstruction) {
|
||||
EuclideanReconstruction &reconstruction =
|
||||
libmv_reconstruction->reconstruction;
|
||||
|
||||
/* Reprojection error calculation. */
|
||||
libmv_reconstruction->tracks = tracks;
|
||||
libmv_reconstruction->error = EuclideanReprojectionError(tracks,
|
||||
reconstruction,
|
||||
camera_intrinsics);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Based on the 'libmv_solveReconstruction()' function from 'libmv_capi' (blender API)
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/* Perform the complete reconstruction process
|
||||
*/
|
||||
|
||||
static
|
||||
std::shared_ptr<libmv_Reconstruction> libmv_solveReconstruction(
|
||||
const Tracks &libmv_tracks,
|
||||
const libmv_CameraIntrinsicsOptions* libmv_camera_intrinsics_options,
|
||||
libmv_ReconstructionOptions* libmv_reconstruction_options) {
|
||||
std::shared_ptr<libmv_Reconstruction> libmv_reconstruction = std::make_shared<libmv_Reconstruction>();
|
||||
|
||||
Tracks tracks = libmv_tracks;
|
||||
EuclideanReconstruction &reconstruction =
|
||||
libmv_reconstruction->reconstruction;
|
||||
|
||||
/* Retrieve reconstruction options from C-API to libmv API. */
|
||||
std::shared_ptr<CameraIntrinsics> camera_intrinsics;
|
||||
camera_intrinsics = libmv_reconstruction->intrinsics =
|
||||
libmv_cameraIntrinsicsCreateFromOptions(libmv_camera_intrinsics_options);
|
||||
|
||||
/* Invert the camera intrinsics/ */
|
||||
Tracks normalized_tracks;
|
||||
libmv_getNormalizedTracks(tracks, *camera_intrinsics, &normalized_tracks);
|
||||
|
||||
/* keyframe selection. */
|
||||
int keyframe1 = libmv_reconstruction_options->keyframe1,
|
||||
keyframe2 = libmv_reconstruction_options->keyframe2;
|
||||
|
||||
if (libmv_reconstruction_options->select_keyframes) {
|
||||
LG << "Using automatic keyframe selection";
|
||||
|
||||
selectTwoKeyframesBasedOnGRICAndVariance(tracks,
|
||||
normalized_tracks,
|
||||
*camera_intrinsics,
|
||||
keyframe1,
|
||||
keyframe2);
|
||||
|
||||
/* so keyframes in the interface would be updated */
|
||||
libmv_reconstruction_options->keyframe1 = keyframe1;
|
||||
libmv_reconstruction_options->keyframe2 = keyframe2;
|
||||
}
|
||||
|
||||
/* Actual reconstruction. */
|
||||
LG << "frames to init from: " << keyframe1 << " " << keyframe2;
|
||||
|
||||
libmv::vector<Marker> keyframe_markers =
|
||||
normalized_tracks.MarkersForTracksInBothImages(keyframe1, keyframe2);
|
||||
|
||||
LG << "number of markers for init: " << keyframe_markers.size();
|
||||
|
||||
if (keyframe_markers.size() < 8) {
|
||||
LG << "No enough markers to initialize from";
|
||||
libmv_reconstruction->is_valid = false;
|
||||
return libmv_reconstruction;
|
||||
}
|
||||
|
||||
EuclideanReconstructTwoFrames(keyframe_markers, &reconstruction);
|
||||
EuclideanBundle(normalized_tracks, &reconstruction);
|
||||
EuclideanCompleteReconstruction(normalized_tracks,
|
||||
&reconstruction,
|
||||
NULL);
|
||||
|
||||
/* Refinement/ */
|
||||
if (libmv_reconstruction_options->refine_intrinsics) {
|
||||
libmv_solveRefineIntrinsics(
|
||||
tracks,
|
||||
libmv_reconstruction_options->refine_intrinsics,
|
||||
libmv::BUNDLE_NO_CONSTRAINTS,
|
||||
&reconstruction,
|
||||
camera_intrinsics.get());
|
||||
}
|
||||
|
||||
/* Set reconstruction scale to unity. */
|
||||
EuclideanScaleToUnity(&reconstruction);
|
||||
|
||||
finishReconstruction(tracks,
|
||||
*camera_intrinsics,
|
||||
libmv_reconstruction.get());
|
||||
|
||||
libmv_reconstruction->is_valid = true;
|
||||
return libmv_reconstruction;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,9 @@
|
||||
#Install macro for libmv libraries
|
||||
MACRO (LIBMV_INSTALL_LIB name)
|
||||
|
||||
if(NOT BUILD_SHARED_LIBS)
|
||||
ocv_install_target(${name} EXPORT OpenCVModules
|
||||
ARCHIVE DESTINATION ${OPENCV_3P_LIB_INSTALL_PATH} COMPONENT dev)
|
||||
endif()
|
||||
|
||||
ENDMACRO (LIBMV_INSTALL_LIB)
|
||||
@@ -0,0 +1,14 @@
|
||||
# installation rules
|
||||
include(CMake/Installation.cmake)
|
||||
|
||||
set(BUILD_SHARED_LIBS OFF) # Force static libs for 3rdparty dependencies
|
||||
|
||||
ocv_warnings_disable(CMAKE_CXX_FLAGS -Winconsistent-missing-override -Wsuggest-override)
|
||||
if(CV_GCC AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 8.0)
|
||||
ocv_warnings_disable(CMAKE_CXX_FLAGS -Wclass-memaccess)
|
||||
endif()
|
||||
if((CV_GCC AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 9.0) OR CV_CLANG)
|
||||
ocv_warnings_disable(CMAKE_CXX_FLAGS -Wdeprecated-copy)
|
||||
endif()
|
||||
|
||||
add_subdirectory(libmv)
|
||||
@@ -0,0 +1,7 @@
|
||||
add_subdirectory(correspondence)
|
||||
add_subdirectory(multiview)
|
||||
add_subdirectory(numeric)
|
||||
|
||||
if ( Ceres_FOUND )
|
||||
add_subdirectory(simple_pipeline)
|
||||
endif ()
|
||||
@@ -0,0 +1,183 @@
|
||||
// Copyright (c) 2007, 2008 libmv authors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//
|
||||
// Get an aligned vector implementation. Must be included before <vector>. The
|
||||
// Eigen guys went through some trouble to make a portable override for the
|
||||
// fixed size vector types.
|
||||
|
||||
#ifndef LIBMV_BASE_VECTOR_H
|
||||
#define LIBMV_BASE_VECTOR_H
|
||||
|
||||
#include <cstring>
|
||||
#include <new>
|
||||
|
||||
#include <Eigen/Core>
|
||||
|
||||
namespace libmv {
|
||||
|
||||
// A simple container class, which guarantees 16 byte alignment needed for most
|
||||
// vectorization. Don't use this container for classes that cannot be copied
|
||||
// via memcpy.
|
||||
// FIXME: this class has some issues:
|
||||
// - doesn't support iterators.
|
||||
// - impede compatibility with code using STL.
|
||||
// - the STL already provide support for custom allocators
|
||||
// it could be replaced with a simple
|
||||
// template <T> class vector : std::vector<T, aligned_allocator> {} declaration
|
||||
// provided it doesn't break code relying on libmv::vector specific behavior
|
||||
template <typename T,
|
||||
typename Allocator = Eigen::aligned_allocator<T> >
|
||||
class vector {
|
||||
public:
|
||||
~vector() { clear(); }
|
||||
|
||||
vector() { init(); }
|
||||
vector(int size) { init(); resize(size); }
|
||||
vector(int size, const T & val) {
|
||||
init();
|
||||
resize(size);
|
||||
std::fill(data_, data_+size_, val); }
|
||||
|
||||
// Copy constructor and assignment.
|
||||
vector(const vector<T, Allocator> &rhs) {
|
||||
init();
|
||||
copy(rhs);
|
||||
}
|
||||
vector<T, Allocator> &operator=(const vector<T, Allocator> &rhs) {
|
||||
if (&rhs != this) {
|
||||
copy(rhs);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// Swaps the contents of two vectors in constant time.
|
||||
void swap(vector<T, Allocator> &other) {
|
||||
std::swap(allocator_, other.allocator_);
|
||||
std::swap(size_, other.size_);
|
||||
std::swap(capacity_, other.capacity_);
|
||||
std::swap(data_, other.data_);
|
||||
}
|
||||
|
||||
T *data() const { return data_; }
|
||||
int size() const { return size_; }
|
||||
int capacity() const { return capacity_; }
|
||||
const T& back() const { return data_[size_ - 1]; }
|
||||
T& back() { return data_[size_ - 1]; }
|
||||
const T& front() const { return data_[0]; }
|
||||
T& front() { return data_[0]; }
|
||||
const T& operator[](int n) const { return data_[n]; }
|
||||
T& operator[](int n) { return data_[n]; }
|
||||
const T& at(int n) const { return data_[n]; }
|
||||
T& at(int n) { return data_[n]; }
|
||||
const T * begin() const { return data_; }
|
||||
const T * end() const { return data_+size_; }
|
||||
T * begin() { return data_; }
|
||||
T * end() { return data_+size_; }
|
||||
|
||||
void resize(size_t size) {
|
||||
reserve(size);
|
||||
if (size > size_) {
|
||||
construct(size_, size);
|
||||
} else if (size < size_) {
|
||||
destruct(size, size_);
|
||||
}
|
||||
size_ = size;
|
||||
}
|
||||
|
||||
void push_back(const T &value) {
|
||||
if (size_ == capacity_) {
|
||||
reserve(size_ ? 2 * size_ : 1);
|
||||
}
|
||||
new (&data_[size_++]) T(value);
|
||||
}
|
||||
|
||||
void pop_back() {
|
||||
resize(size_ - 1);
|
||||
}
|
||||
|
||||
void clear() {
|
||||
destruct(0, size_);
|
||||
deallocate();
|
||||
init();
|
||||
}
|
||||
|
||||
void reserve(unsigned int size) {
|
||||
if (size > size_) {
|
||||
T *data = static_cast<T *>(allocate(size));
|
||||
#if defined(__GNUC__) && __GNUC__ < 5 // legacy compilers branch
|
||||
memcpy(data, data_, sizeof(*data)*size_);
|
||||
#else
|
||||
for (int i = 0; i < size_; ++i)
|
||||
new (&data[i]) T(std::move(data_[i]));
|
||||
for (int i = 0; i < size_; ++i)
|
||||
data_[i].~T();
|
||||
#endif
|
||||
allocator_.deallocate(data_, capacity_);
|
||||
data_ = data;
|
||||
capacity_ = size;
|
||||
}
|
||||
}
|
||||
|
||||
bool empty() {
|
||||
return size_ == 0;
|
||||
}
|
||||
|
||||
private:
|
||||
void construct(int start, int end) {
|
||||
for (int i = start; i < end; ++i) {
|
||||
new (&data_[i]) T;
|
||||
}
|
||||
}
|
||||
void destruct(int start, int end) {
|
||||
for (int i = start; i < end; ++i) {
|
||||
data_[i].~T();
|
||||
}
|
||||
}
|
||||
void init() {
|
||||
size_ = 0;
|
||||
data_ = 0;
|
||||
capacity_ = 0;
|
||||
}
|
||||
|
||||
void *allocate(int size) {
|
||||
return size ? allocator_.allocate(size) : 0;
|
||||
}
|
||||
|
||||
void deallocate() {
|
||||
allocator_.deallocate(data_, size_);
|
||||
data_ = 0;
|
||||
}
|
||||
|
||||
void copy(const vector<T, Allocator> &rhs) {
|
||||
resize(rhs.size());
|
||||
for (int i = 0; i < rhs.size(); ++i) {
|
||||
(*this)[i] = rhs[i];
|
||||
}
|
||||
}
|
||||
|
||||
Allocator allocator_;
|
||||
size_t size_;
|
||||
size_t capacity_;
|
||||
T *data_;
|
||||
};
|
||||
|
||||
} // namespace libmv
|
||||
|
||||
#endif // LIBMV_BASE_VECTOR_H
|
||||
@@ -0,0 +1,34 @@
|
||||
// Copyright (c) 2009 libmv authors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
|
||||
|
||||
#ifndef LIBMV_BASE_VECTOR_UTILS_H_
|
||||
#define LIBMV_BASE_VECTOR_UTILS_H_
|
||||
|
||||
/// Delete the contents of a container.
|
||||
template <class Array>
|
||||
void DeleteElements(Array *array) {
|
||||
for (int i = 0; i < array->size(); ++i) {
|
||||
delete (*array)[i];
|
||||
}
|
||||
array->clear();
|
||||
}
|
||||
|
||||
#endif // LIBMV_BASE_VECTOR_UTILS_H_
|
||||
@@ -0,0 +1,17 @@
|
||||
# define the source files
|
||||
SET(CORRESPONDENCE_SRC feature_matching.cc
|
||||
matches.cc
|
||||
nRobustViewMatching.cc)
|
||||
|
||||
# define the header files (make the headers appear in IDEs.)
|
||||
FILE(GLOB CORRESPONDENCE_HDRS *.h)
|
||||
|
||||
ADD_LIBRARY(opencv.sfm.correspondence STATIC ${CORRESPONDENCE_SRC} ${CORRESPONDENCE_HDRS})
|
||||
|
||||
ocv_target_link_libraries(opencv.sfm.correspondence LINK_PRIVATE ${GLOG_LIBRARIES} opencv.sfm.multiview opencv_imgcodecs)
|
||||
IF(TARGET Eigen3::Eigen)
|
||||
TARGET_LINK_LIBRARIES(opencv.sfm.correspondence LINK_PUBLIC Eigen3::Eigen)
|
||||
ENDIF()
|
||||
|
||||
|
||||
LIBMV_INSTALL_LIB(opencv.sfm.correspondence)
|
||||
@@ -0,0 +1,139 @@
|
||||
// Copyright (c) 2009 libmv authors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
|
||||
#ifndef LIBMV_CORRESPONDENCE_INT_BIPARTITE_GRAPH_H_
|
||||
#define LIBMV_CORRESPONDENCE_INT_BIPARTITE_GRAPH_H_
|
||||
|
||||
#include <limits>
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <cassert>
|
||||
|
||||
namespace libmv {
|
||||
|
||||
// A bipartite graph with labelled edges.
|
||||
template<typename T, typename EdgeT>
|
||||
class BipartiteGraph {
|
||||
public:
|
||||
typedef std::map<std::pair<T, T>, EdgeT> EdgeMap;
|
||||
|
||||
void Insert(const T &left, const T &right, const EdgeT &edge) {
|
||||
left_to_right_[std::make_pair(left, right)] = edge;
|
||||
right_to_left_[std::make_pair(right, left)] = edge;
|
||||
}
|
||||
void Remove(const T &left, const T &right) {
|
||||
typename EdgeMap::iterator iter =
|
||||
left_to_right_.find(std::make_pair(left, right));
|
||||
if (iter != left_to_right_.end())
|
||||
left_to_right_.erase(iter);
|
||||
iter = right_to_left_.find(std::make_pair(right, left));
|
||||
if (iter != right_to_left_.end())
|
||||
right_to_left_.erase(iter);
|
||||
}
|
||||
|
||||
int NumLeftLeft(T left) const {
|
||||
int n = 0;
|
||||
typename EdgeMap::const_iterator it;
|
||||
for (it = left_to_right_.begin(); it != left_to_right_.end(); ++it) {
|
||||
if (it->first.first == left)
|
||||
n++;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
int NumLeftRight(T right) const {
|
||||
int n = 0;
|
||||
typename EdgeMap::const_iterator it;
|
||||
for (it = left_to_right_.begin(); it != left_to_right_.end(); ++it) {
|
||||
if (it->first.second == right)
|
||||
n++;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
// Erases all the elements.
|
||||
// Note that this function does not desallocate pointers
|
||||
void Clear() {
|
||||
left_to_right_.clear();
|
||||
right_to_left_.clear();
|
||||
}
|
||||
class Range {
|
||||
friend class BipartiteGraph<T, EdgeT>;
|
||||
public:
|
||||
T left() const { return reversed_ ? it_->first.second : it_->first.first; }
|
||||
T right() const { return reversed_ ? it_->first.first : it_->first.second;}
|
||||
EdgeT edge() const { return it_->second; }
|
||||
|
||||
void operator++() { ++it_; }
|
||||
EdgeT operator*() { return it_->second; }
|
||||
operator bool() const { return it_ != end_; }
|
||||
|
||||
private:
|
||||
Range(typename EdgeMap::const_iterator it,
|
||||
typename EdgeMap::const_iterator end,
|
||||
bool reversed)
|
||||
: reversed_(reversed), it_(it), end_(end) {}
|
||||
|
||||
bool reversed_;
|
||||
typename EdgeMap::const_iterator it_, end_;
|
||||
};
|
||||
|
||||
Range All() const {
|
||||
return Range(left_to_right_.begin(), left_to_right_.end(), false);
|
||||
}
|
||||
|
||||
Range AllReversed() const {
|
||||
return Range(right_to_left_.begin(), right_to_left_.end(), true);
|
||||
}
|
||||
|
||||
Range ToLeft(T left) const {
|
||||
return Range(left_to_right_.lower_bound(Lower(left)),
|
||||
left_to_right_.upper_bound(Upper(left)), false);
|
||||
}
|
||||
|
||||
Range ToRight(T right) const {
|
||||
return Range(right_to_left_.lower_bound(Lower(right)),
|
||||
right_to_left_.upper_bound(Upper(right)), true);
|
||||
}
|
||||
|
||||
// Find a pointer to the edge, or NULL if not found.
|
||||
const EdgeT *Edge(T left, T right) const {
|
||||
typename EdgeMap::const_iterator it =
|
||||
left_to_right_.find(std::make_pair(left, right));
|
||||
if (it != left_to_right_.end()) {
|
||||
return &(it->second);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
private:
|
||||
std::pair<T, T> Lower(T first) const {
|
||||
return std::make_pair(first, std::numeric_limits<T>::min());
|
||||
}
|
||||
std::pair<T, T> Upper(T first) const {
|
||||
return std::make_pair(first, std::numeric_limits<T>::max());
|
||||
}
|
||||
EdgeMap left_to_right_;
|
||||
EdgeMap right_to_left_;
|
||||
};
|
||||
|
||||
} // namespace libmv
|
||||
|
||||
#endif // LIBMV_CORRESPONDENCE_BIPARTITE_GRAPH_H_
|
||||
@@ -0,0 +1,72 @@
|
||||
// Copyright (c) 2007, 2008 libmv authors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
|
||||
#ifndef LIBMV_CORRESPONDENCE_FEATURE_H_
|
||||
#define LIBMV_CORRESPONDENCE_FEATURE_H_
|
||||
|
||||
#include <opencv2/core.hpp>
|
||||
|
||||
#include "libmv/numeric/numeric.h"
|
||||
|
||||
namespace libmv
|
||||
{
|
||||
class Feature
|
||||
{
|
||||
public:
|
||||
virtual
|
||||
~Feature() {};
|
||||
};
|
||||
|
||||
class PointFeature : public Feature {
|
||||
public:
|
||||
PointFeature(float xx=0.0f, float yy=0.0f) {
|
||||
coords[0] = xx;
|
||||
coords[1] = yy;
|
||||
scale = 0.0;
|
||||
orientation = 0.0;
|
||||
}
|
||||
|
||||
PointFeature &operator=(const PointFeature &other)
|
||||
{
|
||||
if (this == &other)
|
||||
return *this;
|
||||
scale = other.scale;
|
||||
orientation = other.orientation;
|
||||
coords = other.coords;
|
||||
return *this;
|
||||
}
|
||||
|
||||
PointFeature(const cv::KeyPoint & keypoint) {
|
||||
coords[0] = keypoint.pt.x;
|
||||
coords[1] = keypoint.pt.y;
|
||||
scale = keypoint.octave;
|
||||
orientation = keypoint.angle;
|
||||
}
|
||||
float x() const { return coords(0); }
|
||||
float y() const { return coords(1); }
|
||||
|
||||
Vec2f coords; // (x, y), i.e. (column, row).
|
||||
float scale; // In pixels.
|
||||
float orientation; // In radians.
|
||||
};
|
||||
|
||||
} // namespace libmv
|
||||
|
||||
#endif // LIBMV_CORRESPONDENCE_FEATURE_H_
|
||||
@@ -0,0 +1,143 @@
|
||||
// Copyright (c) 2009 libmv authors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
|
||||
#include <opencv2/features.hpp>
|
||||
|
||||
#include "libmv/correspondence/feature_matching.h"
|
||||
|
||||
// Compute candidate matches between 2 sets of features. Two features A and B
|
||||
// are a candidate match if A is the nearest neighbor of B and B is the nearest
|
||||
// neighbor of A.
|
||||
void FindCandidateMatches(const FeatureSet &left,
|
||||
const FeatureSet &right,
|
||||
Matches *matches) {
|
||||
if (left.features.empty() ||
|
||||
right.features.empty() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
cv::FlannBasedMatcher matcherA;
|
||||
cv::FlannBasedMatcher matcherB;
|
||||
|
||||
// Paste the necessary data in contiguous arrays.
|
||||
cv::Mat arrayA = FeatureSet::FeatureSetDescriptorsToContiguousArray(left);
|
||||
cv::Mat arrayB = FeatureSet::FeatureSetDescriptorsToContiguousArray(right);
|
||||
|
||||
matcherA.add(std::vector<cv::Mat>(1, arrayB));
|
||||
matcherB.add(std::vector<cv::Mat>(1, arrayA));
|
||||
std::vector<cv::DMatch> matchesA, matchesB;
|
||||
matcherA.match(arrayA, matchesA);
|
||||
matcherB.match(arrayB, matchesB);
|
||||
|
||||
// From putative matches get symmetric matches.
|
||||
int max_track_number = 0;
|
||||
for (size_t i = 0; i < matchesA.size(); ++i)
|
||||
{
|
||||
// Add the match only if we have a symmetric result.
|
||||
if (i == matchesB[matchesA[i].trainIdx].trainIdx)
|
||||
{
|
||||
matches->Insert(0, max_track_number, &left.features[i]);
|
||||
matches->Insert(1, max_track_number, &right.features[matchesA[i].trainIdx]);
|
||||
++max_track_number;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cv::Mat FeatureSet::FeatureSetDescriptorsToContiguousArray
|
||||
( const FeatureSet & featureSet ) {
|
||||
|
||||
if (featureSet.features.empty()) {
|
||||
return cv::Mat();
|
||||
}
|
||||
int descriptorSize = featureSet.features[0].descriptor.cols;
|
||||
// Allocate and paste the necessary data.
|
||||
cv::Mat array(featureSet.features.size(), descriptorSize, CV_32F);
|
||||
|
||||
//-- Paste data in the contiguous array :
|
||||
for (int i = 0; i < (int)featureSet.features.size(); ++i) {
|
||||
featureSet.features[i].descriptor.copyTo(array.row(i));
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
// Compute candidate matches between 2 sets of features with a ratio.
|
||||
void FindCandidateMatches_Ratio(const FeatureSet &left,
|
||||
const FeatureSet &right,
|
||||
Matches *matches,
|
||||
float fRatio) {
|
||||
if (left.features.empty() || right.features.empty())
|
||||
return;
|
||||
|
||||
cv::FlannBasedMatcher matcherA;
|
||||
|
||||
// Paste the necessary data in contiguous arrays.
|
||||
cv::Mat arrayA = FeatureSet::FeatureSetDescriptorsToContiguousArray(left);
|
||||
cv::Mat arrayB = FeatureSet::FeatureSetDescriptorsToContiguousArray(right);
|
||||
|
||||
matcherA.add(std::vector<cv::Mat>(1, arrayB));
|
||||
std::vector < std::vector<cv::DMatch> > matchesA;
|
||||
matcherA.knnMatch(arrayA, matchesA, 2);
|
||||
|
||||
// From putative matches get matches that fit the "Ratio" heuristic.
|
||||
int max_track_number = 0;
|
||||
for (size_t i = 0; i < matchesA.size(); ++i)
|
||||
{
|
||||
float distance0 = matchesA[i][0].distance;
|
||||
float distance1 = matchesA[i][1].distance;
|
||||
// Add the match only if we have a symmetric result.
|
||||
if (distance0 < fRatio * distance1)
|
||||
{
|
||||
{
|
||||
matches->Insert(0, max_track_number, &left.features[i]);
|
||||
matches->Insert(1, max_track_number, &right.features[matchesA[i][0].trainIdx]);
|
||||
++max_track_number;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Compute correspondences that match between 2 sets of features with a ratio.
|
||||
void FindCorrespondences(const FeatureSet &left,
|
||||
const FeatureSet &right,
|
||||
std::map<size_t, size_t> *correspondences,
|
||||
float fRatio) {
|
||||
if (left.features.empty() || right.features.empty())
|
||||
return;
|
||||
|
||||
cv::FlannBasedMatcher matcherA;
|
||||
|
||||
// Paste the necessary data in contiguous arrays.
|
||||
cv::Mat arrayA = FeatureSet::FeatureSetDescriptorsToContiguousArray(left);
|
||||
cv::Mat arrayB = FeatureSet::FeatureSetDescriptorsToContiguousArray(right);
|
||||
|
||||
matcherA.add(std::vector<cv::Mat>(1, arrayB));
|
||||
std::vector < std::vector<cv::DMatch> > matchesA;
|
||||
matcherA.knnMatch(arrayA, matchesA, 2);
|
||||
|
||||
// From putative matches get matches that fit the "Ratio" heuristic.
|
||||
for (size_t i = 0; i < matchesA.size(); ++i)
|
||||
{
|
||||
float distance0 = matchesA[i][0].distance;
|
||||
float distance1 = matchesA[i][1].distance;
|
||||
// Add the match only if we have a symmetric result.
|
||||
if (distance0 < fRatio * distance1)
|
||||
(*correspondences)[i] = matchesA[i][0].trainIdx;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
// Copyright (c) 2009 libmv authors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
|
||||
|
||||
#ifndef LIBMV_CORRESPONDENCE_FEATURE_MATCHING_H_
|
||||
#define LIBMV_CORRESPONDENCE_FEATURE_MATCHING_H_
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include <opencv2/core.hpp>
|
||||
|
||||
#include "libmv/base/vector.h"
|
||||
#include "libmv/correspondence/feature.h"
|
||||
#include "libmv/correspondence/matches.h"
|
||||
|
||||
using namespace libmv;
|
||||
|
||||
/// Define the description of a feature described by :
|
||||
/// A PointFeature (x,y,scale,orientation),
|
||||
/// And a descriptor (a vector of floats).
|
||||
class KeypointFeature : public ::PointFeature {
|
||||
public:
|
||||
virtual ~KeypointFeature(){};
|
||||
|
||||
void set(const PointFeature &feature,const cv::Mat &descriptor)
|
||||
{
|
||||
PointFeature::operator=(feature);
|
||||
descriptor.copyTo(this->descriptor);
|
||||
}
|
||||
|
||||
// Match kdtree traits: with this, the Feature can act as a kdtree point.
|
||||
float operator[](int i) const {
|
||||
if (descriptor.depth() != CV_32F)
|
||||
std::cerr << "KeypointFeature does not contain floats" << std::endl;
|
||||
return descriptor.at<float>(i);
|
||||
}
|
||||
|
||||
cv::Mat descriptor;
|
||||
};
|
||||
|
||||
/// FeatureSet : Store an array of KeypointFeature ( Keypoint and descriptor).
|
||||
struct FeatureSet {
|
||||
std::vector<KeypointFeature> features;
|
||||
|
||||
/// return a float * containing the concatenation of descriptor data.
|
||||
/// Must be deleted with []
|
||||
static cv::Mat FeatureSetDescriptorsToContiguousArray
|
||||
( const FeatureSet & featureSet );
|
||||
};
|
||||
|
||||
// Compute candidate matches between 2 sets of features. Two features a and b
|
||||
// are a candidate match if a is the nearest neighbor of b and b is the nearest
|
||||
// neighbor of a.
|
||||
void FindCandidateMatches(const FeatureSet &left,
|
||||
const FeatureSet &right,
|
||||
Matches *matches);
|
||||
|
||||
// Compute candidate matches between 2 sets of features.
|
||||
// Keep only strong and distinctive matches by using the Davide Lowe's ratio
|
||||
// method.
|
||||
// I.E: A match is considered as strong if the following test is true :
|
||||
// I.E distance[0] < fRatio * distances[1].
|
||||
// From David Lowe "Distinctive Image Features from Scale-Invariant Keypoints".
|
||||
// You can use David Lowe's magic ratio (0.6 or 0.8).
|
||||
// 0.8 allow to remove 90% of the false matches while discarding less than 5%
|
||||
// of the correct matches.
|
||||
void FindCandidateMatches_Ratio(const FeatureSet &left,
|
||||
const FeatureSet &right,
|
||||
Matches *matches,
|
||||
float fRatio = 0.8f);
|
||||
// TODO(pmoulon) Add Lowe's ratio symmetric match method.
|
||||
// Compute correspondences that match between 2 sets of features with a ratio.
|
||||
|
||||
void FindCorrespondences(const FeatureSet &left,
|
||||
const FeatureSet &right,
|
||||
std::map<size_t, size_t> *correspondences,
|
||||
float fRatio = 0.8f);
|
||||
|
||||
#endif //LIBMV_CORRESPONDENCE_FEATURE_MATCHING_H_
|
||||
@@ -0,0 +1,99 @@
|
||||
// Copyright (c) 2007, 2008 libmv authors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
|
||||
#include "libmv/correspondence/matches.h"
|
||||
#include "libmv/correspondence/feature.h"
|
||||
|
||||
namespace libmv {
|
||||
|
||||
Matches::~Matches() {}
|
||||
|
||||
void DeleteMatchFeatures(Matches *matches) {
|
||||
(void) matches;
|
||||
// XXX
|
||||
/*
|
||||
for (Correspondences::FeatureIterator it = correspondences->ScanAllFeatures();
|
||||
!it.Done(); it.Next()) {
|
||||
delete const_cast<Feature *>(it.feature());
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
int Matches::GetNumberOfMatches(ImageID id1,ImageID id2) const
|
||||
{
|
||||
Features<Feature> features1 = InImage<Feature>(id1);
|
||||
Features<Feature> features2 = InImage<Feature>(id2);
|
||||
int count = 0;
|
||||
for(int i1=0;features1;++features1,++i1)
|
||||
{
|
||||
Features<Feature> temp = features2;
|
||||
for(int i2=0;temp;++temp,++i2)
|
||||
{
|
||||
if(features1.track() == temp.track())
|
||||
{
|
||||
++count;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
void Matches::DrawMatches(ImageID image_id1,const cv::Mat &image1,ImageID image_id2,const cv::Mat &image2, cv::Mat &out)const
|
||||
{
|
||||
std::vector<cv::KeyPoint> points1;
|
||||
std::vector<cv::KeyPoint> points2;
|
||||
std::vector<cv::DMatch> matches;
|
||||
KeyPoints(image_id1,points1);
|
||||
KeyPoints(image_id2,points2);
|
||||
MatchesTwo(image_id1,image_id2,matches);
|
||||
cv::drawMatches(image1,points1,image2,points2,matches,out);
|
||||
}
|
||||
|
||||
void Matches::MatchesTwo(ImageID image1,ImageID image2,std::vector<cv::DMatch> &matches)const
|
||||
{
|
||||
Features<PointFeature> features1 = InImage<PointFeature>(image1);
|
||||
Features<PointFeature> features2 = InImage<PointFeature>(image2);
|
||||
for(int i1=0;features1;++features1,++i1)
|
||||
{
|
||||
Features<PointFeature> temp = features2;
|
||||
for(int i2=0;temp;++temp,++i2)
|
||||
{
|
||||
if(features1.track() == temp.track())
|
||||
{
|
||||
matches.push_back(cv::DMatch(i1,i2,std::numeric_limits<float>::max()));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Matches::KeyPoints(ImageID image,std::vector<cv::KeyPoint> &keypoints)const
|
||||
{
|
||||
PointFeatures2KeyPoints(InImage<PointFeature>(image),keypoints);
|
||||
}
|
||||
|
||||
void Matches::PointFeatures2KeyPoints(Features<PointFeature> features,std::vector<cv::KeyPoint> &keypoints)const
|
||||
{
|
||||
for(;features;++features)
|
||||
keypoints.push_back(cv::KeyPoint(features.feature()->x(),features.feature()->y(),1));
|
||||
}
|
||||
|
||||
} // namespace libmv
|
||||
@@ -0,0 +1,319 @@
|
||||
// Copyright (c) 2007, 2008 libmv authors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
|
||||
#ifndef LIBMV_CORRESPONDENCE_MATCHES_H_
|
||||
#define LIBMV_CORRESPONDENCE_MATCHES_H_
|
||||
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
|
||||
#include <opencv2/core.hpp>
|
||||
#include <opencv2/features.hpp>
|
||||
|
||||
#include "libmv/base/vector.h"
|
||||
// TODO(julien) use the bipartite_graph_new.h now
|
||||
#include "libmv/correspondence/bipartite_graph.h"
|
||||
#include "libmv/logging/logging.h"
|
||||
#include "libmv/correspondence/feature.h"
|
||||
#include "libmv/numeric/numeric.h"
|
||||
|
||||
namespace libmv {
|
||||
|
||||
class Matches {
|
||||
public:
|
||||
typedef int ImageID;
|
||||
typedef int TrackID;
|
||||
typedef BipartiteGraph<int, const Feature *> Graph;
|
||||
|
||||
~Matches();
|
||||
|
||||
// Iterate over features, silently skiping any that are not FeatureT or
|
||||
// derived from FeatureT.
|
||||
template<typename FeatureT>
|
||||
class Features {
|
||||
public:
|
||||
ImageID image() const { return r_.left(); }
|
||||
TrackID track() const { return r_.right(); }
|
||||
const FeatureT *feature() const {
|
||||
return static_cast<const FeatureT *>(r_.edge());
|
||||
}
|
||||
operator bool() const { return r_; }
|
||||
void operator++() { ++r_; Skip(); }
|
||||
Features(Graph::Range range) : r_(range) { Skip(); }
|
||||
|
||||
private:
|
||||
void Skip() {
|
||||
while (r_ && !dynamic_cast<const FeatureT *> (r_.edge())) ++r_;
|
||||
}
|
||||
Graph::Range r_;
|
||||
};
|
||||
typedef Features<PointFeature> Points;
|
||||
|
||||
template<typename T>
|
||||
Features<T> All() const { return Features<T>(graph_.All()); }
|
||||
|
||||
template<typename T>
|
||||
Features<T> AllReversed() const { return Features<T>(graph_.AllReversed()); }
|
||||
|
||||
template<typename T>
|
||||
Features<T> InImage(ImageID image) const {
|
||||
return Features<T>(graph_.ToLeft(image));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Features<T> InTrack(TrackID track) const {
|
||||
return Features<T>(graph_.ToRight(track));
|
||||
}
|
||||
|
||||
void PointFeatures2KeyPoints(Features<PointFeature> features,std::vector<cv::KeyPoint> &keypoints)const;
|
||||
void KeyPoints(ImageID image,std::vector<cv::KeyPoint> &keypoints)const;
|
||||
void MatchesTwo(ImageID image1,ImageID image2,std::vector<cv::DMatch> &matches)const;
|
||||
void DrawMatches(ImageID image_id1,const cv::Mat &image1,ImageID image_id2,const cv::Mat &image2, cv::Mat &out)const;
|
||||
|
||||
// Does not take ownership of feature.
|
||||
void Insert(ImageID image, TrackID track, const Feature *feature) {
|
||||
graph_.Insert(image, track, feature);
|
||||
images_.insert(image);
|
||||
tracks_.insert(track);
|
||||
}
|
||||
|
||||
void Remove(ImageID image, TrackID track) {
|
||||
graph_.Remove(image, track);
|
||||
}
|
||||
|
||||
// Erases all the elements.
|
||||
// Note that this function does not desallocate features
|
||||
void Clear() {
|
||||
graph_.Clear();
|
||||
images_.clear();
|
||||
tracks_.clear();
|
||||
}
|
||||
// Insert all elements of matches (images, tracks, feature) as new data
|
||||
void Insert(const Matches &matches) {
|
||||
size_t max_images = GetMaxImageID();
|
||||
size_t max_tracks = GetMaxTrackID();
|
||||
std::map<ImageID, ImageID> new_image_ids;
|
||||
std::map<TrackID, TrackID> new_track_ids;
|
||||
std::set<ImageID>::const_iterator iter_image;
|
||||
std::set<TrackID>::const_iterator iter_track;
|
||||
|
||||
ImageID image_id;
|
||||
iter_image = matches.images_.begin();
|
||||
for (; iter_image != matches.images_.end(); ++iter_image) {
|
||||
image_id = ++max_images;
|
||||
new_image_ids[*iter_image] = image_id;
|
||||
images_.insert(image_id);
|
||||
}
|
||||
TrackID track_id;
|
||||
iter_track = matches.tracks_.begin();
|
||||
for (; iter_track != matches.tracks_.end(); ++iter_track) {
|
||||
track_id = ++max_tracks;
|
||||
new_track_ids[*iter_track] = track_id;
|
||||
tracks_.insert(track_id);
|
||||
}
|
||||
iter_image = matches.images_.begin();
|
||||
for (; iter_image != matches.images_.end(); ++iter_image) {
|
||||
iter_track = matches.tracks_.begin();
|
||||
for (; iter_track != matches.tracks_.end(); ++iter_track) {
|
||||
const Feature * feature = matches.Get(*iter_image, *iter_track);
|
||||
image_id = new_image_ids[*iter_image];
|
||||
track_id = new_track_ids[*iter_track];
|
||||
graph_.Insert(image_id, track_id, feature);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Merge common elements add new data (image, track, feature).
|
||||
void Merge(const Matches &matches) {
|
||||
std::map<TrackID, TrackID> new_track_ids;
|
||||
std::set<ImageID>::const_iterator iter_image;
|
||||
std::set<TrackID>::const_iterator iter_track;
|
||||
//Find non common elements and add them into new_matches
|
||||
std::set<ImageID>::const_iterator found_image;
|
||||
std::set<TrackID>::const_iterator found_track;
|
||||
iter_image = matches.images_.begin();
|
||||
for (; iter_image != matches.images_.end(); ++iter_image) {
|
||||
found_image = images_.find(*iter_image);
|
||||
if (found_image == images_.end()) {
|
||||
images_.insert(*iter_image);
|
||||
}
|
||||
iter_track = matches.tracks_.begin();
|
||||
for (; iter_track != matches.tracks_.end(); ++iter_track) {
|
||||
found_track = tracks_.find(*iter_track);
|
||||
if (found_track == tracks_.end()
|
||||
&& new_track_ids.find(*iter_track) == new_track_ids.end()) {
|
||||
new_track_ids[*iter_track] = *iter_track;
|
||||
tracks_.insert(*iter_track);
|
||||
}
|
||||
const Feature * feature = matches.Get(*iter_image, *iter_track);
|
||||
graph_.Insert(*iter_image, *iter_track, feature);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const Feature *Get(ImageID image, TrackID track) const {
|
||||
const Feature *const *f = graph_.Edge(image, track);
|
||||
return f ? *f : NULL;
|
||||
}
|
||||
|
||||
ImageID GetMaxImageID() const {
|
||||
ImageID max_images = -1;
|
||||
std::set<ImageID>::const_iterator iter_image =
|
||||
std::max_element (images_.begin(), images_.end());
|
||||
if (iter_image != images_.end()) {
|
||||
max_images = *iter_image;
|
||||
}
|
||||
return max_images;
|
||||
}
|
||||
|
||||
TrackID GetMaxTrackID() const {
|
||||
TrackID max_tracks = -1;
|
||||
std::set<TrackID>::const_iterator iter_track =
|
||||
std::max_element (tracks_.begin(), tracks_.end());
|
||||
if (iter_track != tracks_.end()) {
|
||||
max_tracks = *iter_track;
|
||||
}
|
||||
return max_tracks;
|
||||
}
|
||||
|
||||
int GetNumberOfMatches(ImageID id1,ImageID id2) const;
|
||||
|
||||
const std::set<ImageID> &get_images() const {
|
||||
return images_;
|
||||
}
|
||||
const std::set<TrackID> &get_tracks() const {
|
||||
return tracks_;
|
||||
}
|
||||
|
||||
int NumFeatureImage(ImageID image_id) const {
|
||||
return graph_.NumLeftLeft(image_id);
|
||||
}
|
||||
|
||||
int NumFeatureTrack(TrackID track_id) const {
|
||||
return graph_.NumLeftRight(track_id);
|
||||
}
|
||||
|
||||
|
||||
size_t NumTracks() const { return tracks_.size(); }
|
||||
size_t NumImages() const { return images_.size(); }
|
||||
|
||||
private:
|
||||
Graph graph_;
|
||||
std::set<ImageID> images_;
|
||||
std::set<TrackID> tracks_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Intersect sorted lists. Destroys originals; leaves results as the single
|
||||
* entry in sorted_items.
|
||||
*/
|
||||
template<typename T>
|
||||
void Intersect(std::vector< std::vector<T> > *sorted_items) {
|
||||
std::vector<T> tmp;
|
||||
while (sorted_items->size() > 1) {
|
||||
int n = sorted_items->size();
|
||||
std::vector<T> &s1 = (*sorted_items)[n - 1];
|
||||
std::vector<T> &s2 = (*sorted_items)[n - 2];
|
||||
tmp.resize(std::min(s1.size(), s2.size()));
|
||||
typename std::vector<T>::iterator it = std::set_intersection(
|
||||
s1.begin(), s1.end(), s2.begin(), s2.end(), tmp.begin());
|
||||
tmp.resize(int(it - tmp.begin()));
|
||||
std::swap(tmp, s2);
|
||||
tmp.resize(0);
|
||||
sorted_items->pop_back();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract matrices from a set of matches, containing the point locations. Only
|
||||
* points for tracks which appear in all images are returned in tracks.
|
||||
*
|
||||
* \param matches The matches from which to extract the points.
|
||||
* \param images Which images to extract the points from.
|
||||
* \param xs The resulting matrices containing the points. The entries will
|
||||
* match the ordering of images.
|
||||
*/
|
||||
inline void TracksInAllImages(const Matches &matches,
|
||||
const vector<Matches::ImageID> &images,
|
||||
vector<Matches::TrackID> *tracks) {
|
||||
if (!images.size()) {
|
||||
return;
|
||||
}
|
||||
std::vector<std::vector<Matches::TrackID> > all_tracks;
|
||||
all_tracks.resize(images.size());
|
||||
for (int i = 0; i < images.size(); ++i) {
|
||||
for (Matches::Points r = matches.InImage<PointFeature>(images[i]); r; ++r) {
|
||||
all_tracks[i].push_back(r.track());
|
||||
}
|
||||
}
|
||||
Intersect(&all_tracks);
|
||||
CHECK(all_tracks.size() == 1);
|
||||
for (size_t i = 0; i < all_tracks[0].size(); ++i) {
|
||||
tracks->push_back(all_tracks[0][i]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract matrices from a set of matches, containing the point locations. Only
|
||||
* points for tracks which appear in all images are returned in xs. Each output
|
||||
* matrix is of size 2 x N, where N is the number of tracks that are in all the
|
||||
* images.
|
||||
*
|
||||
* \param matches The matches from which to extract the points.
|
||||
* \param images Which images to extract the points from.
|
||||
* \param xs The resulting matrices containing the points. The entries will
|
||||
* match the ordering of images.
|
||||
*/
|
||||
inline void PointMatchMatrices(const Matches &matches,
|
||||
const vector<Matches::ImageID> &images,
|
||||
vector<Matches::TrackID> *tracks,
|
||||
vector<Mat> *xs) {
|
||||
TracksInAllImages(matches, images, tracks);
|
||||
|
||||
xs->resize(images.size());
|
||||
for (int i = 0; i < images.size(); ++i) {
|
||||
(*xs)[i].resize(2, tracks->size());
|
||||
for (int j = 0; j < tracks->size(); ++j) {
|
||||
const PointFeature *f = static_cast<const PointFeature *>(
|
||||
matches.Get(images[i], (*tracks)[j]));
|
||||
(*xs)[i](0, j) = f->x();
|
||||
(*xs)[i](1, j) = f->y();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline void TwoViewPointMatchMatrices(const Matches &matches,
|
||||
Matches::ImageID image_id1,
|
||||
Matches::ImageID image_id2,
|
||||
vector<Mat> *xs) {
|
||||
vector<Matches::TrackID> tracks;
|
||||
vector<Matches::ImageID> images;
|
||||
images.push_back(image_id1);
|
||||
images.push_back(image_id2);
|
||||
PointMatchMatrices(matches, images, &tracks, xs);
|
||||
}
|
||||
|
||||
// Delete the features in a correspondences. Uses const_cast to avoid the
|
||||
// constness problems. This is more intended for tests than for actual use.
|
||||
void DeleteMatchFeatures(Matches *matches);
|
||||
|
||||
} // namespace libmv
|
||||
|
||||
#endif // LIBMV_CORRESPONDENCE_MATCHES_H_
|
||||
@@ -0,0 +1,303 @@
|
||||
// Copyright (c) 2010 libmv authors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
|
||||
#include <opencv2/imgcodecs.hpp>
|
||||
|
||||
#include "libmv/base/vector_utils.h"
|
||||
#include "libmv/correspondence/feature.h"
|
||||
#include "libmv/correspondence/feature_matching.h"
|
||||
#include "libmv/correspondence/nRobustViewMatching.h"
|
||||
#include "libmv/multiview/robust_fundamental.h"
|
||||
|
||||
using namespace libmv;
|
||||
using namespace correspondence;
|
||||
using namespace std;
|
||||
|
||||
nRobustViewMatching::nRobustViewMatching(){
|
||||
#ifdef CV_VERSION_EPOCH
|
||||
m_pDescriber = NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
nRobustViewMatching::nRobustViewMatching(
|
||||
cv::Ptr<cv::FeatureDetector> pDetector,
|
||||
cv::Ptr<cv::DescriptorExtractor> pDescriber){
|
||||
m_pDetector = pDetector;
|
||||
m_pDescriber = pDescriber;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute the data and store it in the class map<string,T>
|
||||
*
|
||||
* \param[in] filename The file from which the data will be extracted.
|
||||
*
|
||||
* \return True if success.
|
||||
*/
|
||||
bool nRobustViewMatching::computeData(const string & filename)
|
||||
{
|
||||
cv::Mat im_cv = cv::imread(filename, 0);
|
||||
if (im_cv.empty()) {
|
||||
LOG(FATAL) << "Failed loading image: " << filename;
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
libmv::vector<libmv::Feature *> features;
|
||||
std::vector<cv::KeyPoint> features_cv;
|
||||
m_pDetector->detect( im_cv, features_cv );
|
||||
features.resize(features_cv.size());
|
||||
for(size_t i=0; i<features_cv.size(); ++i)
|
||||
features[i] = new libmv::PointFeature(features_cv[i]);
|
||||
|
||||
cv::Mat descriptors;
|
||||
m_pDescriber->compute(im_cv, features_cv, descriptors);
|
||||
|
||||
// Copy data.
|
||||
m_ViewData.insert( make_pair(filename,FeatureSet()) );
|
||||
FeatureSet & KeypointData = m_ViewData[filename];
|
||||
KeypointData.features.resize(descriptors.rows);
|
||||
for(int i = 0;i < descriptors.rows; ++i)
|
||||
{
|
||||
KeypointFeature & feat = KeypointData.features[i];
|
||||
descriptors.row(i).copyTo(feat.descriptor);
|
||||
*(PointFeature*)(&feat) = *(PointFeature*)features[i];
|
||||
}
|
||||
|
||||
DeleteElements(&features);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute the putative match between data computed from element A and B
|
||||
* Store the match data internally in the class
|
||||
* map< <string, string> , MatchObject >
|
||||
*
|
||||
* \param[in] The name of the filename A (use computed data for this element)
|
||||
* \param[in] The name of the filename B (use computed data for this element)
|
||||
*
|
||||
* \return True if success.
|
||||
*/
|
||||
bool nRobustViewMatching::MatchData(const string & dataA, const string & dataB)
|
||||
{
|
||||
// Check input data
|
||||
if ( find(m_vec_InputNames.begin(), m_vec_InputNames.end(), dataA)
|
||||
== m_vec_InputNames.end() ||
|
||||
find(m_vec_InputNames.begin(), m_vec_InputNames.end(), dataB)
|
||||
== m_vec_InputNames.end())
|
||||
{
|
||||
LOG(INFO) << "[nViewMatching::MatchData] "
|
||||
<< "Could not identify one of the input name.";
|
||||
return false;
|
||||
}
|
||||
if (m_ViewData.find(dataA) == m_ViewData.end() ||
|
||||
m_ViewData.find(dataB) == m_ViewData.end())
|
||||
{
|
||||
LOG(INFO) << "[nViewMatching::MatchData] "
|
||||
<< "Could not identify data for one of the input name.";
|
||||
return false;
|
||||
}
|
||||
|
||||
// Computed data exist for the given name
|
||||
int iDataA = find(m_vec_InputNames.begin(), m_vec_InputNames.end(), dataA)
|
||||
- m_vec_InputNames.begin();
|
||||
int iDataB = find(m_vec_InputNames.begin(), m_vec_InputNames.end(), dataB)
|
||||
- m_vec_InputNames.begin();
|
||||
|
||||
Matches matches;
|
||||
//TODO(pmoulon) make FindCandidatesMatches a parameter.
|
||||
FindCandidateMatches_Ratio(m_ViewData[dataA],
|
||||
m_ViewData[dataB],
|
||||
&matches);
|
||||
Matches consistent_matches;
|
||||
if (computeConstrainMatches(matches,iDataA,iDataB,&consistent_matches))
|
||||
{
|
||||
matches = consistent_matches;
|
||||
}
|
||||
if (matches.NumTracks() > 0)
|
||||
{
|
||||
m_sharedData.insert(
|
||||
make_pair(
|
||||
make_pair(m_vec_InputNames[iDataA],m_vec_InputNames[iDataB]),
|
||||
matches)
|
||||
);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* From a series of element it computes the cross putative match list.
|
||||
*
|
||||
* \param[in] vec_data The data on which we want compute cross matches.
|
||||
*
|
||||
* \return True if success (and any matches was found).
|
||||
*/
|
||||
bool nRobustViewMatching::computeCrossMatch( const std::vector<string> & vec_data)
|
||||
{
|
||||
if (m_pDetector == NULL || m_pDescriber == NULL) {
|
||||
LOG(FATAL) << "Invalid Detector or Describer.";
|
||||
return false;
|
||||
}
|
||||
|
||||
m_vec_InputNames = vec_data;
|
||||
bool bRes = true;
|
||||
for (int i=0; i < vec_data.size(); ++i) {
|
||||
bRes &= computeData(vec_data[i]);
|
||||
}
|
||||
|
||||
bool bRes2 = true;
|
||||
for (int i=0; i < vec_data.size(); ++i) {
|
||||
for (int j=0; j < i; ++j)
|
||||
{
|
||||
if (m_ViewData.find(vec_data[i]) != m_ViewData.end() &&
|
||||
m_ViewData.find(vec_data[j]) != m_ViewData.end())
|
||||
{
|
||||
bRes2 &= this->MatchData( vec_data[i], vec_data[j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
return bRes2;
|
||||
}
|
||||
|
||||
bool nRobustViewMatching::computeRelativeMatch(
|
||||
const std::vector<string>& vec_data) {
|
||||
if (m_pDetector == NULL || m_pDescriber == NULL) {
|
||||
LOG(FATAL) << "Invalid Detector or Describer.";
|
||||
return false;
|
||||
}
|
||||
|
||||
m_vec_InputNames = vec_data;
|
||||
bool bRes = true;
|
||||
for (int i=0; i < vec_data.size(); ++i) {
|
||||
bRes &= computeData(vec_data[i]);
|
||||
}
|
||||
|
||||
bool bRes2 = true;
|
||||
for (int i=1; i < vec_data.size(); ++i) {
|
||||
if (m_ViewData.find(vec_data[i-1]) != m_ViewData.end() &&
|
||||
m_ViewData.find(vec_data[i]) != m_ViewData.end())
|
||||
{
|
||||
bRes2 &= this->MatchData(vec_data[i-1], vec_data[i]);
|
||||
}
|
||||
}
|
||||
// Match the first and the last images (in order to detect loop)
|
||||
bRes2 &= this->MatchData(vec_data[0], vec_data[vec_data.size() - 1]);
|
||||
return bRes2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Give the posibility to constrain the matches list.
|
||||
*
|
||||
* \param[in] matchIn The input match data between indexA and indexB.
|
||||
* \param[in] dataAindex The reference index for element A.
|
||||
* \param[in] dataBindex The reference index for element B.
|
||||
* \param[out] matchesOut The output match that satisfy the internal constraint.
|
||||
*
|
||||
* \return True if success.
|
||||
*/
|
||||
bool nRobustViewMatching::computeConstrainMatches(const Matches & matchIn,
|
||||
int dataAindex,
|
||||
int dataBindex,
|
||||
Matches * matchesOut)
|
||||
{
|
||||
if (matchesOut == NULL)
|
||||
{
|
||||
LOG(INFO) << "[nViewMatching::computeConstrainMatches]"
|
||||
<< " Could not export constrained matches.";
|
||||
return false;
|
||||
}
|
||||
libmv::vector<Mat> x;
|
||||
libmv::vector<int> tracks, images;
|
||||
images.push_back(0);
|
||||
images.push_back(1);
|
||||
PointMatchMatrices(matchIn, images, &tracks, &x);
|
||||
|
||||
libmv::vector<int> inliers;
|
||||
Mat3 H;
|
||||
// TODO(pmoulon) Make the Correspondence filter a parameter.
|
||||
//HomographyFromCorrespondences2PointRobust(x[0], x[1], 0.3, &H, &inliers);
|
||||
//HomographyFromCorrespondences4PointRobust(x[0], x[1], 0.3, &H, &inliers);
|
||||
//AffineFromCorrespondences2PointRobust(x[0], x[1], 1, &H, &inliers);
|
||||
FundamentalFromCorrespondences7PointRobust(x[0], x[1], 1.0, &H, &inliers);
|
||||
|
||||
//TODO(pmoulon) insert an optimization phase.
|
||||
// Rerun Robust correspondance on the inliers.
|
||||
// it will allow to compute a better model and filter ugly fitting.
|
||||
|
||||
//-- Assert that the output of the model is consistent :
|
||||
// As much as the minimal points are inliers.
|
||||
if (inliers.size() > 7 * 2) { //2* [nbPoints required by the estimator]
|
||||
// If tracks table is empty initialize it
|
||||
if (m_featureToTrackTable.size() == 0) {
|
||||
// Build new correspondence graph containing only inliers.
|
||||
for (int l = 0; l < inliers.size(); ++l) {
|
||||
const int k = inliers[l];
|
||||
m_featureToTrackTable[matchIn.Get(0, tracks[k])] = l;
|
||||
m_featureToTrackTable[matchIn.Get(1, tracks[k])] = l;
|
||||
m_tracks.Insert(dataAindex, l,
|
||||
matchIn.Get(dataBindex, tracks[k]));
|
||||
m_tracks.Insert(dataBindex, l,
|
||||
matchIn.Get(dataAindex, tracks[k]));
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Else update the tracks
|
||||
for (int l = 0; l < inliers.size(); ++l) {
|
||||
const int k = inliers[l];
|
||||
map<const Feature*, int>::const_iterator iter =
|
||||
m_featureToTrackTable.find(matchIn.Get(1, tracks[k]));
|
||||
|
||||
if (iter!=m_featureToTrackTable.end()) {
|
||||
// Add a feature to the existing track
|
||||
const int trackIndex = iter->second;
|
||||
m_featureToTrackTable[matchIn.Get(0, tracks[k])] = trackIndex;
|
||||
m_tracks.Insert(dataAindex, trackIndex,
|
||||
matchIn.Get(0, tracks[k]));
|
||||
}
|
||||
else {
|
||||
// It's a new track
|
||||
const int trackIndex = m_tracks.NumTracks();
|
||||
m_featureToTrackTable[matchIn.Get(0, tracks[k])] = trackIndex;
|
||||
m_featureToTrackTable[matchIn.Get(1, tracks[k])] = trackIndex;
|
||||
m_tracks.Insert(dataAindex, trackIndex,
|
||||
matchIn.Get(0, tracks[k]));
|
||||
m_tracks.Insert(dataBindex, trackIndex,
|
||||
matchIn.Get(1, tracks[k]));
|
||||
}
|
||||
}
|
||||
}
|
||||
// Export common feature between the two view
|
||||
if (matchesOut) {
|
||||
Matches & consistent_matches = *matchesOut;
|
||||
// Build new correspondence graph containing only inliers.
|
||||
for (int l = 0; l < inliers.size(); ++l) {
|
||||
int k = inliers[l];
|
||||
for (int i = 0; i < 2; ++i) {
|
||||
consistent_matches.Insert(images[i], tracks[k],
|
||||
matchIn.Get(images[i], tracks[k]));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,138 @@
|
||||
// Copyright (c) 2010 libmv authors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
|
||||
#ifndef LIBMV_CORRESPONDENCE_N_ROBUST_VIEW_MATCHING_INTERFACE_H_
|
||||
#define LIBMV_CORRESPONDENCE_N_ROBUST_VIEW_MATCHING_INTERFACE_H_
|
||||
|
||||
struct FeatureSet;
|
||||
#include <map>
|
||||
|
||||
#include "libmv/correspondence/feature.h"
|
||||
#include "libmv/correspondence/matches.h"
|
||||
#include "libmv/correspondence/nViewMatchingInterface.h"
|
||||
|
||||
namespace libmv {
|
||||
namespace correspondence {
|
||||
|
||||
using namespace std;
|
||||
|
||||
class nRobustViewMatching :public nViewMatchingInterface {
|
||||
|
||||
public:
|
||||
nRobustViewMatching();
|
||||
// Constructor (Specify a detector and a describer interface)
|
||||
// The class do not handle memory management over this two parameter.
|
||||
nRobustViewMatching(cv::Ptr<cv::FeatureDetector> pDetector,
|
||||
cv::Ptr<cv::DescriptorExtractor> pDescriber);
|
||||
//TODO(pmoulon) Add a constructor with a Detector and a Descriptor
|
||||
// Add also a Template function to make the match robust..
|
||||
~nRobustViewMatching(){};
|
||||
|
||||
/**
|
||||
* Compute the data and store it in the class map<string,T>
|
||||
*
|
||||
* \param[in] filename The file from which the data will be extracted.
|
||||
*
|
||||
* \return True if success.
|
||||
*/
|
||||
bool computeData(const string & filename);
|
||||
|
||||
/**
|
||||
* Compute the putative match between data computed from element A and B
|
||||
* Store the match data internally in the class
|
||||
* map< <string, string> , MatchObject >
|
||||
*
|
||||
* \param[in] The name of the filename A (use computed data for this element)
|
||||
* \param[in] The name of the filename B (use computed data for this element)
|
||||
*
|
||||
* \return True if success.
|
||||
*/
|
||||
bool MatchData(const string & dataA, const string & dataB);
|
||||
|
||||
/**
|
||||
* From a series of element it computes the cross putative match list.
|
||||
*
|
||||
* \param[in] vec_data The data on which we want compute cross matches.
|
||||
*
|
||||
* \return True if success (and any matches was found).
|
||||
*/
|
||||
bool computeCrossMatch( const std::vector<string> & vec_data);
|
||||
|
||||
|
||||
/**
|
||||
* From a series of element it computes the incremental putative match list.
|
||||
* (only locally, in the relative neighborhood)
|
||||
*
|
||||
* \param[in] vec_data The data on which we want compute matches.
|
||||
*
|
||||
* \return True if success (and any matches was found).
|
||||
*/
|
||||
bool computeRelativeMatch( const std::vector<string> & vec_data);
|
||||
|
||||
/**
|
||||
* Give the posibility to constrain the matches list.
|
||||
*
|
||||
* \param[in] matchIn The input match data between indexA and indexB.
|
||||
* \param[in] dataAindex The reference index for element A.
|
||||
* \param[in] dataBindex The reference index for element B.
|
||||
* \param[out] matchesOut The output match that satisfy the internal constraint.
|
||||
*
|
||||
* \return True if success.
|
||||
*/
|
||||
bool computeConstrainMatches(const Matches & matchIn,
|
||||
int dataAindex,
|
||||
int dataBindex,
|
||||
Matches * matchesOut);
|
||||
|
||||
/// Return pairwise correspondence ( geometrically filtered )
|
||||
const map< pair<string,string>, Matches> & getSharedData() const
|
||||
{ return m_sharedData; }
|
||||
/// Return extracted feature over the given image.
|
||||
const map<string,FeatureSet> & getViewData() const
|
||||
{ return m_ViewData; }
|
||||
/// Return detected geometrical consistent matches
|
||||
const Matches & getMatches() const
|
||||
{ return m_tracks; }
|
||||
|
||||
private :
|
||||
/// Input data names
|
||||
std::vector<string> m_vec_InputNames;
|
||||
/// Data that represent each named element.
|
||||
map<string,FeatureSet> m_ViewData;
|
||||
/// Matches between element named element <A,B>.
|
||||
map< pair<string,string>, Matches> m_sharedData;
|
||||
|
||||
/// LookUpTable to make the crossCorrespondence easier between tracks
|
||||
/// and feature.
|
||||
map<const Feature*, int> m_featureToTrackTable;
|
||||
|
||||
/// Matches between all the view.
|
||||
Matches m_tracks;
|
||||
|
||||
/// Interface to detect Keypoint.
|
||||
std::shared_ptr<cv::FeatureDetector> m_pDetector;
|
||||
/// Interface to describe Keypoint.
|
||||
std::shared_ptr<cv::DescriptorExtractor> m_pDescriber;
|
||||
};
|
||||
|
||||
} // using namespace correspondence
|
||||
} // using namespace libmv
|
||||
|
||||
#endif // LIBMV_CORRESPONDENCE_N_ROBUST_VIEW_MATCHING_INTERFACE_H_
|
||||
@@ -0,0 +1,70 @@
|
||||
// Copyright (c) 2010 libmv authors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
|
||||
#ifndef LIBMV_CORRESPONDENCE_N_VIEW_MATCHING_INTERFACE_H_
|
||||
#define LIBMV_CORRESPONDENCE_N_VIEW_MATCHING_INTERFACE_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace libmv {
|
||||
namespace correspondence {
|
||||
|
||||
using namespace std;
|
||||
|
||||
class nViewMatchingInterface {
|
||||
|
||||
public:
|
||||
virtual ~nViewMatchingInterface() {};
|
||||
|
||||
/**
|
||||
* Compute the data and store it in the class map<string,T>
|
||||
*
|
||||
* \param[in] filename The file from which the data will be extracted.
|
||||
*
|
||||
* \return True if success.
|
||||
*/
|
||||
virtual bool computeData(const string & filename)=0;
|
||||
|
||||
/**
|
||||
* Compute the putative match between data computed from element A and B
|
||||
* Store the match data internally in the class
|
||||
* map< <string, string> , MatchObject >
|
||||
*
|
||||
* \param[in] The name of the filename A (use computed data for this element)
|
||||
* \param[in] The name of the filename B (use computed data for this element)
|
||||
*
|
||||
* \return True if success.
|
||||
*/
|
||||
virtual bool MatchData(const string & dataA, const string & dataB)=0;
|
||||
|
||||
/**
|
||||
* From a series of element it compute the cross putative match list.
|
||||
*
|
||||
* \param[in] vec_data The data on which we want compute cross matches.
|
||||
*
|
||||
* \return True if success (and any matches was found).
|
||||
*/
|
||||
virtual bool computeCrossMatch( const std::vector<string> & vec_data)=0;
|
||||
};
|
||||
|
||||
} // using namespace correspondence
|
||||
} // using namespace libmv
|
||||
|
||||
#endif // LIBMV_CORRESPONDENCE_N_VIEW_MATCHING_INTERFACE_H_
|
||||
@@ -0,0 +1,36 @@
|
||||
// Copyright (c) 2007, 2008, 2009 libmv authors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
|
||||
#ifndef LIBMV_LOGGING_LOGGING_H
|
||||
#define LIBMV_LOGGING_LOGGING_H
|
||||
|
||||
#include <glog/logging.h>
|
||||
|
||||
|
||||
#if defined _MSC_VER && _MSC_VER < 1900
|
||||
# define snprintf _snprintf
|
||||
#endif
|
||||
|
||||
#define LG LOG(INFO)
|
||||
#define V0 LOG(INFO)
|
||||
#define V1 LOG(INFO)
|
||||
#define V2 LOG(INFO)
|
||||
|
||||
#endif // LIBMV_LOGGING_LOGGING_H
|
||||
@@ -0,0 +1,28 @@
|
||||
# define the source files
|
||||
SET(MULTIVIEW_SRC conditioning.cc
|
||||
euclidean_resection.cc
|
||||
fundamental.cc
|
||||
fundamental_kernel.cc
|
||||
homography.cc
|
||||
panography.cc
|
||||
panography_kernel.cc
|
||||
projection.cc
|
||||
robust_estimation.cc
|
||||
robust_fundamental.cc
|
||||
robust_resection.cc
|
||||
triangulation.cc
|
||||
twoviewtriangulation.cc)
|
||||
|
||||
# define the header files (make the headers appear in IDEs.)
|
||||
FILE(GLOB MULTIVIEW_HDRS *.h)
|
||||
|
||||
ADD_LIBRARY(opencv.sfm.multiview STATIC ${MULTIVIEW_SRC} ${MULTIVIEW_HDRS})
|
||||
TARGET_LINK_LIBRARIES(opencv.sfm.multiview LINK_PRIVATE ${GLOG_LIBRARIES} opencv.sfm.numeric)
|
||||
IF(TARGET Eigen3::Eigen)
|
||||
TARGET_LINK_LIBRARIES(opencv.sfm.multiview LINK_PUBLIC Eigen3::Eigen)
|
||||
ENDIF()
|
||||
IF(CERES_LIBRARIES)
|
||||
TARGET_LINK_LIBRARIES(opencv.sfm.multiview LINK_PRIVATE ${CERES_LIBRARIES})
|
||||
ENDIF()
|
||||
|
||||
LIBMV_INSTALL_LIB(opencv.sfm.multiview)
|
||||
@@ -0,0 +1,99 @@
|
||||
// Copyright (c) 2010 libmv authors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
|
||||
#include "libmv/multiview/conditioning.h"
|
||||
#include "libmv/multiview/projection.h"
|
||||
|
||||
namespace libmv {
|
||||
|
||||
// HZ 4.4.4 pag.109: Point conditioning (non isotropic)
|
||||
void PreconditionerFromPoints(const Mat &points, Mat3 *T) {
|
||||
Vec mean, variance;
|
||||
MeanAndVarianceAlongRows(points, &mean, &variance);
|
||||
|
||||
double xfactor = sqrt(2.0 / variance(0));
|
||||
double yfactor = sqrt(2.0 / variance(1));
|
||||
|
||||
// If variance is equal to 0.0 set scaling factor to identity.
|
||||
// -> Else it will provide nan value (because division by 0).
|
||||
if (variance(0) < 1e-8)
|
||||
xfactor = mean(0) = 1.0;
|
||||
if (variance(1) < 1e-8)
|
||||
yfactor = mean(1) = 1.0;
|
||||
|
||||
*T << xfactor, 0, -xfactor * mean(0),
|
||||
0, yfactor, -yfactor * mean(1),
|
||||
0, 0, 1;
|
||||
}
|
||||
// HZ 4.4.4 pag.107: Point conditioning (isotropic)
|
||||
void IsotropicPreconditionerFromPoints(const Mat &points, Mat3 *T) {
|
||||
Vec mean, variance;
|
||||
MeanAndVarianceAlongRows(points, &mean, &variance);
|
||||
|
||||
double var_norm = variance.norm();
|
||||
double factor = sqrt(2.0 / var_norm);
|
||||
|
||||
// If variance is equal to 0.0 set scaling factor to identity.
|
||||
// -> Else it will provide nan value (because division by 0).
|
||||
if (var_norm < 1e-8) {
|
||||
factor = 1.0;
|
||||
mean.setOnes();
|
||||
}
|
||||
|
||||
*T << factor, 0, -factor * mean(0),
|
||||
0, factor, -factor * mean(1),
|
||||
0, 0, 1;
|
||||
}
|
||||
|
||||
void ApplyTransformationToPoints(const Mat &points,
|
||||
const Mat3 &T,
|
||||
Mat *transformed_points) {
|
||||
int n = points.cols();
|
||||
transformed_points->resize(2, n);
|
||||
Mat3X p(3, n);
|
||||
EuclideanToHomogeneous(points, &p);
|
||||
p = T * p;
|
||||
HomogeneousToEuclidean(p, transformed_points);
|
||||
}
|
||||
|
||||
void NormalizePoints(const Mat &points,
|
||||
Mat *normalized_points,
|
||||
Mat3 *T) {
|
||||
PreconditionerFromPoints(points, T);
|
||||
ApplyTransformationToPoints(points, *T, normalized_points);
|
||||
}
|
||||
|
||||
void NormalizeIsotropicPoints(const Mat &points,
|
||||
Mat *normalized_points,
|
||||
Mat3 *T) {
|
||||
IsotropicPreconditionerFromPoints(points, T);
|
||||
ApplyTransformationToPoints(points, *T, normalized_points);
|
||||
}
|
||||
|
||||
// Denormalize the results. See HZ page 109.
|
||||
void UnnormalizerT::Unnormalize(const Mat3 &T1, const Mat3 &T2, Mat3 *H) {
|
||||
*H = T2.transpose() * (*H) * T1;
|
||||
}
|
||||
|
||||
void UnnormalizerI::Unnormalize(const Mat3 &T1, const Mat3 &T2, Mat3 *H) {
|
||||
*H = T2.inverse() * (*H) * T1;
|
||||
}
|
||||
|
||||
} // namespace libmv
|
||||
@@ -0,0 +1,59 @@
|
||||
// Copyright (c) 2010 libmv authors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
|
||||
#ifndef LIBMV_MULTIVIEW_CONDITIONNING_H_
|
||||
#define LIBMV_MULTIVIEW_CONDITIONNING_H_
|
||||
|
||||
#include "libmv/numeric/numeric.h"
|
||||
|
||||
namespace libmv {
|
||||
|
||||
// Point conditioning (non isotropic)
|
||||
void PreconditionerFromPoints(const Mat &points, Mat3 *T);
|
||||
// Point conditioning (isotropic)
|
||||
void IsotropicPreconditionerFromPoints(const Mat &points, Mat3 *T);
|
||||
|
||||
void ApplyTransformationToPoints(const Mat &points,
|
||||
const Mat3 &T,
|
||||
Mat *transformed_points);
|
||||
|
||||
void NormalizePoints(const Mat &points,
|
||||
Mat *normalized_points,
|
||||
Mat3 *T);
|
||||
|
||||
void NormalizeIsotropicPoints(const Mat &points,
|
||||
Mat *normalized_points,
|
||||
Mat3 *T);
|
||||
|
||||
/// Use inverse for unnormalize
|
||||
struct UnnormalizerI {
|
||||
// Denormalize the results. See HZ page 109.
|
||||
static void Unnormalize(const Mat3 &T1, const Mat3 &T2, Mat3 *H);
|
||||
};
|
||||
|
||||
/// Use transpose for unnormalize
|
||||
struct UnnormalizerT {
|
||||
// Denormalize the results. See HZ page 109.
|
||||
static void Unnormalize(const Mat3 &T1, const Mat3 &T2, Mat3 *H);
|
||||
};
|
||||
|
||||
} // namespace libmv
|
||||
|
||||
#endif // LIBMV_MULTIVIEW_CONDITIONNING_H_
|
||||
@@ -0,0 +1,774 @@
|
||||
// Copyright (c) 2009 libmv authors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
|
||||
#include "libmv/multiview/euclidean_resection.h"
|
||||
|
||||
#include <cmath>
|
||||
#include <limits>
|
||||
|
||||
#include <Eigen/SVD>
|
||||
#include <Eigen/Geometry>
|
||||
|
||||
#include "libmv/base/vector.h"
|
||||
#include "libmv/logging/logging.h"
|
||||
#include "libmv/multiview/projection.h"
|
||||
|
||||
namespace libmv {
|
||||
namespace euclidean_resection {
|
||||
|
||||
typedef unsigned int uint;
|
||||
|
||||
bool EuclideanResection(const Mat2X &x_camera,
|
||||
const Mat3X &X_world,
|
||||
Mat3 *R, Vec3 *t,
|
||||
ResectionMethod method) {
|
||||
switch (method) {
|
||||
case RESECTION_ANSAR_DANIILIDIS:
|
||||
EuclideanResectionAnsarDaniilidis(x_camera, X_world, R, t);
|
||||
break;
|
||||
case RESECTION_EPNP:
|
||||
return EuclideanResectionEPnP(x_camera, X_world, R, t);
|
||||
break;
|
||||
case RESECTION_PPNP:
|
||||
return EuclideanResectionPPnP(x_camera, X_world, R, t);
|
||||
break;
|
||||
default:
|
||||
LOG(FATAL) << "Unknown resection method.";
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool EuclideanResection(const Mat &x_image,
|
||||
const Mat3X &X_world,
|
||||
const Mat3 &K,
|
||||
Mat3 *R, Vec3 *t,
|
||||
ResectionMethod method) {
|
||||
CHECK(x_image.rows() == 2 || x_image.rows() == 3)
|
||||
<< "Invalid size for x_image: "
|
||||
<< x_image.rows() << "x" << x_image.cols();
|
||||
|
||||
Mat2X x_camera;
|
||||
if (x_image.rows() == 2) {
|
||||
EuclideanToNormalizedCamera(x_image, K, &x_camera);
|
||||
} else if (x_image.rows() == 3) {
|
||||
HomogeneousToNormalizedCamera(x_image, K, &x_camera);
|
||||
}
|
||||
return EuclideanResection(x_camera, X_world, R, t, method);
|
||||
}
|
||||
|
||||
void AbsoluteOrientation(const Mat3X &X,
|
||||
const Mat3X &Xp,
|
||||
Mat3 *R,
|
||||
Vec3 *t) {
|
||||
int num_points = X.cols();
|
||||
Vec3 C = X.rowwise().sum() / num_points; // Centroid of X.
|
||||
Vec3 Cp = Xp.rowwise().sum() / num_points; // Centroid of Xp.
|
||||
|
||||
// Normalize the two point sets.
|
||||
Mat3X Xn(3, num_points), Xpn(3, num_points);
|
||||
for (int i = 0; i < num_points; ++i) {
|
||||
Xn.col(i) = X.col(i) - C;
|
||||
Xpn.col(i) = Xp.col(i) - Cp;
|
||||
}
|
||||
|
||||
// Construct the N matrix (pg. 635).
|
||||
double Sxx = Xn.row(0).dot(Xpn.row(0));
|
||||
double Syy = Xn.row(1).dot(Xpn.row(1));
|
||||
double Szz = Xn.row(2).dot(Xpn.row(2));
|
||||
double Sxy = Xn.row(0).dot(Xpn.row(1));
|
||||
double Syx = Xn.row(1).dot(Xpn.row(0));
|
||||
double Sxz = Xn.row(0).dot(Xpn.row(2));
|
||||
double Szx = Xn.row(2).dot(Xpn.row(0));
|
||||
double Syz = Xn.row(1).dot(Xpn.row(2));
|
||||
double Szy = Xn.row(2).dot(Xpn.row(1));
|
||||
|
||||
Mat4 N;
|
||||
N << Sxx + Syy + Szz, Syz - Szy, Szx - Sxz, Sxy - Syx,
|
||||
Syz - Szy, Sxx - Syy - Szz, Sxy + Syx, Szx + Sxz,
|
||||
Szx - Sxz, Sxy + Syx, -Sxx + Syy - Szz, Syz + Szy,
|
||||
Sxy - Syx, Szx + Sxz, Syz + Szy, -Sxx - Syy + Szz;
|
||||
|
||||
// Find the unit quaternion q that maximizes qNq. It is the eigenvector
|
||||
// corresponding to the lagest eigenvalue.
|
||||
Vec4 q = N.jacobiSvd(Eigen::ComputeFullU).matrixU().col(0);
|
||||
|
||||
// Retrieve the 3x3 rotation matrix.
|
||||
Vec4 qq = q.array() * q.array();
|
||||
double q0q1 = q(0) * q(1);
|
||||
double q0q2 = q(0) * q(2);
|
||||
double q0q3 = q(0) * q(3);
|
||||
double q1q2 = q(1) * q(2);
|
||||
double q1q3 = q(1) * q(3);
|
||||
double q2q3 = q(2) * q(3);
|
||||
|
||||
(*R) << qq(0) + qq(1) - qq(2) - qq(3),
|
||||
2 * (q1q2 - q0q3),
|
||||
2 * (q1q3 + q0q2),
|
||||
2 * (q1q2+ q0q3),
|
||||
qq(0) - qq(1) + qq(2) - qq(3),
|
||||
2 * (q2q3 - q0q1),
|
||||
2 * (q1q3 - q0q2),
|
||||
2 * (q2q3 + q0q1),
|
||||
qq(0) - qq(1) - qq(2) + qq(3);
|
||||
|
||||
// Fix the handedness of the R matrix.
|
||||
if (R->determinant() < 0) {
|
||||
R->row(2) = -R->row(2);
|
||||
}
|
||||
// Compute the final translation.
|
||||
*t = Cp - *R * C;
|
||||
}
|
||||
|
||||
// Convert i and j indices of the original variables into their quadratic
|
||||
// permutation single index. It follows that t_ij = t_ji.
|
||||
static int IJToPointIndex(int i, int j, int num_points) {
|
||||
// Always make sure that j is bigger than i. This handles t_ij = t_ji.
|
||||
if (j < i) {
|
||||
std::swap(i, j);
|
||||
}
|
||||
int idx;
|
||||
int num_permutation_rows = num_points * (num_points - 1) / 2;
|
||||
|
||||
// All t_ii's are located at the end of the t vector after all t_ij's.
|
||||
if (j == i) {
|
||||
idx = num_permutation_rows + i;
|
||||
} else {
|
||||
int offset = (num_points - i - 1) * (num_points - i) / 2;
|
||||
idx = (num_permutation_rows - offset + j - i - 1);
|
||||
}
|
||||
return idx;
|
||||
};
|
||||
|
||||
// Convert i and j indexes of the solution for lambda to their linear indexes.
|
||||
static int IJToIndex(int i, int j, int num_lambda) {
|
||||
if (j < i) {
|
||||
std::swap(i, j);
|
||||
}
|
||||
int A = num_lambda * (num_lambda + 1) / 2;
|
||||
int B = num_lambda - i;
|
||||
int C = B * (B + 1) / 2;
|
||||
int idx = A - C + j - i;
|
||||
return idx;
|
||||
};
|
||||
|
||||
static int Sign(double value) {
|
||||
return (value < 0) ? -1 : 1;
|
||||
};
|
||||
|
||||
// Organizes a square matrix into a single row constraint on the elements of
|
||||
// Lambda to create the constraints in equation (5) in "Linear Pose Estimation
|
||||
// from Points or Lines", by Ansar, A. and Daniilidis, PAMI 2003. vol. 25, no.
|
||||
// 5.
|
||||
static Vec MatrixToConstraint(const Mat &A,
|
||||
int num_k_columns,
|
||||
int num_lambda) {
|
||||
Vec C(num_k_columns);
|
||||
C.setZero();
|
||||
int idx = 0;
|
||||
for (int i = 0; i < num_lambda; ++i) {
|
||||
for (int j = i; j < num_lambda; ++j) {
|
||||
C(idx) = A(i, j);
|
||||
if (i != j) {
|
||||
C(idx) += A(j, i);
|
||||
}
|
||||
++idx;
|
||||
}
|
||||
}
|
||||
return C;
|
||||
}
|
||||
|
||||
// Normalizes the columns of vectors.
|
||||
static void NormalizeColumnVectors(Mat3X *vectors) {
|
||||
int num_columns = vectors->cols();
|
||||
for (int i = 0; i < num_columns; ++i) {
|
||||
vectors->col(i).normalize();
|
||||
}
|
||||
}
|
||||
|
||||
void EuclideanResectionAnsarDaniilidis(const Mat2X &x_camera,
|
||||
const Mat3X &X_world,
|
||||
Mat3 *R,
|
||||
Vec3 *t) {
|
||||
CHECK(x_camera.cols() == X_world.cols());
|
||||
CHECK(x_camera.cols() > 3);
|
||||
|
||||
int num_points = x_camera.cols();
|
||||
|
||||
// Copy the normalized camera coords into 3 vectors and normalize them so
|
||||
// that they are unit vectors from the camera center.
|
||||
Mat3X x_camera_unit(3, num_points);
|
||||
x_camera_unit.block(0, 0, 2, num_points) = x_camera;
|
||||
x_camera_unit.row(2).setOnes();
|
||||
NormalizeColumnVectors(&x_camera_unit);
|
||||
|
||||
int num_m_rows = num_points * (num_points - 1) / 2;
|
||||
int num_tt_variables = num_points * (num_points + 1) / 2;
|
||||
int num_m_columns = num_tt_variables + 1;
|
||||
Mat M(num_m_columns, num_m_columns);
|
||||
M.setZero();
|
||||
Matu ij_index(num_tt_variables, 2);
|
||||
|
||||
// Create the constraint equations for the t_ij variables (7) and arrange
|
||||
// them into the M matrix (8). Also store the initial (i, j) indices.
|
||||
int row = 0;
|
||||
for (int i = 0; i < num_points; ++i) {
|
||||
for (int j = i+1; j < num_points; ++j) {
|
||||
M(row, row) = -2 * x_camera_unit.col(i).dot(x_camera_unit.col(j));
|
||||
M(row, num_m_rows + i) = x_camera_unit.col(i).dot(x_camera_unit.col(i));
|
||||
M(row, num_m_rows + j) = x_camera_unit.col(j).dot(x_camera_unit.col(j));
|
||||
Vec3 Xdiff = X_world.col(i) - X_world.col(j);
|
||||
double center_to_point_distance = Xdiff.norm();
|
||||
M(row, num_m_columns - 1) =
|
||||
- center_to_point_distance * center_to_point_distance;
|
||||
ij_index(row, 0) = i;
|
||||
ij_index(row, 1) = j;
|
||||
++row;
|
||||
}
|
||||
ij_index(i + num_m_rows, 0) = i;
|
||||
ij_index(i + num_m_rows, 1) = i;
|
||||
}
|
||||
|
||||
int num_lambda = num_points + 1; // Dimension of the null space of M.
|
||||
Mat V = M.jacobiSvd(Eigen::ComputeFullV).matrixV().block(0,
|
||||
num_m_rows,
|
||||
num_m_columns,
|
||||
num_lambda);
|
||||
|
||||
// TODO(vess): The number of constraint equations in K (num_k_rows) must be
|
||||
// (num_points + 1) * (num_points + 2)/2. This creates a performance issue
|
||||
// for more than 4 points. It is fine for 4 points at the moment with 18
|
||||
// instead of 15 equations.
|
||||
int num_k_rows = num_m_rows + num_points *
|
||||
(num_points*(num_points-1)/2 - num_points+1);
|
||||
int num_k_columns = num_lambda * (num_lambda + 1) / 2;
|
||||
Mat K(num_k_rows, num_k_columns);
|
||||
K.setZero();
|
||||
|
||||
// Construct the first part of the K matrix corresponding to (t_ii, t_jk) for
|
||||
// i != j.
|
||||
int counter_k_row = 0;
|
||||
for (int idx1 = num_m_rows; idx1 < num_tt_variables; ++idx1) {
|
||||
for (int idx2 = 0; idx2 < num_m_rows; ++idx2) {
|
||||
unsigned int i = ij_index(idx1, 0);
|
||||
unsigned int j = ij_index(idx2, 0);
|
||||
unsigned int k = ij_index(idx2, 1);
|
||||
|
||||
if (i != j && i != k) {
|
||||
int idx3 = IJToPointIndex(i, j, num_points);
|
||||
int idx4 = IJToPointIndex(i, k, num_points);
|
||||
|
||||
K.row(counter_k_row) =
|
||||
MatrixToConstraint(V.row(idx1).transpose() * V.row(idx2)-
|
||||
V.row(idx3).transpose() * V.row(idx4),
|
||||
num_k_columns,
|
||||
num_lambda);
|
||||
++counter_k_row;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Construct the second part of the K matrix corresponding to (t_ii,t_jk) for
|
||||
// j==k.
|
||||
for (int idx1 = num_m_rows; idx1 < num_tt_variables; ++idx1) {
|
||||
for (int idx2 = idx1 + 1; idx2 < num_tt_variables; ++idx2) {
|
||||
unsigned int i = ij_index(idx1, 0);
|
||||
unsigned int j = ij_index(idx2, 0);
|
||||
unsigned int k = ij_index(idx2, 1);
|
||||
|
||||
int idx3 = IJToPointIndex(i, j, num_points);
|
||||
int idx4 = IJToPointIndex(i, k, num_points);
|
||||
|
||||
K.row(counter_k_row) =
|
||||
MatrixToConstraint(V.row(idx1).transpose() * V.row(idx2)-
|
||||
V.row(idx3).transpose() * V.row(idx4),
|
||||
num_k_columns,
|
||||
num_lambda);
|
||||
++counter_k_row;
|
||||
}
|
||||
}
|
||||
Vec L_sq = K.jacobiSvd(Eigen::ComputeFullV).matrixV().col(num_k_columns - 1);
|
||||
|
||||
// Pivot on the largest element for numerical stability. Afterwards recover
|
||||
// the sign of the lambda solution.
|
||||
double max_L_sq_value = fabs(L_sq(IJToIndex(0, 0, num_lambda)));
|
||||
int max_L_sq_index = 1;
|
||||
for (int i = 1; i < num_lambda; ++i) {
|
||||
double abs_sq_value = fabs(L_sq(IJToIndex(i, i, num_lambda)));
|
||||
if (max_L_sq_value < abs_sq_value) {
|
||||
max_L_sq_value = abs_sq_value;
|
||||
max_L_sq_index = i;
|
||||
}
|
||||
}
|
||||
// Ensure positiveness of the largest value corresponding to lambda_ii.
|
||||
L_sq = L_sq * Sign(L_sq(IJToIndex(max_L_sq_index,
|
||||
max_L_sq_index,
|
||||
num_lambda)));
|
||||
|
||||
Vec L(num_lambda);
|
||||
L(max_L_sq_index) = sqrt(L_sq(IJToIndex(max_L_sq_index,
|
||||
max_L_sq_index,
|
||||
num_lambda)));
|
||||
|
||||
for (int i = 0; i < num_lambda; ++i) {
|
||||
if (i != max_L_sq_index) {
|
||||
L(i) = L_sq(IJToIndex(max_L_sq_index, i, num_lambda)) / L(max_L_sq_index);
|
||||
}
|
||||
}
|
||||
|
||||
// Correct the scale using the fact that the last constraint is equal to 1.
|
||||
L = L / (V.row(num_m_columns - 1).dot(L));
|
||||
Vec X = V * L;
|
||||
|
||||
// Recover the distances from the camera center to the 3D points Q.
|
||||
Vec d(num_points);
|
||||
d.setZero();
|
||||
for (int c_point = num_m_rows; c_point < num_tt_variables; ++c_point) {
|
||||
d(c_point - num_m_rows) = sqrt(X(c_point));
|
||||
}
|
||||
|
||||
// Create the 3D points in the camera system.
|
||||
Mat X_cam(3, num_points);
|
||||
for (int c_point = 0; c_point < num_points; ++c_point) {
|
||||
X_cam.col(c_point) = d(c_point) * x_camera_unit.col(c_point);
|
||||
}
|
||||
// Recover the camera translation and rotation.
|
||||
AbsoluteOrientation(X_world, X_cam, R, t);
|
||||
}
|
||||
|
||||
// Selects 4 virtual control points using mean and PCA.
|
||||
static void SelectControlPoints(const Mat3X &X_world,
|
||||
Mat *X_centered,
|
||||
Mat34 *X_control_points) {
|
||||
size_t num_points = X_world.cols();
|
||||
|
||||
// The first virtual control point, C0, is the centroid.
|
||||
Vec mean, variance;
|
||||
MeanAndVarianceAlongRows(X_world, &mean, &variance);
|
||||
X_control_points->col(0) = mean;
|
||||
|
||||
// Computes PCA
|
||||
X_centered->resize(3, num_points);
|
||||
for (size_t c = 0; c < num_points; c++) {
|
||||
X_centered->col(c) = X_world.col(c) - mean;
|
||||
}
|
||||
Mat3 X_centered_sq = (*X_centered) * X_centered->transpose();
|
||||
Eigen::JacobiSVD<Mat3> X_centered_sq_svd(X_centered_sq, Eigen::ComputeFullU);
|
||||
Vec3 w = X_centered_sq_svd.singularValues();
|
||||
Mat3 u = X_centered_sq_svd.matrixU();
|
||||
for (size_t c = 0; c < 3; c++) {
|
||||
double k = sqrt(w(c) / num_points);
|
||||
X_control_points->col(c + 1) = mean + k * u.col(c);
|
||||
}
|
||||
}
|
||||
|
||||
// Computes the barycentric coordinates for all real points
|
||||
static void ComputeBarycentricCoordinates(const Mat3X &X_world_centered,
|
||||
const Mat34 &X_control_points,
|
||||
Mat4X *alphas) {
|
||||
size_t num_points = X_world_centered.cols();
|
||||
Mat3 C2;
|
||||
for (size_t c = 1; c < 4; c++) {
|
||||
C2.col(c-1) = X_control_points.col(c) - X_control_points.col(0);
|
||||
}
|
||||
|
||||
Mat3 C2inv = C2.inverse();
|
||||
Mat3X a = C2inv * X_world_centered;
|
||||
|
||||
alphas->resize(4, num_points);
|
||||
alphas->setZero();
|
||||
alphas->block(1, 0, 3, num_points) = a;
|
||||
for (size_t c = 0; c < num_points; c++) {
|
||||
(*alphas)(0, c) = 1.0 - alphas->col(c).sum();
|
||||
}
|
||||
}
|
||||
|
||||
// Estimates the coordinates of all real points in the camera coordinate frame
|
||||
static void ComputePointsCoordinatesInCameraFrame(
|
||||
const Mat4X &alphas,
|
||||
const Vec4 &betas,
|
||||
const Eigen::Matrix<double, 12, 12> &U,
|
||||
Mat3X *X_camera) {
|
||||
size_t num_points = alphas.cols();
|
||||
|
||||
// Estimates the control points in the camera reference frame.
|
||||
Mat34 C2b; C2b.setZero();
|
||||
for (size_t cu = 0; cu < 4; cu++) {
|
||||
for (size_t c = 0; c < 4; c++) {
|
||||
C2b.col(c) += betas(cu) * U.block(11 - cu, c * 3, 1, 3).transpose();
|
||||
}
|
||||
}
|
||||
|
||||
// Estimates the 3D points in the camera reference frame
|
||||
X_camera->resize(3, num_points);
|
||||
for (size_t c = 0; c < num_points; c++) {
|
||||
X_camera->col(c) = C2b * alphas.col(c);
|
||||
}
|
||||
|
||||
// Check the sign of the z coordinate of the points (should be positive)
|
||||
uint num_z_neg = 0;
|
||||
for (size_t i = 0; i < X_camera->cols(); ++i) {
|
||||
if ((*X_camera)(2, i) < 0) {
|
||||
num_z_neg++;
|
||||
}
|
||||
}
|
||||
|
||||
// If more than 50% of z are negative, we change the signs
|
||||
if (num_z_neg > 0.5 * X_camera->cols()) {
|
||||
C2b = -C2b;
|
||||
*X_camera = -(*X_camera);
|
||||
}
|
||||
}
|
||||
|
||||
bool EuclideanResectionEPnP(const Mat2X &x_camera,
|
||||
const Mat3X &X_world,
|
||||
Mat3 *R, Vec3 *t) {
|
||||
CHECK(x_camera.cols() == X_world.cols());
|
||||
CHECK(x_camera.cols() > 3);
|
||||
size_t num_points = X_world.cols();
|
||||
|
||||
// Select the control points.
|
||||
Mat34 X_control_points;
|
||||
Mat X_centered;
|
||||
SelectControlPoints(X_world, &X_centered, &X_control_points);
|
||||
|
||||
// Compute the barycentric coordinates.
|
||||
Mat4X alphas(4, num_points);
|
||||
ComputeBarycentricCoordinates(X_centered, X_control_points, &alphas);
|
||||
|
||||
// Estimates the M matrix with the barycentric coordinates
|
||||
Mat M(2 * num_points, 12);
|
||||
Eigen::Matrix<double, 2, 12> sub_M;
|
||||
for (size_t c = 0; c < num_points; c++) {
|
||||
double a0 = alphas(0, c);
|
||||
double a1 = alphas(1, c);
|
||||
double a2 = alphas(2, c);
|
||||
double a3 = alphas(3, c);
|
||||
double ui = x_camera(0, c);
|
||||
double vi = x_camera(1, c);
|
||||
M.block(2*c, 0, 2, 12) << a0, 0,
|
||||
a0*(-ui), a1, 0,
|
||||
a1*(-ui), a2, 0,
|
||||
a2*(-ui), a3, 0,
|
||||
a3*(-ui), 0,
|
||||
a0, a0*(-vi), 0,
|
||||
a1, a1*(-vi), 0,
|
||||
a2, a2*(-vi), 0,
|
||||
a3, a3*(-vi);
|
||||
}
|
||||
|
||||
// TODO(julien): Avoid the transpose by rewriting the u2.block() calls.
|
||||
Eigen::JacobiSVD<Mat> MtMsvd(M.transpose()*M, Eigen::ComputeFullU);
|
||||
Eigen::Matrix<double, 12, 12> u2 = MtMsvd.matrixU().transpose();
|
||||
|
||||
// Estimate the L matrix.
|
||||
Eigen::Matrix<double, 6, 3> dv1;
|
||||
Eigen::Matrix<double, 6, 3> dv2;
|
||||
Eigen::Matrix<double, 6, 3> dv3;
|
||||
Eigen::Matrix<double, 6, 3> dv4;
|
||||
|
||||
dv1.row(0) = u2.block(11, 0, 1, 3) - u2.block(11, 3, 1, 3);
|
||||
dv1.row(1) = u2.block(11, 0, 1, 3) - u2.block(11, 6, 1, 3);
|
||||
dv1.row(2) = u2.block(11, 0, 1, 3) - u2.block(11, 9, 1, 3);
|
||||
dv1.row(3) = u2.block(11, 3, 1, 3) - u2.block(11, 6, 1, 3);
|
||||
dv1.row(4) = u2.block(11, 3, 1, 3) - u2.block(11, 9, 1, 3);
|
||||
dv1.row(5) = u2.block(11, 6, 1, 3) - u2.block(11, 9, 1, 3);
|
||||
dv2.row(0) = u2.block(10, 0, 1, 3) - u2.block(10, 3, 1, 3);
|
||||
dv2.row(1) = u2.block(10, 0, 1, 3) - u2.block(10, 6, 1, 3);
|
||||
dv2.row(2) = u2.block(10, 0, 1, 3) - u2.block(10, 9, 1, 3);
|
||||
dv2.row(3) = u2.block(10, 3, 1, 3) - u2.block(10, 6, 1, 3);
|
||||
dv2.row(4) = u2.block(10, 3, 1, 3) - u2.block(10, 9, 1, 3);
|
||||
dv2.row(5) = u2.block(10, 6, 1, 3) - u2.block(10, 9, 1, 3);
|
||||
dv3.row(0) = u2.block(9, 0, 1, 3) - u2.block(9, 3, 1, 3);
|
||||
dv3.row(1) = u2.block(9, 0, 1, 3) - u2.block(9, 6, 1, 3);
|
||||
dv3.row(2) = u2.block(9, 0, 1, 3) - u2.block(9, 9, 1, 3);
|
||||
dv3.row(3) = u2.block(9, 3, 1, 3) - u2.block(9, 6, 1, 3);
|
||||
dv3.row(4) = u2.block(9, 3, 1, 3) - u2.block(9, 9, 1, 3);
|
||||
dv3.row(5) = u2.block(9, 6, 1, 3) - u2.block(9, 9, 1, 3);
|
||||
dv4.row(0) = u2.block(8, 0, 1, 3) - u2.block(8, 3, 1, 3);
|
||||
dv4.row(1) = u2.block(8, 0, 1, 3) - u2.block(8, 6, 1, 3);
|
||||
dv4.row(2) = u2.block(8, 0, 1, 3) - u2.block(8, 9, 1, 3);
|
||||
dv4.row(3) = u2.block(8, 3, 1, 3) - u2.block(8, 6, 1, 3);
|
||||
dv4.row(4) = u2.block(8, 3, 1, 3) - u2.block(8, 9, 1, 3);
|
||||
dv4.row(5) = u2.block(8, 6, 1, 3) - u2.block(8, 9, 1, 3);
|
||||
|
||||
Eigen::Matrix<double, 6, 10> L;
|
||||
for (size_t r = 0; r < 6; r++) {
|
||||
L.row(r) << dv1.row(r).dot(dv1.row(r)),
|
||||
2.0 * dv1.row(r).dot(dv2.row(r)),
|
||||
dv2.row(r).dot(dv2.row(r)),
|
||||
2.0 * dv1.row(r).dot(dv3.row(r)),
|
||||
2.0 * dv2.row(r).dot(dv3.row(r)),
|
||||
dv3.row(r).dot(dv3.row(r)),
|
||||
2.0 * dv1.row(r).dot(dv4.row(r)),
|
||||
2.0 * dv2.row(r).dot(dv4.row(r)),
|
||||
2.0 * dv3.row(r).dot(dv4.row(r)),
|
||||
dv4.row(r).dot(dv4.row(r));
|
||||
}
|
||||
Vec6 rho;
|
||||
rho << (X_control_points.col(0) - X_control_points.col(1)).squaredNorm(),
|
||||
(X_control_points.col(0) - X_control_points.col(2)).squaredNorm(),
|
||||
(X_control_points.col(0) - X_control_points.col(3)).squaredNorm(),
|
||||
(X_control_points.col(1) - X_control_points.col(2)).squaredNorm(),
|
||||
(X_control_points.col(1) - X_control_points.col(3)).squaredNorm(),
|
||||
(X_control_points.col(2) - X_control_points.col(3)).squaredNorm();
|
||||
|
||||
// There are three possible solutions based on the three approximations of L
|
||||
// (betas). Below, each one is solved for then the best one is chosen.
|
||||
Mat3X X_camera;
|
||||
Mat3 K; K.setIdentity();
|
||||
vector<Mat3> Rs(3);
|
||||
vector<Vec3> ts(3);
|
||||
Vec rmse(3);
|
||||
|
||||
// At one point this threshold was 1e-3, and caused no end of problems in
|
||||
// Blender by causing frames to not resect when they would have worked fine.
|
||||
// When the resect failed, the projective followup is run leading to worse
|
||||
// results, and often the dreaded "flipping" where objects get flipped
|
||||
// between frames. Instead, disable the check for now, always succeeding. The
|
||||
// ultimate check is always reprojection error anyway.
|
||||
//
|
||||
// TODO(keir): Decide if setting this to infinity, effectively disabling the
|
||||
// check, is the right approach. So far this seems the case.
|
||||
double kSuccessThreshold = std::numeric_limits<double>::max();
|
||||
|
||||
// Find the first possible solution for R, t corresponding to:
|
||||
// Betas = [b00 b01 b11 b02 b12 b22 b03 b13 b23 b33]
|
||||
// Betas_approx_1 = [b00 b01 b02 b03]
|
||||
Vec4 betas = Vec4::Zero();
|
||||
Eigen::Matrix<double, 6, 4> l_6x4;
|
||||
for (size_t r = 0; r < 6; r++) {
|
||||
l_6x4.row(r) << L(r, 0), L(r, 1), L(r, 3), L(r, 6);
|
||||
}
|
||||
Eigen::JacobiSVD<Mat> svd_of_l4(l_6x4,
|
||||
Eigen::ComputeFullU | Eigen::ComputeFullV);
|
||||
Vec4 b4 = svd_of_l4.solve(rho);
|
||||
if ((l_6x4 * b4).isApprox(rho, kSuccessThreshold)) {
|
||||
if (b4(0) < 0) {
|
||||
b4 = -b4;
|
||||
}
|
||||
b4(0) = std::sqrt(b4(0));
|
||||
betas << b4(0), b4(1) / b4(0), b4(2) / b4(0), b4(3) / b4(0);
|
||||
ComputePointsCoordinatesInCameraFrame(alphas, betas, u2, &X_camera);
|
||||
AbsoluteOrientation(X_world, X_camera, &Rs[0], &ts[0]);
|
||||
rmse(0) = RootMeanSquareError(x_camera, X_world, K, Rs[0], ts[0]);
|
||||
} else {
|
||||
LOG(ERROR) << "First approximation of beta not good enough.";
|
||||
ts[0].setZero();
|
||||
rmse(0) = std::numeric_limits<double>::max();
|
||||
}
|
||||
|
||||
// Find the second possible solution for R, t corresponding to:
|
||||
// Betas = [b00 b01 b11 b02 b12 b22 b03 b13 b23 b33]
|
||||
// Betas_approx_2 = [b00 b01 b11]
|
||||
betas.setZero();
|
||||
Eigen::Matrix<double, 6, 3> l_6x3;
|
||||
l_6x3 = L.block(0, 0, 6, 3);
|
||||
Eigen::JacobiSVD<Mat> svdOfL3(l_6x3,
|
||||
Eigen::ComputeFullU | Eigen::ComputeFullV);
|
||||
Vec3 b3 = svdOfL3.solve(rho);
|
||||
VLOG(2) << " rho = " << rho;
|
||||
VLOG(2) << " l_6x3 * b3 = " << l_6x3 * b3;
|
||||
if ((l_6x3 * b3).isApprox(rho, kSuccessThreshold)) {
|
||||
if (b3(0) < 0) {
|
||||
betas(0) = std::sqrt(-b3(0));
|
||||
betas(1) = (b3(2) < 0) ? std::sqrt(-b3(2)) : 0;
|
||||
} else {
|
||||
betas(0) = std::sqrt(b3(0));
|
||||
betas(1) = (b3(2) > 0) ? std::sqrt(b3(2)) : 0;
|
||||
}
|
||||
if (b3(1) < 0) {
|
||||
betas(0) = -betas(0);
|
||||
}
|
||||
betas(2) = 0;
|
||||
betas(3) = 0;
|
||||
ComputePointsCoordinatesInCameraFrame(alphas, betas, u2, &X_camera);
|
||||
AbsoluteOrientation(X_world, X_camera, &Rs[1], &ts[1]);
|
||||
rmse(1) = RootMeanSquareError(x_camera, X_world, K, Rs[1], ts[1]);
|
||||
} else {
|
||||
LOG(ERROR) << "Second approximation of beta not good enough.";
|
||||
ts[1].setZero();
|
||||
rmse(1) = std::numeric_limits<double>::max();
|
||||
}
|
||||
|
||||
// Find the third possible solution for R, t corresponding to:
|
||||
// Betas = [b00 b01 b11 b02 b12 b22 b03 b13 b23 b33]
|
||||
// Betas_approx_3 = [b00 b01 b11 b02 b12]
|
||||
betas.setZero();
|
||||
Eigen::Matrix<double, 6, 5> l_6x5;
|
||||
l_6x5 = L.block(0, 0, 6, 5);
|
||||
Eigen::JacobiSVD<Mat> svdOfL5(l_6x5,
|
||||
Eigen::ComputeFullU | Eigen::ComputeFullV);
|
||||
Vec5 b5 = svdOfL5.solve(rho);
|
||||
if ((l_6x5 * b5).isApprox(rho, kSuccessThreshold)) {
|
||||
if (b5(0) < 0) {
|
||||
betas(0) = std::sqrt(-b5(0));
|
||||
if (b5(2) < 0) {
|
||||
betas(1) = std::sqrt(-b5(2));
|
||||
} else {
|
||||
b5(2) = 0;
|
||||
}
|
||||
} else {
|
||||
betas(0) = std::sqrt(b5(0));
|
||||
if (b5(2) > 0) {
|
||||
betas(1) = std::sqrt(b5(2));
|
||||
} else {
|
||||
b5(2) = 0;
|
||||
}
|
||||
}
|
||||
if (b5(1) < 0) {
|
||||
betas(0) = -betas(0);
|
||||
}
|
||||
betas(2) = b5(3) / betas(0);
|
||||
betas(3) = 0;
|
||||
ComputePointsCoordinatesInCameraFrame(alphas, betas, u2, &X_camera);
|
||||
AbsoluteOrientation(X_world, X_camera, &Rs[2], &ts[2]);
|
||||
rmse(2) = RootMeanSquareError(x_camera, X_world, K, Rs[2], ts[2]);
|
||||
} else {
|
||||
LOG(ERROR) << "Third approximation of beta not good enough.";
|
||||
ts[2].setZero();
|
||||
rmse(2) = std::numeric_limits<double>::max();
|
||||
}
|
||||
|
||||
// Finally, with all three solutions, select the (R, t) with the best RMSE.
|
||||
VLOG(2) << "RMSE for solution 0: " << rmse(0);
|
||||
VLOG(2) << "RMSE for solution 1: " << rmse(1);
|
||||
VLOG(2) << "RMSE for solution 2: " << rmse(2);
|
||||
size_t n = 0;
|
||||
if (rmse(1) < rmse(0)) {
|
||||
n = 1;
|
||||
}
|
||||
if (rmse(2) < rmse(n)) {
|
||||
n = 2;
|
||||
}
|
||||
if (rmse(n) == std::numeric_limits<double>::max()) {
|
||||
LOG(ERROR) << "All three possibilities failed. Reporting failure.";
|
||||
return false;
|
||||
}
|
||||
|
||||
VLOG(1) << "RMSE for best solution #" << n << ": " << rmse(n);
|
||||
*R = Rs[n];
|
||||
*t = ts[n];
|
||||
|
||||
// TODO(julien): Improve the solutions with non-linear refinement.
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
Straight from the paper:
|
||||
http://www.diegm.uniud.it/fusiello/papers/3dimpvt12-b.pdf
|
||||
|
||||
function [R T] = ppnp(P,S,tol)
|
||||
% input
|
||||
% P : matrix (nx3) image coordinates in camera reference [u v 1]
|
||||
% S : matrix (nx3) coordinates in world reference [X Y Z]
|
||||
% tol: exit threshold
|
||||
%
|
||||
% output
|
||||
% R : matrix (3x3) rotation (world-to-camera)
|
||||
% T : vector (3x1) translation (world-to-camera)
|
||||
%
|
||||
n = size(P,1);
|
||||
Z = zeros(n);
|
||||
e = ones(n,1);
|
||||
A = eye(n)-((e*e’)./n);
|
||||
II = e./n;
|
||||
err = +Inf;
|
||||
E_old = 1000*ones(n,3);
|
||||
while err>tol
|
||||
[U,˜,V] = svd(P’*Z*A*S);
|
||||
VT = V’;
|
||||
R=U*[1 0 0; 0 1 0; 0 0 det(U*VT)]*VT;
|
||||
PR = P*R;
|
||||
c = (S-Z*PR)’*II;
|
||||
Y = S-e*c’;
|
||||
Zmindiag = diag(PR*Y’)./(sum(P.*P,2));
|
||||
Zmindiag(Zmindiag<0)=0;
|
||||
Z = diag(Zmindiag);
|
||||
E = Y-Z*PR;
|
||||
err = norm(E-E_old,’fro’);
|
||||
E_old = E;
|
||||
end
|
||||
T = -R*c;
|
||||
end
|
||||
|
||||
*/
|
||||
// TODO(keir): Re-do all the variable names and add comments matching the paper.
|
||||
// This implementation has too much of the terseness of the original. On the
|
||||
// other hand, it did work on the first try.
|
||||
bool EuclideanResectionPPnP(const Mat2X &x_camera,
|
||||
const Mat3X &X_world,
|
||||
Mat3 *R, Vec3 *t) {
|
||||
int n = x_camera.cols();
|
||||
Mat Z = Mat::Zero(n, n);
|
||||
Vec e = Vec::Ones(n);
|
||||
Mat A = Mat::Identity(n, n) - (e * e.transpose() / n);
|
||||
Vec II = e / n;
|
||||
|
||||
Mat P(n, 3);
|
||||
P.col(0) = x_camera.row(0);
|
||||
P.col(1) = x_camera.row(1);
|
||||
P.col(2).setConstant(1.0);
|
||||
|
||||
Mat S = X_world.transpose();
|
||||
|
||||
double error = std::numeric_limits<double>::infinity();
|
||||
Mat E_old = 1000 * Mat::Ones(n, 3);
|
||||
|
||||
Vec3 c;
|
||||
Mat E(n, 3);
|
||||
|
||||
int iteration = 0;
|
||||
double tolerance = 1e-5;
|
||||
// TODO(keir): The limit of 100 can probably be reduced, but this will require
|
||||
// some investigation.
|
||||
while (error > tolerance && iteration < 100) {
|
||||
Mat3 tmp = P.transpose() * Z * A * S;
|
||||
Eigen::JacobiSVD<Mat3> svd(tmp, Eigen::ComputeFullU | Eigen::ComputeFullV);
|
||||
Mat3 U = svd.matrixU();
|
||||
Mat3 VT = svd.matrixV().transpose();
|
||||
Vec3 s;
|
||||
s << 1, 1, (U * VT).determinant();
|
||||
*R = U * s.asDiagonal() * VT;
|
||||
Mat PR = P * *R; // n x 3
|
||||
c = (S - Z*PR).transpose() * II;
|
||||
Mat Y = S - e*c.transpose(); // n x 3
|
||||
Vec Zmindiag = (PR * Y.transpose()).diagonal()
|
||||
.cwiseQuotient(P.rowwise().squaredNorm());
|
||||
for (int i = 0; i < n; ++i) {
|
||||
Zmindiag[i] = std::max(Zmindiag[i], 0.0);
|
||||
}
|
||||
Z = Zmindiag.asDiagonal();
|
||||
E = Y - Z*PR;
|
||||
error = (E - E_old).norm();
|
||||
LOG(INFO) << "PPnP error(" << (iteration++) << "): " << error;
|
||||
E_old = E;
|
||||
}
|
||||
*t = -*R*c;
|
||||
|
||||
// TODO(keir): Figure out what the failure cases are. Is it too many
|
||||
// iterations? Spend some time going through the math figuring out if there
|
||||
// is some way to detect that the algorithm is going crazy, and return false.
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
} // namespace resection
|
||||
} // namespace libmv
|
||||
@@ -0,0 +1,148 @@
|
||||
// Copyright (c) 2010 libmv authors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
|
||||
#ifndef LIBMV_MULTIVIEW_EUCLIDEAN_RESECTION_H_
|
||||
#define LIBMV_MULTIVIEW_EUCLIDEAN_RESECTION_H_
|
||||
|
||||
#include "libmv/numeric/numeric.h"
|
||||
#include "libmv/multiview/projection.h"
|
||||
|
||||
namespace libmv {
|
||||
namespace euclidean_resection {
|
||||
|
||||
enum ResectionMethod {
|
||||
RESECTION_ANSAR_DANIILIDIS,
|
||||
|
||||
// The "EPnP" algorithm by Lepetit et al.
|
||||
// http://cvlab.epfl.ch/~lepetit/papers/lepetit_ijcv08.pdf
|
||||
RESECTION_EPNP,
|
||||
|
||||
// The Procrustes PNP algorithm ("PPnP")
|
||||
// http://www.diegm.uniud.it/fusiello/papers/3dimpvt12-b.pdf
|
||||
RESECTION_PPNP
|
||||
};
|
||||
|
||||
/**
|
||||
* Computes the extrinsic parameters, R and t for a calibrated camera
|
||||
* from 4 or more 3D points and their normalized images.
|
||||
*
|
||||
* \param x_camera Image points in normalized camera coordinates e.g. x_camera
|
||||
* = inv(K) * x_image.
|
||||
* \param X_world 3D points in the world coordinate system
|
||||
* \param R Solution for the camera rotation matrix
|
||||
* \param t Solution for the camera translation vector
|
||||
* \param method The resection method to use.
|
||||
*/
|
||||
bool EuclideanResection(const Mat2X &x_camera,
|
||||
const Mat3X &X_world,
|
||||
Mat3 *R, Vec3 *t,
|
||||
ResectionMethod method = RESECTION_EPNP);
|
||||
|
||||
/**
|
||||
* Computes the extrinsic parameters, R and t for a calibrated camera
|
||||
* from 4 or more 3D points and their images.
|
||||
*
|
||||
* \param x_image Image points in non-normalized image coordinates. The
|
||||
* coordates are laid out one per row. The matrix can be Nx2
|
||||
* or Nx3 for euclidean or homogenous 2D coordinates.
|
||||
* \param X_world 3D points in the world coordinate system
|
||||
* \param K Intrinsic parameters camera matrix
|
||||
* \param R Solution for the camera rotation matrix
|
||||
* \param t Solution for the camera translation vector
|
||||
* \param method Resection method
|
||||
*/
|
||||
bool EuclideanResection(const Mat &x_image,
|
||||
const Mat3X &X_world,
|
||||
const Mat3 &K,
|
||||
Mat3 *R, Vec3 *t,
|
||||
ResectionMethod method = RESECTION_EPNP);
|
||||
|
||||
/**
|
||||
* The absolute orientation algorithm recovers the transformation between a set
|
||||
* of 3D points, X and Xp such that:
|
||||
*
|
||||
* Xp = R*X + t
|
||||
*
|
||||
* The recovery of the absolute orientation is implemented after this article:
|
||||
* Horn, Hilden, "Closed-form solution of absolute orientation using
|
||||
* orthonormal matrices"
|
||||
*/
|
||||
void AbsoluteOrientation(const Mat3X &X,
|
||||
const Mat3X &Xp,
|
||||
Mat3 *R,
|
||||
Vec3 *t);
|
||||
|
||||
/**
|
||||
* Computes the extrinsic parameters, R and t for a calibrated camera from 4 or
|
||||
* more 3D points and their images.
|
||||
*
|
||||
* \param x_camera Image points in normalized camera coordinates, e.g.
|
||||
* x_camera=inv(K)*x_image
|
||||
* \param X_world 3D points in the world coordinate system
|
||||
* \param R Solution for the camera rotation matrix
|
||||
* \param t Solution for the camera translation vector
|
||||
*
|
||||
* This is the algorithm described in: "Linear Pose Estimation from Points or
|
||||
* Lines", by Ansar, A. and Daniilidis, PAMI 2003. vol. 25, no. 5.
|
||||
*/
|
||||
void EuclideanResectionAnsarDaniilidis(const Mat2X &x_camera,
|
||||
const Mat3X &X_world,
|
||||
Mat3 *R, Vec3 *t);
|
||||
/**
|
||||
* Computes the extrinsic parameters, R and t for a calibrated camera from 4 or
|
||||
* more 3D points and their images.
|
||||
*
|
||||
* \param x_camera Image points in normalized camera coordinates,
|
||||
* e.g. x_camera = inv(K) * x_image
|
||||
* \param X_world 3D points in the world coordinate system
|
||||
* \param R Solution for the camera rotation matrix
|
||||
* \param t Solution for the camera translation vector
|
||||
*
|
||||
* This is the algorithm described in:
|
||||
* "{EP$n$P: An Accurate $O(n)$ Solution to the P$n$P Problem", by V. Lepetit
|
||||
* and F. Moreno-Noguer and P. Fua, IJCV 2009. vol. 81, no. 2
|
||||
* \note: the non-linear optimization is not implemented here.
|
||||
*/
|
||||
bool EuclideanResectionEPnP(const Mat2X &x_camera,
|
||||
const Mat3X &X_world,
|
||||
Mat3 *R, Vec3 *t);
|
||||
|
||||
/**
|
||||
* Computes the extrinsic parameters, R and t for a calibrated camera from 4 or
|
||||
* more 3D points and their images.
|
||||
*
|
||||
* \param x_camera Image points in normalized camera coordinates,
|
||||
* e.g. x_camera = inv(K) * x_image
|
||||
* \param X_world 3D points in the world coordinate system
|
||||
* \param R Solution for the camera rotation matrix
|
||||
* \param t Solution for the camera translation vector
|
||||
*
|
||||
* Straight from the paper:
|
||||
* http://www.diegm.uniud.it/fusiello/papers/3dimpvt12-b.pdf
|
||||
*/
|
||||
bool EuclideanResectionPPnP(const Mat2X &x_camera,
|
||||
const Mat3X &X_world,
|
||||
Mat3 *R, Vec3 *t);
|
||||
|
||||
} // namespace euclidean_resection
|
||||
} // namespace libmv
|
||||
|
||||
|
||||
#endif /* LIBMV_MULTIVIEW_EUCLIDEAN_RESECTION_H_ */
|
||||
@@ -0,0 +1,551 @@
|
||||
// Copyright (c) 2007, 2008 libmv authors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
|
||||
#include "libmv/multiview/fundamental.h"
|
||||
|
||||
#if CERES_FOUND
|
||||
#include "ceres/ceres.h"
|
||||
#endif
|
||||
#include "libmv/logging/logging.h"
|
||||
#include "libmv/numeric/numeric.h"
|
||||
#include "libmv/numeric/poly.h"
|
||||
#include "libmv/multiview/conditioning.h"
|
||||
#include "libmv/multiview/projection.h"
|
||||
#include "libmv/multiview/triangulation.h"
|
||||
|
||||
namespace libmv {
|
||||
|
||||
static void EliminateRow(const Mat34 &P, int row, Mat *X) {
|
||||
X->resize(2, 4);
|
||||
|
||||
int first_row = (row + 1) % 3;
|
||||
int second_row = (row + 2) % 3;
|
||||
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
(*X)(0, i) = P(first_row, i);
|
||||
(*X)(1, i) = P(second_row, i);
|
||||
}
|
||||
}
|
||||
|
||||
void ProjectionsFromFundamental(const Mat3 &F, Mat34 *P1, Mat34 *P2) {
|
||||
*P1 << Mat3::Identity(), Vec3::Zero();
|
||||
Vec3 e2;
|
||||
Mat3 Ft = F.transpose();
|
||||
Nullspace(&Ft, &e2);
|
||||
*P2 << CrossProductMatrix(e2) * F, e2;
|
||||
}
|
||||
|
||||
// Addapted from vgg_F_from_P.
|
||||
void FundamentalFromProjections(const Mat34 &P1, const Mat34 &P2, Mat3 *F) {
|
||||
Mat X[3];
|
||||
Mat Y[3];
|
||||
Mat XY;
|
||||
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
EliminateRow(P1, i, X + i);
|
||||
EliminateRow(P2, i, Y + i);
|
||||
}
|
||||
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
for (int j = 0; j < 3; ++j) {
|
||||
VerticalStack(X[j], Y[i], &XY);
|
||||
(*F)(i, j) = XY.determinant();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// HZ 11.1 pag.279 (x1 = x, x2 = x')
|
||||
// http://www.cs.unc.edu/~marc/tutorial/node54.html
|
||||
static double EightPointSolver(const Mat &x1, const Mat &x2, Mat3 *F) {
|
||||
DCHECK_EQ(x1.rows(), 2);
|
||||
DCHECK_GE(x1.cols(), 8);
|
||||
DCHECK_EQ(x1.rows(), x2.rows());
|
||||
DCHECK_EQ(x1.cols(), x2.cols());
|
||||
|
||||
int n = x1.cols();
|
||||
Mat A(n, 9);
|
||||
for (int i = 0; i < n; ++i) {
|
||||
A(i, 0) = x2(0, i) * x1(0, i);
|
||||
A(i, 1) = x2(0, i) * x1(1, i);
|
||||
A(i, 2) = x2(0, i);
|
||||
A(i, 3) = x2(1, i) * x1(0, i);
|
||||
A(i, 4) = x2(1, i) * x1(1, i);
|
||||
A(i, 5) = x2(1, i);
|
||||
A(i, 6) = x1(0, i);
|
||||
A(i, 7) = x1(1, i);
|
||||
A(i, 8) = 1;
|
||||
}
|
||||
|
||||
Vec9 f;
|
||||
double smaller_singular_value = Nullspace(&A, &f);
|
||||
*F = Map<RMat3>(f.data());
|
||||
return smaller_singular_value;
|
||||
}
|
||||
|
||||
// HZ 11.1.1 pag.280
|
||||
void EnforceFundamentalRank2Constraint(Mat3 *F) {
|
||||
Eigen::JacobiSVD<Mat3> USV(*F, Eigen::ComputeFullU | Eigen::ComputeFullV);
|
||||
Vec3 d = USV.singularValues();
|
||||
d(2) = 0.0;
|
||||
*F = USV.matrixU() * d.asDiagonal() * USV.matrixV().transpose();
|
||||
}
|
||||
|
||||
// HZ 11.2 pag.281 (x1 = x, x2 = x')
|
||||
double NormalizedEightPointSolver(const Mat &x1,
|
||||
const Mat &x2,
|
||||
Mat3 *F) {
|
||||
DCHECK_EQ(x1.rows(), 2);
|
||||
DCHECK_GE(x1.cols(), 8);
|
||||
DCHECK_EQ(x1.rows(), x2.rows());
|
||||
DCHECK_EQ(x1.cols(), x2.cols());
|
||||
|
||||
// Normalize the data.
|
||||
Mat3 T1, T2;
|
||||
PreconditionerFromPoints(x1, &T1);
|
||||
PreconditionerFromPoints(x2, &T2);
|
||||
Mat x1_normalized, x2_normalized;
|
||||
ApplyTransformationToPoints(x1, T1, &x1_normalized);
|
||||
ApplyTransformationToPoints(x2, T2, &x2_normalized);
|
||||
|
||||
// Estimate the fundamental matrix.
|
||||
double smaller_singular_value =
|
||||
EightPointSolver(x1_normalized, x2_normalized, F);
|
||||
EnforceFundamentalRank2Constraint(F);
|
||||
|
||||
// Denormalize the fundamental matrix.
|
||||
*F = T2.transpose() * (*F) * T1;
|
||||
|
||||
return smaller_singular_value;
|
||||
}
|
||||
|
||||
// Seven-point algorithm.
|
||||
// http://www.cs.unc.edu/~marc/tutorial/node55.html
|
||||
double FundamentalFrom7CorrespondencesLinear(const Mat &x1,
|
||||
const Mat &x2,
|
||||
std::vector<Mat3> *F) {
|
||||
DCHECK_EQ(x1.rows(), 2);
|
||||
DCHECK_EQ(x1.cols(), 7);
|
||||
DCHECK_EQ(x1.rows(), x2.rows());
|
||||
DCHECK_EQ(x2.cols(), x2.cols());
|
||||
|
||||
// Build a 9 x n matrix from point matches, where each row is equivalent to
|
||||
// the equation x'T*F*x = 0 for a single correspondence pair (x', x). The
|
||||
// domain of the matrix is a 9 element vector corresponding to F. The
|
||||
// nullspace should be rank two; the two dimensions correspond to the set of
|
||||
// F matrices satisfying the epipolar geometry.
|
||||
Matrix<double, 7, 9> A;
|
||||
for (int ii = 0; ii < 7; ++ii) {
|
||||
A(ii, 0) = x1(0, ii) * x2(0, ii); // 0 represents x coords,
|
||||
A(ii, 1) = x1(1, ii) * x2(0, ii); // 1 represents y coords.
|
||||
A(ii, 2) = x2(0, ii);
|
||||
A(ii, 3) = x1(0, ii) * x2(1, ii);
|
||||
A(ii, 4) = x1(1, ii) * x2(1, ii);
|
||||
A(ii, 5) = x2(1, ii);
|
||||
A(ii, 6) = x1(0, ii);
|
||||
A(ii, 7) = x1(1, ii);
|
||||
A(ii, 8) = 1.0;
|
||||
}
|
||||
|
||||
// Find the two F matrices in the nullspace of A.
|
||||
Vec9 f1, f2;
|
||||
double s = Nullspace2(&A, &f1, &f2);
|
||||
Mat3 F1 = Map<RMat3>(f1.data());
|
||||
Mat3 F2 = Map<RMat3>(f2.data());
|
||||
|
||||
// Then, use the condition det(F) = 0 to determine F. In other words, solve
|
||||
// det(F1 + a*F2) = 0 for a.
|
||||
double a = F1(0, 0), j = F2(0, 0),
|
||||
b = F1(0, 1), k = F2(0, 1),
|
||||
c = F1(0, 2), l = F2(0, 2),
|
||||
d = F1(1, 0), m = F2(1, 0),
|
||||
e = F1(1, 1), n = F2(1, 1),
|
||||
f = F1(1, 2), o = F2(1, 2),
|
||||
g = F1(2, 0), p = F2(2, 0),
|
||||
h = F1(2, 1), q = F2(2, 1),
|
||||
i = F1(2, 2), r = F2(2, 2);
|
||||
|
||||
// Run fundamental_7point_coeffs.py to get the below coefficients.
|
||||
// The coefficients are in ascending powers of alpha, i.e. P[N]*x^N.
|
||||
double P[4] = {
|
||||
a*e*i + b*f*g + c*d*h - a*f*h - b*d*i - c*e*g,
|
||||
a*e*r + a*i*n + b*f*p + b*g*o + c*d*q + c*h*m + d*h*l + e*i*j + f*g*k -
|
||||
a*f*q - a*h*o - b*d*r - b*i*m - c*e*p - c*g*n - d*i*k - e*g*l - f*h*j,
|
||||
a*n*r + b*o*p + c*m*q + d*l*q + e*j*r + f*k*p + g*k*o + h*l*m + i*j*n -
|
||||
a*o*q - b*m*r - c*n*p - d*k*r - e*l*p - f*j*q - g*l*n - h*j*o - i*k*m,
|
||||
j*n*r + k*o*p + l*m*q - j*o*q - k*m*r - l*n*p,
|
||||
};
|
||||
|
||||
// Solve for the roots of P[3]*x^3 + P[2]*x^2 + P[1]*x + P[0] = 0.
|
||||
double roots[3];
|
||||
int num_roots = SolveCubicPolynomial(P, roots);
|
||||
|
||||
// Build the fundamental matrix for each solution.
|
||||
for (int kk = 0; kk < num_roots; ++kk) {
|
||||
F->push_back(F1 + roots[kk] * F2);
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
double FundamentalFromCorrespondences7Point(const Mat &x1,
|
||||
const Mat &x2,
|
||||
std::vector<Mat3> *F) {
|
||||
DCHECK_EQ(x1.rows(), 2);
|
||||
DCHECK_GE(x1.cols(), 7);
|
||||
DCHECK_EQ(x1.rows(), x2.rows());
|
||||
DCHECK_EQ(x1.cols(), x2.cols());
|
||||
|
||||
// Normalize the data.
|
||||
Mat3 T1, T2;
|
||||
PreconditionerFromPoints(x1, &T1);
|
||||
PreconditionerFromPoints(x2, &T2);
|
||||
Mat x1_normalized, x2_normalized;
|
||||
ApplyTransformationToPoints(x1, T1, &x1_normalized);
|
||||
ApplyTransformationToPoints(x2, T2, &x2_normalized);
|
||||
|
||||
// Estimate the fundamental matrix.
|
||||
double smaller_singular_value =
|
||||
FundamentalFrom7CorrespondencesLinear(x1_normalized, x2_normalized, &(*F));
|
||||
|
||||
for (int k = 0; k < F->size(); ++k) {
|
||||
Mat3 & Fmat = (*F)[k];
|
||||
// Denormalize the fundamental matrix.
|
||||
Fmat = T2.transpose() * Fmat * T1;
|
||||
}
|
||||
return smaller_singular_value;
|
||||
}
|
||||
|
||||
void NormalizeFundamental(const Mat3 &F, Mat3 *F_normalized) {
|
||||
*F_normalized = F / FrobeniusNorm(F);
|
||||
if ((*F_normalized)(2, 2) < 0) {
|
||||
*F_normalized *= -1;
|
||||
}
|
||||
}
|
||||
|
||||
double SampsonDistance(const Mat &F, const Vec2 &x1, const Vec2 &x2) {
|
||||
Vec3 x(x1(0), x1(1), 1.0);
|
||||
Vec3 y(x2(0), x2(1), 1.0);
|
||||
|
||||
Vec3 F_x = F * x;
|
||||
Vec3 Ft_y = F.transpose() * y;
|
||||
double y_F_x = y.dot(F_x);
|
||||
|
||||
return Square(y_F_x) / ( F_x.head<2>().squaredNorm()
|
||||
+ Ft_y.head<2>().squaredNorm());
|
||||
}
|
||||
|
||||
double SymmetricEpipolarDistance(const Mat &F, const Vec2 &x1, const Vec2 &x2) {
|
||||
Vec3 x(x1(0), x1(1), 1.0);
|
||||
Vec3 y(x2(0), x2(1), 1.0);
|
||||
|
||||
Vec3 F_x = F * x;
|
||||
Vec3 Ft_y = F.transpose() * y;
|
||||
double y_F_x = y.dot(F_x);
|
||||
|
||||
return Square(y_F_x) * ( 1 / F_x.head<2>().squaredNorm()
|
||||
+ 1 / Ft_y.head<2>().squaredNorm());
|
||||
}
|
||||
|
||||
// HZ 9.6 pag 257 (formula 9.12)
|
||||
void EssentialFromFundamental(const Mat3 &F,
|
||||
const Mat3 &K1,
|
||||
const Mat3 &K2,
|
||||
Mat3 *E) {
|
||||
*E = K2.transpose() * F * K1;
|
||||
}
|
||||
|
||||
// HZ 9.6 pag 257 (formula 9.12)
|
||||
// Or http://ai.stanford.edu/~birch/projective/node20.html
|
||||
void FundamentalFromEssential(const Mat3 &E,
|
||||
const Mat3 &K1,
|
||||
const Mat3 &K2,
|
||||
Mat3 *F) {
|
||||
*F = K2.inverse().transpose() * E * K1.inverse();
|
||||
}
|
||||
|
||||
void RelativeCameraMotion(const Mat3 &R1,
|
||||
const Vec3 &t1,
|
||||
const Mat3 &R2,
|
||||
const Vec3 &t2,
|
||||
Mat3 *R,
|
||||
Vec3 *t) {
|
||||
*R = R2 * R1.transpose();
|
||||
*t = t2 - (*R) * t1;
|
||||
}
|
||||
|
||||
// HZ 9.6 pag 257
|
||||
void EssentialFromRt(const Mat3 &R1,
|
||||
const Vec3 &t1,
|
||||
const Mat3 &R2,
|
||||
const Vec3 &t2,
|
||||
Mat3 *E) {
|
||||
Mat3 R;
|
||||
Vec3 t;
|
||||
RelativeCameraMotion(R1, t1, R2, t2, &R, &t);
|
||||
Mat3 Tx = CrossProductMatrix(t);
|
||||
*E = Tx * R;
|
||||
}
|
||||
|
||||
// HZ 9.6 pag 259 (Result 9.19)
|
||||
void MotionFromEssential(const Mat3 &E,
|
||||
std::vector<Mat3> *Rs,
|
||||
std::vector<Vec3> *ts) {
|
||||
Eigen::JacobiSVD<Mat3> USV(E, Eigen::ComputeFullU | Eigen::ComputeFullV);
|
||||
Mat3 U = USV.matrixU();
|
||||
Mat3 Vt = USV.matrixV().transpose();
|
||||
|
||||
// Last column of U is undetermined since d = (a a 0).
|
||||
if (U.determinant() < 0) {
|
||||
U.col(2) *= -1;
|
||||
}
|
||||
// Last row of Vt is undetermined since d = (a a 0).
|
||||
if (Vt.determinant() < 0) {
|
||||
Vt.row(2) *= -1;
|
||||
}
|
||||
|
||||
Mat3 W;
|
||||
W << 0, -1, 0,
|
||||
1, 0, 0,
|
||||
0, 0, 1;
|
||||
|
||||
Mat3 U_W_Vt = U * W * Vt;
|
||||
Mat3 U_Wt_Vt = U * W.transpose() * Vt;
|
||||
|
||||
Rs->resize(4);
|
||||
(*Rs)[0] = U_W_Vt;
|
||||
(*Rs)[1] = U_W_Vt;
|
||||
(*Rs)[2] = U_Wt_Vt;
|
||||
(*Rs)[3] = U_Wt_Vt;
|
||||
|
||||
ts->resize(4);
|
||||
(*ts)[0] = U.col(2);
|
||||
(*ts)[1] = -U.col(2);
|
||||
(*ts)[2] = U.col(2);
|
||||
(*ts)[3] = -U.col(2);
|
||||
}
|
||||
|
||||
int MotionFromEssentialChooseSolution(const std::vector<Mat3> &Rs,
|
||||
const std::vector<Vec3> &ts,
|
||||
const Mat3 &K1,
|
||||
const Vec2 &x1,
|
||||
const Mat3 &K2,
|
||||
const Vec2 &x2) {
|
||||
DCHECK_EQ(4, Rs.size());
|
||||
DCHECK_EQ(4, ts.size());
|
||||
|
||||
Mat34 P1, P2;
|
||||
Mat3 R1;
|
||||
Vec3 t1;
|
||||
R1.setIdentity();
|
||||
t1.setZero();
|
||||
P_From_KRt(K1, R1, t1, &P1);
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
const Mat3 &R2 = Rs[i];
|
||||
const Vec3 &t2 = ts[i];
|
||||
P_From_KRt(K2, R2, t2, &P2);
|
||||
Vec3 X;
|
||||
TriangulateDLT(P1, x1, P2, x2, &X);
|
||||
double d1 = Depth(R1, t1, X);
|
||||
double d2 = Depth(R2, t2, X);
|
||||
// Test if point is front to the two cameras.
|
||||
if (d1 > 0 && d2 > 0) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool MotionFromEssentialAndCorrespondence(const Mat3 &E,
|
||||
const Mat3 &K1,
|
||||
const Vec2 &x1,
|
||||
const Mat3 &K2,
|
||||
const Vec2 &x2,
|
||||
Mat3 *R,
|
||||
Vec3 *t) {
|
||||
std::vector<Mat3> Rs;
|
||||
std::vector<Vec3> ts;
|
||||
MotionFromEssential(E, &Rs, &ts);
|
||||
int solution = MotionFromEssentialChooseSolution(Rs, ts, K1, x1, K2, x2);
|
||||
if (solution >= 0) {
|
||||
*R = Rs[solution];
|
||||
*t = ts[solution];
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void FundamentalToEssential(const Mat3 &F, Mat3 *E) {
|
||||
Eigen::JacobiSVD<Mat3> svd(F, Eigen::ComputeFullU | Eigen::ComputeFullV);
|
||||
|
||||
// See Hartley & Zisserman page 294, result 11.1, which shows how to get the
|
||||
// closest essential matrix to a matrix that is "almost" an essential matrix.
|
||||
double a = svd.singularValues()(0);
|
||||
double b = svd.singularValues()(1);
|
||||
double s = (a + b) / 2.0;
|
||||
|
||||
LG << "Initial reconstruction's rotation is non-euclidean by "
|
||||
<< (((a - b) / std::max(a, b)) * 100) << "%; singular values:"
|
||||
<< svd.singularValues().transpose();
|
||||
|
||||
Vec3 diag;
|
||||
diag << s, s, 0;
|
||||
|
||||
*E = svd.matrixU() * diag.asDiagonal() * svd.matrixV().transpose();
|
||||
}
|
||||
|
||||
// Default settings for fundamental estimation which should be suitable
|
||||
// for a wide range of use cases.
|
||||
EstimateFundamentalOptions::EstimateFundamentalOptions(void) :
|
||||
max_num_iterations(50),
|
||||
expected_average_symmetric_distance(1e-16) {
|
||||
}
|
||||
|
||||
namespace {
|
||||
// Cost functor which computes symmetric epipolar distance
|
||||
// used for fundamental matrix refinement.
|
||||
class FundamentalSymmetricEpipolarCostFunctor {
|
||||
public:
|
||||
FundamentalSymmetricEpipolarCostFunctor(const Vec2 &x,
|
||||
const Vec2 &y)
|
||||
: x_(x), y_(y) {}
|
||||
|
||||
template<typename T>
|
||||
bool operator()(const T *fundamental_parameters, T *residuals) const {
|
||||
typedef Eigen::Matrix<T, 3, 3> Mat3;
|
||||
typedef Eigen::Matrix<T, 3, 1> Vec3;
|
||||
|
||||
Mat3 F(fundamental_parameters);
|
||||
|
||||
Vec3 x(T(x_(0)), T(x_(1)), T(1.0));
|
||||
Vec3 y(T(y_(0)), T(y_(1)), T(1.0));
|
||||
|
||||
Vec3 F_x = F * x;
|
||||
Vec3 Ft_y = F.transpose() * y;
|
||||
T y_F_x = y.dot(F_x);
|
||||
|
||||
residuals[0] = y_F_x * T(1) / F_x.head(2).norm();
|
||||
residuals[1] = y_F_x * T(1) / Ft_y.head(2).norm();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
const Mat x_;
|
||||
const Mat y_;
|
||||
};
|
||||
|
||||
#if CERES_FOUND
|
||||
// Termination checking callback used for fundamental estimation.
|
||||
// It finished the minimization as soon as actual average of
|
||||
// symmetric epipolar distance is less or equal to the expected
|
||||
// average value.
|
||||
class TerminationCheckingCallback : public ceres::IterationCallback {
|
||||
public:
|
||||
TerminationCheckingCallback(const Mat &x1, const Mat &x2,
|
||||
const EstimateFundamentalOptions &options,
|
||||
Mat3 *F)
|
||||
: options_(options), x1_(x1), x2_(x2), F_(F) {}
|
||||
|
||||
virtual ceres::CallbackReturnType operator()(
|
||||
const ceres::IterationSummary& summary) {
|
||||
// If the step wasn't successful, there's nothing to do.
|
||||
if (!summary.step_is_successful) {
|
||||
return ceres::SOLVER_CONTINUE;
|
||||
}
|
||||
|
||||
// Calculate average of symmetric epipolar distance.
|
||||
double average_distance = 0.0;
|
||||
for (int i = 0; i < x1_.cols(); i++) {
|
||||
average_distance = SymmetricEpipolarDistance(*F_,
|
||||
x1_.col(i),
|
||||
x2_.col(i));
|
||||
}
|
||||
average_distance /= x1_.cols();
|
||||
|
||||
if (average_distance <= options_.expected_average_symmetric_distance) {
|
||||
return ceres::SOLVER_TERMINATE_SUCCESSFULLY;
|
||||
}
|
||||
|
||||
return ceres::SOLVER_CONTINUE;
|
||||
}
|
||||
|
||||
private:
|
||||
const EstimateFundamentalOptions &options_;
|
||||
const Mat &x1_;
|
||||
const Mat &x2_;
|
||||
Mat3 *F_;
|
||||
};
|
||||
#endif // CERES_FOUND
|
||||
} // namespace
|
||||
|
||||
/* Fundamental transformation estimation. */
|
||||
bool EstimateFundamentalFromCorrespondences(
|
||||
const Mat &x1,
|
||||
const Mat &x2,
|
||||
const EstimateFundamentalOptions &options,
|
||||
Mat3 *F) {
|
||||
// Step 1: Algebraic fundamental estimation.
|
||||
|
||||
// Assume algebraic estiation always succeeds,
|
||||
NormalizedEightPointSolver(x1, x2, F);
|
||||
|
||||
#if CERES_FOUND
|
||||
LG << "Estimated matrix after algebraic estimation:\n" << *F;
|
||||
|
||||
// Step 2: Refine matrix using Ceres minimizer.
|
||||
ceres::Problem problem;
|
||||
for (int i = 0; i < x1.cols(); i++) {
|
||||
FundamentalSymmetricEpipolarCostFunctor
|
||||
*fundamental_symmetric_epipolar_cost_function =
|
||||
new FundamentalSymmetricEpipolarCostFunctor(x1.col(i),
|
||||
x2.col(i));
|
||||
|
||||
problem.AddResidualBlock(
|
||||
new ceres::AutoDiffCostFunction<
|
||||
FundamentalSymmetricEpipolarCostFunctor,
|
||||
2, // num_residuals
|
||||
9>(fundamental_symmetric_epipolar_cost_function),
|
||||
nullptr,
|
||||
F->data());
|
||||
}
|
||||
|
||||
// Configure the solve.
|
||||
ceres::Solver::Options solver_options;
|
||||
solver_options.linear_solver_type = ceres::DENSE_QR;
|
||||
solver_options.max_num_iterations = options.max_num_iterations;
|
||||
solver_options.update_state_every_iteration = true;
|
||||
|
||||
// Terminate if the average symmetric distance is good enough.
|
||||
TerminationCheckingCallback callback(x1, x2, options, F);
|
||||
solver_options.callbacks.push_back(&callback);
|
||||
|
||||
// Run the solve.
|
||||
ceres::Solver::Summary summary;
|
||||
ceres::Solve(solver_options, &problem, &summary);
|
||||
|
||||
VLOG(1) << "Summary:\n" << summary.FullReport();
|
||||
|
||||
LG << "Final refined matrix:\n" << *F;
|
||||
|
||||
return summary.IsSolutionUsable();
|
||||
#endif // CERES_FOUND
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace libmv
|
||||
@@ -0,0 +1,187 @@
|
||||
// Copyright (c) 2007, 2008, 2011 libmv authors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
|
||||
#ifndef LIBMV_MULTIVIEW_FUNDAMENTAL_H_
|
||||
#define LIBMV_MULTIVIEW_FUNDAMENTAL_H_
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "libmv/numeric/numeric.h"
|
||||
|
||||
namespace libmv {
|
||||
|
||||
void ProjectionsFromFundamental(const Mat3 &F, Mat34 *P1, Mat34 *P2);
|
||||
void FundamentalFromProjections(const Mat34 &P1, const Mat34 &P2, Mat3 *F);
|
||||
|
||||
/**
|
||||
* The normalized 8-point fundamental matrix solver.
|
||||
*/
|
||||
double NormalizedEightPointSolver(const Mat &x1,
|
||||
const Mat &x2,
|
||||
Mat3 *F);
|
||||
|
||||
/**
|
||||
* 7 points (minimal case, points coordinates must be normalized before):
|
||||
*/
|
||||
double FundamentalFrom7CorrespondencesLinear(const Mat &x1,
|
||||
const Mat &x2,
|
||||
std::vector<Mat3> *F);
|
||||
|
||||
/**
|
||||
* 7 points (points coordinates must be in image space):
|
||||
*/
|
||||
double FundamentalFromCorrespondences7Point(const Mat &x1,
|
||||
const Mat &x2,
|
||||
std::vector<Mat3> *F);
|
||||
|
||||
/**
|
||||
* 8 points (points coordinates must be in image space):
|
||||
*/
|
||||
double NormalizedEightPointSolver(const Mat &x1,
|
||||
const Mat &x2,
|
||||
Mat3 *F);
|
||||
|
||||
/**
|
||||
* Fundamental matrix utility function:
|
||||
*/
|
||||
void EnforceFundamentalRank2Constraint(Mat3 *F);
|
||||
|
||||
void NormalizeFundamental(const Mat3 &F, Mat3 *F_normalized);
|
||||
|
||||
/**
|
||||
* Approximate squared reprojection errror.
|
||||
*
|
||||
* See page 287 of HZ equation 11.9. This avoids triangulating the point,
|
||||
* relying only on the entries in F.
|
||||
*/
|
||||
double SampsonDistance(const Mat &F, const Vec2 &x1, const Vec2 &x2);
|
||||
|
||||
/**
|
||||
* Calculates the sum of the distances from the points to the epipolar lines.
|
||||
*
|
||||
* See page 288 of HZ equation 11.10.
|
||||
*/
|
||||
double SymmetricEpipolarDistance(const Mat &F, const Vec2 &x1, const Vec2 &x2);
|
||||
|
||||
/**
|
||||
* Compute the relative camera motion between two cameras.
|
||||
*
|
||||
* Given the motion parameters of two cameras, computes the motion parameters
|
||||
* of the second one assuming the first one to be at the origin.
|
||||
* If T1 and T2 are the camera motions, the computed relative motion is
|
||||
* T = T2 T1^{-1}
|
||||
*/
|
||||
void RelativeCameraMotion(const Mat3 &R1,
|
||||
const Vec3 &t1,
|
||||
const Mat3 &R2,
|
||||
const Vec3 &t2,
|
||||
Mat3 *R,
|
||||
Vec3 *t);
|
||||
|
||||
void EssentialFromFundamental(const Mat3 &F,
|
||||
const Mat3 &K1,
|
||||
const Mat3 &K2,
|
||||
Mat3 *E);
|
||||
|
||||
void FundamentalFromEssential(const Mat3 &E,
|
||||
const Mat3 &K1,
|
||||
const Mat3 &K2,
|
||||
Mat3 *F);
|
||||
|
||||
void EssentialFromRt(const Mat3 &R1,
|
||||
const Vec3 &t1,
|
||||
const Mat3 &R2,
|
||||
const Vec3 &t2,
|
||||
Mat3 *E);
|
||||
|
||||
void MotionFromEssential(const Mat3 &E,
|
||||
std::vector<Mat3> *Rs,
|
||||
std::vector<Vec3> *ts);
|
||||
|
||||
/**
|
||||
* Choose one of the four possible motion solutions from an essential matrix.
|
||||
*
|
||||
* Decides the right solution by checking that the triangulation of a match
|
||||
* x1--x2 lies in front of the cameras. See HZ 9.6 pag 259 (9.6.3 Geometrical
|
||||
* interpretation of the 4 solutions)
|
||||
*
|
||||
* \return index of the right solution or -1 if no solution.
|
||||
*/
|
||||
int MotionFromEssentialChooseSolution(const std::vector<Mat3> &Rs,
|
||||
const std::vector<Vec3> &ts,
|
||||
const Mat3 &K1,
|
||||
const Vec2 &x1,
|
||||
const Mat3 &K2,
|
||||
const Vec2 &x2);
|
||||
|
||||
bool MotionFromEssentialAndCorrespondence(const Mat3 &E,
|
||||
const Mat3 &K1,
|
||||
const Vec2 &x1,
|
||||
const Mat3 &K2,
|
||||
const Vec2 &x2,
|
||||
Mat3 *R,
|
||||
Vec3 *t);
|
||||
|
||||
/**
|
||||
* Find closest essential matrix E to fundamental F
|
||||
*/
|
||||
void FundamentalToEssential(const Mat3 &F, Mat3 *E);
|
||||
|
||||
/**
|
||||
* This structure contains options that controls how the fundamental
|
||||
* estimation operates.
|
||||
*
|
||||
* Defaults should be suitable for a wide range of use cases, but
|
||||
* better performance and accuracy might require tweaking/
|
||||
*/
|
||||
struct EstimateFundamentalOptions {
|
||||
// Default constructor which sets up a options for generic usage.
|
||||
EstimateFundamentalOptions(void);
|
||||
|
||||
// Maximal number of iterations for refinement step.
|
||||
int max_num_iterations;
|
||||
|
||||
// Expected average of symmetric epipolar distance between
|
||||
// actual destination points and original ones transformed by
|
||||
// estimated fundamental matrix.
|
||||
//
|
||||
// Refinement will finish as soon as average of symmetric
|
||||
// epipolar distance is less or equal to this value.
|
||||
//
|
||||
// This distance is measured in the same units as input points are.
|
||||
double expected_average_symmetric_distance;
|
||||
};
|
||||
|
||||
/**
|
||||
* Fundamental transformation estimation.
|
||||
*
|
||||
* This function estimates the fundamental transformation from a list of 2D
|
||||
* correspondences by doing algebraic estimation first followed with result
|
||||
* refinement.
|
||||
*/
|
||||
bool EstimateFundamentalFromCorrespondences(
|
||||
const Mat &x1,
|
||||
const Mat &x2,
|
||||
const EstimateFundamentalOptions &options,
|
||||
Mat3 *F);
|
||||
|
||||
} // namespace libmv
|
||||
|
||||
#endif // LIBMV_MULTIVIEW_FUNDAMENTAL_H_
|
||||
@@ -0,0 +1,110 @@
|
||||
// Copyright (c) 2009 libmv authors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
|
||||
#include <cstdio>
|
||||
|
||||
// TODO(keir): This code is plain unfinished! Doesn't even compile!
|
||||
|
||||
#include "libmv/base/vector.h"
|
||||
#include "libmv/multiview/fundamental_kernel.h"
|
||||
#include "libmv/numeric/numeric.h"
|
||||
#include "libmv/numeric/poly.h"
|
||||
#include "libmv/logging/logging.h"
|
||||
|
||||
namespace libmv {
|
||||
namespace fundamental {
|
||||
namespace kernel {
|
||||
|
||||
void SevenPointSolver::Solve(const Mat &x1, const Mat &x2, vector<Mat3> *F) {
|
||||
assert(2 == x1.rows());
|
||||
assert(7 <= x1.cols());
|
||||
assert(x1.rows() == x2.rows());
|
||||
assert(x1.cols() == x2.cols());
|
||||
|
||||
// Set up the homogeneous system Af = 0 from the equations x'T*F*x = 0.
|
||||
MatX9 A(x1.cols(), 9);
|
||||
EncodeEpipolarEquation(x1, x2, &A);
|
||||
|
||||
// Find the two F matrices in the nullspace of A.
|
||||
Vec9 f1, f2;
|
||||
Nullspace2(&A, &f1, &f2);
|
||||
Mat3 F1 = Map<RMat3>(f1.data());
|
||||
Mat3 F2 = Map<RMat3>(f2.data());
|
||||
|
||||
// Then, use the condition det(F) = 0 to determine F. In other words, solve
|
||||
// det(F1 + a*F2) = 0 for a.
|
||||
double a = F1(0, 0), j = F2(0, 0),
|
||||
b = F1(0, 1), k = F2(0, 1),
|
||||
c = F1(0, 2), l = F2(0, 2),
|
||||
d = F1(1, 0), m = F2(1, 0),
|
||||
e = F1(1, 1), n = F2(1, 1),
|
||||
f = F1(1, 2), o = F2(1, 2),
|
||||
g = F1(2, 0), p = F2(2, 0),
|
||||
h = F1(2, 1), q = F2(2, 1),
|
||||
i = F1(2, 2), r = F2(2, 2);
|
||||
|
||||
// Run fundamental_7point_coeffs.py to get the below coefficients.
|
||||
// The coefficients are in ascending powers of alpha, i.e. P[N]*x^N.
|
||||
double P[4] = {
|
||||
a*e*i + b*f*g + c*d*h - a*f*h - b*d*i - c*e*g,
|
||||
a*e*r + a*i*n + b*f*p + b*g*o + c*d*q + c*h*m + d*h*l + e*i*j + f*g*k -
|
||||
a*f*q - a*h*o - b*d*r - b*i*m - c*e*p - c*g*n - d*i*k - e*g*l - f*h*j,
|
||||
a*n*r + b*o*p + c*m*q + d*l*q + e*j*r + f*k*p + g*k*o + h*l*m + i*j*n -
|
||||
a*o*q - b*m*r - c*n*p - d*k*r - e*l*p - f*j*q - g*l*n - h*j*o - i*k*m,
|
||||
j*n*r + k*o*p + l*m*q - j*o*q - k*m*r - l*n*p,
|
||||
};
|
||||
|
||||
// Solve for the roots of P[3]*x^3 + P[2]*x^2 + P[1]*x + P[0] = 0.
|
||||
double roots[3];
|
||||
int num_roots = SolveCubicPolynomial(P, roots);
|
||||
|
||||
// Build the fundamental matrix for each solution.
|
||||
for (int kk = 0; kk < num_roots; ++kk) {
|
||||
F->push_back(F1 + roots[kk] * F2);
|
||||
}
|
||||
}
|
||||
|
||||
//template<bool force_essential_constraint>
|
||||
void EightPointSolver::Solve(const Mat &x1, const Mat &x2, vector<Mat3> *Fs) {
|
||||
assert(2 == x1.rows());
|
||||
assert(8 <= x1.cols());
|
||||
assert(x1.rows() == x2.rows());
|
||||
assert(x1.cols() == x2.cols());
|
||||
|
||||
MatX9 A(x1.cols(), 9);
|
||||
EncodeEpipolarEquation(x1, x2, &A);
|
||||
|
||||
Vec9 f;
|
||||
Nullspace(&A, &f);
|
||||
Mat3 F = Map<RMat3>(f.data());
|
||||
|
||||
// Force the fundamental property if the A matrix has full rank.
|
||||
if (x1.cols() > 8) {
|
||||
Eigen::JacobiSVD<Mat3> USV(F, Eigen::ComputeFullU | Eigen::ComputeFullV);
|
||||
Vec3 d = USV.singularValues();
|
||||
d[2] = 0.0;
|
||||
F = USV.matrixU() * d.asDiagonal() * USV.matrixV().transpose();
|
||||
}
|
||||
Fs->push_back(F);
|
||||
}
|
||||
|
||||
} // namespace kernel
|
||||
} // namespace fundamental
|
||||
} // namespace libmv
|
||||
@@ -0,0 +1,148 @@
|
||||
// Copyright (c) 2009 libmv authors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
|
||||
// TODO(keir): This code is plain unfinished! Doesn't even compile!
|
||||
|
||||
#ifndef LIBMV_MULTIVIEW_FUNDAMENTAL_KERNEL_H_
|
||||
#define LIBMV_MULTIVIEW_FUNDAMENTAL_KERNEL_H_
|
||||
|
||||
#include "libmv/base/vector.h"
|
||||
#include "libmv/multiview/conditioning.h"
|
||||
#include "libmv/multiview/two_view_kernel.h"
|
||||
#include "libmv/numeric/numeric.h"
|
||||
#include "libmv/logging/logging.h"
|
||||
|
||||
namespace libmv {
|
||||
namespace fundamental {
|
||||
namespace kernel {
|
||||
|
||||
// TODO(keir): Templatize error functions to work with autodiff (only F).
|
||||
struct SampsonError {
|
||||
static double Error(const Mat3 &F, const Vec2 &x1, const Vec2 &x2) {
|
||||
Vec3 x(x1(0), x1(1), 1.0);
|
||||
Vec3 y(x2(0), x2(1), 1.0);
|
||||
// See page 287 equation (11.9) of HZ.
|
||||
Vec3 F_x = F * x;
|
||||
Vec3 Ft_y = F.transpose() * y;
|
||||
return Square(y.dot(F_x)) / ( F_x.head<2>().squaredNorm()
|
||||
+ Ft_y.head<2>().squaredNorm());
|
||||
}
|
||||
};
|
||||
|
||||
struct SymmetricEpipolarDistanceError {
|
||||
static double Error(const Mat3 &F, const Vec2 &x1, const Vec2 &x2) {
|
||||
Vec3 x(x1(0), x1(1), 1.0);
|
||||
Vec3 y(x2(0), x2(1), 1.0);
|
||||
// See page 288 equation (11.10) of HZ.
|
||||
Vec3 F_x = F * x;
|
||||
Vec3 Ft_y = F.transpose() * y;
|
||||
return Square(y.dot(F_x)) * ( 1 / F_x.head<2>().squaredNorm()
|
||||
+ 1 / Ft_y.head<2>().squaredNorm())
|
||||
/ 4.0; // The divide by 4 is to make this match the sampson distance.
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Seven-point algorithm for solving for the fundamental matrix from point
|
||||
* correspondences. See page 281 in HZ, though oddly they use a different
|
||||
* equation: \f$det(\alpha F_1 + (1-\alpha)F_2) = 0\f$. Since \f$F_1\f$ and
|
||||
* \f$F2\f$ are projective, there's no need to balance the relative scale.
|
||||
* Instead, here, the simpler equation is solved: \f$det(F_1 + \alpha F_2) =
|
||||
* 0\f$.
|
||||
*
|
||||
* \see http://www.cs.unc.edu/~marc/tutorial/node55.html
|
||||
*/
|
||||
struct SevenPointSolver {
|
||||
enum { MINIMUM_SAMPLES = 7 };
|
||||
static void Solve(const Mat &x1, const Mat &x2, vector<Mat3> *F);
|
||||
};
|
||||
|
||||
struct EightPointSolver {
|
||||
enum { MINIMUM_SAMPLES = 8 };
|
||||
static void Solve(const Mat &x1, const Mat &x2, vector<Mat3> *Fs);
|
||||
};
|
||||
|
||||
typedef two_view::kernel::Kernel<SevenPointSolver, SampsonError, Mat3>
|
||||
SevenPointKernel;
|
||||
|
||||
typedef two_view::kernel::Kernel<EightPointSolver, SampsonError, Mat3>
|
||||
EightPointKernel;
|
||||
|
||||
typedef two_view::kernel::Kernel<
|
||||
two_view::kernel::NormalizedSolver<SevenPointSolver, UnnormalizerT>,
|
||||
SampsonError,
|
||||
Mat3>
|
||||
NormalizedSevenPointKernel;
|
||||
|
||||
typedef two_view::kernel::Kernel<
|
||||
two_view::kernel::NormalizedSolver<EightPointSolver, UnnormalizerT>,
|
||||
SampsonError,
|
||||
Mat3>
|
||||
NormalizedEightPointKernel;
|
||||
|
||||
// Set the default kernel to normalized 7 point, because it is the fastest (in
|
||||
// a robust estimation context) and most robust of the above kernels.
|
||||
typedef NormalizedSevenPointKernel Kernel;
|
||||
|
||||
// TODO(keir): Convert this to a solver that enforces the essential
|
||||
// constraints; in particular det(F) = 0 and the two nonzero singular values
|
||||
// are equal.
|
||||
typedef two_view::kernel::Kernel<EightPointSolver,
|
||||
SampsonError,
|
||||
Mat3>
|
||||
EssentialKernel;
|
||||
|
||||
/**
|
||||
* Build a 9 x n matrix from point matches, where each row is equivalent to the
|
||||
* equation x'T*F*x = 0 for a single correspondence pair (x', x). The domain of
|
||||
* the matrix is a 9 element vector corresponding to F. In other words, set up
|
||||
* the linear system
|
||||
*
|
||||
* Af = 0,
|
||||
*
|
||||
* where f is the F matrix as a 9-vector rather than a 3x3 matrix (row
|
||||
* major). If the points are well conditioned and there are 8 or more, then
|
||||
* the nullspace should be rank one. If the nullspace is two dimensional,
|
||||
* then the rank 2 constraint must be enforced to identify the appropriate F
|
||||
* matrix.
|
||||
*
|
||||
* Note that this does not resize the matrix A; it is expected to have the
|
||||
* appropriate size already.
|
||||
*/
|
||||
template<typename TMatX, typename TMatA>
|
||||
inline void EncodeEpipolarEquation(const TMatX &x1, const TMatX &x2, TMatA *A) {
|
||||
for (int i = 0; i < x1.cols(); ++i) {
|
||||
(*A)(i, 0) = x2(0, i) * x1(0, i); // 0 represents x coords,
|
||||
(*A)(i, 1) = x2(0, i) * x1(1, i); // 1 represents y coords.
|
||||
(*A)(i, 2) = x2(0, i);
|
||||
(*A)(i, 3) = x2(1, i) * x1(0, i);
|
||||
(*A)(i, 4) = x2(1, i) * x1(1, i);
|
||||
(*A)(i, 5) = x2(1, i);
|
||||
(*A)(i, 6) = x1(0, i);
|
||||
(*A)(i, 7) = x1(1, i);
|
||||
(*A)(i, 8) = 1.0;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace kernel
|
||||
} // namespace fundamental
|
||||
} // namespace libmv
|
||||
|
||||
#endif // LIBMV_MULTIVIEW_FUNDAMENTAL_KERNEL_H_
|
||||
@@ -0,0 +1,477 @@
|
||||
// Copyright (c) 2008, 2009 libmv authors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
|
||||
#include "libmv/multiview/homography.h"
|
||||
|
||||
#if CERES_FOUND
|
||||
#include "ceres/ceres.h"
|
||||
#endif
|
||||
#include "libmv/logging/logging.h"
|
||||
#include "libmv/multiview/conditioning.h"
|
||||
#include "libmv/multiview/homography_parameterization.h"
|
||||
|
||||
namespace libmv {
|
||||
/** 2D Homography transformation estimation in the case that points are in
|
||||
* euclidean coordinates.
|
||||
*
|
||||
* x = H y
|
||||
* x and y vector must have the same direction, we could write
|
||||
* crossproduct(|x|, * H * |y| ) = |0|
|
||||
*
|
||||
* | 0 -1 x2| |a b c| |y1| |0|
|
||||
* | 1 0 -x1| * |d e f| * |y2| = |0|
|
||||
* |-x2 x1 0| |g h 1| |1 | |0|
|
||||
*
|
||||
* That gives :
|
||||
*
|
||||
* (-d+x2*g)*y1 + (-e+x2*h)*y2 + -f+x2 |0|
|
||||
* (a-x1*g)*y1 + (b-x1*h)*y2 + c-x1 = |0|
|
||||
* (-x2*a+x1*d)*y1 + (-x2*b+x1*e)*y2 + -x2*c+x1*f |0|
|
||||
*/
|
||||
static bool Homography2DFromCorrespondencesLinearEuc(
|
||||
const Mat &x1,
|
||||
const Mat &x2,
|
||||
Mat3 *H,
|
||||
double expected_precision) {
|
||||
assert(2 == x1.rows());
|
||||
assert(4 <= x1.cols());
|
||||
assert(x1.rows() == x2.rows());
|
||||
assert(x1.cols() == x2.cols());
|
||||
|
||||
int n = x1.cols();
|
||||
MatX8 L = Mat::Zero(n * 3, 8);
|
||||
Mat b = Mat::Zero(n * 3, 1);
|
||||
for (int i = 0; i < n; ++i) {
|
||||
int j = 3 * i;
|
||||
L(j, 0) = x1(0, i); // a
|
||||
L(j, 1) = x1(1, i); // b
|
||||
L(j, 2) = 1.0; // c
|
||||
L(j, 6) = -x2(0, i) * x1(0, i); // g
|
||||
L(j, 7) = -x2(0, i) * x1(1, i); // h
|
||||
b(j, 0) = x2(0, i); // i
|
||||
|
||||
++j;
|
||||
L(j, 3) = x1(0, i); // d
|
||||
L(j, 4) = x1(1, i); // e
|
||||
L(j, 5) = 1.0; // f
|
||||
L(j, 6) = -x2(1, i) * x1(0, i); // g
|
||||
L(j, 7) = -x2(1, i) * x1(1, i); // h
|
||||
b(j, 0) = x2(1, i); // i
|
||||
|
||||
// This ensures better stability
|
||||
// TODO(julien) make a lite version without this 3rd set
|
||||
++j;
|
||||
L(j, 0) = x2(1, i) * x1(0, i); // a
|
||||
L(j, 1) = x2(1, i) * x1(1, i); // b
|
||||
L(j, 2) = x2(1, i); // c
|
||||
L(j, 3) = -x2(0, i) * x1(0, i); // d
|
||||
L(j, 4) = -x2(0, i) * x1(1, i); // e
|
||||
L(j, 5) = -x2(0, i); // f
|
||||
}
|
||||
// Solve Lx=B
|
||||
Vec h = L.fullPivLu().solve(b);
|
||||
Homography2DNormalizedParameterization<double>::To(h, H);
|
||||
if ((L * h).isApprox(b, expected_precision)) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/** 2D Homography transformation estimation in the case that points are in
|
||||
* homogeneous coordinates.
|
||||
*
|
||||
* | 0 -x3 x2| |a b c| |y1| -x3*d+x2*g -x3*e+x2*h -x3*f+x2*1 |y1| (-x3*d+x2*g)*y1 (-x3*e+x2*h)*y2 (-x3*f+x2*1)*y3 |0|
|
||||
* | x3 0 -x1| * |d e f| * |y2| = x3*a-x1*g x3*b-x1*h x3*c-x1*1 * |y2| = (x3*a-x1*g)*y1 (x3*b-x1*h)*y2 (x3*c-x1*1)*y3 = |0|
|
||||
* |-x2 x1 0| |g h 1| |y3| -x2*a+x1*d -x2*b+x1*e -x2*c+x1*f |y3| (-x2*a+x1*d)*y1 (-x2*b+x1*e)*y2 (-x2*c+x1*f)*y3 |0|
|
||||
* X = |a b c d e f g h|^t
|
||||
*/
|
||||
bool Homography2DFromCorrespondencesLinear(const Mat &x1,
|
||||
const Mat &x2,
|
||||
Mat3 *H,
|
||||
double expected_precision) {
|
||||
if (x1.rows() == 2) {
|
||||
return Homography2DFromCorrespondencesLinearEuc(x1, x2, H,
|
||||
expected_precision);
|
||||
}
|
||||
assert(3 == x1.rows());
|
||||
assert(4 <= x1.cols());
|
||||
assert(x1.rows() == x2.rows());
|
||||
assert(x1.cols() == x2.cols());
|
||||
|
||||
const int x = 0;
|
||||
const int y = 1;
|
||||
const int w = 2;
|
||||
int n = x1.cols();
|
||||
MatX8 L = Mat::Zero(n * 3, 8);
|
||||
Mat b = Mat::Zero(n * 3, 1);
|
||||
for (int i = 0; i < n; ++i) {
|
||||
int j = 3 * i;
|
||||
L(j, 0) = x2(w, i) * x1(x, i); // a
|
||||
L(j, 1) = x2(w, i) * x1(y, i); // b
|
||||
L(j, 2) = x2(w, i) * x1(w, i); // c
|
||||
L(j, 6) = -x2(x, i) * x1(x, i); // g
|
||||
L(j, 7) = -x2(x, i) * x1(y, i); // h
|
||||
b(j, 0) = x2(x, i) * x1(w, i);
|
||||
|
||||
++j;
|
||||
L(j, 3) = x2(w, i) * x1(x, i); // d
|
||||
L(j, 4) = x2(w, i) * x1(y, i); // e
|
||||
L(j, 5) = x2(w, i) * x1(w, i); // f
|
||||
L(j, 6) = -x2(y, i) * x1(x, i); // g
|
||||
L(j, 7) = -x2(y, i) * x1(y, i); // h
|
||||
b(j, 0) = x2(y, i) * x1(w, i);
|
||||
|
||||
// This ensures better stability
|
||||
++j;
|
||||
L(j, 0) = x2(y, i) * x1(x, i); // a
|
||||
L(j, 1) = x2(y, i) * x1(y, i); // b
|
||||
L(j, 2) = x2(y, i) * x1(w, i); // c
|
||||
L(j, 3) = -x2(x, i) * x1(x, i); // d
|
||||
L(j, 4) = -x2(x, i) * x1(y, i); // e
|
||||
L(j, 5) = -x2(x, i) * x1(w, i); // f
|
||||
}
|
||||
// Solve Lx=B
|
||||
Vec h = L.fullPivLu().solve(b);
|
||||
if ((L * h).isApprox(b, expected_precision)) {
|
||||
Homography2DNormalizedParameterization<double>::To(h, H);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Default settings for homography estimation which should be suitable
|
||||
// for a wide range of use cases.
|
||||
EstimateHomographyOptions::EstimateHomographyOptions(void) :
|
||||
use_normalization(true),
|
||||
max_num_iterations(50),
|
||||
expected_average_symmetric_distance(1e-16) {
|
||||
}
|
||||
|
||||
namespace {
|
||||
void GetNormalizedPoints(const Mat &original_points,
|
||||
Mat *normalized_points,
|
||||
Mat3 *normalization_matrix) {
|
||||
IsotropicPreconditionerFromPoints(original_points, normalization_matrix);
|
||||
ApplyTransformationToPoints(original_points,
|
||||
*normalization_matrix,
|
||||
normalized_points);
|
||||
}
|
||||
|
||||
// Cost functor which computes symmetric geometric distance
|
||||
// used for homography matrix refinement.
|
||||
class HomographySymmetricGeometricCostFunctor {
|
||||
public:
|
||||
HomographySymmetricGeometricCostFunctor(const Vec2 &x,
|
||||
const Vec2 &y) {
|
||||
xx_ = x(0);
|
||||
xy_ = x(1);
|
||||
yx_ = y(0);
|
||||
yy_ = y(1);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool operator()(const T *homography_parameters, T *residuals) const {
|
||||
typedef Eigen::Matrix<T, 3, 3> Mat3;
|
||||
typedef Eigen::Matrix<T, 3, 1> Vec3;
|
||||
|
||||
Mat3 H(homography_parameters);
|
||||
|
||||
Vec3 x(T(xx_), T(xy_), T(1.0));
|
||||
Vec3 y(T(yx_), T(yy_), T(1.0));
|
||||
|
||||
Vec3 H_x = H * x;
|
||||
Vec3 Hinv_y = H.inverse() * y;
|
||||
|
||||
H_x /= H_x(2);
|
||||
Hinv_y /= Hinv_y(2);
|
||||
|
||||
// This is a forward error.
|
||||
residuals[0] = H_x(0) - T(yx_);
|
||||
residuals[1] = H_x(1) - T(yy_);
|
||||
|
||||
// This is a backward error.
|
||||
residuals[2] = Hinv_y(0) - T(xx_);
|
||||
residuals[3] = Hinv_y(1) - T(xy_);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// TODO(sergey): Think of better naming.
|
||||
double xx_, xy_;
|
||||
double yx_, yy_;
|
||||
};
|
||||
|
||||
#if CERES_FOUND
|
||||
// Termination checking callback used for homography estimation.
|
||||
// It finished the minimization as soon as actual average of
|
||||
// symmetric geometric distance is less or equal to the expected
|
||||
// average value.
|
||||
class TerminationCheckingCallback : public ceres::IterationCallback {
|
||||
public:
|
||||
TerminationCheckingCallback(const Mat &x1, const Mat &x2,
|
||||
const EstimateHomographyOptions &options,
|
||||
Mat3 *H)
|
||||
: options_(options), x1_(x1), x2_(x2), H_(H) {}
|
||||
|
||||
virtual ceres::CallbackReturnType operator()(
|
||||
const ceres::IterationSummary& summary) {
|
||||
// If the step wasn't successful, there's nothing to do.
|
||||
if (!summary.step_is_successful) {
|
||||
return ceres::SOLVER_CONTINUE;
|
||||
}
|
||||
|
||||
// Calculate average of symmetric geometric distance.
|
||||
double average_distance = 0.0;
|
||||
for (int i = 0; i < x1_.cols(); i++) {
|
||||
average_distance = SymmetricGeometricDistance(*H_,
|
||||
x1_.col(i),
|
||||
x2_.col(i));
|
||||
}
|
||||
average_distance /= x1_.cols();
|
||||
|
||||
if (average_distance <= options_.expected_average_symmetric_distance) {
|
||||
return ceres::SOLVER_TERMINATE_SUCCESSFULLY;
|
||||
}
|
||||
|
||||
return ceres::SOLVER_CONTINUE;
|
||||
}
|
||||
|
||||
private:
|
||||
const EstimateHomographyOptions &options_;
|
||||
const Mat &x1_;
|
||||
const Mat &x2_;
|
||||
Mat3 *H_;
|
||||
};
|
||||
#endif // CERES_FOUND
|
||||
} // namespace
|
||||
|
||||
/** 2D Homography transformation estimation in the case that points are in
|
||||
* euclidean coordinates.
|
||||
*/
|
||||
bool EstimateHomography2DFromCorrespondences(
|
||||
const Mat &x1,
|
||||
const Mat &x2,
|
||||
const EstimateHomographyOptions &options,
|
||||
Mat3 *H) {
|
||||
// TODO(sergey): Support homogenous coordinates, not just euclidean.
|
||||
|
||||
assert(2 == x1.rows());
|
||||
assert(4 <= x1.cols());
|
||||
assert(x1.rows() == x2.rows());
|
||||
assert(x1.cols() == x2.cols());
|
||||
|
||||
Mat3 T1 = Mat3::Identity(),
|
||||
T2 = Mat3::Identity();
|
||||
|
||||
// Step 1: Algebraic homography estimation.
|
||||
Mat x1_normalized, x2_normalized;
|
||||
|
||||
if (options.use_normalization) {
|
||||
LG << "Estimating homography using normalization.";
|
||||
GetNormalizedPoints(x1, &x1_normalized, &T1);
|
||||
GetNormalizedPoints(x2, &x2_normalized, &T2);
|
||||
} else {
|
||||
x1_normalized = x1;
|
||||
x2_normalized = x2;
|
||||
}
|
||||
|
||||
// Assume algebraic estiation always succeeds,
|
||||
Homography2DFromCorrespondencesLinear(x1_normalized, x2_normalized, H);
|
||||
|
||||
// Denormalize the homography matrix.
|
||||
if (options.use_normalization) {
|
||||
*H = T2.inverse() * (*H) * T1;
|
||||
}
|
||||
|
||||
LG << "Estimated matrix after algebraic estimation:\n" << *H;
|
||||
|
||||
#if CERES_FOUND
|
||||
// Step 2: Refine matrix using Ceres minimizer.
|
||||
ceres::Problem problem;
|
||||
for (int i = 0; i < x1.cols(); i++) {
|
||||
HomographySymmetricGeometricCostFunctor
|
||||
*homography_symmetric_geometric_cost_function =
|
||||
new HomographySymmetricGeometricCostFunctor(x1.col(i),
|
||||
x2.col(i));
|
||||
|
||||
problem.AddResidualBlock(
|
||||
new ceres::AutoDiffCostFunction<
|
||||
HomographySymmetricGeometricCostFunctor,
|
||||
4, // num_residuals
|
||||
9>(homography_symmetric_geometric_cost_function),
|
||||
nullptr,
|
||||
H->data());
|
||||
}
|
||||
|
||||
// Configure the solve.
|
||||
ceres::Solver::Options solver_options;
|
||||
solver_options.linear_solver_type = ceres::DENSE_QR;
|
||||
solver_options.max_num_iterations = options.max_num_iterations;
|
||||
solver_options.update_state_every_iteration = true;
|
||||
|
||||
// Terminate if the average symmetric distance is good enough.
|
||||
TerminationCheckingCallback callback(x1, x2, options, H);
|
||||
solver_options.callbacks.push_back(&callback);
|
||||
|
||||
// Run the solve.
|
||||
ceres::Solver::Summary summary;
|
||||
ceres::Solve(solver_options, &problem, &summary);
|
||||
|
||||
VLOG(1) << "Summary:\n" << summary.FullReport();
|
||||
|
||||
LG << "Final refined matrix:\n" << *H;
|
||||
|
||||
return summary.IsSolutionUsable();
|
||||
#endif // CERES_FOUND
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* x2 ~ A * x1
|
||||
* x2^t * Hi * A *x1 = 0
|
||||
* H1 = H2 = H3 =
|
||||
* | 0 0 0 1| |-x2w| |0 0 0 0| | 0 | | 0 0 1 0| |-x2z|
|
||||
* | 0 0 0 0| -> | 0 | |0 0 1 0| -> |-x2z| | 0 0 0 0| -> | 0 |
|
||||
* | 0 0 0 0| | 0 | |0-1 0 0| | x2y| |-1 0 0 0| | x2x|
|
||||
* |-1 0 0 0| | x2x| |0 0 0 0| | 0 | | 0 0 0 0| | 0 |
|
||||
* H4 = H5 = H6 =
|
||||
* |0 0 0 0| | 0 | | 0 1 0 0| |-x2y| |0 0 0 0| | 0 |
|
||||
* |0 0 0 1| -> |-x2w| |-1 0 0 0| -> | x2x| |0 0 0 0| -> | 0 |
|
||||
* |0 0 0 0| | 0 | | 0 0 0 0| | 0 | |0 0 0 1| |-x2w|
|
||||
* |0-1 0 0| | x2y| | 0 0 0 0| | 0 | |0 0-1 0| | x2z|
|
||||
* |a b c d|
|
||||
* A = |e f g h|
|
||||
* |i j k l|
|
||||
* |m n o 1|
|
||||
*
|
||||
* x2^t * H1 * A *x1 = (-x2w*a +x2x*m )*x1x + (-x2w*b +x2x*n )*x1y + (-x2w*c +x2x*o )*x1z + (-x2w*d +x2x*1 )*x1w = 0
|
||||
* x2^t * H2 * A *x1 = (-x2z*e +x2y*i )*x1x + (-x2z*f +x2y*j )*x1y + (-x2z*g +x2y*k )*x1z + (-x2z*h +x2y*l )*x1w = 0
|
||||
* x2^t * H3 * A *x1 = (-x2z*a +x2x*i )*x1x + (-x2z*b +x2x*j )*x1y + (-x2z*c +x2x*k )*x1z + (-x2z*d +x2x*l )*x1w = 0
|
||||
* x2^t * H4 * A *x1 = (-x2w*e +x2y*m )*x1x + (-x2w*f +x2y*n )*x1y + (-x2w*g +x2y*o )*x1z + (-x2w*h +x2y*1 )*x1w = 0
|
||||
* x2^t * H5 * A *x1 = (-x2y*a +x2x*e )*x1x + (-x2y*b +x2x*f )*x1y + (-x2y*c +x2x*g )*x1z + (-x2y*d +x2x*h )*x1w = 0
|
||||
* x2^t * H6 * A *x1 = (-x2w*i +x2z*m )*x1x + (-x2w*j +x2z*n )*x1y + (-x2w*k +x2z*o )*x1z + (-x2w*l +x2z*1 )*x1w = 0
|
||||
*
|
||||
* X = |a b c d e f g h i j k l m n o|^t
|
||||
*/
|
||||
bool Homography3DFromCorrespondencesLinear(const Mat &x1,
|
||||
const Mat &x2,
|
||||
Mat4 *H,
|
||||
double expected_precision) {
|
||||
assert(4 == x1.rows());
|
||||
assert(5 <= x1.cols());
|
||||
assert(x1.rows() == x2.rows());
|
||||
assert(x1.cols() == x2.cols());
|
||||
const int x = 0;
|
||||
const int y = 1;
|
||||
const int z = 2;
|
||||
const int w = 3;
|
||||
int n = x1.cols();
|
||||
MatX15 L = Mat::Zero(n * 6, 15);
|
||||
Mat b = Mat::Zero(n * 6, 1);
|
||||
for (int i = 0; i < n; ++i) {
|
||||
int j = 6 * i;
|
||||
L(j, 0) = -x2(w, i) * x1(x, i); // a
|
||||
L(j, 1) = -x2(w, i) * x1(y, i); // b
|
||||
L(j, 2) = -x2(w, i) * x1(z, i); // c
|
||||
L(j, 3) = -x2(w, i) * x1(w, i); // d
|
||||
L(j, 12) = x2(x, i) * x1(x, i); // m
|
||||
L(j, 13) = x2(x, i) * x1(y, i); // n
|
||||
L(j, 14) = x2(x, i) * x1(z, i); // o
|
||||
b(j, 0) = -x2(x, i) * x1(w, i);
|
||||
|
||||
++j;
|
||||
L(j, 4) = -x2(z, i) * x1(x, i); // e
|
||||
L(j, 5) = -x2(z, i) * x1(y, i); // f
|
||||
L(j, 6) = -x2(z, i) * x1(z, i); // g
|
||||
L(j, 7) = -x2(z, i) * x1(w, i); // h
|
||||
L(j, 8) = x2(y, i) * x1(x, i); // i
|
||||
L(j, 9) = x2(y, i) * x1(y, i); // j
|
||||
L(j, 10) = x2(y, i) * x1(z, i); // k
|
||||
L(j, 11) = x2(y, i) * x1(w, i); // l
|
||||
|
||||
++j;
|
||||
L(j, 0) = -x2(z, i) * x1(x, i); // a
|
||||
L(j, 1) = -x2(z, i) * x1(y, i); // b
|
||||
L(j, 2) = -x2(z, i) * x1(z, i); // c
|
||||
L(j, 3) = -x2(z, i) * x1(w, i); // d
|
||||
L(j, 8) = x2(x, i) * x1(x, i); // i
|
||||
L(j, 9) = x2(x, i) * x1(y, i); // j
|
||||
L(j, 10) = x2(x, i) * x1(z, i); // k
|
||||
L(j, 11) = x2(x, i) * x1(w, i); // l
|
||||
|
||||
++j;
|
||||
L(j, 4) = -x2(w, i) * x1(x, i); // e
|
||||
L(j, 5) = -x2(w, i) * x1(y, i); // f
|
||||
L(j, 6) = -x2(w, i) * x1(z, i); // g
|
||||
L(j, 7) = -x2(w, i) * x1(w, i); // h
|
||||
L(j, 12) = x2(y, i) * x1(x, i); // m
|
||||
L(j, 13) = x2(y, i) * x1(y, i); // n
|
||||
L(j, 14) = x2(y, i) * x1(z, i); // o
|
||||
b(j, 0) = -x2(y, i) * x1(w, i);
|
||||
|
||||
++j;
|
||||
L(j, 0) = -x2(y, i) * x1(x, i); // a
|
||||
L(j, 1) = -x2(y, i) * x1(y, i); // b
|
||||
L(j, 2) = -x2(y, i) * x1(z, i); // c
|
||||
L(j, 3) = -x2(y, i) * x1(w, i); // d
|
||||
L(j, 4) = x2(x, i) * x1(x, i); // e
|
||||
L(j, 5) = x2(x, i) * x1(y, i); // f
|
||||
L(j, 6) = x2(x, i) * x1(z, i); // g
|
||||
L(j, 7) = x2(x, i) * x1(w, i); // h
|
||||
|
||||
++j;
|
||||
L(j, 8) = -x2(w, i) * x1(x, i); // i
|
||||
L(j, 9) = -x2(w, i) * x1(y, i); // j
|
||||
L(j, 10) = -x2(w, i) * x1(z, i); // k
|
||||
L(j, 11) = -x2(w, i) * x1(w, i); // l
|
||||
L(j, 12) = x2(z, i) * x1(x, i); // m
|
||||
L(j, 13) = x2(z, i) * x1(y, i); // n
|
||||
L(j, 14) = x2(z, i) * x1(z, i); // o
|
||||
b(j, 0) = -x2(z, i) * x1(w, i);
|
||||
}
|
||||
// Solve Lx=B
|
||||
Vec h = L.fullPivLu().solve(b);
|
||||
if ((L * h).isApprox(b, expected_precision)) {
|
||||
Homography3DNormalizedParameterization<double>::To(h, H);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
double SymmetricGeometricDistance(const Mat3 &H,
|
||||
const Vec2 &x1,
|
||||
const Vec2 &x2) {
|
||||
Vec3 x(x1(0), x1(1), 1.0);
|
||||
Vec3 y(x2(0), x2(1), 1.0);
|
||||
|
||||
Vec3 H_x = H * x;
|
||||
Vec3 Hinv_y = H.inverse() * y;
|
||||
|
||||
H_x /= H_x(2);
|
||||
Hinv_y /= Hinv_y(2);
|
||||
|
||||
return (H_x.head<2>() - y.head<2>()).squaredNorm() +
|
||||
(Hinv_y.head<2>() - x.head<2>()).squaredNorm();
|
||||
}
|
||||
|
||||
} // namespace libmv
|
||||
@@ -0,0 +1,145 @@
|
||||
// Copyright (c) 2011 libmv authors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
|
||||
#ifndef LIBMV_MULTIVIEW_HOMOGRAPHY_H_
|
||||
#define LIBMV_MULTIVIEW_HOMOGRAPHY_H_
|
||||
|
||||
#include "libmv/numeric/numeric.h"
|
||||
|
||||
namespace libmv {
|
||||
|
||||
/**
|
||||
* 2D homography transformation estimation.
|
||||
*
|
||||
* This function estimates the homography transformation from a list of 2D
|
||||
* correspondences which represents either:
|
||||
*
|
||||
* - 3D points on a plane, with a general moving camera.
|
||||
* - 3D points with a rotating camera (pure rotation).
|
||||
* - 3D points + different planar projections
|
||||
*
|
||||
* \param x1 The first 2xN or 3xN matrix of euclidean or homogeneous points.
|
||||
* \param x2 The second 2xN or 3xN matrix of euclidean or homogeneous points.
|
||||
* \param H The 3x3 homography transformation matrix (8 dof) such that
|
||||
* x2 = H * x1 with |a b c|
|
||||
* H = |d e f|
|
||||
* |g h 1|
|
||||
* \param expected_precision The expected precision in order for instance
|
||||
* to accept almost homography matrices.
|
||||
*
|
||||
* \return True if the transformation estimation has succeeded.
|
||||
* \note There must be at least 4 non-colinear points.
|
||||
*/
|
||||
bool Homography2DFromCorrespondencesLinear(const Mat &x1,
|
||||
const Mat &x2,
|
||||
Mat3 *H,
|
||||
double expected_precision =
|
||||
EigenDouble::dummy_precision());
|
||||
|
||||
/**
|
||||
* This structure contains options that controls how the homography
|
||||
* estimation operates.
|
||||
*
|
||||
* Defaults should be suitable for a wide range of use cases, but
|
||||
* better performance and accuracy might require tweaking/
|
||||
*/
|
||||
struct EstimateHomographyOptions {
|
||||
// Default constructor which sets up a options for generic usage.
|
||||
EstimateHomographyOptions(void);
|
||||
|
||||
// Normalize correspondencies before estimating the homography
|
||||
// in order to increase estimation stability.
|
||||
//
|
||||
// Normaliztion will make it so centroid od correspondences
|
||||
// is the coordinate origin and their average distance from
|
||||
// the origin is sqrt(2).
|
||||
//
|
||||
// See:
|
||||
// - R. Hartley and A. Zisserman. Multiple View Geometry in Computer
|
||||
// Vision. Cambridge University Press, second edition, 2003.
|
||||
// - https://www.cs.ubc.ca/grads/resources/thesis/May09/Dubrofsky_Elan.pdf
|
||||
bool use_normalization;
|
||||
|
||||
// Maximal number of iterations for the refinement step.
|
||||
int max_num_iterations;
|
||||
|
||||
// Expected average of symmetric geometric distance between
|
||||
// actual destination points and original ones transformed by
|
||||
// estimated homography matrix.
|
||||
//
|
||||
// Refinement will finish as soon as average of symmetric
|
||||
// geometric distance is less or equal to this value.
|
||||
//
|
||||
// This distance is measured in the same units as input points are.
|
||||
double expected_average_symmetric_distance;
|
||||
};
|
||||
|
||||
/**
|
||||
* 2D homography transformation estimation.
|
||||
*
|
||||
* This function estimates the homography transformation from a list of 2D
|
||||
* correspondences by doing algebraic estimation first followed with result
|
||||
* refinement.
|
||||
*/
|
||||
bool EstimateHomography2DFromCorrespondences(
|
||||
const Mat &x1,
|
||||
const Mat &x2,
|
||||
const EstimateHomographyOptions &options,
|
||||
Mat3 *H);
|
||||
|
||||
/**
|
||||
* 3D Homography transformation estimation.
|
||||
*
|
||||
* This function can be used in order to estimate the homography transformation
|
||||
* from a list of 3D correspondences.
|
||||
*
|
||||
* \param[in] x1 The first 4xN matrix of homogeneous points
|
||||
* \param[in] x2 The second 4xN matrix of homogeneous points
|
||||
* \param[out] H The 4x4 homography transformation matrix (15 dof) such that
|
||||
* x2 = H * x1 with |a b c d|
|
||||
* H = |e f g h|
|
||||
* |i j k l|
|
||||
* |m n o 1|
|
||||
* \param[in] expected_precision The expected precision in order for instance
|
||||
* to accept almost homography matrices.
|
||||
*
|
||||
* \return true if the transformation estimation has succeeded
|
||||
*
|
||||
* \note Need at least 5 non coplanar points
|
||||
* \note Points coordinates must be in homogeneous coordinates
|
||||
*/
|
||||
bool Homography3DFromCorrespondencesLinear(const Mat &x1,
|
||||
const Mat &x2,
|
||||
Mat4 *H,
|
||||
double expected_precision =
|
||||
EigenDouble::dummy_precision());
|
||||
|
||||
/**
|
||||
* Calculate symmetric geometric cost:
|
||||
*
|
||||
* D(H * x1, x2)^2 + D(H^-1 * x2, x1)
|
||||
*/
|
||||
double SymmetricGeometricDistance(const Mat3 &H,
|
||||
const Vec2 &x1,
|
||||
const Vec2 &x2);
|
||||
|
||||
} // namespace libmv
|
||||
|
||||
#endif // LIBMV_MULTIVIEW_HOMOGRAPHY_H_
|
||||
@@ -0,0 +1,248 @@
|
||||
// Copyright (c) 2011 libmv authors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
|
||||
#ifndef LIBMV_MULTIVIEW_HOMOGRAPHY_ERRORS_H_
|
||||
#define LIBMV_MULTIVIEW_HOMOGRAPHY_ERRORS_H_
|
||||
|
||||
#include "libmv/multiview/projection.h"
|
||||
|
||||
namespace libmv {
|
||||
namespace homography {
|
||||
namespace homography2D {
|
||||
|
||||
/**
|
||||
* Structure for estimating the asymmetric error between a vector x2 and the
|
||||
* transformed x1 such that
|
||||
* Error = ||x2 - Psi(H * x1)||^2
|
||||
* where Psi is the function that transforms homogeneous to euclidean coords.
|
||||
* \note It should be distributed as Chi-squared with k = 2.
|
||||
*/
|
||||
struct AsymmetricError {
|
||||
/**
|
||||
* Computes the asymmetric residuals between a set of 2D points x2 and the
|
||||
* transformed 2D point set x1 such that
|
||||
* Residuals_i = x2_i - Psi(H * x1_i)
|
||||
* where Psi is the function that transforms homogeneous to euclidean coords.
|
||||
*
|
||||
* \param[in] H The 3x3 homography matrix.
|
||||
* The estimated homography should approximatelly hold the condition y = H x.
|
||||
* \param[in] x1 A set of 2D points (2xN or 3xN matrix of column vectors).
|
||||
* \param[in] x2 A set of 2D points (2xN or 3xN matrix of column vectors).
|
||||
* \param[out] dx A 2xN matrix of column vectors of residuals errors
|
||||
*/
|
||||
static void Residuals(const Mat &H, const Mat &x1,
|
||||
const Mat &x2, Mat2X *dx) {
|
||||
dx->resize(2, x1.cols());
|
||||
Mat3X x2h_est;
|
||||
if (x1.rows() == 2)
|
||||
x2h_est = H * EuclideanToHomogeneous(static_cast<Mat2X>(x1));
|
||||
else
|
||||
x2h_est = H * x1;
|
||||
dx->row(0) = x2h_est.row(0).array() / x2h_est.row(2).array();
|
||||
dx->row(1) = x2h_est.row(1).array() / x2h_est.row(2).array();
|
||||
if (x2.rows() == 2)
|
||||
*dx = x2 - *dx;
|
||||
else
|
||||
*dx = HomogeneousToEuclidean(static_cast<Mat3X>(x2)) - *dx;
|
||||
}
|
||||
/**
|
||||
* Computes the asymmetric residuals between a 2D point x2 and the transformed
|
||||
* 2D point x1 such that
|
||||
* Residuals = x2 - Psi(H * x1)
|
||||
* where Psi is the function that transforms homogeneous to euclidean coords.
|
||||
*
|
||||
* \param[in] H The 3x3 homography matrix.
|
||||
* The estimated homography should approximatelly hold the condition y = H x.
|
||||
* \param[in] x1 A 2D point (vector of size 2 or 3 (euclidean/homogeneous))
|
||||
* \param[in] x2 A 2D point (vector of size 2 or 3 (euclidean/homogeneous))
|
||||
* \param[out] dx A vector of size 2 of the residual error
|
||||
*/
|
||||
static void Residuals(const Mat &H, const Vec &x1,
|
||||
const Vec &x2, Vec2 *dx) {
|
||||
Vec3 x2h_est;
|
||||
if (x1.rows() == 2)
|
||||
x2h_est = H * EuclideanToHomogeneous(static_cast<Vec2>(x1));
|
||||
else
|
||||
x2h_est = H * x1;
|
||||
if (x2.rows() == 2)
|
||||
*dx = x2 - x2h_est.head<2>() / x2h_est[2];
|
||||
else
|
||||
*dx = HomogeneousToEuclidean(static_cast<Vec3>(x2)) -
|
||||
x2h_est.head<2>() / x2h_est[2];
|
||||
}
|
||||
/**
|
||||
* Computes the squared norm of the residuals between a set of 2D points x2
|
||||
* and the transformed 2D point set x1 such that
|
||||
* Error = || x2 - Psi(H * x1) ||^2
|
||||
* where Psi is the function that transforms homogeneous to euclidean coords.
|
||||
*
|
||||
* \param[in] H The 3x3 homography matrix.
|
||||
* The estimated homography should approximatelly hold the condition y = H x.
|
||||
* \param[in] x1 A set of 2D points (2xN or 3xN matrix of column vectors).
|
||||
* \param[in] x2 A set of 2D points (2xN or 3xN matrix of column vectors).
|
||||
* \return The squared norm of the asymmetric residuals errors
|
||||
*/
|
||||
static double Error(const Mat &H, const Mat &x1, const Mat &x2) {
|
||||
Mat2X dx;
|
||||
Residuals(H, x1, x2, &dx);
|
||||
return dx.squaredNorm();
|
||||
}
|
||||
/**
|
||||
* Computes the squared norm of the residuals between a 2D point x2 and the
|
||||
* transformed 2D point x1 such that rms = || x2 - Psi(H * x1) ||^2
|
||||
* where Psi is the function that transforms homogeneous to euclidean coords.
|
||||
*
|
||||
* \param[in] H The 3x3 homography matrix.
|
||||
* The estimated homography should approximatelly hold the condition y = H x.
|
||||
* \param[in] x1 A 2D point (vector of size 2 or 3 (euclidean/homogeneous))
|
||||
* \param[in] x2 A 2D point (vector of size 2 or 3 (euclidean/homogeneous))
|
||||
* \return The squared norm of the asymmetric residual error
|
||||
*/
|
||||
static double Error(const Mat &H, const Vec &x1, const Vec &x2) {
|
||||
Vec2 dx;
|
||||
Residuals(H, x1, x2, &dx);
|
||||
return dx.squaredNorm();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Structure for estimating the symmetric error
|
||||
* between a vector x2 and the transformed x1 such that
|
||||
* Error = ||x2 - Psi(H * x1)||^2 + ||x1 - Psi(H^-1 * x2)||^2
|
||||
* where Psi is the function that transforms homogeneous to euclidean coords.
|
||||
* \note It should be distributed as Chi-squared with k = 4.
|
||||
*/
|
||||
struct SymmetricError {
|
||||
/**
|
||||
* Computes the squared norm of the residuals between x2 and the
|
||||
* transformed x1 such that
|
||||
* Error = ||x2 - Psi(H * x1)||^2 + ||x1 - Psi(H^-1 * x2)||^2
|
||||
* where Psi is the function that transforms homogeneous to euclidean coords.
|
||||
*
|
||||
* \param[in] H The 3x3 homography matrix.
|
||||
* The estimated homography should approximatelly hold the condition y = H x.
|
||||
* \param[in] x1 A 2D point (vector of size 2 or 3 (euclidean/homogeneous))
|
||||
* \param[in] x2 A 2D point (vector of size 2 or 3 (euclidean/homogeneous))
|
||||
* \return The squared norm of the symmetric residuals errors
|
||||
*/
|
||||
static double Error(const Mat &H, const Vec &x1, const Vec &x2) {
|
||||
// TODO(keir): This is awesomely inefficient because it does a 3x3
|
||||
// inversion for each evaluation.
|
||||
Mat3 Hinv = H.inverse();
|
||||
return AsymmetricError::Error(H, x1, x2) +
|
||||
AsymmetricError::Error(Hinv, x2, x1);
|
||||
}
|
||||
// TODO(julien) Add residuals function \see AsymmetricError
|
||||
};
|
||||
/**
|
||||
* Structure for estimating the algebraic error (cross product)
|
||||
* between a vector x2 and the transformed x1 such that
|
||||
* Error = ||[x2] * H * x1||^^2
|
||||
* where [x2] is the skew matrix of x2.
|
||||
*/
|
||||
struct AlgebraicError {
|
||||
// TODO(julien) Make an AlgebraicError2Rows and AlgebraicError3Rows
|
||||
|
||||
/**
|
||||
* Computes the algebraic residuals (cross product) between a set of 2D
|
||||
* points x2 and the transformed 2D point set x1 such that
|
||||
* [x2] * H * x1 where [x2] is the skew matrix of x2.
|
||||
*
|
||||
* \param[in] H The 3x3 homography matrix.
|
||||
* The estimated homography should approximatelly hold the condition y = H x.
|
||||
* \param[in] x1 A set of 2D points (2xN or 3xN matrix of column vectors).
|
||||
* \param[in] x2 A set of 2D points (2xN or 3xN matrix of column vectors).
|
||||
* \param[out] dx A 3xN matrix of column vectors of residuals errors
|
||||
*/
|
||||
static void Residuals(const Mat &H, const Mat &x1,
|
||||
const Mat &x2, Mat3X *dx) {
|
||||
dx->resize(3, x1.cols());
|
||||
Vec3 col;
|
||||
for (int i = 0; i < x1.cols(); ++i) {
|
||||
Residuals(H, x1.col(i), x2.col(i), &col);
|
||||
dx->col(i) = col;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Computes the algebraic residuals (cross product) between a 2D point x2
|
||||
* and the transformed 2D point x1 such that
|
||||
* [x2] * H * x1 where [x2] is the skew matrix of x2.
|
||||
*
|
||||
* \param[in] H The 3x3 homography matrix.
|
||||
* The estimated homography should approximatelly hold the condition y = H x.
|
||||
* \param[in] x1 A 2D point (vector of size 2 or 3 (euclidean/homogeneous))
|
||||
* \param[in] x2 A 2D point (vector of size 2 or 3 (euclidean/homogeneous))
|
||||
* \param[out] dx A vector of size 3 of the residual error
|
||||
*/
|
||||
static void Residuals(const Mat &H, const Vec &x1,
|
||||
const Vec &x2, Vec3 *dx) {
|
||||
Vec3 x2h_est;
|
||||
if (x1.rows() == 2)
|
||||
x2h_est = H * EuclideanToHomogeneous(static_cast<Vec2>(x1));
|
||||
else
|
||||
x2h_est = H * x1;
|
||||
if (x2.rows() == 2)
|
||||
*dx = SkewMat(EuclideanToHomogeneous(static_cast<Vec2>(x2))) * x2h_est;
|
||||
else
|
||||
*dx = SkewMat(x2) * x2h_est;
|
||||
// TODO(julien) This is inefficient since it creates an
|
||||
// identical 3x3 skew matrix for each evaluation.
|
||||
}
|
||||
/**
|
||||
* Computes the squared norm of the algebraic residuals between a set of 2D
|
||||
* points x2 and the transformed 2D point set x1 such that
|
||||
* [x2] * H * x1 where [x2] is the skew matrix of x2.
|
||||
*
|
||||
* \param[in] H The 3x3 homography matrix.
|
||||
* The estimated homography should approximatelly hold the condition y = H x.
|
||||
* \param[in] x1 A set of 2D points (2xN or 3xN matrix of column vectors).
|
||||
* \param[in] x2 A set of 2D points (2xN or 3xN matrix of column vectors).
|
||||
* \return The squared norm of the asymmetric residuals errors
|
||||
*/
|
||||
static double Error(const Mat &H, const Mat &x1, const Mat &x2) {
|
||||
Mat3X dx;
|
||||
Residuals(H, x1, x2, &dx);
|
||||
return dx.squaredNorm();
|
||||
}
|
||||
/**
|
||||
* Computes the squared norm of the algebraic residuals between a 2D point x2
|
||||
* and the transformed 2D point x1 such that
|
||||
* [x2] * H * x1 where [x2] is the skew matrix of x2.
|
||||
*
|
||||
* \param[in] H The 3x3 homography matrix.
|
||||
* The estimated homography should approximatelly hold the condition y = H x.
|
||||
* \param[in] x1 A 2D point (vector of size 2 or 3 (euclidean/homogeneous))
|
||||
* \param[in] x2 A 2D point (vector of size 2 or 3 (euclidean/homogeneous))
|
||||
* \return The squared norm of the asymmetric residual error
|
||||
*/
|
||||
static double Error(const Mat &H, const Vec &x1, const Vec &x2) {
|
||||
Vec3 dx;
|
||||
Residuals(H, x1, x2, &dx);
|
||||
return dx.squaredNorm();
|
||||
}
|
||||
};
|
||||
// TODO(keir): Add error based on ideal points.
|
||||
|
||||
} // namespace homography2D
|
||||
// TODO(julien) add homography3D errors
|
||||
} // namespace homography
|
||||
} // namespace libmv
|
||||
|
||||
#endif // LIBMV_MULTIVIEW_HOMOGRAPHY_ERRORS_H_
|
||||
@@ -0,0 +1,91 @@
|
||||
// Copyright (c) 2011 libmv authors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
|
||||
#ifndef LIBMV_MULTIVIEW_HOMOGRAPHY_PARAMETERIZATION_H_
|
||||
#define LIBMV_MULTIVIEW_HOMOGRAPHY_PARAMETERIZATION_H_
|
||||
|
||||
#include "libmv/numeric/numeric.h"
|
||||
|
||||
namespace libmv {
|
||||
|
||||
/** A parameterization of the 2D homography matrix that uses 8 parameters so
|
||||
* that the matrix is normalized (H(2,2) == 1).
|
||||
* The homography matrix H is built from a list of 8 parameters (a, b,...g, h)
|
||||
* as follows
|
||||
* |a b c|
|
||||
* H = |d e f|
|
||||
* |g h 1|
|
||||
*/
|
||||
template<typename T = double>
|
||||
class Homography2DNormalizedParameterization {
|
||||
public:
|
||||
typedef Eigen::Matrix<T, 8, 1> Parameters; // a, b, ... g, h
|
||||
typedef Eigen::Matrix<T, 3, 3> Parameterized; // H
|
||||
|
||||
/// Convert from the 8 parameters to a H matrix.
|
||||
static void To(const Parameters &p, Parameterized *h) {
|
||||
*h << p(0), p(1), p(2),
|
||||
p(3), p(4), p(5),
|
||||
p(6), p(7), 1.0;
|
||||
}
|
||||
|
||||
/// Convert from a H matrix to the 8 parameters.
|
||||
static void From(const Parameterized &h, Parameters *p) {
|
||||
*p << h(0, 0), h(0, 1), h(0, 2),
|
||||
h(1, 0), h(1, 1), h(1, 2),
|
||||
h(2, 0), h(2, 1);
|
||||
}
|
||||
};
|
||||
|
||||
/** A parameterization of the 2D homography matrix that uses 15 parameters so
|
||||
* that the matrix is normalized (H(3,3) == 1).
|
||||
* The homography matrix H is built from a list of 15 parameters (a, b,...n, o)
|
||||
* as follows
|
||||
* |a b c d|
|
||||
* H = |e f g h|
|
||||
* |i j k l|
|
||||
* |m n o 1|
|
||||
*/
|
||||
template<typename T = double>
|
||||
class Homography3DNormalizedParameterization {
|
||||
public:
|
||||
typedef Eigen::Matrix<T, 15, 1> Parameters; // a, b, ... n, o
|
||||
typedef Eigen::Matrix<T, 4, 4> Parameterized; // H
|
||||
|
||||
/// Convert from the 15 parameters to a H matrix.
|
||||
static void To(const Parameters &p, Parameterized *h) {
|
||||
*h << p(0), p(1), p(2), p(3),
|
||||
p(4), p(5), p(6), p(7),
|
||||
p(8), p(9), p(10), p(11),
|
||||
p(12), p(13), p(14), 1.0;
|
||||
}
|
||||
|
||||
/// Convert from a H matrix to the 15 parameters.
|
||||
static void From(const Parameterized &h, Parameters *p) {
|
||||
*p << h(0, 0), h(0, 1), h(0, 2), h(0, 3),
|
||||
h(1, 0), h(1, 1), h(1, 2), h(1, 3),
|
||||
h(2, 0), h(2, 1), h(2, 2), h(2, 3),
|
||||
h(3, 0), h(3, 1), h(3, 2);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace libmv
|
||||
|
||||
#endif // LIBMV_MULTIVIEW_HOMOGRAPHY_PARAMETERIZATION_H_
|
||||
@@ -0,0 +1,80 @@
|
||||
// Copyright (c) 2009 libmv authors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//
|
||||
// Compute a 3D position of a point from several images of it. In particular,
|
||||
// compute the projective point X in R^4 such that x = PX.
|
||||
//
|
||||
// Algorithm is the standard DLT; for derivation see appendix of Keir's thesis.
|
||||
|
||||
#ifndef LIBMV_MULTIVIEW_NVIEWTRIANGULATION_H
|
||||
#define LIBMV_MULTIVIEW_NVIEWTRIANGULATION_H
|
||||
|
||||
#include "libmv/base/vector.h"
|
||||
#include "libmv/logging/logging.h"
|
||||
#include "libmv/numeric/numeric.h"
|
||||
|
||||
namespace libmv {
|
||||
|
||||
// x's are 2D coordinates (x,y,1) in each image; Ps are projective cameras. The
|
||||
// output, X, is a homogeneous four vectors.
|
||||
template<typename T>
|
||||
void NViewTriangulate(const Matrix<T, 2, Dynamic> &x,
|
||||
const vector<Matrix<T, 3, 4> > &Ps,
|
||||
Matrix<T, 4, 1> *X) {
|
||||
int nviews = x.cols();
|
||||
assert(nviews == Ps.size());
|
||||
|
||||
Matrix<T, Dynamic, Dynamic> design(3*nviews, 4 + nviews);
|
||||
design.setConstant(0.0);
|
||||
for (int i = 0; i < nviews; i++) {
|
||||
design.template block<3, 4>(3*i, 0) = -Ps[i];
|
||||
design(3*i + 0, 4 + i) = x(0, i);
|
||||
design(3*i + 1, 4 + i) = x(1, i);
|
||||
design(3*i + 2, 4 + i) = 1.0;
|
||||
}
|
||||
Matrix<T, Dynamic, 1> X_and_alphas;
|
||||
Nullspace(&design, &X_and_alphas);
|
||||
X->resize(4);
|
||||
*X = X_and_alphas.head(4);
|
||||
}
|
||||
|
||||
// x's are 2D coordinates (x,y,1) in each image; Ps are projective cameras. The
|
||||
// output, X, is a homogeneous four vectors.
|
||||
// This method uses the algebraic distance approximation.
|
||||
// Note that this method works better when the 2D points are normalized
|
||||
// with an isotopic normalization.
|
||||
template<typename T>
|
||||
void NViewTriangulateAlgebraic(const Matrix<T, 2, Dynamic> &x,
|
||||
const vector<Matrix<T, 3, 4> > &Ps,
|
||||
Matrix<T, 4, 1> *X) {
|
||||
int nviews = x.cols();
|
||||
assert(nviews == Ps.size());
|
||||
|
||||
Matrix<T, Dynamic, 4> design(2*nviews, 4);
|
||||
for (int i = 0; i < nviews; i++) {
|
||||
design.template block<2, 4>(2*i, 0) = SkewMatMinimal(x.col(i)) * Ps[i];
|
||||
}
|
||||
X->resize(4);
|
||||
Nullspace(&design, X);
|
||||
}
|
||||
|
||||
} // namespace libmv
|
||||
|
||||
#endif // LIBMV_MULTIVIEW_RESECTION_H
|
||||
@@ -0,0 +1,125 @@
|
||||
// Copyright (c) 2009 libmv authors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
#include "libmv/multiview/panography.h"
|
||||
|
||||
namespace libmv {
|
||||
|
||||
static bool Build_Minimal2Point_PolynomialFactor(
|
||||
const Mat & x1, const Mat & x2,
|
||||
double * P) { // P must be a double[4]
|
||||
assert(2 == x1.rows());
|
||||
assert(2 == x1.cols());
|
||||
assert(x1.rows() == x2.rows());
|
||||
assert(x1.cols() == x2.cols());
|
||||
|
||||
// Setup the variable of the input problem:
|
||||
Vec xx1 = (x1.col(0)).transpose();
|
||||
Vec yx1 = (x1.col(1)).transpose();
|
||||
|
||||
double a12 = xx1.dot(yx1);
|
||||
Vec xx2 = (x2.col(0)).transpose();
|
||||
Vec yx2 = (x2.col(1)).transpose();
|
||||
double b12 = xx2.dot(yx2);
|
||||
|
||||
double a1 = xx1.squaredNorm();
|
||||
double a2 = yx1.squaredNorm();
|
||||
|
||||
double b1 = xx2.squaredNorm();
|
||||
double b2 = yx2.squaredNorm();
|
||||
|
||||
// Build the 3rd degre polynomial in F^2.
|
||||
//
|
||||
// f^6 * p + f^4 * q + f^2* r + s = 0;
|
||||
//
|
||||
// Coefficients in ascending powers of alpha, i.e. P[N]*x^N.
|
||||
// Run panography_coeffs.py to get the below coefficients.
|
||||
P[0] = b1*b2*a12*a12-a1*a2*b12*b12;
|
||||
P[1] = -2*a1*a2*b12+2*a12*b1*b2+b1*a12*a12+b2*a12*a12-a1*b12*b12-a2*b12*b12;
|
||||
P[2] = b1*b2-a1*a2-2*a1*b12-2*a2*b12+2*a12*b1+2*a12*b2+a12*a12-b12*b12;
|
||||
P[3] = b1+b2-2*b12-a1-a2+2*a12;
|
||||
|
||||
// If P[3] equal to 0 we get ill conditionned data
|
||||
return (P[3] != 0.0);
|
||||
}
|
||||
|
||||
// This implements a minimal solution (2 points) for panoramic stitching:
|
||||
//
|
||||
// http://www.cs.ubc.ca/~mbrown/minimal/minimal.html
|
||||
//
|
||||
// [1] M. Brown and R. Hartley and D. Nister. Minimal Solutions for Panoramic
|
||||
// Stitching. CVPR07.
|
||||
void F_FromCorrespondance_2points(const Mat &x1, const Mat &x2,
|
||||
vector<double> *fs) {
|
||||
// Build Polynomial factor to get squared focal value.
|
||||
double P[4];
|
||||
Build_Minimal2Point_PolynomialFactor(x1, x2, &P[0]);
|
||||
|
||||
// Solve it by using F = f^2 and a Cubic polynomial solver
|
||||
//
|
||||
// F^3 * p + F^2 * q + F^1 * r + s = 0
|
||||
//
|
||||
double roots[3];
|
||||
int num_roots = SolveCubicPolynomial(P, roots);
|
||||
for (int i = 0; i < num_roots; ++i) {
|
||||
if (roots[i] > 0.0) {
|
||||
fs->push_back(sqrt(roots[i]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Compute the 3x3 rotation matrix that fits two 3D point clouds in the least
|
||||
// square sense. The method is from:
|
||||
//
|
||||
// K. Arun,T. Huand and D. Blostein. Least-squares fitting of 2 3-D point
|
||||
// sets. IEEE Transactions on Pattern Analysis and Machine Intelligence,
|
||||
// 9:698-700, 1987.
|
||||
void GetR_FixedCameraCenter(const Mat &x1, const Mat &x2,
|
||||
const double focal,
|
||||
Mat3 *R) {
|
||||
assert(3 == x1.rows());
|
||||
assert(2 <= x1.cols());
|
||||
assert(x1.rows() == x2.rows());
|
||||
assert(x1.cols() == x2.cols());
|
||||
|
||||
// Build simplified K matrix
|
||||
Mat3 K(Mat3::Identity() * 1.0/focal);
|
||||
K(2, 2)= 1.0;
|
||||
|
||||
// Build the correlation matrix; equation (22) in [1].
|
||||
Mat3 C = Mat3::Zero();
|
||||
for (int i = 0; i < x1.cols(); ++i) {
|
||||
Mat r1i = (K * x1.col(i)).normalized();
|
||||
Mat r2i = (K * x2.col(i)).normalized();
|
||||
C += r2i * r1i.transpose();
|
||||
}
|
||||
|
||||
// Solve for rotation. Equations (24) and (25) in [1].
|
||||
Eigen::JacobiSVD<Mat> svd(C, Eigen::ComputeThinU | Eigen::ComputeThinV);
|
||||
Mat3 scale = Mat3::Identity();
|
||||
scale(2, 2) = ((svd.matrixU() * svd.matrixV().transpose()).determinant() > 0.0)
|
||||
? 1.0
|
||||
: -1.0;
|
||||
|
||||
(*R) = svd.matrixU() * scale * svd.matrixV().transpose();
|
||||
}
|
||||
|
||||
} // namespace libmv
|
||||
@@ -0,0 +1,99 @@
|
||||
// Copyright (c) 2009 libmv authors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
#ifndef LIBMV_MULTIVIEW_PANOGRAPHY_H
|
||||
#define LIBMV_MULTIVIEW_PANOGRAPHY_H
|
||||
|
||||
#include "libmv/numeric/numeric.h"
|
||||
#include "libmv/numeric/poly.h"
|
||||
#include "libmv/base/vector.h"
|
||||
|
||||
namespace libmv {
|
||||
|
||||
// This implements a minimal solution (2 points) for panoramic stitching:
|
||||
//
|
||||
// http://www.cs.ubc.ca/~mbrown/minimal/minimal.html
|
||||
//
|
||||
// [1] M. Brown and R. Hartley and D. Nister. Minimal Solutions for Panoramic
|
||||
// Stitching. CVPR07.
|
||||
//
|
||||
// The 2-point algorithm solves for the rotation of the camera with a single
|
||||
// focal length (4 degrees of freedom).
|
||||
//
|
||||
// Compute from 1 to 3 possible focal length for 2 point correspondences.
|
||||
// Suppose that the cameras share the same optical center and focal lengths:
|
||||
//
|
||||
// Image 1 => H*x = x' => Image 2
|
||||
// x (u1j) x' (u2j)
|
||||
// a (u11) a' (u21)
|
||||
// b (u12) b' (u22)
|
||||
//
|
||||
// The return values are 1 to 3 possible values for the focal lengths such
|
||||
// that:
|
||||
//
|
||||
// [f 0 0]
|
||||
// K = [0 f 0]
|
||||
// [0 0 1]
|
||||
//
|
||||
void F_FromCorrespondance_2points(const Mat &x1, const Mat &x2,
|
||||
vector<double> *fs);
|
||||
|
||||
// Compute the 3x3 rotation matrix that fits two 3D point clouds in the least
|
||||
// square sense. The method is from:
|
||||
//
|
||||
// K. Arun,T. Huand and D. Blostein. Least-squares fitting of 2 3-D point
|
||||
// sets. IEEE Transactions on Pattern Analysis and Machine Intelligence,
|
||||
// 9:698-700, 1987.
|
||||
//
|
||||
// Given the calibration matrices K1, K2 solve for the rotation from
|
||||
// corresponding image rays.
|
||||
//
|
||||
// R = min || X2 - R * x1 ||.
|
||||
//
|
||||
// In case of panography, which is for a camera that shares the same camera
|
||||
// center,
|
||||
//
|
||||
// H = K2 * R * K1.inverse();
|
||||
//
|
||||
// For the full explanation, see Section 8, Solving for Rotation from [1].
|
||||
//
|
||||
// Parameters:
|
||||
//
|
||||
// x1 : Point cloud A (3D coords)
|
||||
// x2 : Point cloud B (3D coords)
|
||||
//
|
||||
// [f 0 0]
|
||||
// K1 = [0 f 0]
|
||||
// [0 0 1]
|
||||
//
|
||||
// K2 (the same form as K1, but may have different f)
|
||||
//
|
||||
// Returns: A rotation matrix that minimizes
|
||||
//
|
||||
// R = arg min || X2 - R * x1 ||
|
||||
//
|
||||
void GetR_FixedCameraCenter(const Mat &x1, const Mat &x2,
|
||||
const double focal,
|
||||
Mat3 *R);
|
||||
|
||||
} // namespace libmv
|
||||
|
||||
#endif // LIBMV_MULTIVIEW_PANOGRAPHY_H
|
||||
@@ -0,0 +1,51 @@
|
||||
// Copyright (c) 2008, 2009 libmv authors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
|
||||
#include "libmv/multiview/panography_kernel.h"
|
||||
#include "libmv/multiview/panography.h"
|
||||
|
||||
namespace libmv {
|
||||
namespace panography {
|
||||
namespace kernel {
|
||||
|
||||
void TwoPointSolver::Solve(const Mat &x1, const Mat &x2, vector<Mat3> *Hs) {
|
||||
// Solve for the focal lengths.
|
||||
vector<double> fs;
|
||||
F_FromCorrespondance_2points(x1, x2, &fs);
|
||||
|
||||
// Then solve for the rotations and homographies.
|
||||
Mat x1h, x2h;
|
||||
EuclideanToHomogeneous(x1, &x1h);
|
||||
EuclideanToHomogeneous(x2, &x2h);
|
||||
for (int i = 0; i < fs.size(); ++i) {
|
||||
Mat3 K1 = Mat3::Identity() * fs[i];
|
||||
K1(2, 2) = 1.0;
|
||||
|
||||
Mat3 R;
|
||||
GetR_FixedCameraCenter(x1h, x2h, fs[i], &R);
|
||||
R /= R(2, 2);
|
||||
|
||||
(*Hs).push_back(K1 * R * K1.inverse());
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace kernel
|
||||
} // namespace panography
|
||||
} // namespace libmv
|
||||
@@ -0,0 +1,54 @@
|
||||
// Copyright (c) 2009 libmv authors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
|
||||
#ifndef LIBMV_MULTIVIEW_PANOGRAPHY_KERNEL_H
|
||||
#define LIBMV_MULTIVIEW_PANOGRAPHY_KERNEL_H
|
||||
|
||||
#include "libmv/base/vector.h"
|
||||
#include "libmv/multiview/conditioning.h"
|
||||
#include "libmv/multiview/projection.h"
|
||||
#include "libmv/multiview/two_view_kernel.h"
|
||||
#include "libmv/multiview/homography_error.h"
|
||||
#include "libmv/numeric/numeric.h"
|
||||
|
||||
namespace libmv {
|
||||
namespace panography {
|
||||
namespace kernel {
|
||||
|
||||
struct TwoPointSolver {
|
||||
enum { MINIMUM_SAMPLES = 2 };
|
||||
static void Solve(const Mat &x1, const Mat &x2, vector<Mat3> *Hs);
|
||||
};
|
||||
|
||||
typedef two_view::kernel::Kernel<
|
||||
TwoPointSolver, homography::homography2D::AsymmetricError, Mat3>
|
||||
UnnormalizedKernel;
|
||||
|
||||
typedef two_view::kernel::Kernel<
|
||||
two_view::kernel::NormalizedSolver<TwoPointSolver, UnnormalizerI>,
|
||||
homography::homography2D::AsymmetricError,
|
||||
Mat3>
|
||||
Kernel;
|
||||
|
||||
} // namespace kernel
|
||||
} // namespace panography
|
||||
} // namespace libmv
|
||||
|
||||
#endif // LIBMV_MULTIVIEW_PANOGRAPHY_KERNEL_H
|
||||
@@ -0,0 +1,224 @@
|
||||
// Copyright (c) 2007, 2008 libmv authors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
|
||||
#include "libmv/multiview/projection.h"
|
||||
#include "libmv/numeric/numeric.h"
|
||||
|
||||
namespace libmv {
|
||||
|
||||
void P_From_KRt(const Mat3 &K, const Mat3 &R, const Vec3 &t, Mat34 *P) {
|
||||
P->block<3, 3>(0, 0) = R;
|
||||
P->col(3) = t;
|
||||
(*P) = K * (*P);
|
||||
}
|
||||
|
||||
void KRt_From_P(const Mat34 &P, Mat3 *Kp, Mat3 *Rp, Vec3 *tp) {
|
||||
// Decompose using the RQ decomposition HZ A4.1.1 pag.579.
|
||||
Mat3 K = P.block(0, 0, 3, 3);
|
||||
|
||||
Mat3 Q;
|
||||
Q.setIdentity();
|
||||
|
||||
// Set K(2,1) to zero.
|
||||
if (K(2, 1) != 0) {
|
||||
double c = -K(2, 2);
|
||||
double s = K(2, 1);
|
||||
double l = sqrt(c * c + s * s);
|
||||
c /= l;
|
||||
s /= l;
|
||||
Mat3 Qx;
|
||||
Qx << 1, 0, 0,
|
||||
0, c, -s,
|
||||
0, s, c;
|
||||
K = K * Qx;
|
||||
Q = Qx.transpose() * Q;
|
||||
}
|
||||
// Set K(2,0) to zero.
|
||||
if (K(2, 0) != 0) {
|
||||
double c = K(2, 2);
|
||||
double s = K(2, 0);
|
||||
double l = sqrt(c * c + s * s);
|
||||
c /= l;
|
||||
s /= l;
|
||||
Mat3 Qy;
|
||||
Qy << c, 0, s,
|
||||
0, 1, 0,
|
||||
-s, 0, c;
|
||||
K = K * Qy;
|
||||
Q = Qy.transpose() * Q;
|
||||
}
|
||||
// Set K(1,0) to zero.
|
||||
if (K(1, 0) != 0) {
|
||||
double c = -K(1, 1);
|
||||
double s = K(1, 0);
|
||||
double l = sqrt(c * c + s * s);
|
||||
c /= l;
|
||||
s /= l;
|
||||
Mat3 Qz;
|
||||
Qz << c, -s, 0,
|
||||
s, c, 0,
|
||||
0, 0, 1;
|
||||
K = K * Qz;
|
||||
Q = Qz.transpose() * Q;
|
||||
}
|
||||
|
||||
Mat3 R = Q;
|
||||
|
||||
// Ensure that the diagonal is positive.
|
||||
// TODO(pau) Change this to ensure that:
|
||||
// - K(0,0) > 0
|
||||
// - K(2,2) = 1
|
||||
// - det(R) = 1
|
||||
if (K(2, 2) < 0) {
|
||||
K = -K;
|
||||
R = -R;
|
||||
}
|
||||
if (K(1, 1) < 0) {
|
||||
Mat3 S;
|
||||
S << 1, 0, 0,
|
||||
0, -1, 0,
|
||||
0, 0, 1;
|
||||
K = K * S;
|
||||
R = S * R;
|
||||
}
|
||||
if (K(0, 0) < 0) {
|
||||
Mat3 S;
|
||||
S << -1, 0, 0,
|
||||
0, 1, 0,
|
||||
0, 0, 1;
|
||||
K = K * S;
|
||||
R = S * R;
|
||||
}
|
||||
|
||||
// Compute translation.
|
||||
Vec p(3);
|
||||
p << P(0, 3), P(1, 3), P(2, 3);
|
||||
// TODO(pau) This should be done by a SolveLinearSystem(A, b, &x) call.
|
||||
// TODO(keir) use the eigen LU solver syntax...
|
||||
Vec3 t = K.inverse() * p;
|
||||
|
||||
// scale K so that K(2,2) = 1
|
||||
K = K / K(2, 2);
|
||||
|
||||
*Kp = K;
|
||||
*Rp = R;
|
||||
*tp = t;
|
||||
}
|
||||
|
||||
void ProjectionShiftPrincipalPoint(const Mat34 &P,
|
||||
const Vec2 &principal_point,
|
||||
const Vec2 &principal_point_new,
|
||||
Mat34 *P_new) {
|
||||
Mat3 T;
|
||||
T << 1, 0, principal_point_new(0) - principal_point(0),
|
||||
0, 1, principal_point_new(1) - principal_point(1),
|
||||
0, 0, 1;
|
||||
*P_new = T * P;
|
||||
}
|
||||
|
||||
void ProjectionChangeAspectRatio(const Mat34 &P,
|
||||
const Vec2 &principal_point,
|
||||
double aspect_ratio,
|
||||
double aspect_ratio_new,
|
||||
Mat34 *P_new) {
|
||||
Mat3 T;
|
||||
T << 1, 0, 0,
|
||||
0, aspect_ratio_new / aspect_ratio, 0,
|
||||
0, 0, 1;
|
||||
Mat34 P_temp;
|
||||
|
||||
ProjectionShiftPrincipalPoint(P, principal_point, Vec2(0, 0), &P_temp);
|
||||
P_temp = T * P_temp;
|
||||
ProjectionShiftPrincipalPoint(P_temp, Vec2(0, 0), principal_point, P_new);
|
||||
}
|
||||
|
||||
void HomogeneousToEuclidean(const Mat &H, Mat *X) {
|
||||
int d = H.rows() - 1;
|
||||
int n = H.cols();
|
||||
X->resize(d, n);
|
||||
for (size_t i = 0; i < n; ++i) {
|
||||
double h = H(d, i);
|
||||
for (int j = 0; j < d; ++j) {
|
||||
(*X)(j, i) = H(j, i) / h;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void HomogeneousToEuclidean(const Mat3X &h, Mat2X *e) {
|
||||
e->resize(2, h.cols());
|
||||
e->row(0) = h.row(0).array() / h.row(2).array();
|
||||
e->row(1) = h.row(1).array() / h.row(2).array();
|
||||
}
|
||||
void HomogeneousToEuclidean(const Mat4X &h, Mat3X *e) {
|
||||
e->resize(3, h.cols());
|
||||
e->row(0) = h.row(0).array() / h.row(3).array();
|
||||
e->row(1) = h.row(1).array() / h.row(3).array();
|
||||
e->row(2) = h.row(2).array() / h.row(3).array();
|
||||
}
|
||||
|
||||
void HomogeneousToEuclidean(const Vec3 &H, Vec2 *X) {
|
||||
double w = H(2);
|
||||
*X << H(0) / w, H(1) / w;
|
||||
}
|
||||
|
||||
void HomogeneousToEuclidean(const Vec4 &H, Vec3 *X) {
|
||||
double w = H(3);
|
||||
*X << H(0) / w, H(1) / w, H(2) / w;
|
||||
}
|
||||
|
||||
void EuclideanToHomogeneous(const Mat &X, Mat *H) {
|
||||
int d = X.rows();
|
||||
int n = X.cols();
|
||||
H->resize(d + 1, n);
|
||||
H->block(0, 0, d, n) = X;
|
||||
H->row(d).setOnes();
|
||||
}
|
||||
|
||||
void EuclideanToHomogeneous(const Vec2 &X, Vec3 *H) {
|
||||
*H << X(0), X(1), 1;
|
||||
}
|
||||
|
||||
void EuclideanToHomogeneous(const Vec3 &X, Vec4 *H) {
|
||||
*H << X(0), X(1), X(2), 1;
|
||||
}
|
||||
|
||||
// TODO(julien) Call conditioning.h/ApplyTransformationToPoints ?
|
||||
void EuclideanToNormalizedCamera(const Mat2X &x, const Mat3 &K, Mat2X *n) {
|
||||
Mat3X x_image_h;
|
||||
EuclideanToHomogeneous(x, &x_image_h);
|
||||
Mat3X x_camera_h = K.inverse() * x_image_h;
|
||||
HomogeneousToEuclidean(x_camera_h, n);
|
||||
}
|
||||
|
||||
void HomogeneousToNormalizedCamera(const Mat3X &x, const Mat3 &K, Mat2X *n) {
|
||||
Mat3X x_camera_h = K.inverse() * x;
|
||||
HomogeneousToEuclidean(x_camera_h, n);
|
||||
}
|
||||
|
||||
double Depth(const Mat3 &R, const Vec3 &t, const Vec3 &X) {
|
||||
return (R*X)(2) + t(2);
|
||||
}
|
||||
|
||||
double Depth(const Mat3 &R, const Vec3 &t, const Vec4 &X) {
|
||||
Vec3 Xe = X.head<3>() / X(3);
|
||||
return Depth(R, t, Xe);
|
||||
}
|
||||
|
||||
} // namespace libmv
|
||||
@@ -0,0 +1,231 @@
|
||||
// Copyright (c) 2007, 2008 libmv authors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
|
||||
#ifndef LIBMV_MULTIVIEW_PROJECTION_H_
|
||||
#define LIBMV_MULTIVIEW_PROJECTION_H_
|
||||
|
||||
#include "libmv/numeric/numeric.h"
|
||||
|
||||
namespace libmv {
|
||||
|
||||
void P_From_KRt(const Mat3 &K, const Mat3 &R, const Vec3 &t, Mat34 *P);
|
||||
void KRt_From_P(const Mat34 &P, Mat3 *K, Mat3 *R, Vec3 *t);
|
||||
|
||||
// Applies a change of basis to the image coordinates of the projection matrix
|
||||
// so that the principal point becomes principal_point_new.
|
||||
void ProjectionShiftPrincipalPoint(const Mat34 &P,
|
||||
const Vec2 &principal_point,
|
||||
const Vec2 &principal_point_new,
|
||||
Mat34 *P_new);
|
||||
|
||||
// Applies a change of basis to the image coordinates of the projection matrix
|
||||
// so that the aspect ratio becomes aspect_ratio_new. This is done by
|
||||
// stretching the y axis. The aspect ratio is defined as the quotient between
|
||||
// the focal length of the y and the x axis.
|
||||
void ProjectionChangeAspectRatio(const Mat34 &P,
|
||||
const Vec2 &principal_point,
|
||||
double aspect_ratio,
|
||||
double aspect_ratio_new,
|
||||
Mat34 *P_new);
|
||||
|
||||
void HomogeneousToEuclidean(const Mat &H, Mat *X);
|
||||
void HomogeneousToEuclidean(const Mat3X &h, Mat2X *e);
|
||||
void HomogeneousToEuclidean(const Mat4X &h, Mat3X *e);
|
||||
void HomogeneousToEuclidean(const Vec3 &H, Vec2 *X);
|
||||
void HomogeneousToEuclidean(const Vec4 &H, Vec3 *X);
|
||||
inline Vec2 HomogeneousToEuclidean(const Vec3 &h) {
|
||||
return h.head<2>() / h(2);
|
||||
}
|
||||
inline Vec3 HomogeneousToEuclidean(const Vec4 &h) {
|
||||
return h.head<3>() / h(3);
|
||||
}
|
||||
inline Mat2X HomogeneousToEuclidean(const Mat3X &h) {
|
||||
Mat2X e(2, h.cols());
|
||||
e.row(0) = h.row(0).array() / h.row(2).array();
|
||||
e.row(1) = h.row(1).array() / h.row(2).array();
|
||||
return e;
|
||||
}
|
||||
|
||||
void EuclideanToHomogeneous(const Mat &X, Mat *H);
|
||||
inline Mat3X EuclideanToHomogeneous(const Mat2X &x) {
|
||||
Mat3X h(3, x.cols());
|
||||
h.block(0, 0, 2, x.cols()) = x;
|
||||
h.row(2).setOnes();
|
||||
return h;
|
||||
}
|
||||
inline void EuclideanToHomogeneous(const Mat2X &x, Mat3X *h) {
|
||||
h->resize(3, x.cols());
|
||||
h->block(0, 0, 2, x.cols()) = x;
|
||||
h->row(2).setOnes();
|
||||
}
|
||||
inline Mat4X EuclideanToHomogeneous(const Mat3X &x) {
|
||||
Mat4X h(4, x.cols());
|
||||
h.block(0, 0, 3, x.cols()) = x;
|
||||
h.row(3).setOnes();
|
||||
return h;
|
||||
}
|
||||
inline void EuclideanToHomogeneous(const Mat3X &x, Mat4X *h) {
|
||||
h->resize(4, x.cols());
|
||||
h->block(0, 0, 3, x.cols()) = x;
|
||||
h->row(3).setOnes();
|
||||
}
|
||||
void EuclideanToHomogeneous(const Vec2 &X, Vec3 *H);
|
||||
void EuclideanToHomogeneous(const Vec3 &X, Vec4 *H);
|
||||
inline Vec3 EuclideanToHomogeneous(const Vec2 &x) {
|
||||
return Vec3(x(0), x(1), 1);
|
||||
}
|
||||
inline Vec4 EuclideanToHomogeneous(const Vec3 &x) {
|
||||
return Vec4(x(0), x(1), x(2), 1);
|
||||
}
|
||||
// Conversion from image coordinates to normalized camera coordinates
|
||||
void EuclideanToNormalizedCamera(const Mat2X &x, const Mat3 &K, Mat2X *n);
|
||||
void HomogeneousToNormalizedCamera(const Mat3X &x, const Mat3 &K, Mat2X *n);
|
||||
|
||||
inline Vec2 Project(const Mat34 &P, const Vec3 &X) {
|
||||
Vec4 HX;
|
||||
HX << X, 1.0;
|
||||
Vec3 hx = P * HX;
|
||||
return hx.head<2>() / hx(2);
|
||||
}
|
||||
|
||||
inline void Project(const Mat34 &P, const Vec4 &X, Vec3 *x) {
|
||||
*x = P * X;
|
||||
}
|
||||
|
||||
inline void Project(const Mat34 &P, const Vec4 &X, Vec2 *x) {
|
||||
Vec3 hx = P * X;
|
||||
*x = hx.head<2>() / hx(2);
|
||||
}
|
||||
|
||||
inline void Project(const Mat34 &P, const Vec3 &X, Vec3 *x) {
|
||||
Vec4 HX;
|
||||
HX << X, 1.0;
|
||||
Project(P, HX, x);
|
||||
}
|
||||
|
||||
inline void Project(const Mat34 &P, const Vec3 &X, Vec2 *x) {
|
||||
Vec3 hx;
|
||||
Project(P, X, &hx);
|
||||
*x = hx.head<2>() / hx(2);
|
||||
}
|
||||
|
||||
inline void Project(const Mat34 &P, const Mat4X &X, Mat2X *x) {
|
||||
x->resize(2, X.cols());
|
||||
for (int c = 0; c < X.cols(); ++c) {
|
||||
Vec3 hx = P * X.col(c);
|
||||
x->col(c) = hx.head<2>() / hx(2);
|
||||
}
|
||||
}
|
||||
|
||||
inline Mat2X Project(const Mat34 &P, const Mat4X &X) {
|
||||
Mat2X x;
|
||||
Project(P, X, &x);
|
||||
return x;
|
||||
}
|
||||
|
||||
inline void Project(const Mat34 &P, const Mat3X &X, Mat2X *x) {
|
||||
x->resize(2, X.cols());
|
||||
for (int c = 0; c < X.cols(); ++c) {
|
||||
Vec4 HX;
|
||||
HX << X.col(c), 1.0;
|
||||
Vec3 hx = P * HX;
|
||||
x->col(c) = hx.head<2>() / hx(2);
|
||||
}
|
||||
}
|
||||
|
||||
inline void Project(const Mat34 &P, const Mat3X &X, const Vecu &ids, Mat2X *x) {
|
||||
x->resize(2, ids.size());
|
||||
Vec4 HX;
|
||||
Vec3 hx;
|
||||
for (int c = 0; c < ids.size(); ++c) {
|
||||
HX << X.col(ids[c]), 1.0;
|
||||
hx = P * HX;
|
||||
x->col(c) = hx.head<2>() / hx(2);
|
||||
}
|
||||
}
|
||||
|
||||
inline Mat2X Project(const Mat34 &P, const Mat3X &X) {
|
||||
Mat2X x(2, X.cols());
|
||||
Project(P, X, &x);
|
||||
return x;
|
||||
}
|
||||
|
||||
inline Mat2X Project(const Mat34 &P, const Mat3X &X, const Vecu &ids) {
|
||||
Mat2X x(2, ids.size());
|
||||
Project(P, X, ids, &x);
|
||||
return x;
|
||||
}
|
||||
|
||||
double Depth(const Mat3 &R, const Vec3 &t, const Vec3 &X);
|
||||
double Depth(const Mat3 &R, const Vec3 &t, const Vec4 &X);
|
||||
|
||||
/**
|
||||
* Returns true if the homogenious 3D point X is in front of
|
||||
* the camera P.
|
||||
*/
|
||||
inline bool isInFrontOfCamera(const Mat34 &P, const Vec4 &X) {
|
||||
double condition_1 = P.row(2).dot(X) * X[3];
|
||||
double condition_2 = X[2] * X[3];
|
||||
if (condition_1 > 0 && condition_2 > 0)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
inline bool isInFrontOfCamera(const Mat34 &P, const Vec3 &X) {
|
||||
Vec4 X_homo;
|
||||
X_homo.segment<3>(0) = X;
|
||||
X_homo(3) = 1;
|
||||
return isInFrontOfCamera( P, X_homo);
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms a 2D point from pixel image coordinates to a 2D point in
|
||||
* normalized image coordinates.
|
||||
*/
|
||||
inline Vec2 ImageToNormImageCoordinates(Mat3 &Kinverse, Vec2 &x) {
|
||||
Vec3 x_h = Kinverse*EuclideanToHomogeneous(x);
|
||||
return HomogeneousToEuclidean( x_h );
|
||||
}
|
||||
|
||||
/// Estimates the root mean square error (2D)
|
||||
inline double RootMeanSquareError(const Mat2X &x_image,
|
||||
const Mat4X &X_world,
|
||||
const Mat34 &P) {
|
||||
size_t num_points = x_image.cols();
|
||||
Mat2X dx = Project(P, X_world) - x_image;
|
||||
return dx.norm() / num_points;
|
||||
}
|
||||
|
||||
/// Estimates the root mean square error (2D)
|
||||
inline double RootMeanSquareError(const Mat2X &x_image,
|
||||
const Mat3X &X_world,
|
||||
const Mat3 &K,
|
||||
const Mat3 &R,
|
||||
const Vec3 &t) {
|
||||
Mat34 P;
|
||||
P_From_KRt(K, R, t, &P);
|
||||
size_t num_points = x_image.cols();
|
||||
Mat2X dx = Project(P, X_world) - x_image;
|
||||
return dx.norm() / num_points;
|
||||
}
|
||||
} // namespace libmv
|
||||
|
||||
#endif // LIBMV_MULTIVIEW_PROJECTION_H_
|
||||
@@ -0,0 +1,63 @@
|
||||
// Copyright (c) 2009 libmv authors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
|
||||
#ifndef LIBMV_MULTIVIEW_RANDOM_SAMPLE_H_
|
||||
#define LIBMV_MULTIVIEW_RANDOM_SAMPLE_H_
|
||||
|
||||
#include "libmv/base/vector.h"
|
||||
#include "libmv/logging/logging.h"
|
||||
|
||||
namespace libmv {
|
||||
|
||||
/*!
|
||||
Pick a random subset of the integers [0, total), in random order. Note that
|
||||
this can behave badly if num_samples is close to total; runtime could be
|
||||
unlimited!
|
||||
|
||||
This uses a quadratic rejection strategy and should only be used for small
|
||||
num_samples.
|
||||
|
||||
\param num_samples The number of samples to produce.
|
||||
\param total_samples The number of samples available.
|
||||
\param samples num_samples of numbers in [0, total_samples) is placed
|
||||
here on return.
|
||||
*/
|
||||
static void UniformSample(int num_samples,
|
||||
int total_samples,
|
||||
vector<int> *samples) {
|
||||
samples->resize(0);
|
||||
while (samples->size() < num_samples) {
|
||||
int sample = rand() % total_samples;
|
||||
bool found = false;
|
||||
for (int j = 0; j < samples->size(); ++j) {
|
||||
found = (*samples)[j] == sample;
|
||||
if (found) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
samples->push_back(sample);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace libmv
|
||||
|
||||
#endif // LIBMV_MULTIVIEW_RANDOM_SAMPLE_H_
|
||||
@@ -0,0 +1,62 @@
|
||||
// Copyright (c) 2009 libmv authors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//
|
||||
// Compute the projection matrix from a set of 3D points X and their
|
||||
// projections x = PX in 2D. This is useful if a point cloud is reconstructed.
|
||||
//
|
||||
// Algorithm is the standard DLT as described in Hartley & Zisserman, page 179.
|
||||
|
||||
#ifndef LIBMV_MULTIVIEW_RESECTION_H
|
||||
#define LIBMV_MULTIVIEW_RESECTION_H
|
||||
|
||||
#include "libmv/logging/logging.h"
|
||||
#include "libmv/numeric/numeric.h"
|
||||
|
||||
namespace libmv {
|
||||
namespace resection {
|
||||
|
||||
// x's are 2D image coordinates, (x,y,1), and X's are homogeneous four vectors.
|
||||
template<typename T>
|
||||
void Resection(const Matrix<T, 2, Dynamic> &x,
|
||||
const Matrix<T, 4, Dynamic> &X,
|
||||
Matrix<T, 3, 4> *P) {
|
||||
int N = x.cols();
|
||||
assert(X.cols() == N);
|
||||
|
||||
Matrix<T, Dynamic, 12> design(2*N, 12);
|
||||
design.setZero();
|
||||
for (int i = 0; i < N; i++) {
|
||||
T xi = x(0, i);
|
||||
T yi = x(1, i);
|
||||
// See equation (7.2) on page 179 of H&Z.
|
||||
design.template block<1, 4>(2*i, 4) = -X.col(i).transpose();
|
||||
design.template block<1, 4>(2*i, 8) = yi*X.col(i).transpose();
|
||||
design.template block<1, 4>(2*i + 1, 0) = X.col(i).transpose();
|
||||
design.template block<1, 4>(2*i + 1, 8) = -xi*X.col(i).transpose();
|
||||
}
|
||||
Matrix<T, 12, 1> p;
|
||||
Nullspace(&design, &p);
|
||||
reshape(p, 3, 4, P);
|
||||
}
|
||||
|
||||
} // namespace resection
|
||||
} // namespace libmv
|
||||
|
||||
#endif // LIBMV_MULTIVIEW_RESECTION_H
|
||||
@@ -0,0 +1,66 @@
|
||||
// Copyright (c) 2009 libmv authors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
|
||||
#ifndef LIBMV_MULTIVIEW_RESECTION_KERNEL_H
|
||||
#define LIBMV_MULTIVIEW_RESECTION_KERNEL_H
|
||||
|
||||
#include "libmv/base/vector.h"
|
||||
#include "libmv/logging/logging.h"
|
||||
#include "libmv/multiview/resection.h"
|
||||
#include "libmv/multiview/projection.h"
|
||||
#include "libmv/numeric/numeric.h"
|
||||
|
||||
namespace libmv {
|
||||
namespace resection {
|
||||
namespace kernel {
|
||||
|
||||
class Kernel {
|
||||
public:
|
||||
typedef Mat34 Model;
|
||||
enum { MINIMUM_SAMPLES = 6 };
|
||||
|
||||
Kernel(const Mat2X &x, const Mat4X &X) : x_(x), X_(X) {
|
||||
CHECK(x.cols() == X.cols());
|
||||
}
|
||||
void Fit(const vector<int> &samples, vector<Model> *models) const {
|
||||
Mat2X x = ExtractColumns(x_, samples);
|
||||
Mat4X X = ExtractColumns(X_, samples);
|
||||
Mat34 P;
|
||||
Resection(x, X, &P);
|
||||
models->push_back(P);
|
||||
}
|
||||
double Error(int sample, const Model &model) const {
|
||||
Mat4X X = X_.col(sample);
|
||||
Mat2X error = Project(model, X) - x_.col(sample);
|
||||
return error.col(0).squaredNorm();
|
||||
}
|
||||
int NumSamples() const {
|
||||
return x_.cols();
|
||||
}
|
||||
private:
|
||||
const Mat2X &x_;
|
||||
const Mat4X &X_;
|
||||
};
|
||||
|
||||
} // namespace kernel
|
||||
} // namespace resection
|
||||
} // namespace libmv
|
||||
|
||||
#endif // LIBMV_MULTIVIEW_RESECTION_KERNEL_H
|
||||
@@ -0,0 +1,31 @@
|
||||
// Copyright (c) 2007, 2008 libmv authors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
|
||||
#include <cmath>
|
||||
#include <cstdio>
|
||||
#include <algorithm>
|
||||
#include <set>
|
||||
|
||||
#include "libmv/multiview/robust_estimation.h"
|
||||
#include "libmv/numeric/numeric.h"
|
||||
|
||||
namespace libmv {
|
||||
|
||||
} // namespace libmv
|
||||
@@ -0,0 +1,154 @@
|
||||
// Copyright (c) 2007, 2008 libmv authors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
|
||||
#ifndef LIBMV_MULTIVIEW_ROBUST_ESTIMATION_H_
|
||||
#define LIBMV_MULTIVIEW_ROBUST_ESTIMATION_H_
|
||||
|
||||
#include <set>
|
||||
|
||||
#include "libmv/base/vector.h"
|
||||
#include "libmv/logging/logging.h"
|
||||
#include "libmv/multiview/random_sample.h"
|
||||
#include "libmv/numeric/numeric.h"
|
||||
|
||||
namespace libmv {
|
||||
|
||||
template<typename Kernel>
|
||||
class MLEScorer {
|
||||
public:
|
||||
MLEScorer(double threshold) : threshold_(threshold) {}
|
||||
double Score(const Kernel &kernel,
|
||||
const typename Kernel::Model &model,
|
||||
const vector<int> &samples,
|
||||
vector<int> *inliers) const {
|
||||
double cost = 0.0;
|
||||
for (int j = 0; j < samples.size(); ++j) {
|
||||
double error = kernel.Error(samples[j], model);
|
||||
if (error < threshold_) {
|
||||
cost += error;
|
||||
inliers->push_back(samples[j]);
|
||||
} else {
|
||||
cost += threshold_;
|
||||
}
|
||||
}
|
||||
return cost;
|
||||
}
|
||||
private:
|
||||
double threshold_;
|
||||
};
|
||||
|
||||
static unsigned int IterationsRequired(int min_samples,
|
||||
double outliers_probability,
|
||||
double inlier_ratio) {
|
||||
return static_cast<unsigned int>(
|
||||
log(outliers_probability) / log(1.0 - pow(inlier_ratio, min_samples)));
|
||||
}
|
||||
|
||||
// 1. The model.
|
||||
// 2. The minimum number of samples needed to fit.
|
||||
// 3. A way to convert samples to a model.
|
||||
// 4. A way to convert samples and a model to an error.
|
||||
//
|
||||
// 1. Kernel::Model
|
||||
// 2. Kernel::MINIMUM_SAMPLES
|
||||
// 3. Kernel::Fit(vector<int>, vector<Kernel::Model> *)
|
||||
// 4. Kernel::Error(Model, int) -> error
|
||||
template<typename Kernel, typename Scorer>
|
||||
typename Kernel::Model Estimate(const Kernel &kernel,
|
||||
const Scorer &scorer,
|
||||
vector<int> *best_inliers = NULL,
|
||||
double *best_score = NULL,
|
||||
double outliers_probability = 1e-2) {
|
||||
CHECK(outliers_probability < 1.0);
|
||||
CHECK(outliers_probability > 0.0);
|
||||
size_t iteration = 0;
|
||||
const size_t min_samples = Kernel::MINIMUM_SAMPLES;
|
||||
const size_t total_samples = kernel.NumSamples();
|
||||
|
||||
size_t max_iterations = 100;
|
||||
const size_t really_max_iterations = 1000;
|
||||
|
||||
int best_num_inliers = 0;
|
||||
double best_cost = HUGE_VAL;
|
||||
double best_inlier_ratio = 0.0;
|
||||
typename Kernel::Model best_model;
|
||||
|
||||
// Test if we have sufficient points to for the kernel.
|
||||
if (total_samples < min_samples) {
|
||||
if (best_inliers) {
|
||||
best_inliers->resize(0);
|
||||
}
|
||||
return best_model;
|
||||
}
|
||||
|
||||
// In this robust estimator, the scorer always works on all the data points
|
||||
// at once. So precompute the list ahead of time.
|
||||
vector<int> all_samples;
|
||||
for (int i = 0; i < total_samples; ++i) {
|
||||
all_samples.push_back(i);
|
||||
}
|
||||
|
||||
vector<int> sample;
|
||||
for (iteration = 0;
|
||||
iteration < max_iterations &&
|
||||
iteration < really_max_iterations; ++iteration) {
|
||||
UniformSample(min_samples, total_samples, &sample);
|
||||
|
||||
vector<typename Kernel::Model> models;
|
||||
kernel.Fit(sample, &models);
|
||||
VLOG(4) << "Fitted subset; found " << models.size() << " model(s).";
|
||||
|
||||
// Compute costs for each fit.
|
||||
for (int i = 0; i < models.size(); ++i) {
|
||||
vector<int> inliers;
|
||||
double cost = scorer.Score(kernel, models[i], all_samples, &inliers);
|
||||
VLOG(5) << "Fit cost: " << cost
|
||||
<< ", number of inliers: " << inliers.size();
|
||||
|
||||
if (cost < best_cost) {
|
||||
best_cost = cost;
|
||||
best_inlier_ratio = inliers.size() / double(total_samples);
|
||||
best_num_inliers = inliers.size();
|
||||
best_model = models[i];
|
||||
if (best_inliers) {
|
||||
best_inliers->swap(inliers);
|
||||
}
|
||||
VLOG(4) << "New best cost: " << best_cost << " with "
|
||||
<< best_num_inliers << " inlying of "
|
||||
<< total_samples << " total samples.";
|
||||
}
|
||||
if (best_inlier_ratio) {
|
||||
max_iterations = IterationsRequired(min_samples,
|
||||
outliers_probability,
|
||||
best_inlier_ratio);
|
||||
}
|
||||
|
||||
VLOG(5) << "Max iterations needed given best inlier ratio: "
|
||||
<< max_iterations << "; best inlier ratio: " << best_inlier_ratio;
|
||||
}
|
||||
}
|
||||
if (best_score)
|
||||
*best_score = best_cost;
|
||||
return best_model;
|
||||
}
|
||||
|
||||
} // namespace libmv
|
||||
|
||||
#endif // LIBMV_MULTIVIEW_ROBUST_ESTIMATION_H_
|
||||
@@ -0,0 +1,69 @@
|
||||
// Copyright (c) 2007, 2008 libmv authors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
|
||||
#include "libmv/multiview/fundamental_kernel.h"
|
||||
#include "libmv/multiview/robust_estimation.h"
|
||||
#include "libmv/multiview/robust_fundamental.h"
|
||||
#include "libmv/numeric/numeric.h"
|
||||
|
||||
namespace libmv {
|
||||
|
||||
// TODO(keir): This interface is a bit ugly; consider fixing it.
|
||||
double FundamentalFromCorrespondences8PointRobust(const Mat &x1,
|
||||
const Mat &x2,
|
||||
double max_error,
|
||||
Mat3 *F,
|
||||
vector<int> *inliers,
|
||||
double outliers_probability) {
|
||||
// The threshold is on the sum of the squared errors in the two images.
|
||||
// Actually, Sampson's approximation of this error.
|
||||
double threshold = 2 * Square(max_error);
|
||||
double best_score = HUGE_VAL;
|
||||
typedef fundamental::kernel::NormalizedEightPointKernel Kernel;
|
||||
Kernel kernel(x1, x2);
|
||||
*F = Estimate(kernel, MLEScorer<Kernel>(threshold), inliers,
|
||||
&best_score, outliers_probability);
|
||||
if (best_score == HUGE_VAL)
|
||||
return HUGE_VAL;
|
||||
else
|
||||
return std::sqrt(best_score / 2.0);
|
||||
}
|
||||
|
||||
double FundamentalFromCorrespondences7PointRobust(const Mat &x1,
|
||||
const Mat &x2,
|
||||
double max_error,
|
||||
Mat3 * F,
|
||||
vector<int> *inliers,
|
||||
double outliers_probability) {
|
||||
// The threshold is on the sum of the squared errors in the two images.
|
||||
// Actually, Sampson's approximation of this error.
|
||||
double threshold = 2 * Square(max_error);
|
||||
double best_score = HUGE_VAL;
|
||||
typedef fundamental::kernel::NormalizedSevenPointKernel Kernel;
|
||||
Kernel kernel(x1, x2);
|
||||
*F = Estimate(kernel, MLEScorer<Kernel>(threshold), inliers,
|
||||
&best_score, outliers_probability);
|
||||
if (best_score == HUGE_VAL)
|
||||
return HUGE_VAL;
|
||||
else
|
||||
return std::sqrt(best_score / 2.0);
|
||||
}
|
||||
|
||||
} // namespace libmv
|
||||
@@ -0,0 +1,53 @@
|
||||
// Copyright (c) 2007, 2008 libmv authors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
|
||||
#ifndef LIBMV_MULTIVIEW_ROBUST_FUNDAMENTAL_H_
|
||||
#define LIBMV_MULTIVIEW_ROBUST_FUNDAMENTAL_H_
|
||||
|
||||
#include "libmv/base/vector.h"
|
||||
#include "libmv/numeric/numeric.h"
|
||||
|
||||
namespace libmv {
|
||||
|
||||
// Estimate robustly the fundamental matrix between two dataset of 2D point
|
||||
// (image coords space). The fundamental solver relies on the 8 point solution.
|
||||
// Returns the score associated to the solution F
|
||||
double FundamentalFromCorrespondences8PointRobust(
|
||||
const Mat &x1,
|
||||
const Mat &x2,
|
||||
double max_error,
|
||||
Mat3 *F,
|
||||
vector<int> *inliers = NULL,
|
||||
double outliers_probability = 1e-2);
|
||||
|
||||
// Estimate robustly the fundamental matrix between two dataset of 2D point
|
||||
// (image coords space). The fundamental solver relies on the 7 point solution.
|
||||
// Returns the score associated to the solution F
|
||||
double FundamentalFromCorrespondences7PointRobust(
|
||||
const Mat &x1,
|
||||
const Mat &x2,
|
||||
double max_error,
|
||||
Mat3 * F,
|
||||
vector<int> *inliers = NULL,
|
||||
double outliers_probability = 1e-2);
|
||||
|
||||
} // namespace libmv
|
||||
|
||||
#endif // LIBMV_MULTIVIEW_ROBUST_FUNDAMENTAL_H_
|
||||
@@ -0,0 +1,48 @@
|
||||
// Copyright (c) 2010 libmv authors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
|
||||
#include "libmv/multiview/resection_kernel.h"
|
||||
#include "libmv/multiview/robust_estimation.h"
|
||||
#include "libmv/multiview/robust_resection.h"
|
||||
#include "libmv/numeric/numeric.h"
|
||||
|
||||
namespace libmv {
|
||||
// Estimate robustly the the projection matrix of a uncalibrated
|
||||
// camera from 6 or more 3D points and their images.
|
||||
double ResectionRobust(const Mat2X &x_image,
|
||||
const Mat4X &X_world,
|
||||
double max_error,
|
||||
Mat34 *P,
|
||||
vector<int> *inliers,
|
||||
double outliers_probability) {
|
||||
// The threshold is on the sum of the squared errors.
|
||||
double threshold = Square(max_error);
|
||||
double best_score = HUGE_VAL;
|
||||
typedef libmv::resection::kernel::Kernel Kernel;
|
||||
Kernel kernel(x_image, X_world);
|
||||
*P = Estimate(kernel, MLEScorer<Kernel>(threshold), inliers,
|
||||
&best_score, outliers_probability);
|
||||
if (best_score == HUGE_VAL)
|
||||
return HUGE_VAL;
|
||||
else
|
||||
return std::sqrt(best_score / 2.0);
|
||||
}
|
||||
|
||||
} // namespace libmv
|
||||
@@ -0,0 +1,41 @@
|
||||
// Copyright (c) 2010 libmv authors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
|
||||
#ifndef LIBMV_MULTIVIEW_ROBUST_RESECTION_H_
|
||||
#define LIBMV_MULTIVIEW_ROBUST_RESECTION_H_
|
||||
|
||||
#include "libmv/base/vector.h"
|
||||
#include "libmv/numeric/numeric.h"
|
||||
|
||||
namespace libmv {
|
||||
|
||||
// Estimate robustly the the projection matrix of a uncalibrated
|
||||
// camera from 6 or more 3D points and their images.
|
||||
// Returns the score associated to the solution P
|
||||
double ResectionRobust(const Mat2X &x_image,
|
||||
const Mat4X &X_world,
|
||||
double max_error,
|
||||
Mat34 *P,
|
||||
vector<int> *inliers = NULL,
|
||||
double outliers_probability = 1e-2);
|
||||
|
||||
} // namespace libmv
|
||||
|
||||
#endif // LIBMV_MULTIVIEW_ROBUST_RESECTION_H_
|
||||
@@ -0,0 +1,50 @@
|
||||
// Copyright (c) 2007, 2008 libmv authors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
|
||||
#include "libmv/multiview/triangulation.h"
|
||||
|
||||
#include "libmv/numeric/numeric.h"
|
||||
#include "libmv/multiview/projection.h"
|
||||
|
||||
namespace libmv {
|
||||
|
||||
// HZ 12.2 pag.312
|
||||
void TriangulateDLT(const Mat34 &P1, const Vec2 &x1,
|
||||
const Mat34 &P2, const Vec2 &x2,
|
||||
Vec4 *X_homogeneous) {
|
||||
Mat4 design;
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
design(0, i) = x1(0) * P1(2, i) - P1(0, i);
|
||||
design(1, i) = x1(1) * P1(2, i) - P1(1, i);
|
||||
design(2, i) = x2(0) * P2(2, i) - P2(0, i);
|
||||
design(3, i) = x2(1) * P2(2, i) - P2(1, i);
|
||||
}
|
||||
Nullspace(&design, X_homogeneous);
|
||||
}
|
||||
|
||||
void TriangulateDLT(const Mat34 &P1, const Vec2 &x1,
|
||||
const Mat34 &P2, const Vec2 &x2,
|
||||
Vec3 *X_euclidean) {
|
||||
Vec4 X_homogeneous;
|
||||
TriangulateDLT(P1, x1, P2, x2, &X_homogeneous);
|
||||
HomogeneousToEuclidean(X_homogeneous, X_euclidean);
|
||||
}
|
||||
|
||||
} // namespace libmv
|
||||
@@ -0,0 +1,38 @@
|
||||
// Copyright (c) 2007, 2008 libmv authors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
|
||||
#ifndef LIBMV_MULTIVIEW_TRIANGULATION_H_
|
||||
#define LIBMV_MULTIVIEW_TRIANGULATION_H_
|
||||
|
||||
#include "libmv/numeric/numeric.h"
|
||||
|
||||
namespace libmv {
|
||||
|
||||
void TriangulateDLT(const Mat34 &P1, const Vec2 &x1,
|
||||
const Mat34 &P2, const Vec2 &x2,
|
||||
Vec4 *X_homogeneous);
|
||||
|
||||
void TriangulateDLT(const Mat34 &P1, const Vec2 &x1,
|
||||
const Mat34 &P2, const Vec2 &x2,
|
||||
Vec3 *X_euclidean);
|
||||
|
||||
} // namespace libmv
|
||||
|
||||
#endif // LIBMV_MULTIVIEW_TRIANGULATION_H_
|
||||
@@ -0,0 +1,137 @@
|
||||
// Copyright (c) 2009 libmv authors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
|
||||
#ifndef LIBMV_MULTIVIEW_TWO_VIEW_KERNEL_H_
|
||||
#define LIBMV_MULTIVIEW_TWO_VIEW_KERNEL_H_
|
||||
|
||||
#include "libmv/base/vector.h"
|
||||
#include "libmv/logging/logging.h"
|
||||
#include "libmv/multiview/conditioning.h"
|
||||
#include "libmv/numeric/numeric.h"
|
||||
|
||||
namespace libmv {
|
||||
namespace two_view {
|
||||
namespace kernel {
|
||||
|
||||
template<typename Solver, typename Unnormalizer>
|
||||
struct NormalizedSolver {
|
||||
enum { MINIMUM_SAMPLES = Solver::MINIMUM_SAMPLES };
|
||||
static void Solve(const Mat &x1, const Mat &x2, vector<Mat3> *models) {
|
||||
assert(2 == x1.rows());
|
||||
assert(MINIMUM_SAMPLES <= x1.cols());
|
||||
assert(x1.rows() == x2.rows());
|
||||
assert(x1.cols() == x2.cols());
|
||||
|
||||
// Normalize the data.
|
||||
Mat3 T1, T2;
|
||||
Mat x1_normalized, x2_normalized;
|
||||
NormalizePoints(x1, &x1_normalized, &T1);
|
||||
NormalizePoints(x2, &x2_normalized, &T2);
|
||||
|
||||
Solver::Solve(x1_normalized, x2_normalized, models);
|
||||
|
||||
for (int i = 0; i < models->size(); ++i) {
|
||||
Unnormalizer::Unnormalize(T1, T2, &(*models)[i]);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Solver, typename Unnormalizer>
|
||||
struct IsotropicNormalizedSolver {
|
||||
enum { MINIMUM_SAMPLES = Solver::MINIMUM_SAMPLES };
|
||||
static void Solve(const Mat &x1, const Mat &x2, vector<Mat3> *models) {
|
||||
assert(2 == x1.rows());
|
||||
assert(MINIMUM_SAMPLES <= x1.cols());
|
||||
assert(x1.rows() == x2.rows());
|
||||
assert(x1.cols() == x2.cols());
|
||||
|
||||
// Normalize the data.
|
||||
Mat3 T1, T2;
|
||||
Mat x1_normalized, x2_normalized;
|
||||
NormalizeIsotropicPoints(x1, &x1_normalized, &T1);
|
||||
NormalizeIsotropicPoints(x2, &x2_normalized, &T2);
|
||||
|
||||
Solver::Solve(x1_normalized, x2_normalized, models);
|
||||
|
||||
for (int i = 0; i < models->size(); ++i) {
|
||||
Unnormalizer::Unnormalize(T1, T2, &(*models)[i]);
|
||||
}
|
||||
}
|
||||
};
|
||||
// This is one example (targeted at solvers that operate on correspondences
|
||||
// between two views) that shows the "kernel" part of a robust fitting
|
||||
// problem:
|
||||
//
|
||||
// 1. The model; Mat3 in the case of the F or H matrix.
|
||||
// 2. The minimum number of samples needed to fit; 7 or 8 (or 4).
|
||||
// 3. A way to convert samples to a model.
|
||||
// 4. A way to convert a sample and a model to an error.
|
||||
//
|
||||
// Of particular note is that the kernel does not expose what the samples are.
|
||||
// All the robust fitting algorithm sees is that there is some number of
|
||||
// samples; it is able to fit subsets of them (via the kernel) and check their
|
||||
// error, but can never access the samples themselves.
|
||||
//
|
||||
// The Kernel objects must follow the following concept so that the robust
|
||||
// fitting alogrithm can fit this type of relation:
|
||||
//
|
||||
// 1. Kernel::Model
|
||||
// 2. Kernel::MINIMUM_SAMPLES
|
||||
// 3. Kernel::Fit(vector<int>, vector<Kernel::Model> *)
|
||||
// 4. Kernel::Error(int, Model) -> error
|
||||
//
|
||||
// The fit routine must not clear existing entries in the vector of models; it
|
||||
// should append new solutions to the end.
|
||||
template<typename SolverArg,
|
||||
typename ErrorArg,
|
||||
typename ModelArg = Mat3>
|
||||
class Kernel {
|
||||
public:
|
||||
Kernel(const Mat &x1, const Mat &x2) : x1_(x1), x2_(x2) {}
|
||||
typedef SolverArg Solver;
|
||||
typedef ModelArg Model;
|
||||
enum { MINIMUM_SAMPLES = Solver::MINIMUM_SAMPLES };
|
||||
void Fit(const vector<int> &samples, vector<Model> *models) const {
|
||||
Mat x1 = ExtractColumns(x1_, samples);
|
||||
Mat x2 = ExtractColumns(x2_, samples);
|
||||
Solver::Solve(x1, x2, models);
|
||||
}
|
||||
double Error(int sample, const Model &model) const {
|
||||
return ErrorArg::Error(model,
|
||||
static_cast<Vec>(x1_.col(sample)),
|
||||
static_cast<Vec>(x2_.col(sample)));
|
||||
}
|
||||
int NumSamples() const {
|
||||
return x1_.cols();
|
||||
}
|
||||
static void Solve(const Mat &x1, const Mat &x2, vector<Model> *models) {
|
||||
// By offering this, Kernel types can be passed to templates.
|
||||
Solver::Solve(x1, x2, models);
|
||||
}
|
||||
protected:
|
||||
const Mat &x1_;
|
||||
const Mat &x2_;
|
||||
};
|
||||
|
||||
} // namespace kernel
|
||||
} // namespace two_view
|
||||
} // namespace libmv
|
||||
|
||||
#endif // LIBMV_MULTIVIEW_TWO_VIEW_KERNEL_H_
|
||||
@@ -0,0 +1,90 @@
|
||||
// Copyright (c) 2007, 2008 libmv authors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
|
||||
#include "libmv/numeric/numeric.h"
|
||||
#include "libmv/multiview/projection.h"
|
||||
#include "libmv/multiview/twoviewtriangulation.h"
|
||||
#include "libmv/multiview/projection.h"
|
||||
|
||||
|
||||
namespace libmv {
|
||||
|
||||
void TwoViewTriangulationByPlanes(const Vec3 &x1, const Vec3 &x2,
|
||||
const Mat34 &P, const Mat3 &E,
|
||||
Vec4 *X) {
|
||||
Vec3 a = E.transpose() * x2;
|
||||
Vec3 a0 = a;
|
||||
a0(2) = 0;
|
||||
Vec3 b = x1;
|
||||
b = b.cross(a0);
|
||||
|
||||
Vec3 c = E * x1;
|
||||
c(2) = 0;
|
||||
c = c.cross(x2);
|
||||
Vec4 C = P.transpose() * c;
|
||||
|
||||
Vec3 d = a.cross(b);
|
||||
Vec3 q = d * C[3];
|
||||
(*X)[0] = q[0];
|
||||
(*X)[1] = q[1];
|
||||
(*X)[2] = q[2];
|
||||
(*X)[3] = -(d[0] * C[0] + d[1] * C[1] + d[2] * C[2]);
|
||||
}
|
||||
|
||||
void TwoViewTriangulationByPlanes(const Vec2 &x1, const Vec2 &x2,
|
||||
const Mat34 &P,const Mat3 &E,
|
||||
Vec3 *X) {
|
||||
Vec3 x1_homogenious = EuclideanToHomogeneous(x1);
|
||||
Vec3 x2_homogenious = EuclideanToHomogeneous(x2);
|
||||
Vec4 X_homogenious;
|
||||
TwoViewTriangulationByPlanes(x1_homogenious,
|
||||
x2_homogenious,
|
||||
P, E, &X_homogenious);
|
||||
(*X) = HomogeneousToEuclidean(X_homogenious);
|
||||
}
|
||||
|
||||
void TwoViewTriangulationIdeal(const Vec3 &x1, const Vec3 &x2,
|
||||
const Mat34 &P, const Mat3 &E,
|
||||
Vec4 *X){
|
||||
Vec3 c = E * x1;
|
||||
c(2) = 0;
|
||||
c = c.cross(x2);
|
||||
Vec4 C = P.transpose() * c;
|
||||
|
||||
Vec3 q = x1 * C[3];
|
||||
(*X)[0] = q[0];
|
||||
(*X)[1] = q[1];
|
||||
(*X)[2] = q[2];
|
||||
(*X)[3] = -(x1[0] * C[0] + x1[1] * C[1] + x1[2] * C[2]);
|
||||
}
|
||||
|
||||
void TwoViewTriangulationIdeal(const Vec2 &x1, const Vec2 &x2,
|
||||
const Mat34 &P, const Mat3 &E,
|
||||
Vec3 *X) {
|
||||
Vec3 x1_homogenious = EuclideanToHomogeneous(x1);
|
||||
Vec3 x2_homogenious = EuclideanToHomogeneous(x2);
|
||||
Vec4 X_homogenious;
|
||||
TwoViewTriangulationIdeal(x1_homogenious,
|
||||
x2_homogenious,
|
||||
P, E, &X_homogenious);
|
||||
(*X) = HomogeneousToEuclidean(X_homogenious);
|
||||
}
|
||||
|
||||
} // namespace libmv
|
||||
@@ -0,0 +1,82 @@
|
||||
// Copyright (c) 2010 libmv authors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//
|
||||
// Compute a 3D position of a point from several images of it. In particular,
|
||||
// compute the projective point X in R^4 such that x = PX.
|
||||
//
|
||||
// Algorithm is the standard DLT; for derivation see appendix of Keir's thesis.
|
||||
|
||||
#ifndef LIBMV_TWOVIEW_NVIEWTRIANGULATION_H
|
||||
#define LIBMV_TWOVIEW_NVIEWTRIANGULATION_H
|
||||
|
||||
#include "libmv/numeric/numeric.h"
|
||||
|
||||
namespace libmv {
|
||||
|
||||
/**
|
||||
* Two view triangulation for cameras in canonical form,
|
||||
* where the reference camera is in the form [I|0] and P is in
|
||||
* the form [R|t]. The algorithm minimizes the re-projection error
|
||||
* in the first image only, i.e. the error in the second image is 0
|
||||
* while the point in the first image is the point lying on the
|
||||
* epipolar line that is closest to x1.
|
||||
*
|
||||
* \param x1 The normalized image point in the first camera
|
||||
* (inv(K1)*x1_image)
|
||||
* \param x2 The normalized image point in the second camera
|
||||
* (inv(K2)*x2_image)
|
||||
* \param P The second camera matrix in the form [R|t]
|
||||
* \param E The essential matrix between the two cameras
|
||||
* \param X The 3D homogeneous point
|
||||
*
|
||||
* This is the algorithm described in Appendix A in:
|
||||
* "An efficient solution to the five-point relative pose problem",
|
||||
* by D. Nist\'er, IEEE PAMI, vol. 26
|
||||
*/
|
||||
void TwoViewTriangulationByPlanes(const Vec3 &x1, const Vec3 &x2,
|
||||
const Mat34 &P,const Mat3 &E, Vec4 *X);
|
||||
void TwoViewTriangulationByPlanes(const Vec2 &x1, const Vec2 &x2,
|
||||
const Mat34 &P,const Mat3 &E, Vec3 *X);
|
||||
|
||||
/**
|
||||
* The same algorithm as above generalized for ideal points,
|
||||
* e.i. where x1*E*x2' = 0. This will not work if the points are
|
||||
* not ideal. In the case of measured image points it is best to
|
||||
* either use the TwoViewTriangulationByPlanes function or correct
|
||||
* the points so that they lay on the corresponding epipolar lines.
|
||||
*
|
||||
* \param x1 The normalized image point in the first camera
|
||||
* (inv(K1)*x1_image)
|
||||
* \param x2 The normalized image point in the second camera
|
||||
* (inv(K2)*x2_image)
|
||||
* \param P The second camera matrix in the form [R|t]
|
||||
* \param E The essential matrix between the two cameras
|
||||
* \param X The 3D homogeneous point
|
||||
*/
|
||||
void TwoViewTriangulationIdeal(const Vec3 &x1, const Vec3 &x2,
|
||||
const Mat34 &P, const Mat3 &E,
|
||||
Vec4 *X);
|
||||
void TwoViewTriangulationIdeal(const Vec2 &x1, const Vec2 &x2,
|
||||
const Mat34 &P, const Mat3 &E,
|
||||
Vec3 *X);
|
||||
|
||||
} // namespace libmv
|
||||
|
||||
#endif // LIBMV_MULTIVIEW_RESECTION_H
|
||||
@@ -0,0 +1,14 @@
|
||||
# define the source files
|
||||
SET(NUMERIC_SRC numeric.cc
|
||||
poly.cc)
|
||||
|
||||
# define the header files (make the headers appear in IDEs.)
|
||||
FILE(GLOB NUMERIC_HDRS *.h)
|
||||
|
||||
ADD_LIBRARY(opencv.sfm.numeric STATIC ${NUMERIC_SRC} ${NUMERIC_HDRS})
|
||||
|
||||
IF(TARGET Eigen3::Eigen)
|
||||
TARGET_LINK_LIBRARIES(opencv.sfm.numeric LINK_PUBLIC Eigen3::Eigen)
|
||||
ENDIF()
|
||||
|
||||
LIBMV_INSTALL_LIB(opencv.sfm.numeric)
|
||||
@@ -0,0 +1,107 @@
|
||||
// Copyright (c) 2007, 2008, 2009 libmv authors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
|
||||
#ifndef LIBMV_NUMERIC_DERIVATIVE_H
|
||||
#define LIBMV_NUMERIC_DERIVATIVE_H
|
||||
|
||||
#include <cmath>
|
||||
|
||||
#include "libmv/numeric/numeric.h"
|
||||
#include "libmv/logging/logging.h"
|
||||
|
||||
namespace libmv {
|
||||
|
||||
// Numeric derivative of a function.
|
||||
// TODO(keir): Consider adding a quadratic approximation.
|
||||
|
||||
enum NumericJacobianMode {
|
||||
CENTRAL,
|
||||
FORWARD,
|
||||
};
|
||||
|
||||
template<typename Function, NumericJacobianMode mode = CENTRAL>
|
||||
class NumericJacobian {
|
||||
public:
|
||||
typedef typename Function::XMatrixType Parameters;
|
||||
typedef typename Function::XMatrixType::RealScalar XScalar;
|
||||
typedef typename Function::FMatrixType FMatrixType;
|
||||
typedef Matrix<typename Function::FMatrixType::RealScalar,
|
||||
Function::FMatrixType::RowsAtCompileTime,
|
||||
Function::XMatrixType::RowsAtCompileTime>
|
||||
JMatrixType;
|
||||
|
||||
NumericJacobian(const Function &f) : f_(f) {}
|
||||
|
||||
// TODO(keir): Perhaps passing the jacobian back by value is not a good idea.
|
||||
JMatrixType operator()(const Parameters &x) {
|
||||
// Empirically determined constant.
|
||||
Parameters eps = x.array().abs() * XScalar(1e-5);
|
||||
// To handle cases where a paremeter is exactly zero, instead use the mean
|
||||
// eps for the other dimensions.
|
||||
XScalar mean_eps = eps.sum() / eps.rows();
|
||||
if (mean_eps == XScalar(0)) {
|
||||
// TODO(keir): Do something better here.
|
||||
mean_eps = 1e-8; // ~sqrt(machine precision).
|
||||
}
|
||||
// TODO(keir): Elimininate this needless function evaluation for the
|
||||
// central difference case.
|
||||
FMatrixType fx = f_(x);
|
||||
const int rows = fx.rows();
|
||||
const int cols = x.rows();
|
||||
JMatrixType jacobian(rows, cols);
|
||||
Parameters x_plus_delta = x;
|
||||
for (int c = 0; c < cols; ++c) {
|
||||
if (eps(c) == XScalar(0)) {
|
||||
eps(c) = mean_eps;
|
||||
}
|
||||
x_plus_delta(c) = x(c) + eps(c);
|
||||
jacobian.col(c) = f_(x_plus_delta);
|
||||
|
||||
XScalar one_over_h = 1 / eps(c);
|
||||
if (mode == CENTRAL) {
|
||||
x_plus_delta(c) = x(c) - eps(c);
|
||||
jacobian.col(c) -= f_(x_plus_delta);
|
||||
one_over_h /= 2;
|
||||
} else {
|
||||
jacobian.col(c) -= fx;
|
||||
}
|
||||
x_plus_delta(c) = x(c);
|
||||
jacobian.col(c) = jacobian.col(c) * one_over_h;
|
||||
}
|
||||
return jacobian;
|
||||
}
|
||||
private:
|
||||
const Function &f_;
|
||||
};
|
||||
|
||||
template<typename Function, typename Jacobian>
|
||||
bool CheckJacobian(const Function &f, const typename Function::XMatrixType &x) {
|
||||
Jacobian j_analytic(f);
|
||||
NumericJacobian<Function> j_numeric(f);
|
||||
|
||||
typename NumericJacobian<Function>::JMatrixType J_numeric = j_numeric(x);
|
||||
typename NumericJacobian<Function>::JMatrixType J_analytic = j_analytic(x);
|
||||
LG << J_numeric - J_analytic;
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace libmv
|
||||
|
||||
#endif // LIBMV_NUMERIC_DERIVATIVE_H
|
||||
@@ -0,0 +1,183 @@
|
||||
// Copyright (c) 2007, 2008, 2009 libmv authors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//
|
||||
// A simple implementation of levenberg marquardt.
|
||||
//
|
||||
// [1] K. Madsen, H. Nielsen, O. Tingleoff. Methods for Non-linear Least
|
||||
// Squares Problems.
|
||||
// http://www2.imm.dtu.dk/pubdb/views/edoc_download.php/3215/pdf/imm3215.pdf
|
||||
//
|
||||
// TODO(keir): Cite the Lourakis' dogleg paper.
|
||||
|
||||
#ifndef LIBMV_NUMERIC_LEVENBERG_MARQUARDT_H
|
||||
#define LIBMV_NUMERIC_LEVENBERG_MARQUARDT_H
|
||||
|
||||
#include <cmath>
|
||||
|
||||
#include "libmv/numeric/numeric.h"
|
||||
#include "libmv/numeric/function_derivative.h"
|
||||
#include "libmv/logging/logging.h"
|
||||
|
||||
namespace libmv {
|
||||
|
||||
template<typename Function,
|
||||
typename Jacobian = NumericJacobian<Function>,
|
||||
typename Solver = Eigen::PartialPivLU<
|
||||
Matrix<typename Function::FMatrixType::RealScalar,
|
||||
Function::XMatrixType::RowsAtCompileTime,
|
||||
Function::XMatrixType::RowsAtCompileTime> > >
|
||||
class LevenbergMarquardt {
|
||||
public:
|
||||
typedef typename Function::XMatrixType::RealScalar Scalar;
|
||||
typedef typename Function::FMatrixType FVec;
|
||||
typedef typename Function::XMatrixType Parameters;
|
||||
typedef Matrix<typename Function::FMatrixType::RealScalar,
|
||||
Function::FMatrixType::RowsAtCompileTime,
|
||||
Function::XMatrixType::RowsAtCompileTime> JMatrixType;
|
||||
typedef Matrix<typename JMatrixType::RealScalar,
|
||||
JMatrixType::ColsAtCompileTime,
|
||||
JMatrixType::ColsAtCompileTime> AMatrixType;
|
||||
|
||||
// TODO(keir): Some of these knobs can be derived from each other and
|
||||
// removed, instead of requiring the user to set them.
|
||||
enum Status {
|
||||
RUNNING,
|
||||
GRADIENT_TOO_SMALL, // eps > max(J'*f(x))
|
||||
RELATIVE_STEP_SIZE_TOO_SMALL, // eps > ||dx|| / ||x||
|
||||
ERROR_TOO_SMALL, // eps > ||f(x)||
|
||||
HIT_MAX_ITERATIONS,
|
||||
};
|
||||
|
||||
LevenbergMarquardt(const Function &f)
|
||||
: f_(f), df_(f) {}
|
||||
|
||||
struct SolverParameters {
|
||||
SolverParameters()
|
||||
: gradient_threshold(1e-16),
|
||||
relative_step_threshold(1e-16),
|
||||
error_threshold(1e-16),
|
||||
initial_scale_factor(1e-3),
|
||||
max_iterations(100) {}
|
||||
Scalar gradient_threshold; // eps > max(J'*f(x))
|
||||
Scalar relative_step_threshold; // eps > ||dx|| / ||x||
|
||||
Scalar error_threshold; // eps > ||f(x)||
|
||||
Scalar initial_scale_factor; // Initial u for solving normal equations.
|
||||
int max_iterations; // Maximum number of solver iterations.
|
||||
};
|
||||
|
||||
struct Results {
|
||||
Scalar error_magnitude; // ||f(x)||
|
||||
Scalar gradient_magnitude; // ||J'f(x)||
|
||||
int iterations;
|
||||
Status status;
|
||||
};
|
||||
|
||||
Status Update(const Parameters &x, const SolverParameters ¶ms,
|
||||
JMatrixType *J, AMatrixType *A, FVec *error, Parameters *g) {
|
||||
*J = df_(x);
|
||||
*A = (*J).transpose() * (*J);
|
||||
*error = -f_(x);
|
||||
*g = (*J).transpose() * *error;
|
||||
if (g->array().abs().maxCoeff() < params.gradient_threshold) {
|
||||
return GRADIENT_TOO_SMALL;
|
||||
} else if (error->norm() < params.error_threshold) {
|
||||
return ERROR_TOO_SMALL;
|
||||
}
|
||||
return RUNNING;
|
||||
}
|
||||
|
||||
Results minimize(Parameters *x_and_min) {
|
||||
SolverParameters params;
|
||||
minimize(params, x_and_min);
|
||||
}
|
||||
|
||||
Results minimize(const SolverParameters ¶ms, Parameters *x_and_min) {
|
||||
Parameters &x = *x_and_min;
|
||||
JMatrixType J;
|
||||
AMatrixType A;
|
||||
FVec error;
|
||||
Parameters g;
|
||||
|
||||
Results results;
|
||||
results.status = Update(x, params, &J, &A, &error, &g);
|
||||
|
||||
Scalar u = Scalar(params.initial_scale_factor*A.diagonal().maxCoeff());
|
||||
Scalar v = 2;
|
||||
|
||||
Parameters dx, x_new;
|
||||
int i;
|
||||
for (i = 0; results.status == RUNNING && i < params.max_iterations; ++i) {
|
||||
VLOG(3) << "iteration: " << i;
|
||||
VLOG(3) << "||f(x)||: " << f_(x).norm();
|
||||
VLOG(3) << "max(g): " << g.array().abs().maxCoeff();
|
||||
VLOG(3) << "u: " << u;
|
||||
VLOG(3) << "v: " << v;
|
||||
|
||||
AMatrixType A_augmented = A + u*AMatrixType::Identity(J.cols(), J.cols());
|
||||
Solver solver(A_augmented);
|
||||
dx = solver.solve(g);
|
||||
bool solved = (A_augmented * dx).isApprox(g);
|
||||
if (!solved) {
|
||||
LOG(ERROR) << "Failed to solve";
|
||||
}
|
||||
if (solved && dx.norm() <= params.relative_step_threshold * x.norm()) {
|
||||
results.status = RELATIVE_STEP_SIZE_TOO_SMALL;
|
||||
break;
|
||||
}
|
||||
if (solved) {
|
||||
x_new = x + dx;
|
||||
// Rho is the ratio of the actual reduction in error to the reduction
|
||||
// in error that would be obtained if the problem was linear.
|
||||
// See [1] for details.
|
||||
Scalar rho((error.squaredNorm() - f_(x_new).squaredNorm())
|
||||
/ dx.dot(u*dx + g));
|
||||
if (rho > 0) {
|
||||
// Accept the Gauss-Newton step because the linear model fits well.
|
||||
x = x_new;
|
||||
results.status = Update(x, params, &J, &A, &error, &g);
|
||||
Scalar tmp = Scalar(2*rho-1);
|
||||
u = u*std::max(1/3., 1 - (tmp*tmp*tmp));
|
||||
v = 2;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
// Reject the update because either the normal equations failed to solve
|
||||
// or the local linear model was not good (rho < 0). Instead, increase u
|
||||
// to move closer to gradient descent.
|
||||
u *= v;
|
||||
v *= 2;
|
||||
}
|
||||
if (results.status == RUNNING) {
|
||||
results.status = HIT_MAX_ITERATIONS;
|
||||
}
|
||||
results.error_magnitude = error.norm();
|
||||
results.gradient_magnitude = g.norm();
|
||||
results.iterations = i;
|
||||
return results;
|
||||
}
|
||||
|
||||
private:
|
||||
const Function &f_;
|
||||
Jacobian df_;
|
||||
};
|
||||
|
||||
} // namespace mv
|
||||
|
||||
#endif // LIBMV_NUMERIC_LEVENBERG_MARQUARDT_H
|
||||
@@ -0,0 +1,136 @@
|
||||
// Copyright (c) 2007, 2008 libmv authors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
|
||||
|
||||
#include "libmv/numeric/numeric.h"
|
||||
|
||||
namespace libmv {
|
||||
|
||||
Mat3 RotationAroundX(double angle) {
|
||||
double c, s;
|
||||
sincos(angle, &s, &c);
|
||||
Mat3 R;
|
||||
R << 1, 0, 0,
|
||||
0, c, -s,
|
||||
0, s, c;
|
||||
return R;
|
||||
}
|
||||
|
||||
Mat3 RotationAroundY(double angle) {
|
||||
double c, s;
|
||||
sincos(angle, &s, &c);
|
||||
Mat3 R;
|
||||
R << c, 0, s,
|
||||
0, 1, 0,
|
||||
-s, 0, c;
|
||||
return R;
|
||||
}
|
||||
|
||||
Mat3 RotationAroundZ(double angle) {
|
||||
double c, s;
|
||||
sincos(angle, &s, &c);
|
||||
Mat3 R;
|
||||
R << c, -s, 0,
|
||||
s, c, 0,
|
||||
0, 0, 1;
|
||||
return R;
|
||||
}
|
||||
|
||||
|
||||
Mat3 RotationRodrigues(const Vec3 &axis) {
|
||||
double theta = axis.norm();
|
||||
Vec3 w = axis / theta;
|
||||
Mat3 W = CrossProductMatrix(w);
|
||||
|
||||
return Mat3::Identity() + sin(theta) * W + (1 - cos(theta)) * W * W;
|
||||
}
|
||||
|
||||
|
||||
Mat3 LookAt(Vec3 center) {
|
||||
Vec3 zc = center.normalized();
|
||||
Vec3 xc = Vec3::UnitY().cross(zc).normalized();
|
||||
Vec3 yc = zc.cross(xc);
|
||||
Mat3 R;
|
||||
R.row(0) = xc;
|
||||
R.row(1) = yc;
|
||||
R.row(2) = zc;
|
||||
return R;
|
||||
}
|
||||
|
||||
Mat3 CrossProductMatrix(const Vec3 &x) {
|
||||
Mat3 X;
|
||||
X << 0, -x(2), x(1),
|
||||
x(2), 0, -x(0),
|
||||
-x(1), x(0), 0;
|
||||
return X;
|
||||
}
|
||||
|
||||
void MeanAndVarianceAlongRows(const Mat &A,
|
||||
Vec *mean_pointer,
|
||||
Vec *variance_pointer) {
|
||||
Vec &mean = *mean_pointer;
|
||||
Vec &variance = *variance_pointer;
|
||||
int n = A.rows();
|
||||
int m = A.cols();
|
||||
mean.resize(n);
|
||||
variance.resize(n);
|
||||
|
||||
for (int i = 0; i < n; ++i) {
|
||||
mean(i) = 0;
|
||||
variance(i) = 0;
|
||||
for (int j = 0; j < m; ++j) {
|
||||
double x = A(i, j);
|
||||
mean(i) += x;
|
||||
variance(i) += x * x;
|
||||
}
|
||||
}
|
||||
|
||||
mean /= m;
|
||||
for (int i = 0; i < n; ++i) {
|
||||
variance(i) = variance(i) / m - Square(mean(i));
|
||||
}
|
||||
}
|
||||
|
||||
void HorizontalStack(const Mat &left, const Mat &right, Mat *stacked) {
|
||||
assert(left.rows() == left.rows());
|
||||
int n = left.rows();
|
||||
int m1 = left.cols();
|
||||
int m2 = right.cols();
|
||||
|
||||
stacked->resize(n, m1 + m2);
|
||||
stacked->block(0, 0, n, m1) = left;
|
||||
stacked->block(0, m1, n, m2) = right;
|
||||
}
|
||||
|
||||
void MatrixColumn(const Mat &A, int i, Vec2 *v) {
|
||||
assert(A.rows() == 2);
|
||||
*v << A(0, i), A(1, i);
|
||||
}
|
||||
void MatrixColumn(const Mat &A, int i, Vec3 *v) {
|
||||
assert(A.rows() == 3);
|
||||
*v << A(0, i), A(1, i), A(2, i);
|
||||
}
|
||||
void MatrixColumn(const Mat &A, int i, Vec4 *v) {
|
||||
assert(A.rows() == 4);
|
||||
*v << A(0, i), A(1, i), A(2, i), A(3, i);
|
||||
}
|
||||
|
||||
} // namespace libmv
|
||||
|
||||
@@ -0,0 +1,503 @@
|
||||
// Copyright (c) 2007, 2008 libmv authors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//
|
||||
// Matrix and vector classes, based on Eigen2.
|
||||
//
|
||||
// Avoid using Eigen2 classes directly; instead typedef them here.
|
||||
|
||||
#ifndef LIBMV_NUMERIC_NUMERIC_H
|
||||
#define LIBMV_NUMERIC_NUMERIC_H
|
||||
|
||||
#include <Eigen/Cholesky>
|
||||
#include <Eigen/Core>
|
||||
#include <Eigen/Eigenvalues>
|
||||
#include <Eigen/Geometry>
|
||||
#include <Eigen/LU>
|
||||
#include <Eigen/QR>
|
||||
#include <Eigen/SVD>
|
||||
#include <cassert>
|
||||
|
||||
#if !defined(__MINGW32__)
|
||||
# if defined(_WIN32) || defined(__APPLE__) || \
|
||||
defined(__FreeBSD__) || defined(__NetBSD__)
|
||||
static void sincos(double x, double *sinx, double *cosx) {
|
||||
*sinx = sin(x);
|
||||
*cosx = cos(x);
|
||||
}
|
||||
# endif
|
||||
#endif // !__MINGW32__
|
||||
|
||||
#if (defined(_WIN32)) && !defined(__MINGW32__)
|
||||
inline long lround(double d) {
|
||||
return (long)(d>0 ? d+0.5 : ceil(d-0.5));
|
||||
}
|
||||
# if _MSC_VER < 1800
|
||||
inline int round(double d) {
|
||||
return (d>0) ? int(d+0.5) : int(d-0.5);
|
||||
}
|
||||
# endif // _MSC_VER < 1800
|
||||
typedef unsigned int uint;
|
||||
#endif // _WIN32
|
||||
|
||||
namespace libmv {
|
||||
|
||||
typedef Eigen::MatrixXd Mat;
|
||||
typedef Eigen::VectorXd Vec;
|
||||
|
||||
typedef Eigen::MatrixXf Matf;
|
||||
typedef Eigen::VectorXf Vecf;
|
||||
|
||||
typedef Eigen::Matrix<unsigned int, Eigen::Dynamic, Eigen::Dynamic> Matu;
|
||||
typedef Eigen::Matrix<unsigned int, Eigen::Dynamic, 1> Vecu;
|
||||
typedef Eigen::Matrix<unsigned int, 2, 1> Vec2u;
|
||||
|
||||
typedef Eigen::Matrix<double, 2, 2> Mat2;
|
||||
typedef Eigen::Matrix<double, 2, 3> Mat23;
|
||||
typedef Eigen::Matrix<double, 3, 3> Mat3;
|
||||
typedef Eigen::Matrix<double, 3, 4> Mat34;
|
||||
typedef Eigen::Matrix<double, 3, 5> Mat35;
|
||||
typedef Eigen::Matrix<double, 4, 1> Mat41;
|
||||
typedef Eigen::Matrix<double, 4, 3> Mat43;
|
||||
typedef Eigen::Matrix<double, 4, 4> Mat4;
|
||||
typedef Eigen::Matrix<double, 4, 6> Mat46;
|
||||
typedef Eigen::Matrix<float, 2, 2> Mat2f;
|
||||
typedef Eigen::Matrix<float, 2, 3> Mat23f;
|
||||
typedef Eigen::Matrix<float, 3, 3> Mat3f;
|
||||
typedef Eigen::Matrix<float, 3, 4> Mat34f;
|
||||
typedef Eigen::Matrix<float, 3, 5> Mat35f;
|
||||
typedef Eigen::Matrix<float, 4, 3> Mat43f;
|
||||
typedef Eigen::Matrix<float, 4, 4> Mat4f;
|
||||
typedef Eigen::Matrix<float, 4, 6> Mat46f;
|
||||
|
||||
typedef Eigen::Matrix<double, 3, 3, Eigen::RowMajor> RMat3;
|
||||
typedef Eigen::Matrix<double, 4, 4, Eigen::RowMajor> RMat4;
|
||||
|
||||
typedef Eigen::Matrix<double, 2, Eigen::Dynamic> Mat2X;
|
||||
typedef Eigen::Matrix<double, 3, Eigen::Dynamic> Mat3X;
|
||||
typedef Eigen::Matrix<double, 4, Eigen::Dynamic> Mat4X;
|
||||
typedef Eigen::Matrix<double, Eigen::Dynamic, 2> MatX2;
|
||||
typedef Eigen::Matrix<double, Eigen::Dynamic, 3> MatX3;
|
||||
typedef Eigen::Matrix<double, Eigen::Dynamic, 4> MatX4;
|
||||
typedef Eigen::Matrix<double, Eigen::Dynamic, 5> MatX5;
|
||||
typedef Eigen::Matrix<double, Eigen::Dynamic, 6> MatX6;
|
||||
typedef Eigen::Matrix<double, Eigen::Dynamic, 7> MatX7;
|
||||
typedef Eigen::Matrix<double, Eigen::Dynamic, 8> MatX8;
|
||||
typedef Eigen::Matrix<double, Eigen::Dynamic, 9> MatX9;
|
||||
typedef Eigen::Matrix<double, Eigen::Dynamic, 15> MatX15;
|
||||
typedef Eigen::Matrix<double, Eigen::Dynamic, 16> MatX16;
|
||||
|
||||
typedef Eigen::Vector2d Vec2;
|
||||
typedef Eigen::Vector3d Vec3;
|
||||
typedef Eigen::Vector4d Vec4;
|
||||
typedef Eigen::Matrix<double, 5, 1> Vec5;
|
||||
typedef Eigen::Matrix<double, 6, 1> Vec6;
|
||||
typedef Eigen::Matrix<double, 7, 1> Vec7;
|
||||
typedef Eigen::Matrix<double, 8, 1> Vec8;
|
||||
typedef Eigen::Matrix<double, 9, 1> Vec9;
|
||||
typedef Eigen::Matrix<double, 10, 1> Vec10;
|
||||
typedef Eigen::Matrix<double, 11, 1> Vec11;
|
||||
typedef Eigen::Matrix<double, 12, 1> Vec12;
|
||||
typedef Eigen::Matrix<double, 13, 1> Vec13;
|
||||
typedef Eigen::Matrix<double, 14, 1> Vec14;
|
||||
typedef Eigen::Matrix<double, 15, 1> Vec15;
|
||||
typedef Eigen::Matrix<double, 16, 1> Vec16;
|
||||
typedef Eigen::Matrix<double, 17, 1> Vec17;
|
||||
typedef Eigen::Matrix<double, 18, 1> Vec18;
|
||||
typedef Eigen::Matrix<double, 19, 1> Vec19;
|
||||
typedef Eigen::Matrix<double, 20, 1> Vec20;
|
||||
|
||||
typedef Eigen::Vector2f Vec2f;
|
||||
typedef Eigen::Vector3f Vec3f;
|
||||
typedef Eigen::Vector4f Vec4f;
|
||||
|
||||
typedef Eigen::VectorXi VecXi;
|
||||
|
||||
typedef Eigen::Vector2i Vec2i;
|
||||
typedef Eigen::Vector3i Vec3i;
|
||||
typedef Eigen::Vector4i Vec4i;
|
||||
|
||||
typedef Eigen::Matrix<float,
|
||||
Eigen::Dynamic,
|
||||
Eigen::Dynamic,
|
||||
Eigen::RowMajor> RMatf;
|
||||
|
||||
typedef Eigen::NumTraits<double> EigenDouble;
|
||||
|
||||
using Eigen::Map;
|
||||
using Eigen::Dynamic;
|
||||
using Eigen::Matrix;
|
||||
|
||||
// Find U, s, and VT such that
|
||||
//
|
||||
// A = U * diag(s) * VT
|
||||
//
|
||||
template <typename TMat, typename TVec>
|
||||
inline void SVD(TMat *A, Vec *s, Mat *U, Mat *VT) {
|
||||
assert(0);
|
||||
}
|
||||
|
||||
// Solve the linear system Ax = 0 via SVD. Store the solution in x, such that
|
||||
// ||x|| = 1.0. Return the singluar value corresponding to the solution.
|
||||
// Destroys A and resizes x if necessary.
|
||||
// TODO(maclean): Take the SVD of the transpose instead of this zero padding.
|
||||
template <typename TMat, typename TVec>
|
||||
double Nullspace(TMat *A, TVec *nullspace) {
|
||||
Eigen::JacobiSVD<TMat> svd(*A, Eigen::ComputeFullV);
|
||||
(*nullspace) = svd.matrixV().col(A->cols()-1);
|
||||
if (A->rows() >= A->cols())
|
||||
return svd.singularValues()(A->cols()-1);
|
||||
else
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
// Solve the linear system Ax = 0 via SVD. Finds two solutions, x1 and x2, such
|
||||
// that x1 is the best solution and x2 is the next best solution (in the L2
|
||||
// norm sense). Store the solution in x1 and x2, such that ||x|| = 1.0. Return
|
||||
// the singluar value corresponding to the solution x1. Destroys A and resizes
|
||||
// x if necessary.
|
||||
template <typename TMat, typename TVec1, typename TVec2>
|
||||
double Nullspace2(TMat *A, TVec1 *x1, TVec2 *x2) {
|
||||
Eigen::JacobiSVD<TMat> svd(*A, Eigen::ComputeFullV);
|
||||
*x1 = svd.matrixV().col(A->cols() - 1);
|
||||
*x2 = svd.matrixV().col(A->cols() - 2);
|
||||
if (A->rows() >= A->cols())
|
||||
return svd.singularValues()(A->cols()-1);
|
||||
else
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
// In place transpose for square matrices.
|
||||
template<class TA>
|
||||
inline void TransposeInPlace(TA *A) {
|
||||
*A = A->transpose().eval();
|
||||
}
|
||||
|
||||
template<typename TVec>
|
||||
inline double NormL1(const TVec &x) {
|
||||
return x.array().abs().sum();
|
||||
}
|
||||
|
||||
template<typename TVec>
|
||||
inline double NormL2(const TVec &x) {
|
||||
return x.norm();
|
||||
}
|
||||
|
||||
template<typename TVec>
|
||||
inline double NormLInfinity(const TVec &x) {
|
||||
return x.array().abs().maxCoeff();
|
||||
}
|
||||
|
||||
template<typename TVec>
|
||||
inline double DistanceL1(const TVec &x, const TVec &y) {
|
||||
return (x - y).array().abs().sum();
|
||||
}
|
||||
|
||||
template<typename TVec>
|
||||
inline double DistanceL2(const TVec &x, const TVec &y) {
|
||||
return (x - y).norm();
|
||||
}
|
||||
template<typename TVec>
|
||||
inline double DistanceLInfinity(const TVec &x, const TVec &y) {
|
||||
return (x - y).array().abs().maxCoeff();
|
||||
}
|
||||
|
||||
// Normalize a vector with the L1 norm, and return the norm before it was
|
||||
// normalized.
|
||||
template<typename TVec>
|
||||
inline double NormalizeL1(TVec *x) {
|
||||
double norm = NormL1(*x);
|
||||
*x /= norm;
|
||||
return norm;
|
||||
}
|
||||
|
||||
// Normalize a vector with the L2 norm, and return the norm before it was
|
||||
// normalized.
|
||||
template<typename TVec>
|
||||
inline double NormalizeL2(TVec *x) {
|
||||
double norm = NormL2(*x);
|
||||
*x /= norm;
|
||||
return norm;
|
||||
}
|
||||
|
||||
// Normalize a vector with the L^Infinity norm, and return the norm before it
|
||||
// was normalized.
|
||||
template<typename TVec>
|
||||
inline double NormalizeLInfinity(TVec *x) {
|
||||
double norm = NormLInfinity(*x);
|
||||
*x /= norm;
|
||||
return norm;
|
||||
}
|
||||
|
||||
// Return the square of a number.
|
||||
template<typename T>
|
||||
inline T Square(T x) {
|
||||
return x * x;
|
||||
}
|
||||
|
||||
Mat3 RotationAroundX(double angle);
|
||||
Mat3 RotationAroundY(double angle);
|
||||
Mat3 RotationAroundZ(double angle);
|
||||
|
||||
// Returns the rotation matrix of a rotation of angle |axis| around axis.
|
||||
// This is computed using the Rodrigues formula, see:
|
||||
// http://mathworld.wolfram.com/RodriguesRotationFormula.html
|
||||
Mat3 RotationRodrigues(const Vec3 &axis);
|
||||
|
||||
// Make a rotation matrix such that center becomes the direction of the
|
||||
// positive z-axis, and y is oriented close to up.
|
||||
Mat3 LookAt(Vec3 center);
|
||||
|
||||
// Return a diagonal matrix from a vector containg the diagonal values.
|
||||
template <typename TVec>
|
||||
inline Mat Diag(const TVec &x) {
|
||||
return x.asDiagonal();
|
||||
}
|
||||
|
||||
template<typename TMat>
|
||||
inline double FrobeniusNorm(const TMat &A) {
|
||||
return sqrt(A.array().abs2().sum());
|
||||
}
|
||||
|
||||
template<typename TMat>
|
||||
inline double FrobeniusDistance(const TMat &A, const TMat &B) {
|
||||
return FrobeniusNorm(A - B);
|
||||
}
|
||||
|
||||
inline Vec3 CrossProduct(const Vec3 &x, const Vec3 &y) {
|
||||
return x.cross(y);
|
||||
}
|
||||
|
||||
Mat3 CrossProductMatrix(const Vec3 &x);
|
||||
|
||||
void MeanAndVarianceAlongRows(const Mat &A,
|
||||
Vec *mean_pointer,
|
||||
Vec *variance_pointer);
|
||||
|
||||
#if _WIN32
|
||||
// TODO(bomboze): un-#if this for both platforms once tested under Windows
|
||||
/* This solution was extensively discussed here
|
||||
http://forum.kde.org/viewtopic.php?f=74&t=61940 */
|
||||
#define SUM_OR_DYNAMIC(x, y) (x == Eigen::Dynamic || y == Eigen::Dynamic) ? Eigen::Dynamic : (x+y)
|
||||
|
||||
template<typename Derived1, typename Derived2>
|
||||
struct hstack_return {
|
||||
typedef typename Derived1::Scalar Scalar;
|
||||
enum {
|
||||
RowsAtCompileTime = Derived1::RowsAtCompileTime,
|
||||
ColsAtCompileTime = SUM_OR_DYNAMIC(Derived1::ColsAtCompileTime,
|
||||
Derived2::ColsAtCompileTime),
|
||||
Options = Derived1::Flags&Eigen::RowMajorBit ? Eigen::RowMajor : 0,
|
||||
MaxRowsAtCompileTime = Derived1::MaxRowsAtCompileTime,
|
||||
MaxColsAtCompileTime = SUM_OR_DYNAMIC(Derived1::MaxColsAtCompileTime,
|
||||
Derived2::MaxColsAtCompileTime)
|
||||
};
|
||||
typedef Eigen::Matrix<Scalar,
|
||||
RowsAtCompileTime,
|
||||
ColsAtCompileTime,
|
||||
Options,
|
||||
MaxRowsAtCompileTime,
|
||||
MaxColsAtCompileTime> type;
|
||||
};
|
||||
|
||||
template<typename Derived1, typename Derived2>
|
||||
typename hstack_return<Derived1, Derived2>::type
|
||||
HStack(const Eigen::MatrixBase<Derived1>& lhs,
|
||||
const Eigen::MatrixBase<Derived2>& rhs) {
|
||||
typename hstack_return<Derived1, Derived2>::type res;
|
||||
res.resize(lhs.rows(), lhs.cols()+rhs.cols());
|
||||
res << lhs, rhs;
|
||||
return res;
|
||||
};
|
||||
|
||||
|
||||
template<typename Derived1, typename Derived2>
|
||||
struct vstack_return {
|
||||
typedef typename Derived1::Scalar Scalar;
|
||||
enum {
|
||||
RowsAtCompileTime = SUM_OR_DYNAMIC(Derived1::RowsAtCompileTime,
|
||||
Derived2::RowsAtCompileTime),
|
||||
ColsAtCompileTime = Derived1::ColsAtCompileTime,
|
||||
Options = Derived1::Flags&Eigen::RowMajorBit ? Eigen::RowMajor : 0,
|
||||
MaxRowsAtCompileTime = SUM_OR_DYNAMIC(Derived1::MaxRowsAtCompileTime,
|
||||
Derived2::MaxRowsAtCompileTime),
|
||||
MaxColsAtCompileTime = Derived1::MaxColsAtCompileTime
|
||||
};
|
||||
typedef Eigen::Matrix<Scalar,
|
||||
RowsAtCompileTime,
|
||||
ColsAtCompileTime,
|
||||
Options,
|
||||
MaxRowsAtCompileTime,
|
||||
MaxColsAtCompileTime> type;
|
||||
};
|
||||
|
||||
template<typename Derived1, typename Derived2>
|
||||
typename vstack_return<Derived1, Derived2>::type
|
||||
VStack(const Eigen::MatrixBase<Derived1>& lhs,
|
||||
const Eigen::MatrixBase<Derived2>& rhs) {
|
||||
typename vstack_return<Derived1, Derived2>::type res;
|
||||
res.resize(lhs.rows()+rhs.rows(), lhs.cols());
|
||||
res << lhs, rhs;
|
||||
return res;
|
||||
};
|
||||
|
||||
|
||||
#else // _WIN32
|
||||
|
||||
// Since it is not possible to typedef privately here, use a macro.
|
||||
// Always take dynamic columns if either side is dynamic.
|
||||
#define COLS \
|
||||
((ColsLeft == Eigen::Dynamic || ColsRight == Eigen::Dynamic) \
|
||||
? Eigen::Dynamic : (ColsLeft + ColsRight))
|
||||
|
||||
// Same as above, except that prefer fixed size if either is fixed.
|
||||
#define ROWS \
|
||||
((RowsLeft == Eigen::Dynamic && RowsRight == Eigen::Dynamic) \
|
||||
? Eigen::Dynamic \
|
||||
: ((RowsLeft == Eigen::Dynamic) \
|
||||
? RowsRight \
|
||||
: RowsLeft \
|
||||
) \
|
||||
)
|
||||
|
||||
// TODO(keir): Add a static assert if both rows are at compiletime.
|
||||
template<typename T, int RowsLeft, int RowsRight, int ColsLeft, int ColsRight>
|
||||
Eigen::Matrix<T, ROWS, COLS>
|
||||
HStack(const Eigen::Matrix<T, RowsLeft, ColsLeft> &left,
|
||||
const Eigen::Matrix<T, RowsRight, ColsRight> &right) {
|
||||
assert(left.rows() == right.rows());
|
||||
int n = left.rows();
|
||||
int m1 = left.cols();
|
||||
int m2 = right.cols();
|
||||
|
||||
Eigen::Matrix<T, ROWS, COLS> stacked(n, m1 + m2);
|
||||
stacked.block(0, 0, n, m1) = left;
|
||||
stacked.block(0, m1, n, m2) = right;
|
||||
return stacked;
|
||||
}
|
||||
|
||||
// Reuse the above macros by swapping the order of Rows and Cols. Nasty, but
|
||||
// the duplication is worse.
|
||||
// TODO(keir): Add a static assert if both rows are at compiletime.
|
||||
// TODO(keir): Mail eigen list about making this work for general expressions
|
||||
// rather than only matrix types.
|
||||
template<typename T, int RowsLeft, int RowsRight, int ColsLeft, int ColsRight>
|
||||
Eigen::Matrix<T, COLS, ROWS>
|
||||
VStack(const Eigen::Matrix<T, ColsLeft, RowsLeft> &top,
|
||||
const Eigen::Matrix<T, ColsRight, RowsRight> &bottom) {
|
||||
assert(top.cols() == bottom.cols());
|
||||
int n1 = top.rows();
|
||||
int n2 = bottom.rows();
|
||||
int m = top.cols();
|
||||
|
||||
Eigen::Matrix<T, COLS, ROWS> stacked(n1 + n2, m);
|
||||
stacked.block(0, 0, n1, m) = top;
|
||||
stacked.block(n1, 0, n2, m) = bottom;
|
||||
return stacked;
|
||||
}
|
||||
#undef COLS
|
||||
#undef ROWS
|
||||
#endif // _WIN32
|
||||
|
||||
|
||||
|
||||
void HorizontalStack(const Mat &left, const Mat &right, Mat *stacked);
|
||||
|
||||
template<typename TTop, typename TBot, typename TStacked>
|
||||
void VerticalStack(const TTop &top, const TBot &bottom, TStacked *stacked) {
|
||||
assert(top.cols() == bottom.cols());
|
||||
int n1 = top.rows();
|
||||
int n2 = bottom.rows();
|
||||
int m = top.cols();
|
||||
|
||||
stacked->resize(n1 + n2, m);
|
||||
stacked->block(0, 0, n1, m) = top;
|
||||
stacked->block(n1, 0, n2, m) = bottom;
|
||||
}
|
||||
|
||||
void MatrixColumn(const Mat &A, int i, Vec2 *v);
|
||||
void MatrixColumn(const Mat &A, int i, Vec3 *v);
|
||||
void MatrixColumn(const Mat &A, int i, Vec4 *v);
|
||||
|
||||
template <typename TMat, typename TCols>
|
||||
TMat ExtractColumns(const TMat &A, const TCols &columns) {
|
||||
TMat compressed(A.rows(), columns.size());
|
||||
for (int i = 0; i < columns.size(); ++i) {
|
||||
compressed.col(i) = A.col(columns[i]);
|
||||
}
|
||||
return compressed;
|
||||
}
|
||||
|
||||
template <typename TMat, typename TDest>
|
||||
void reshape(const TMat &a, int rows, int cols, TDest *b) {
|
||||
assert(a.rows()*a.cols() == rows*cols);
|
||||
b->resize(rows, cols);
|
||||
for (int i = 0; i < rows; i++) {
|
||||
for (int j = 0; j < cols; j++) {
|
||||
(*b)(i, j) = a[cols*i + j];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline bool isnan(double i) {
|
||||
#ifdef WIN32
|
||||
return _isnan(i) > 0;
|
||||
#else
|
||||
return std::isnan(i);
|
||||
#endif
|
||||
}
|
||||
|
||||
/// Ceil function that has the same behaviour for positive
|
||||
/// and negative values
|
||||
template <typename FloatType>
|
||||
FloatType ceil0(const FloatType& value) {
|
||||
FloatType result = std::ceil(std::fabs(value));
|
||||
return (value < 0.0) ? -result : result;
|
||||
}
|
||||
|
||||
/// Returns the skew anti-symmetric matrix of a vector
|
||||
inline Mat3 SkewMat(const Vec3 &x) {
|
||||
Mat3 skew;
|
||||
skew << 0 , -x(2), x(1),
|
||||
x(2), 0 , -x(0),
|
||||
-x(1), x(0), 0;
|
||||
return skew;
|
||||
}
|
||||
/// Returns the skew anti-symmetric matrix of a vector with only
|
||||
/// the first two (independent) lines
|
||||
inline Mat23 SkewMatMinimal(const Vec2 &x) {
|
||||
Mat23 skew;
|
||||
skew << 0, -1, x(1),
|
||||
1, 0, -x(0);
|
||||
return skew;
|
||||
}
|
||||
|
||||
/// Returns the rotaiton matrix built from given vector of euler angles
|
||||
inline Mat3 RotationFromEulerVector(Vec3 euler_vector) {
|
||||
double theta = euler_vector.norm();
|
||||
if (theta == 0.0) {
|
||||
return Mat3::Identity();
|
||||
}
|
||||
Vec3 w = euler_vector / theta;
|
||||
Mat3 w_hat = CrossProductMatrix(w);
|
||||
return Mat3::Identity() + w_hat*sin(theta) + w_hat*w_hat*(1 - cos(theta));
|
||||
}
|
||||
} // namespace libmv
|
||||
|
||||
#endif // LIBMV_NUMERIC_NUMERIC_H
|
||||
@@ -0,0 +1,23 @@
|
||||
// Copyright (c) 2007, 2008 libmv authors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//
|
||||
// Routines for solving polynomials.
|
||||
|
||||
// TODO(keir): Add a solver for degree > 3 polynomials.
|
||||
@@ -0,0 +1,123 @@
|
||||
// Copyright (c) 2007, 2008 libmv authors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
|
||||
#ifndef LIBMV_NUMERIC_POLY_H_
|
||||
#define LIBMV_NUMERIC_POLY_H_
|
||||
|
||||
#include <cmath>
|
||||
#include <stdio.h>
|
||||
|
||||
namespace libmv {
|
||||
|
||||
// Solve the cubic polynomial
|
||||
//
|
||||
// x^3 + a*x^2 + b*x + c = 0
|
||||
//
|
||||
// The number of roots (from zero to three) is returned. If the number of roots
|
||||
// is less than three, then higher numbered x's are not changed. For example,
|
||||
// if there are 2 roots, only x0 and x1 are set.
|
||||
//
|
||||
// The GSL cubic solver was used as a reference for this routine.
|
||||
template<typename Real>
|
||||
int SolveCubicPolynomial(Real a, Real b, Real c,
|
||||
Real *x0, Real *x1, Real *x2) {
|
||||
Real q = a * a - 3 * b;
|
||||
Real r = 2 * a * a * a - 9 * a * b + 27 * c;
|
||||
|
||||
Real Q = q / 9;
|
||||
Real R = r / 54;
|
||||
|
||||
Real Q3 = Q * Q * Q;
|
||||
Real R2 = R * R;
|
||||
|
||||
Real CR2 = 729 * r * r;
|
||||
Real CQ3 = 2916 * q * q * q;
|
||||
|
||||
if (R == 0 && Q == 0) {
|
||||
// Tripple root in one place.
|
||||
*x0 = *x1 = *x2 = -a / 3;
|
||||
return 3;
|
||||
|
||||
} else if (CR2 == CQ3) {
|
||||
// This test is actually R2 == Q3, written in a form suitable for exact
|
||||
// computation with integers.
|
||||
//
|
||||
// Due to finite precision some double roots may be missed, and considered
|
||||
// to be a pair of complex roots z = x +/- epsilon i close to the real
|
||||
// axis.
|
||||
Real sqrtQ = sqrt(Q);
|
||||
if (R > 0) {
|
||||
*x0 = -2 * sqrtQ - a / 3;
|
||||
*x1 = sqrtQ - a / 3;
|
||||
*x2 = sqrtQ - a / 3;
|
||||
} else {
|
||||
*x0 = -sqrtQ - a / 3;
|
||||
*x1 = -sqrtQ - a / 3;
|
||||
*x2 = 2 * sqrtQ - a / 3;
|
||||
}
|
||||
return 3;
|
||||
|
||||
} else if (CR2 < CQ3) {
|
||||
// This case is equivalent to R2 < Q3.
|
||||
Real sqrtQ = sqrt(Q);
|
||||
Real sqrtQ3 = sqrtQ * sqrtQ * sqrtQ;
|
||||
Real theta = acos(R / sqrtQ3);
|
||||
Real norm = -2 * sqrtQ;
|
||||
*x0 = norm * cos(theta / 3) - a / 3;
|
||||
*x1 = norm * cos((theta + 2.0 * M_PI) / 3) - a / 3;
|
||||
*x2 = norm * cos((theta - 2.0 * M_PI) / 3) - a / 3;
|
||||
|
||||
// Put the roots in ascending order.
|
||||
if (*x0 > *x1) {
|
||||
std::swap(*x0, *x1);
|
||||
}
|
||||
if (*x1 > *x2) {
|
||||
std::swap(*x1, *x2);
|
||||
if (*x0 > *x1) {
|
||||
std::swap(*x0, *x1);
|
||||
}
|
||||
}
|
||||
return 3;
|
||||
}
|
||||
Real sgnR = (R >= 0 ? 1 : -1);
|
||||
Real A = -sgnR * pow(fabs(R) + sqrt(R2 - Q3), 1.0/3.0);
|
||||
Real B = Q / A;
|
||||
*x0 = A + B - a / 3;
|
||||
return 1;
|
||||
}
|
||||
|
||||
// The coefficients are in ascending powers, i.e. coeffs[N]*x^N.
|
||||
template<typename Real>
|
||||
int SolveCubicPolynomial(const Real *coeffs, Real *solutions) {
|
||||
if (coeffs[0] == 0.0) {
|
||||
// TODO(keir): This is a quadratic not a cubic. Implement a quadratic
|
||||
// solver!
|
||||
return 0;
|
||||
}
|
||||
Real a = coeffs[2] / coeffs[3];
|
||||
Real b = coeffs[1] / coeffs[3];
|
||||
Real c = coeffs[0] / coeffs[3];
|
||||
return SolveCubicPolynomial(a, b, c,
|
||||
solutions + 0,
|
||||
solutions + 1,
|
||||
solutions + 2);
|
||||
}
|
||||
} // namespace libmv
|
||||
#endif // LIBMV_NUMERIC_POLY_H_
|
||||
@@ -0,0 +1,22 @@
|
||||
SET(SIMPLE_PIPELINE_SRC
|
||||
bundle.cc
|
||||
camera_intrinsics.cc
|
||||
distortion_models.cc
|
||||
initialize_reconstruction.cc
|
||||
intersect.cc
|
||||
keyframe_selection.cc
|
||||
pipeline.cc
|
||||
reconstruction.cc
|
||||
reconstruction_scale.cc
|
||||
resect.cc
|
||||
tracks.cc
|
||||
)
|
||||
|
||||
# Define the header files so that they appear in IDEs.
|
||||
FILE(GLOB SIMPLE_PIPELINE_HDRS *.h)
|
||||
|
||||
ADD_LIBRARY(opencv.sfm.simple_pipeline STATIC ${SIMPLE_PIPELINE_SRC} ${SIMPLE_PIPELINE_HDRS})
|
||||
|
||||
TARGET_LINK_LIBRARIES(opencv.sfm.simple_pipeline LINK_PRIVATE opencv.sfm.multiview ${CERES_LIBRARIES})
|
||||
|
||||
LIBMV_INSTALL_LIB(opencv.sfm.simple_pipeline)
|
||||
@@ -0,0 +1,686 @@
|
||||
// Copyright (c) 2011, 2012, 2013 libmv authors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
|
||||
#include "libmv/simple_pipeline/bundle.h"
|
||||
|
||||
#include <map>
|
||||
|
||||
#include "ceres/ceres.h"
|
||||
#include "ceres/rotation.h"
|
||||
#include "ceres/version.h"
|
||||
#include "libmv/base/vector.h"
|
||||
#include "libmv/logging/logging.h"
|
||||
#include "libmv/multiview/fundamental.h"
|
||||
#include "libmv/multiview/projection.h"
|
||||
#include "libmv/numeric/numeric.h"
|
||||
#include "libmv/simple_pipeline/camera_intrinsics.h"
|
||||
#include "libmv/simple_pipeline/reconstruction.h"
|
||||
#include "libmv/simple_pipeline/tracks.h"
|
||||
#include "libmv/simple_pipeline/distortion_models.h"
|
||||
|
||||
#ifdef _OPENMP
|
||||
# include <omp.h>
|
||||
#endif
|
||||
|
||||
namespace libmv {
|
||||
|
||||
// The intrinsics need to get combined into a single parameter block; use these
|
||||
// enums to index instead of numeric constants.
|
||||
enum {
|
||||
// Camera calibration values.
|
||||
OFFSET_FOCAL_LENGTH,
|
||||
OFFSET_PRINCIPAL_POINT_X,
|
||||
OFFSET_PRINCIPAL_POINT_Y,
|
||||
|
||||
// Distortion model coefficients.
|
||||
OFFSET_K1,
|
||||
OFFSET_K2,
|
||||
OFFSET_K3,
|
||||
OFFSET_P1,
|
||||
OFFSET_P2,
|
||||
|
||||
// Maximal possible offset.
|
||||
OFFSET_MAX,
|
||||
};
|
||||
|
||||
#define FIRST_DISTORTION_COEFFICIENT OFFSET_K1
|
||||
#define LAST_DISTORTION_COEFFICIENT OFFSET_P2
|
||||
#define NUM_DISTORTION_COEFFICIENTS \
|
||||
(LAST_DISTORTION_COEFFICIENT - FIRST_DISTORTION_COEFFICIENT + 1)
|
||||
|
||||
namespace {
|
||||
|
||||
// Cost functor which computes reprojection error of 3D point X
|
||||
// on camera defined by angle-axis rotation and it's translation
|
||||
// (which are in the same block due to optimization reasons).
|
||||
//
|
||||
// This functor uses a radial distortion model.
|
||||
struct OpenCVReprojectionError {
|
||||
OpenCVReprojectionError(const DistortionModelType distortion_model,
|
||||
const double observed_x,
|
||||
const double observed_y,
|
||||
const double weight)
|
||||
: distortion_model_(distortion_model),
|
||||
observed_x_(observed_x), observed_y_(observed_y),
|
||||
weight_(weight) {}
|
||||
|
||||
template <typename T>
|
||||
bool operator()(const T* const intrinsics,
|
||||
const T* const R_t, // Rotation denoted by angle axis
|
||||
// followed with translation
|
||||
const T* const X, // Point coordinates 3x1.
|
||||
T* residuals) const {
|
||||
// Unpack the intrinsics.
|
||||
const T& focal_length = intrinsics[OFFSET_FOCAL_LENGTH];
|
||||
const T& principal_point_x = intrinsics[OFFSET_PRINCIPAL_POINT_X];
|
||||
const T& principal_point_y = intrinsics[OFFSET_PRINCIPAL_POINT_Y];
|
||||
|
||||
// Compute projective coordinates: x = RX + t.
|
||||
T x[3];
|
||||
|
||||
ceres::AngleAxisRotatePoint(R_t, X, x);
|
||||
x[0] += R_t[3];
|
||||
x[1] += R_t[4];
|
||||
x[2] += R_t[5];
|
||||
|
||||
// Prevent points from going behind the camera.
|
||||
if (x[2] < T(0)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Compute normalized coordinates: x /= x[2].
|
||||
T xn = x[0] / x[2];
|
||||
T yn = x[1] / x[2];
|
||||
|
||||
T predicted_x, predicted_y;
|
||||
|
||||
// Apply distortion to the normalized points to get (xd, yd).
|
||||
// TODO(keir): Do early bailouts for zero distortion; these are expensive
|
||||
// jet operations.
|
||||
switch (distortion_model_) {
|
||||
case DISTORTION_MODEL_POLYNOMIAL:
|
||||
{
|
||||
const T& k1 = intrinsics[OFFSET_K1];
|
||||
const T& k2 = intrinsics[OFFSET_K2];
|
||||
const T& k3 = intrinsics[OFFSET_K3];
|
||||
const T& p1 = intrinsics[OFFSET_P1];
|
||||
const T& p2 = intrinsics[OFFSET_P2];
|
||||
|
||||
ApplyPolynomialDistortionModel(focal_length,
|
||||
focal_length,
|
||||
principal_point_x,
|
||||
principal_point_y,
|
||||
k1, k2, k3,
|
||||
p1, p2,
|
||||
xn, yn,
|
||||
&predicted_x,
|
||||
&predicted_y);
|
||||
break;
|
||||
}
|
||||
case DISTORTION_MODEL_DIVISION:
|
||||
{
|
||||
const T& k1 = intrinsics[OFFSET_K1];
|
||||
const T& k2 = intrinsics[OFFSET_K2];
|
||||
|
||||
ApplyDivisionDistortionModel(focal_length,
|
||||
focal_length,
|
||||
principal_point_x,
|
||||
principal_point_y,
|
||||
k1, k2,
|
||||
xn, yn,
|
||||
&predicted_x,
|
||||
&predicted_y);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
LOG(FATAL) << "Unknown distortion model";
|
||||
}
|
||||
|
||||
// The error is the difference between the predicted and observed position.
|
||||
residuals[0] = (predicted_x - T(observed_x_)) * weight_;
|
||||
residuals[1] = (predicted_y - T(observed_y_)) * weight_;
|
||||
return true;
|
||||
}
|
||||
|
||||
const DistortionModelType distortion_model_;
|
||||
const double observed_x_;
|
||||
const double observed_y_;
|
||||
const double weight_;
|
||||
};
|
||||
|
||||
// Print a message to the log which camera intrinsics are gonna to be optimixed.
|
||||
void BundleIntrinsicsLogMessage(const int bundle_intrinsics) {
|
||||
if (bundle_intrinsics == BUNDLE_NO_INTRINSICS) {
|
||||
LOG(INFO) << "Bundling only camera positions.";
|
||||
} else {
|
||||
std::string bundling_message = "";
|
||||
|
||||
#define APPEND_BUNDLING_INTRINSICS(name, flag) \
|
||||
if (bundle_intrinsics & flag) { \
|
||||
if (!bundling_message.empty()) { \
|
||||
bundling_message += ", "; \
|
||||
} \
|
||||
bundling_message += name; \
|
||||
} (void)0
|
||||
|
||||
APPEND_BUNDLING_INTRINSICS("f", BUNDLE_FOCAL_LENGTH);
|
||||
APPEND_BUNDLING_INTRINSICS("px, py", BUNDLE_PRINCIPAL_POINT);
|
||||
APPEND_BUNDLING_INTRINSICS("k1", BUNDLE_RADIAL_K1);
|
||||
APPEND_BUNDLING_INTRINSICS("k2", BUNDLE_RADIAL_K2);
|
||||
APPEND_BUNDLING_INTRINSICS("p1", BUNDLE_TANGENTIAL_P1);
|
||||
APPEND_BUNDLING_INTRINSICS("p2", BUNDLE_TANGENTIAL_P2);
|
||||
|
||||
LOG(INFO) << "Bundling " << bundling_message << ".";
|
||||
}
|
||||
}
|
||||
|
||||
// Pack intrinsics from object to an array for easier
|
||||
// and faster minimization.
|
||||
void PackIntrinisicsIntoArray(const CameraIntrinsics &intrinsics,
|
||||
double ceres_intrinsics[OFFSET_MAX]) {
|
||||
ceres_intrinsics[OFFSET_FOCAL_LENGTH] = intrinsics.focal_length();
|
||||
ceres_intrinsics[OFFSET_PRINCIPAL_POINT_X] = intrinsics.principal_point_x();
|
||||
ceres_intrinsics[OFFSET_PRINCIPAL_POINT_Y] = intrinsics.principal_point_y();
|
||||
|
||||
int num_distortion_parameters = intrinsics.num_distortion_parameters();
|
||||
assert(num_distortion_parameters <= NUM_DISTORTION_COEFFICIENTS);
|
||||
|
||||
const double *distortion_parameters = intrinsics.distortion_parameters();
|
||||
for (int i = 0; i < num_distortion_parameters; ++i) {
|
||||
ceres_intrinsics[FIRST_DISTORTION_COEFFICIENT + i] =
|
||||
distortion_parameters[i];
|
||||
}
|
||||
}
|
||||
|
||||
// Unpack intrinsics back from an array to an object.
|
||||
void UnpackIntrinsicsFromArray(const double ceres_intrinsics[OFFSET_MAX],
|
||||
CameraIntrinsics *intrinsics) {
|
||||
intrinsics->SetFocalLength(ceres_intrinsics[OFFSET_FOCAL_LENGTH],
|
||||
ceres_intrinsics[OFFSET_FOCAL_LENGTH]);
|
||||
|
||||
intrinsics->SetPrincipalPoint(ceres_intrinsics[OFFSET_PRINCIPAL_POINT_X],
|
||||
ceres_intrinsics[OFFSET_PRINCIPAL_POINT_Y]);
|
||||
|
||||
int num_distortion_parameters = intrinsics->num_distortion_parameters();
|
||||
assert(num_distortion_parameters <= NUM_DISTORTION_COEFFICIENTS);
|
||||
|
||||
double *distortion_parameters = intrinsics->distortion_parameters();
|
||||
for (int i = 0; i < num_distortion_parameters; ++i) {
|
||||
distortion_parameters[i] =
|
||||
ceres_intrinsics[FIRST_DISTORTION_COEFFICIENT + i];
|
||||
}
|
||||
}
|
||||
|
||||
// Get a vector of camera's rotations denoted by angle axis
|
||||
// conjuncted with translations into single block
|
||||
//
|
||||
// Element with index i matches to a rotation+translation for
|
||||
// camera at image i.
|
||||
vector<Vec6> PackCamerasRotationAndTranslation(
|
||||
const Tracks &tracks,
|
||||
const EuclideanReconstruction &reconstruction) {
|
||||
vector<Vec6> all_cameras_R_t;
|
||||
int max_image = tracks.MaxImage();
|
||||
|
||||
all_cameras_R_t.resize(max_image + 1);
|
||||
|
||||
for (int i = 0; i <= max_image; i++) {
|
||||
const EuclideanCamera *camera = reconstruction.CameraForImage(i);
|
||||
|
||||
if (!camera) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ceres::RotationMatrixToAngleAxis(&camera->R(0, 0),
|
||||
&all_cameras_R_t[i](0));
|
||||
all_cameras_R_t[i].tail<3>() = camera->t;
|
||||
}
|
||||
return all_cameras_R_t;
|
||||
}
|
||||
|
||||
// Convert cameras rotations fro mangle axis back to rotation matrix.
|
||||
void UnpackCamerasRotationAndTranslation(
|
||||
const Tracks &tracks,
|
||||
const vector<Vec6> &all_cameras_R_t,
|
||||
EuclideanReconstruction *reconstruction) {
|
||||
int max_image = tracks.MaxImage();
|
||||
|
||||
for (int i = 0; i <= max_image; i++) {
|
||||
EuclideanCamera *camera = reconstruction->CameraForImage(i);
|
||||
|
||||
if (!camera) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ceres::AngleAxisToRotationMatrix(&all_cameras_R_t[i](0),
|
||||
&camera->R(0, 0));
|
||||
camera->t = all_cameras_R_t[i].tail<3>();
|
||||
}
|
||||
}
|
||||
|
||||
// Converts sparse CRSMatrix to Eigen matrix, so it could be used
|
||||
// all over in the pipeline.
|
||||
//
|
||||
// TODO(sergey): currently uses dense Eigen matrices, best would
|
||||
// be to use sparse Eigen matrices
|
||||
void CRSMatrixToEigenMatrix(const ceres::CRSMatrix &crs_matrix,
|
||||
Mat *eigen_matrix) {
|
||||
eigen_matrix->resize(crs_matrix.num_rows, crs_matrix.num_cols);
|
||||
eigen_matrix->setZero();
|
||||
|
||||
for (int row = 0; row < crs_matrix.num_rows; ++row) {
|
||||
int start = crs_matrix.rows[row];
|
||||
int end = crs_matrix.rows[row + 1] - 1;
|
||||
|
||||
for (int i = start; i <= end; i++) {
|
||||
int col = crs_matrix.cols[i];
|
||||
double value = crs_matrix.values[i];
|
||||
|
||||
(*eigen_matrix)(row, col) = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EuclideanBundlerPerformEvaluation(const Tracks &tracks,
|
||||
EuclideanReconstruction *reconstruction,
|
||||
vector<Vec6> *all_cameras_R_t,
|
||||
ceres::Problem *problem,
|
||||
BundleEvaluation *evaluation) {
|
||||
int max_track = tracks.MaxTrack();
|
||||
// Number of camera rotations equals to number of translation,
|
||||
int num_cameras = all_cameras_R_t->size();
|
||||
int num_points = 0;
|
||||
|
||||
vector<EuclideanPoint*> minimized_points;
|
||||
for (int i = 0; i <= max_track; i++) {
|
||||
EuclideanPoint *point = reconstruction->PointForTrack(i);
|
||||
if (point) {
|
||||
// We need to know whether the track is constant zero weight,
|
||||
// and it so it wouldn't have parameter block in the problem.
|
||||
//
|
||||
// Getting all markers for track is not so bac currently since
|
||||
// this code is only used by keyframe selection when there are
|
||||
// not so much tracks and only 2 frames anyway.
|
||||
vector<Marker> markera_of_track = tracks.MarkersForTrack(i);
|
||||
for (int j = 0; j < markera_of_track.size(); j++) {
|
||||
if (markera_of_track.at(j).weight != 0.0) {
|
||||
minimized_points.push_back(point);
|
||||
num_points++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LG << "Number of cameras " << num_cameras;
|
||||
LG << "Number of points " << num_points;
|
||||
|
||||
evaluation->num_cameras = num_cameras;
|
||||
evaluation->num_points = num_points;
|
||||
|
||||
if (evaluation->evaluate_jacobian) { // Evaluate jacobian matrix.
|
||||
ceres::CRSMatrix evaluated_jacobian;
|
||||
ceres::Problem::EvaluateOptions eval_options;
|
||||
|
||||
// Cameras goes first in the ordering.
|
||||
int max_image = tracks.MaxImage();
|
||||
for (int i = 0; i <= max_image; i++) {
|
||||
const EuclideanCamera *camera = reconstruction->CameraForImage(i);
|
||||
if (camera) {
|
||||
double *current_camera_R_t = &(*all_cameras_R_t)[i](0);
|
||||
|
||||
// All cameras are variable now.
|
||||
problem->SetParameterBlockVariable(current_camera_R_t);
|
||||
|
||||
eval_options.parameter_blocks.push_back(current_camera_R_t);
|
||||
}
|
||||
}
|
||||
|
||||
// Points goes at the end of ordering,
|
||||
for (int i = 0; i < minimized_points.size(); i++) {
|
||||
EuclideanPoint *point = minimized_points.at(i);
|
||||
eval_options.parameter_blocks.push_back(&point->X(0));
|
||||
}
|
||||
|
||||
problem->Evaluate(eval_options,
|
||||
NULL, NULL, NULL,
|
||||
&evaluated_jacobian);
|
||||
|
||||
CRSMatrixToEigenMatrix(evaluated_jacobian, &evaluation->jacobian);
|
||||
}
|
||||
}
|
||||
|
||||
// This is an utility function to only bundle 3D position of
|
||||
// given markers list.
|
||||
//
|
||||
// Main purpose of this function is to adjust positions of tracks
|
||||
// which does have constant zero weight and so far only were using
|
||||
// algebraic intersection to obtain their 3D positions.
|
||||
//
|
||||
// At this point we only need to bundle points positions, cameras
|
||||
// are to be totally still here.
|
||||
void EuclideanBundlePointsOnly(const DistortionModelType distortion_model,
|
||||
const vector<Marker> &markers,
|
||||
vector<Vec6> &all_cameras_R_t,
|
||||
double ceres_intrinsics[OFFSET_MAX],
|
||||
EuclideanReconstruction *reconstruction) {
|
||||
ceres::Problem::Options problem_options;
|
||||
ceres::Problem problem(problem_options);
|
||||
int num_residuals = 0;
|
||||
for (int i = 0; i < markers.size(); ++i) {
|
||||
const Marker &marker = markers[i];
|
||||
EuclideanCamera *camera = reconstruction->CameraForImage(marker.image);
|
||||
EuclideanPoint *point = reconstruction->PointForTrack(marker.track);
|
||||
if (camera == NULL || point == NULL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Rotation of camera denoted in angle axis followed with
|
||||
// camera translaiton.
|
||||
double *current_camera_R_t = &all_cameras_R_t[camera->image](0);
|
||||
|
||||
problem.AddResidualBlock(new ceres::AutoDiffCostFunction<
|
||||
OpenCVReprojectionError, 2, OFFSET_MAX, 6, 3>(
|
||||
new OpenCVReprojectionError(
|
||||
distortion_model,
|
||||
marker.x,
|
||||
marker.y,
|
||||
1.0)),
|
||||
nullptr,
|
||||
ceres_intrinsics,
|
||||
current_camera_R_t,
|
||||
&point->X(0));
|
||||
|
||||
problem.SetParameterBlockConstant(current_camera_R_t);
|
||||
num_residuals++;
|
||||
}
|
||||
|
||||
LG << "Number of residuals: " << num_residuals;
|
||||
if (!num_residuals) {
|
||||
LG << "Skipping running minimizer with zero residuals";
|
||||
return;
|
||||
}
|
||||
|
||||
problem.SetParameterBlockConstant(ceres_intrinsics);
|
||||
|
||||
// Configure the solver.
|
||||
ceres::Solver::Options options;
|
||||
options.use_nonmonotonic_steps = true;
|
||||
options.preconditioner_type = ceres::SCHUR_JACOBI;
|
||||
options.linear_solver_type = ceres::ITERATIVE_SCHUR;
|
||||
options.use_explicit_schur_complement = true;
|
||||
options.use_inner_iterations = true;
|
||||
options.max_num_iterations = 100;
|
||||
|
||||
#ifdef _OPENMP
|
||||
options.num_threads = omp_get_max_threads();
|
||||
#if CERES_VERSION_MAJOR <= 1 && CERES_VERSION_MINOR <= 13
|
||||
// deprecated since Ceres 1.14.0
|
||||
options.num_linear_solver_threads = omp_get_max_threads();
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Solve!
|
||||
ceres::Solver::Summary summary;
|
||||
ceres::Solve(options, &problem, &summary);
|
||||
|
||||
LG << "Final report:\n" << summary.FullReport();
|
||||
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void EuclideanBundle(const Tracks &tracks,
|
||||
EuclideanReconstruction *reconstruction) {
|
||||
PolynomialCameraIntrinsics empty_intrinsics;
|
||||
EuclideanBundleCommonIntrinsics(tracks,
|
||||
BUNDLE_NO_INTRINSICS,
|
||||
BUNDLE_NO_CONSTRAINTS,
|
||||
reconstruction,
|
||||
&empty_intrinsics,
|
||||
NULL);
|
||||
}
|
||||
|
||||
void EuclideanBundleCommonIntrinsics(
|
||||
const Tracks &tracks,
|
||||
const int bundle_intrinsics,
|
||||
const int bundle_constraints,
|
||||
EuclideanReconstruction *reconstruction,
|
||||
CameraIntrinsics *intrinsics,
|
||||
BundleEvaluation *evaluation) {
|
||||
LG << "Original intrinsics: " << *intrinsics;
|
||||
vector<Marker> markers = tracks.AllMarkers();
|
||||
|
||||
// N-th element denotes whether track N is a constant zero-weigthed track.
|
||||
vector<bool> zero_weight_tracks_flags(tracks.MaxTrack() + 1, true);
|
||||
|
||||
// Residual blocks with 10 parameters are unwieldy with Ceres, so pack the
|
||||
// intrinsics into a single block and rely on local parameterizations to
|
||||
// control which intrinsics are allowed to vary.
|
||||
double ceres_intrinsics[OFFSET_MAX];
|
||||
PackIntrinisicsIntoArray(*intrinsics, ceres_intrinsics);
|
||||
|
||||
// Convert cameras rotations to angle axis and merge with translation
|
||||
// into single parameter block for maximal minimization speed.
|
||||
//
|
||||
// Block for minimization has got the following structure:
|
||||
// <3 elements for angle-axis> <3 elements for translation>
|
||||
vector<Vec6> all_cameras_R_t =
|
||||
PackCamerasRotationAndTranslation(tracks, *reconstruction);
|
||||
|
||||
// Parameterization used to restrict camera motion for modal solvers.
|
||||
#if CERES_VERSION_MAJOR >= 3 || (CERES_VERSION_MAJOR >= 2 && CERES_VERSION_MINOR >= 1)
|
||||
ceres::SubsetManifold *constant_translation_manifold = NULL;
|
||||
#else
|
||||
ceres::SubsetParameterization *constant_translation_parameterization = NULL;
|
||||
#endif
|
||||
if (bundle_constraints & BUNDLE_NO_TRANSLATION) {
|
||||
std::vector<int> constant_translation;
|
||||
|
||||
// First three elements are rotation, ast three are translation.
|
||||
constant_translation.push_back(3);
|
||||
constant_translation.push_back(4);
|
||||
constant_translation.push_back(5);
|
||||
|
||||
#if CERES_VERSION_MAJOR >= 3 || (CERES_VERSION_MAJOR >= 2 && CERES_VERSION_MINOR >= 1)
|
||||
constant_translation_manifold =
|
||||
new ceres::SubsetManifold(6, constant_translation);
|
||||
#else
|
||||
constant_translation_parameterization =
|
||||
new ceres::SubsetParameterization(6, constant_translation);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Add residual blocks to the problem.
|
||||
ceres::Problem::Options problem_options;
|
||||
ceres::Problem problem(problem_options);
|
||||
int num_residuals = 0;
|
||||
bool have_locked_camera = false;
|
||||
for (int i = 0; i < markers.size(); ++i) {
|
||||
const Marker &marker = markers[i];
|
||||
EuclideanCamera *camera = reconstruction->CameraForImage(marker.image);
|
||||
EuclideanPoint *point = reconstruction->PointForTrack(marker.track);
|
||||
if (camera == NULL || point == NULL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Rotation of camera denoted in angle axis followed with
|
||||
// camera translaiton.
|
||||
double *current_camera_R_t = &all_cameras_R_t[camera->image](0);
|
||||
|
||||
// Skip residual block for markers which does have absolutely
|
||||
// no affect on the final solution.
|
||||
// This way ceres is not gonna to go crazy.
|
||||
if (marker.weight != 0.0) {
|
||||
problem.AddResidualBlock(new ceres::AutoDiffCostFunction<
|
||||
OpenCVReprojectionError, 2, OFFSET_MAX, 6, 3>(
|
||||
new OpenCVReprojectionError(
|
||||
intrinsics->GetDistortionModelType(),
|
||||
marker.x,
|
||||
marker.y,
|
||||
marker.weight)),
|
||||
NULL,
|
||||
ceres_intrinsics,
|
||||
current_camera_R_t,
|
||||
&point->X(0));
|
||||
|
||||
// We lock the first camera to better deal with scene orientation ambiguity.
|
||||
if (!have_locked_camera) {
|
||||
problem.SetParameterBlockConstant(current_camera_R_t);
|
||||
have_locked_camera = true;
|
||||
}
|
||||
|
||||
if (bundle_constraints & BUNDLE_NO_TRANSLATION) {
|
||||
#if CERES_VERSION_MAJOR >= 3 || (CERES_VERSION_MAJOR >= 2 && CERES_VERSION_MINOR >= 1)
|
||||
problem.SetManifold(current_camera_R_t,
|
||||
constant_translation_manifold);
|
||||
#else
|
||||
problem.SetParameterization(current_camera_R_t,
|
||||
constant_translation_parameterization);
|
||||
#endif
|
||||
}
|
||||
|
||||
zero_weight_tracks_flags[marker.track] = false;
|
||||
num_residuals++;
|
||||
}
|
||||
}
|
||||
LG << "Number of residuals: " << num_residuals;
|
||||
|
||||
if (!num_residuals) {
|
||||
LG << "Skipping running minimizer with zero residuals";
|
||||
return;
|
||||
}
|
||||
|
||||
if (intrinsics->GetDistortionModelType() == DISTORTION_MODEL_DIVISION &&
|
||||
(bundle_intrinsics & BUNDLE_TANGENTIAL) != 0) {
|
||||
LOG(FATAL) << "Division model doesn't support bundling "
|
||||
"of tangential distortion";
|
||||
}
|
||||
|
||||
BundleIntrinsicsLogMessage(bundle_intrinsics);
|
||||
|
||||
if (bundle_intrinsics == BUNDLE_NO_INTRINSICS) {
|
||||
// No camera intrinsics are being refined,
|
||||
// set the whole parameter block as constant for best performance.
|
||||
problem.SetParameterBlockConstant(ceres_intrinsics);
|
||||
} else {
|
||||
// Set the camera intrinsics that are not to be bundled as
|
||||
// constant using some macro trickery.
|
||||
|
||||
std::vector<int> constant_intrinsics;
|
||||
#define MAYBE_SET_CONSTANT(bundle_enum, offset) \
|
||||
if (!(bundle_intrinsics & bundle_enum)) { \
|
||||
constant_intrinsics.push_back(offset); \
|
||||
}
|
||||
MAYBE_SET_CONSTANT(BUNDLE_FOCAL_LENGTH, OFFSET_FOCAL_LENGTH);
|
||||
MAYBE_SET_CONSTANT(BUNDLE_PRINCIPAL_POINT, OFFSET_PRINCIPAL_POINT_X);
|
||||
MAYBE_SET_CONSTANT(BUNDLE_PRINCIPAL_POINT, OFFSET_PRINCIPAL_POINT_Y);
|
||||
MAYBE_SET_CONSTANT(BUNDLE_RADIAL_K1, OFFSET_K1);
|
||||
MAYBE_SET_CONSTANT(BUNDLE_RADIAL_K2, OFFSET_K2);
|
||||
MAYBE_SET_CONSTANT(BUNDLE_TANGENTIAL_P1, OFFSET_P1);
|
||||
MAYBE_SET_CONSTANT(BUNDLE_TANGENTIAL_P2, OFFSET_P2);
|
||||
#undef MAYBE_SET_CONSTANT
|
||||
|
||||
// Always set K3 constant, it's not used at the moment.
|
||||
constant_intrinsics.push_back(OFFSET_K3);
|
||||
|
||||
#if CERES_VERSION_MAJOR >= 3 || (CERES_VERSION_MAJOR >= 2 && CERES_VERSION_MINOR >= 1)
|
||||
ceres::SubsetManifold *subset_manifold =
|
||||
new ceres::SubsetManifold(OFFSET_MAX, constant_intrinsics);
|
||||
|
||||
problem.SetManifold(ceres_intrinsics, subset_manifold);
|
||||
#else
|
||||
ceres::SubsetParameterization *subset_parameterization =
|
||||
new ceres::SubsetParameterization(OFFSET_MAX, constant_intrinsics);
|
||||
|
||||
problem.SetParameterization(ceres_intrinsics, subset_parameterization);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Configure the solver.
|
||||
ceres::Solver::Options options;
|
||||
options.use_nonmonotonic_steps = true;
|
||||
options.preconditioner_type = ceres::SCHUR_JACOBI;
|
||||
options.linear_solver_type = ceres::ITERATIVE_SCHUR;
|
||||
options.use_explicit_schur_complement = true;
|
||||
options.use_inner_iterations = true;
|
||||
options.max_num_iterations = 100;
|
||||
|
||||
#ifdef _OPENMP
|
||||
options.num_threads = omp_get_max_threads();
|
||||
#if CERES_VERSION_MAJOR <= 1 && CERES_VERSION_MINOR <= 13
|
||||
// deprecated since Ceres 1.14.0
|
||||
options.num_linear_solver_threads = omp_get_max_threads();
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Solve!
|
||||
ceres::Solver::Summary summary;
|
||||
ceres::Solve(options, &problem, &summary);
|
||||
|
||||
LG << "Final report:\n" << summary.FullReport();
|
||||
|
||||
// Copy rotations and translations back.
|
||||
UnpackCamerasRotationAndTranslation(tracks,
|
||||
all_cameras_R_t,
|
||||
reconstruction);
|
||||
|
||||
// Copy intrinsics back.
|
||||
if (bundle_intrinsics != BUNDLE_NO_INTRINSICS)
|
||||
UnpackIntrinsicsFromArray(ceres_intrinsics, intrinsics);
|
||||
|
||||
LG << "Final intrinsics: " << *intrinsics;
|
||||
|
||||
if (evaluation) {
|
||||
EuclideanBundlerPerformEvaluation(tracks, reconstruction, &all_cameras_R_t,
|
||||
&problem, evaluation);
|
||||
}
|
||||
|
||||
// Separate step to adjust positions of tracks which are
|
||||
// constant zero-weighted.
|
||||
vector<Marker> zero_weight_markers;
|
||||
for (int track = 0; track < tracks.MaxTrack(); ++track) {
|
||||
if (zero_weight_tracks_flags[track]) {
|
||||
vector<Marker> current_markers = tracks.MarkersForTrack(track);
|
||||
zero_weight_markers.reserve(zero_weight_markers.size() +
|
||||
current_markers.size());
|
||||
for (int i = 0; i < current_markers.size(); ++i) {
|
||||
zero_weight_markers.push_back(current_markers[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (zero_weight_markers.size()) {
|
||||
LG << "Refining position of constant zero-weighted tracks";
|
||||
EuclideanBundlePointsOnly(intrinsics->GetDistortionModelType(),
|
||||
zero_weight_markers,
|
||||
all_cameras_R_t,
|
||||
ceres_intrinsics,
|
||||
reconstruction);
|
||||
}
|
||||
}
|
||||
|
||||
void ProjectiveBundle(const Tracks & /*tracks*/,
|
||||
ProjectiveReconstruction * /*reconstruction*/) {
|
||||
// TODO(keir): Implement this! This can't work until we have a better bundler
|
||||
// than SSBA, since SSBA has no support for projective bundling.
|
||||
}
|
||||
|
||||
} // namespace libmv
|
||||