├── CMakeLists.txt ├── LICENSE ├── cmake_scripts ├── Config.cmake.in ├── ConfigVersion.cmake.in ├── LibEpipolarConsistencyConfig.cmake ├── LibEpipolarConsistencyConfigVersion.cmake ├── LibGeometryCalibrationConfig.cmake ├── LibGeometryCalibrationConfigVersion.cmake ├── LibProjectiveGeometryConfig.cmake ├── LibProjectiveGeometryConfigVersion.cmake ├── LibRayCastBackprojectConfig.cmake ├── LibRayCastBackprojectConfigVersion.cmake ├── LibSimpleConfig.cmake ├── LibSimpleConfigVersion.cmake ├── LibUtilsCudaConfig.cmake ├── LibUtilsCudaConfigVersion.cmake ├── LibUtilsGLConfig.cmake ├── LibUtilsGLConfigVersion.cmake ├── LibUtilsQtConfig.cmake ├── LibUtilsQtConfigVersion.cmake ├── add_package.cmake ├── findAndTestCUDA.cmake ├── has_cuda_gpu.cpp └── qt5_win32_copy_dlls.cmake ├── code ├── HeaderOnly │ ├── LibOpterix │ │ ├── Opterix.hxx │ │ ├── ParameterGui.hxx │ │ ├── ParameterModel.hxx │ │ └── WrapNLOpt.hxx │ ├── NRRD │ │ ├── BaseTypes.hxx │ │ ├── GetSetCmdLine.hxx │ │ ├── GetSetMinimal.hxx │ │ ├── StringConversion.hxx │ │ ├── StringType.hxx │ │ ├── StringUtil.hxx │ │ ├── nrrd.hxx │ │ ├── nrrd_connected_components.hxx │ │ ├── nrrd_frst.hxx │ │ ├── nrrd_image.hxx │ │ ├── nrrd_image_stack.hxx │ │ ├── nrrd_image_view.hxx │ │ ├── nrrd_itk.hxx │ │ ├── nrrd_local_crorrelation.hxx │ │ ├── nrrd_lowpass.hxx │ │ ├── nrrd_metaio.hxx │ │ ├── nrrd_morphology.hxx │ │ └── nrrd_transform.hxx │ └── Utils │ │ ├── ITKUtils.hxx │ │ ├── ProgressInterface.hxx │ │ ├── Projtable.hxx │ │ ├── TimerWin32.hxx │ │ └── UglyXML.hxx ├── LibEpipolarConsistency │ ├── CMakeLists.txt │ ├── EpipolarConsistency.cpp │ ├── EpipolarConsistency.h │ ├── EpipolarConsistencyCommon.hxx │ ├── EpipolarConsistencyDirect.cpp │ ├── EpipolarConsistencyDirect.cu │ ├── EpipolarConsistencyDirect.h │ ├── EpipolarConsistencyRadonIntermediate.cpp │ ├── EpipolarConsistencyRadonIntermediate.cu │ ├── EpipolarConsistencyRadonIntermediate.h │ ├── EpipolarConsistencyRadonIntermediateCPU.hxx │ ├── Gui │ │ ├── ComputeRadonIntermediate.hxx │ │ ├── DisplayGeometry.hxx │ │ ├── FDCTMotionCorrection.hxx │ │ ├── InputDataDirect.cpp │ │ ├── InputDataDirect.h │ │ ├── InputDataRadonIntermediate.cpp │ │ ├── InputDataRadonIntermediate.h │ │ ├── PreProccess.cpp │ │ ├── PreProccess.h │ │ ├── Registration.cpp │ │ ├── Registration.h │ │ ├── SingleImageMotion.h │ │ ├── SingleImageMotion.hxx │ │ ├── Visualization.cpp │ │ └── Visualization.h │ ├── RadonIntermediate.cpp │ ├── RadonIntermediate.cu │ ├── RadonIntermediate.h │ ├── Rectification.cu │ └── RectifiedFBCC.h ├── LibGeometryCalibration │ ├── BeadDetection.cpp │ ├── BeadDetection.h │ ├── BeadPhantomGui.hxx │ ├── CMakeLists.txt │ ├── EstimateProjectionMatrix.cpp │ ├── EstimateProjectionMatrix.h │ ├── GeometryCalibration.cpp │ ├── GeometryCalibration.h │ ├── PhantomPDS2.cpp │ ├── PhantomPDS2.h │ └── main_pds2.cpp ├── LibProjectiveGeometry │ ├── CMakeLists.txt │ ├── CameraOpenGL.hxx │ ├── EigenToStr.hxx │ ├── EstimateProjectionMatrix.cpp │ ├── EstimateProjectionMatrix.h │ ├── GeometryVisualization.hxx │ ├── LibOpterix │ │ ├── Opterix.hxx │ │ ├── ParameterGui.hxx │ │ ├── ParameterModel.hxx │ │ └── WrapNLOpt.hxx │ ├── Models │ │ ├── ModelCameraKRt.hxx │ │ ├── ModelCameraSimilarity2D3D.hxx │ │ ├── ModelFDCTCalibrationCorrection.hxx │ │ ├── ModelHomography2D.hxx │ │ ├── ModelHomography3D.hxx │ │ ├── ModelSimilarity2D.hxx │ │ ├── ModelSimilarity3D.hxx │ │ └── ModelTrajectoryIEC61217.hxx │ ├── ProjectionMatrix.cpp │ ├── ProjectionMatrix.h │ ├── ProjectiveGeometry.hxx │ ├── SingularValueDecomposition.cpp │ ├── SingularValueDecomposition.h │ ├── SourceDetectorGeometry.cpp │ └── SourceDetectorGeometry.h ├── LibRayCastBackproject │ ├── CMakeLists.txt │ ├── Reconstruction.cpp │ ├── Reconstruction.cu │ ├── Reconstruction.h │ ├── VolumeRendering.cpp │ ├── VolumeRendering.cu │ ├── VolumeRendering.h │ ├── VolumeRenderingGui.cpp │ ├── VolumeRenderingGui.h │ ├── VoxelData.cpp │ ├── VoxelData.cu │ ├── VoxelData.h │ ├── ray_box_intersection.hxx │ ├── vr_cuda.hxx │ ├── vr_ray_geom_setup.cu │ ├── vr_raycast_debug.cu │ ├── vr_raycast_drr.cu │ ├── vr_raycast_ea_1Dtf.cu │ ├── vr_raycast_iso.cu │ └── vr_raycast_mip.cu ├── LibSimple │ ├── BufferUtils.h │ ├── CMakeLists.txt │ ├── GL │ │ ├── glad.c │ │ ├── glad.h │ │ └── khrplatform.h │ ├── SimpleEmptySpaceSkipping.cpp │ ├── SimpleEmptySpaceSkipping.h │ ├── SimpleGL.cpp │ ├── SimpleGL.h │ ├── SimpleMHD.cpp │ ├── SimpleMHD.h │ ├── SimpleOptimizer.cpp │ ├── SimpleOptimizer.h │ ├── SimpleQTGL.cpp │ ├── SimpleQTGL.h │ ├── SimpleRayCastPass.cpp │ ├── SimpleRayCastPass.h │ ├── SimpleVR.cpp │ └── SimpleVR.h ├── LibUtilsCuda │ ├── CMakeLists.txt │ ├── CudaAlgorithms.cpp │ ├── CudaAlgorithms.h │ ├── CudaBindlessTexture.cpp │ ├── CudaBindlessTexture.cu │ ├── CudaBindlessTexture.h │ ├── CudaConvolution.cu │ ├── CudaMemory.cpp │ ├── CudaMemory.h │ ├── CudaTextureArray.hxx │ ├── TestCudaUtils.cpp │ ├── TestCudaUtils.cu │ ├── UtilsCuda.hxx │ ├── culaut │ │ ├── culaut.hxx │ │ ├── xgeinv.hxx │ │ ├── xgemm.hxx │ │ ├── xgemv.hxx │ │ ├── xprojectionmatrix.hxx │ │ └── xprojectivegeometry.hxx │ └── cutil_math.h └── LibUtilsQt │ ├── CMakeLists.txt │ ├── EventFilters.cpp │ ├── EventFilters.h │ ├── Figure.hxx │ ├── FigureWindow.cpp │ ├── FigureWindow.h │ ├── GraphicsItemConvexMesh.hxx │ ├── GraphicsItems.hxx │ ├── Plot.hxx │ ├── ProjectionParameters.hxx │ ├── QCameraView.cpp │ ├── QCameraView.h │ ├── QCustomPlot.cpp │ ├── QCustomPlot.h │ ├── QGLPlot3D.cpp │ ├── QGLPlot3D.h │ └── nrrdqt.hxx ├── config ├── VisualizeECC.ini ├── example_data │ ├── proj000.nrrd │ └── proj040.nrrd └── resources │ ├── arrow_ne.svg │ ├── move.svg │ ├── rotate.svg │ └── select_rect.svg ├── examples.gitignore ├── matlab ├── ecc_demo.m ├── ecc_demo │ ├── ecc_computeK01.m │ ├── ecc_compute_consistency.m │ ├── ecc_compute_dtr.m │ ├── ecc_sample_dtr.m │ ├── ecc_sample_dtr_debug.m │ └── line_to_angle_distance.m ├── ecc_load_data.m ├── ecc_plot_uv.m ├── pluecker │ ├── join.m │ ├── join3.m │ ├── meet.m │ ├── pluecker_closest_point_to_origin.m │ ├── pluecker_direction.m │ ├── pluecker_distance_to_origin.m │ ├── pluecker_join.m │ ├── pluecker_matrix.m │ ├── pluecker_matrix3.m │ ├── pluecker_matrix_dual.m │ ├── pluecker_meet.m │ └── pluecker_moment.m └── utility │ ├── camera_normalize.m │ ├── ecc_show_lines.m │ ├── line_stroke.m │ └── nrrdread.m ├── readme.md └── tools ├── ComputeRadonIntermediate ├── CMakeLists.txt └── ComputeRadonIntermediate.cpp ├── ConsistencyDemo ├── CMakeLists.txt └── main.cpp ├── FDCTCalibrationCorrection ├── AlgorithmsNLoptFDCTCalibrationCorrection.hxx ├── CMakeLists.txt └── FDCTCalibrationCorrection.cpp ├── FDCTMotionCorrection ├── CMakeLists.txt ├── EpipolarConsistencyCalibration.hxx ├── ModelFDCT.hxx └── main_gradient_free.cpp ├── FluoroTracking ├── CMakeLists.txt ├── FluoroTracking.cpp ├── FluoroTracking_rectify.cpp └── compute_line_integrals.cu ├── Registration ├── CMakeLists.txt ├── Registration.cpp ├── Registration3D3D.hxx ├── RegistrationIntensityBased.cpp └── warp3d.cu ├── Registration2D3D ├── CMakeLists.txt ├── ComputeDRR.cpp ├── Registration2D3D.cpp ├── Registration2D3D.h └── main.cpp ├── TrajectoryView ├── CMakeLists.txt ├── file.xcf ├── icon.ico ├── icon.png ├── icon_win.aps ├── icon_win.rc └── main_trajectoryview.cpp ├── VisualizeECC ├── CMakeLists.txt ├── VisualizeECC.cpp ├── VisualizeECC_ComputedTomography.cpp ├── VisualizeECC_RadonIntermediate.cpp └── draw_epipolar_lines.hxx ├── VolumeRendering ├── CMakeLists.txt └── volume_renderer.cpp ├── nrrdView ├── CMakeLists.txt ├── file.xcf ├── icon.ico ├── icon.png ├── icon_win.rc └── nrrdView.cpp └── projtable2ompl ├── CMakeLists.txt ├── ompl2projtable.cpp ├── ompl2rtkgeometry.cpp └── projtable2ompl.cpp /cmake_scripts/Config.cmake.in: -------------------------------------------------------------------------------- 1 | get_filename_component(myDir ${CMAKE_CURRENT_LIST_FILE} PATH) 2 | get_filename_component(rootDir ${myDir} ABSOLUTE) 3 | 4 | # set the version of myself 5 | set(@LIB_NAME_CAPS@_VERSION_MAJOR @VERSION_MAJOR@) 6 | set(@LIB_NAME_CAPS@_VERSION_MINOR @VERSION_MINOR@) 7 | set(@LIB_NAME_CAPS@_VERSION_PATCH @VERSION_PATCH@) 8 | set(@LIB_NAME_CAPS@_VERSION ${@LIB_NAME_CAPS@_VERSION_MAJOR}.${@LIB_NAME_CAPS@_VERSION_MINOR}.${@LIB_NAME_CAPS@_VERSION_PATCH} ) 9 | 10 | # what is my include directory 11 | set(@LIB_NAME_CAPS@_INCLUDE_DIRS "${rootDir}/include") 12 | set(@LIB_NAME_CAPS@_DIR "${rootDir}") 13 | 14 | # import the exported targets 15 | include(${myDir}/cmake/@LIB_NAME@-targets.cmake) 16 | 17 | # set the expected library variable 18 | set(@LIB_NAME_CAPS@_LIBRARIES @LIB_NAME@ ) 19 | -------------------------------------------------------------------------------- /cmake_scripts/ConfigVersion.cmake.in: -------------------------------------------------------------------------------- 1 | # This is a very basic file for the new style find_package() search mode, 2 | # i.e. Config-mode. 3 | # In this mode find_package() searches for a Config.cmake 4 | # file and an associated Version.cmake file, which it loads to check 5 | # the version number. 6 | # This file can be used with configure_file() to generate such a file for a project 7 | # with very basic logic. 8 | # It sets PACKAGE_VERSION_EXACT if the current version string and the requested 9 | # version string are exactly the same and it sets PACKAGE_VERSION_COMPATIBLE 10 | # if the current version is >= requested version. 11 | # If this is not good enough for your project, you need to write your own 12 | # improved Version.cmake file. 13 | 14 | 15 | set(PACKAGE_VERSION @VERSION_MAJOR@.@VERSION_MINOR@.@VERSION_PATCH@) 16 | 17 | if("${PACKAGE_VERSION}" VERSION_LESS "${PACKAGE_FIND_VERSION}" ) 18 | set(PACKAGE_VERSION_COMPATIBLE FALSE) 19 | else("${PACKAGE_VERSION}" VERSION_LESS "${PACKAGE_FIND_VERSION}" ) 20 | set(PACKAGE_VERSION_COMPATIBLE TRUE) 21 | if( "${PACKAGE_FIND_VERSION}" STREQUAL "${PACKAGE_VERSION}") 22 | set(PACKAGE_VERSION_EXACT TRUE) 23 | endif( "${PACKAGE_FIND_VERSION}" STREQUAL "${PACKAGE_VERSION}") 24 | endif("${PACKAGE_VERSION}" VERSION_LESS "${PACKAGE_FIND_VERSION}" ) -------------------------------------------------------------------------------- /cmake_scripts/LibEpipolarConsistencyConfig.cmake: -------------------------------------------------------------------------------- 1 | get_filename_component(myDir ${CMAKE_CURRENT_LIST_FILE} PATH) 2 | get_filename_component(rootDir ${myDir} ABSOLUTE) 3 | 4 | # set the version of myself 5 | set(LIBEPIPOLARCONSISTENCY_VERSION_MAJOR 1) 6 | set(LIBEPIPOLARCONSISTENCY_VERSION_MINOR 2) 7 | set(LIBEPIPOLARCONSISTENCY_VERSION_PATCH 2) 8 | set(LIBEPIPOLARCONSISTENCY_VERSION ${LIBEPIPOLARCONSISTENCY_VERSION_MAJOR}.${LIBEPIPOLARCONSISTENCY_VERSION_MINOR}.${LIBEPIPOLARCONSISTENCY_VERSION_PATCH} ) 9 | 10 | # what is my include directory 11 | set(LIBEPIPOLARCONSISTENCY_INCLUDE_DIRS "${rootDir}/include") 12 | set(LIBEPIPOLARCONSISTENCY_DIR "${rootDir}") 13 | 14 | # import the exported targets 15 | include(${myDir}/cmake/LibEpipolarConsistency-targets.cmake) 16 | 17 | # set the expected library variable 18 | set(LIBEPIPOLARCONSISTENCY_LIBRARIES LibEpipolarConsistency ) 19 | -------------------------------------------------------------------------------- /cmake_scripts/LibEpipolarConsistencyConfigVersion.cmake: -------------------------------------------------------------------------------- 1 | # This is a very basic file for the new style find_package() search mode, 2 | # i.e. Config-mode. 3 | # In this mode find_package() searches for a Config.cmake 4 | # file and an associated Version.cmake file, which it loads to check 5 | # the version number. 6 | # This file can be used with configure_file() to generate such a file for a project 7 | # with very basic logic. 8 | # It sets PACKAGE_VERSION_EXACT if the current version string and the requested 9 | # version string are exactly the same and it sets PACKAGE_VERSION_COMPATIBLE 10 | # if the current version is >= requested version. 11 | # If this is not good enough for your project, you need to write your own 12 | # improved Version.cmake file. 13 | 14 | 15 | set(PACKAGE_VERSION 1.2.2) 16 | 17 | if("${PACKAGE_VERSION}" VERSION_LESS "${PACKAGE_FIND_VERSION}" ) 18 | set(PACKAGE_VERSION_COMPATIBLE FALSE) 19 | else("${PACKAGE_VERSION}" VERSION_LESS "${PACKAGE_FIND_VERSION}" ) 20 | set(PACKAGE_VERSION_COMPATIBLE TRUE) 21 | if( "${PACKAGE_FIND_VERSION}" STREQUAL "${PACKAGE_VERSION}") 22 | set(PACKAGE_VERSION_EXACT TRUE) 23 | endif( "${PACKAGE_FIND_VERSION}" STREQUAL "${PACKAGE_VERSION}") 24 | endif("${PACKAGE_VERSION}" VERSION_LESS "${PACKAGE_FIND_VERSION}" ) 25 | -------------------------------------------------------------------------------- /cmake_scripts/LibGeometryCalibrationConfig.cmake: -------------------------------------------------------------------------------- 1 | get_filename_component(myDir ${CMAKE_CURRENT_LIST_FILE} PATH) 2 | get_filename_component(rootDir ${myDir} ABSOLUTE) 3 | 4 | # set the version of myself 5 | set(LIBGEOMETRYCALIBRATION_VERSION_MAJOR 1) 6 | set(LIBGEOMETRYCALIBRATION_VERSION_MINOR 2) 7 | set(LIBGEOMETRYCALIBRATION_VERSION_PATCH 2) 8 | set(LIBGEOMETRYCALIBRATION_VERSION ${LIBGEOMETRYCALIBRATION_VERSION_MAJOR}.${LIBGEOMETRYCALIBRATION_VERSION_MINOR}.${LIBGEOMETRYCALIBRATION_VERSION_PATCH} ) 9 | 10 | # what is my include directory 11 | set(LIBGEOMETRYCALIBRATION_INCLUDE_DIRS "${rootDir}/include") 12 | set(LIBGEOMETRYCALIBRATION_DIR "${rootDir}") 13 | 14 | # import the exported targets 15 | include(${myDir}/cmake/LibGeometryCalibration-targets.cmake) 16 | 17 | # set the expected library variable 18 | set(LIBGEOMETRYCALIBRATION_LIBRARIES LibGeometryCalibration ) 19 | -------------------------------------------------------------------------------- /cmake_scripts/LibGeometryCalibrationConfigVersion.cmake: -------------------------------------------------------------------------------- 1 | # This is a very basic file for the new style find_package() search mode, 2 | # i.e. Config-mode. 3 | # In this mode find_package() searches for a Config.cmake 4 | # file and an associated Version.cmake file, which it loads to check 5 | # the version number. 6 | # This file can be used with configure_file() to generate such a file for a project 7 | # with very basic logic. 8 | # It sets PACKAGE_VERSION_EXACT if the current version string and the requested 9 | # version string are exactly the same and it sets PACKAGE_VERSION_COMPATIBLE 10 | # if the current version is >= requested version. 11 | # If this is not good enough for your project, you need to write your own 12 | # improved Version.cmake file. 13 | 14 | 15 | set(PACKAGE_VERSION 1.2.2) 16 | 17 | if("${PACKAGE_VERSION}" VERSION_LESS "${PACKAGE_FIND_VERSION}" ) 18 | set(PACKAGE_VERSION_COMPATIBLE FALSE) 19 | else("${PACKAGE_VERSION}" VERSION_LESS "${PACKAGE_FIND_VERSION}" ) 20 | set(PACKAGE_VERSION_COMPATIBLE TRUE) 21 | if( "${PACKAGE_FIND_VERSION}" STREQUAL "${PACKAGE_VERSION}") 22 | set(PACKAGE_VERSION_EXACT TRUE) 23 | endif( "${PACKAGE_FIND_VERSION}" STREQUAL "${PACKAGE_VERSION}") 24 | endif("${PACKAGE_VERSION}" VERSION_LESS "${PACKAGE_FIND_VERSION}" ) 25 | -------------------------------------------------------------------------------- /cmake_scripts/LibProjectiveGeometryConfig.cmake: -------------------------------------------------------------------------------- 1 | get_filename_component(myDir ${CMAKE_CURRENT_LIST_FILE} PATH) 2 | get_filename_component(rootDir ${myDir} ABSOLUTE) 3 | 4 | # set the version of myself 5 | set(LIBPROJECTIVEGEOMETRY_VERSION_MAJOR 1) 6 | set(LIBPROJECTIVEGEOMETRY_VERSION_MINOR 2) 7 | set(LIBPROJECTIVEGEOMETRY_VERSION_PATCH 2) 8 | set(LIBPROJECTIVEGEOMETRY_VERSION ${LIBPROJECTIVEGEOMETRY_VERSION_MAJOR}.${LIBPROJECTIVEGEOMETRY_VERSION_MINOR}.${LIBPROJECTIVEGEOMETRY_VERSION_PATCH} ) 9 | 10 | # what is my include directory 11 | set(LIBPROJECTIVEGEOMETRY_INCLUDE_DIRS "${rootDir}/include") 12 | set(LIBPROJECTIVEGEOMETRY_DIR "${rootDir}") 13 | 14 | # import the exported targets 15 | include(${myDir}/cmake/LibProjectiveGeometry-targets.cmake) 16 | 17 | # set the expected library variable 18 | set(LIBPROJECTIVEGEOMETRY_LIBRARIES LibProjectiveGeometry ) 19 | -------------------------------------------------------------------------------- /cmake_scripts/LibProjectiveGeometryConfigVersion.cmake: -------------------------------------------------------------------------------- 1 | # This is a very basic file for the new style find_package() search mode, 2 | # i.e. Config-mode. 3 | # In this mode find_package() searches for a Config.cmake 4 | # file and an associated Version.cmake file, which it loads to check 5 | # the version number. 6 | # This file can be used with configure_file() to generate such a file for a project 7 | # with very basic logic. 8 | # It sets PACKAGE_VERSION_EXACT if the current version string and the requested 9 | # version string are exactly the same and it sets PACKAGE_VERSION_COMPATIBLE 10 | # if the current version is >= requested version. 11 | # If this is not good enough for your project, you need to write your own 12 | # improved Version.cmake file. 13 | 14 | 15 | set(PACKAGE_VERSION 1.2.2) 16 | 17 | if("${PACKAGE_VERSION}" VERSION_LESS "${PACKAGE_FIND_VERSION}" ) 18 | set(PACKAGE_VERSION_COMPATIBLE FALSE) 19 | else("${PACKAGE_VERSION}" VERSION_LESS "${PACKAGE_FIND_VERSION}" ) 20 | set(PACKAGE_VERSION_COMPATIBLE TRUE) 21 | if( "${PACKAGE_FIND_VERSION}" STREQUAL "${PACKAGE_VERSION}") 22 | set(PACKAGE_VERSION_EXACT TRUE) 23 | endif( "${PACKAGE_FIND_VERSION}" STREQUAL "${PACKAGE_VERSION}") 24 | endif("${PACKAGE_VERSION}" VERSION_LESS "${PACKAGE_FIND_VERSION}" ) 25 | -------------------------------------------------------------------------------- /cmake_scripts/LibRayCastBackprojectConfig.cmake: -------------------------------------------------------------------------------- 1 | get_filename_component(myDir ${CMAKE_CURRENT_LIST_FILE} PATH) 2 | get_filename_component(rootDir ${myDir} ABSOLUTE) 3 | 4 | # set the version of myself 5 | set(LIBRAYCASTBACKPROJECT_VERSION_MAJOR 1) 6 | set(LIBRAYCASTBACKPROJECT_VERSION_MINOR 2) 7 | set(LIBRAYCASTBACKPROJECT_VERSION_PATCH 2) 8 | set(LIBRAYCASTBACKPROJECT_VERSION ${LIBRAYCASTBACKPROJECT_VERSION_MAJOR}.${LIBRAYCASTBACKPROJECT_VERSION_MINOR}.${LIBRAYCASTBACKPROJECT_VERSION_PATCH} ) 9 | 10 | # what is my include directory 11 | set(LIBRAYCASTBACKPROJECT_INCLUDE_DIRS "${rootDir}/include") 12 | set(LIBRAYCASTBACKPROJECT_DIR "${rootDir}") 13 | 14 | # import the exported targets 15 | include(${myDir}/cmake/LibRayCastBackproject-targets.cmake) 16 | 17 | # set the expected library variable 18 | set(LIBRAYCASTBACKPROJECT_LIBRARIES LibRayCastBackproject ) 19 | -------------------------------------------------------------------------------- /cmake_scripts/LibRayCastBackprojectConfigVersion.cmake: -------------------------------------------------------------------------------- 1 | # This is a very basic file for the new style find_package() search mode, 2 | # i.e. Config-mode. 3 | # In this mode find_package() searches for a Config.cmake 4 | # file and an associated Version.cmake file, which it loads to check 5 | # the version number. 6 | # This file can be used with configure_file() to generate such a file for a project 7 | # with very basic logic. 8 | # It sets PACKAGE_VERSION_EXACT if the current version string and the requested 9 | # version string are exactly the same and it sets PACKAGE_VERSION_COMPATIBLE 10 | # if the current version is >= requested version. 11 | # If this is not good enough for your project, you need to write your own 12 | # improved Version.cmake file. 13 | 14 | 15 | set(PACKAGE_VERSION 1.2.2) 16 | 17 | if("${PACKAGE_VERSION}" VERSION_LESS "${PACKAGE_FIND_VERSION}" ) 18 | set(PACKAGE_VERSION_COMPATIBLE FALSE) 19 | else("${PACKAGE_VERSION}" VERSION_LESS "${PACKAGE_FIND_VERSION}" ) 20 | set(PACKAGE_VERSION_COMPATIBLE TRUE) 21 | if( "${PACKAGE_FIND_VERSION}" STREQUAL "${PACKAGE_VERSION}") 22 | set(PACKAGE_VERSION_EXACT TRUE) 23 | endif( "${PACKAGE_FIND_VERSION}" STREQUAL "${PACKAGE_VERSION}") 24 | endif("${PACKAGE_VERSION}" VERSION_LESS "${PACKAGE_FIND_VERSION}" ) 25 | -------------------------------------------------------------------------------- /cmake_scripts/LibSimpleConfig.cmake: -------------------------------------------------------------------------------- 1 | get_filename_component(myDir ${CMAKE_CURRENT_LIST_FILE} PATH) 2 | get_filename_component(rootDir ${myDir} ABSOLUTE) 3 | 4 | # set the version of myself 5 | set(LIBSIMPLE_VERSION_MAJOR 0) 6 | set(LIBSIMPLE_VERSION_MINOR 0) 7 | set(LIBSIMPLE_VERSION_PATCH 1) 8 | set(LIBSIMPLE_VERSION ${LIBSIMPLE_VERSION_MAJOR}.${LIBSIMPLE_VERSION_MINOR}.${LIBSIMPLE_VERSION_PATCH} ) 9 | 10 | # what is my include directory 11 | set(LIBSIMPLE_INCLUDE_DIRS "${rootDir}/include") 12 | set(LIBSIMPLE_DIR "${rootDir}") 13 | 14 | # import the exported targets 15 | include(${myDir}/cmake/LibSimple-targets.cmake) 16 | 17 | # set the expected library variable 18 | set(LIBSIMPLE_LIBRARIES LibSimple ) 19 | -------------------------------------------------------------------------------- /cmake_scripts/LibSimpleConfigVersion.cmake: -------------------------------------------------------------------------------- 1 | # This is a very basic file for the new style find_package() search mode, 2 | # i.e. Config-mode. 3 | # In this mode find_package() searches for a Config.cmake 4 | # file and an associated Version.cmake file, which it loads to check 5 | # the version number. 6 | # This file can be used with configure_file() to generate such a file for a project 7 | # with very basic logic. 8 | # It sets PACKAGE_VERSION_EXACT if the current version string and the requested 9 | # version string are exactly the same and it sets PACKAGE_VERSION_COMPATIBLE 10 | # if the current version is >= requested version. 11 | # If this is not good enough for your project, you need to write your own 12 | # improved Version.cmake file. 13 | 14 | 15 | set(PACKAGE_VERSION 0.0.1) 16 | 17 | if("${PACKAGE_VERSION}" VERSION_LESS "${PACKAGE_FIND_VERSION}" ) 18 | set(PACKAGE_VERSION_COMPATIBLE FALSE) 19 | else("${PACKAGE_VERSION}" VERSION_LESS "${PACKAGE_FIND_VERSION}" ) 20 | set(PACKAGE_VERSION_COMPATIBLE TRUE) 21 | if( "${PACKAGE_FIND_VERSION}" STREQUAL "${PACKAGE_VERSION}") 22 | set(PACKAGE_VERSION_EXACT TRUE) 23 | endif( "${PACKAGE_FIND_VERSION}" STREQUAL "${PACKAGE_VERSION}") 24 | endif("${PACKAGE_VERSION}" VERSION_LESS "${PACKAGE_FIND_VERSION}" ) 25 | -------------------------------------------------------------------------------- /cmake_scripts/LibUtilsCudaConfig.cmake: -------------------------------------------------------------------------------- 1 | get_filename_component(myDir ${CMAKE_CURRENT_LIST_FILE} PATH) 2 | get_filename_component(rootDir ${myDir} ABSOLUTE) 3 | 4 | # set the version of myself 5 | set(LIBUTILSCUDA_VERSION_MAJOR 1) 6 | set(LIBUTILSCUDA_VERSION_MINOR 2) 7 | set(LIBUTILSCUDA_VERSION_PATCH 2) 8 | set(LIBUTILSCUDA_VERSION ${LIBUTILSCUDA_VERSION_MAJOR}.${LIBUTILSCUDA_VERSION_MINOR}.${LIBUTILSCUDA_VERSION_PATCH} ) 9 | 10 | # what is my include directory 11 | set(LIBUTILSCUDA_INCLUDE_DIRS "${rootDir}/include") 12 | set(LIBUTILSCUDA_DIR "${rootDir}") 13 | 14 | # import the exported targets 15 | include(${myDir}/cmake/LibUtilsCuda-targets.cmake) 16 | 17 | # set the expected library variable 18 | set(LIBUTILSCUDA_LIBRARIES LibUtilsCuda ) 19 | -------------------------------------------------------------------------------- /cmake_scripts/LibUtilsCudaConfigVersion.cmake: -------------------------------------------------------------------------------- 1 | # This is a very basic file for the new style find_package() search mode, 2 | # i.e. Config-mode. 3 | # In this mode find_package() searches for a Config.cmake 4 | # file and an associated Version.cmake file, which it loads to check 5 | # the version number. 6 | # This file can be used with configure_file() to generate such a file for a project 7 | # with very basic logic. 8 | # It sets PACKAGE_VERSION_EXACT if the current version string and the requested 9 | # version string are exactly the same and it sets PACKAGE_VERSION_COMPATIBLE 10 | # if the current version is >= requested version. 11 | # If this is not good enough for your project, you need to write your own 12 | # improved Version.cmake file. 13 | 14 | 15 | set(PACKAGE_VERSION 1.2.2) 16 | 17 | if("${PACKAGE_VERSION}" VERSION_LESS "${PACKAGE_FIND_VERSION}" ) 18 | set(PACKAGE_VERSION_COMPATIBLE FALSE) 19 | else("${PACKAGE_VERSION}" VERSION_LESS "${PACKAGE_FIND_VERSION}" ) 20 | set(PACKAGE_VERSION_COMPATIBLE TRUE) 21 | if( "${PACKAGE_FIND_VERSION}" STREQUAL "${PACKAGE_VERSION}") 22 | set(PACKAGE_VERSION_EXACT TRUE) 23 | endif( "${PACKAGE_FIND_VERSION}" STREQUAL "${PACKAGE_VERSION}") 24 | endif("${PACKAGE_VERSION}" VERSION_LESS "${PACKAGE_FIND_VERSION}" ) 25 | -------------------------------------------------------------------------------- /cmake_scripts/LibUtilsGLConfig.cmake: -------------------------------------------------------------------------------- 1 | get_filename_component(myDir ${CMAKE_CURRENT_LIST_FILE} PATH) 2 | get_filename_component(rootDir ${myDir} ABSOLUTE) 3 | 4 | # set the version of myself 5 | set(LIBUTILSGL_VERSION_MAJOR 1) 6 | set(LIBUTILSGL_VERSION_MINOR 2) 7 | set(LIBUTILSGL_VERSION_PATCH 2) 8 | set(LIBUTILSGL_VERSION ${LIBUTILSGL_VERSION_MAJOR}.${LIBUTILSGL_VERSION_MINOR}.${LIBUTILSGL_VERSION_PATCH} ) 9 | 10 | # what is my include directory 11 | set(LIBUTILSGL_INCLUDE_DIRS "${rootDir}/include") 12 | set(LIBUTILSGL_DIR "${rootDir}") 13 | 14 | # import the exported targets 15 | include(${myDir}/cmake/LibUtilsGL-targets.cmake) 16 | 17 | # set the expected library variable 18 | set(LIBUTILSGL_LIBRARIES LibUtilsGL ) 19 | -------------------------------------------------------------------------------- /cmake_scripts/LibUtilsGLConfigVersion.cmake: -------------------------------------------------------------------------------- 1 | # This is a very basic file for the new style find_package() search mode, 2 | # i.e. Config-mode. 3 | # In this mode find_package() searches for a Config.cmake 4 | # file and an associated Version.cmake file, which it loads to check 5 | # the version number. 6 | # This file can be used with configure_file() to generate such a file for a project 7 | # with very basic logic. 8 | # It sets PACKAGE_VERSION_EXACT if the current version string and the requested 9 | # version string are exactly the same and it sets PACKAGE_VERSION_COMPATIBLE 10 | # if the current version is >= requested version. 11 | # If this is not good enough for your project, you need to write your own 12 | # improved Version.cmake file. 13 | 14 | 15 | set(PACKAGE_VERSION 1.2.2) 16 | 17 | if("${PACKAGE_VERSION}" VERSION_LESS "${PACKAGE_FIND_VERSION}" ) 18 | set(PACKAGE_VERSION_COMPATIBLE FALSE) 19 | else("${PACKAGE_VERSION}" VERSION_LESS "${PACKAGE_FIND_VERSION}" ) 20 | set(PACKAGE_VERSION_COMPATIBLE TRUE) 21 | if( "${PACKAGE_FIND_VERSION}" STREQUAL "${PACKAGE_VERSION}") 22 | set(PACKAGE_VERSION_EXACT TRUE) 23 | endif( "${PACKAGE_FIND_VERSION}" STREQUAL "${PACKAGE_VERSION}") 24 | endif("${PACKAGE_VERSION}" VERSION_LESS "${PACKAGE_FIND_VERSION}" ) 25 | -------------------------------------------------------------------------------- /cmake_scripts/LibUtilsQtConfig.cmake: -------------------------------------------------------------------------------- 1 | get_filename_component(myDir ${CMAKE_CURRENT_LIST_FILE} PATH) 2 | get_filename_component(rootDir ${myDir} ABSOLUTE) 3 | 4 | # set the version of myself 5 | set(LIBUTILSQT_VERSION_MAJOR 1) 6 | set(LIBUTILSQT_VERSION_MINOR 2) 7 | set(LIBUTILSQT_VERSION_PATCH 2) 8 | set(LIBUTILSQT_VERSION ${LIBUTILSQT_VERSION_MAJOR}.${LIBUTILSQT_VERSION_MINOR}.${LIBUTILSQT_VERSION_PATCH} ) 9 | 10 | # what is my include directory 11 | set(LIBUTILSQT_INCLUDE_DIRS "${rootDir}/include") 12 | set(LIBUTILSQT_DIR "${rootDir}") 13 | 14 | # import the exported targets 15 | include(${myDir}/cmake/LibUtilsQt-targets.cmake) 16 | 17 | # set the expected library variable 18 | set(LIBUTILSQT_LIBRARIES LibUtilsQt ) 19 | -------------------------------------------------------------------------------- /cmake_scripts/LibUtilsQtConfigVersion.cmake: -------------------------------------------------------------------------------- 1 | # This is a very basic file for the new style find_package() search mode, 2 | # i.e. Config-mode. 3 | # In this mode find_package() searches for a Config.cmake 4 | # file and an associated Version.cmake file, which it loads to check 5 | # the version number. 6 | # This file can be used with configure_file() to generate such a file for a project 7 | # with very basic logic. 8 | # It sets PACKAGE_VERSION_EXACT if the current version string and the requested 9 | # version string are exactly the same and it sets PACKAGE_VERSION_COMPATIBLE 10 | # if the current version is >= requested version. 11 | # If this is not good enough for your project, you need to write your own 12 | # improved Version.cmake file. 13 | 14 | 15 | set(PACKAGE_VERSION 1.2.2) 16 | 17 | if("${PACKAGE_VERSION}" VERSION_LESS "${PACKAGE_FIND_VERSION}" ) 18 | set(PACKAGE_VERSION_COMPATIBLE FALSE) 19 | else("${PACKAGE_VERSION}" VERSION_LESS "${PACKAGE_FIND_VERSION}" ) 20 | set(PACKAGE_VERSION_COMPATIBLE TRUE) 21 | if( "${PACKAGE_FIND_VERSION}" STREQUAL "${PACKAGE_VERSION}") 22 | set(PACKAGE_VERSION_EXACT TRUE) 23 | endif( "${PACKAGE_FIND_VERSION}" STREQUAL "${PACKAGE_VERSION}") 24 | endif("${PACKAGE_VERSION}" VERSION_LESS "${PACKAGE_FIND_VERSION}" ) 25 | -------------------------------------------------------------------------------- /cmake_scripts/add_package.cmake: -------------------------------------------------------------------------------- 1 | # 2 | # Function to create configure scripts for find_package automatically 3 | # For a package containing the sub-project MyOptionalProject of version 1.0.2 4 | # add_package MyOptionalProject "." 1 0 2) 5 | # The same for an optional project that shall not have a find_package script (on by default) 6 | # add_subproject(MyOptionalProject "." ON) 7 | 8 | 9 | # 10 | # Function to create configure scripts for find_package automatically 11 | # 12 | function(configure_find_script LIB_NAME VERSION_MAJOR VERSION_MINOR VERSION_PATCH ) 13 | #set(${varName} ${varValue} PARENT_SCOPE) 14 | string(TOUPPER ${LIB_NAME} LIB_NAME_CAPS) 15 | # Create ${LIB_NAME}Config.cmake and ${LIB_NAME}ConfigVersion.cmake files for find_package() 16 | configure_file(cmake_scripts/Config.cmake.in ${CMAKE_CURRENT_SOURCE_DIR}/cmake_scripts/${LIB_NAME}Config.cmake @ONLY ) 17 | configure_file(cmake_scripts/ConfigVersion.cmake.in ${CMAKE_CURRENT_SOURCE_DIR}/cmake_scripts/${LIB_NAME}ConfigVersion.cmake @ONLY ) 18 | # Install files into the root of the install directory 19 | install(FILES cmake_scripts/${LIB_NAME}Config.cmake cmake_scripts/${LIB_NAME}ConfigVersion.cmake DESTINATION . ) 20 | endfunction(configure_find_script) 21 | 22 | # 23 | # Function to add a library or executable from a subdirectory 24 | # 25 | function(add_subproject SUBPROJECT_NAME SUBPROJECT_CATEGORY BUILD_BY_DEFAULT) 26 | string(TOUPPER ${SUBPROJECT_NAME} SUBPROJECT_NAME_CAPS) 27 | string(TOUPPER ${SUBPROJECT_CATEGORY} SUBPROJECT_CATEGORY_CAPS) 28 | option(BUILD${SUBPROJECT_CATEGORY_CAPS}_${SUBPROJECT_NAME_CAPS} "Build ${SUBPROJECT_CATEGORY}/${SUBPROJECT_NAME}?" ${BUILD_BY_DEFAULT}) 29 | if(BUILD${SUBPROJECT_CATEGORY_CAPS}_${SUBPROJECT_NAME_CAPS}) 30 | add_subdirectory(${SUBPROJECT_CATEGORY}/${SUBPROJECT_NAME} "${CMAKE_CURRENT_BINARY_DIR}/${SUBPROJECT_NAME}") 31 | endif(BUILD${SUBPROJECT_CATEGORY_CAPS}_${SUBPROJECT_NAME_CAPS}) 32 | endfunction(add_subproject) 33 | 34 | # 35 | # Function to add a library from a subdirectory and configre find script for find_package 36 | # 37 | function(add_package SUBPROJECT_NAME SUBPROJECT_CATEGORY VERSION_MAJOR VERSION_MINOR VERSION_PATCH) 38 | string(TOUPPER ${SUBPROJECT_NAME} SUBPROJECT_NAME_CAPS) 39 | string(TOUPPER ${SUBPROJECT_CATEGORY} SUBPROJECT_CATEGORY_CAPS) 40 | set(BUILD${SUBPROJECT_CATEGORY_CAPS}_${SUBPROJECT_NAME_CAPS} ON) 41 | if(BUILD${SUBPROJECT_CATEGORY_CAPS}_${SUBPROJECT_NAME_CAPS}) 42 | add_subdirectory(${SUBPROJECT_CATEGORY}/${SUBPROJECT_NAME} "${CMAKE_CURRENT_BINARY_DIR}/${SUBPROJECT_NAME}") 43 | configure_find_script(${SUBPROJECT_NAME} ${VERSION_MAJOR} ${VERSION_MINOR} ${VERSION_PATCH}) 44 | endif(BUILD${SUBPROJECT_CATEGORY_CAPS}_${SUBPROJECT_NAME_CAPS}) 45 | endfunction(add_package) 46 | -------------------------------------------------------------------------------- /cmake_scripts/findAndTestCUDA.cmake: -------------------------------------------------------------------------------- 1 | # Add CUDA 2 | find_package(CUDA) 3 | if(CUDA_FOUND) 4 | try_run(RUN_RESULT_VAR COMPILE_RESULT_VAR 5 | ${CMAKE_BINARY_DIR} 6 | ${CMAKE_CURRENT_SOURCE_DIR}/cmake_scripts/has_cuda_gpu.cpp 7 | CMAKE_FLAGS 8 | -DINCLUDE_DIRECTORIES:STRING=${CUDA_TOOLKIT_INCLUDE} 9 | -DLINK_LIBRARIES:STRING=${CUDA_CUDART_LIBRARY} 10 | COMPILE_OUTPUT_VARIABLE COMPILE_OUTPUT_VAR 11 | RUN_OUTPUT_VARIABLE RUN_OUTPUT_VAR) 12 | message("${RUN_OUTPUT_VAR}") # Display number of GPUs found 13 | # COMPILE_RESULT_VAR is TRUE when compile succeeds 14 | # RUN_RESULT_VAR is zero when a GPU is found 15 | if(NOT COMPILE_RESULT_VAR) 16 | message("Compilation of a simple CUDA program failed. Please check if CUDA is installed correctly.") 17 | endif() 18 | if(COMPILE_RESULT_VAR AND NOT RUN_RESULT_VAR) 19 | set(CUDA_HAVE_GPU TRUE CACHE BOOL "Whether CUDA-capable GPU is present") 20 | else() 21 | set(CUDA_HAVE_GPU FALSE CACHE BOOL "Whether CUDA-capable GPU is present") 22 | endif() 23 | # nvcc flags 24 | set(CUDA_NVCC_FLAGS ${CUDA_NVCC_FLAGS};--gpu-architecture sm_50) 25 | option(CUDA_NVCC_DEBUGGING "Build CUDA code with NVCC debug info (-g;-G)" OFF) 26 | if(CUDA_NVCC_DEBUGGING) 27 | set(CUDA_NVCC_FLAGS ${CUDA_NVCC_FLAGS};-g;-G) 28 | endif() 29 | option(CUDA_NVCC_VERBOSE "Verbose output of NVCC" OFF) 30 | if(CUDA_NVCC_VERBOSE) 31 | set(CUDA_NVCC_FLAGS --ptxas-options=-v;-lineinfo) 32 | endif(CUDA_NVCC_VERBOSE) 33 | endif(CUDA_FOUND) 34 | -------------------------------------------------------------------------------- /cmake_scripts/has_cuda_gpu.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main() { 5 | int deviceCount, device; 6 | int gpuDeviceCount = 0; 7 | struct cudaDeviceProp properties; 8 | cudaError_t cudaResultCode = cudaGetDeviceCount(&deviceCount); 9 | if (cudaResultCode != cudaSuccess) 10 | { 11 | deviceCount = 0; 12 | cudaError_t error = cudaGetLastError(); 13 | fprintf(stderr,"ERROR: %s\n", cudaGetErrorString(error) ); 14 | } 15 | /* machines with no GPUs can still report one emulation device */ 16 | for (device = 0; device < deviceCount; ++device) { 17 | cudaGetDeviceProperties(&properties, device); 18 | if (properties.major != 9999) /* 9999 means emulation only */ 19 | ++gpuDeviceCount; 20 | } 21 | printf("%d GPU CUDA device(s) found\n", gpuDeviceCount); 22 | 23 | /* don't just return the number of gpus, because other runtime cuda 24 | errors can also yield non-zero return values */ 25 | if (gpuDeviceCount > 0) 26 | return 0; /* success */ 27 | else 28 | return 1; /* failure */ 29 | } 30 | -------------------------------------------------------------------------------- /cmake_scripts/qt5_win32_copy_dlls.cmake: -------------------------------------------------------------------------------- 1 | function(qt5_win32_copy_dlls APP) 2 | 3 | # if(CMAKE_BUILD_TYPE MATCHES RELEASE AND WIN32) 4 | 5 | 6 | # get_target_property(QT5_QMAKE_EXECUTABLE Qt5::qmake IMPORTED_LOCATION) 7 | # get_filename_component(QT5_WINDEPLOYQT_EXECUTABLE ${QT5_QMAKE_EXECUTABLE} PATH) 8 | # set(QT5_WINDEPLOYQT_EXECUTABLE "${QT5_WINDEPLOYQT_EXECUTABLE}/windeployqt.exe") 9 | 10 | # add_custom_command(TARGET ${APP} POST_BUILD 11 | # COMMAND ${QT5_WINDEPLOYQT_EXECUTABLE} --qmldir ${CMAKE_SOURCE_DIR} $ --no-translations --no-quick-import --no-webkit2 --no-angle) 12 | 13 | # endif() 14 | 15 | # foreach(DLL ${QT5_MODULES}) 16 | # # find the release *.dll file 17 | # get_target_property(Qt5_${DLL}Location Qt5::${DLL} LOCATION) 18 | # # find the debug *d.dll file 19 | # get_target_property(Qt5_${DLL}LocationDebug Qt5::${DLL} IMPORTED_LOCATION_DEBUG) 20 | 21 | # add_custom_command(TARGET ${APP} POST_BUILD 22 | # COMMAND ${CMAKE_COMMAND} -E copy_if_different $<$:${Qt5_${DLL}LocationDebug}> $<$>:${Qt5_${DLL}Location}> $) 23 | # endforeach(DLL) 24 | 25 | endfunction(qt5_win32_copy_dlls) 26 | -------------------------------------------------------------------------------- /code/HeaderOnly/LibOpterix/Opterix.hxx: -------------------------------------------------------------------------------- 1 | // LibOpterix. 2 | // + `@ 3 | // `@ .@# 4 | // @@. ,+@@# 5 | // @@@ .@@@@+. @, 6 | // ,@@@@@@@@@@#', @@@. `@@@. 7 | // @ `,;#@@@@@@; ,, ++', :@@+ 8 | // #@. +@@@.@ +' @@:, 9 | // :+@@@@@@@@@@` @ @@ 10 | // ' ,@@+@` @@ 11 | // ,#@@@@ `@ 12 | // @@ @ 13 | // :@@ O P T E R I X 14 | // @@@+;'@: 15 | // A c++ library allowing non-linear optimization to easily exchange parametrizations and optimization algorithms/libraries. 16 | // To use this library, you need to define two classes, one deriving from OptimizationProblem, and another deriving from AbstractOptimizer. 17 | // This library includes a simple grid-search and Powell optimizer and optional wrappers for NLopt (others pending). 18 | 19 | #ifndef __opterix_hxx 20 | #define __opterix_hxx 21 | 22 | #include 23 | #include 24 | 25 | namespace LibOpterix { 26 | 27 | /// Interface for an objective function 28 | struct AbstractOptimizationProblem 29 | { 30 | AbstractParameterModel& abstract_model; 31 | AbstractOptimizationProblem(AbstractParameterModel& _abstract_model) 32 | : abstract_model(_abstract_model) 33 | {} 34 | 35 | // Compute cost function value given a parameter vector 36 | virtual double evaluate(const std::vector& x) =0; 37 | 38 | /// Compute gradient and cost function value. 39 | virtual double evaluate_gradient(const std::vector& x, std::vector& gradient) 40 | { 41 | throw std::logic_error("AbstractObjectiveFunction: Gradient computation is not implemented for this optimization problem."); 42 | } 43 | }; 44 | 45 | /// The actual optimization problem, which uses a specific parametrization of ParametrizedObject. 46 | template 47 | struct OptimizationProblem : public AbstractOptimizationProblem 48 | { 49 | ParameterModel& model; 50 | OptimizationProblem(ParameterModel& _model) 51 | : AbstractOptimizationProblem(_model) 52 | , model(_model) 53 | {} 54 | 55 | /// Compute cost function value from ParametrizedObject 56 | virtual double evaluate(const ParametrizedObject& obj) =0; 57 | 58 | /// Compute cost function value given a parameter vector 59 | virtual double evaluate(const std::vector& x) 60 | { 61 | model.expand(&x[0]); 62 | return evaluate(model.getInstance()); 63 | } 64 | }; 65 | 66 | /// To use this library, you need to define two classes, one deriving from OptimizationProblem, and another deriving from AbstractOptimizer. 67 | struct AbstractOptimizer 68 | { 69 | public: 70 | // Simple callback mechanism for a notification after each cost-function evaluation 71 | typedef void (*NotifyUpdate)(double current_cost, AbstractOptimizationProblem* problem); 72 | 73 | // Optimization problem 74 | AbstractOptimizationProblem& abstract_objective; 75 | AbstractOptimizer(AbstractOptimizationProblem& _abstract_objective) 76 | : abstract_objective(_abstract_objective) 77 | , user_callback(0x0) 78 | , progress(0x0) 79 | {} 80 | 81 | /// Perform optimization over parameters in AbstractOptimizationProblem. 82 | virtual bool optimize(std::vector &x, GetSetGui::ProgressInterface&) =0; 83 | 84 | /// Optionally ask optimizer to notify called after each cost function evaluation. 85 | AbstractOptimizer& setCallback(NotifyUpdate _callback) 86 | { 87 | user_callback=_callback; 88 | return *this; 89 | } 90 | 91 | protected: 92 | NotifyUpdate user_callback; 93 | GetSetGui::ProgressInterface *progress; 94 | }; 95 | 96 | } // namspace Optimizationx 97 | 98 | #endif // __opterix_hxx 99 | -------------------------------------------------------------------------------- /code/HeaderOnly/NRRD/BaseTypes.hxx: -------------------------------------------------------------------------------- 1 | // 2 | // Disabling types: 3 | // _DEFINE_TYPE_NO_BOOL <> bool 4 | // _DEFINE_TYPE_NO_CHAR <> char (UNSIGNED CHAR STILL USED) 5 | // _DEFINE_TYPE_NO_INT <> short, int, long, unsigned short, unsigned int, unsigned long 6 | // _DEFINE_TYPE_NO_SHORT <> short, unsigned short 7 | // _DEFINE_TYPE_NO_LONG <> long unsigned long 8 | // _DEFINE_TYPE_NO_FLOATING_POINT <> float, double 9 | // _DEFINE_TYPE_NO_DOUBLE <> double 10 | // _DEFINE_TYPE_NO_UNSIGNED <> unsigned anything 11 | 12 | 13 | #ifndef _DEFINE_TYPE_NO_BOOL 14 | _DEFINE_TYPE(bool) 15 | #endif 16 | 17 | #ifndef _DEFINE_TYPE_NO_CHAR 18 | _DEFINE_TYPE(char) 19 | #endif 20 | #ifndef _DEFINE_TYPE_NO_UNSIGNED 21 | _DEFINE_TYPE(unsigned char) 22 | #endif 23 | 24 | 25 | #ifndef _DEFINE_TYPE_NO_INT 26 | #ifndef _DEFINE_TYPE_NO_SHORT 27 | _DEFINE_TYPE(short) 28 | #ifndef _DEFINE_TYPE_NO_UNSIGNED 29 | _DEFINE_TYPE(unsigned short) 30 | #endif 31 | #endif 32 | _DEFINE_TYPE(int) 33 | #ifndef _DEFINE_TYPE_NO_UNSIGNED 34 | _DEFINE_TYPE(unsigned int) 35 | #endif 36 | #ifndef _DEFINE_TYPE_NO_LONG 37 | _DEFINE_TYPE(long) 38 | #ifndef _DEFINE_TYPE_NO_UNSIGNED 39 | _DEFINE_TYPE(unsigned long) 40 | #endif 41 | #endif 42 | #endif 43 | 44 | #ifndef _DEFINE_TYPE_NO_FLOATING_POINT 45 | _DEFINE_TYPE(float) 46 | #ifndef _DEFINE_TYPE_NO_DOUBLE 47 | _DEFINE_TYPE(double) 48 | #endif 49 | #endif 50 | 51 | #undef _DEFINE_TYPE 52 | -------------------------------------------------------------------------------- /code/HeaderOnly/NRRD/GetSetCmdLine.hxx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aaichert/EpipolarConsistency/8feb718e6b35a943d30684a40e52feb024df91fc/code/HeaderOnly/NRRD/GetSetCmdLine.hxx -------------------------------------------------------------------------------- /code/HeaderOnly/NRRD/GetSetMinimal.hxx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aaichert/EpipolarConsistency/8feb718e6b35a943d30684a40e52feb024df91fc/code/HeaderOnly/NRRD/GetSetMinimal.hxx -------------------------------------------------------------------------------- /code/HeaderOnly/NRRD/StringConversion.hxx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aaichert/EpipolarConsistency/8feb718e6b35a943d30684a40e52feb024df91fc/code/HeaderOnly/NRRD/StringConversion.hxx -------------------------------------------------------------------------------- /code/HeaderOnly/NRRD/StringType.hxx: -------------------------------------------------------------------------------- 1 | // 2 | // Library: GetSet 3 | // c++ library for load/saving *typed* and *named* properties and automatic GUI. 4 | // 5 | // Copyright (c) by Andr� Aichert (aaichert@gmail.com) 6 | // 7 | // Licensed under the Apache License, Version 2.0 (the "License"); 8 | // you may not use this file except in compliance with the License. 9 | // You may obtain a copy of the License at 10 | // 11 | // http://www.apache.org/licenses/LICENSE-2.0 12 | // 13 | // Unless required by applicable law or agreed to in writing, software 14 | // distributed under the License is distributed on an "AS IS" BASIS, 15 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | // See the License for the specific language governing permissions and 17 | // limitations under the License. 18 | // 19 | 20 | #ifndef __string_type_hxx 21 | #define __string_type_hxx 22 | 23 | #include 24 | #include 25 | #include 26 | 27 | /// Get a c++ type name as string 28 | template inline std::string typeName() 29 | { 30 | return typeid(T).name(); 31 | } 32 | 33 | // Specializations 34 | template<> inline std::string typeName() {return "string";} 35 | template<> inline std::string typeName >() {return "vector";} 36 | 37 | #define _DEFINE_TYPE(X) template<> inline std::string typeName >() {return "vector<"#X">";} 38 | #include "BaseTypes.hxx" 39 | #define _DEFINE_TYPE(X) template<> inline std::string typeName() {return #X;} 40 | #include "BaseTypes.hxx" 41 | 42 | inline bool isTypeStr(const std::string& type) 43 | { 44 | bool isType=false; 45 | #define _DEFINE_TYPE(T) \ 46 | if (!isType && type==#T) isType=true; 47 | #include "BaseTypes.hxx" 48 | #undef _DEFINE_TYPE 49 | return isType; 50 | } 51 | 52 | #endif // __string_type_hxx 53 | -------------------------------------------------------------------------------- /code/HeaderOnly/NRRD/StringUtil.hxx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aaichert/EpipolarConsistency/8feb718e6b35a943d30684a40e52feb024df91fc/code/HeaderOnly/NRRD/StringUtil.hxx -------------------------------------------------------------------------------- /code/HeaderOnly/NRRD/nrrd_frst.hxx: -------------------------------------------------------------------------------- 1 | #ifndef __nrrd_frst_hxx 2 | #define __nrrd_frst_hxx 3 | 4 | #include 5 | #include 6 | 7 | namespace NRRD { 8 | 9 | // img must be dimension 2, radii is a list of radii of interest, radial_strictness is the fall-off. 10 | bool frst(NRRD::ImageView& img, const std::vector& radii, double sigma = 3.68, int k= 5, double radial_strictness =1, double threshold_gradient=0) 11 | { 12 | // Make sure we have a 2D image and get its size 13 | if (img.dimension()!=2 || radii.empty()) 14 | return false; 15 | int l=img.length(); 16 | int n_x=img.size(0); 17 | int n_y=img.size(1); 18 | // Allocate temporary images 19 | NRRD::Image On(n_x,n_y),Mn(n_x,n_y); 20 | #pragma omp parallel for schedule(dynamic, 128) 21 | for (int i=0;i=0&&py>=0&&px=0&&my>=0&&mx()) return "MET_FLOAT"; 35 | else if (type==typeName()) return "MET_DOUBLE"; 36 | else if (type==typeName()) return "MET_CHAR"; 37 | else if (type==typeName()) return "MET_USHORT"; 38 | else if (type==typeName()) return "MET_INT"; 39 | else if (type==typeName()) return "MET_UCHAR"; 40 | else if (type==typeName()) return "MET_SHORT"; 41 | else if (type==typeName()) return "MET_UINT"; 42 | else return ""; 43 | } 44 | 45 | inline std::string typeFromMET(std::string type) 46 | { 47 | std::transform(type.begin(), type.end(), type.begin(), tolower); 48 | if (false) ; 49 | else if (type=="MET_FLOAT") return typeName(); 50 | else if (type=="MET_DOUBLE") return typeName(); 51 | else if (type=="MET_CHAR") return typeName(); 52 | else if (type=="MET_SHORT") return typeName(); 53 | else if (type=="MET_INT") return typeName(); 54 | else if (type=="MET_UCHAR") return typeName(); 55 | else if (type=="MET_UINT") return typeName(); 56 | else if (type=="MET_USHORT") return typeName(); 57 | else return ""; 58 | } 59 | 60 | /// Save raw data in MHA file. 61 | template 62 | bool saveMHA(const std::string& file, const NRRD::ImageView& img ) 63 | { 64 | std::ofstream mha(file.c_str(),std::ios::binary); 65 | if (!mha||!mha.good()) 66 | return false; 67 | // Write MetaIO header 68 | mha 69 | << "ObjectType = Image\n" 70 | << "NDims = " << img.dimension() << "\n" 71 | << "BinaryData = True\n" 72 | << "BinaryDataByteOrderMSB = " << (is_cpu_BIG_endian()?"True":"False") << "\n" 73 | << "CompressedData = False\n" 74 | << "ElementSpacing = " << img.spacing(0) << " " << img.spacing(1) << " " << img.spacing(2) << "\n" 75 | << "ElementType = " << typeToMET(typeName()) 76 | << "ElementDataFile = LOCAL\n"; 77 | // Write raw data chunk 78 | mha.write((char*)((T*)img),sizeof(T)*img.length()); 79 | return true; 80 | } 81 | 82 | } // namespace NRRD 83 | 84 | 85 | #endif // __NRRD_HXX 86 | -------------------------------------------------------------------------------- /code/HeaderOnly/NRRD/nrrd_morphology.hxx: -------------------------------------------------------------------------------- 1 | // Created by A. Aichert on Wed April 16th 2014 2 | 3 | #ifndef __nrrd_morphology_hxx 4 | #define __nrrd_morphology_hxx 5 | 6 | #include "nrrd_image_view.hxx" 7 | 8 | namespace NRRD { 9 | 10 | /// An int tripel 11 | struct Index3 { 12 | Index3(int _x, int _y, int _z) : x(_x), y(_y), z(_z) {} 13 | int x,y,z; 14 | }; 15 | 16 | inline std::vector sphere(int n) 17 | { 18 | std::vector ret; 19 | for (int z=-n;z<=n;z++) 20 | for (int y=-n;y<=n;y++) 21 | for (int x=-n;x<=n;x++) 22 | if (std::sqrt((double)x*x+y*y+z*z)<=n) 23 | ret.push_back(Index3(x,y,z)); 24 | return ret; 25 | } 26 | 27 | /// 1 voxel dilation 28 | template 29 | void dilate3D(NRRD::ImageView img, int radius=1) 30 | { 31 | std::vector& structure_element=sphere(radius); 32 | if (!img) return; 33 | NRRD::Image tmp; 34 | int nx=img.size(0); 35 | int ny=img.size(1); 36 | int nz=img.size(2); 37 | tmp.set(nx,ny,nz); 38 | for (int i=0;ix,y+it->y,z+it->z)) 48 | max=tmp(x+it->x,y+it->y,z+it->z); 49 | img.pixel(x,y,z)=max; 50 | } 51 | } 52 | 53 | /// 1 voxel erosion 54 | template 55 | void erode3D(NRRD::ImageView img, int radius=1) 56 | { 57 | std::vector& structure_element=sphere(radius); 58 | if (!img) return; 59 | NRRD::Image tmp; 60 | int nx=img.size(0); 61 | int ny=img.size(1); 62 | int nz=img.size(2); 63 | tmp.set(nx,ny,nz); 64 | for (int i=0;itmp(x+it->x,y+it->y,z+it->z)) 74 | min=tmp(x+it->x,y+it->y,z+it->z); 75 | img.pixel(x,y,z)=min; 76 | } 77 | } 78 | 79 | } // namespace NRRD 80 | 81 | #endif // __nrrd_morphology_hxx 82 | -------------------------------------------------------------------------------- /code/HeaderOnly/NRRD/nrrd_transform.hxx: -------------------------------------------------------------------------------- 1 | // Created by A. Aichert 2 | #ifndef __nrrd_transform_hxx 3 | #define __nrrd_transform_hxx 4 | 5 | #include "nrrd_image.hxx" 6 | // 2do replace LAUT with GLM or similar 7 | #include "../deprecated/laut.hxx" 8 | 9 | #define HAVE_OPENMP 10 | 11 | #ifdef HAVE_OPENMP 12 | #include 13 | #endif 14 | 15 | namespace NRRD { 16 | 17 | /// Transform a volume given a projective transformation. 18 | /// Coordinates in millimeters with the lower back left corner as origin. 19 | /// Spacing provided is(x/y/z) and os(x/y/z), number of voxels as provided. 20 | template 21 | void transform_volume( 22 | const NRRD::Image& I, NRRD::Image& O, double* _T, 23 | double isx=1, double isy=1, double isz=1, 24 | double osx=1, double osy=1, double osz=1) 25 | { 26 | LAUT::Ref T(_T,4,4); 27 | // Invert for backward warping 28 | LAUT::Mat Tinv; 29 | LAUT::xgeinv4(T,Tinv); 30 | 31 | // Image sizes, for readibility. 32 | int onx=O.size(0),ony=O.size(1),onz=O.size(2); 33 | 34 | #ifdef HAVE_OPENMP 35 | #pragma omp parallel for 36 | #endif 37 | for (int z=0;z 5 | class ProgressInterface { 6 | public: 7 | virtual void progressStart(const std::string& progress, const std::string& info, int maximum, bool *cancel_clicked=0x0) 8 | { std::cout << progress << ": " << info << std::endl; } 9 | 10 | virtual void progressUpdate(int i) { std::cout << i << "..." << std::endl; } 11 | virtual void progressEnd() { std::cout << "Done." << std::endl; } 12 | 13 | virtual void info(const std::string& who, const std::string& what, bool show_dialog=false) 14 | { std::cout << who << ": " << what << std::endl; } 15 | virtual void warn(const std::string& who, const std::string& what, bool only_inormative=true) 16 | { std::cout << (only_inormative?"Warning - ":"Error - ") << who << ": " << what << std::endl; } 17 | }; 18 | 19 | #endif // __progress_interface 20 | -------------------------------------------------------------------------------- /code/HeaderOnly/Utils/Projtable.hxx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aaichert/EpipolarConsistency/8feb718e6b35a943d30684a40e52feb024df91fc/code/HeaderOnly/Utils/Projtable.hxx -------------------------------------------------------------------------------- /code/HeaderOnly/Utils/TimerWin32.hxx: -------------------------------------------------------------------------------- 1 | #ifndef hr_timer 2 | #define hr_timer 3 | // Created by aaichert on Sept 12th 2014 4 | // WIN32-only high precision timer. 5 | 6 | #ifdef WIN32 7 | #include 8 | #endif 9 | 10 | namespace Utils { 11 | 12 | class TimerWin32 { 13 | private: 14 | #ifdef WIN32 15 | struct { 16 | LARGE_INTEGER start; 17 | LARGE_INTEGER current; 18 | } timer; 19 | LARGE_INTEGER frequency; 20 | #endif 21 | 22 | public: 23 | TimerWin32(){ 24 | #ifdef WIN32 25 | timer.start.QuadPart=0; 26 | timer.current.QuadPart=0; 27 | QueryPerformanceFrequency( &frequency ); 28 | startTimer(); 29 | #endif 30 | } 31 | 32 | /// (Re-) Start Timer 33 | void startTimer() { 34 | #ifdef WIN32 35 | QueryPerformanceCounter(&timer.start); 36 | timer.current.QuadPart=timer.start.QuadPart; 37 | #endif 38 | } 39 | 40 | // Elapsed Time in Seconds since last call to getElapsedTime() or startTimer() 41 | double getElapsedTime() { 42 | #ifdef WIN32 43 | LARGE_INTEGER now; 44 | QueryPerformanceCounter(&now); 45 | LONGLONG elapsed=now.QuadPart - timer.current.QuadPart; 46 | timer.current=now; 47 | return (double)elapsed/(double)frequency.QuadPart; 48 | #else 49 | return 0; 50 | #endif 51 | } 52 | 53 | // Elapsed Time in Seconds since startTimer() 54 | double getTotalTime() { 55 | #ifdef WIN32 56 | LARGE_INTEGER now; 57 | QueryPerformanceCounter(&now); 58 | LONGLONG elapsed=now.QuadPart-timer.start.QuadPart; 59 | return (double)elapsed/(double)frequency.QuadPart; 60 | #else 61 | return 0; 62 | #endif 63 | } 64 | }; 65 | 66 | } // namespace Utils 67 | 68 | #endif 69 | -------------------------------------------------------------------------------- /code/LibEpipolarConsistency/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | # A library to evaluate a metric of epipolar consistency 3 | cuda_add_library(LibEpipolarConsistency 4 | # Common methods for ECC direct and with Radon intermediate 5 | EpipolarConsistency.h 6 | EpipolarConsistency.cpp 7 | # Some epipolar geometry functions which are needed in any case. 8 | EpipolarConsistencyCommon.hxx 9 | # Extract redundant signals directly from images 10 | # This version is useful when ECC metric is computed only once 11 | # or when the images are subject to change during optimization. 12 | EpipolarConsistencyDirect.h 13 | EpipolarConsistencyDirect.cpp 14 | EpipolarConsistencyDirect.cu 15 | # Compute pairwise fan-beam cc via rectification. 16 | RectifiedFBCC.h 17 | # Actual rectification (used only for visualization) 18 | Rectification.cu 19 | # Extract redundant samples from Radon intermediate functions of images. 20 | # This Version requires the Radon transform to be pre-computed. It is able to 21 | # quickly evaluate the ECC metric if only projection matrices are changed. 22 | EpipolarConsistencyRadonIntermediate.h 23 | EpipolarConsistencyRadonIntermediate.cpp 24 | EpipolarConsistencyRadonIntermediate.cu 25 | # The Radon intermediate functions is the expensive pre-computation. 26 | RadonIntermediate.h 27 | RadonIntermediate.cpp 28 | RadonIntermediate.cu 29 | OPTIONS -DHAS_CUDA="Cuda Support" 30 | ) 31 | target_link_libraries(LibEpipolarConsistency LibProjectiveGeometry LibUtilsCuda ${CUDA_CUFFT_LIBRARIES} ) 32 | install(FILES EpipolarConsistencyCommon.hxx EpipolarConsistency.h EpipolarConsistencyDirect.h RectifiedFBCC.h RadonIntermediate.h EpipolarConsistencyRadonIntermediate.h DESTINATION include/LibEpipolarConsistency) 33 | install(TARGETS LibEpipolarConsistency DESTINATION lib EXPORT LibEpipolarConsistency-targets) 34 | install(EXPORT LibEpipolarConsistency-targets DESTINATION cmake) 35 | set_property(TARGET LibEpipolarConsistency PROPERTY FOLDER "EpipolarConsistency") 36 | 37 | # Some useful code for loading and pre-processing data when GetSetGui is available. 38 | add_library(LibEpipolarConsistencyGui 39 | # Pre-Processing and Radon intermediate function 40 | Gui/PreProccess.h 41 | Gui/PreProccess.cpp 42 | Gui/ComputeRadonIntermediate.hxx 43 | # Input Data 44 | Gui/InputDataRadonIntermediate.h 45 | Gui/InputDataRadonIntermediate.cpp 46 | Gui/InputDataDirect.h 47 | Gui/InputDataDirect.cpp 48 | # Visualization 49 | Gui/DisplayGeometry.hxx 50 | Gui/Visualization.h 51 | Gui/Visualization.cpp 52 | # Input Data 53 | Gui/SingleImageMotion.h 54 | # Registration 55 | Gui/Registration.h 56 | Gui/Registration.cpp 57 | # ECC optimization over one input image given several reference images 58 | # (e.g. one by one optimimization for FDCT or tracking of Fluoro sequence) 59 | #Gui/SingleImageMotion.hxx 60 | # (Inefficiant but simple) implementation of ECC motion correction in FDCT 61 | Gui/FDCTMotionCorrection.hxx 62 | ) 63 | target_link_libraries(LibEpipolarConsistencyGui LibEpipolarConsistency LibProjectiveGeometry LibUtilsQt GetSet GetSetGui) 64 | install(FILES Gui/PreProccess.h Gui/ComputeRadonIntermediate.hxx Gui/Visualization.h Gui/DisplayGeometry.hxx Gui/SingleImageMotion.hxx Gui/FDCTMotionCorrection.hxx DESTINATION include/LibEpipolarConsistency/Gui) 65 | install(TARGETS LibEpipolarConsistencyGui DESTINATION lib EXPORT LibEpipolarConsistencyGui-targets) 66 | install(EXPORT LibEpipolarConsistencyGui-targets DESTINATION cmake) 67 | set_property(TARGET LibEpipolarConsistencyGui PROPERTY FOLDER "EpipolarConsistency") 68 | -------------------------------------------------------------------------------- /code/LibEpipolarConsistency/EpipolarConsistency.cpp: -------------------------------------------------------------------------------- 1 | #include "EpipolarConsistency.h" 2 | 3 | #include 4 | 5 | namespace EpipolarConsistency 6 | { 7 | using Geometry::Pi; 8 | 9 | /// 2DO Should use SVD from Geometry module to reduce compile time. 10 | Geometry::RP3Point estimateIsoCenter(const std::vector &Ps) 11 | { 12 | int n=(int)Ps.size(); 13 | Eigen::Matrix3d A=Eigen::Vector3d(n,n,n).asDiagonal(); 14 | Eigen::Vector3d b(0,0,0); 15 | // Distance as norm of a point projected to plane orthogonal to view direction through the origin. 16 | for (int i=0;i(0,0); 21 | // View direction 22 | Eigen::Vector3d V=P.block<1,3>(2,0).normalized(); 23 | // O=id-v*v^T is projection in direction v. 24 | A-=V*V.transpose(); 25 | // For points x on the principal ray it holds that O*x=O*C 26 | b+=C-V*(V.transpose()*C); 27 | } 28 | // Solve by SVD 29 | Eigen::JacobiSVD svd(A, Eigen::ComputeFullU | Eigen::ComputeFullV); 30 | Geometry::RP3Point O(0,0,0,1); 31 | O.block<3,1>(0,0)=svd.solve(b); 32 | return O; 33 | } 34 | 35 | double estimateObjectRadius(const ProjectionMatrix& P, int n_u, int n_v) 36 | { 37 | using namespace Geometry; 38 | using namespace std; 39 | // Get the focal lengths in pixels. 40 | auto alphas=getCameraFocalLengthPx(P); 41 | // Compute field of view (use maximum of u and v). 42 | double fov =max(abs(atan(0.5*n_u/alphas.first)), abs(atan(0.5*n_v/alphas.second))); 43 | // The source to iso-center distance. 44 | double sid =getCameraCenter(P).head(3).norm(); 45 | // Return approximate radius of an circumscribed sphere. 46 | return sin(fov)*sid; 47 | } 48 | 49 | std::pair estimateAngularRange(const RP3Line& B, double object_radius_mm) 50 | { 51 | // Distance of baseline to origin 52 | double baseline_dist=Geometry::pluecker_distance_to_origin(B); 53 | // If the baseline intersects the object, ECC is not well-defined. We return a half circle anyway. 54 | if (baseline_dist<=object_radius_mm) 55 | return std::make_pair(-0.5*Pi,0.5*Pi); 56 | // Else, find angle of plane which touches the sphere 57 | double kappa_max=std::abs(std::asin(object_radius_mm/baseline_dist)); 58 | return std::make_pair(-kappa_max,kappa_max); 59 | } 60 | 61 | double estimateAngularStep(const ProjectionMatrix& P0, const ProjectionMatrix& P1, int n_u, int n_v) 62 | { 63 | using namespace Geometry; 64 | double radius_mm=std::max(estimateObjectRadius(P0,n_u,n_v),estimateObjectRadius(P1,n_u,n_v)); 65 | auto baseline=join_pluecker(getCameraCenter(P0),getCameraCenter(P1)); 66 | auto range_kappa=estimateAngularRange(baseline,radius_mm); 67 | return 2.0*(range_kappa.second-range_kappa.first)/std::sqrt(n_u*n_u+n_v*n_v); 68 | } 69 | 70 | Metric& Metric::setObjectRadius(double radius_mm) 71 | { 72 | object_radius_mm=radius_mm; 73 | return *this; 74 | } 75 | 76 | double Metric::getObjectRadius() const 77 | { 78 | if (object_radius_mm>0) 79 | return object_radius_mm; 80 | if (getProjectionMatrices().empty()) 81 | return 0; 82 | auto P=getProjectionMatrices().front(); 83 | return estimateObjectRadius(P,n_u,n_v); 84 | } 85 | 86 | Metric& Metric::setEpipolarPlaneStep(double dkappa_rad) { 87 | dkappa=dkappa_rad; 88 | return *this; 89 | } 90 | 91 | Metric& Metric::setProjectionMatrices(const std::vector& _Ps) 92 | { 93 | Ps=_Ps; 94 | return *this; 95 | } 96 | 97 | const std::vector&Metric:: getProjectionMatrices() const 98 | { 99 | return Ps; 100 | } 101 | 102 | Metric::Metric() : object_radius_mm(0), dkappa(0), n_u(0), n_v(0) {} 103 | 104 | Metric::~Metric() {} 105 | 106 | } // namespace EpipolarConsistency 107 | -------------------------------------------------------------------------------- /code/LibEpipolarConsistency/EpipolarConsistencyCommon.hxx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aaichert/EpipolarConsistency/8feb718e6b35a943d30684a40e52feb024df91fc/code/LibEpipolarConsistency/EpipolarConsistencyCommon.hxx -------------------------------------------------------------------------------- /code/LibEpipolarConsistency/EpipolarConsistencyDirect.h: -------------------------------------------------------------------------------- 1 | #ifndef __epipolar_consistency_direct_h 2 | #define __epipolar_consistency_direct_h 3 | // Created by A. Aichert on Thu Nov 21st 2018 4 | // Class to compute Epipolar Consistency given ProjectionMatrices and pre-processed x-ray proections. 5 | 6 | #include "EpipolarConsistency.h" 7 | 8 | // NRRD Image File Format 9 | #include 10 | 11 | // Projective Geometry 12 | #include 13 | 14 | namespace EpipolarConsistency 15 | { 16 | /// The main algorithm behind epipolar consistency, when not using Radon intermediate functions. 17 | double computeForImagePair( 18 | const Geometry::ProjectionMatrix& P0, const Geometry::ProjectionMatrix& P1, 19 | const UtilsCuda::BindlessTexture2D& I0, const UtilsCuda::BindlessTexture2D& I1, 20 | double dkappa, double object_radius_mm, bool fbcc=false, 21 | std::vector *redundant_samples0=0x0, std::vector *redundant_samples1=0x0, 22 | std::vector *kappas=0x0); 23 | 24 | /// How epipolar planes will be sampled 25 | // enum SamplingStrategy { RegularEpipolarAngle, EqualNumberOfSamples } 26 | 27 | /// Compute Epipolar Consistency on the GPU directly from projection images. 28 | class MetricDirect : public Metric { 29 | /// Projection matrices 30 | std::vector Ps; 31 | /// Projection images as 2D single.channel float Cuda textures. 32 | std::vector*> Is; 33 | /// Use standard epipolar consistecy with derivative or the rectified version without derivative? 34 | bool use_fbcc; 35 | public: 36 | 37 | /// Direct evaluation of epipolar consistency metrix (for repeated evaluations see also: MetricRadonIntermediate) 38 | MetricDirect(const std::vector& Ps, const std::vector*>& _Is); 39 | 40 | /// Set projection matrices. 41 | virtual Metric& setProjectionMatrices(const std::vector& Ps); 42 | 43 | /// Set projections images from single-channel 2D float textures. 44 | virtual Metric& setProjectionImages(const std::vector*>& Is); 45 | 46 | /// The number of projections. The number of evaluations will be n*(n-1)/2 47 | virtual int getNumberOfProjetions(); 48 | 49 | /// Evaluates metric and optionally returns n*n cost image. 50 | virtual double evaluate(float * out=0x0); 51 | 52 | /// Evaluate for just tow images i and j and optionally also return redundant values. 53 | virtual double evaluateForImagePair(int i, int j, 54 | std::vector *redundant_samples0=0x0, std::vector *redundant_samples1=0x0, 55 | std::vector *kappas=0x0); 56 | 57 | /// Change algorith to use retification instead of derivative. 58 | MetricDirect& setFanBeamConsistency(bool fbcc=true); 59 | 60 | }; 61 | 62 | } // namespace EpipolarConsistency 63 | 64 | #endif // __epipolar_consistency_direct_h 65 | -------------------------------------------------------------------------------- /code/LibEpipolarConsistency/EpipolarConsistencyRadonIntermediate.cu: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aaichert/EpipolarConsistency/8feb718e6b35a943d30684a40e52feb024df91fc/code/LibEpipolarConsistency/EpipolarConsistencyRadonIntermediate.cu -------------------------------------------------------------------------------- /code/LibEpipolarConsistency/EpipolarConsistencyRadonIntermediateCPU.hxx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aaichert/EpipolarConsistency/8feb718e6b35a943d30684a40e52feb024df91fc/code/LibEpipolarConsistency/EpipolarConsistencyRadonIntermediateCPU.hxx -------------------------------------------------------------------------------- /code/LibEpipolarConsistency/Gui/ComputeRadonIntermediate.hxx: -------------------------------------------------------------------------------- 1 | // Created by A. Aichert on Mon Mar 27st 2017. 2 | #ifndef __compute_radon_intermediate 3 | #define __compute_radon_intermediate 4 | 5 | #include 6 | #include 7 | 8 | #include 9 | #include 10 | 11 | #include 12 | 13 | #include 14 | 15 | #include 16 | 17 | #include "PreProccess.h" 18 | 19 | #include 20 | #include 21 | 22 | ///////////////////////// 23 | // JUST FOR TESTING 24 | #include 25 | ///////////////////////// 26 | 27 | namespace EpipolarConsistency 28 | { 29 | // 30 | // Computing Radon Intermediate and Filter 31 | // 32 | 33 | struct RadonIntermediateFunction : public GetSetGui::Configurable { 34 | 35 | /// Filter applied to Radon transform. 36 | RadonIntermediate::Filter filter=RadonIntermediate::Derivative; 37 | 38 | /// Function applied to each value in the Radon transform 39 | RadonIntermediate::PostProcess post_process=RadonIntermediate::Identity; 40 | 41 | /// Size of the Radon transform. 42 | struct NumberOfBins { 43 | int angle=768; //< Size of the Radon transform in angle-direction. 44 | int distance=768; //< Size of the Radon transform in distance-direction. 45 | } number_of_bins; 46 | 47 | /// Declare default values. 48 | void gui_declare_section (const GetSetGui::Section& section) 49 | { 50 | // RadonIntermediate 51 | GetSet ("Number Of Bins/Angle" , section, number_of_bins.angle ).setDescription("Number of Radon bins in alpha-direction"); 52 | GetSet ("Number Of Bins/Distance" , section, number_of_bins.distance ).setDescription("Number of Radon bins in t-direction"); 53 | section.subsection("Number Of Bins").setGrouped(); 54 | GetSetGui::Enum ("Distance Filter" , section, filter ).setChoices("Derivative;Ramp;None") 55 | .setDescription("A homogeneous function of degree two must be applied for the consistency condition to hold. This becomes a Ramp or derivative filter in t-direction."); 56 | GetSetGui::Enum ("Post Process" , section, post_process ).setChoices("Identity;sgn(x)*sqrt(abs(x));sgn(x)*log(abs(x)-1)") 57 | .setDescription("A function applied to the Radon transform after computation. Function: x, sgn(x)*sqrt(abs(x)) or sgn(x)*log(abs(x)+1)."); 58 | } 59 | 60 | // Retreive current values from GUI 61 | void gui_retreive_section(const GetSetGui::Section& section) 62 | { 63 | post_process =(RadonIntermediate::PostProcess)(GetSet("Post Process" , section).getValue()); 64 | filter =(RadonIntermediate::Filter) (GetSet("Distance Filter" , section).getValue()); 65 | number_of_bins.angle = GetSet("Number Of Bins/Angle" , section); 66 | number_of_bins.distance = GetSet("Number Of Bins/Distance" , section); 67 | } 68 | 69 | /// Load and process Radon Intemediate Functions. 70 | RadonIntermediate* compute(NRRD::ImageView& img, Geometry::ProjectionMatrix *P=0x0, double *mm_per_px=0x0) 71 | { 72 | // Compute Radon Intermediate 73 | int n_alpha=number_of_bins.angle; 74 | int n_t=number_of_bins.distance; 75 | auto * dtr=new EpipolarConsistency::RadonIntermediate( img, n_alpha,n_t, filter, post_process); 76 | 77 | 78 | // Store projection matrix in NRRD header, if provided 79 | if (P) img.meta_info["Original Image/Projection Matrix"] = toString(*P); 80 | if (mm_per_px) img.meta_info["Original Image/Pixel Spacing" ] = toString(*mm_per_px); 81 | 82 | return dtr; 83 | } 84 | 85 | }; 86 | 87 | 88 | } // namespace EpipolarConsistency 89 | 90 | #endif // __compute_radon_intermediate 91 | -------------------------------------------------------------------------------- /code/LibEpipolarConsistency/Gui/FDCTMotionCorrection.hxx: -------------------------------------------------------------------------------- 1 | #ifndef _ecc_motioncompenstation_hxx 2 | #define _ecc_motioncompenstation_hxx 3 | 4 | #include 5 | 6 | #include 7 | 8 | #include 9 | 10 | namespace EpipolarConsistency { 11 | 12 | // Epipolar consistency metric for changes on one projection matrix. 13 | class FDCTMoCo : public LibOpterix::OptimizationProblem > 14 | { 15 | std::vector Ps; //< Initial Guess of Projection Matrices. 16 | std::vector dtrs; //< Radon Intermediate functions. 17 | 18 | EpipolarConsistency::MetricRadonIntermediate *ecc; //< The object which computes ECC on the GPU 19 | NRRD::Image cost_image; //< Pairwise results for initial guess (lower triangular part) and last evaluation (upper triangular part) 20 | 21 | FDCTMoCo(const FDCTMoCo&); 22 | 23 | public: 24 | /// Create a FDCTMoCo object from a set of projections 25 | FDCTMoCo( 26 | LibOpterix::ParameterModel& _parameter_model, 27 | std::vector _Ps, 28 | std::vector _dtrs, 29 | int _input_index=0 30 | ) 31 | : LibOpterix::OptimizationProblem(_parameter_model) 32 | , Ps(_Ps) 33 | , dtrs(_dtrs) 34 | , ecc(new EpipolarConsistency::MetricRadonIntermediate(Ps,dtrs)) 35 | { 36 | int n=(int)_dtrs.size(); 37 | for (int i=0;i& getTemporaryResults() 49 | { 50 | return cost_image; 51 | } 52 | 53 | /// (re-)evaluate epipolar consistency for input image. Optional n*n image out contains metric for all pairs before and after optimization. 54 | double evaluate(float *out=0x0) 55 | { 56 | /// An optional temporary vector 57 | if (!out) { 58 | cost_image.set(dtrs.size(),dtrs.size()); 59 | int l=cost_image.length(); 60 | #pragma omp parallel for 61 | for (int i=0;ievaluate(); // Should be same as ecc->evaluate(indices, out); except some constant part is added. 67 | 68 | 69 | ecc->evaluate(indices, out); 70 | int n=(int)dtrs.size()-1; 71 | double sum=0; 72 | for (int i=0;isetProjectionMatrices(Ps); 83 | return evaluate(); 84 | } 85 | 86 | }; 87 | 88 | } // EpipolarConsistency 89 | 90 | #endif // _ecc_motioncompenstation_hxx 91 | -------------------------------------------------------------------------------- /code/LibEpipolarConsistency/Gui/InputDataRadonIntermediate.h: -------------------------------------------------------------------------------- 1 | // Created by A. Aichert on Tue Aug 8th 2017. 2 | #ifndef __input_data_radon_intermediate 3 | #define __input_data_radon_intermediate 4 | 5 | #include 6 | #include 7 | 8 | #include "InputDataDirect.h" 9 | #include "ComputeRadonIntermediate.hxx" 10 | 11 | namespace EpipolarConsistency { 12 | 13 | /// Loading and preparation of (mostly) FDCT data for Epipolar Consistency. 14 | struct InputDataRadonIntermediate : public InputDataDirect { 15 | 16 | RadonIntermediateFunction radon_intermediate; //< Computing the Radon intermediate functions 17 | 18 | /// Storing and visualizing output results (to recover more quickly when validating/evaluating) 19 | struct Advanced_DTR { 20 | bool show_radon_intermediate=true; //< Displays the Radon Intermediate Function after computation 21 | std::string basename_radon_intermediate; //< If specified, Radon Intermediate Images are stored here. 22 | std::vector precomputed_radon_intermediate_files; //< Loaded if non-empty and set if basename_radon_intermediate is non-empty. 23 | } advanced_dtr; 24 | 25 | /// Declare default values. 26 | void gui_declare_section (const GetSetGui::Section& section); 27 | 28 | // Retreive current values from GUI 29 | void gui_retreive_section(const GetSetGui::Section& section); 30 | 31 | /// Retreive information about input data from GUI and load data. Does nothing if data is already valid unless force_reload is set. 32 | bool loadData(std::vector& Ps, std::vector& dtrs, GetSetGui::ProgressInterface& progress, bool force_reload=false); 33 | 34 | /// Handles GUI changes automatically. (currently does nothing) 35 | void gui_notify(const std::string& section, const GetSetInternal::Node&) {} 36 | 37 | }; 38 | 39 | /// An advanced GetSet Object based on the simple Configurable 40 | class InputDataRadonIntermediateGui : public GetSetGui::Object, public InputDataRadonIntermediate { 41 | protected: 42 | std::vector Ps; 43 | std::vector dtrs; 44 | 45 | /// Handle (Re-)Load button and visualization stuff. 46 | virtual void gui_notify(const std::string& section, const GetSetInternal::Node&); 47 | 48 | /// Adds a re-load button to the usual InputDataRadonIntermediate Gui. 49 | virtual void gui_declare_section(const GetSetGui::Section& section); 50 | 51 | public: 52 | InputDataRadonIntermediateGui(const GetSetGui::Section& section, GetSetGui::ProgressInterface* app=0x0); 53 | 54 | /// Attempt to load data. If force_reload is not set and Ps and rdas are already set, just returns true. 55 | bool loadData(bool force_reload); 56 | 57 | /// Projection matrices. Make sure to first call laodData(bool force_reload) and check for success. 58 | const std::vector& getProjectionMatrices() const; 59 | 60 | /// Radon Intermediate Functions. Make sure to first call laodData(bool force_reload) and check for success. 61 | const std::vector& getRadonIntermediateFunctions() const; 62 | 63 | }; 64 | 65 | } // namespace EpipolarConsistency 66 | 67 | #endif // __input_data_radon_intermediate 68 | -------------------------------------------------------------------------------- /code/LibEpipolarConsistency/Gui/PreProccess.h: -------------------------------------------------------------------------------- 1 | // Created by A. Aichert on Tue Mar 21st 2017. 2 | #ifndef __pre_process_h 3 | #define __pre_process_h 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | 11 | namespace EpipolarConsistency 12 | { 13 | /// Pre-processing of X-ray projection images. 14 | struct PreProccess : public GetSetGui::Configurable { 15 | 16 | /// Modifying intensities (first normalize, then apply bias and scale, then logarithm) 17 | struct Intensity { 18 | bool normalize =false; 19 | double bias =0.0; 20 | double scale =1.0; 21 | bool apply_log =false; 22 | } intensity; 23 | 24 | /// Low-pass filter. Applied after intensity changes. 25 | struct Lowpass { 26 | double gaussian_sigma =1.84; 27 | int half_kernel_width =5; 28 | } lowpass; 29 | 30 | /// Modifying geometry 31 | struct ImageGeometry { 32 | bool flip_u =false; 33 | bool flip_v =false; 34 | } image_geometry; 35 | 36 | /// Masking and feathering image borders. Offsets are left, right, bottom, top. 37 | struct Border { 38 | Eigen::Vector4i zero=Eigen::Vector4i::Constant(1); 39 | Eigen::Vector4i feather=Eigen::Vector4i::Constant(16); 40 | std::vector blanks; 41 | } border; 42 | 43 | void gui_declare_section (const GetSetGui::Section& section); 44 | void gui_retreive_section(const GetSetGui::Section& section); 45 | 46 | void process(NRRD::ImageView& image) const; 47 | 48 | void apply_weight_cos_principal_ray(NRRD::ImageView& image, const Geometry::ProjectionMatrix& P) const; 49 | 50 | }; 51 | 52 | } // namespace EpipolarConsistency 53 | 54 | #endif // __pre_process_h 55 | -------------------------------------------------------------------------------- /code/LibEpipolarConsistency/Gui/Registration.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aaichert/EpipolarConsistency/8feb718e6b35a943d30684a40e52feb024df91fc/code/LibEpipolarConsistency/Gui/Registration.cpp -------------------------------------------------------------------------------- /code/LibEpipolarConsistency/Gui/Registration.h: -------------------------------------------------------------------------------- 1 | #ifndef _ecc_motioncompenstation_hxx 2 | #define _ecc_motioncompenstation_hxx 3 | 4 | #include 5 | 6 | #include 7 | 8 | #include 9 | 10 | namespace EpipolarConsistency { 11 | 12 | // Epipolar consistency metric for registration of two CTs 13 | class Registration : public LibOpterix::OptimizationProblem 14 | { 15 | std::vector Ps; //< Projection Matrices. First is input image. 16 | std::vector dtrs; //< Radon Intermediate functions. First is input image. 17 | 18 | EpipolarConsistency::MetricRadonIntermediate *ecc; //< The object which computes ECC on the GPU 19 | std::vector indices; //< The pairs of views used for evaluation 20 | std::vector tmp_results; //< The most pairwise results is the last evalutaion. 21 | 22 | Registration(const Registration&); 23 | 24 | public: 25 | 26 | Registration( 27 | LibOpterix::ParameterModel& _parameter_model, 28 | std::vector _Ps, 29 | std::vector _dtrs 30 | ) 31 | : LibOpterix::OptimizationProblem(_parameter_model) 32 | , Ps(_Ps) 33 | , dtrs(_dtrs) 34 | , ecc(new EpipolarConsistency::MetricRadonIntermediate(Ps,dtrs)) 35 | { 36 | int n=(int)_dtrs.size(); 37 | for (int i=1;i& getTemporaryResults() 49 | { 50 | return tmp_results; 51 | } 52 | 53 | /// Access to the pairs of images, which are used for evaluation. See also: getTemporaryResults() 54 | const std::vector& getIndices() 55 | { 56 | return indices; 57 | } 58 | 59 | /// (re-)evaluate epipolar consistency for input image. Optional n-1 vector out contains metric for all pairs. 60 | double evaluate(float *out=0x0) 61 | { 62 | /// An optional temporary vector 63 | if (!out) { 64 | tmp_results.resize(dtrs.size()); 65 | out=&tmp_results[0]; 66 | } 67 | ecc->evaluate(indices, out); 68 | int n=(int)dtrs.size()-1; 69 | double sum=0; 70 | for (int i=0;isetProjectionMatrices(Ps); 81 | return evaluate(); 82 | } 83 | 84 | }; 85 | 86 | } // EpipolarConsistency 87 | 88 | #endif // _ecc_motioncompenstation_hxx 89 | -------------------------------------------------------------------------------- /code/LibEpipolarConsistency/Gui/SingleImageMotion.h: -------------------------------------------------------------------------------- 1 | #ifndef _ecc_motioncompenstation_hxx 2 | #define _ecc_motioncompenstation_hxx 3 | 4 | #include 5 | 6 | #include 7 | 8 | #include 9 | 10 | namespace EpipolarConsistency { 11 | 12 | // Epipolar consistency metric for changes on one projection matrix. 13 | class SingleImageMotion : public LibOpterix::OptimizationProblem 14 | { 15 | std::vector Ps; //< Projection Matrices. First is input image. 16 | std::vector dtrs; //< Radon Intermediate functions. First is input image. 17 | int input_index; //< Index of projection matric being optimized over. 18 | 19 | EpipolarConsistency::MetricRadonIntermediate *ecc; //< The object which computes ECC on the GPU 20 | std::vector indices; //< The pairs of views used for evaluation 21 | std::vector tmp_results; //< The most pairwise results is the last evalutaion. 22 | 23 | SingleImageMotion(const SingleImageMotion&); 24 | 25 | public: 26 | /// Create a SingleImageMotion object from a set of projections and an index 27 | SingleImageMotion( 28 | LibOpterix::ParameterModel& _parameter_model, 29 | std::vector _Ps, 30 | std::vector _dtrs, 31 | int _input_index=0 32 | ) 33 | : LibOpterix::OptimizationProblem(_parameter_model) 34 | , Ps(_Ps) 35 | , dtrs(_dtrs) 36 | , input_index(_input_index) 37 | , ecc(new EpipolarConsistency::MetricRadonIntermediate(Ps,dtrs)) 38 | { 39 | int n=(int)_dtrs.size(); 40 | for (int i=0;i& getTemporaryResults() 52 | { 53 | return tmp_results; 54 | } 55 | 56 | /// Access to the pairs of images, which are used for evaluation. See also: getTemporaryResults() 57 | const std::vector& getIndices() 58 | { 59 | return indices; 60 | } 61 | 62 | /// (re-)evaluate epipolar consistency for input image. Optional n-1 vector out contains metric for all pairs. 63 | double evaluate(float *out=0x0) 64 | { 65 | /// An optional temporary vector 66 | if (!out) { 67 | tmp_results.resize(dtrs.size()); 68 | out=tmp_results.data(); 69 | } 70 | 71 | 72 | return ecc->evaluate(); // Should be same as ecc->evaluate(indices, out); except some constant part is added. 73 | 74 | 75 | ecc->evaluate(indices, out); 76 | int n=(int)dtrs.size()-1; 77 | double sum=0; 78 | for (int i=0;isetProjectionMatrices(Ps); 89 | return evaluate(); 90 | } 91 | 92 | }; 93 | 94 | } // EpipolarConsistency 95 | 96 | #endif // _ecc_motioncompenstation_hxx 97 | -------------------------------------------------------------------------------- /code/LibEpipolarConsistency/Gui/SingleImageMotion.hxx: -------------------------------------------------------------------------------- 1 | #ifndef _ecc_single_image_motion_hxx 2 | #define _ecc_single_image_motion_hxx 3 | 4 | #include 5 | 6 | #include 7 | 8 | #include 9 | 10 | namespace EpipolarConsistency { 11 | 12 | // Epipolar consistency metric for changes on one projection matrix. 13 | class SingleImageMotion : public LibOpterix::OptimizationProblem 14 | { 15 | std::vector Ps; //< Projection Matrices. First is input image. 16 | std::vector dtrs; //< Radon Intermediate functions. First is input image. 17 | int input_index; //< Index of projection matric being optimized over. 18 | 19 | EpipolarConsistency::MetricRadonIntermediate *ecc; //< The object which computes ECC on the GPU 20 | std::vector indices; //< The pairs of views used for evaluation 21 | std::vector tmp_results; //< The most pairwise results is the last evalutaion. 22 | 23 | SingleImageMotion(const SingleImageMotion&); 24 | 25 | public: 26 | /// Create a SingleImageMotion object from a set of projections and an index 27 | SingleImageMotion( 28 | LibOpterix::ParameterModel& _parameter_model, 29 | std::vector _Ps, 30 | std::vector _dtrs, 31 | int _input_index=0 32 | ) 33 | : LibOpterix::OptimizationProblem(_parameter_model) 34 | , Ps(_Ps) 35 | , dtrs(_dtrs) 36 | , input_index(_input_index) 37 | , ecc(new EpipolarConsistency::MetricRadonIntermediate(Ps,dtrs)) 38 | { 39 | int n=(int)_dtrs.size(); 40 | for (int i=0;i& getTemporaryResults() 52 | { 53 | return tmp_results; 54 | } 55 | 56 | /// Access to the pairs of images, which are used for evaluation. See also: getTemporaryResults() 57 | const std::vector& getIndices() 58 | { 59 | return indices; 60 | } 61 | 62 | /// (re-)evaluate epipolar consistency for input image. Optional n-1 vector out contains metric for all pairs. 63 | double evaluate(float *out=0x0) 64 | { 65 | /// An optional temporary vector 66 | if (!out) { 67 | tmp_results.resize(dtrs.size()); 68 | out=tmp_results.data(); 69 | } 70 | 71 | 72 | return ecc->evaluate(); // Should be same as ecc->evaluate(indices, out); except some constant part is added. 73 | 74 | 75 | ecc->evaluate(indices, out); 76 | int n=(int)dtrs.size()-1; 77 | double sum=0; 78 | for (int i=0;isetProjectionMatrices(Ps); 89 | return evaluate(); 90 | } 91 | 92 | }; 93 | 94 | } // EpipolarConsistency 95 | 96 | #endif // _ecc_single_image_motion_hxx 97 | -------------------------------------------------------------------------------- /code/LibEpipolarConsistency/Gui/Visualization.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aaichert/EpipolarConsistency/8feb718e6b35a943d30684a40e52feb024df91fc/code/LibEpipolarConsistency/Gui/Visualization.cpp -------------------------------------------------------------------------------- /code/LibEpipolarConsistency/RectifiedFBCC.h: -------------------------------------------------------------------------------- 1 | // Created by A. Aichert on Dec 20th 2017 2 | 3 | #ifndef __line_perspectivity_hxx 4 | #define __line_perspectivity_hxx 5 | 6 | #ifndef __device__ 7 | #define __device__ 8 | #define udef__device__ 9 | #endif 10 | #ifndef __host__ 11 | #define __host__ 12 | #define udef__host__ 13 | #endif 14 | 15 | /// Perspectivity on a Line l=H^T*l_prime in an image transformed by x_prime=H*x 16 | struct LinePerspectivity { 17 | float a=1.f; 18 | float b=0.f; 19 | float c=0.f; 20 | float d=1.f; 21 | 22 | // We use Eigen only in c++ code, not when compiled for CUDA 23 | #ifdef __real_projective_space_types_defined 24 | /// Compute line coordinate of a 2D point x on the line l 25 | static Geometry::RP2Point project_to_plane(double t, Geometry::RP2Line& l) { 26 | return Geometry::RP2Point(-l[2]*l[0]+t*l[1],-l[2]*l[1]-t*l[0],1.0); 27 | } 28 | 29 | /// Compute line coordinate of a 2D point x on the line l 30 | static double project_to_line(const Geometry::RP2Point& x, const Geometry::RP2Line& l) { 31 | return l[1]*x[0]/x[2] -l[0]*x[1]/x[2]; 32 | } 33 | 34 | /// Line distance (is zero for point x on line l) 35 | static double line_distance(double u, double v, Geometry::RP2Line& l) { 36 | return l[0]*u +l[1]*v+l[2]; 37 | } 38 | 39 | /// Mapping of line coordinates on a line in a projectively transforming image. 40 | LinePerspectivity(const Geometry::RP2Homography& H, const Geometry::RP2Line& l) { 41 | a=(float)( H(0,0)*l(1)-H(1,0)*l(0) ); 42 | b=(float)(H(0,2) -H(0,0)*l(0)*l(2)); 43 | c=(float)( H(2,0)*l(1)-H(2,1)*l(0) ); 44 | d=(float)(H(2,2)-H(2,0)*l(0)*l(2) -H(2,1)*l(1)*l(2)); 45 | if (a*d - b*c < 0) { 46 | a*=-1; 47 | b*=-1; 48 | } 49 | } 50 | 51 | /// 2D rigid transformation which brings closest point on line to origin and rotates line into u-axis. 52 | static Geometry::RP2Homography mapping_to_line_coordinates(const Geometry::RP2Line& l) { 53 | Geometry::RP2Homography Hlu; 54 | Hlu << 55 | l[1],-l[0], 0., 56 | l[0], l[1],l[2], 57 | 0., 0., 1.; 58 | return Hlu; 59 | } 60 | #endif // __real_projective_space_types_defined 61 | 62 | /// Initialize with identity or from raw memory 63 | __device__ __host__ LinePerspectivity(float *v=0x0) : a(v?v[0]:1.f), b(v?v[1]:.0f), c(v?v[2]:.0f), d(v?v[3]:1.f) {} 64 | 65 | /// Perspective transformation of line coordinate 66 | __device__ __host__ float transform (float t) const { 67 | return (a*t+b)/(c*t+d); 68 | } 69 | 70 | /// Inverse perspective transformation of line coordinate 71 | __device__ __host__ float inverse (float t_prime) const { 72 | return (d*t_prime-b)/(-c*t_prime+a); 73 | } 74 | 75 | /// Derivative of transform(...) 76 | __device__ __host__ float derivative(float t) const { 77 | return (a*d-b*c) / (c*c*t*t +2*c*d*t +d*d); 78 | } 79 | 80 | }; 81 | 82 | /// Mixed bad of all important information to compute FBCC in cone-beam projections. 83 | struct FBCC_weighting_info { 84 | LinePerspectivity phi; //< Transformation from line coords on l_kappa to virtual detector u-axis 85 | float t_prime_ak; //< Closest point to epipolar line in virtual detector u-coordinates 86 | float d_l_kappa_C_sq; //< Squared pixel distance from source to epipolar line 87 | float dummy0,dummy1; 88 | }; 89 | 90 | #ifdef udef__device__ 91 | #undef __device__ 92 | #endif 93 | #ifdef udef__host__ 94 | #undef __host__ 95 | #endif 96 | 97 | #endif // __line_perspectivity_hxx 98 | -------------------------------------------------------------------------------- /code/LibGeometryCalibration/BeadDetection.h: -------------------------------------------------------------------------------- 1 | #ifndef _beaddetection_h 2 | #define _beaddetection_h 3 | 4 | #include 5 | #include 6 | 7 | #include 8 | 9 | #include 10 | #include 11 | 12 | namespace Calibration { 13 | 14 | /// Detect bright round blobs in an image. 15 | struct BeadDetection : public GetSetGui::Configurable { 16 | /// Parameers for the fast radial symmetry transform 17 | struct ParamsFRST { 18 | std::vector beadRadiiPx=stringToVector("4;8"); 19 | double gaussian_sigma = 3.68; 20 | int gaussian_width = 5; 21 | double threshold_frst = 0.1; 22 | double threshold_gradient= 0; 23 | } paramsFRST; 24 | 25 | /// Result: Detected beads 26 | std::vector beads; 27 | /// Intermediate result: FRST (after thresholding) 28 | NRRD::Image frst; 29 | /// Intermediate result: Connected components of thresholded FRST. 30 | NRRD::Image components; 31 | 32 | /// Visualize results 33 | static void overlayDetectedBeads( 34 | const std::vector& result, 35 | GraphicsItems::Group& overlay, 36 | double last_component_threshold=0); 37 | 38 | /// Analyze single channel 2D image for bright beads. Returns (X,Y,radius). 39 | const std::vector& process(const NRRD::ImageView& image); 40 | 41 | virtual void gui_declare_section (const GetSetGui::Section §ion); 42 | virtual void gui_retreive_section(const GetSetGui::Section §ion); 43 | 44 | }; 45 | 46 | #undef small 47 | 48 | /// Differentiate between large and small bright blobs 49 | struct BeadDetectionTwoSize : public GetSetGui::Configurable { 50 | 51 | double min_distance_px=10; //< If two detections are less than min_distance_px apart, they are handled according to prefer_beads 52 | BeadDetection large; 53 | BeadDetection small; 54 | /// Result: Detected beads 55 | std::vector beads; 56 | 57 | /// Analyze single channel 2D image for bright beads. Returns (X,Y,radius). 58 | const std::vector& process(const NRRD::ImageView& image); 59 | 60 | virtual void gui_declare_section (const GetSetGui::Section §ion); 61 | virtual void gui_retreive_section(const GetSetGui::Section §ion); 62 | }; 63 | 64 | /// BeadDetectionTwoSize with testing functions 65 | struct BeadDetectionGui : public BeadDetectionTwoSize, public GetSetGui::Object { 66 | BeadDetectionGui(const GetSetGui::Section& section, GetSetGui::ProgressInterface *app); 67 | virtual void gui_init(); 68 | virtual void gui_notify(const std::string& relative_section, const GetSetInternal::Node& node); 69 | }; 70 | 71 | } // Calibration 72 | 73 | #endif // _beaddetection_h 74 | -------------------------------------------------------------------------------- /code/LibGeometryCalibration/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_library( LibGeometryCalibration 2 | BeadDetection.h 3 | BeadDetection.cpp 4 | GeometryCalibration.h 5 | GeometryCalibration.cpp 6 | EstimateProjectionMatrix.h 7 | EstimateProjectionMatrix.cpp 8 | PhantomPDS2.h 9 | PhantomPDS2.cpp 10 | BeadPhantomGui.hxx 11 | ) 12 | target_link_libraries( LibGeometryCalibration LibProjectiveGeometry LibRayCastBackproject LibUtilsQt GetSet GetSetGui) 13 | qt5_use_modules(LibGeometryCalibration Gui Svg PrintSupport) 14 | install(TARGETS LibGeometryCalibration DESTINATION lib) 15 | set_property(TARGET LibGeometryCalibration PROPERTY FOLDER "Calibration") 16 | 17 | add_executable( CalibPDS2 18 | main_pds2.cpp 19 | ) 20 | target_link_libraries( CalibPDS2 LibGeometryCalibration LibRayCastBackproject LibEpipolarConsistencyGui LibRayCastBackproject LibUtilsQt GetSet GetSetGui) 21 | qt5_use_modules(CalibPDS2 Gui Svg PrintSupport) 22 | set_property(TARGET CalibPDS2 PROPERTY FOLDER "Calibration") 23 | -------------------------------------------------------------------------------- /code/LibGeometryCalibration/EstimateProjectionMatrix.h: -------------------------------------------------------------------------------- 1 | #ifndef __estimate_projection_matrix_h 2 | #define __estimate_projection_matrix_h 3 | 4 | #include 5 | #include 6 | 7 | #include 8 | #include 9 | 10 | #include 11 | 12 | namespace Calibration { 13 | 14 | /// An abstract class which supports generating candidate matches to a set of 3D Points 15 | class EstimateProjectionMatrix : public GetSetGui::Configurable { 16 | public: 17 | struct ICP { 18 | int num_ietartions = 2; //< The maximum number of iterations allowed in the algorithm. 19 | double inliner_tolerance_px = 10; //< A distance threshold for closest bead for the match to be considered correct. 20 | } icp; 21 | struct RANSAC { 22 | double inliner_tolerance_px = 4; //< When the reprojection error of a point is larger, we consider it an outlier. 23 | int max_ietartions = 100; //< The maximum number of iterations allowed in the algorithm. 24 | double min_inliner_rel = 0.5; //< Stopping criteria: minimum proportion of inliers. 25 | } ransac; 26 | struct Algorithms { 27 | bool use_ransac = true; //< Use Random Sample Consensus 28 | bool use_icp = false; //< Use Iterative Closest Point for more matches 29 | bool use_non_linear_refinement = false; //< 2do not implemented 30 | } algorithms; 31 | 32 | mutable std::map inlier_set; // debug 33 | 34 | /// Compute candidate matching. Returns map from 2D bead index to 3D bead index. 35 | Geometry::ProjectionMatrix estimateProjection( 36 | const std::map& matching, 37 | const std::vector& detected_beads, 38 | const std::vector& phantom_beads 39 | ) const; 40 | 41 | /// Declare types and default values for all properties. 42 | virtual void gui_declare_section (const GetSetGui::Section& section); 43 | /// Retreive current values from GUI 44 | virtual void gui_retreive_section(const GetSetGui::Section& section); 45 | 46 | }; 47 | 48 | 49 | } // namespace Calibration 50 | 51 | #endif // __estimate_projection_matrix_h 52 | -------------------------------------------------------------------------------- /code/LibGeometryCalibration/PhantomPDS2.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aaichert/EpipolarConsistency/8feb718e6b35a943d30684a40e52feb024df91fc/code/LibGeometryCalibration/PhantomPDS2.cpp -------------------------------------------------------------------------------- /code/LibGeometryCalibration/PhantomPDS2.h: -------------------------------------------------------------------------------- 1 | #ifndef __phantompds2_hxx 2 | #define __phantompds2_hxx 3 | 4 | #include 5 | 6 | #include 7 | 8 | 9 | namespace Calibration { 10 | 11 | /// A description of a PDS2 bead phantom 12 | struct PhantomDescriptorPDS2 : public BeadPhantomDescriptor 13 | { 14 | /// A sequence of small (false) and big (true) beads, with all unambiguous sub-sequences of 8. 15 | static const std::vector& defaultBeadSequence(); 16 | 17 | /// The helix of beads 18 | struct Helix { 19 | double height = 206; 20 | double offset = 33; 21 | double radius = 67; 22 | double angularIncrement = 9.0 / 180.0 * Geometry::Pi; 23 | } helix; 24 | /// The plastic cylinder 25 | struct Cylinder { 26 | double outerRadius = 72; 27 | double innerRadius = 62; 28 | double density = 0.125; 29 | } cylinder; 30 | /// The actual beads 31 | struct Beads { 32 | double axialIncrement = 1.308411215; 33 | double smallDiameter = 1.6; 34 | double largeDiameter = 3.2; 35 | double density = 1.0; 36 | } beads; 37 | 38 | /// Sequence of small and big beads 39 | std::vector largeBeadSequence = defaultBeadSequence(); 40 | 41 | /// Create a bead phantom from a PDS2 descriptor 42 | virtual std::vector getBeads() const; 43 | 44 | /// Adds a plastic cylinder to an existing voxelized phantom. 2do 45 | // void addPlasticCylinder(NRRD::ImageView beadphantom, const Geometry::RP3Homography& model_transform); 46 | 47 | /// Find a given code within the largeBeadSequence. 48 | static int computeBeadNumber(const std::vector& code, const std::vector& largeBeadSequence); 49 | 50 | /// Declare types and default values for all properties. 51 | virtual void gui_declare_section (const GetSetGui::Section& section); 52 | /// Retreive current values from GUI 53 | virtual void gui_retreive_section(const GetSetGui::Section& section); 54 | 55 | }; 56 | 57 | /// A class to find 2D/3D matches in projections of the PDS2 phantom 58 | class PhantomDetectionPDS2 : public BeadPhantomDetection 59 | { 60 | public: 61 | struct ParamMatching { 62 | double distance_min = 10; //< Min. distance of closest neighboring bead 63 | double angular_tolerance = 10; //< Neighborhood: Max. degrees deviation from line 64 | } paramMatching; 65 | 66 | /// Compute candidate matching. Returns map from 2D bead index to 3D bead index. 67 | virtual std::map match(const std::vector& detected_beads) const; 68 | 69 | /// Declare types and default values for all properties. 70 | void gui_declare_section (const GetSetGui::Section& section); 71 | /// Retreive current values from GUI 72 | void gui_retreive_section(const GetSetGui::Section& section); 73 | 74 | mutable std::vector debug_dirs; //< Local estimates direction of helix. DELETE just for debugging. 75 | 76 | }; 77 | 78 | } // namespace Calibration 79 | 80 | #endif // __phantompds2_hxx 81 | -------------------------------------------------------------------------------- /code/LibProjectiveGeometry/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # A libbrary for advanced 2D and 3D projective geometry 2 | add_library(LibProjectiveGeometry 3 | # toString and stringTo<...> function for a few Eigen types. 4 | EigenToStr.hxx 5 | # Geometry of 2D point and lines, as well as 3D points, Plücker lines and planes. 6 | ProjectiveGeometry.hxx 7 | # The 3x4 projection matrix and its geometric interpretation as pinhole camera. 8 | ProjectionMatrix.h 9 | ProjectionMatrix.cpp 10 | # The SVD implementation is compiled separately to reduce compilation times. 11 | SingularValueDecomposition.h 12 | SingularValueDecomposition.cpp 13 | # Interpretation as the projection matrix as an X-ray source-detector geometry. 14 | SourceDetectorGeometry.h 15 | SourceDetectorGeometry.cpp 16 | # Linear estimation of the projection matrix. 17 | EstimateProjectionMatrix.h 18 | EstimateProjectionMatrix.cpp 19 | # Conversion of OpenGL and 3x4 projection matrices. 20 | CameraOpenGL.hxx 21 | # An over-parametrization of 8DOF 2D projective transformations. 22 | Models/ModelHomography2D.hxx 23 | Models/ModelHomography3D.hxx 24 | # Parametization of a similarity transformation. 25 | Models/ModelSimilarity2D.hxx 26 | Models/ModelSimilarity3D.hxx 27 | # Parametrization of 2D and 3D similarity transformations acting on a projection matrix. 28 | Models/ModelCameraSimilarity2D3D.hxx 29 | # Parametrization of a projection matrix acoording to the IEC 61217 standard (RTK). 30 | Models/ModelTrajectoryIEC61217.hxx 31 | # Obsolete alternative Parametrization of a projection matrix. 32 | Models/ModelFDCTCalibrationCorrection.hxx 33 | ) 34 | install(FILES EigenToStr.hxx ProjectiveGeometry.hxx ProjectionMatrix.h SingularValueDecomposition.h CameraOpenGL.hxx GeometryVisualization.hxx DESTINATION include/LibProjectiveGeometry) 35 | install(FILES Models/ModelFDCTCalibrationCorrection.hxx Models/ModelCameraSimilarity2D3D.hxx Models/ModelSimilarity2D.hxx Models/ModelHomography2D.hxx Models/ModelSimilarity3D.hxx Models/ModelHomography3D.hxx Models/ModelTrajectoryIEC61217.hxx DESTINATION include/LibProjectiveGeometry/Models) 36 | install(TARGETS LibProjectiveGeometry DESTINATION lib EXPORT LibProjectiveGeometry-targets) 37 | install(EXPORT LibProjectiveGeometry-targets DESTINATION cmake) 38 | set_property(TARGET LibProjectiveGeometry PROPERTY FOLDER "Packages") 39 | -------------------------------------------------------------------------------- /code/LibProjectiveGeometry/EstimateProjectionMatrix.cpp: -------------------------------------------------------------------------------- 1 | #include "EstimateProjectionMatrix.h" 2 | 3 | #include "ProjectiveGeometry.hxx" 4 | #include "ProjectionMatrix.h" 5 | #include "SingularValueDecomposition.h" 6 | 7 | 8 | namespace Geometry { 9 | 10 | /// Normalization of 2D and 3D point clouds: de-mean and scale to +/- sqtr(2), sqrt(3) respectively. Input assumed to have homogeneous coordinate 1. 11 | std::pair dlt_normalization( 12 | const std::vector& p2d, 13 | const std::vector& p3d, 14 | const std::map& match) 15 | { 16 | // Compute mean 17 | Eigen::Vector2d mean2d(0, 0); 18 | Eigen::Vector3d mean3d(0, 0, 0); 19 | for (auto it=match.begin();it!=match.end();++it) { 20 | mean2d += p2d[it->first ].head(2); 21 | mean3d += p3d[it->second].head(3); 22 | } 23 | mean2d /= (double)match.size(); 24 | mean3d /= (double)match.size(); 25 | 26 | // Compute size 27 | double s2d = 0; 28 | double s3d = 0; 29 | for (auto it=match.begin();it!=match.end();++it) { 30 | s2d += (p2d[it->first ].head(2) - mean2d).norm(); 31 | s3d += (p3d[it->second].head(3) - mean3d).norm(); 32 | } 33 | s2d *= sqrt(2) /(double)match.size(); 34 | s3d *= sqrt(3) /(double)match.size(); 35 | 36 | // Compose normalization matrices 37 | return std::make_pair( 38 | Geometry::Scale(s2d,s2d )*Geometry::Translation(-mean2d[0],-mean2d[1]), 39 | Geometry::Scale(s3d,s3d,s3d)*Geometry::Translation(-mean3d) 40 | ); 41 | } 42 | 43 | /// Direct Linear Transformation for projection matrices. Input assumed to have homogeneous coordinate 1. 44 | Geometry::ProjectionMatrix dlt(const std::vector& x, const std::vector& X, std::map match) 45 | { 46 | // Optional match parameter 47 | if (match.empty() && X.size()==x.size() ) { 48 | for (int i=0;i<(int)X.size();i++) 49 | match[i]=i; 50 | } 51 | 52 | // Check for insufficiant data 53 | if (match.size() < 6 ) { 54 | return Geometry::ProjectionMatrix::Zero(); 55 | } 56 | 57 | // Normalization of input data 58 | auto normalization=dlt_normalization(x,X,match); 59 | //auto& N_px=normalization.first; 60 | //auto& N_mm=normalization.second; 61 | 62 | auto& N_px=Geometry::RP2Homography::Identity(); 63 | auto& N_mm=Geometry::RP3Homography::Identity(); 64 | 65 | // Build homgeneous system mmatrix from point matches 66 | Eigen::MatrixXd A(2 * match.size(), 12); 67 | auto it=match.begin(); 68 | for (int k = 0; it!=match.end(); k+=2, ++it) 69 | { 70 | // Normalize input points 71 | Geometry::RP2Point x_norm = N_px*x[it->first]; 72 | Geometry::RP3Point X_norm = N_mm*X[it->second]; 73 | // Write two rows in A (we get two independent equations from one point match) 74 | A.block<1, 4>(k , 0).setZero(); 75 | A.block<1, 4>(k + 1, 4).setZero(); 76 | A.block<1, 4>(k , 4) = x_norm(2) *X_norm.transpose(); 77 | A.block<1, 4>(k + 1, 0) = -x_norm(2) *X_norm.transpose(); 78 | A.block<1, 4>(k , 8) = -x_norm(1) *X_norm.transpose(); 79 | A.block<1, 4>(k + 1, 8) = x_norm(0) *X_norm.transpose(); 80 | } 81 | 82 | // Solve and reshape 83 | Eigen::VectorXd p = Geometry::nullspace(A); 84 | Geometry::ProjectionMatrix P_norm = Eigen::Matrix(p.data()).transpose(); 85 | 86 | //denormalize 87 | Geometry::ProjectionMatrix P = N_px.inverse()*P_norm*N_mm; 88 | Geometry::normalizeProjectionMatrix(P); 89 | return P; 90 | } 91 | 92 | } // namespace Geometry 93 | 94 | -------------------------------------------------------------------------------- /code/LibProjectiveGeometry/EstimateProjectionMatrix.h: -------------------------------------------------------------------------------- 1 | #ifndef __direct_linear_transformation 2 | #define __direct_linear_transformation 3 | 4 | #include "ProjectiveGeometry.hxx" 5 | 6 | #include 7 | #include 8 | 9 | namespace Geometry { 10 | 11 | /// Direct Linear Transformation for projection matrices. Input assumed to have homogeneous coordinate 1. 12 | Geometry::ProjectionMatrix dlt(const std::vector& x, const std::vector& X, std::map match=std::map()); 13 | 14 | } // namespace Geometry 15 | 16 | #endif // __direct_linear_transformation 17 | -------------------------------------------------------------------------------- /code/LibProjectiveGeometry/LibOpterix/Opterix.hxx: -------------------------------------------------------------------------------- 1 | // LibOpterix. 2 | // + `@ 3 | // `@ .@# 4 | // @@. ,+@@# 5 | // @@@ .@@@@+. @, 6 | // ,@@@@@@@@@@#', @@@. `@@@. 7 | // @ `,;#@@@@@@; ,, ++', :@@+ 8 | // #@. +@@@.@ +' @@:, 9 | // :+@@@@@@@@@@` @ @@ 10 | // ' ,@@+@` @@ 11 | // ,#@@@@ `@ 12 | // @@ @ 13 | // :@@ O P T E R I X 14 | // @@@+;'@: 15 | // A c++ library allowing non-linear optimization to easily exchange parametrizations and optimization algorthms/libraries. 16 | // To use this library, you need to define two classes, one deriving from OptimizationProblem, and another deriving from AbstractOptimizer. 17 | // This library includes a simple grid-search and Powell optimizer and optional wrappers for NLopt (others pending). 18 | 19 | #ifndef __opterix_hxx 20 | #define __opterix_hxx 21 | 22 | #include 23 | #include 24 | 25 | namespace LibOpterix { 26 | 27 | /// Interface for an objective function 28 | struct AbstractOptimizationProblem 29 | { 30 | AbstractParameterModel& abstract_model; 31 | AbstractOptimizationProblem(AbstractParameterModel& _abstract_model) 32 | : abstract_model(_abstract_model) 33 | {} 34 | 35 | // Compute cost function value given a parameter vector 36 | virtual double evaluate(const std::vector& x) =0; 37 | 38 | /// Compute gradient and cost function value. 39 | virtual double evaluate_gradient(const std::vector& x, std::vector& gradient) 40 | { 41 | throw std::logic_error("AbstractObjectiveFunction: Gradient computation is not implemented for this optimization problem."); 42 | } 43 | }; 44 | 45 | /// The actual optimization problem, which uses a specific parametrization of ParametrizedObject. 46 | template 47 | struct OptimizationProblem : public AbstractOptimizationProblem 48 | { 49 | ParameterModel& model; 50 | OptimizationProblem(ParameterModel& _model) 51 | : AbstractOptimizationProblem(_model) 52 | , model(_model) 53 | {} 54 | 55 | /// Compute cost function value from ParametrizedObject 56 | virtual double evaluate(const ParametrizedObject& obj) =0; 57 | 58 | /// Compute cost function value given a parameter vector 59 | virtual double evaluate(const std::vector& x) 60 | { 61 | model.expand(&x[0]); 62 | return evaluate(model.getInstance()); 63 | } 64 | }; 65 | 66 | /// To use this library, you need to define two classes, one deriving from OptimizationProblem, and another deriving from AbstractOptimizer. 67 | struct AbstractOptimizer 68 | { 69 | public: 70 | // Simple callback mechanism for a notification after each cost-function evaluation 71 | typedef void (*NotifyUpdate)(double current_cost, AbstractOptimizationProblem* problem); 72 | 73 | // Optimization problem 74 | AbstractOptimizationProblem& abstract_objective; 75 | AbstractOptimizer(AbstractOptimizationProblem& _abstract_objective) 76 | : abstract_objective(_abstract_objective) 77 | , user_callback(0x0) 78 | , progress(0x0) 79 | {} 80 | 81 | /// Perform optimization over parameters in AbstractOptimizationProblem. 82 | virtual bool optimize(GetSetGui::ProgressInterface&) =0; 83 | 84 | /// Optionally ask optimizer to notify called after each cost function evaluation. 85 | AbstractOptimizer& setCallback(NotifyUpdate _callback) 86 | { 87 | user_callback=_callback; 88 | return *this; 89 | } 90 | 91 | protected: 92 | NotifyUpdate user_callback; 93 | GetSetGui::ProgressInterface *progress; 94 | }; 95 | 96 | } // namspace Optimizationx 97 | 98 | #endif // __opterix_hxx 99 | -------------------------------------------------------------------------------- /code/LibProjectiveGeometry/Models/ModelCameraKRt.hxx: -------------------------------------------------------------------------------- 1 | #ifndef __model_camera_decomposition 2 | #define __model_camera_decomposition 3 | // Created by A. Aichert on Fr July 27th 2018 4 | 5 | #include 6 | #include 7 | 8 | namespace Geometry 9 | { 10 | 11 | // Simple Pinhole Camera Class from intrinsic and extrinsic parameters 12 | class ModelCameraKRt : public LibOpterix::ParameterModel 13 | { 14 | public: 15 | /// Human readable names of all parameters. 16 | static const std::vector& ParameterNames() 17 | { 18 | static std::vector names; 19 | if (names.empty()) 20 | { 21 | names.push_back("Focal Length u [px]"); 22 | names.push_back("Focal Length v [px]"); 23 | names.push_back("Principal Point u [px]"); 24 | names.push_back("Principal Point v [px]"); 25 | names.push_back("Skew"); 26 | names.push_back("Translation X"); 27 | names.push_back("Translation Y"); 28 | names.push_back("Translation Z"); 29 | names.push_back("Rotation X"); 30 | names.push_back("Rotation Y"); 31 | names.push_back("Rotation Z"); 32 | } 33 | return names; 34 | } 35 | 36 | /// Frequent sets of active parameters 37 | static const LibOpterix::ParameterSets& ParameterSets() 38 | { 39 | static LibOpterix::ParameterSets sets; 40 | if (sets.empty()) 41 | { 42 | 43 | // 2do 44 | 45 | } 46 | return sets; 47 | } 48 | 49 | ModelCameraKRt(std::set _active = std::set()) 50 | : LibOpterix::ParameterModel(ParameterNames(),_active) 51 | {} 52 | 53 | /// Transform projection matrix with 2D and 3D similarity transform. 54 | virtual Geometry::ProjectionMatrix getInstance() const 55 | { 56 | const std::vector& x(current_values); 57 | Eigen::Matrix3d K,R; 58 | Eigen::Vector3d t; 59 | 60 | K << x[0], x[4], x[2], 61 | 0, x[1], x[3], 62 | 0, 0 , 1; 63 | 64 | R = (RotationX(x[8])*RotationY(x[9])*RotationZ(x[10])).block<3,3>(0,0); 65 | t[0]=x[5]; 66 | t[1]=x[6]; 67 | t[2]=x[7]; 68 | 69 | return makeProjectionMatrix(K,R,t); 70 | } 71 | 72 | /// Decompose existing projection matrix 73 | virtual ModelCameraKRt& setInstance(const Geometry::ProjectionMatrix& P, bool v_points_up) 74 | { 75 | Eigen::Matrix3d K,R; 76 | Eigen::Vector3d t; 77 | Geometry::projectionMatrixDecomposition(P,K,R,t,v_points_up); 78 | std::vector& x(current_values); 79 | x[ 0]=K(0,0); 80 | x[ 1]=K(1,1); 81 | x[ 2]=K(0,2); 82 | x[ 3]=K(1,2); 83 | x[ 4]=K(0,1); 84 | x[ 5]=t(0); 85 | x[ 6]=t(1); 86 | x[ 7]=t(2); 87 | x[ 8]=std::asin(R(1,3)); 88 | x[ 9]=std::acos(R(1,1)/cos(x[ 8])); 89 | x[10]=std::acos(R(3,3)/cos(x[ 8])); 90 | return *this; 91 | } 92 | }; 93 | 94 | } // namespace Geometry 95 | 96 | #endif // __model_camera_decomposition 97 | -------------------------------------------------------------------------------- /code/LibProjectiveGeometry/Models/ModelCameraSimilarity2D3D.hxx: -------------------------------------------------------------------------------- 1 | #ifndef __model_camera_similarity 2 | #define __model_camera_similarity 3 | // Created by A. Aichert on Fr Sept 12th 2014 4 | // Projective transformation of both world and image P'=T*P*H 5 | 6 | #include 7 | #include "ModelSimilarity2D.hxx" 8 | #include "ModelSimilarity3D.hxx" 9 | #include 10 | 11 | namespace Geometry 12 | { 13 | 14 | // Simple Pinhole Camera Class FIXME how to cleanly access template parameter N of ProjectiveTransormationXD 15 | class ModelCameraSimilarity2D3D : public LibOpterix::ParameterModel 16 | { 17 | /// The unaltered projection matrix 18 | Geometry::ProjectionMatrix P; 19 | 20 | public: 21 | /// Human readable names of all parameters. 22 | static const std::vector& ParameterNames() 23 | { 24 | static std::vector names; 25 | if (names.empty()) 26 | { 27 | // Insert names for ModelSimilarity2D and ModelSimilarity3D separately 28 | const auto &s2d=ModelSimilarity2D::ParameterNames(); 29 | const auto &s3d=ModelSimilarity3D::ParameterNames(); 30 | names.insert(names.end(), s2d.begin(), s2d.end()); 31 | names.insert(names.end(), s3d.begin(), s3d.end()); 32 | } 33 | return names; 34 | } 35 | 36 | /// Frequent sets of active parameters 37 | static const LibOpterix::ParameterSets& ParameterSets() 38 | { 39 | static LibOpterix::ParameterSets sets; 40 | if (sets.empty()) 41 | { 42 | // Insert sets for ModelSimilarity2D and adapted indices for sets from ModelSimilarity2D 43 | int n2d=(int)ModelSimilarity2D::ParameterNames().size(); 44 | const auto &s2d=ModelSimilarity3D::ParameterSets(); 45 | sets.insert(s2d.begin(), s2d.end()); 46 | LibOpterix::ParameterSets s3d=ModelSimilarity2D::ParameterSets(); 47 | for (auto mit=s3d.begin();mit!=s3d.end();++mit) 48 | { 49 | std::set& old_idcs(mit->second); 50 | auto& current_set=sets[mit->first]; 51 | for (auto it=old_idcs.begin();it!=old_idcs.end();++it) 52 | current_set.insert(*it+n2d); 53 | } 54 | 55 | } 56 | return sets; 57 | } 58 | 59 | ModelCameraSimilarity2D3D(Geometry::ProjectionMatrix _P, std::set _active) 60 | : LibOpterix::ParameterModel(ParameterNames(),_active) 61 | , P(_P) 62 | {} 63 | 64 | /// Update the unaltered projection matrix 65 | void setOriginalProjectionMatrix(const Geometry::ProjectionMatrix& _P) { 66 | P=_P; 67 | std::fill(current_values.begin(), current_values.end(), 0); 68 | } 69 | 70 | /// The 2D Similarity. 71 | Geometry::RP2Homography getTransform2D() const 72 | { 73 | int n2d=(int)ModelSimilarity2D::ParameterNames().size(); 74 | ModelSimilarity2D m2d; 75 | m2d.current_values=std::vector(current_values.begin(),current_values.begin()+n2d); 76 | return m2d.getInstance(); 77 | } 78 | 79 | /// The 3D similarity. 80 | Geometry::RP3Homography getTransform3D() const 81 | { 82 | int n2d=(int)ModelSimilarity2D::ParameterNames().size(); 83 | ModelSimilarity3D m3d; 84 | m3d.current_values=std::vector(current_values.begin()+n2d,current_values.end()); 85 | return m3d.getInstance(); 86 | } 87 | 88 | /// Transform projection matrix with 2D and 3D similarity transform. 89 | virtual Geometry::ProjectionMatrix getInstance() const 90 | { 91 | return getTransform2D()*P*getTransform3D(); 92 | } 93 | 94 | }; 95 | 96 | } // namespace Geometry 97 | 98 | #endif // __camera_transformation 99 | -------------------------------------------------------------------------------- /code/LibProjectiveGeometry/Models/ModelHomography2D.hxx: -------------------------------------------------------------------------------- 1 | // Created by A. Aichert on Tue Aug 12th 2014 2 | #ifndef __model_homography2D 3 | #define __model_homography2D 4 | 5 | #include 6 | 7 | #include 8 | 9 | namespace Geometry { 10 | // Over-parametrization for a projective transformation of 2-space 11 | struct ModelHomography2D : public LibOpterix::ParameterModel 12 | { 13 | /// Human readable names of all parameters. 14 | static const std::vector& ParameterNames() 15 | { 16 | static std::vector names; 17 | if (names.empty()) 18 | { 19 | names.resize(11); 20 | names[ 0]="Center of Rotation u"; 21 | names[ 1]="Center of Rotation v"; 22 | names[ 2]="Translation u"; 23 | names[ 3]="Translation v"; 24 | names[ 4]="2D Rotation"; 25 | names[ 5]="2D Scale"; 26 | names[ 6]="Scale u"; 27 | names[ 7]="Scale v"; 28 | names[ 8]="Shearing Direction"; 29 | names[ 9]="Projective Distortion u"; 30 | names[10]="Projective Distortion v"; 31 | } 32 | return names; 33 | } 34 | 35 | /// Frequent sets of active parameters 36 | static const LibOpterix::ParameterSets& ParameterSets() 37 | { 38 | static LibOpterix::ParameterSets sets; 39 | if (sets.empty()) 40 | { 41 | sets["2D Translation"].insert(2); 42 | sets["2D Translation"].insert(3); 43 | sets["2D Rigid"].insert(2); 44 | sets["2D Rigid"].insert(3); 45 | sets["2D Rigid"].insert(4); 46 | sets["2D Similarity"].insert(2); 47 | sets["2D Similarity"].insert(3); 48 | sets["2D Similarity"].insert(4); 49 | sets["2D Similarity"].insert(5); 50 | } 51 | return sets; 52 | } 53 | 54 | ModelHomography2D(std::set _active) 55 | : LibOpterix::ParameterModel(ParameterNames(),_active) 56 | {} 57 | 58 | // Compose a 2D homography from parametrization 59 | virtual Geometry::RP2Homography getInstance() const 60 | { 61 | using namespace Eigen; 62 | const std::vector& x(current_values); 63 | 64 | Matrix3d H=Matrix3d::Identity(); 65 | // Rotation 66 | if (x[4]!=0) 67 | { 68 | H << +cos(x[4]), -sin(x[4]), 0, 69 | +sin(x[4]), +cos(x[4]), 0, 70 | 0, 0, 1; 71 | } 72 | // Center of rotation 73 | Eigen::Vector3d c=H*Eigen::Vector3d(x[0],x[1],1); 74 | // Translation 75 | H(0,2)=c(0)-x[0]+x[2]; 76 | H(1,2)=c(1)-x[1]+x[3]; 77 | // (Anisotropic) scaling 78 | Matrix3d D=Eigen::Vector3d((1.0+x[5])*(1.0+x[6]),(1.0+x[5])*(1.0+x[7]),1.0).asDiagonal(); 79 | if (x[8]) 80 | { 81 | // Shearing 82 | Matrix3d Rs; 83 | Rs << +cos(x[8]), -sin(x[8]), 0, 84 | +sin(x[8]), +cos(x[8]), 0, 85 | 0, 0, 1; 86 | // Apply shearing: T=Rigid*Rs'*D*Rs; 87 | H=H*Rs.transpose()*D*Rs; 88 | } 89 | else 90 | H=H*D; 91 | // Projective Distortion 92 | H(2,0)=x[9]; 93 | H(2,1)=x[10]; 94 | // Return result 95 | return H; 96 | } 97 | 98 | }; 99 | 100 | } // namespace Geometry 101 | 102 | #endif // __model_homography2D 103 | -------------------------------------------------------------------------------- /code/LibProjectiveGeometry/Models/ModelSimilarity2D.hxx: -------------------------------------------------------------------------------- 1 | // Created by A. Aichert on Tue Aug 12th 2014 2 | #ifndef __model_similarity2D 3 | #define __model_similarity2D 4 | 5 | #include 6 | 7 | #include 8 | 9 | namespace Geometry { 10 | // Parametrization for a similarity transformation of 2-space 11 | struct ModelSimilarity2D : public LibOpterix::ParameterModel 12 | { 13 | /// Human readable names of all parameters. 14 | static const std::vector& ParameterNames() 15 | { 16 | static std::vector names; 17 | if (names.empty()) 18 | { 19 | names.resize(4); 20 | names[ 0]="Translation u"; 21 | names[ 1]="Translation v"; 22 | names[ 2]="2D Rotation"; 23 | names[ 3]="2D Scale"; 24 | } 25 | return names; 26 | } 27 | 28 | /// Frequent sets of active parameters 29 | static const LibOpterix::ParameterSets& ParameterSets() 30 | { 31 | static LibOpterix::ParameterSets sets; 32 | if (sets.empty()) 33 | { 34 | sets["2D Translation"].insert(0); 35 | sets["2D Translation"].insert(1); 36 | sets["2D Rigid"].insert(0); 37 | sets["2D Rigid"].insert(1); 38 | sets["2D Rigid"].insert(3); 39 | sets["2D Similarity"].insert(0); 40 | sets["2D Similarity"].insert(1); 41 | sets["2D Similarity"].insert(2); 42 | sets["2D Similarity"].insert(3); 43 | } 44 | return sets; 45 | } 46 | 47 | ModelSimilarity2D(std::set _active=std::set()) 48 | : LibOpterix::ParameterModel(ParameterNames(),_active) 49 | {} 50 | 51 | // Compose a 2D homography from parametrization 52 | virtual Geometry::RP2Homography getInstance() const 53 | { 54 | using namespace Eigen; 55 | const std::vector& x(current_values); 56 | 57 | Matrix3d H=Matrix3d::Identity(); 58 | // Rotation 59 | if (x[2]!=0) 60 | { 61 | H << +cos(x[2]), -sin(x[2]), 0, 62 | +sin(x[2]), +cos(x[2]), 0, 63 | 0, 0, 1; 64 | } 65 | // Translation 66 | H(0,2)=+x[0]; 67 | H(1,2)=+x[1]; 68 | // Apply scaling 69 | if (x[3]!=0) H.block<2,2>(0,0)*=(1.0+x[3]); 70 | // Return result 71 | return H; 72 | } 73 | 74 | }; 75 | 76 | } // namespace Geometry 77 | 78 | #endif // __model_similarity2D 79 | -------------------------------------------------------------------------------- /code/LibProjectiveGeometry/Models/ModelSimilarity3D.hxx: -------------------------------------------------------------------------------- 1 | // Created by A. Aichert on Tue Aug 12th 2014 2 | #ifndef __model_similarity3D 3 | #define __model_similarity3D 4 | 5 | #include 6 | 7 | #include 8 | 9 | #include 10 | 11 | namespace Geometry { 12 | // Parametrization for a similarity transformation of 3-space 13 | struct ModelSimilarity3D : public LibOpterix::ParameterModel 14 | { 15 | /// Human readable names of all parameters. 16 | static const std::vector& ParameterNames() 17 | { 18 | static std::vector names; 19 | if (names.empty()) 20 | { 21 | names.resize(7); 22 | names[ 0]="Translation X"; 23 | names[ 1]="Translation Y"; 24 | names[ 2]="Translation Z"; 25 | names[ 3]="Rotation X"; 26 | names[ 4]="Rotation Y"; 27 | names[ 5]="Rotation Z"; 28 | names[ 6]="3D Scale"; 29 | } 30 | return names; 31 | } 32 | 33 | /// Frequent sets of active parameters 34 | static const LibOpterix::ParameterSets& ParameterSets() 35 | { 36 | static LibOpterix::ParameterSets sets; 37 | if (sets.empty()) 38 | { 39 | sets["3D Translation"].insert(0); 40 | sets["3D Translation"].insert(1); 41 | sets["3D Translation"].insert(2); 42 | sets["3D Rigid"].insert(0); 43 | sets["3D Rigid"].insert(1); 44 | sets["3D Rigid"].insert(2); 45 | sets["3D Rigid"].insert(3); 46 | sets["3D Rigid"].insert(4); 47 | sets["3D Rigid"].insert(5); 48 | sets["3D Similarity"].insert(0); 49 | sets["3D Similarity"].insert(1); 50 | sets["3D Similarity"].insert(2); 51 | sets["3D Similarity"].insert(3); 52 | sets["3D Similarity"].insert(4); 53 | sets["3D Similarity"].insert(5); 54 | sets["3D Similarity"].insert(6); 55 | } 56 | return sets; 57 | } 58 | 59 | ModelSimilarity3D(std::set _active=std::set()) 60 | : LibOpterix::ParameterModel(ParameterNames(),_active) 61 | {} 62 | 63 | // Compose a 3D homography from parametrization 64 | virtual Geometry::RP3Homography getInstance() const 65 | { 66 | using namespace Eigen; 67 | // Slicker naming of the parameter vector. 68 | const std::vector& x(current_values); 69 | // We begin with an identity 70 | Matrix4d T=Matrix4d::Identity(); 71 | // Rotation about X Y and Z 72 | if (x[3]!=0||x[4]!=0||x[5]!=0) 73 | { 74 | auto R=( AngleAxisd(x[3], Vector3d::UnitX()) 75 | *AngleAxisd(x[4], Vector3d::UnitY()) 76 | *AngleAxisd(x[5], Vector3d::UnitZ())); 77 | T.block<3,3>(0,0)=(Matrix3d)R; 78 | } 79 | // Center of rotation and translation 80 | T(0,3)=x[0]; 81 | T(1,3)=x[1]; 82 | T(2,3)=x[2]; 83 | // Apply scaling 84 | if (x[6]!=0) T.block<3,3>(0,0)*=(1.0+x[6]); 85 | // Return result 86 | return T; 87 | } 88 | 89 | }; 90 | 91 | } // namespace Geometry 92 | 93 | #endif // __model_similarity3D 94 | -------------------------------------------------------------------------------- /code/LibProjectiveGeometry/ProjectionMatrix.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aaichert/EpipolarConsistency/8feb718e6b35a943d30684a40e52feb024df91fc/code/LibProjectiveGeometry/ProjectionMatrix.cpp -------------------------------------------------------------------------------- /code/LibProjectiveGeometry/ProjectionMatrix.h: -------------------------------------------------------------------------------- 1 | #ifndef __projection_matrix 2 | #define __projection_matrix 3 | // Created by A. Aichert on Mon Nov 18th 2013 4 | // Useful linear algebra for the pinhole camera model and epipolar geometry. 5 | 6 | #include "ProjectiveGeometry.hxx" 7 | 8 | namespace Geometry 9 | { 10 | typedef Eigen::Matrix ProjectionMatrixInverse; 11 | typedef Eigen::Matrix FundamentalMatrix; 12 | 13 | /// Normalize a camera matrix P=[M|p4] by -sign(det(M))/||m3|| such that (du,dv,d)'=P(X,Y,Z,1)' encodes the depth d 14 | void normalizeProjectionMatrix(ProjectionMatrix& P); 15 | 16 | /// Backprojection 17 | ProjectionMatrixInverse pseudoInverse(const ProjectionMatrix&); 18 | 19 | /// Decompose Projection Matrix into K[R|t] using RQ-decomposition. Returns false if R is left-handed (For RHS world coordinate systems, this implies imageVPointsUp is wrong). 20 | bool projectionMatrixDecomposition(const ProjectionMatrix& P, Eigen::Matrix3d& K, Eigen::Matrix3d& R, Eigen::Vector3d& t, bool imageVPointsUp=true); 21 | /// Decompose projection matrix and return intrinsic parameters in upper triangular 3x3 matrix 22 | Eigen::Matrix3d getCameraIntrinsics(const ProjectionMatrix& P); 23 | 24 | /// Extract the world coordinates of the camera center from a projection matrix. 25 | RP3Point getCameraCenter(const ProjectionMatrix& P); 26 | 27 | /// Compute the principal point via M*m3. 28 | RP2Point getCameraPrincipalPoint(const ProjectionMatrix& P); 29 | 30 | /// Direction of principal ray from a projection matrix. (Normal to principal plane, which is last row of P) 31 | Eigen::Vector3d getCameraDirection(const ProjectionMatrix& P); 32 | 33 | /// Compute the two three-points where the image u- and v-axes meet infinity. 34 | std::pair getCameraAxisDirections(const ProjectionMatrix& P); 35 | 36 | /// Compute the focal length in pixels (diagonal entries of K in P=K[R t] ). Assumes normalized projection matrix. 37 | std::pair getCameraFocalLengthPx(const ProjectionMatrix& P); 38 | 39 | /// Decomposes the projection matrix to compute the equation of the image plane. For left-handed coordinate systems, pixel_spacing can be negated. 40 | RP3Plane getCameraImagePlane(const ProjectionMatrix& P, double pixel_spacing); 41 | 42 | /// Intrinsic parameters of a pinhole camera as a 3x3 matrix 43 | inline Eigen::Matrix3d makeCalibrationMatrix(double ax, double ay, double u0, double v0, double skew=0.0) 44 | { 45 | Eigen::Matrix3d K=Eigen::Matrix3d::Identity(); 46 | K(0,0)=ax; 47 | K(1,1)=ay; 48 | K(0,2)=u0; 49 | K(1,2)=v0; 50 | K(0,1)=skew; 51 | return K; 52 | } 53 | 54 | /// Compose a projection matrix from rotation matrix, translation vector and intrinsic parameters 55 | ProjectionMatrix makeProjectionMatrix( 56 | const Eigen::Matrix3d& K, 57 | const Eigen::Matrix3d& R=Eigen::Matrix3d::Identity(), 58 | const Eigen::Vector3d& t=Eigen::Vector3d(0,0,0) 59 | ); 60 | 61 | /// Compute fundamental matrix from two projection matrices. Pseudoinverse-based implementation 62 | FundamentalMatrix computeFundamentalMatrix(const ProjectionMatrix& P0, const ProjectionMatrix& P1); 63 | 64 | } // namespace Geometry 65 | 66 | #endif // __projection_matrix 67 | -------------------------------------------------------------------------------- /code/LibProjectiveGeometry/ProjectiveGeometry.hxx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aaichert/EpipolarConsistency/8feb718e6b35a943d30684a40e52feb024df91fc/code/LibProjectiveGeometry/ProjectiveGeometry.hxx -------------------------------------------------------------------------------- /code/LibProjectiveGeometry/SingularValueDecomposition.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | 4 | using namespace Eigen; 5 | 6 | namespace Geometry 7 | { 8 | 9 | /// Compute the pseudo-inverse of a matrix 10 | Eigen::MatrixXd pseudoInverse(const Eigen::MatrixXd& A) 11 | { 12 | JacobiSVD svd(A, ComputeFullU | ComputeFullV); 13 | double tolerance=1e-6; 14 | int u=(int)A.rows(), v=(int)A.cols(), n=std::min(u,v); 15 | MatrixXd sigma(v,u); 16 | sigma.setZero(); 17 | sigma.topLeftCorner(n,n)=svd.singularValues().asDiagonal(); 18 | for (int i=0;i& P, Eigen::Matrix& Pinv, Eigen::Vector4d& C) 27 | { 28 | JacobiSVD svd(P, ComputeFullU | ComputeFullV); 29 | double tolerance=1e-6; 30 | int u=(int)P.rows(), v=(int)P.cols(), n=std::min(u,v); 31 | MatrixXd sigma(v,u); 32 | sigma.setZero(); 33 | sigma.topLeftCorner(n,n)=svd.singularValues().asDiagonal(); 34 | for (int i=0;i svd(A, Eigen::ComputeFullU | Eigen::ComputeFullV); 46 | auto V=svd.matrixV(); 47 | return V.col(V.cols()-1); 48 | } 49 | 50 | // Enforce rank deficiency 51 | Eigen::MatrixXd makeRankDeficient(const Eigen::MatrixXd& A) 52 | { 53 | JacobiSVD svd(A, Eigen::ComputeFullU | Eigen::ComputeFullV); 54 | VectorXd sigma=svd.singularValues(); 55 | sigma[sigma.size()-1]=0; 56 | return svd.matrixU()*sigma.asDiagonal()*svd.matrixV().transpose(); 57 | } 58 | 59 | // Compute left null-space of A 60 | Eigen::VectorXd nullspace_left(const Eigen::MatrixXd& A) 61 | { 62 | return nullspace(A.transpose()); 63 | } 64 | 65 | } // namespace Geometry 66 | -------------------------------------------------------------------------------- /code/LibProjectiveGeometry/SingularValueDecomposition.h: -------------------------------------------------------------------------------- 1 | #ifndef __singular_value_decomposition_h 2 | #define __singular_value_decomposition_h 3 | // Created by A. Aichert on Mon Nov 18th 2013 4 | // Eigen's SVD is compiled seperately to reduce overall compilation time. 5 | 6 | #include 7 | 8 | namespace Geometry 9 | { 10 | /// Compute the pseudo-inverse of a matrix 11 | Eigen::MatrixXd pseudoInverse(const Eigen::MatrixXd& A); 12 | 13 | /// Compute the pseudo-inverse and null-space of a matrix 14 | void pseudoInverseAndNullspace(const Eigen::Matrix& P, Eigen::Matrix& Pinv, Eigen::Vector4d& C); 15 | 16 | /// Compute right null-space of A 17 | Eigen::VectorXd nullspace(const Eigen::MatrixXd& A); 18 | 19 | // Enforce rank deficiency 20 | Eigen::MatrixXd makeRankDeficient(const Eigen::MatrixXd& A); 21 | 22 | // Compute left null-space of A 23 | Eigen::VectorXd nullspace_left(const Eigen::MatrixXd& A); 24 | 25 | } // namespace Geometry 26 | 27 | #endif // __singular_value_decomposition_h 28 | -------------------------------------------------------------------------------- /code/LibProjectiveGeometry/SourceDetectorGeometry.h: -------------------------------------------------------------------------------- 1 | #ifndef __source_detector_geometry_h 2 | #define __source_detector_geometry_h 3 | // Created by A. Aichert on Mon Jan 15th 2018 4 | // A useful class to relate 3D X-ray detector coordinates with pixels of a projection image. 5 | 6 | #include "ProjectionMatrix.h" 7 | 8 | namespace Geometry 9 | { 10 | /// A class to support computations in world units directly on the physical detector. 11 | struct SourceDetectorGeometry { 12 | // Vectors defining a projection matrix 13 | RP3Point C; //< Center of projection (i.e. source position) 14 | RP3Point O; //< Detector origin in three-space 15 | RP3Point U; //< Inifinte point in u-direction (scaled to pixel size) 16 | RP3Point V; //< Inifinte point in v-direction (scaled to pixel size) 17 | // Additional related objects for utility 18 | RP3Point principal_point_3d; //< Principal Point in three-space 19 | RP3Plane principal_plane; //< Principal plane 20 | RP3Plane image_plane; //< Image plane 21 | RP3Homography central_projection; //< Projection to image plane 22 | 23 | /// Figure out source-detector geometry by decomposing a projection matrix 24 | SourceDetectorGeometry(const ProjectionMatrix&P, double pixel_spacing); 25 | 26 | /// Source-detector given by physical measurements. u/v_axis_vector should be scaled to size of one pixel in millimeters. 27 | SourceDetectorGeometry( 28 | const RP3Point& center_of_projection, const RP3Point& detector_origin, 29 | const Eigen::Vector3d& u_axis_vector, const Eigen::Vector3d& v_axis_vector); 30 | 31 | // Get the 3D coordinates of the pixel (u,v) in world units 32 | RP3Point point_on_detector(double u, double v) const; 33 | // Get the 3D coordinates of the image point x in world units 34 | RP3Point point_on_detector(const RP2Point& x) const; 35 | // Get the 3D coordinates of the image point x in world units 36 | RP3Point project_to_detector(const RP3Point& X) const; 37 | 38 | // Project 3D point to image pixel 39 | RP2Point project(RP3Point X) const; 40 | // Compute a projection matrix which relates 3D points to image pixels. See also: project(...) 41 | ProjectionMatrix projectionMatrix() const; 42 | 43 | }; 44 | 45 | } // namespace Geometry 46 | 47 | #endif // __source_detector_geometry_h 48 | -------------------------------------------------------------------------------- /code/LibRayCastBackproject/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | cuda_add_library(LibRayCastBackproject 3 | VolumeRendering.h 4 | VolumeRendering.cpp 5 | VoxelData.h 6 | VoxelData.cpp 7 | VoxelData.cu 8 | Reconstruction.h 9 | Reconstruction.cpp 10 | Reconstruction.cu 11 | ray_box_intersection.hxx 12 | vr_ray_geom_setup.cu 13 | vr_raycast_drr.cu 14 | vr_raycast_ea_1Dtf.cu 15 | vr_raycast_iso.cu 16 | vr_raycast_mip.cu 17 | vr_raycast_debug.cu 18 | # 2do only if GetSet is available. 19 | VolumeRenderingGui.h 20 | VolumeRenderingGui.cpp 21 | ) 22 | 23 | # DEBUG ONLY LibUtilsQt 24 | target_link_libraries(LibRayCastBackproject LibProjectiveGeometry LibUtilsCuda LibUtilsQt GetSet) 25 | qt5_use_modules(LibRayCastBackproject Core Gui Widgets) 26 | set_property(TARGET LibRayCastBackproject PROPERTY FOLDER "Packages") 27 | 28 | install(FILES VolumeRendering.h DESTINATION include/LibRayCastBackproject) 29 | install(TARGETS LibRayCastBackproject DESTINATION lib EXPORT LibRayCastBackproject-targets) 30 | install(EXPORT LibRayCastBackproject-targets DESTINATION cmake) 31 | 32 | -------------------------------------------------------------------------------- /code/LibRayCastBackproject/Reconstruction.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aaichert/EpipolarConsistency/8feb718e6b35a943d30684a40e52feb024df91fc/code/LibRayCastBackproject/Reconstruction.cpp -------------------------------------------------------------------------------- /code/LibRayCastBackproject/Reconstruction.cu: -------------------------------------------------------------------------------- 1 | 2 | // Created by A. Aichert on Thu Aug 30th 2018 3 | #include 4 | 5 | #include 6 | 7 | #include 8 | #include 9 | 10 | #include 11 | 12 | 13 | __global__ void kernel_backprojection( 14 | unsigned short n_x, unsigned short n_y, unsigned short n_z, float *voxel, 15 | culaut::Array projection_matrix_vx_px, cudaTextureObject_t image) 16 | { 17 | // Find index of current thread 18 | int idx_x = blockIdx.x * blockDim.x + threadIdx.x; 19 | int idx_y = blockIdx.y * blockDim.y + threadIdx.y; 20 | int idx_z = blockIdx.z * blockDim.z + threadIdx.z; 21 | if (idx_x>=n_x) return; 22 | if (idx_y>=n_y) return; 23 | if (idx_z>=n_z) return; 24 | int idx=idx_z*n_y*n_x+idx_y*n_x+idx_x; 25 | 26 | // Homogeneous point in voxels 27 | float X[] = {(float)idx_x, (float)idx_y, (float)idx_z, 1.0f}; 28 | 29 | // Projection to image 30 | float x[3]; 31 | culaut::xgemm(projection_matrix_vx_px.v,X,x); 32 | culaut::xvdehomogenize(x); 33 | 34 | // Sample the image 35 | float &u=x[0]; 36 | float &v=x[1]; 37 | float intensity=tex2D(image,u,v); 38 | 39 | // Backproject in to current voxel 40 | voxel[idx]+=intensity; 41 | 42 | } 43 | 44 | 45 | void backprojection(int n_x, int n_y, int n_z, float *voxel_d, culaut::Array projection_matrix_vx_px, cudaTextureObject_t image ) 46 | { 47 | dim3 block_size; 48 | block_size.x=8; 49 | block_size.y=8; 50 | block_size.z=8; 51 | dim3 grid_size; 52 | grid_size.x = iDivUp(n_x,block_size.x); 53 | grid_size.y = iDivUp(n_y,block_size.y); 54 | grid_size.z = iDivUp(n_z,block_size.z); 55 | 56 | kernel_backprojection<<>>( n_x, n_y, n_z, voxel_d, projection_matrix_vx_px, image); 57 | cudaDeviceSynchronize(); 58 | cudaCheckState 59 | 60 | } 61 | -------------------------------------------------------------------------------- /code/LibRayCastBackproject/Reconstruction.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aaichert/EpipolarConsistency/8feb718e6b35a943d30684a40e52feb024df91fc/code/LibRayCastBackproject/Reconstruction.h -------------------------------------------------------------------------------- /code/LibRayCastBackproject/VolumeRendering.cu: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aaichert/EpipolarConsistency/8feb718e6b35a943d30684a40e52feb024df91fc/code/LibRayCastBackproject/VolumeRendering.cu -------------------------------------------------------------------------------- /code/LibRayCastBackproject/VolumeRenderingGui.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aaichert/EpipolarConsistency/8feb718e6b35a943d30684a40e52feb024df91fc/code/LibRayCastBackproject/VolumeRenderingGui.cpp -------------------------------------------------------------------------------- /code/LibRayCastBackproject/VolumeRenderingGui.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aaichert/EpipolarConsistency/8feb718e6b35a943d30684a40e52feb024df91fc/code/LibRayCastBackproject/VolumeRenderingGui.h -------------------------------------------------------------------------------- /code/LibRayCastBackproject/ray_box_intersection.hxx: -------------------------------------------------------------------------------- 1 | // Created by A. Aichert on Tue Oct 4th 2016 2 | // Contains types and functions to test for intersection of ray and axis aligned bounding box 3 | 4 | #ifndef __ray_box_intersection_hxx 5 | #define __ray_box_intersection_hxx 6 | 7 | #ifndef __device__ 8 | #define __device__ 9 | #define udef__device__ 10 | #endif 11 | #ifndef __host__ 12 | #define __host__ 13 | #define udef__host__ 14 | #endif 15 | 16 | #include "vr_cuda.hxx" 17 | 18 | namespace RayBoxIntersection 19 | { 20 | 21 | template 22 | struct Ray { 23 | T origin[3]; 24 | T direction[3]; 25 | }; 26 | 27 | template 28 | struct Intersections { 29 | T x_min[3]; 30 | T x_max[3]; 31 | }; 32 | 33 | /// Test for intersection of ray with axis aligned box. Intersections are returned as optional out_min/max. 34 | template __device__ __host__ inline 35 | bool ray_box_intersection(const Ray& ray, const AxisAlignedBox& box, Intersections& out) 36 | { 37 | return ray_box_intersection(ray.origin, ray.direction, box.aabb_min, box.aabb_max, out.x_min, out.x_max); 38 | } 39 | 40 | /// Test for intersection of ray (origin, direction) with axis aligned box (aabb_min,aabb_max). Intersections are returned as optional out_min/max. 41 | template __device__ __host__ inline 42 | bool ray_box_intersection(T origin[3], T direction[3], T aabb_min[3], T aabb_max[3], T out_min[3]=0x0, T out_max[3]=0x0) 43 | { 44 | // multipliers for direction min and max ("close" and "far" if positive) 45 | T t_min[3]; 46 | T t_max[3]; 47 | 48 | // figure out intersections for the x-, y- and z-planes 49 | { 50 | T invdir; 51 | invdir=1.0f/direction[0]; 52 | t_min[0] = ((invdir>0?aabb_min[0]:aabb_max[0]) - origin[0]) * invdir; 53 | t_max[0] = ((invdir<0?aabb_min[0]:aabb_max[0]) - origin[0]) * invdir; 54 | invdir=1.0f/direction[1]; 55 | t_min[1] = ((invdir>0?aabb_min[1]:aabb_max[1]) - origin[1]) * invdir; 56 | t_max[1] = ((invdir<0?aabb_min[1]:aabb_max[1]) - origin[1]) * invdir; 57 | invdir=1.0f/direction[2]; 58 | t_min[2] = ((invdir>0?aabb_min[2]:aabb_max[2]) - origin[2]) * invdir; 59 | t_max[2] = ((invdir<0?aabb_min[2]:aabb_max[2]) - origin[2]) * invdir; 60 | } 61 | 62 | // Check for contradictions (ray intersections do not touch box) 63 | if ((t_min[0] > t_max[1]) || (t_min[1] > t_max[0])) return false; 64 | // Keep track of tightest fit. 65 | if (t_min[1] > t_min[0]) t_min[0] = t_min[1]; 66 | if (t_max[1] < t_max[0]) t_max[0] = t_max[1]; 67 | 68 | // Again check for contradictions 69 | if ((t_min[0] > t_max[2]) || (t_min[2] > t_max[0])) return false; 70 | // Again keep track of tightest fit. 71 | if (t_min[2] > t_min[0]) t_min[0] = t_min[2]; 72 | if (t_max[2] < t_max[0]) t_max[0] = t_max[2]; 73 | 74 | // Optional: intersection output 75 | if (out_min) 76 | { 77 | out_min[0]=origin[0]+direction[0]*t_min[0]; 78 | out_min[1]=origin[1]+direction[1]*t_min[0]; 79 | out_min[2]=origin[2]+direction[2]*t_min[0]; 80 | } 81 | if (out_max) 82 | { 83 | out_max[0]=origin[0]+direction[0]*t_max[0]; 84 | out_max[1]=origin[1]+direction[1]*t_max[0]; 85 | out_max[2]=origin[2]+direction[2]*t_max[0]; 86 | } 87 | 88 | return true; 89 | } 90 | 91 | } // namespace RayBoxIntersection 92 | 93 | #ifdef udef__device__ 94 | #undef __device__ 95 | #endif 96 | #ifdef udef__host__ 97 | #undef __host__ 98 | #endif 99 | 100 | #endif // __ray_box_intersection_hxx 101 | -------------------------------------------------------------------------------- /code/LibRayCastBackproject/vr_cuda.hxx: -------------------------------------------------------------------------------- 1 | #ifndef __vr_cuda_hxx 2 | #define __vr_cuda_hxx 3 | 4 | #ifndef __device__ 5 | #define __device__ 6 | #define udef__device__ 7 | #endif 8 | #ifndef __host__ 9 | #define __host__ 10 | #define udef__host__ 11 | #endif 12 | 13 | template 14 | struct AxisAlignedBox { 15 | T aabb_min[3]; 16 | T aabb_max[3]; 17 | }; 18 | 19 | //struct TransferFunctionRamp { 20 | // float in_min; 21 | // float in_max; 22 | // float out_max; 23 | // 24 | // __device__ __host__ inline 25 | // float operator()(float in) 26 | // { 27 | // if (in<=in_min) return 0; 28 | // if (in>=in_max) return out_max; 29 | // return out_max*(in-in_min)/(in_max-in_min); 30 | // } 31 | //}; 32 | 33 | #ifdef udef__device__ 34 | #undef __device__ 35 | #endif 36 | #ifdef udef__host__ 37 | #undef __host__ 38 | #endif 39 | 40 | #endif // __vr_cuda_hxx 41 | -------------------------------------------------------------------------------- /code/LibRayCastBackproject/vr_ray_geom_setup.cu: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aaichert/EpipolarConsistency/8feb718e6b35a943d30684a40e52feb024df91fc/code/LibRayCastBackproject/vr_ray_geom_setup.cu -------------------------------------------------------------------------------- /code/LibRayCastBackproject/vr_raycast_ea_1Dtf.cu: -------------------------------------------------------------------------------- 1 | // Created by A. Aichert on Tue Oct 4th 2016 2 | #include 3 | 4 | #include 5 | 6 | #include 7 | #include 8 | 9 | #include 10 | 11 | #include "vr_cuda.hxx" 12 | 13 | template 14 | __global__ void kernel_raycast( 15 | unsigned short n_u, unsigned short n_v, 16 | float * pixel_data, //< image data (RGBA) 17 | float * model_C_Pinv_h, //< volume model transform (voxels to world) 18 | cudaTextureObject_t voxel_data, //< volume data 19 | float * ray_entry, //< ray entry 20 | float * ray_exit, //< ray exit 21 | float * noise, //< noise for ray offsets 22 | float samples_per_voxel, //< samples per voxel 23 | cudaTextureObject_t tf //< transfer function 24 | ) 25 | { 26 | // Find index of current thread 27 | int idx_x = blockIdx.x * blockDim.x + threadIdx.x; 28 | int idx_y = blockIdx.y * blockDim.y + threadIdx.y; 29 | if (idx_x>=n_u) return; 30 | if (idx_y>=n_v) return; 31 | int idx=idx_y*n_u+idx_x; 32 | 33 | // Access correct pixel 34 | float *entry=ray_entry+4*idx; 35 | float *exit =ray_exit+4*idx; 36 | float *pixel=pixel_data+n_c*idx; 37 | 38 | float ray_length=culaut::xvdistance2(entry,exit); 39 | if (ray_length<=0) 40 | { 41 | culaut::xvset(pixel,0.0f); 42 | return; 43 | } 44 | 45 | float step_in_mm=1; 46 | float4 intensity=make_float4(0,0,0,0); 47 | float step=1.0/ray_length; 48 | step/=samples_per_voxel; 49 | float voxel[3]; 50 | for (float a=noise[idx]*step;a<1.0;a+=step) 51 | { 52 | culaut::xvlincomb(voxel,entry,1.0-a,exit,a); 53 | float sample=tex3D(voxel_data,voxel[0],voxel[1],voxel[2]); 54 | float4 color=tex1D(tf,sample); 55 | color.w/=step_in_mm; 56 | color.x*=color.w; 57 | color.y*=color.w; 58 | color.z*=color.w; 59 | intensity.x+=color.x*(1.0-intensity.w); 60 | intensity.y+=color.y*(1.0-intensity.w); 61 | intensity.z+=color.z*(1.0-intensity.w); 62 | intensity.w+=color.w*(1.0-intensity.w); 63 | if (intensity.w>=1.0) 64 | break; 65 | } 66 | if (n_c>=4) 67 | culaut::xvcpy(pixel,(float*)&intensity); 68 | else if (n_c>=3) 69 | culaut::xvcpy(pixel,(float*)&intensity); 70 | else 71 | culaut::xvset(pixel,culaut::xvnorm2(&intensity.x)); 72 | } 73 | 74 | 75 | void raycast_ea_1Dtf( 76 | int n_u, int n_v, int n_c, //< image size and number of channels 77 | float * pixel_data_d, //< image data (RGBA) 78 | float * model_C_Pinv_d, //< volume model transform (voxels to world) 79 | cudaTextureObject_t voxel_data, //< volume data 80 | float* ray_entry_d, //< ray entry 81 | float* ray_exit_d, //< ray exit 82 | float * noise_d, //< noise for ray offsets 83 | float samples_per_voxel, //< samples per voxel 84 | cudaTextureObject_t tf //< transfer function 85 | ) 86 | { 87 | dim3 block_size; 88 | block_size.x=16; 89 | block_size.y=16; 90 | dim3 grid_size; 91 | grid_size.x = iDivUp(n_u,block_size.x); 92 | grid_size.y = iDivUp(n_v,block_size.y); 93 | 94 | if (n_c==1) 95 | kernel_raycast<1><<>>(n_u, n_v, pixel_data_d, model_C_Pinv_d, voxel_data, ray_entry_d, ray_exit_d, noise_d, samples_per_voxel, tf); 96 | else if (n_c==3) 97 | kernel_raycast<3><<>>(n_u, n_v, pixel_data_d, model_C_Pinv_d, voxel_data, ray_entry_d, ray_exit_d, noise_d, samples_per_voxel, tf); 98 | else if (n_c==4) 99 | kernel_raycast<4><<>>(n_u, n_v, pixel_data_d, model_C_Pinv_d, voxel_data, ray_entry_d, ray_exit_d, noise_d, samples_per_voxel, tf); 100 | else std::cerr << __FILE__ << " : " << __LINE__ << " : invalid number of channels!" << std::endl; 101 | 102 | cudaDeviceSynchronize(); 103 | cudaCheckState 104 | } -------------------------------------------------------------------------------- /code/LibRayCastBackproject/vr_raycast_mip.cu: -------------------------------------------------------------------------------- 1 | // Created by A. Aichert on Tue Oct 4th 2016 2 | #include 3 | 4 | #include 5 | 6 | #include 7 | #include 8 | 9 | #include 10 | 11 | template 12 | __global__ void kernel_raycast( 13 | unsigned short n_u, unsigned short n_v, 14 | float * pixel_data, //< image data (RGBA) 15 | float * model_C_Pinv_h, //< volume model transform (voxels to world) 16 | cudaTextureObject_t voxel_data, //< volume data 17 | float* ray_entry, //< ray entry 18 | float* ray_exit, //< ray exit 19 | float * noise, //< noise for ray offsets 20 | float samples_per_voxel //< samples per voxel 21 | ) 22 | { 23 | // Find index of current thread 24 | int idx_x = blockIdx.x * blockDim.x + threadIdx.x; 25 | int idx_y = blockIdx.y * blockDim.y + threadIdx.y; 26 | if (idx_x>=n_u) return; 27 | if (idx_y>=n_v) return; 28 | int idx=idx_y*n_u+idx_x; 29 | 30 | // Access correct pixel 31 | float *entry=ray_entry+4*idx; 32 | float *exit =ray_exit+4*idx; 33 | float *pixel=pixel_data+n_c*idx; 34 | 35 | float ray_length=culaut::xvdistance2(entry,exit); 36 | if (ray_length<=0) 37 | { 38 | culaut::xvset(pixel,0); 39 | return; 40 | } 41 | 42 | float intensity=0; 43 | float step=1.0/ray_length; 44 | step/=samples_per_voxel; 45 | float voxel[3]; 46 | for (float a=-noise[idx]*step;a<1.0;a+=step) 47 | { 48 | culaut::xvlincomb(voxel,entry,1.0-a,exit,a); 49 | float sample=tex3D(voxel_data,voxel[0],voxel[1],voxel[2]); 50 | if (intensity(pixel,intensity); 54 | 55 | } 56 | 57 | 58 | void raycast_mip( 59 | int n_u, int n_v, int n_c, //< image size and number of channels 60 | float * pixel_data_d, //< image data (RGBA) 61 | float * model_C_Pinv_d, //< volume model transform (voxels to world) 62 | cudaTextureObject_t voxel_data, //< volume data 63 | float * ray_entry_d, //< ray entry 64 | float * ray_exit_d, //< ray exit 65 | float * noise_d, //< noise for ray offsets 66 | float samples_per_voxel //< samples per voxel 67 | ) 68 | { 69 | dim3 block_size; 70 | block_size.x=16; 71 | block_size.y=16; 72 | dim3 grid_size; 73 | grid_size.x = iDivUp(n_u,block_size.x); 74 | grid_size.y = iDivUp(n_v,block_size.y); 75 | 76 | if (n_c==1) 77 | kernel_raycast<1><<>>(n_u, n_v, pixel_data_d, model_C_Pinv_d, voxel_data, ray_entry_d, ray_exit_d, noise_d, samples_per_voxel); 78 | else if (n_c==3) 79 | kernel_raycast<3><<>>(n_u, n_v, pixel_data_d, model_C_Pinv_d, voxel_data, ray_entry_d, ray_exit_d, noise_d, samples_per_voxel); 80 | else if (n_c==4) 81 | kernel_raycast<4><<>>(n_u, n_v, pixel_data_d, model_C_Pinv_d, voxel_data, ray_entry_d, ray_exit_d, noise_d, samples_per_voxel); 82 | else std::cerr << __FILE__ << " : " << __LINE__ << " : invalid number of channels!" << std::endl; 83 | 84 | cudaDeviceSynchronize(); 85 | cudaCheckState 86 | } -------------------------------------------------------------------------------- /code/LibSimple/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | add_library(GLAD 3 | GL/glad.c 4 | ) 5 | target_compile_definitions(GLAD PUBLIC GLAD_GLAPI_EXPORT PRIVATE GLAD_GLAPI_EXPORT_BUILD) 6 | 7 | add_library(LibSimple 8 | BufferUtils.h 9 | SimpleOptimizer.h 10 | SimpleOptimizer.cpp 11 | SimpleMHD.h 12 | SimpleMHD.cpp 13 | SimpleGL.h 14 | SimpleGL.cpp 15 | SimpleQTGL.h 16 | SimpleQTGL.cpp 17 | SimpleVR.h 18 | SimpleVR.cpp 19 | SimpleRayCastPass.h 20 | SimpleRayCastPass.cpp 21 | ) 22 | target_link_libraries(LibSimple GLAD) 23 | qt5_use_modules(LibSimple Widgets OpenGL) -------------------------------------------------------------------------------- /code/LibSimple/SimpleEmptySpaceSkipping.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aaichert/EpipolarConsistency/8feb718e6b35a943d30684a40e52feb024df91fc/code/LibSimple/SimpleEmptySpaceSkipping.cpp -------------------------------------------------------------------------------- /code/LibSimple/SimpleOptimizer.h: -------------------------------------------------------------------------------- 1 | #ifndef SIMPLE_OPTIMIZER_PB 2 | #define SIMPLE_OPTIMIZER_PB 3 | 4 | /** @brief Powell-Brent Optimizer based on Numerical Recepies 5 | * @author Andre Aichert 6 | */ 7 | 8 | 9 | #include 10 | 11 | // Simple Optimization of a function R^n->R 12 | namespace Simple 13 | { 14 | 15 | class Optimizer 16 | { 17 | public: 18 | 19 | Optimizer(double step=1, double ftol=0.01, double * _weigths=0x0) // 2do add max its 20 | :m_step(step), m_ftol(ftol), weigths(_weigths) 21 | {} 22 | 23 | double m_step; // scaling of initial search directions 24 | double m_ftol; // Tolerance in objective function value 25 | 26 | int minimize(std::vector& x, double (*objFun)(double*) ) 27 | { 28 | if (x.empty()) return -1; 29 | std::vector delta(x.size()); 30 | if (weigths) 31 | for (int i=0;i<(int)delta.size(); i++) 32 | delta[i]=m_step*weigths[i]; 33 | else 34 | for (int i=0;i<(int)delta.size(); i++) 35 | delta[i]=m_step; 36 | int iterNr=20; 37 | double fret; 38 | return powell(&(x[0]), &(delta[0]), (int)x.size(), m_ftol, &iterNr, &fret, objFun); 39 | } 40 | 41 | private: 42 | static int powell( 43 | double *p, // solution 44 | double *delta, // step (for example vector of all ones) 45 | int parNr, // problem size 46 | double ftol, // output tolerance 47 | int *iterNr, // output iterations 48 | double *fret, // returned function value 49 | double (*_fun)(double*) ); 50 | double * weigths; 51 | }; 52 | 53 | } // namespace Simple 54 | 55 | #endif // SIMPLE_OPTIMIZER_PB 56 | -------------------------------------------------------------------------------- /code/LibSimple/SimpleQTGL.h: -------------------------------------------------------------------------------- 1 | #ifndef SIMPLE_QT_GL 2 | #define SIMPLE_QT_GL 3 | 4 | #include "GL/glad.h" 5 | 6 | #include 7 | 8 | #include 9 | 10 | #include 11 | 12 | #include 13 | #include 14 | #include 15 | 16 | #include 17 | 18 | #include 19 | 20 | class SimpleQTGL: public QGLWidget 21 | { 22 | Q_OBJECT 23 | 24 | public slots: 25 | void lazyUpdate(); 26 | 27 | public: 28 | // Creates its own independent context 29 | SimpleQTGL(); 30 | 31 | // Shares context of parent 32 | SimpleQTGL(QGLWidget *mainWnd); 33 | 34 | virtual ~SimpleQTGL(); 35 | 36 | bool redisplay; 37 | QTimer m_timer; 38 | QElapsedTimer m_frameTime; 39 | // Mouse state 40 | int m_mouseDown; 41 | int m_mouseX; 42 | int m_mouseY; 43 | 44 | 45 | protected: 46 | QGLWidget *contextOwner; 47 | 48 | // Quit on close IF we are contextOwner 49 | void closeEvent(QCloseEvent *event); 50 | 51 | virtual void mousePressEvent(QMouseEvent *event); 52 | virtual void mouseReleaseEvent(QMouseEvent *event); 53 | virtual void mouseMoveEvent(QMouseEvent *event); 54 | virtual void keyPressEvent(QKeyEvent *event); 55 | virtual void keyReleaseEvent(QKeyEvent *event); 56 | virtual void wheelEvent(QWheelEvent *event); 57 | 58 | virtual void initializeGL(); 59 | virtual void resizeGL( int width, int height ); 60 | virtual void paintGL(); 61 | 62 | 63 | protected: 64 | // function pointers 65 | void (*displayFunc)(void); 66 | void (*reshapeFunc)(int width, int height); 67 | void (*keyboardFunc)(unsigned char key, int x, int y); 68 | void (*keyboardUpFunc)(unsigned char key, int x, int y); 69 | void (*mouseFunc)(int button, int state, int x, int y); 70 | void (*motionFunc)(int dx, int dy); 71 | void (*wheelFunc)(int dx, int dy); 72 | void (*passiveMotionFunc)(int x, int y); 73 | 74 | void (*idleFunc)(void); 75 | 76 | void (*specialFunc)(int key, int x, int y); 77 | void (*specialUpFunc)(int key, int x, int y); 78 | 79 | public: 80 | void setDisplayFunc(void (*f)(void)); 81 | void setReshapeFunc(void (*f)(int width, int height)); 82 | 83 | void setKeyboardFunc(void (*f)(unsigned char key, int x, int y)); 84 | void setKeyboardUpFunc(void (*f)(unsigned char key, int x, int y)); 85 | 86 | void setSpecialFunc(void (*f)(int key, int x, int y)); 87 | void setSpecialUpFunc(void (*f)(int key, int x, int y)); 88 | 89 | void setMouseFunc(void (*f)(int button, int state, int x, int y)); 90 | void setMotionFunc(void (*f)(int dx, int dy)); 91 | void setWheelFunc(void (*f)(int dx, int dy)); 92 | void setPassiveMotionFunc(void (*f)(int x, int y)); 93 | 94 | /// Called when no redisplay is required 95 | void setIdleFunc(void (*f)(void)); 96 | 97 | /// Renders another frame after this one. Multiple calls are fine and do not lead to recursion. 98 | void postRedisplay(); 99 | 100 | /// Acquires context and immediately draws texture of id. 101 | void immediateShowTexture(int id); 102 | 103 | /// Acquires context and immediately calls displayFunc. 104 | void immediateUpdate(); 105 | 106 | }; 107 | #endif // SIMPLE_QT_GL -------------------------------------------------------------------------------- /code/LibUtilsCuda/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | if (CUDA_HAVE_GPU) 3 | # cuda_add_executable(TestUtilsCuda 4 | # TestUtilsCuda.cpp 5 | # TestUtilsCuda.cu 6 | # ) 7 | # target_link_libraries(TestUtilsCuda LibUtilsCuda LibProjectiveGeometry) 8 | 9 | cuda_add_library(LibUtilsCuda STATIC 10 | CudaTextureArray.hxx 11 | CudaBindlessTexture.h 12 | CudaBindlessTexture.cpp 13 | CudaBindlessTexture.cu 14 | CudaMemory.h 15 | CudaMemory.cpp 16 | CudaAlgorithms.h 17 | CudaAlgorithms.cpp 18 | CudaConvolution.cu 19 | OPTIONS -DHAS_CUDA="Cuda Support" 20 | ) 21 | install(FILES UtilsCuda.hxx CudaTextureArray.hxx CudaMemory.h CudaAlgorithms.h CudaBindlessTexture.h DESTINATION include/LibUtilsCuda) 22 | 23 | install(TARGETS LibUtilsCuda DESTINATION lib EXPORT LibUtilsCuda-targets) 24 | install(EXPORT LibUtilsCuda-targets DESTINATION cmake) 25 | endif(CUDA_HAVE_GPU) 26 | 27 | # Header only linear algebra functions work on both CPU and GPU (i.e. always install) 28 | install(FILES culaut/culaut.hxx culaut/xgeinv.hxx culaut/xprojectionmatrix.hxx DESTINATION include/LibUtilsCuda/culaut) 29 | set_property(TARGET LibUtilsCuda PROPERTY FOLDER "Packages") 30 | -------------------------------------------------------------------------------- /code/LibUtilsCuda/CudaAlgorithms.cpp: -------------------------------------------------------------------------------- 1 | #include "CudaAlgorithms.h" 2 | 3 | 4 | 5 | extern void _image2D1C_ConvolveRow(float* img, int n_x, int n_y, short k, float *kernel, float* out); 6 | 7 | 8 | extern void _image2D1C_ConvolveColumn(float* img, int n_x, int n_y, short k, float *kernel, float* out); 9 | 10 | 11 | extern void _image2D1C_ConvolveSperable(float* img, int n_x, int n_y, short kx, float *kernelx, short ky, float *kernely, float* tmp); 12 | 13 | 14 | extern void _image2D1C_Gaussian(float* img, int n_x, int n_y, short k, float sigma, float* tmp); 15 | 16 | 17 | namespace UtilsCuda 18 | { 19 | 20 | void image2D1C_ConvolveRow(float* img, int n_x, int n_y, short k, float *kernel, float* out) 21 | { 22 | _image2D1C_ConvolveRow( img, n_x, n_y, k, kernel, out); 23 | } 24 | 25 | void image2D1C_ConvolveColumn(float* img, int n_x, int n_y, short k, float *kernel, float* out) 26 | { 27 | _image2D1C_ConvolveColumn(img, n_x, n_y, k, kernel, out); 28 | } 29 | 30 | 31 | void image2D1C_ConvolveSperable(float* img, int n_x, int n_y, short kx, float *kernelx, short ky, float *kernely, float* tmp) 32 | { 33 | _image2D1C_ConvolveSperable( img, n_x, n_y, kx, kernelx, ky, kernely, tmp); 34 | } 35 | 36 | 37 | void image2D1C_Gaussian(float* img, int n_x, int n_y, short k, float sigma, float* tmp) 38 | { 39 | _image2D1C_Gaussian( img, n_x, n_y, k, sigma, tmp); 40 | } 41 | 42 | } // namespace UtilsCuda 43 | -------------------------------------------------------------------------------- /code/LibUtilsCuda/CudaAlgorithms.h: -------------------------------------------------------------------------------- 1 | #ifndef __cuda_algorithms_h 2 | #define __cuda_algorithms_h 3 | 4 | namespace UtilsCuda 5 | { 6 | 7 | // 1D convolution along rows of a single-channel 2D image. All pointer are in GPU memory. 8 | void image2D1C_ConvolveRow(float* img, int n_x, int n_y, short k, float *kernel, float* out); 9 | // 1D convolution along columns of a single-channel 2D image. All pointer are in GPU memory. 10 | void image2D1C_ConvolveColumn(float* img, int n_x, int n_y, short k, float *kernel, float* out); 11 | 12 | // 2D convolution of a single-channel 2D image with seperable kernel. All pointer are in GPU memory. 13 | void image2D1C_ConvolveSperable(float* img, int n_x, int n_y, short kx, float *kernelx, short ky, float *kernely, float* tmp); 14 | 15 | // Gaussian convolution of a single-channel 2D image. All pointer are in GPU memory. 16 | void image2D1C_Gaussian(float* img, int n_x, int n_y, short k, float sigma, float* tmp=0x0); 17 | 18 | } // namespace UtilsCuda 19 | 20 | #endif // __cuda_algorithms_h 21 | -------------------------------------------------------------------------------- /code/LibUtilsCuda/CudaBindlessTexture.h: -------------------------------------------------------------------------------- 1 | #ifndef __cuda_bindless_texture_h 2 | #define __cuda_bindless_texture_h 3 | 4 | #include "UtilsCuda.hxx" 5 | 6 | #include "CudaMemory.h" 7 | 8 | // TODO make size a protected member and provide getter. 9 | 10 | namespace UtilsCuda 11 | { 12 | /// Bindless CUDA 2D Texture of Type (e.g. float, float2 unit4 etc.) 13 | /// buffer_is_device : if true, then the buffer is assumed to be a device pointer already 14 | /// interpolate : bilinear interpolation if true 15 | /// normalizedAccess : Access as texture coordinates rather than array index 16 | /// Type : float float2 float4 unsigned char uchar2 uchar4 short unsigned short 17 | template 18 | class BindlessTexture2D 19 | { 20 | public: 21 | const bool normalizedCoords; 22 | int size[2]; 23 | cudaArray_t array; 24 | cudaTextureObject_t tex; 25 | 26 | BindlessTexture2D(int w, int h, const Type * buffer, bool buffer_is_device=false, bool interpolate=true, bool normalizedCoords=false); 27 | 28 | ~BindlessTexture2D(); 29 | 30 | void readback(MemoryBlock& buffer); 31 | 32 | inline operator cudaTextureObject_t () const {return tex;} 33 | }; 34 | 35 | /// Bindless CUDA 3D Texture of Type (e.g. float, float2 unit4 etc.) 36 | /// buffer_is_device : if true, then the buffer is assumed to be a device pointer already 37 | /// interpolate : bilinear interpolation if true 38 | /// normalizedAccess : Access as texture coordinates rather than array index 39 | /// Type : float float2 float4 unsigned char uchar2 uchar4 short unsigned short 40 | template 41 | class BindlessTexture3D 42 | { 43 | public: 44 | const bool normalizedCoords; 45 | int size[3]; 46 | cudaArray_t array; 47 | cudaTextureObject_t tex; 48 | 49 | BindlessTexture3D(int w, int h, int d, const Type * buffer, bool buffer_is_device=false, bool interpolate=true, bool normalizedCoords=false); 50 | 51 | ~BindlessTexture3D(); 52 | 53 | void readback(MemoryBlock& buffer); 54 | 55 | inline operator cudaTextureObject_t () const {return tex;} 56 | }; 57 | 58 | } // namespace UtilsCuda 59 | 60 | #endif // __cuda_bindless_texture_h 61 | -------------------------------------------------------------------------------- /code/LibUtilsCuda/CudaConvolution.cu: -------------------------------------------------------------------------------- 1 | #include "UtilsCuda.hxx" 2 | #include "CudaMemory.h" 3 | 4 | // 2do at least the kernel should be in shared mem 5 | 6 | #include 7 | 8 | // 1D convolution along rows of a single-channel 2D image 9 | __global__ void kernel_image2D1C_ConvolveRow(float* img, int n_x, int n_y, short k, float *kernel, float* out) 10 | { 11 | // Find index of current thread 12 | int idx_x = blockIdx.x * blockDim.x + threadIdx.x; 13 | int idx_y = blockIdx.y * blockDim.y + threadIdx.y; 14 | if (idx_x>=n_x) return; 15 | if (idx_y>=n_y) return; 16 | 17 | float sum=0; 18 | for (short i=-k;i<=k;i++) 19 | { 20 | short x=idx_x+i; 21 | if (x<0) x=0; 22 | if (x>=n_x) x=n_x-1; 23 | sum+=kernel[i+k]*img[idx_y*n_x+x]; 24 | } 25 | out[idx_y*n_x+idx_x]=sum; 26 | } 27 | 28 | void _image2D1C_ConvolveRow(float* img, int n_x, int n_y, short k, float *kernel, float* out) 29 | { 30 | dim3 block_size; 31 | block_size.x=32; 32 | block_size.y=32; 33 | dim3 grid_size; 34 | grid_size.x = iDivUp(n_x,block_size.x); 35 | grid_size.y = iDivUp(n_y,block_size.y); 36 | 37 | cudaCheckState 38 | kernel_image2D1C_ConvolveRow<<>>(img, n_x, n_y, k, kernel, out); 39 | cudaDeviceSynchronize(); 40 | cudaCheckState 41 | } 42 | 43 | // 1D convolution along columns of a single-channel 2D image 44 | __global__ void kernel_image2D1C_ConvolveColumn(float* img, int n_x, int n_y, short k, float *kernel, float* out) 45 | { 46 | // Find index of current thread 47 | int idx_x = blockIdx.x * blockDim.x + threadIdx.x; 48 | int idx_y = blockIdx.y * blockDim.y + threadIdx.y; 49 | if (idx_x>=n_x) return; 50 | if (idx_y>=n_y) return; 51 | float sum=0; 52 | for (short i=-k;i<=k;i++) 53 | { 54 | short y=idx_y+i; 55 | if (y<0) y=0; 56 | if (y>=n_y) y=n_y-1; 57 | sum+=kernel[i+k]*img[y*n_x+idx_x]; 58 | } 59 | out[idx_y*n_x+idx_x]=sum; 60 | } 61 | 62 | void _image2D1C_ConvolveColumn(float* img, int n_x, int n_y, short k, float *kernel, float* out) 63 | { 64 | dim3 block_size; 65 | block_size.x=32; 66 | block_size.y=32; 67 | dim3 grid_size; 68 | grid_size.x = iDivUp(n_x,block_size.x); 69 | grid_size.y = iDivUp(n_y,block_size.y); 70 | 71 | cudaCheckState 72 | kernel_image2D1C_ConvolveColumn<<>>(img, n_x, n_y, k, kernel, out); 73 | cudaDeviceSynchronize(); 74 | cudaCheckState 75 | } 76 | 77 | void _image2D1C_ConvolveSperable(float* img, int n_x, int n_y, short kx, float *kernelx, short ky, float *kernely, float* tmp) 78 | { 79 | _image2D1C_ConvolveRow(img, n_x,n_y, kx,kernelx, tmp); 80 | _image2D1C_ConvolveColumn(tmp, n_x,n_y, ky,kernely, img); 81 | } 82 | 83 | /// A Gaussian curve. 84 | inline float gaussian(float x, float sigma) 85 | { 86 | return expf(-0.5f*powf(x/sigma,2)); 87 | } 88 | 89 | void _image2D1C_Gaussian(float* img, int n_x, int n_y, short k, float sigma, float* tmp) 90 | { 91 | int n=k*2+1; 92 | std::vector kernel(n); 93 | float sum=0; 94 | for (int x=-k;x<=k;x++) 95 | sum+=(kernel[x+k]=gaussian((float)x,sigma)); 96 | for (int i=0;i kernel_device(n,&kernel[0]); 99 | UtilsCuda::MemoryBlock tmp_mem; // allocate if needed 100 | if (!tmp) tmp_mem.allocate(n_x*n_y); 101 | if (!tmp) tmp=tmp_mem; 102 | _image2D1C_ConvolveRow(img, n_x,n_y, k,kernel_device, tmp); 103 | _image2D1C_ConvolveColumn(tmp, n_x,n_y, k,kernel_device, img); 104 | } 105 | -------------------------------------------------------------------------------- /code/LibUtilsCuda/CudaMemory.cpp: -------------------------------------------------------------------------------- 1 | #include "CudaMemory.h" 2 | 3 | #ifdef _cuda_momory_hxx_debug_info 4 | std::map > _cuda_mem_alloc; 5 | void setMemoryAllocation(std::string type, void * location, int length, bool active) 6 | { 7 | if (active) 8 | _cuda_mem_alloc[location]=std::pair(length,type); 9 | else 10 | { 11 | auto it=_cuda_mem_alloc.find(location); 12 | if (it!=_cuda_mem_alloc.end()) 13 | _cuda_mem_alloc.erase(it); 14 | } 15 | } 16 | 17 | namespace UtilsCuda 18 | { 19 | std::map > getLog() 20 | { 21 | return _cuda_mem_alloc; 22 | } 23 | 24 | } // namespace UtilsCuda 25 | #endif 26 | -------------------------------------------------------------------------------- /code/LibUtilsCuda/CudaTextureArray.hxx: -------------------------------------------------------------------------------- 1 | #ifndef __cuda_texture_array_hxx 2 | 3 | namespace UtilsCuda { 4 | 5 | /// Creates an array to be bound to a 3D texture unit 6 | template struct TextureArray3D { 7 | cudaArray *cu_array; 8 | cudaChannelFormatDesc channelDesc; 9 | cudaExtent size; 10 | TextureArray3D(T* host=0x0, int nx=0, int ny=0, int nz=0) 11 | { 12 | // Defaults to invalid instance 13 | if (!host) { 14 | size.width=size.height=size.depth=0; 15 | cu_array=0x0; 16 | return; 17 | } 18 | // Size of array 19 | size.width=nx; 20 | size.height=ny; 21 | size.depth=nz; 22 | // Create 3D array 23 | channelDesc = cudaCreateChannelDesc(); 24 | cudaMalloc3DArray(&cu_array, &channelDesc, size); 25 | cudaCheckState 26 | // Copy data to 3D array 27 | cudaMemcpy3DParms copyParams = {0}; 28 | copyParams.srcPtr = make_cudaPitchedPtr((void*)host, nx*sizeof(T), nx, ny); 29 | copyParams.dstArray = cu_array; 30 | copyParams.extent = size; 31 | copyParams.kind = cudaMemcpyHostToDevice; 32 | cudaMemcpy3D(©Params); 33 | cudaCheckState 34 | } 35 | 36 | /// expects a texture 37 | template void bind(cutex &tex) const 38 | { 39 | cudaBindTextureToArray(tex, cu_array, channelDesc); 40 | cudaCheckState 41 | } 42 | 43 | }; 44 | 45 | /// Creates an array to be bound to a 2D texture unit 46 | template struct TextureArray2D { 47 | cudaArray *cu_array; 48 | cudaChannelFormatDesc channelDesc; 49 | struct { 50 | int width; 51 | int height; 52 | } size; 53 | TextureArray2D(T* host=0x0, int n_x=0, int n_y=0) 54 | { 55 | size.width=n_x;size.height=n_y; 56 | // Defaults to invalid instance 57 | if (host) { 58 | cu_array=0x0; 59 | return; 60 | } 61 | cudaArray* cu_array; 62 | channelDesc = cudaCreateChannelDesc(); 63 | cudaMemcpyToArray(cu_array, 0, 0, host, n_x*n_y*sizeof(T), cudaMemcpyHostToDevice); 64 | cudaMallocArray(&cu_array, &channelDesc, n_x, n_y); 65 | } 66 | 67 | /// expects a texture 68 | template void bind(cutex &tex) const 69 | { 70 | cudaBindTextureToArray(tex, cu_array, channelDesc); 71 | cudaCheckState 72 | } 73 | 74 | }; 75 | 76 | typedef TextureArray3D Tex3Df; 77 | typedef TextureArray2D Tex2Df; 78 | 79 | } // namespace UtilsCuda 80 | 81 | #endif // __cuda_texture_array_hxx 82 | -------------------------------------------------------------------------------- /code/LibUtilsCuda/UtilsCuda.hxx: -------------------------------------------------------------------------------- 1 | // Created by A. Aichert on Thu Nov 21st 2013 2 | #ifndef __cuda__util_hxx 3 | #define __cuda__util_hxx 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #define cudaCheckErrors(ans) cudaAssert((ans), __FILE__, __LINE__); 12 | #define cudaCheckState cudaAssert(cudaPeekAtLastError(), __FILE__, __LINE__); 13 | 14 | inline void cudaAssert(cudaError_t code, const std::string& file, int line, bool abort=true) 15 | { 16 | if (code == cudaSuccess) 17 | return; 18 | auto err=cudaGetErrorString(code); 19 | std::cerr 20 | << "CUDA error " << (int)code << ": " 21 | << err << "\n at " 22 | << file << "(" << line << ")\n"; 23 | if (abort) { 24 | std::cout << "See also:\n" << __FILE__ << "(" << __LINE__ << ")\n"; 25 | exit(code); 26 | } 27 | std::cerr << "Continued.\n"; 28 | } 29 | 30 | inline int iDivUp(int a, int b) { return (a%b!=0)?(a/b+1):(a/b); } 31 | 32 | namespace CudaUtils { 33 | 34 | /// Creates an array to be bound to a 3D texture unit 35 | template struct TextureArray3D { 36 | cudaArray *cu_array; 37 | cudaChannelFormatDesc channelDesc; 38 | cudaExtent size; 39 | TextureArray3D(T* host=0x0, int nx=0, int ny=0, int nz=0) 40 | { 41 | // Defaults to invalid instance 42 | if (!host) { 43 | size.width=size.height=size.depth=0; 44 | cu_array=0x0; 45 | return; 46 | } 47 | // Size of array 48 | size.width=nx; 49 | size.height=ny; 50 | size.depth=nz; 51 | // Create 3D array 52 | channelDesc = cudaCreateChannelDesc(); 53 | cudaMalloc3DArray(&cu_array, &channelDesc, size); 54 | cudaCheckState 55 | // Copy data to 3D array 56 | cudaMemcpy3DParms copyParams = {0}; 57 | copyParams.srcPtr = make_cudaPitchedPtr((void*)host, nx*sizeof(T), nx, ny); 58 | copyParams.dstArray = cu_array; 59 | copyParams.extent = size; 60 | copyParams.kind = cudaMemcpyHostToDevice; 61 | cudaMemcpy3D(©Params); 62 | cudaCheckState 63 | } 64 | 65 | /// expects a texture 66 | template void bind(cutex &tex) const 67 | { 68 | cudaBindTextureToArray(tex, cu_array, channelDesc); 69 | cudaCheckState 70 | } 71 | 72 | }; 73 | 74 | /// Creates an array to be bound to a 2D texture unit 75 | template struct TextureArray2D { 76 | cudaArray *cu_array; 77 | cudaChannelFormatDesc channelDesc; 78 | struct { 79 | int width; 80 | int height; 81 | } size; 82 | TextureArray2D(T* host=0x0, int n_x=0, int n_y=0) 83 | { 84 | size.width=n_x;size.height=n_y; 85 | // Defaults to invalid instance 86 | if (host) { 87 | cu_array=0x0; 88 | return; 89 | } 90 | cudaArray* cu_array; 91 | channelDesc = cudaCreateChannelDesc(); 92 | cudaMemcpyToArray(cu_array, 0, 0, host, n_x*n_y*sizeof(T), cudaMemcpyHostToDevice); 93 | cudaMallocArray(&cu_array, &channelDesc, n_x, n_y); 94 | } 95 | 96 | /// expects a texture 97 | template void bind(cutex &tex) const 98 | { 99 | cudaBindTextureToArray(tex, cu_array, channelDesc); 100 | cudaCheckState 101 | } 102 | 103 | }; 104 | 105 | typedef TextureArray3D Tex3Df; 106 | typedef TextureArray2D Tex2Df; 107 | 108 | } // namespace CUDAUtil 109 | 110 | #endif // __cuda__util_hxx 111 | -------------------------------------------------------------------------------- /code/LibUtilsCuda/culaut/xgemv.hxx: -------------------------------------------------------------------------------- 1 | #ifndef __xgemv_hxx 2 | #define __xgemv_hxx 3 | 4 | #include "culaut.hxx" 5 | 6 | #ifndef __device__ 7 | #define __device__ 8 | #define udef__device__ 9 | #endif 10 | #ifndef __host__ 11 | #define __host__ 12 | #define udef__host__ 13 | #endif 14 | 15 | namespace culaut 16 | { 17 | 18 | /// 3x3 Matrix-Vector Product 19 | template 20 | inline void xgemv3(const Matrix3& A, const Vector3A& x, Vector3B& b) 21 | { 22 | b[0]=A[0]*x[0]+A[3]*x[1]+A[6]*x[2]; 23 | b[1]=A[1]*x[0]+A[4]*x[1]+A[7]*x[2]; 24 | b[2]=A[2]*x[0]+A[5]*x[1]+A[8]*x[2]; 25 | } 26 | 27 | /// 3x3 Matrix-Vector Product, x is overwritten 28 | template 29 | inline void xgemv3(const Matrix3& A, Scalar x[]) 30 | { 31 | Scalar b[] = { 32 | A[0]*x[0]+A[3]*x[1]+A[6]*x[2], 33 | A[1]*x[0]+A[4]*x[1]+A[7]*x[2], 34 | A[2]*x[0]+A[5]*x[1]+A[8]*x[2] 35 | } 36 | x[0]=b[0];x[1]=b[1];x[2]=b[2]; 37 | } 38 | 39 | /// 4x4 Matrix-Vector Product 40 | template 41 | inline void xgemv4(const Matrix4& A, const Vector4A& v, Vector4B& x) 42 | { 43 | x[0]=A[0]*x[0]+A[4]*x[1]+A[ 8]*x[2]+A[12]*x[3]; 44 | x[1]=A[1]*x[0]+A[5]*x[1]+A[ 9]*x[2]+A[13]*x[3]; 45 | x[2]=A[2]*x[0]+A[6]*x[1]+A[10]*x[2]+A[14]*x[3]; 46 | x[3]=A[3]*x[0]+A[7]*x[1]+A[11]*x[2]+A[15]*x[3]; 47 | } 48 | 49 | /// 4x4 Matrix-Vector Product, x is overwritten 50 | template 51 | inline void xgemv4(const Matrix4& A, Scalar x[]) 52 | { 53 | Scalar b[] = { 54 | A[0]*x[0]+A[4]*x[1]+A[ 8]*x[2]+A[12]*x[3], 55 | A[1]*x[0]+A[5]*x[1]+A[ 9]*x[2]+A[13]*x[3], 56 | A[2]*x[0]+A[6]*x[1]+A[10]*x[2]+A[14]*x[3], 57 | A[3]*x[0]+A[7]*x[1]+A[11]*x[2]+A[15]*x[3] 58 | } 59 | x[0]=b[0];x[1]=b[1];x[2]=b[2];x[3]=b[3]; 60 | } 61 | 62 | /// 3x4 Matrix-4-Vector Product (Camera Projection) 63 | template 64 | inline void xgemv34(const Matrix34& P, Vector4& X, Vector3& x) 65 | { 66 | x[0]=P[0]*X[0]+P[3]*X[1]+P[6]*X[2]+P[ 9]*X[3]; 67 | x[1]=P[1]*X[0]+P[4]*X[1]+P[7]*X[2]+P[ 0]*X[3]; 68 | x[2]=P[2]*X[0]+P[5]*X[1]+P[8]*X[2]+P[11]*X[3]; 69 | } 70 | 71 | /// 3x4 Matrix-3-Vector Product (Backprojection) 72 | template 73 | inline void xgemv43(const Matrix43& H, Vector3& v, Vector4& x) 74 | { 75 | P[0]*x[0]+P[4]*x[1]+P[ 8]*x[2]; 76 | P[1]*x[0]+P[5]*x[1]+P[ 9]*x[2]; 77 | P[2]*x[0]+P[6]*x[1]+P[10]*x[2]; 78 | P[3]*x[0]+P[7]*x[1]+P[11]*x[2]; 79 | } 80 | 81 | 82 | } // namespace LAUT 83 | 84 | #ifdef udef__device__ 85 | #undef udef__device__ 86 | #undef __device__ 87 | #endif 88 | #ifdef udef__host__ 89 | #undef udef__host__ 90 | #undef __host__ 91 | #endif 92 | #endif // __xgemv_hxx -------------------------------------------------------------------------------- /code/LibUtilsCuda/culaut/xprojectivegeometry.hxx: -------------------------------------------------------------------------------- 1 | #ifndef __x_projective_geometry_hxx 2 | #define __x_projective_geometry_hxx 3 | 4 | #ifndef __device__ 5 | #define __device__ 6 | #define udef__device__ 7 | #endif 8 | #ifndef __host__ 9 | #define __host__ 10 | #define udef__host__ 11 | #endif 12 | 13 | namespace culaut 14 | { 15 | 16 | /// Join two points to form a line. L= A join B 17 | template __device__ __host__ inline 18 | void join_pluecker(T A[4], T B[4], T L[6]) 19 | { 20 | L[0]=A[0]*B[1]-A[1]*B[0]; 21 | L[1]=A[0]*B[2]-A[2]*B[0]; 22 | L[2]=A[0]*B[3]-A[3]*B[0]; 23 | L[3]=A[1]*B[2]-A[2]*B[1]; 24 | L[4]=A[1]*B[3]-A[3]*B[1]; 25 | L[5]=A[2]*B[3]-A[3]*B[2]; 26 | } 27 | 28 | /// Meet a line and a plane to form a point. X= L meet P 29 | template __device__ __host__ inline 30 | void meet_pluecker(T L[6], T P[4], T X[4]) 31 | { 32 | X[0]= - P[1]*L[0] - P[2]*L[1] - P[3]*L[2] ; 33 | X[1]= + P[0]*L[0] - P[2]*L[3] - P[3]*L[4] ; 34 | X[2]= + P[0]*L[1] + P[1]*L[3] - P[3]*L[5] ; 35 | X[3]= + P[0]*L[2] + P[1]*L[4] + P[2]*L[5] ; 36 | } 37 | 38 | template __device__ __host__ inline 39 | void pluecker_closest_point_to_origin(T L[6], T O[4]) 40 | { 41 | O[0]=L[4]*L[0]+L[1]*L[5]; 42 | O[1]=-L[0]*L[2]+L[3]*L[5]; 43 | O[2]=-L[1]*L[2]-L[3]*L[4]; 44 | O[3]=-L[2]*L[2]-L[4]*L[4]-L[5]*L[5]; 45 | } 46 | 47 | } // namespace culaut 48 | 49 | #endif // __x_projective_geometry_hxx 50 | -------------------------------------------------------------------------------- /code/LibUtilsQt/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | add_library( LibUtilsQt 3 | Figure.hxx 4 | Plot.hxx 5 | EventFilters.h 6 | EventFilters.cpp 7 | FigureWindow.h 8 | FigureWindow.cpp 9 | QCameraView.h 10 | QCameraView.cpp 11 | QGLPlot3D.h 12 | QGLPlot3D.cpp 13 | # QCP should actually be a library built someplace else ... (http://www.qcustomplot.com/) 14 | QCustomPlot.h 15 | QCustomPlot.cpp 16 | ) 17 | qt5_use_modules(LibUtilsQt OpenGL PrintSupport) 18 | target_link_libraries(LibUtilsQt LibProjectiveGeometry GetSet GetSetGui ${OPENGL_LIBRARIES}) 19 | install(TARGETS LibUtilsQt DESTINATION lib EXPORT LibUtilsQt-targets) 20 | install(EXPORT LibUtilsQt-targets DESTINATION cmake) 21 | set_property(TARGET LibUtilsQt PROPERTY FOLDER "Packages") -------------------------------------------------------------------------------- /code/LibUtilsQt/EventFilters.cpp: -------------------------------------------------------------------------------- 1 | #include "EventFilters.h" 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | namespace UtilsQt { 8 | 9 | EventFilterMouse::EventFilterMouse(QWidget * parent) : QObject(parent) { 10 | parent->installEventFilter(this); 11 | parent->setMouseTracking(true); 12 | } 13 | 14 | EventFilterMouse::~EventFilterMouse() { disconnect(); } 15 | 16 | bool EventFilterMouse::eventFilter(QObject * obj, QEvent * ev) 17 | { 18 | if (!obj->isWidgetType()) return false; 19 | QMouseEvent* me=dynamic_cast(ev); 20 | if (!me) { 21 | QWheelEvent *we=dynamic_cast(ev); 22 | if (we){ 23 | bool mod_shit=we->modifiers() & Qt::ShiftModifier; 24 | bool mod_ctrl=we->modifiers() & Qt::ControlModifier; 25 | emit mouse_wheel(we->angleDelta().x(),we->angleDelta().y(), mod_shit, mod_ctrl); 26 | } 27 | return false; 28 | } 29 | int x=me->x(); 30 | int y=me->y(); 31 | int dx=mouse_x-x; 32 | int dy=mouse_y-y; 33 | mouse_x=x; 34 | mouse_y=y; 35 | left_button=me->buttons() & Qt::LeftButton; 36 | mouse_x=x; 37 | mouse_y=y; 38 | if (ev->type() == QEvent::MouseButtonPress) emit mouse_click(x,y,left_button, false); 39 | else if (ev->type() == QEvent::MouseButtonRelease) emit mouse_click(x,y,left_button, true); 40 | else if (ev->type() == QEvent::MouseButtonDblClick) emit mouse_double_click(x,y,left_button); 41 | else if (ev->type() == QEvent::MouseMove && me->buttons()==0) emit mouse_move(x,y,dx,dy); 42 | else if (ev->type() == QEvent::MouseMove && me->buttons()!=0) emit mouse_drag(x,y,dx,dy); 43 | return false; 44 | } 45 | 46 | EventFilterWindow::EventFilterWindow(QWidget * parent) : QObject(parent) { 47 | parent->installEventFilter(this); 48 | } 49 | 50 | EventFilterWindow::~EventFilterWindow() { disconnect(); } 51 | 52 | bool EventFilterWindow::eventFilter(QObject * obj, QEvent * ev) 53 | { 54 | if (!obj->isWidgetType()) return false; 55 | QCloseEvent* ce=dynamic_cast(ev); 56 | if (ce) emit closed(); 57 | else if (ev->type()==QEvent::WindowActivate) 58 | emit activation_change(true); 59 | else if (ev->type()==QEvent::WindowDeactivate) 60 | emit activation_change(true); 61 | else 62 | { 63 | QResizeEvent* re=dynamic_cast(ev); 64 | if (re) resize(re->size().width(), re->size().height()); 65 | } 66 | return false; 67 | } 68 | 69 | } // namespace UtilsQt 70 | -------------------------------------------------------------------------------- /code/LibUtilsQt/EventFilters.h: -------------------------------------------------------------------------------- 1 | #ifndef __event_filters_h 2 | #define __event_filters_h 3 | 4 | #include 5 | #include 6 | 7 | namespace UtilsQt { 8 | 9 | /// An object attached to a widget to capture mouse events. 10 | class EventFilterMouse : public QObject { 11 | Q_OBJECT 12 | 13 | int mouse_x; 14 | int mouse_y; 15 | bool left_button; 16 | 17 | bool eventFilter(QObject* obj, QEvent* ev) Q_DECL_OVERRIDE ; 18 | public: 19 | Q_SIGNAL void mouse_click (int x, int y, bool left_button, bool release); 20 | Q_SIGNAL void mouse_double_click(int x, int y, bool left_button); 21 | Q_SIGNAL void mouse_move (int x, int y, int dx, int dy); 22 | Q_SIGNAL void mouse_drag (int x, int y, int dx, int dy); 23 | Q_SIGNAL void mouse_wheel (int dx, int dy, bool shift, bool ctrl); 24 | 25 | bool is_left_button() { return left_button; } 26 | 27 | EventFilterMouse(QWidget* parent); 28 | ~EventFilterMouse(); 29 | }; 30 | 31 | /// An object attached to a widget to capture window closed and resize events. 32 | class EventFilterWindow : public QObject { 33 | Q_OBJECT 34 | 35 | bool eventFilter(QObject* obj, QEvent* ev) Q_DECL_OVERRIDE ; 36 | public: 37 | Q_SIGNAL void closed(); 38 | Q_SIGNAL void resize(int w, int h); 39 | Q_SIGNAL void activation_change(bool becomes_active); 40 | 41 | EventFilterWindow(QWidget* parent); 42 | ~EventFilterWindow(); 43 | }; 44 | 45 | 46 | } // namespace UtilsQt 47 | 48 | #endif // __event_filters_h 49 | -------------------------------------------------------------------------------- /code/LibUtilsQt/Figure.hxx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aaichert/EpipolarConsistency/8feb718e6b35a943d30684a40e52feb024df91fc/code/LibUtilsQt/Figure.hxx -------------------------------------------------------------------------------- /code/LibUtilsQt/GraphicsItems.hxx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aaichert/EpipolarConsistency/8feb718e6b35a943d30684a40e52feb024df91fc/code/LibUtilsQt/GraphicsItems.hxx -------------------------------------------------------------------------------- /code/LibUtilsQt/QCameraView.h: -------------------------------------------------------------------------------- 1 | #ifndef __camera_view 2 | #define __camera_view 3 | 4 | #define WITH_GETSET 5 | 6 | #ifdef WITH_GETSET 7 | #include 8 | #endif 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #include 16 | #include 17 | #include 18 | 19 | #include 20 | 21 | #include "ProjectionParameters.hxx" 22 | 23 | #include "GraphicsItems.hxx" 24 | #include "GraphicsItemConvexMesh.hxx" 25 | 26 | class QCameraView : public QWidget 27 | { 28 | Q_OBJECT 29 | public: 30 | Geometry::ProjectionMatrix P; //< Projection Matrix for 3D wireframe scene. 31 | UtilsQt::ProjectionParameters *projection; //< Parameters for automatic rotation etc. 32 | GraphicsItems::Group graphics; //< Graphics items automatically drawn. 33 | 34 | QCameraView(QWidget* parent = 0x0, UtilsQt::ProjectionParameters * proj=0x0); 35 | 36 | // Set function pointers 37 | void setDrawFunc(void (*f)(QPainter&,QCameraView*)) {draw=f;} 38 | void setKeyboardFunc(void (*f)(unsigned char key, int x, int y)); 39 | void setKeyboardUpFunc(void (*f)(unsigned char key, int x, int y)); 40 | void setSpecialFunc(void (*f)(int key, int x, int y)); 41 | void setSpecialUpFunc(void (*f)(int key, int x, int y)); 42 | void setMouseFunc(void (*f)(int button, int state, int x, int y)); 43 | void setMotionFunc(void (*f)(int x, int y, int last_button)); 44 | void setPassiveMotionFunc(void (*f)(int x, int y)); 45 | void setWheelFunc(void (*f)(int anglex, int angley)); 46 | void setResizeFunc(void (*f)(int w, int h)); 47 | void setCloseFunc(void (*f)()); 48 | 49 | virtual void paintEvent(QPaintEvent *event); 50 | 51 | void savePDF(const std::string& path); 52 | 53 | private: 54 | // Mouse state 55 | int m_mouseDown; 56 | int m_mouseX; 57 | int m_mouseY; 58 | UtilsQt::ProjectionParameters default_projection; 59 | 60 | // Events for call-back mechanism 61 | virtual void mousePressEvent(QMouseEvent *event); 62 | virtual void mouseReleaseEvent(QMouseEvent *event); 63 | virtual void mouseMoveEvent(QMouseEvent *event); 64 | virtual void keyPressEvent(QKeyEvent *event); 65 | virtual void keyReleaseEvent(QKeyEvent *event); 66 | virtual void wheelEvent(QWheelEvent *event); 67 | virtual void resizeEvent(QResizeEvent *event); 68 | virtual void closeEvent(QCloseEvent *event); 69 | 70 | // function pointers 71 | void (*draw)(QPainter&,QCameraView*); 72 | void (*keyboardFunc)(unsigned char key, int x, int y); 73 | void (*keyboardUpFunc)(unsigned char key, int x, int y); 74 | void (*mouseFunc)(int button, int state, int x, int y); 75 | void (*motionFunc)(int x, int y, int last_button); 76 | void (*passiveMotionFunc)(int x, int y); 77 | void (*specialFunc)(int key, int x, int y); 78 | void (*specialUpFunc)(int key, int x, int y); 79 | void (*wheelFunc)(int anglex, int angley); 80 | void (*resizeFunc)(int w, int h); 81 | void (*closeFunc)(); 82 | 83 | }; 84 | 85 | #endif // __camera_view 86 | -------------------------------------------------------------------------------- /code/LibUtilsQt/QGLPlot3D.h: -------------------------------------------------------------------------------- 1 | // Created by Andre Aichert in 2011 2 | #ifndef QGLPLOT3D_H 3 | #define QGLPLOT3D_H 4 | 5 | #include 6 | 7 | #include 8 | 9 | namespace UtilsQt { 10 | 11 | class QGLPlot3D : public QGLWidget { 12 | public: 13 | QGLPlot3D(QWidget* parent=0x0); 14 | QGLPlot3D(const std::string& path, QWidget* parent=0x0); 15 | // Data is stored in a 3*size*size matrix stores, unlike in MATLAB, in row-major order. 16 | QGLPlot3D(int size, float* data, QWidget* parent = 0); 17 | // Data is stored in a single-channel w*h image 18 | QGLPlot3D(int w, int h, float* data, double minx=-1, double maxx=1, double miny=-1, double maxy=1, QWidget* parent = 0); 19 | void setLabel(const std::string& lx, const std::string& ly) { m_label_x = lx; m_label_y = ly; } 20 | ~QGLPlot3D(); 21 | 22 | /// Save graph as text file. 23 | bool save(const std::string& path); 24 | /// Read file saved by QGLPlot3D 25 | bool load(const std::string& path); 26 | 27 | protected: 28 | /// Set the data to plot, takes ownership of data; 29 | void setData(int size, float *data); 30 | 31 | void initializeGL(); 32 | void paintGL(); 33 | void resizeGL(int width, int height); 34 | 35 | void mouseMoveEvent(QMouseEvent *event); 36 | void wheelEvent(QWheelEvent *event); 37 | void keyPressEvent(QKeyEvent *event); 38 | 39 | /// Cross product of 3-vectors 40 | void crossprod(float *v1, float *v2, float *prod); 41 | /// Normalizes a 3-vector 42 | void normalize(float *v); 43 | /// Draws a surface point with the right color & normal 44 | void draw_vertex(int i, int j); 45 | /// Draws grid lines 46 | void drawGrid(); 47 | /// Render offset text 48 | void renderOffsetText(double x, double y, double z, const std::string& txt, const QFont& f); 49 | /// Draws text 50 | void drawText(); 51 | 52 | float *m_data; ///< The surface data 53 | float *m_normals; ///< The surface normals 54 | int m_size; ///< Width and height of the plot 55 | double m_bounds[6]; ///< Min/Max in X,Y,Z 56 | 57 | // Display Options 58 | bool m_optGrid; ///< Show grid (key 'g') 59 | bool m_optHalfGrid; ///< Fine grid on/off (key 'v') 60 | bool m_optColors; ///< Color code heatmap or just gray (key 'c') 61 | bool m_optFlatShaded; ///< Flat shading (key 'f') 62 | bool m_optLighting; ///< Light on/off (key 'l') 63 | bool m_optIsoLines; ///< Show 10 iso-levels by shading (key 'i') 64 | bool m_optOrtho; ///< Perspective and Orthographic projection (key 'p') 65 | bool m_optNoNumbers; ///< Print scale next to axes (key 'n' as in Numbers) 66 | bool m_optBig; ///< Thicker lines and larger text (key 'b') 67 | bool m_optMovingLight; ///< Light is fixed relative to view. (key 'm') 68 | 69 | double m_view[3]; ///< x/y viewing angles and distance from center 70 | int m_mouse_drag[2]; ///< x/y position of mouse 71 | double m_isoLevel; ///< z-value of threshold plane. (key 't') 72 | 73 | std::string m_label_x; 74 | std::string m_label_y; 75 | 76 | static const float CMAP[196]; ///< MATLAB-style colormap 77 | static const float LightSource[4]; ///< Position of the diffuse light source 78 | static const float LightAmbient[4]; ///< Ambient light color 79 | static const float LightWhite[4]; ///< Diffuse and specular light color 80 | }; 81 | 82 | } // namespace UtilsQt 83 | 84 | #endif // QGLPLOT3D_H 85 | -------------------------------------------------------------------------------- /config/VisualizeECC.ini: -------------------------------------------------------------------------------- 1 | 2 | [Epipolar Consistency/Images] 3 | Image 0 = L:/20141006FOAX/Pumpkin/Motion/M6/NRRD_2014/M6_000.nrrd 4 | Image 1 = L:/20141006FOAX/Pumpkin/Motion/M6/NRRD_2014/M6_055.nrrd 5 | Pixel Spacing = -0.154 6 | 7 | 8 | [Epipolar Consistency/Sampling] 9 | Angle Step (deg) = 0.01 10 | Mode = ECC (Grangeat) 11 | Object Radius = 120 12 | Type = FBCC (weighted integrals) 13 | 14 | 15 | [] 16 | Application = VisualizeECC 17 | ini-File = VisualizeECC.ini 18 | 19 | -------------------------------------------------------------------------------- /config/example_data/proj000.nrrd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aaichert/EpipolarConsistency/8feb718e6b35a943d30684a40e52feb024df91fc/config/example_data/proj000.nrrd -------------------------------------------------------------------------------- /config/example_data/proj040.nrrd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aaichert/EpipolarConsistency/8feb718e6b35a943d30684a40e52feb024df91fc/config/example_data/proj040.nrrd -------------------------------------------------------------------------------- /examples.gitignore: -------------------------------------------------------------------------------- 1 | # The purpose of gitignore files is to ensure that certain files not tracked by Git remain untracked. 2 | # -> files are tracked at the moment: 3 | # To stop tracking a file that is currently tracked, use git rm --cached. 4 | 5 | # syntax: 6 | 7 | # one file per line 8 | # normally all files with that name in all subdirectories are ignored 9 | # begin with "/" (example: /file.type) -> only the current file in this directory is ignored 10 | # *.type -> ignores all files with that extension 11 | 12 | 13 | #ignored files: 14 | config/example_data/proj000.nrrd 15 | config/example_data/proj040.nrrd 16 | config/VisualizeECC.ini -------------------------------------------------------------------------------- /matlab/ecc_demo/ecc_computeK01.m: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aaichert/EpipolarConsistency/8feb718e6b35a943d30684a40e52feb024df91fc/matlab/ecc_demo/ecc_computeK01.m -------------------------------------------------------------------------------- /matlab/ecc_demo/ecc_compute_consistency.m: -------------------------------------------------------------------------------- 1 | % P0, P1 Projection matrices 2 | % n_x, n_y Original image size in pixels 3 | % dtr0, dtr1 Derivatives of Radon transforms of original images 4 | % range_t Range (pixels) of Radon transform. Usually equal to original image diagonal 5 | % dkappa Angular step between epipolar planes. Should be small enough to densely sample RDAs 6 | function consistency=ecc_compute_consistency(P0, P1, n_x, n_y, dtr0, dtr1, range_t, dkappa) 7 | 8 | % Mapping to epipolar lines 9 | [K0 K1]=ecc_computeK01(P0,P1, n_x, n_y); 10 | 11 | % Sum of inconsistencies = Consistency Metric 12 | consistency=0; 13 | for kappa=[0:dkappa:pi*0.5] 14 | % Compute epipolar line for +kappa 15 | x_kappa=[cos(kappa); sin(kappa)]; 16 | l0_plus_kappa=K0*x_kappa; 17 | l1_plus_kappa=K1*x_kappa; 18 | % Sample Radon derivatives at corresponding locations 19 | vp0=ecc_sample_dtr(l0_plus_kappa, dtr0, range_t); 20 | vp1=ecc_sample_dtr(l1_plus_kappa, dtr1, range_t); 21 | 22 | % Compute epipolar line for -kappa 23 | x_kappa=[cos(-kappa); sin(-kappa)]; 24 | l0_minus_kappa=K0*x_kappa; 25 | l1_minus_kappa=K1*x_kappa; 26 | % Sample Radon derivatives at corresponding locations 27 | vm0=ecc_sample_dtr(l0_minus_kappa, dtr0, range_t); 28 | vm1=ecc_sample_dtr(l1_minus_kappa, dtr1, range_t); 29 | 30 | % Compute squared difference (for both +/- kappa) 31 | v=(vp0-vp1)*(vp0-vp1)+(vm0-vm1)*(vm0-vm1); 32 | 33 | % Stopping criteria (important if epipole not within images 34 | if v==0 35 | break; 36 | end % if 37 | 38 | % Compute sum 39 | consistency=consistency+v*dkappa; 40 | end % for 41 | end % function 42 | -------------------------------------------------------------------------------- /matlab/ecc_demo/ecc_compute_dtr.m: -------------------------------------------------------------------------------- 1 | function dtr = ecc_compute_dtr(I) 2 | % Original image size 3 | [n_x n_y]=size(I); 4 | % Some appropriate bin size for angles 5 | diagonal=norm([n_x n_y]); 6 | radon_binsize_alpha_deg=180/diagonal; 7 | % Radon transform 8 | rhoI=radon(I,[0:radon_binsize_alpha_deg:180]); 9 | % Gradient computation (in t-direction) 10 | [unused dtr]=gradient(rhoI); 11 | % Number of pixels in original image, to which one bin of radon transform 12 | radon_binsize_t=1; 13 | end % function 14 | -------------------------------------------------------------------------------- /matlab/ecc_demo/ecc_sample_dtr.m: -------------------------------------------------------------------------------- 1 | function [deriv_line_integral]=ecc_sample_dtr(line, dtr, range_t) 2 | % Convert line to angle-distance 3 | [alpha, t]=line_to_angle_distance(line); 4 | 5 | % Scale to Radon bins 6 | dtr_x=alpha/pi+1; % 0 to 2 range 7 | dtr_y=t/range_t+0.5; % 0 to 1 with image center at .5 8 | 9 | % Compute normalized coordinates in Radon derivative 10 | % Also accounts for symmetry rho(alpha,t)=-rho(alpha+pi,-t) 11 | if (dtr_x>1) 12 | weight=-1; 13 | dtr_x=dtr_x-1.0; 14 | dtr_y=1.0-dtr_y; 15 | else 16 | weight=1; 17 | end % if 18 | 19 | % Scale to actual pixels (one-based and flip to be consistent with MATLAB's radon() function) 20 | dtr_x=(1-dtr_x)*size(dtr,1)+1; 21 | dtr_y=(1-dtr_y)*size(dtr,2)+1; 22 | % Sample image (linear interpolation) 23 | deriv_line_integral=weight*interp2(dtr,dtr_x,dtr_y,'linear',0); 24 | 25 | end % function 26 | -------------------------------------------------------------------------------- /matlab/ecc_demo/ecc_sample_dtr_debug.m: -------------------------------------------------------------------------------- 1 | function [deriv_line_integral, dtr_x, dtr_y, weight]=ecc_sample_dtr_debug(line, dtr, range_t) 2 | % Convert line to angle-distance 3 | [alpha, t]=line_to_angle_distance(line); 4 | 5 | % Scale to Radon bins 6 | dtr_x=alpha/pi+1; % 0 to 2 range 7 | dtr_y=t/range_t+0.5; % 0 to 1 with image center at .5 8 | 9 | % Compute normalized coordinates in Radon derivative 10 | % Also accounts for symmetry rho(alpha,t)=-rho(alpha+pi,-t) 11 | if (dtr_x>1) 12 | weight=-1; 13 | dtr_x=dtr_x-1.0; 14 | dtr_y=1.0-dtr_y; 15 | else 16 | weight=1; 17 | end % if 18 | 19 | % Scale to actual pixels (one-based and flip to be consistent with MATLAB's radon() function) 20 | dtr_x=(1-dtr_x)*size(dtr,1)+1; 21 | dtr_y=(1-dtr_y)*size(dtr,2)+1; 22 | % Sample image (linear interpolation) 23 | deriv_line_integral=weight*interp2(dtr,dtr_x,dtr_y,'linear',0); 24 | 25 | end % function 26 | -------------------------------------------------------------------------------- /matlab/ecc_demo/line_to_angle_distance.m: -------------------------------------------------------------------------------- 1 | function [alpha t] = line_to_angle_distance(l) 2 | % Length or normal vector 3 | length=norm(l(1:2)); 4 | % Angle between line normal and x-axis 5 | alpha=atan2(l(2),l(1)); 6 | % Distance to the origin (scaled to RDA bins) 7 | t=l(3)/length; 8 | end % function 9 | -------------------------------------------------------------------------------- /matlab/ecc_load_data.m: -------------------------------------------------------------------------------- 1 | % 2 | % Let Octave know the location of some additional functions 3 | % 4 | addpath ("./utility") 5 | addpath ("./ecc_demo") 6 | 7 | % 8 | % Loaing data 9 | % 10 | file_dtr0='./ecc_demo_data/pumpkin/dtr/dtr_V01.nrrd'; 11 | file_dtr1='./ecc_demo_data/pumpkin/dtr/dtr_V13.nrrd'; 12 | file_projection0='./ecc_demo_data/pumpkin/V01.nrrd'; 13 | file_projection1='./ecc_demo_data/pumpkin/V13.nrrd'; 14 | 15 | % Load NRRD files 16 | I0 = nrrdread(file_projection0); 17 | I1 = nrrdread(file_projection1); 18 | [dtr0, meta0] = nrrdread(file_dtr0); 19 | [dtr1, meta1] = nrrdread(file_dtr1); 20 | 21 | % Size of projection image 22 | n_x=str2double(meta0.originalimagewidth); 23 | n_y=str2double(meta0.originalimageheight); 24 | % Number of pixels in original image, to which one bin of radon transform corresponds. 25 | radon_binsize_t= str2double(meta0.stepintercept); 26 | % One over the range of the t-axis of the radon transform in pixels 27 | range_t=size(dtr0,1)*radon_binsize_t; 28 | % Projection matrices 29 | eval(meta0.projectionmatrix); 30 | P0=ans; 31 | eval(meta1.projectionmatrix); 32 | P1=ans; 33 | -------------------------------------------------------------------------------- /matlab/ecc_plot_uv.m: -------------------------------------------------------------------------------- 1 | % range_px Number of pixles to shift u and v (positive and negatvie) 2 | % num_steps Number of step sin each direction (output will be (num_steps+1)x(num_steps+1) ) 3 | % P0, P1 Projection matrices 4 | % n_x, n_y Original image size in pixels 5 | % dtr0, dtr1 Derivatives of Radon transforms of original images 6 | % range_t Range (pixels) of Radon transform. Usually equal to original image diagonal 7 | % dkappa Angular step between epipolar planes. Should be small enough to densely sample RDAs 8 | function consistency_uv = ecc_plot_uv(range_px, num_steps, P0, P1, n_x, n_y, dtr0, dtr1, range_t, dkappa) 9 | 10 | consistency_uv=zeros(2*num_steps+1); 11 | 12 | h = waitbar (0, 'Computing plot (slow!) 0.00%'); 13 | for v_step=-num_steps:num_steps 14 | for u_step=-num_steps:num_steps 15 | progress=((v_step+num_steps)*(2*num_steps+1)+u_step+num_steps)/((2*num_steps+1)*(2*num_steps+1)); 16 | waitbar(progress,h,sprintf('Computing plot (slow!) %.2f%%', 100*progress)) 17 | % Build transformation matrix of image 0 18 | H=diag([1 1 1]); 19 | H(1:2,3)=[ u_step; v_step ].*range_px; 20 | % Compute ECC for transformation H of image 0 21 | consistency_uv(u_step+num_steps+1,v_step+num_steps+1)=ecc_compute_consistency(H*P0, P1, n_x, n_y, dtr0, dtr1, range_t, dkappa); 22 | end % for 23 | end % for 24 | 25 | % Close waitbar 26 | close(h); 27 | 28 | end % function 29 | -------------------------------------------------------------------------------- /matlab/pluecker/join.m: -------------------------------------------------------------------------------- 1 | % line L = point A join point B 2 | function L=join(A, B) 3 | 4 | L=[ 5 | A(1)*B(2)-A(2)*B(1); 6 | A(1)*B(3)-A(3)*B(1); 7 | A(1)*B(4)-A(4)*B(1); 8 | A(2)*B(3)-A(3)*B(2); 9 | A(2)*B(4)-A(4)*B(2); 10 | A(3)*B(4)-A(4)*B(3) 11 | ]; 12 | 13 | end % function -------------------------------------------------------------------------------- /matlab/pluecker/join3.m: -------------------------------------------------------------------------------- 1 | % Plane through three points or point of intersection of three planes 2 | function X=join3(A,B,C) 3 | ABC=[A,B,C]; 4 | X=[ 5 | +det(ABC([2 3 4],:)) 6 | -det(ABC([1 3 4],:)) 7 | +det(ABC([1 2 4],:)) 8 | -det(ABC([1 2 3],:)) 9 | ]; 10 | end % function -------------------------------------------------------------------------------- /matlab/pluecker/meet.m: -------------------------------------------------------------------------------- 1 | % line L = plane P meet plane Q 2 | function L=meet(P, Q) 3 | L=[ 4 | P(3)*Q(4)-P(4)*Q(3); 5 | P(4)*Q(2)-P(2)*Q(4); 6 | P(2)*Q(3)-P(3)*Q(2); 7 | P(1)*Q(4)-P(4)*Q(1); 8 | P(3)*Q(1)-P(1)*Q(3); 9 | P(1)*Q(2)-P(2)*Q(1) 10 | ]; 11 | end % function 12 | -------------------------------------------------------------------------------- /matlab/pluecker/pluecker_closest_point_to_origin.m: -------------------------------------------------------------------------------- 1 | % Compute the closest point of a line to the origin (Lx=pluecker_matrix(L); O=Lx*Lx*[0;0;0;1];) 2 | function O = pluecker_closest_point_to_origin(L) 3 | O=[ L(5)*L(1)+L(2)*L(6); -L(1)*L(3)+L(4)*L(6); -L(2)*L(3)-L(4)*L(5); -L(3)*L(3)-L(5)*L(5)-L(6)*L(6) ]; 4 | end % function 5 | -------------------------------------------------------------------------------- /matlab/pluecker/pluecker_direction.m: -------------------------------------------------------------------------------- 1 | % Direction of a plucker line L 2 | function N=pluecker_direction(L) 3 | N=[-L(3) -L(5) -L(6) 0]'; 4 | end % function 5 | -------------------------------------------------------------------------------- /matlab/pluecker/pluecker_distance_to_origin.m: -------------------------------------------------------------------------------- 1 | % Distance of the line L to the origin 2 | function d=pluecker_distance_to_origin(L) 3 | d=norm(pluecker_moment(L))/norm(pluecker_direction(L)) 4 | end % function 5 | -------------------------------------------------------------------------------- /matlab/pluecker/pluecker_join.m: -------------------------------------------------------------------------------- 1 | % plane P = line L join point X 2 | function P=pluecker_join(L, X) 3 | 4 | P=[ 5 | + X(2)*L(6) - X(3)*L(5) + X(4)*L(4); 6 | - X(1)*L(6) + X(3)*L(3) - X(4)*L(2); 7 | + X(1)*L(5) - X(2)*L(3) + X(4)*L(1); 8 | - X(1)*L(4) + X(2)*L(2) - X(3)*L(1) 9 | ]; 10 | 11 | end % function -------------------------------------------------------------------------------- /matlab/pluecker/pluecker_matrix.m: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aaichert/EpipolarConsistency/8feb718e6b35a943d30684a40e52feb024df91fc/matlab/pluecker/pluecker_matrix.m -------------------------------------------------------------------------------- /matlab/pluecker/pluecker_matrix3.m: -------------------------------------------------------------------------------- 1 | function A=pluecker_matrix3(a) 2 | 3 | A = [ 0 -a(3) a(2); a(3) 0 -a(1); -a(2) +a(1) 0 ]; 4 | 5 | end % function -------------------------------------------------------------------------------- /matlab/pluecker/pluecker_matrix_dual.m: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aaichert/EpipolarConsistency/8feb718e6b35a943d30684a40e52feb024df91fc/matlab/pluecker/pluecker_matrix_dual.m -------------------------------------------------------------------------------- /matlab/pluecker/pluecker_meet.m: -------------------------------------------------------------------------------- 1 | % point X = line L meet plane P 2 | function X=pluecker_meet(L, P) 3 | 4 | X=[ 5 | - P(2)*L(1) - P(3)*L(2) - P(4)*L(3), 6 | + P(1)*L(1) - P(3)*L(4) - P(4)*L(5), 7 | + P(1)*L(2) + P(2)*L(4) - P(4)*L(6), 8 | + P(1)*L(3) + P(2)*L(5) + P(3)*L(6) 9 | ]; 10 | 11 | end % function -------------------------------------------------------------------------------- /matlab/pluecker/pluecker_moment.m: -------------------------------------------------------------------------------- 1 | % Moment of a plucker line L 2 | function N=pluecker_moment(L) 3 | N=[L(4) -L(2) L(1) 0]'; 4 | end % function 5 | -------------------------------------------------------------------------------- /matlab/utility/camera_normalize.m: -------------------------------------------------------------------------------- 1 | % Normalize projection matrix with such that principal vector P(3,1:3) has unit length and points towards image 2 | function P=camera_normalize(P) 3 | % Get length of principal ray 4 | m3n=norm(P(3,1:3)); 5 | % Enforce positivity of determinant 6 | if (det(P(:,1:3))<0) 7 | m3n=-m3n; 8 | end % if 9 | P=P/m3n; 10 | end % function 11 | -------------------------------------------------------------------------------- /matlab/utility/ecc_show_lines.m: -------------------------------------------------------------------------------- 1 | function ecc_show_lines(lines, n_x, n_y, line_color, line_width) 2 | l_left=[1;0;-n_x*0.5]; 3 | l_right=[1;0;n_x*0.5]; 4 | l_bottom=[0;1;-n_y*0.5]; 5 | l_top=[0;1;n_y*0.5]; 6 | for i=1:size(lines,2) 7 | l=lines(:,i); 8 | if l(1)>l(2) 9 | x0=cross(l,l_top); 10 | x1=cross(l,l_bottom); 11 | else 12 | x0=cross(l,l_left); 13 | x1=cross(l,l_right); 14 | end % if 15 | x0=x0./x0(3); 16 | x1=x1./x1(3); 17 | line( [x0(1)+n_x*0.5, x1(1)+n_x*0.5 ], [x0(2)+n_y*0.5, x1(2)+n_y*0.5 ], 'color', line_color , 'linewidth', line_width ); 18 | end % for 19 | 20 | end % function 21 | -------------------------------------------------------------------------------- /matlab/utility/line_stroke.m: -------------------------------------------------------------------------------- 1 | function line_stroke(from, to, color, width) 2 | 3 | if nargin < 2 4 | line( [from(1) to(1) ], [from(2) to(2) ] ); 5 | else if nargin < 3 6 | line( [from(1) to(1) ], [from(2) to(2) ], 'color', color ); 7 | else 8 | line( [from(1) to(1) ], [from(2) to(2) ], 'color', color , 'linewidth', width ); 9 | end % if 10 | 11 | end % function 12 | -------------------------------------------------------------------------------- /tools/ComputeRadonIntermediate/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_executable(ComputeRadonIntermediate 2 | ComputeRadonIntermediate.cpp 3 | ) 4 | target_link_libraries( ComputeRadonIntermediate LibProjectiveGeometry LibEpipolarConsistency LibEpipolarConsistencyGui LibUtilsQt LibUtilsCuda GetSet GetSetGui ) 5 | qt5_use_modules(ComputeRadonIntermediate Widgets Svg OpenGL PrintSupport) 6 | install(TARGETS ComputeRadonIntermediate DESTINATION bin) 7 | qt5_win32_copy_dlls(ComputeRadonIntermediate) 8 | set_property(TARGET ComputeRadonIntermediate PROPERTY FOLDER "Utilities") 9 | -------------------------------------------------------------------------------- /tools/ComputeRadonIntermediate/ComputeRadonIntermediate.cpp: -------------------------------------------------------------------------------- 1 | //#include 2 | //#include 3 | // 4 | //#include 5 | // 6 | //GetSetGui::Application g_app("ComputeRadonIntermediate"); 7 | //EpipolarConsistency::InputDataGui g_data(GetSetGui::Section("File"),&g_app); 8 | // 9 | //void gui(const GetSetInternal::Node& node) 10 | //{ 11 | // g_app.saveSettings(); 12 | //} 13 | // 14 | //int main(int argc, char ** argv) 15 | //{ 16 | // g_data.gui_ignore_notify(true); 17 | // g_app.init(argc,argv,gui); 18 | // g_data.gui_ignore_notify(false); 19 | // return g_app.exec(); 20 | //} 21 | -------------------------------------------------------------------------------- /tools/ConsistencyDemo/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | add_executable( ConsistencyDemo 3 | main.cpp 4 | ) 5 | target_link_libraries( ConsistencyDemo LibProjectiveGeometry LibEpipolarConsistency LibEpipolarConsistencyGui LibUtilsQt GetSet GetSetGui) 6 | qt5_use_modules(ConsistencyDemo Gui Svg OpenGL PrintSupport) 7 | install(TARGETS ConsistencyDemo RUNTIME DESTINATION bin) 8 | set_property(TARGET ConsistencyDemo PROPERTY FOLDER "Utilities") 9 | -------------------------------------------------------------------------------- /tools/FDCTCalibrationCorrection/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | add_executable( FDCTCalibrationCorrection 3 | FDCTCalibrationCorrection.cpp 4 | ) 5 | target_link_libraries( FDCTCalibrationCorrection LibProjectiveGeometry LibEpipolarConsistency LibCudaUtils QCP GetSet GetSetGui LibPlotView ${NLOPT_LIBRARY}) 6 | qt5_use_modules(FDCTCalibrationCorrection Widgets OpenGL PrintSupport) 7 | install(TARGETS FDCTCalibrationCorrection DESTINATION bin) 8 | -------------------------------------------------------------------------------- /tools/FDCTCalibrationCorrection/FDCTCalibrationCorrection.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aaichert/EpipolarConsistency/8feb718e6b35a943d30684a40e52feb024df91fc/tools/FDCTCalibrationCorrection/FDCTCalibrationCorrection.cpp -------------------------------------------------------------------------------- /tools/FDCTMotionCorrection/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_executable( FDCTMotionCorrection 2 | main_gradient_free.cpp 3 | ) 4 | target_link_libraries( FDCTMotionCorrection LibProjectiveGeometry LibEpipolarConsistency LibCudaUtils QCP GetSet GetSetGui ${OPENGL_LIBRARIES} ${NLOPT_LIBRARY}) 5 | qt5_use_modules(FDCTMotionCorrection Widgets OpenGL PrintSupport) 6 | install(TARGETS FDCTMotionCorrection DESTINATION bin) 7 | 8 | -------------------------------------------------------------------------------- /tools/FDCTMotionCorrection/EpipolarConsistencyCalibration.hxx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aaichert/EpipolarConsistency/8feb718e6b35a943d30684a40e52feb024df91fc/tools/FDCTMotionCorrection/EpipolarConsistencyCalibration.hxx -------------------------------------------------------------------------------- /tools/FDCTMotionCorrection/ModelFDCT.hxx: -------------------------------------------------------------------------------- 1 | // Parametrization of a projective 2D or 3D transformation 2 | #include 3 | 4 | namespace Geometry 5 | { 6 | /// Parametrization of motion correction for FDCT 7 | struct ModelFDCT 8 | { 9 | 10 | ModelCameraSimilarity2D3D stencil; //< All projection matrices will abide to this model 11 | int n_active; //< Number of active parameters in stencil 12 | int n_proj; //< Number of projections 13 | 14 | std::vector params; //< Raw parameter vector (remains constant) 15 | std::vector params_delta; //< Raw parameter vector plus those currently being changed 16 | 17 | std::vector trajectory; //< current estimate of the trajectory 18 | 19 | /// Parametrize FDCT trajectory via projective transformation of space and image 20 | ModelFDCT(ModelCameraSimilarity2D3D _stencil) 21 | : stencil(_stencil) 22 | , n_active((int)stencil.getActiveParamIndices().size()) 23 | {} 24 | 25 | /// Apply parameter vector for view i. If view<0, all parameters will be updated. 26 | std::vector& applyModel(int view, const double *delta, const std::vector& Ps) 27 | { 28 | // Make sure we have work space 29 | n_proj=(int)Ps.size(); 30 | if (trajectory.size()!=n_proj) trajectory.resize(n_proj); 31 | if (params.size()!=n_proj*n_active) params=std::vector(n_proj*n_active,0.0); 32 | if (params_delta.size()!=n_proj*n_active) params_delta=std::vector(n_proj*n_active,0.0); 33 | 34 | // Copy delta to params_delta 35 | #pragma omp parallel for 36 | for (int i=0;i 10 | #include 11 | 12 | // Plotting and Visualization 13 | #include 14 | #include 15 | 16 | // Timing cost function evaluations when plotting 17 | #include 18 | 19 | // Utility functions for frequently used loading/visualization routines and GUI. 20 | #include 21 | #include 22 | #include 23 | 24 | // Optimization 25 | #include 26 | 27 | // Parametrization of Transformation 28 | #include 29 | typedef Geometry::ModelCameraSimilarity2D3D ParameterModel; 30 | 31 | GetSetGui::Application g_app("FDCTMotionCompensation"); 32 | -------------------------------------------------------------------------------- /tools/FluoroTracking/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | #remove cuda_ 3 | 4 | cuda_add_executable(FluoroTracking 5 | FluoroTracking.cpp 6 | ) 7 | target_link_libraries( FluoroTracking LibProjectiveGeometry LibEpipolarConsistency LibEpipolarConsistencyGui LibUtilsQt LibUtilsCuda GetSet GetSetGui ${OPENGL_LIBRARIES} ${NLOPT_LIBRARIES}) 8 | qt5_use_modules(FluoroTracking Widgets Svg OpenGL PrintSupport) 9 | install(TARGETS FluoroTracking DESTINATION bin) 10 | qt5_win32_copy_dlls(FluoroTracking) 11 | set_property(TARGET FluoroTracking PROPERTY FOLDER "EpipolarConsistency") 12 | -------------------------------------------------------------------------------- /tools/Registration/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_executable(Registration 2 | Registration.cpp 3 | Registration3D3D.hxx 4 | ) 5 | target_link_libraries( Registration LibProjectiveGeometry LibEpipolarConsistency LibEpipolarConsistencyGui LibUtilsQt LibUtilsCuda GetSet GetSetGui ${OPENGL_LIBRARIES} ${NLOPT_LIBRARIES}) 6 | qt5_use_modules(Registration Widgets Svg OpenGL PrintSupport) 7 | install(TARGETS Registration DESTINATION bin) 8 | set_property(TARGET Registration PROPERTY FOLDER "EpipolarConsistency") 9 | 10 | 11 | cuda_add_executable(RegistrationIntensityBased 12 | RegistrationIntensityBased.cpp 13 | warp3d.cu 14 | ) 15 | target_link_libraries( RegistrationIntensityBased LibProjectiveGeometry LibRayCastBackproject LibUtilsQt LibUtilsCuda GetSet GetSetGui ${OPENGL_LIBRARIES} ${NLOPT_LIBRARIES}) 16 | qt5_use_modules(RegistrationIntensityBased Widgets Svg OpenGL PrintSupport) 17 | install(TARGETS RegistrationIntensityBased DESTINATION bin) 18 | set_property(TARGET RegistrationIntensityBased PROPERTY FOLDER "Utilities") 19 | 20 | -------------------------------------------------------------------------------- /tools/Registration2D3D/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | # Add DRR tool 3 | add_executable(ComputeDRR 4 | ComputeDRR.cpp 5 | ) 6 | target_link_libraries(ComputeDRR GetSet GetSetGui LibSimple LibProjectiveGeometry LibUtilsQt GLAD) 7 | qt5_use_modules(ComputeDRR Gui OpenGL) 8 | install(TARGETS ComputeDRR RUNTIME DESTINATION ".") 9 | 10 | # Add Registration Tool 11 | add_executable(Registration2D3D 12 | Registration2D3D.h 13 | Registration2D3D.cpp 14 | main.cpp 15 | ) 16 | target_link_libraries( Registration2D3D GetSet GetSetGui LibSimple LibProjectiveGeometry LibUtilsQt GLAD) 17 | qt5_use_modules(Registration2D3D Gui OpenGL) 18 | install(TARGETS Registration2D3D RUNTIME DESTINATION ".") -------------------------------------------------------------------------------- /tools/Registration2D3D/Registration2D3D.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aaichert/EpipolarConsistency/8feb718e6b35a943d30684a40e52feb024df91fc/tools/Registration2D3D/Registration2D3D.cpp -------------------------------------------------------------------------------- /tools/Registration2D3D/Registration2D3D.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aaichert/EpipolarConsistency/8feb718e6b35a943d30684a40e52feb024df91fc/tools/Registration2D3D/Registration2D3D.h -------------------------------------------------------------------------------- /tools/TrajectoryView/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | if(MSVC) 2 | set(ICON_RC icon_win.rc icon.ico) 3 | else() 4 | set(ICON_RC "") 5 | endif() 6 | 7 | # The actual TrajectoryView executable 8 | add_executable( TrajectoryView 9 | main_trajectoryview.cpp 10 | ${ICON_RC} 11 | ) 12 | target_link_libraries( TrajectoryView LibProjectiveGeometry LibUtilsQt GetSet GetSetGui) 13 | qt5_use_modules(TrajectoryView Gui Svg OpenGL PrintSupport) 14 | qt5_win32_copy_dlls(TrajectoryView "Core;Gui;Widgets;Svg;OpenGL;PrintSupport") 15 | install(TARGETS TrajectoryView RUNTIME DESTINATION bin) 16 | set_property(TARGET TrajectoryView PROPERTY FOLDER "Utilities") 17 | -------------------------------------------------------------------------------- /tools/TrajectoryView/file.xcf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aaichert/EpipolarConsistency/8feb718e6b35a943d30684a40e52feb024df91fc/tools/TrajectoryView/file.xcf -------------------------------------------------------------------------------- /tools/TrajectoryView/icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aaichert/EpipolarConsistency/8feb718e6b35a943d30684a40e52feb024df91fc/tools/TrajectoryView/icon.ico -------------------------------------------------------------------------------- /tools/TrajectoryView/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aaichert/EpipolarConsistency/8feb718e6b35a943d30684a40e52feb024df91fc/tools/TrajectoryView/icon.png -------------------------------------------------------------------------------- /tools/TrajectoryView/icon_win.aps: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aaichert/EpipolarConsistency/8feb718e6b35a943d30684a40e52feb024df91fc/tools/TrajectoryView/icon_win.aps -------------------------------------------------------------------------------- /tools/TrajectoryView/icon_win.rc: -------------------------------------------------------------------------------- 1 | IDI_ICON1 ICON DISCARDABLE "icon.ico" -------------------------------------------------------------------------------- /tools/VisualizeECC/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | cuda_add_executable(VisualizeECC 3 | draw_epipolar_lines.hxx 4 | VisualizeECC.cpp 5 | ) 6 | target_link_libraries( VisualizeECC LibProjectiveGeometry LibEpipolarConsistency LibEpipolarConsistencyGui LibUtilsQt LibUtilsCuda GetSet GetSetGui ${OPENGL_LIBRARIES} ${NLOPT_LIBRARIES}) 7 | qt5_use_modules(VisualizeECC Widgets Svg OpenGL PrintSupport) 8 | install(TARGETS VisualizeECC DESTINATION bin) 9 | set_property(TARGET VisualizeECC PROPERTY FOLDER "EpipolarConsistency") 10 | 11 | cuda_add_executable(VisualizeECC_RadonIntermediate 12 | draw_epipolar_lines.hxx 13 | VisualizeECC_RadonIntermediate.cpp 14 | ) 15 | target_link_libraries( VisualizeECC_RadonIntermediate LibProjectiveGeometry LibEpipolarConsistency LibEpipolarConsistencyGui LibUtilsQt LibUtilsCuda GetSet GetSetGui ${OPENGL_LIBRARIES} ${NLOPT_LIBRARIES}) 16 | qt5_use_modules(VisualizeECC_RadonIntermediate Widgets Svg OpenGL PrintSupport) 17 | install(TARGETS VisualizeECC_RadonIntermediate DESTINATION bin) 18 | set_property(TARGET VisualizeECC_RadonIntermediate PROPERTY FOLDER "EpipolarConsistency") 19 | 20 | cuda_add_executable(VisualizeECC_ComputedTomography 21 | draw_epipolar_lines.hxx 22 | VisualizeECC_ComputedTomography.cpp 23 | ) 24 | target_link_libraries( VisualizeECC_ComputedTomography LibProjectiveGeometry LibEpipolarConsistency LibEpipolarConsistencyGui LibUtilsQt LibUtilsCuda GetSet GetSetGui ${OPENGL_LIBRARIES} ${NLOPT_LIBRARIES}) 25 | qt5_use_modules(VisualizeECC_ComputedTomography Widgets Svg OpenGL PrintSupport) 26 | install(TARGETS VisualizeECC_ComputedTomography DESTINATION bin) 27 | set_property(TARGET VisualizeECC_ComputedTomography PROPERTY FOLDER "EpipolarConsistency") 28 | -------------------------------------------------------------------------------- /tools/VolumeRendering/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | cuda_add_executable( VolumeRendering 3 | volume_renderer.cpp 4 | ) 5 | target_link_libraries( VolumeRendering LibProjectiveGeometry LibRayCastBackproject LibUtilsCuda LibUtilsQt GetSet GetSetGui) 6 | qt5_use_modules(VolumeRendering Gui ) 7 | install(TARGETS VolumeRendering RUNTIME DESTINATION bin) 8 | set_property(TARGET VolumeRendering PROPERTY FOLDER "Utilities") 9 | 10 | # cuda_add_executable( Reconstruction 11 | # reconstruction.cpp 12 | # ) 13 | # target_link_libraries( Reconstruction LibProjectiveGeometry LibRayCastBackproject LibEpipolarConsistencyGui LibUtilsCuda LibUtilsQt GetSet GetSetGui) 14 | # qt5_use_modules(Reconstruction Gui ) 15 | # install(TARGETS Reconstruction RUNTIME DESTINATION bin) 16 | # set_property(TARGET Reconstruction PROPERTY FOLDER "Utilities") 17 | -------------------------------------------------------------------------------- /tools/nrrdView/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | if(MSVC) 2 | set(ICON_RC icon_win.rc icon.ico) 3 | else() 4 | set(ICON_RC "") 5 | endif() 6 | 7 | add_executable( nrrdView 8 | nrrdView.cpp 9 | ${ICON_RC} 10 | ) 11 | target_link_libraries( nrrdView LibProjectiveGeometry LibUtilsQt GetSet GetSetGui ) 12 | install(TARGETS nrrdView RUNTIME DESTINATION bin) 13 | set_property(TARGET nrrdView PROPERTY FOLDER "Utilities") 14 | -------------------------------------------------------------------------------- /tools/nrrdView/file.xcf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aaichert/EpipolarConsistency/8feb718e6b35a943d30684a40e52feb024df91fc/tools/nrrdView/file.xcf -------------------------------------------------------------------------------- /tools/nrrdView/icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aaichert/EpipolarConsistency/8feb718e6b35a943d30684a40e52feb024df91fc/tools/nrrdView/icon.ico -------------------------------------------------------------------------------- /tools/nrrdView/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aaichert/EpipolarConsistency/8feb718e6b35a943d30684a40e52feb024df91fc/tools/nrrdView/icon.png -------------------------------------------------------------------------------- /tools/nrrdView/icon_win.rc: -------------------------------------------------------------------------------- 1 | IDI_ICON1 ICON DISCARDABLE "icon.ico" -------------------------------------------------------------------------------- /tools/nrrdView/nrrdView.cpp: -------------------------------------------------------------------------------- 1 | // Qt5 2 | #include 3 | #include 4 | 5 | // Utility 6 | #include 7 | 8 | #include 9 | #include 10 | 11 | int main(int argc, char* argv[]) 12 | { 13 | QApplication app(argc,argv); 14 | if (argc==1) { 15 | std::string path=QFileDialog::getOpenFileName(0x0, "Open NRRD Image", "", "NRRD Image (*.nrrd);;All Files (*)").toStdString(); 16 | if (path.empty()) return 2; 17 | NRRD::Image img(path); 18 | if (!img) return 3; 19 | UtilsQt::Figure(path,img); 20 | } 21 | else if (argc==2) { 22 | NRRD::Image img(argv[1]); 23 | if (!img) return 4; 24 | UtilsQt::Figure(argv[1],img); 25 | } 26 | else { 27 | std::cerr << "Usage: nrrdView image.nrrd\n"; 28 | return 0; 29 | } 30 | return app.exec(); 31 | } 32 | -------------------------------------------------------------------------------- /tools/projtable2ompl/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | add_executable(projtable2ompl 3 | projtable2ompl.cpp 4 | ) 5 | target_link_libraries(projtable2ompl LibProjectiveGeometry) 6 | install(TARGETS projtable2ompl RUNTIME DESTINATION bin) 7 | set_property(TARGET projtable2ompl PROPERTY FOLDER "Utilities") 8 | 9 | add_executable(ompl2projtable 10 | ompl2projtable.cpp 11 | ) 12 | target_link_libraries(ompl2projtable LibProjectiveGeometry) 13 | install(TARGETS ompl2projtable RUNTIME DESTINATION bin) 14 | set_property(TARGET ompl2projtable PROPERTY FOLDER "Utilities") 15 | 16 | add_executable(ompl2rtkgeometry 17 | ompl2rtkgeometry.cpp 18 | ) 19 | target_link_libraries(ompl2rtkgeometry LibProjectiveGeometry) 20 | install(TARGETS ompl2rtkgeometry RUNTIME DESTINATION bin) 21 | set_property(TARGET ompl2rtkgeometry PROPERTY FOLDER "Utilities") -------------------------------------------------------------------------------- /tools/projtable2ompl/ompl2projtable.cpp: -------------------------------------------------------------------------------- 1 | 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | int main(int argc, char ** argv) 8 | { 9 | if (argc!=2) return 1; 10 | auto Ps=ProjTable::loadProjectionsOneMatrixPerLine(argv[1]); 11 | ProjTable::saveProjtable(Ps,std::string(argv[1])+".txt"); 12 | return 0; 13 | } 14 | -------------------------------------------------------------------------------- /tools/projtable2ompl/ompl2rtkgeometry.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | 6 | int usage() 7 | { 8 | std::cerr << 9 | "Usage:\n" 10 | " ompl2rtkgeometry file.ompl\n" 11 | " ompl2rtkgeometryfile.ompl --sdd \n" 12 | // " ompl2rtkgeometryfile.ompl --px2mm \n" 13 | ; 14 | return 1; 15 | } 16 | 17 | int main(int argc, char ** argv) 18 | { 19 | double sdd=0; 20 | if (argc == 4) 21 | { 22 | if (argv[2]=="--sdd") 23 | sdd=std::abs(stringTo(argv[3])); 24 | else if (argv[2]=="--px2mm") 25 | { 26 | sdd=-std::abs(stringTo(argv[3])); 27 | std::cerr << "Error: --px2mm not implemented.\n"; 28 | return 2; 29 | } 30 | else usage(); 31 | } 32 | else if (argc!=2) return usage(); 33 | auto Ps=ProjTable::loadProjectionsOneMatrixPerLine(argv[1]); 34 | if (sdd<0 && !Ps.empty()) 35 | { 36 | Eigen::Matrix3d K,R; 37 | Eigen::Vector3d t; 38 | Geometry::projectionMatrixDecomposition(Ps.front(),K,R,t); 39 | sdd*=-0.5*(std::abs(K(0,0))+std::abs(K(1,1))); 40 | } 41 | // ProjTable::saveProjectionsRTK_circular(Ps,std::string(argv[1])+".rtk",sdd); 42 | return 0; 43 | } 44 | -------------------------------------------------------------------------------- /tools/projtable2ompl/projtable2ompl.cpp: -------------------------------------------------------------------------------- 1 | 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | int main(int argc, char ** argv) 8 | { 9 | if (argc!=2) return 1; 10 | auto Ps=ProjTable::loadProjtable(argv[1]); 11 | ProjTable::saveProjectionsOneMatrixPerLine(Ps,std::string(argv[1])+".ompl"); 12 | return 0; 13 | } 14 | --------------------------------------------------------------------------------