├── .gitignore ├── CMakeLists.txt ├── LICENCE ├── README.md ├── config.ini ├── examples ├── Fatcat │ ├── 0.png │ ├── 1.png │ ├── 10.png │ ├── 100.png │ ├── 101.png │ ├── 102.png │ ├── 103.png │ ├── 104.png │ ├── 105.png │ ├── 106.png │ ├── 107.png │ ├── 108.png │ ├── 109.png │ ├── 11.png │ ├── 110.png │ ├── 111.png │ ├── 112.png │ ├── 113.png │ ├── 114.png │ ├── 115.png │ ├── 116.png │ ├── 117.png │ ├── 118.png │ ├── 119.png │ ├── 12.png │ ├── 120.png │ ├── 121.png │ ├── 122.png │ ├── 123.png │ ├── 124.png │ ├── 13.png │ ├── 14.png │ ├── 15.png │ ├── 16.png │ ├── 17.png │ ├── 18.png │ ├── 19.png │ ├── 2.png │ ├── 20.png │ ├── 21.png │ ├── 22.png │ ├── 23.png │ ├── 24.png │ ├── 25.png │ ├── 26.png │ ├── 27.png │ ├── 28.png │ ├── 29.png │ ├── 3.png │ ├── 30.png │ ├── 31.png │ ├── 32.png │ ├── 33.png │ ├── 34.png │ ├── 35.png │ ├── 36.png │ ├── 37.png │ ├── 38.png │ ├── 39.png │ ├── 4.png │ ├── 40.png │ ├── 41.png │ ├── 42.png │ ├── 43.png │ ├── 44.png │ ├── 45.png │ ├── 46.png │ ├── 47.png │ ├── 48.png │ ├── 49.png │ ├── 5.png │ ├── 50.png │ ├── 51.png │ ├── 52.png │ ├── 53.png │ ├── 54.png │ ├── 55.png │ ├── 56.png │ ├── 57.png │ ├── 58.png │ ├── 59.png │ ├── 6.png │ ├── 60.png │ ├── 61.png │ ├── 62.png │ ├── 63.png │ ├── 64.png │ ├── 65.png │ ├── 66.png │ ├── 67.png │ ├── 68.png │ ├── 69.png │ ├── 7.png │ ├── 70.png │ ├── 71.png │ ├── 72.png │ ├── 73.png │ ├── 74.png │ ├── 75.png │ ├── 76.png │ ├── 77.png │ ├── 78.png │ ├── 79.png │ ├── 8.png │ ├── 80.png │ ├── 81.png │ ├── 82.png │ ├── 83.png │ ├── 84.png │ ├── 85.png │ ├── 86.png │ ├── 87.png │ ├── 88.png │ ├── 89.png │ ├── 9.png │ ├── 90.png │ ├── 91.png │ ├── 92.png │ ├── 93.png │ ├── 94.png │ ├── 95.png │ ├── 96.png │ ├── 97.png │ ├── 98.png │ ├── 99.png │ └── local_config.ini └── Star │ ├── 0.png │ ├── 1.png │ ├── 10.png │ ├── 100.png │ ├── 101.png │ ├── 102.png │ ├── 103.png │ ├── 104.png │ ├── 105.png │ ├── 106.png │ ├── 107.png │ ├── 108.png │ ├── 109.png │ ├── 11.png │ ├── 110.png │ ├── 111.png │ ├── 112.png │ ├── 113.png │ ├── 114.png │ ├── 115.png │ ├── 116.png │ ├── 117.png │ ├── 118.png │ ├── 119.png │ ├── 12.png │ ├── 120.png │ ├── 121.png │ ├── 122.png │ ├── 123.png │ ├── 124.png │ ├── 125.png │ ├── 126.png │ ├── 127.png │ ├── 128.png │ ├── 129.png │ ├── 13.png │ ├── 130.png │ ├── 131.png │ ├── 132.png │ ├── 133.png │ ├── 134.png │ ├── 135.png │ ├── 136.png │ ├── 137.png │ ├── 138.png │ ├── 139.png │ ├── 14.png │ ├── 140.png │ ├── 141.png │ ├── 142.png │ ├── 143.png │ ├── 144.png │ ├── 145.png │ ├── 146.png │ ├── 147.png │ ├── 148.png │ ├── 149.png │ ├── 15.png │ ├── 150.png │ ├── 151.png │ ├── 152.png │ ├── 153.png │ ├── 154.png │ ├── 155.png │ ├── 156.png │ ├── 157.png │ ├── 158.png │ ├── 16.png │ ├── 17.png │ ├── 18.png │ ├── 19.png │ ├── 2.png │ ├── 20.png │ ├── 21.png │ ├── 22.png │ ├── 23.png │ ├── 24.png │ ├── 25.png │ ├── 26.png │ ├── 27.png │ ├── 28.png │ ├── 29.png │ ├── 3.png │ ├── 30.png │ ├── 31.png │ ├── 32.png │ ├── 33.png │ ├── 34.png │ ├── 35.png │ ├── 36.png │ ├── 37.png │ ├── 38.png │ ├── 39.png │ ├── 4.png │ ├── 40.png │ ├── 41.png │ ├── 42.png │ ├── 43.png │ ├── 44.png │ ├── 45.png │ ├── 46.png │ ├── 47.png │ ├── 48.png │ ├── 49.png │ ├── 5.png │ ├── 50.png │ ├── 51.png │ ├── 52.png │ ├── 53.png │ ├── 54.png │ ├── 55.png │ ├── 56.png │ ├── 57.png │ ├── 58.png │ ├── 59.png │ ├── 6.png │ ├── 60.png │ ├── 61.png │ ├── 62.png │ ├── 63.png │ ├── 64.png │ ├── 65.png │ ├── 66.png │ ├── 67.png │ ├── 68.png │ ├── 69.png │ ├── 7.png │ ├── 70.png │ ├── 71.png │ ├── 72.png │ ├── 73.png │ ├── 74.png │ ├── 75.png │ ├── 76.png │ ├── 77.png │ ├── 78.png │ ├── 79.png │ ├── 8.png │ ├── 80.png │ ├── 81.png │ ├── 82.png │ ├── 83.png │ ├── 84.png │ ├── 85.png │ ├── 86.png │ ├── 87.png │ ├── 88.png │ ├── 89.png │ ├── 9.png │ ├── 90.png │ ├── 91.png │ ├── 92.png │ ├── 93.png │ ├── 94.png │ ├── 95.png │ ├── 96.png │ ├── 97.png │ ├── 98.png │ ├── 99.png │ └── local_config.ini ├── src ├── Core │ ├── CurveExtractor.cpp │ ├── CurveExtractor.h │ ├── CurveMatcher.cpp │ ├── CurveMatcher.h │ ├── Initializer.cpp │ ├── Initializer.h │ ├── Model.cpp │ ├── Model.h │ ├── Optimizer.h │ ├── View.cpp │ ├── View.h │ └── ViewOptimizer.h ├── DisplayMain.cpp ├── Reconstructor.cpp ├── Reconstructor.h └── Utils │ ├── BezierCurve.cpp │ ├── BezierCurve.h │ ├── Camera.cpp │ ├── Camera.h │ ├── Common.h │ ├── CubeSet.cpp │ ├── CubeSet.h │ ├── FastOpticalFlow │ ├── OFDIS.cpp │ ├── OFDIS.h │ ├── README.md │ ├── image.c │ ├── image.h │ ├── oflow.cpp │ ├── oflow.h │ ├── opticalflow_aux.c │ ├── opticalflow_aux.h │ ├── patch.cpp │ ├── patch.h │ ├── patchgrid.cpp │ ├── patchgrid.h │ ├── refine_variational.cpp │ ├── refine_variational.h │ ├── solver.c │ └── solver.h │ ├── GlobalDataPool.cpp │ ├── GlobalDataPool.h │ ├── Graph.cpp │ ├── Graph.h │ ├── ICP.cpp │ ├── ICP.h │ ├── KMeansClustering.cpp │ ├── KMeansClustering.h │ ├── LSQR │ ├── lsqrBase.cpp │ ├── lsqrBase.h │ ├── lsqrSparse.cpp │ └── lsqrSparse.h │ ├── Loader.cpp │ ├── Loader.h │ ├── Math.cpp │ ├── Math.h │ ├── MeshICP.cpp │ ├── MeshICP.h │ ├── OctreeNew.cpp │ ├── OctreeNew.h │ ├── QuadTree.cpp │ ├── QuadTree.h │ ├── SegmentQuadTree.cpp │ ├── SegmentQuadTree.h │ ├── SimpleRenderer.cpp │ ├── SimpleRenderer.h │ ├── StopWatch.cpp │ ├── StopWatch.h │ ├── Streamer.cpp │ ├── Streamer.h │ ├── SweepSurface.h │ ├── Thinning.h │ ├── Utils.cpp │ └── Utils.h └── static └── teaser.png /.gitignore: -------------------------------------------------------------------------------- 1 | # Prerequisites 2 | *.d 3 | 4 | # Compiled Object files 5 | *.slo 6 | *.lo 7 | *.o 8 | *.obj 9 | 10 | # Precompiled Headers 11 | *.gch 12 | *.pch 13 | 14 | # Compiled Dynamic libraries 15 | *.so 16 | *.dylib 17 | *.dll 18 | 19 | # Fortran module files 20 | *.mod 21 | *.smod 22 | 23 | # Compiled Static libraries 24 | *.lai 25 | *.la 26 | *.a 27 | *.lib 28 | 29 | # Executables 30 | *.exe 31 | *.out 32 | *.app 33 | 34 | # CMake 35 | CMakeCache.txt 36 | CMakeFiles 37 | CMakeScripts 38 | Testing 39 | Makefile 40 | cmake_install.cmake 41 | install_manifest.txt 42 | compile_commands.json 43 | CTestTestfile.cmake 44 | 45 | # Clion 46 | *.idea 47 | cmake-build-debug 48 | *.directory 49 | 50 | # VS-Code 51 | *.vscode 52 | *build 53 | 54 | # ThirdParty 55 | ThirdParty -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.5) 2 | project(ARAP CXX C) 3 | 4 | set(CMAKE_CXX_STANDARD 14) 5 | set(CMAKE_BUILD_TYPE Release) 6 | 7 | # ceres-solver 8 | find_package(Ceres REQUIRED) 9 | include_directories(${CERES_INCLUDE_DIRS}) 10 | 11 | # glog 12 | # find_package(glog REQUIRED) 13 | # include_directories(${GLOG_INCLUDE_DIRS}) 14 | 15 | # OpenCV 16 | find_package(OpenCV REQUIRED) 17 | include_directories(${OpenCV_INCLUDE_DIRS}) 18 | 19 | # OpenMP 20 | find_package(OpenMP) 21 | message(STATUS "OpenMP flags = ${OpenMP_CXX_FLAGS}") 22 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}") 23 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}") 24 | 25 | # Eigen 26 | find_package(Eigen) 27 | include_directories(${Eigen_INCLUDE_DIRS}) 28 | 29 | set(ALL_LIBS glog gomp ${OpenCV_LIBS} ${CERES_LIBRARIES} ${Pangolin_LIBRARIES}) 30 | 31 | # Pangolin 32 | if(DEFINED USE_GUI) 33 | add_definitions(-DUSE_GUI) 34 | find_package(Pangolin REQUIRED) 35 | include_directories(${Pangolin_INCLUDE_DIRS}) 36 | set(ALL_LIBS ${ALL_LIBS} ${Pangolin_LIBRARIES}) 37 | endif() 38 | 39 | file(GLOB LSQR_FILES src/Utils/LSQR/*) 40 | file(GLOB OF_DIS_FILES src/Utils/FastOpticalFlow/*) 41 | file(GLOB CORE_FILES src/Core/*) 42 | file(GLOB UTILS_FILES src/Utils/*) 43 | set(SOURCE_FILES ${OF_DIS_FILES} ${LSQR_FILES} ${CORE_FILES} ${UTILS_FILES}) 44 | 45 | add_executable(Display ${SOURCE_FILES} src/DisplayMain.cpp src/Reconstructor.cpp) 46 | set_target_properties (Display PROPERTIES COMPILE_DEFINITIONS "SELECTMODE=1") 47 | set_property(TARGET Display APPEND PROPERTY COMPILE_DEFINITIONS "SELECTCHANNEL=1") # use grey-valued image 48 | target_link_libraries(Display ${ALL_LIBS}) 49 | 50 | # Test programs. 51 | # include(AddTests.cmake) 52 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # Vid2Curve 4 | 5 | ![](./static/teaser.png) 6 | 7 | This is the reference implementation for thin structure reconstruction from an image sequence. 8 | 9 | ## Dependency 10 | 11 | - OpenCV (4.3.0) 12 | - Boost (1.72.0) 13 | - Ceres solver (1.14.0) 14 | - OpenMP (10.0.0) 15 | - glog (0.4.0) 16 | - Eigen (3.3.7) 17 | - Pangolin (optional, for the visualization of reconstruction process) 18 | 19 | ## Installation 20 | 21 | This project is mainly developed and tested at Manjaro Linux. Please refer to the following steps to accomplish your installation. 22 | 23 | - Clone the repository: 24 | 25 | ```shell 26 | git clone https://github.com/Totoro97/Vid2Curve.git 27 | ``` 28 | 29 | - Then run the following commands: 30 | 31 | ```shell 32 | cd Vid2Curve 33 | mkdir build 34 | cd build 35 | # ----- Default compile setting ----- 36 | cmake .. 37 | make Display 38 | # ----- Or compile with GUI(Pangolin) ----- 39 | cmake .. -DUSE_GUI=1 40 | make Display 41 | ``` 42 | 43 | 44 | 45 | ## Usage 46 | 47 | At the `build` directory, run command `./Display` . 48 | 49 | In the `config.ini` file, you can modify the `DataPath` field for your own use and test. 50 | 51 | The mesh and the curve skeleton will be saved as `curves_mesh.obj` and `curves.obj` at the `build` directory after the reconstruction process is done. And the camera poses will be saved at `cameras.txt` as rotation matrix and translation vectors (from world to camera). 52 | 53 | ## Data Preparation 54 | 55 | In this repository we have prepared two simple [examples](./examples) for your quick validation. For more cases, please refer to the [link](https://drive.google.com/drive/folders/1jGPW8ZlKwg4qX82HWMW9l3pbhrAI0XNn?usp=sharing). 56 | 57 | If you would like to use the project for reconstruction of your own thin objects, please prepare the data as the following steps: 58 | 59 | - Prepare a sequence of segmented binary images (as the examples show). 60 | - 💡The project doesn't provide image distortion function, thus the input images should be undistorted in advance. 61 | - 💡It is hoped that images are captured from different view angles, to gain better reconstruction quality. 62 | - 💡Since the initialization step is rather important, the first several frames are hoped to have as few self-occlusions as possible. 63 | - 💡The recommended resolution of the input images is between `500x500` and `1000x1000`. 64 | - Create a `local_config.ini` file that indicates the internal parameters of the camera and some other information (as the examples show). 65 | 66 | ## Citation 67 | 68 | If you would like to use this project for your own use, please cite: 69 | 70 | ``` 71 | @article{wang2020vid2curve, 72 | title={Vid2Curve: Simultaneous Camera Motion Estimation and Thin Structure Reconstruction from an RGB Video}, 73 | author={Wang, Peng and Liu, Lingjie and Chen, Nenglun and Chu, Hung-Kuo and Theobalt, Christian and Wang, Wenping}, 74 | Journal={ACM Trans. Graph. (SIGGRAPH)}, 75 | year={2020}, 76 | Number={4}, 77 | Volume={38}, 78 | DOI={https://doi.org/10.1145/3386569.3392476}, 79 | Publisher={ACM} 80 | } 81 | ``` 82 | 83 | ## Acknowledgment 84 | 85 | This project also uses the codes from : 86 | 87 | - OF_DIS, for computing optical flow (https://github.com/tikroeger/OF_DIS) 88 | - LSQR, for solving sparse linear system (https://web.stanford.edu/group/SOL/software/lsqr/) 89 | 90 | Thanks for these great implementations. -------------------------------------------------------------------------------- /config.ini: -------------------------------------------------------------------------------- 1 | [Global] 2 | DataPath = ../examples/Fatcat 3 | InitDepth = 1.0 4 | 5 | ShrinkErrorWeight = 0.1 6 | 7 | # Tunable parameters. 8 | 9 | # The smooth weight in the iteration stage. 10 | IteratingSmoothingWeight = 0.1 11 | 12 | # The smooth weight at final stage. 13 | FinalSmoothingWeight = 5.0 14 | 15 | # The smooth weight at estimated radius. 16 | RadiusSmoothingWeight = 10.0 17 | 18 | # The parameter for radius based junction merge. Larger value will make more junctions into one. 19 | # For more details of radius based junction merge, please see: 20 | # Noris, G., Hornung, A., Sumner, R. W., Simmons, M., & Gross, M. (2013). 21 | # Topology-driven vectorization of clean line drawings. ACM Transactions on Graphics (TOG), 32(1), 1-11. 22 | RadiusDilation = 1.0 23 | 24 | [Streamer] 25 | StreamerType = IMAGE_STREAMER 26 | 27 | [CurveExtractor] 28 | ExtractionMethod = NAIVE 29 | UseGPU = 0 30 | 31 | [View] 32 | EmphasizeMissingPaths = 1 33 | 34 | [Model] 35 | UpdatePointsMethod = SPLIT_AND_SOLVE 36 | ViewWeightDistributionType = STD_DEV_THRESHOLD 37 | SolverType = CERES 38 | SmoothMethod = LAPLACIAN 39 | FinalProcessMethod = RADIUS_BASED_MERGE_JUNCTION 40 | AddLostPointsMethod = SEARCH 41 | OutCurveFormat = SWEEP 42 | OutputProcedureMesh = 0 43 | -------------------------------------------------------------------------------- /examples/Fatcat/0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Fatcat/0.png -------------------------------------------------------------------------------- /examples/Fatcat/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Fatcat/1.png -------------------------------------------------------------------------------- /examples/Fatcat/10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Fatcat/10.png -------------------------------------------------------------------------------- /examples/Fatcat/100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Fatcat/100.png -------------------------------------------------------------------------------- /examples/Fatcat/101.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Fatcat/101.png -------------------------------------------------------------------------------- /examples/Fatcat/102.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Fatcat/102.png -------------------------------------------------------------------------------- /examples/Fatcat/103.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Fatcat/103.png -------------------------------------------------------------------------------- /examples/Fatcat/104.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Fatcat/104.png -------------------------------------------------------------------------------- /examples/Fatcat/105.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Fatcat/105.png -------------------------------------------------------------------------------- /examples/Fatcat/106.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Fatcat/106.png -------------------------------------------------------------------------------- /examples/Fatcat/107.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Fatcat/107.png -------------------------------------------------------------------------------- /examples/Fatcat/108.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Fatcat/108.png -------------------------------------------------------------------------------- /examples/Fatcat/109.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Fatcat/109.png -------------------------------------------------------------------------------- /examples/Fatcat/11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Fatcat/11.png -------------------------------------------------------------------------------- /examples/Fatcat/110.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Fatcat/110.png -------------------------------------------------------------------------------- /examples/Fatcat/111.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Fatcat/111.png -------------------------------------------------------------------------------- /examples/Fatcat/112.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Fatcat/112.png -------------------------------------------------------------------------------- /examples/Fatcat/113.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Fatcat/113.png -------------------------------------------------------------------------------- /examples/Fatcat/114.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Fatcat/114.png -------------------------------------------------------------------------------- /examples/Fatcat/115.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Fatcat/115.png -------------------------------------------------------------------------------- /examples/Fatcat/116.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Fatcat/116.png -------------------------------------------------------------------------------- /examples/Fatcat/117.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Fatcat/117.png -------------------------------------------------------------------------------- /examples/Fatcat/118.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Fatcat/118.png -------------------------------------------------------------------------------- /examples/Fatcat/119.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Fatcat/119.png -------------------------------------------------------------------------------- /examples/Fatcat/12.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Fatcat/12.png -------------------------------------------------------------------------------- /examples/Fatcat/120.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Fatcat/120.png -------------------------------------------------------------------------------- /examples/Fatcat/121.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Fatcat/121.png -------------------------------------------------------------------------------- /examples/Fatcat/122.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Fatcat/122.png -------------------------------------------------------------------------------- /examples/Fatcat/123.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Fatcat/123.png -------------------------------------------------------------------------------- /examples/Fatcat/124.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Fatcat/124.png -------------------------------------------------------------------------------- /examples/Fatcat/13.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Fatcat/13.png -------------------------------------------------------------------------------- /examples/Fatcat/14.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Fatcat/14.png -------------------------------------------------------------------------------- /examples/Fatcat/15.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Fatcat/15.png -------------------------------------------------------------------------------- /examples/Fatcat/16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Fatcat/16.png -------------------------------------------------------------------------------- /examples/Fatcat/17.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Fatcat/17.png -------------------------------------------------------------------------------- /examples/Fatcat/18.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Fatcat/18.png -------------------------------------------------------------------------------- /examples/Fatcat/19.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Fatcat/19.png -------------------------------------------------------------------------------- /examples/Fatcat/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Fatcat/2.png -------------------------------------------------------------------------------- /examples/Fatcat/20.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Fatcat/20.png -------------------------------------------------------------------------------- /examples/Fatcat/21.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Fatcat/21.png -------------------------------------------------------------------------------- /examples/Fatcat/22.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Fatcat/22.png -------------------------------------------------------------------------------- /examples/Fatcat/23.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Fatcat/23.png -------------------------------------------------------------------------------- /examples/Fatcat/24.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Fatcat/24.png -------------------------------------------------------------------------------- /examples/Fatcat/25.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Fatcat/25.png -------------------------------------------------------------------------------- /examples/Fatcat/26.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Fatcat/26.png -------------------------------------------------------------------------------- /examples/Fatcat/27.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Fatcat/27.png -------------------------------------------------------------------------------- /examples/Fatcat/28.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Fatcat/28.png -------------------------------------------------------------------------------- /examples/Fatcat/29.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Fatcat/29.png -------------------------------------------------------------------------------- /examples/Fatcat/3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Fatcat/3.png -------------------------------------------------------------------------------- /examples/Fatcat/30.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Fatcat/30.png -------------------------------------------------------------------------------- /examples/Fatcat/31.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Fatcat/31.png -------------------------------------------------------------------------------- /examples/Fatcat/32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Fatcat/32.png -------------------------------------------------------------------------------- /examples/Fatcat/33.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Fatcat/33.png -------------------------------------------------------------------------------- /examples/Fatcat/34.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Fatcat/34.png -------------------------------------------------------------------------------- /examples/Fatcat/35.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Fatcat/35.png -------------------------------------------------------------------------------- /examples/Fatcat/36.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Fatcat/36.png -------------------------------------------------------------------------------- /examples/Fatcat/37.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Fatcat/37.png -------------------------------------------------------------------------------- /examples/Fatcat/38.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Fatcat/38.png -------------------------------------------------------------------------------- /examples/Fatcat/39.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Fatcat/39.png -------------------------------------------------------------------------------- /examples/Fatcat/4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Fatcat/4.png -------------------------------------------------------------------------------- /examples/Fatcat/40.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Fatcat/40.png -------------------------------------------------------------------------------- /examples/Fatcat/41.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Fatcat/41.png -------------------------------------------------------------------------------- /examples/Fatcat/42.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Fatcat/42.png -------------------------------------------------------------------------------- /examples/Fatcat/43.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Fatcat/43.png -------------------------------------------------------------------------------- /examples/Fatcat/44.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Fatcat/44.png -------------------------------------------------------------------------------- /examples/Fatcat/45.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Fatcat/45.png -------------------------------------------------------------------------------- /examples/Fatcat/46.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Fatcat/46.png -------------------------------------------------------------------------------- /examples/Fatcat/47.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Fatcat/47.png -------------------------------------------------------------------------------- /examples/Fatcat/48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Fatcat/48.png -------------------------------------------------------------------------------- /examples/Fatcat/49.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Fatcat/49.png -------------------------------------------------------------------------------- /examples/Fatcat/5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Fatcat/5.png -------------------------------------------------------------------------------- /examples/Fatcat/50.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Fatcat/50.png -------------------------------------------------------------------------------- /examples/Fatcat/51.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Fatcat/51.png -------------------------------------------------------------------------------- /examples/Fatcat/52.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Fatcat/52.png -------------------------------------------------------------------------------- /examples/Fatcat/53.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Fatcat/53.png -------------------------------------------------------------------------------- /examples/Fatcat/54.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Fatcat/54.png -------------------------------------------------------------------------------- /examples/Fatcat/55.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Fatcat/55.png -------------------------------------------------------------------------------- /examples/Fatcat/56.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Fatcat/56.png -------------------------------------------------------------------------------- /examples/Fatcat/57.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Fatcat/57.png -------------------------------------------------------------------------------- /examples/Fatcat/58.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Fatcat/58.png -------------------------------------------------------------------------------- /examples/Fatcat/59.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Fatcat/59.png -------------------------------------------------------------------------------- /examples/Fatcat/6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Fatcat/6.png -------------------------------------------------------------------------------- /examples/Fatcat/60.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Fatcat/60.png -------------------------------------------------------------------------------- /examples/Fatcat/61.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Fatcat/61.png -------------------------------------------------------------------------------- /examples/Fatcat/62.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Fatcat/62.png -------------------------------------------------------------------------------- /examples/Fatcat/63.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Fatcat/63.png -------------------------------------------------------------------------------- /examples/Fatcat/64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Fatcat/64.png -------------------------------------------------------------------------------- /examples/Fatcat/65.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Fatcat/65.png -------------------------------------------------------------------------------- /examples/Fatcat/66.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Fatcat/66.png -------------------------------------------------------------------------------- /examples/Fatcat/67.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Fatcat/67.png -------------------------------------------------------------------------------- /examples/Fatcat/68.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Fatcat/68.png -------------------------------------------------------------------------------- /examples/Fatcat/69.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Fatcat/69.png -------------------------------------------------------------------------------- /examples/Fatcat/7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Fatcat/7.png -------------------------------------------------------------------------------- /examples/Fatcat/70.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Fatcat/70.png -------------------------------------------------------------------------------- /examples/Fatcat/71.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Fatcat/71.png -------------------------------------------------------------------------------- /examples/Fatcat/72.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Fatcat/72.png -------------------------------------------------------------------------------- /examples/Fatcat/73.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Fatcat/73.png -------------------------------------------------------------------------------- /examples/Fatcat/74.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Fatcat/74.png -------------------------------------------------------------------------------- /examples/Fatcat/75.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Fatcat/75.png -------------------------------------------------------------------------------- /examples/Fatcat/76.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Fatcat/76.png -------------------------------------------------------------------------------- /examples/Fatcat/77.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Fatcat/77.png -------------------------------------------------------------------------------- /examples/Fatcat/78.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Fatcat/78.png -------------------------------------------------------------------------------- /examples/Fatcat/79.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Fatcat/79.png -------------------------------------------------------------------------------- /examples/Fatcat/8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Fatcat/8.png -------------------------------------------------------------------------------- /examples/Fatcat/80.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Fatcat/80.png -------------------------------------------------------------------------------- /examples/Fatcat/81.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Fatcat/81.png -------------------------------------------------------------------------------- /examples/Fatcat/82.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Fatcat/82.png -------------------------------------------------------------------------------- /examples/Fatcat/83.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Fatcat/83.png -------------------------------------------------------------------------------- /examples/Fatcat/84.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Fatcat/84.png -------------------------------------------------------------------------------- /examples/Fatcat/85.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Fatcat/85.png -------------------------------------------------------------------------------- /examples/Fatcat/86.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Fatcat/86.png -------------------------------------------------------------------------------- /examples/Fatcat/87.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Fatcat/87.png -------------------------------------------------------------------------------- /examples/Fatcat/88.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Fatcat/88.png -------------------------------------------------------------------------------- /examples/Fatcat/89.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Fatcat/89.png -------------------------------------------------------------------------------- /examples/Fatcat/9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Fatcat/9.png -------------------------------------------------------------------------------- /examples/Fatcat/90.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Fatcat/90.png -------------------------------------------------------------------------------- /examples/Fatcat/91.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Fatcat/91.png -------------------------------------------------------------------------------- /examples/Fatcat/92.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Fatcat/92.png -------------------------------------------------------------------------------- /examples/Fatcat/93.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Fatcat/93.png -------------------------------------------------------------------------------- /examples/Fatcat/94.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Fatcat/94.png -------------------------------------------------------------------------------- /examples/Fatcat/95.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Fatcat/95.png -------------------------------------------------------------------------------- /examples/Fatcat/96.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Fatcat/96.png -------------------------------------------------------------------------------- /examples/Fatcat/97.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Fatcat/97.png -------------------------------------------------------------------------------- /examples/Fatcat/98.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Fatcat/98.png -------------------------------------------------------------------------------- /examples/Fatcat/99.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Fatcat/99.png -------------------------------------------------------------------------------- /examples/Fatcat/local_config.ini: -------------------------------------------------------------------------------- 1 | [Local] 2 | ImgPath = ./ 3 | NumImages = 125 4 | FocalLength = 964.2 5 | Height = 540 6 | Width = 960 7 | -------------------------------------------------------------------------------- /examples/Star/0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/0.png -------------------------------------------------------------------------------- /examples/Star/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/1.png -------------------------------------------------------------------------------- /examples/Star/10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/10.png -------------------------------------------------------------------------------- /examples/Star/100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/100.png -------------------------------------------------------------------------------- /examples/Star/101.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/101.png -------------------------------------------------------------------------------- /examples/Star/102.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/102.png -------------------------------------------------------------------------------- /examples/Star/103.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/103.png -------------------------------------------------------------------------------- /examples/Star/104.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/104.png -------------------------------------------------------------------------------- /examples/Star/105.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/105.png -------------------------------------------------------------------------------- /examples/Star/106.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/106.png -------------------------------------------------------------------------------- /examples/Star/107.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/107.png -------------------------------------------------------------------------------- /examples/Star/108.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/108.png -------------------------------------------------------------------------------- /examples/Star/109.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/109.png -------------------------------------------------------------------------------- /examples/Star/11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/11.png -------------------------------------------------------------------------------- /examples/Star/110.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/110.png -------------------------------------------------------------------------------- /examples/Star/111.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/111.png -------------------------------------------------------------------------------- /examples/Star/112.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/112.png -------------------------------------------------------------------------------- /examples/Star/113.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/113.png -------------------------------------------------------------------------------- /examples/Star/114.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/114.png -------------------------------------------------------------------------------- /examples/Star/115.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/115.png -------------------------------------------------------------------------------- /examples/Star/116.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/116.png -------------------------------------------------------------------------------- /examples/Star/117.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/117.png -------------------------------------------------------------------------------- /examples/Star/118.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/118.png -------------------------------------------------------------------------------- /examples/Star/119.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/119.png -------------------------------------------------------------------------------- /examples/Star/12.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/12.png -------------------------------------------------------------------------------- /examples/Star/120.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/120.png -------------------------------------------------------------------------------- /examples/Star/121.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/121.png -------------------------------------------------------------------------------- /examples/Star/122.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/122.png -------------------------------------------------------------------------------- /examples/Star/123.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/123.png -------------------------------------------------------------------------------- /examples/Star/124.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/124.png -------------------------------------------------------------------------------- /examples/Star/125.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/125.png -------------------------------------------------------------------------------- /examples/Star/126.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/126.png -------------------------------------------------------------------------------- /examples/Star/127.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/127.png -------------------------------------------------------------------------------- /examples/Star/128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/128.png -------------------------------------------------------------------------------- /examples/Star/129.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/129.png -------------------------------------------------------------------------------- /examples/Star/13.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/13.png -------------------------------------------------------------------------------- /examples/Star/130.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/130.png -------------------------------------------------------------------------------- /examples/Star/131.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/131.png -------------------------------------------------------------------------------- /examples/Star/132.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/132.png -------------------------------------------------------------------------------- /examples/Star/133.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/133.png -------------------------------------------------------------------------------- /examples/Star/134.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/134.png -------------------------------------------------------------------------------- /examples/Star/135.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/135.png -------------------------------------------------------------------------------- /examples/Star/136.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/136.png -------------------------------------------------------------------------------- /examples/Star/137.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/137.png -------------------------------------------------------------------------------- /examples/Star/138.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/138.png -------------------------------------------------------------------------------- /examples/Star/139.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/139.png -------------------------------------------------------------------------------- /examples/Star/14.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/14.png -------------------------------------------------------------------------------- /examples/Star/140.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/140.png -------------------------------------------------------------------------------- /examples/Star/141.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/141.png -------------------------------------------------------------------------------- /examples/Star/142.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/142.png -------------------------------------------------------------------------------- /examples/Star/143.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/143.png -------------------------------------------------------------------------------- /examples/Star/144.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/144.png -------------------------------------------------------------------------------- /examples/Star/145.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/145.png -------------------------------------------------------------------------------- /examples/Star/146.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/146.png -------------------------------------------------------------------------------- /examples/Star/147.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/147.png -------------------------------------------------------------------------------- /examples/Star/148.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/148.png -------------------------------------------------------------------------------- /examples/Star/149.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/149.png -------------------------------------------------------------------------------- /examples/Star/15.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/15.png -------------------------------------------------------------------------------- /examples/Star/150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/150.png -------------------------------------------------------------------------------- /examples/Star/151.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/151.png -------------------------------------------------------------------------------- /examples/Star/152.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/152.png -------------------------------------------------------------------------------- /examples/Star/153.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/153.png -------------------------------------------------------------------------------- /examples/Star/154.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/154.png -------------------------------------------------------------------------------- /examples/Star/155.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/155.png -------------------------------------------------------------------------------- /examples/Star/156.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/156.png -------------------------------------------------------------------------------- /examples/Star/157.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/157.png -------------------------------------------------------------------------------- /examples/Star/158.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/158.png -------------------------------------------------------------------------------- /examples/Star/16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/16.png -------------------------------------------------------------------------------- /examples/Star/17.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/17.png -------------------------------------------------------------------------------- /examples/Star/18.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/18.png -------------------------------------------------------------------------------- /examples/Star/19.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/19.png -------------------------------------------------------------------------------- /examples/Star/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/2.png -------------------------------------------------------------------------------- /examples/Star/20.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/20.png -------------------------------------------------------------------------------- /examples/Star/21.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/21.png -------------------------------------------------------------------------------- /examples/Star/22.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/22.png -------------------------------------------------------------------------------- /examples/Star/23.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/23.png -------------------------------------------------------------------------------- /examples/Star/24.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/24.png -------------------------------------------------------------------------------- /examples/Star/25.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/25.png -------------------------------------------------------------------------------- /examples/Star/26.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/26.png -------------------------------------------------------------------------------- /examples/Star/27.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/27.png -------------------------------------------------------------------------------- /examples/Star/28.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/28.png -------------------------------------------------------------------------------- /examples/Star/29.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/29.png -------------------------------------------------------------------------------- /examples/Star/3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/3.png -------------------------------------------------------------------------------- /examples/Star/30.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/30.png -------------------------------------------------------------------------------- /examples/Star/31.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/31.png -------------------------------------------------------------------------------- /examples/Star/32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/32.png -------------------------------------------------------------------------------- /examples/Star/33.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/33.png -------------------------------------------------------------------------------- /examples/Star/34.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/34.png -------------------------------------------------------------------------------- /examples/Star/35.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/35.png -------------------------------------------------------------------------------- /examples/Star/36.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/36.png -------------------------------------------------------------------------------- /examples/Star/37.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/37.png -------------------------------------------------------------------------------- /examples/Star/38.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/38.png -------------------------------------------------------------------------------- /examples/Star/39.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/39.png -------------------------------------------------------------------------------- /examples/Star/4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/4.png -------------------------------------------------------------------------------- /examples/Star/40.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/40.png -------------------------------------------------------------------------------- /examples/Star/41.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/41.png -------------------------------------------------------------------------------- /examples/Star/42.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/42.png -------------------------------------------------------------------------------- /examples/Star/43.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/43.png -------------------------------------------------------------------------------- /examples/Star/44.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/44.png -------------------------------------------------------------------------------- /examples/Star/45.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/45.png -------------------------------------------------------------------------------- /examples/Star/46.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/46.png -------------------------------------------------------------------------------- /examples/Star/47.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/47.png -------------------------------------------------------------------------------- /examples/Star/48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/48.png -------------------------------------------------------------------------------- /examples/Star/49.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/49.png -------------------------------------------------------------------------------- /examples/Star/5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/5.png -------------------------------------------------------------------------------- /examples/Star/50.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/50.png -------------------------------------------------------------------------------- /examples/Star/51.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/51.png -------------------------------------------------------------------------------- /examples/Star/52.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/52.png -------------------------------------------------------------------------------- /examples/Star/53.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/53.png -------------------------------------------------------------------------------- /examples/Star/54.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/54.png -------------------------------------------------------------------------------- /examples/Star/55.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/55.png -------------------------------------------------------------------------------- /examples/Star/56.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/56.png -------------------------------------------------------------------------------- /examples/Star/57.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/57.png -------------------------------------------------------------------------------- /examples/Star/58.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/58.png -------------------------------------------------------------------------------- /examples/Star/59.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/59.png -------------------------------------------------------------------------------- /examples/Star/6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/6.png -------------------------------------------------------------------------------- /examples/Star/60.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/60.png -------------------------------------------------------------------------------- /examples/Star/61.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/61.png -------------------------------------------------------------------------------- /examples/Star/62.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/62.png -------------------------------------------------------------------------------- /examples/Star/63.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/63.png -------------------------------------------------------------------------------- /examples/Star/64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/64.png -------------------------------------------------------------------------------- /examples/Star/65.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/65.png -------------------------------------------------------------------------------- /examples/Star/66.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/66.png -------------------------------------------------------------------------------- /examples/Star/67.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/67.png -------------------------------------------------------------------------------- /examples/Star/68.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/68.png -------------------------------------------------------------------------------- /examples/Star/69.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/69.png -------------------------------------------------------------------------------- /examples/Star/7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/7.png -------------------------------------------------------------------------------- /examples/Star/70.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/70.png -------------------------------------------------------------------------------- /examples/Star/71.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/71.png -------------------------------------------------------------------------------- /examples/Star/72.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/72.png -------------------------------------------------------------------------------- /examples/Star/73.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/73.png -------------------------------------------------------------------------------- /examples/Star/74.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/74.png -------------------------------------------------------------------------------- /examples/Star/75.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/75.png -------------------------------------------------------------------------------- /examples/Star/76.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/76.png -------------------------------------------------------------------------------- /examples/Star/77.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/77.png -------------------------------------------------------------------------------- /examples/Star/78.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/78.png -------------------------------------------------------------------------------- /examples/Star/79.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/79.png -------------------------------------------------------------------------------- /examples/Star/8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/8.png -------------------------------------------------------------------------------- /examples/Star/80.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/80.png -------------------------------------------------------------------------------- /examples/Star/81.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/81.png -------------------------------------------------------------------------------- /examples/Star/82.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/82.png -------------------------------------------------------------------------------- /examples/Star/83.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/83.png -------------------------------------------------------------------------------- /examples/Star/84.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/84.png -------------------------------------------------------------------------------- /examples/Star/85.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/85.png -------------------------------------------------------------------------------- /examples/Star/86.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/86.png -------------------------------------------------------------------------------- /examples/Star/87.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/87.png -------------------------------------------------------------------------------- /examples/Star/88.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/88.png -------------------------------------------------------------------------------- /examples/Star/89.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/89.png -------------------------------------------------------------------------------- /examples/Star/9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/9.png -------------------------------------------------------------------------------- /examples/Star/90.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/90.png -------------------------------------------------------------------------------- /examples/Star/91.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/91.png -------------------------------------------------------------------------------- /examples/Star/92.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/92.png -------------------------------------------------------------------------------- /examples/Star/93.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/93.png -------------------------------------------------------------------------------- /examples/Star/94.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/94.png -------------------------------------------------------------------------------- /examples/Star/95.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/95.png -------------------------------------------------------------------------------- /examples/Star/96.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/96.png -------------------------------------------------------------------------------- /examples/Star/97.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/97.png -------------------------------------------------------------------------------- /examples/Star/98.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/98.png -------------------------------------------------------------------------------- /examples/Star/99.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/examples/Star/99.png -------------------------------------------------------------------------------- /examples/Star/local_config.ini: -------------------------------------------------------------------------------- 1 | [Local] 2 | ImgPath = ./ 3 | NumImages = 159 4 | FocalLength = 964.2 5 | Height = 540 6 | Width = 960 7 | -------------------------------------------------------------------------------- /src/Core/CurveExtractor.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by aska on 2019/3/12. 3 | // 4 | #pragma once 5 | #include 6 | #include 7 | #include "../Utils/Streamer.h" 8 | 9 | // std 10 | #include 11 | 12 | enum SegNoiseType { SHAKING, POLLUTING }; 13 | 14 | struct ImageDirPoint { 15 | public: 16 | ImageDirPoint() = default; 17 | ImageDirPoint(const Eigen::Vector2d &o, const Eigen::Vector2d &v, double score = 1.0, int idx = -1): 18 | o_(o), v_(v), score_(score) {} 19 | Eigen::Vector2d o_, v_; 20 | double score_ = 1.0; 21 | int idx = -1; 22 | }; 23 | 24 | class CurveExtractor { 25 | 26 | public: 27 | CurveExtractor(StreamerBase* streamer, PropertyTree* ptree); 28 | // Deprecated. 29 | CurveExtractor(double *prob_map, int height, int width); 30 | ~CurveExtractor(); 31 | void CalcEstimateRadius(); 32 | 33 | // Method 1: Naive. 34 | // TODO: Better default parameters. 35 | void RunPca(int trunc_r = 3, double r = 3.0); 36 | void RunPcaGPU(int trunc_r = 3, double r = 3.0); 37 | // Method 2: Color difference. 38 | void RunPcaConsideringColor(StreamerBase* streamer); 39 | // Method 3: https://cgl.ethz.ch/Downloads/Publications/Papers/2013/Nor13/Nor13.pdf 40 | void RunGradientBasedExtraction(StreamerBase* streamer); 41 | 42 | std::pair CalcTangAndScore(const Eigen::Vector2d &pix); 43 | 44 | void FindNearestPointsOffline(const std::vector& query_points, 45 | std::vector* nearest_points, 46 | double searching_r = 15.0); 47 | 48 | void CalcEigens(const Eigen::Matrix2d &C, double &l1, double &l2, 49 | Eigen::Vector2d &v1, Eigen::Vector2d &v2); 50 | void SmoothPoints(); 51 | void LinkAll(); 52 | void FilterTooThickPoints(); 53 | void CalcLinkInformation(); 54 | void CalcPaths(); 55 | void GetEdgePoints(std::vector* points); 56 | cv::Mat GetSegImageWithNoise(double shaking_len, 57 | double shaking_ang, 58 | const std::vector& polluted_positions, 59 | double polluted_radius); 60 | cv::Mat GetGaussianNoiseSegmentation(double std_dev = 1.0); 61 | double RadiusAt(double a, double b); 62 | double RadiusAtInt(int a, int b); 63 | double* ConvertImg2ProbMap(const cv::Mat &img); 64 | double ProbAt(double a, double b); 65 | double EstimateR(double base_a, double base_b, double step_a, double step_b); 66 | 67 | public: 68 | // Data. 69 | bool use_gpu_; 70 | bool need_delete_prob_map_; 71 | // TODO: Change it from ptr to std::vector. 72 | double *prob_map_ = nullptr; 73 | std::vector seg_map_; 74 | std::vector candi_points_; 75 | std::vector points_; 76 | std::vector tangs_; 77 | std::vector tang_scores_; 78 | std::vector estimated_rs_; 79 | double average_radius_; 80 | std::vector> link_info_; 81 | std::vector> paths_; 82 | std::vector> edges_; 83 | std::vector> neighbors_; 84 | std::vector near_junction_; 85 | std::vector thick_ratio_; 86 | int height_, width_; 87 | int n_points_; 88 | int id_ = -1; 89 | PropertyTree* ptree_; 90 | 91 | }; 92 | 93 | // ------------------------ Declaration for GPU methods ---------------------- 94 | 95 | void CudaPca(int height, int width, double* prob_map, double* out_data_pool); 96 | 97 | void CudaPcaConsideringColor(int height, int width, int radius, uchar* img_data, double* out_data_pool); 98 | -------------------------------------------------------------------------------- /src/Core/CurveMatcher.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by aska on 2019/3/6. 3 | // 4 | #pragma once 5 | #include "CurveExtractor.h" 6 | #include 7 | #include 8 | #include 9 | 10 | using Vector3d = Eigen::Vector3d; 11 | using Vector2d = Eigen::Vector2d; 12 | 13 | // Local Core in image coordinate system. 14 | struct ImageLocalMatching { 15 | ImageLocalMatching(const ImageDirPoint &p, 16 | const ImageDirPoint &q) : p(p), q(q) {} 17 | ImageDirPoint p; 18 | ImageDirPoint q; 19 | }; 20 | 21 | struct TangCostFunctor { 22 | TangCostFunctor(const Eigen::Vector3d &P, 23 | const Eigen::Vector3d &Q, 24 | const Eigen::Vector3d &N, 25 | const Eigen::Vector3d &M) : P_(P), Q_(Q), N_(N), M_(M) {} 26 | bool operator() (const double *const parameters, double *residual) const { 27 | // residual[0] = (10 - parameters[0]) * (10 - parameters[0]) + parameters[0] * parameters[0]; 28 | // return true; 29 | Eigen::Matrix3d R; 30 | R = Eigen::AngleAxisd(parameters[0], Vector3d::UnitX()) * 31 | Eigen::AngleAxisd(parameters[1], Vector3d::UnitY()) * 32 | Eigen::AngleAxisd(parameters[2], Vector3d::UnitZ()); 33 | double x = parameters[3]; 34 | double y = parameters[4]; 35 | Eigen::Vector3d T(std::cos(x) * std::sin(y), std::cos(x) * std::cos(y), std::sin(x)); 36 | residual[0] = (R * P_).cross(Q_).dot(T); 37 | return true; 38 | double t = (Q_ - T).dot(N_) / ((R * P_).dot(N_) + 1e-9); 39 | residual[0] = (t * R * P_ + T - Q_).dot(M_); 40 | return true; 41 | } 42 | 43 | private: 44 | Eigen::Vector3d P_, Q_, N_, M_; 45 | }; 46 | 47 | // Matcher should be more global. 48 | class CurveMatcher { 49 | public: 50 | // Methods 51 | CurveMatcher(int height, int width, double *prob_map_0, double *prob_map_1); 52 | CurveMatcher(CurveExtractor *extractor_0, 53 | CurveExtractor *extractor_1); 54 | ~CurveMatcher(); 55 | 56 | void FindLocalCurveMatching(std::vector>& matchings); 57 | std::pair FindMatching(Eigen::Vector2d pix); 58 | void EstimateRT(double focal_length, 59 | const std::string& method, 60 | std::vector>* poses); 61 | void FindMatchings(const std::string &method, std::vector* matchings, 62 | bool show_debug_message = false); 63 | void FindMatchingsByOpticalFlow(std::vector* matchings); 64 | void FindMatchingsByDP(std::vector* matchings); 65 | bool ValidateCandiCurves(); 66 | 67 | void ShowDebugInfo(); 68 | 69 | int height_, width_; 70 | double *prob_map_0_, *prob_map_1_; 71 | CurveExtractor *extractor_0_, *extractor_1_; 72 | cv::Mat img_0_, img_1_; 73 | cv::Mat flow_img_; 74 | }; 75 | -------------------------------------------------------------------------------- /src/Core/Initializer.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by aska on 2019/9/4. 3 | // 4 | 5 | #include "Initializer.h" 6 | 7 | #include "../Utils/Utils.h" 8 | 9 | Initializer::Initializer( 10 | const std::vector &curve_extractors, 11 | double focal_length, 12 | double width, 13 | double height, 14 | double single_depth_error_weight, 15 | double relative_depth_error_weight) : 16 | curve_extractors_(curve_extractors), 17 | focal_length_(focal_length), 18 | width_(width), 19 | height_(height), 20 | single_depth_error_weight_(single_depth_error_weight), 21 | relative_depth_error_weight_(relative_depth_error_weight) { 22 | } 23 | 24 | // Estimate camera pose candidates and initial points by several frames. 25 | // Currently we only support two frames as input. 26 | void Initializer::GetInitialModelData(std::vector>* model_states) { 27 | model_states->clear(); 28 | CHECK_EQ(curve_extractors_.size(), 2); 29 | CurveExtractor* extractor_0 = curve_extractors_[0]; 30 | CurveExtractor* extractor_1 = curve_extractors_[1]; 31 | auto curve_matcher = std::make_unique(extractor_0, extractor_1); 32 | std::vector matchings; 33 | curve_matcher->FindMatchings("DP", &matchings); 34 | CHECK(!matchings.empty()); 35 | 36 | const double kTranslationBias = 0.01; 37 | double camera_poses[6] = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }; 38 | const double kInitialDepth = 1.0; 39 | std::vector depths(extractor_0->n_points_, kInitialDepth); 40 | auto RandLR = [](double L, double R) { 41 | return L + (double) rand() / (double) RAND_MAX * (R - L); 42 | }; 43 | double average_trans = 0.0; 44 | for (int x = -1; x <= 1; x++) { 45 | for (int y = -1; y <= 1; y++) { 46 | for (int z = 0; z <= 0; z++) { 47 | // Initialization. 48 | for (int i = 0; i < extractor_0->n_points_; i++) { 49 | depths[i] = kInitialDepth; 50 | } 51 | // std::fill(depths.begin(), depths.end(), kInitialDepth * RandLR(0.9, 1.1)); 52 | camera_poses[3] = x * kTranslationBias; 53 | camera_poses[4] = y * kTranslationBias; 54 | camera_poses[5] = z * kTranslationBias; 55 | for (int i = 0; i < 3; i++) { 56 | camera_poses[i] = 0.0; 57 | } 58 | 59 | // Problem registration. 60 | ceres::Problem problem; 61 | for (const auto& matching : matchings) { 62 | ceres::CostFunction* cost_function = 63 | ProjectionError::Create(matching, (matching.q.score_ - 1.0) * (-2.0), focal_length_, width_, height_); 64 | problem.AddResidualBlock(cost_function, nullptr, camera_poses, depths.data() + matching.p.idx); 65 | } 66 | 67 | double final_single_depth_error_weight = 68 | single_depth_error_weight_ / kInitialDepth * focal_length_ * matchings.size() / extractor_0->n_points_; 69 | for (int i = 0; i < extractor_0->n_points_; i++) { 70 | ceres::CostFunction* cost_function = SingleDepthError::Create(kInitialDepth, final_single_depth_error_weight); 71 | problem.AddResidualBlock(cost_function, nullptr, depths.data() + i); 72 | } 73 | 74 | double final_relative_depth_error_weight = 75 | relative_depth_error_weight_ / kInitialDepth * focal_length_ * 76 | matchings.size() / (double) extractor_0->n_points_; 77 | if (final_relative_depth_error_weight > 1e-9) { 78 | for (const auto& path : extractor_0->paths_) { 79 | for (int i = 0; i + 1 < path.size(); i++) { 80 | ceres::CostFunction *cost_function = 81 | RelativeDepthError::Create(final_relative_depth_error_weight); 82 | problem.AddResidualBlock(cost_function, 83 | nullptr, 84 | depths.data() + path[i], 85 | depths.data() + path[i + 1]); 86 | } 87 | } 88 | } 89 | 90 | // Solve & Optimization. 91 | ceres::Solver::Options options; 92 | options.linear_solver_type = ceres::DENSE_SCHUR; 93 | options.minimizer_progress_to_stdout = false; 94 | ceres::Solver::Summary summary; 95 | ceres::Solve(options, &problem, &summary); 96 | LOG(INFO) << camera_poses[3] << " " << camera_poses[4] << " " << camera_poses[5]; 97 | double ave_depth = 0.0; 98 | for (double depth : depths) { 99 | ave_depth += depth; 100 | } 101 | LOG(INFO) << "ave depth:" << ave_depth / depths.size(); 102 | 103 | Eigen::Matrix3d R; 104 | Eigen::Vector3d angle_axis(camera_poses[0], camera_poses[1], camera_poses[2]); 105 | R = Eigen::AngleAxisd(angle_axis.norm(), angle_axis / angle_axis.norm()); 106 | Eigen::Vector3d T(camera_poses[3], camera_poses[4], camera_poses[5]); 107 | double trans_len = T.norm() / (ave_depth / depths.size()); 108 | LOG(INFO) << "trans len: " << trans_len; 109 | bool is_redundant = false; 110 | const double kMinDifferentTranslationThreshold = 0.01; 111 | for (const auto& model_state : *model_states) { 112 | if ((model_state->camera_poses.back().second - T).norm() < kMinDifferentTranslationThreshold) { 113 | is_redundant = true; 114 | break; 115 | } 116 | } 117 | if (is_redundant) { 118 | continue; 119 | } 120 | 121 | // Add to model state. 122 | average_trans += trans_len; 123 | model_states->emplace_back(new ModelData()); 124 | ModelData* new_model_state = model_states->back().get(); 125 | 126 | new_model_state->curve_extractors.emplace_back(extractor_0); 127 | new_model_state->curve_extractors.emplace_back(extractor_1); 128 | 129 | new_model_state->camera_poses.emplace_back(Eigen::Matrix3d::Identity(), Eigen::Vector3d::Zero()); 130 | new_model_state->camera_poses.emplace_back(R, T); 131 | 132 | CHECK_EQ(extractor_0->n_points_, depths.size()); 133 | for (int i = 0; i < extractor_0->n_points_; i++) { 134 | new_model_state->points.emplace_back( 135 | Utils::ImageCoordToCamera(extractor_0->candi_points_[i].o_, height_, width_, focal_length_) * depths[i]); 136 | } 137 | } 138 | } 139 | } 140 | average_trans /= model_states->size(); 141 | if (average_trans < 0.03) { 142 | model_states->clear(); 143 | } 144 | LOG(INFO) << "Initialize: Totally " << model_states->size() << " pose candidates."; 145 | } -------------------------------------------------------------------------------- /src/Core/Initializer.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by aska on 2019/9/4. 3 | // 4 | #pragma once 5 | #include "Model.h" 6 | #include "CurveExtractor.h" 7 | #include "CurveMatcher.h" 8 | #include "../Utils/Common.h" 9 | 10 | // ceres solver 11 | #include 12 | #include 13 | 14 | const double kTangErrorWeight = 0.2; 15 | 16 | // error setting for ceres. 17 | struct ProjectionError { 18 | ProjectionError(const ImageLocalMatching& matching, 19 | double weight, 20 | double focal_length, 21 | double width, 22 | double height) { 23 | weight_ = std::max(kTangErrorWeight, weight); 24 | focal_length_ = focal_length; 25 | p_x_ = matching.p.o_(1) - width * 0.5; 26 | p_y_ = matching.p.o_(0) - height * 0.5; 27 | q_x_ = matching.q.o_(1) - width * 0.5; 28 | q_y_ = matching.q.o_(0) - height * 0.5; 29 | dir_x_ = matching.q.v_(1); 30 | dir_y_ = matching.q.v_(0); 31 | } 32 | 33 | template 34 | bool operator()(const T* const camera, 35 | const T* const depth, 36 | T* residuals) const { 37 | T point[3]; 38 | point[0] = T(p_x_) * *depth / T(focal_length_); 39 | point[1] = T(p_y_) * *depth / T(focal_length_); 40 | point[2] = *depth; 41 | T p[3]; 42 | // camera[0,1,2] are the angle-axis rotation. 43 | ceres::AngleAxisRotatePoint(camera, point, p); 44 | // camera[3,4,5] are the translation. 45 | p[0] += camera[3]; p[1] += camera[4]; p[2] += camera[5]; 46 | 47 | T bias_x = p[0] / p[2] * T(focal_length_) - T(q_x_); 48 | T bias_y = p[1] / p[2] * T(focal_length_) - T(q_y_); 49 | 50 | residuals[0] = bias_x * T(dir_y_) - bias_y * T(dir_x_); 51 | residuals[1] = (bias_x * T(dir_x_) + bias_y * T(dir_y_)) * T(weight_); 52 | return true; 53 | } 54 | 55 | // Factory to hide the construction of the CostFunction object from 56 | // the client code. 57 | static ceres::CostFunction* Create(const ImageLocalMatching& matching, 58 | double weight, 59 | double focal_length, 60 | double width, 61 | double height) { 62 | // LOG(INFO) << "weight: " << weight; 63 | return (new ceres::AutoDiffCostFunction( 64 | new ProjectionError(matching, weight, focal_length, width, height))); 65 | } 66 | 67 | double weight_; 68 | double focal_length_; 69 | double p_x_, p_y_; 70 | double q_x_, q_y_; 71 | double dir_x_, dir_y_; 72 | }; 73 | 74 | struct SingleDepthError { 75 | explicit SingleDepthError(double hope_depth = 1.0, double weight = 1.0) : hope_depth_(hope_depth), weight_(weight) {} 76 | 77 | template 78 | bool operator()(const T* const depth, 79 | T* residuals) const { 80 | residuals[0] = (*depth - T(hope_depth_)) * T(weight_); 81 | return true; 82 | } 83 | 84 | static ceres::CostFunction* Create(double hope_depth = 1.0, double weight = 1.0) { 85 | return (new ceres::AutoDiffCostFunction(new SingleDepthError(hope_depth, weight))); 86 | } 87 | 88 | double hope_depth_ = 1.0; 89 | double weight_ = 1.0; 90 | }; 91 | 92 | struct RelativeDepthError { 93 | explicit RelativeDepthError(double weight = 1.0) : weight_(weight) {} 94 | 95 | template 96 | bool operator()(const T* const depth_0, 97 | const T* const depth_1, 98 | T* residuals) const { 99 | residuals[0] = (*depth_0 - *depth_1) * T(weight_); 100 | return true; 101 | } 102 | 103 | static ceres::CostFunction* Create(double weight = 1.0) { 104 | return (new ceres::AutoDiffCostFunction(new RelativeDepthError(weight))); 105 | } 106 | 107 | double weight_ = 1.0; 108 | }; 109 | 110 | class Initializer { 111 | public: 112 | Initializer(const std::vector& curve_extractors, 113 | double focal_length, 114 | double width, 115 | double height, 116 | double single_depth_error_weight, 117 | double relative_depth_error_weight); 118 | void GetInitialModelData(std::vector>* model_states); 119 | 120 | private: 121 | std::vector curve_extractors_; 122 | double focal_length_; 123 | double width_; 124 | double height_; 125 | double single_depth_error_weight_ = 0.01; 126 | double relative_depth_error_weight_ = 0.05; 127 | }; 128 | -------------------------------------------------------------------------------- /src/Core/Model.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by aska on 2019/4/21. 3 | // 4 | #pragma once 5 | #include "Optimizer.h" 6 | #include "CurveExtractor.h" 7 | #include "View.h" 8 | #include "../Utils/GlobalDataPool.h" 9 | #include "../Utils/Graph.h" 10 | #include "../Utils/OctreeNew.h" 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | enum SolverType { LSQR, CERES, CERES_BEZIER }; 17 | enum ViewWeightDistributionType { STD_DEV_THRESHOLD, STD_DEV, UNIFORM }; 18 | enum ModelState { INITIALIZING, ITERATING }; 19 | 20 | struct ModelData { 21 | std::vector curve_extractors; 22 | std::vector> camera_poses; 23 | std::vector points; 24 | std::vector tangs; 25 | std::vector tang_scores; 26 | }; 27 | 28 | class Model { 29 | public: 30 | Model(ModelData* model_sate, const PropertyTree &ptree, GlobalDataPool* global_data_pool); 31 | ~Model(); 32 | void SetParameters(const PropertyTree &ptree); 33 | double Score(); 34 | void EstimateHopeDist(); 35 | void FeedExtractor(CurveExtractor *extractor); 36 | void FeedExtractor(CurveExtractor *extractor, const Eigen::Matrix3d &R, const Eigen::Vector3d &T); 37 | void Update(); 38 | 39 | double UpdatePoints(bool use_linked_paths = false, Graph* graph = nullptr, Graph* tree = nullptr); 40 | double UpdatePointsGlobal(); 41 | double UpdatePointsSplitAndSolve(bool use_linked_paths = false, 42 | Graph* graph = nullptr, 43 | Graph* tree = nullptr); 44 | double UpdatePointsSingleComponent(const std::vector& indexes, 45 | const std::vector& weights, 46 | std::vector* solutions); 47 | void GetControlIndexes(const std::vector& indexes, std::vector* control_indexes); 48 | void PathsSmoothing(); 49 | void Update3DRadius(double extend_2d_radius = 0.0); 50 | void RadiusSmoothing(Graph* graph = nullptr); 51 | void RecoverUncertainRadius(Graph* graph); 52 | 53 | void GetSinglePointViewWeight(int pt_idx, std::vector>* weighted_views); 54 | double GetSinglePoint3dRadius(int pt_idx); 55 | void MoveModelPointsToCenter(); 56 | void UpdateViews(); 57 | double MissingRatio(); 58 | void UpdateTangs(Graph* graph = nullptr); 59 | void DeleteOutliers(); 60 | 61 | // Functions for adding missing/lost points; 62 | void AddLostPoints(); 63 | void AddLostPointsByDenseVoxel(); 64 | void AddLostPointsBySearch(); 65 | void GetDepthCandidatesByWorldRay(const Eigen::Vector3d& o, 66 | const Eigen::Vector3d& v, 67 | double d_min, 68 | double d_max, 69 | std::vector* depth_candidates); 70 | void AddLostPointsByDepthSampling(); 71 | double FindBestDepthByWorldRay(const Eigen::Vector3d& o, 72 | const Eigen::Vector3d& v, 73 | double initial_depth, 74 | double d_min, 75 | double d_max); 76 | 77 | void RefinePoints(); 78 | void FinalProcess(const std::string& out_file_name = "curves"); 79 | void OutputFinalModel(Graph* graph, const std::string& out_file_name = "curves"); 80 | SelfDefinedGraph* MergeJunction(); 81 | IronTown* RadiusBasedMergeJunction(); 82 | void UpdateSpanningTree(); 83 | void UpdateDataStructure(bool update_3d_radius = true); 84 | void UpdateOctree(); 85 | void AdjustPoints(Graph* graph); 86 | bool IsTrackingGood(); 87 | bool IsCameraMovementSufficient(); 88 | bool IsCameraMotionSimilar(Model* ano_model); 89 | bool IsSinglePointFeasible(const Eigen::Vector3d& point, 90 | double single_view_max_error = 2.0, 91 | double ave_max_error = 1.5); 92 | bool IsSinglePointVisible(const Eigen::Vector3d& point); 93 | // Before using this fuction, pls make sure hitmap of each view has been refreshed. 94 | bool IsSinglePointNeeded(const Eigen::Vector3d& point); 95 | void ShowModelPoints(); 96 | void ShowCameras(); 97 | void OutputProcedureMesh(); 98 | 99 | std::vector points_; 100 | std::vector tangs_; 101 | std::vector points_history_; 102 | std::vector tang_scores_; 103 | std::vector points_radius_3d_; 104 | std::vector points_feasible_; 105 | std::vector> view_pools_; 106 | std::vector views_; // active views; 107 | int global_view_ticker_ = -1; 108 | int global_iter_num_ = 0; 109 | int n_points_; 110 | double focal_length_; 111 | double init_depth_; 112 | double hope_dist_; 113 | 114 | // Data structures. 115 | OctreeNew* octree_ = nullptr; 116 | GlobalDataPool* global_data_pool_ = nullptr; 117 | IronTown* curve_network_ = nullptr; 118 | SpanningTree* spanning_tree_ = nullptr; 119 | 120 | // For last tracking. 121 | Eigen::Matrix3d last_R_; 122 | Eigen::Vector3d last_T_; 123 | // state flags. 124 | bool is_last_view_keyframe_ = false; 125 | bool is_tracking_good_ = false; 126 | 127 | // parameters. 128 | double gather_weight_ = 0.0; 129 | double hope_dist_weight_ = 1.0; 130 | double final_smoothing_weight_ = 1.0; 131 | double shrink_error_weight_ = 1.0; 132 | double radius_dilation_ = 1.0; 133 | double radius_smoothing_weight_ = 1.0; 134 | double topology_searching_radius_ = 5.0; 135 | std::string update_points_method_ = "SPLIT_AND_SOLVE"; 136 | std::string smooth_method_ = "LAPLACIAN"; 137 | std::string out_curve_format_ = "SWEEP"; 138 | std::string final_process_method_ = "RADIUS_BASED_MERGE_JUNCTION"; 139 | std::string add_lost_points_method_ = "DP"; 140 | bool output_procedure_mesh_ = false; 141 | bool is_model_feasible_ = true; 142 | TrackType track_type_ = TrackType::MATCHING_OF; 143 | SolverType solver_type_ = SolverType::CERES; 144 | ModelState model_state_ = ModelState::INITIALIZING; 145 | ViewWeightDistributionType view_weight_distribution_type_ = ViewWeightDistributionType::STD_DEV_THRESHOLD; 146 | }; 147 | 148 | // For ceres solver. 149 | -------------------------------------------------------------------------------- /src/Core/ViewOptimizer.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by aska on 2020/3/2. 3 | // 4 | 5 | #include "../Utils/Common.h" 6 | // ceres solver 7 | #include 8 | #include 9 | 10 | const double kViewTangErrorWeight = 0.5; 11 | 12 | struct ViewProjectionError { 13 | ViewProjectionError(const Eigen::Vector3d& world_pt, 14 | const Eigen::Vector2d& img_pt, 15 | const Eigen::Vector2d& img_tang, 16 | double weight, 17 | double focal_length, 18 | double width, 19 | double height) { 20 | weight_ = std::max(kViewTangErrorWeight, weight); 21 | focal_length_ = focal_length; 22 | world_x_ = world_pt(0); 23 | world_y_ = world_pt(1); 24 | world_z_ = world_pt(2); 25 | p_x_ = img_pt(1) - width * 0.5; 26 | p_y_ = img_pt(0) - height * 0.5; 27 | dir_x_ = img_tang(1); 28 | dir_y_ = img_tang(0); 29 | } 30 | 31 | template 32 | bool operator()(const T* const camera, 33 | T* residuals) const { 34 | T point[3]; 35 | point[0] = T(world_x_); 36 | point[1] = T(world_y_); 37 | point[2] = T(world_z_); 38 | T p[3]; 39 | // camera[0,1,2] are the angle-axis rotation. 40 | ceres::AngleAxisRotatePoint(camera, point, p); 41 | // camera[3,4,5] are the translation. 42 | p[0] += camera[3]; p[1] += camera[4]; p[2] += camera[5]; 43 | 44 | T bias_x = p[0] / p[2] * T(focal_length_) - T(p_x_); 45 | T bias_y = p[1] / p[2] * T(focal_length_) - T(p_y_); 46 | 47 | residuals[0] = (bias_x * T(dir_y_) - bias_y * T(dir_x_)) * T(weight_); 48 | residuals[1] = (bias_x * T(dir_x_) + bias_y * T(dir_y_)) * T(weight_ * kViewTangErrorWeight); 49 | return true; 50 | } 51 | 52 | // Factory to hide the construction of the CostFunction object from 53 | // the client code. 54 | static ceres::CostFunction* Create(const Eigen::Vector3d& world_pt, 55 | const Eigen::Vector2d& img_pt, 56 | const Eigen::Vector2d& img_tang, 57 | double weight, 58 | double focal_length, 59 | double width, 60 | double height) { 61 | // LOG(INFO) << "weight: " << weight; 62 | return (new ceres::AutoDiffCostFunction( 63 | new ViewProjectionError(world_pt, img_pt, img_tang, weight, focal_length, width, height))); 64 | } 65 | 66 | double weight_; 67 | double focal_length_; 68 | double p_x_, p_y_; 69 | double dir_x_, dir_y_; 70 | double world_x_, world_y_, world_z_; 71 | }; 72 | -------------------------------------------------------------------------------- /src/DisplayMain.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by aska on 2019/9/26. 3 | // 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | #ifdef USE_GUI 10 | #include 11 | #endif 12 | 13 | #include "Reconstructor.h" 14 | #include "Utils/Common.h" 15 | #include "Utils/GlobalDataPool.h" 16 | 17 | int main(int argc, char* argv[]) { 18 | google::InitGoogleLogging(argv[0]); 19 | FLAGS_logtostderr = true; 20 | FLAGS_minloglevel = 3; // LOG level: 3 -> FATAL 21 | LOG(INFO) << "Hello Wooden!"; 22 | 23 | #ifdef USE_GUI 24 | // Build Global data pool 25 | auto global_data_pool = std::make_unique(); 26 | 27 | // Build Reconstructor 28 | auto reconstructor = std::make_unique("../config.ini", global_data_pool.get()); 29 | std::thread reconstruct_worker(&Reconstructor::Run, reconstructor.get()); 30 | 31 | // Create OpenGL window in single line 32 | pangolin::CreateWindowAndBind("Main", 640, 480); 33 | 34 | glEnable(GL_DEPTH_TEST); 35 | 36 | pangolin::OpenGlRenderState s_cam( 37 | pangolin::ProjectionMatrix(640,480,420,420,320,240,0.1,1000), 38 | pangolin::ModelViewLookAt(-1,1,-1, 0,0,0, pangolin::AxisY)); 39 | 40 | pangolin::View& d_cam = pangolin::Display("cam") 41 | .SetBounds(0,1.0f,0,1.0f,-640/480.0) 42 | .SetHandler(new pangolin::Handler3D(s_cam)); 43 | 44 | pangolin::View& d_image = pangolin::Display("image") 45 | .SetBounds(3/4.0f,1.0f,0,1/4.0f, double(reconstructor->width_) / reconstructor->height_) 46 | .SetLock(pangolin::LockLeft, pangolin::LockBottom); 47 | 48 | pangolin::GlTexture image_texture(reconstructor->width_, 49 | reconstructor->height_, 50 | GL_RGB, 51 | false, 52 | 0, 53 | GL_RGB, 54 | GL_UNSIGNED_BYTE); 55 | 56 | while(!pangolin::ShouldQuit() && reconstructor->state_ == Reconstructor::State::RUNNING) { 57 | glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); 58 | 59 | d_cam.Activate(s_cam); 60 | 61 | // Draw cameras. 62 | global_data_pool->DrawCameras(); 63 | 64 | // Draw points. 65 | pangolin::GlBuffer glxyz(pangolin::GlArrayBuffer, global_data_pool->n_points(), GL_FLOAT, 3, GL_DYNAMIC_DRAW); 66 | 67 | glColor3f(1.0, 1.0, 1.0); 68 | global_data_pool->DrawModelPoints(&glxyz); 69 | global_data_pool->model_points_mutex_.unlock(); 70 | pangolin::RenderVbo(glxyz, GL_POINTS); 71 | 72 | // Draw images. 73 | global_data_pool->DrawImage(&image_texture); 74 | d_image.Activate(); 75 | image_texture.RenderToViewport(); 76 | 77 | pangolin::FinishFrame(); 78 | } 79 | 80 | pangolin::QuitAll(); 81 | reconstruct_worker.join(); 82 | #else 83 | auto reconstructor = std::make_unique("../config.ini", nullptr); 84 | reconstructor->Run(); 85 | #endif 86 | return 0; 87 | } 88 | -------------------------------------------------------------------------------- /src/Reconstructor.h: -------------------------------------------------------------------------------- 1 | // Created by aska on 2019/4/14. 2 | // 3 | #pragma once 4 | 5 | #include "Core/Model.h" 6 | #include "Core/CurveExtractor.h" 7 | #include "Core/CurveMatcher.h" 8 | #include "Core/View.h" 9 | #include "Utils/Common.h" 10 | #include "Utils/GlobalDataPool.h" 11 | #include "Utils/Streamer.h" 12 | 13 | #include 14 | #include 15 | #include 16 | 17 | class Reconstructor { 18 | public: 19 | enum State { RUNNING, EXIT_OK }; 20 | 21 | Reconstructor(std::string ini_file_name, GlobalDataPool* global_data_pool); 22 | ~Reconstructor(); 23 | void Run(); 24 | void Initialize(); 25 | void PushNewExtractors(int n_new_extractors = 1); 26 | void PressureTest(Model* final_model); 27 | 28 | // Configures 29 | PropertyTree ptree_; 30 | std::string img_path_; 31 | std::string data_path_; 32 | int n_views_, initial_idx_; 33 | int height_, width_; 34 | bool use_gpu_; 35 | double focal_length_; 36 | double init_depth_; 37 | 38 | // Configures: For Deforming 39 | double rigid_weight_; 40 | 41 | std::string reconstruction_method_; 42 | 43 | // Data 44 | std::vector > extractors_; 45 | 46 | std::unique_ptr streamer_; 47 | GlobalDataPool* global_data_pool_; 48 | State state_ = State::RUNNING; 49 | }; -------------------------------------------------------------------------------- /src/Utils/BezierCurve.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by aska on 2020/2/18. 3 | // 4 | 5 | #include "BezierCurve.h" 6 | 7 | BezierCurve::BezierCurve(const std::vector& initial_points, 8 | const std::vector& errors, 9 | double error_threshold, 10 | double hope_dist) { 11 | points_p_.clear(); 12 | points_t_.clear(); 13 | hope_dist_ = hope_dist; 14 | BuildBezierCurve(initial_points, errors, error_threshold, 0, initial_points.size() - 1); 15 | CHECK_EQ(points_p_.size(), points_t_.size()); 16 | CHECK_EQ(expressions_.size() + 1, initial_points.size()); 17 | expressions_.emplace_back(points_p_.size() - 1, points_p_.size(), points_t_.size() - 1, 1.0); 18 | points_p_.emplace_back(initial_points.back()); 19 | } 20 | 21 | void BezierCurve::BuildBezierCurve(const std::vector &initial_points, 22 | const std::vector &errors, 23 | double error_threshold, 24 | int l_bound, 25 | int r_bound) { 26 | Eigen::Vector3d p1; 27 | if (IsSingleFittingOK(initial_points, errors, error_threshold, l_bound, r_bound, &p1)) { 28 | points_p_.emplace_back(initial_points[l_bound]); 29 | points_t_.emplace_back(p1); 30 | double len_sum = 0.0; 31 | for (int i = l_bound; i < r_bound; i++) { 32 | len_sum += (initial_points[i + 1] - initial_points[i]).norm(); 33 | } 34 | double current_sum = 0.0; 35 | for (int i = l_bound; i < r_bound; i++) { 36 | expressions_.emplace_back(points_p_.size() - 1, points_p_.size(), points_t_.size() - 1, current_sum / len_sum); 37 | current_sum += (initial_points[i + 1] - initial_points[i]).norm(); 38 | } 39 | return; 40 | } 41 | int mid = (l_bound + r_bound) / 2; 42 | BuildBezierCurve(initial_points, errors, error_threshold, l_bound, mid); 43 | BuildBezierCurve(initial_points, errors, error_threshold, mid, r_bound); 44 | return; 45 | } 46 | 47 | // Quadratic Bezier Curve 48 | // B(t) = (1 - t)^2 * P0 + 2t(1 - t) * P1 + t^2 * P2 49 | bool BezierCurve::IsSingleFittingOK(const std::vector& initial_points, 50 | const std::vector& errors, 51 | double error_threshold, 52 | int l_bound, 53 | int r_bound, 54 | Eigen::Vector3d* estimated_p1) { 55 | CHECK_LT(l_bound, r_bound); 56 | if (l_bound + 1 >= r_bound) { 57 | if (estimated_p1 != nullptr) { 58 | *estimated_p1 = (initial_points[l_bound] + initial_points[r_bound]) * 0.5; 59 | } 60 | return true; 61 | } 62 | for (int i = l_bound + 1; i < r_bound; i++) { 63 | if (errors[i] > error_threshold) { 64 | return false; 65 | } 66 | } 67 | double len_sum = 0.0; 68 | for (int i = l_bound; i < r_bound; i++) { 69 | len_sum += (initial_points[i + 1] - initial_points[i]).norm(); 70 | } 71 | double current_len = 0.0; 72 | const Eigen::Vector3d& p0 = initial_points[l_bound]; 73 | const Eigen::Vector3d& p2 = initial_points[r_bound]; 74 | Eigen::Vector3d A(0.0, 0.0, 0.0); 75 | Eigen::Vector3d B(0.0, 0.0, 0.0); 76 | Eigen::Vector3d C(0.0, 0.0, 0.0); 77 | // Find Best p1. 78 | for (int i = l_bound + 1; i < r_bound; i++) { 79 | current_len += (initial_points[i] - initial_points[i - 1]).norm(); 80 | double t = current_len / len_sum; 81 | Eigen::Vector3d known_term = (1.0 - t) * (1.0 - t) * p0 + t * t * p2; 82 | double co = 2.0 * t * (1.0 - t); 83 | Eigen::Vector3d hope_residual = (initial_points[i] - known_term) / co; 84 | // (p1 - hope_residual)^2 -> 85 | for (int k = 0; k < 3; k++) { 86 | A(k) += 1.0; 87 | B(k) += - 2.0 * hope_residual(k); 88 | C(k) += hope_residual(k) * hope_residual(k); 89 | } 90 | } 91 | 92 | Eigen::Vector3d p1; 93 | for (int k = 0; k < 3; k++) { 94 | p1(k) = -0.5 * B(k) / A(k); 95 | } 96 | 97 | const double kErrorTolerance = hope_dist_ * 1.0; 98 | current_len = 0.0; 99 | for (int i = l_bound + 1; i < r_bound; i++) { 100 | current_len += (initial_points[i] - initial_points[i - 1]).norm(); 101 | double t = current_len / len_sum; 102 | Eigen::Vector3d estimated_pt = (1.0 - t) * (1.0 - t) * p0 + 2.0 * (1.0 - t) * t * p1 + t * t * p2; 103 | double current_error = (estimated_pt - initial_points[i]).norm(); 104 | if (current_error > kErrorTolerance) { 105 | return false; 106 | } 107 | } 108 | if (estimated_p1 != nullptr) { 109 | *estimated_p1 = p1; 110 | } 111 | return true; 112 | } -------------------------------------------------------------------------------- /src/Utils/BezierCurve.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by aska on 2020/2/18. 3 | // 4 | #include "Common.h" 5 | 6 | struct BezierPointExpIdx { 7 | BezierPointExpIdx(int p0_idx = -1, int p1_idx = -1, int t_idx = -1, double t = -1) : 8 | p0_idx_(p0_idx), p1_idx_(p1_idx), t_idx_(t_idx), t_(t) {} 9 | int p0_idx_, p1_idx_; 10 | int t_idx_; 11 | double t_; 12 | }; 13 | 14 | class BezierCurve { 15 | public: 16 | BezierCurve(const std::vector& initial_points, 17 | const std::vector& errors, 18 | double error_threshold, 19 | double hope_dist); 20 | std::vector points_p_; 21 | std::vector points_t_; 22 | std::vector expressions_; 23 | double hope_dist_ = 0.0; 24 | 25 | private: 26 | void BuildBezierCurve(const std::vector& initial_points, 27 | const std::vector& errors, 28 | double error_threshold, 29 | int l_bound, 30 | int r_bound); 31 | bool IsSingleFittingOK(const std::vector& initial_points, 32 | const std::vector& errors, 33 | double error_threshold, 34 | int l_bound, 35 | int r_bound, 36 | Eigen::Vector3d* estimated_p1 = nullptr); 37 | }; -------------------------------------------------------------------------------- /src/Utils/Camera.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by aska on 2019/9/4. 3 | // 4 | 5 | #include "Camera.h" 6 | 7 | Camera::Camera(const Eigen::Matrix3d& intrinsic_mat, 8 | const Eigen::Matrix3d& R, 9 | const Eigen::Vector3d& T, 10 | const Eigen::Vector2d& distortion) { 11 | CHECK_NEAR(intrinsic_mat(2, 2), 1.0, 1e-5); 12 | focal_length_x_ = intrinsic_mat(0, 0); 13 | focal_length_y_ = intrinsic_mat(1, 1); 14 | half_width_ = intrinsic_mat(0, 2); 15 | half_height_ = intrinsic_mat(1, 2); 16 | R_ = R; 17 | T_ = T; 18 | distort_0_ = distortion(0); 19 | distort_1_ = distortion(1); 20 | } 21 | 22 | Camera::Camera(double focal_length, double width, double height) { 23 | focal_length_x_ = focal_length; 24 | focal_length_y_ = focal_length; 25 | half_width_ = width * 0.5; 26 | half_height_ = height * 0.5; 27 | } 28 | 29 | Eigen::Vector2d Camera::Cam2Image(const Eigen::Vector3d& point) { 30 | return { point(1) / point(2) * focal_length_y_ + half_height_, 31 | point(0) / point(2) * focal_length_x_ + half_width_ }; 32 | } 33 | 34 | Eigen::Vector2d Camera::World2Image(const Eigen::Vector3d& point) { 35 | return Cam2Image(World2Cam(point)); 36 | } 37 | 38 | Eigen::Vector3d Camera::World2Cam(const Eigen::Vector3d& point) { 39 | return R_ * point + T_; 40 | } 41 | 42 | Eigen::Vector3d Camera::Cam2World(const Eigen::Vector3d& point) { 43 | return R_.inverse() * (point - T_); 44 | } 45 | 46 | Eigen::Vector3d Camera::Image2Cam(const Eigen::Vector2d& point, double depth) { 47 | Eigen::Vector3d pt((point(1) - half_width_) / focal_length_x_, (point(0) - half_height_) / focal_length_y_, 1.0); 48 | return pt * depth; 49 | } 50 | 51 | Eigen::Vector3d Camera::Image2World(const Eigen::Vector2d& point, double depth) { 52 | return Cam2World(Image2Cam(point, depth)); 53 | } 54 | 55 | double Camera::GetFocalLengthX() { 56 | return focal_length_x_; 57 | } 58 | 59 | double Camera::GetFocalLengthY() { 60 | return focal_length_y_; 61 | } 62 | 63 | void Camera::UpdateRT(const Eigen::Matrix3d &R, const Eigen::Vector3d &T) { 64 | R_ = R; 65 | T_ = T; 66 | } 67 | 68 | -------------------------------------------------------------------------------- /src/Utils/Camera.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by aska on 2019/9/4. 3 | // 4 | #pragma once 5 | #include "Common.h" 6 | 7 | class Camera { 8 | public: 9 | Camera(const Eigen::Matrix3d& intrinsic_mat, 10 | const Eigen::Matrix3d& R, 11 | const Eigen::Vector3d& T, 12 | const Eigen::Vector2d& distortion); 13 | Camera(double focal_length, double width, double height); 14 | 15 | Eigen::Vector2d Cam2Image(const Eigen::Vector3d& point); 16 | Eigen::Vector2d World2Image(const Eigen::Vector3d& point); 17 | Eigen::Vector3d World2Cam(const Eigen::Vector3d& point); 18 | Eigen::Vector3d Cam2World(const Eigen::Vector3d& point); 19 | Eigen::Vector3d Image2Cam(const Eigen::Vector2d& point, double depth = 1.0); 20 | Eigen::Vector3d Image2World(const Eigen::Vector2d& point, double depth = 1.0); 21 | double GetFocalLengthX(); 22 | double GetFocalLengthY(); 23 | 24 | void UpdateRT(const Eigen::Matrix3d& R, const Eigen::Vector3d& T); 25 | private: 26 | double focal_length_x_ = 1.0; 27 | double focal_length_y_ = 1.0; 28 | double half_width_ = 0.0; 29 | double half_height_ = 0.0; 30 | double distort_0_ = 0.0; 31 | double distort_1_ = 0.0; 32 | Eigen::Matrix3d R_; 33 | Eigen::Vector3d T_; 34 | }; -------------------------------------------------------------------------------- /src/Utils/Common.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by aska on 2019/8/3. 3 | // 4 | #pragma once 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include "Math.h" 13 | #include "Utils.h" 14 | #include "StopWatch.h" 15 | 16 | #define kOnePi (3.14159265358979323846264338) 17 | #define kHalfPi (1.57079632679489661923132169) 18 | #define kDoublePi (6.28318530717958647692528676) 19 | 20 | using PropertyTree = boost::property_tree::ptree; 21 | -------------------------------------------------------------------------------- /src/Utils/CubeSet.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by aska on 2019/7/20. 3 | // 4 | 5 | #include "CubeSet.h" 6 | 7 | #include 8 | #include 9 | 10 | CubeSet::CubeSet(const Eigen::Vector3d ¢er, double r, double fineness) 11 | : center_(center), r_(r), fineness_(fineness) { 12 | } 13 | 14 | void CubeSet::UpdateCurrentSet() { 15 | for (const auto& pr : st_) { 16 | if (!mp_.count(pr.first)) { 17 | mp_.emplace(pr.first, pr.second); 18 | } 19 | else { 20 | mp_[pr.first] += pr.second; 21 | } 22 | } 23 | st_.clear(); 24 | } 25 | 26 | void CubeSet::CalcAllCubes(const Eigen::Vector3d& o, const Eigen::Vector3d& v, std::vector* cubes) { 27 | cubes->clear(); 28 | double in_times[3] = { 29 | std::numeric_limits::infinity(), 30 | std::numeric_limits::infinity(), 31 | std::numeric_limits::infinity() }; 32 | double out_times[3] = { 33 | -std::numeric_limits::infinity(), 34 | -std::numeric_limits::infinity(), 35 | -std::numeric_limits::infinity() }; 36 | 37 | const double eps = 1e-9; 38 | for (int t = 0; t < 3; t++) { 39 | if (std::abs(v(t)) < eps) { 40 | if (o(t) >= center_(t) - r_ && o(t) <= center_(t) + r_) { 41 | in_times[t] = -std::numeric_limits::infinity(); 42 | out_times[t] = std::numeric_limits::infinity(); 43 | } 44 | } 45 | else { 46 | in_times[t] = (center_(t) - r_ - o(t)) / v(t); 47 | out_times[t] = (center_(t) + r_ - o(t)) / v(t); 48 | if (v(t) < 0.0) { 49 | std::swap(in_times[t], out_times[t]); 50 | } 51 | } 52 | } 53 | 54 | double in_time = -std::numeric_limits::infinity(); 55 | double out_time = std::numeric_limits::infinity(); 56 | for (int t = 0; t < 3; t++) { 57 | in_time = std::max(in_time, in_times[t]); 58 | out_time = std::min(out_time, out_times[t]); 59 | } 60 | 61 | Eigen::Vector3d corner = center_ - Eigen::Vector3d(r_, r_, r_); 62 | double step_len = fineness_ / v.norm(); 63 | long long x = -(1LL << 20); 64 | long long y = -(1LL << 20); 65 | long long z = -(1LL << 20); 66 | for (double current_t = std::max(0.0, in_time); current_t <= out_time; current_t += step_len) { 67 | Eigen::Vector3d current_pt = o + v * current_t; 68 | long long new_x = std::floor((current_pt(0) - corner(0) + 1e-5) / fineness_); 69 | long long new_y = std::floor((current_pt(1) - corner(1) + 1e-5) / fineness_); 70 | long long new_z = std::floor((current_pt(2) - corner(2) + 1e-5) / fineness_); 71 | if (new_x == x && new_y == y && new_z == z) { 72 | continue; 73 | } 74 | x = new_x; 75 | y = new_y; 76 | z = new_z; 77 | if (x < 0 || y < 0 || z < 0) { 78 | LOG(FATAL) << "[CubeSet]: Error: Negative index."; 79 | } 80 | cubes->emplace_back((x << 40) + (y << 20) + z); 81 | } 82 | } 83 | 84 | void CubeSet::AddRay(const Eigen::Vector3d &o, const Eigen::Vector3d &v, double weight) { 85 | rays_.emplace_back(o, v); 86 | std::vector cubes; 87 | CalcAllCubes(o, v, &cubes); 88 | for (long long cube : cubes) { 89 | if (!st_.count(cube)) { 90 | st_.emplace(cube, weight); 91 | } else { 92 | st_[cube] = std::max(st_[cube], weight); 93 | } 94 | } 95 | } 96 | 97 | void CubeSet::FindDenseCubes(double cnt_threshold, std::vector> &cubes) { 98 | cubes.clear(); 99 | Eigen::Vector3d corner = center_ - Eigen::Vector3d(r_, r_, r_); 100 | long long mask = (1LL << 20) - 1; 101 | const int kCounterInf = 1e9; 102 | for (const auto& ray : rays_) { 103 | std::vector cube_indexes; 104 | CalcAllCubes(ray.first, ray.second, &cube_indexes); 105 | long long cube_to_add = -1; 106 | double counter = -1; 107 | for (long long cube_index : cube_indexes) { 108 | double current_counter = mp_[cube_index]; 109 | if (current_counter > counter) { 110 | counter = current_counter; 111 | cube_to_add = cube_index; 112 | } 113 | } 114 | if (counter + 1.0 < kCounterInf && counter > cnt_threshold) { 115 | mp_[cube_to_add] = kCounterInf; 116 | Eigen::Vector3d pt((cube_to_add >> 40) & mask, (cube_to_add >> 20) & mask, cube_to_add & mask); 117 | pt = (pt + Eigen::Vector3d(0.5, 0.5, 0.5)) * fineness_ + corner; 118 | cubes.emplace_back(counter, pt); 119 | } 120 | } 121 | } -------------------------------------------------------------------------------- /src/Utils/CubeSet.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by aska on 2019/7/20. 3 | // 4 | 5 | #ifndef ARAP_CUBESET_H 6 | #define ARAP_CUBESET_H 7 | 8 | #include "Common.h" 9 | 10 | #include 11 | #include 12 | 13 | struct CubeNode { 14 | public: 15 | CubeNode() = default; 16 | int counter_ = 0; 17 | std::vector source_indexes_; 18 | }; 19 | 20 | class CubeSet { 21 | public: 22 | CubeSet(const Eigen::Vector3d ¢er, double r, double fineness); 23 | ~CubeSet() = default; 24 | void UpdateCurrentSet(); 25 | void CalcAllCubes(const Eigen::Vector3d& o, const Eigen::Vector3d& v, std::vector* cubes); 26 | void AddRay(const Eigen::Vector3d& o, const Eigen::Vector3d& v, double weight = 1.0); 27 | void FindDenseCubes(double cnt_threshold, std::vector>& cubes); 28 | // data 29 | Eigen::Vector3d center_; 30 | double r_; 31 | double fineness_; 32 | int global_timestamp_; 33 | std::unordered_map st_; 34 | std::unordered_map mp_; 35 | std::vector> rays_; 36 | }; 37 | 38 | 39 | #endif //ARAP_CUBESET_H -------------------------------------------------------------------------------- /src/Utils/FastOpticalFlow/OFDIS.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by aska on 2020/4/29. 3 | // 4 | 5 | #pragma once 6 | cv::Mat RunOFDIS(const cv::Mat& pre, const cv::Mat& nex); -------------------------------------------------------------------------------- /src/Utils/FastOpticalFlow/README.md: -------------------------------------------------------------------------------- 1 | # Fast Optical Flow using Dense Inverse Search (DIS) # 2 | 3 | Our code is released only for scientific or personal use. 4 | Please contact us for commercial use. 5 | 6 | If used this work, please cite: 7 | 8 | `@inproceedings{kroegerECCV2016, 9 | Author = {Till Kroeger and Radu Timofte and Dengxin Dai and Luc Van Gool}, 10 | Title = {Fast Optical Flow using Dense Inverse Search}, 11 | Booktitle = {Proceedings of the European Conference on Computer Vision ({ECCV})}, 12 | Year = {2016}} ` 13 | 14 | Is you use the variational refinement, please additionally cite: 15 | 16 | ` @inproceedings{weinzaepfelICCV2013, 17 | TITLE = {{DeepFlow: Large displacement optical flow with deep matching}}, 18 | AUTHOR = {Weinzaepfel, Philippe and Revaud, J{\'e}r{\^o}me and Harchaoui, Zaid and Schmid, Cordelia}, 19 | BOOKTITLE = {{ICCV 2013 - IEEE International Conference on Computer Vision}}, 20 | YEAR = {2013}} ` 21 | 22 | 23 | 24 | 25 | ## Compiling ## 26 | 27 | The program was only tested under a 64-bit Linux distribution. 28 | SSE instructions from built-in X86 functions for GNU GCC were used. 29 | 30 | The following will build four binaries: 31 | Two for optical flow (`run_OF_*`) and two for depth from stereo (`run_DE_*`). 32 | For each problem, a fast variant operating on intensity images (`run_*_INT`) and 33 | a slower variant operating on RGB images (`run_*_RGB`) is provided. 34 | 35 | ``` 36 | mkdir build 37 | cd build 38 | cmake ../ 39 | make -j 40 | ``` 41 | 42 | The code depends on Eigen3 and OpenCV. However, OpenCV is only used for image loading, 43 | scaling and gradient computation (`run_dense.cpp`). It can easily be replaced by other libraries. 44 | 45 | 46 | 47 | 48 | ## Usage ## 49 | The interface for all four binaries (`run_*_*`) is the same. 50 | 51 | VARIANT 1 (Uses operating point 2 of the paper, automatically selects coarsest scale): 52 | 53 | ` ./run_*_* image1.png image2.png outputfile ` 54 | 55 | 56 | VARIANT 2 (Manually select operating point X=1-4, automatically selects coarsest scale): 57 | 58 | ` ./run_*_* image1.png image2.png outputfile X ` 59 | 60 | 61 | VARIANT 3 (Set all parameters explicitly): 62 | 63 | ` ./run_*_* image1.png image2.png outputfile p1 p2 p3 p4 p5 p6 p7 p8 p9 p10 p11 p12 p13 p14 p15 p16 p17 p18 p19 p20` 64 | 65 | Example for variant 3 using operating point 2 of the paper: 66 | 67 | ` ./run_OF_INT in1.png int2.png out.flo 5 3 12 12 0.05 0.95 0 8 0.40 0 1 0 1 10 10 5 1 3 1.6 2 ` 68 | 69 | 70 | 71 | Parameters: 72 | ``` 73 | 1. Coarsest scale (here: 5) 74 | 2. Finest scale (here: 3) 75 | 3/4. Min./Max. iterations (here: 12) 76 | 5./6./7. Early stopping parameters 77 | 8. Patch size (here: 8) 78 | 9. Patch overlap (here: 0.4) 79 | 10.Use forward-backward consistency (here: 0/no) 80 | 11.Mean-normalize patches (here: 1/yes) 81 | 12.Cost function (here: 0/L2) Alternatives: 1/L1, 2/Huber, 10/NCC 82 | 13.Use TV refinement (here: 1/yes) 83 | 14./15./16. TV parameters alpha,gamma,delta (here 10,10,5) 84 | 17. Number of TV outer iterations (here: 1) 85 | 18. Number of TV solver iterations (here: 3) 86 | 19. TV SOR value (here: 1.6) 87 | 20. Verbosity (here: 2) Alternatives: 0/no output, 1/only flow runtime, 2/total runtime 88 | ``` 89 | 90 | 91 | The optical flow output is saves as .flo file. 92 | (http://sintel.is.tue.mpg.de/downloads) 93 | 94 | The interface for depth from stereo is exactly the same. The output is saves as pfm file. 95 | (http://vision.middlebury.edu/stereo/code/) 96 | 97 | 98 | NOTES: 99 | 1. For better quality, increase the number iterations (param 3/4), use finer scales (param. 2), higher patch overlap (param. 9), more outer TV iterations (param. 17) 100 | 2. L1/Huber cost functions (param. 12) provide better results, but require more iterations (param. 3/4) 101 | 102 | 103 | 104 | ## Bugs and extensions ## 105 | 106 | If you find bugs, etc., please feel free to contact me. 107 | Contact details are available on my webpage. 108 | http://www.vision.ee.ethz.ch/~kroegert/ 109 | 110 | 111 | 112 | ## History ## 113 | 114 | July 2016 v1.0.0 - Initial Release 115 | August 2016 v1.0.1 - Minor Bugfix: Error in L1 and Huber error norm computation. 116 | 117 | 118 | 119 | 120 | ## LICENCE CONDITIONS ## 121 | 122 | GPLv3: http://gplv3.fsf.org/ 123 | 124 | All programs in this collection are free software: 125 | you can redistribute it and/or modify 126 | it under the terms of the GNU General Public License as published by 127 | the Free Software Foundation, either version 3 of the License, or 128 | (at your option) any later version. 129 | 130 | This program is distributed in the hope that it will be useful, 131 | but WITHOUT ANY WARRANTY; without even the implied warranty of 132 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 133 | GNU General Public License for more details. 134 | 135 | You should have received a copy of the GNU General Public License 136 | along with this program. If not, see . 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | -------------------------------------------------------------------------------- /src/Utils/FastOpticalFlow/image.h: -------------------------------------------------------------------------------- 1 | #ifndef __IMAGE_H_ 2 | #define __IMAGE_H_ 3 | #pragma once 4 | #include 5 | 6 | #define MIN_TA(a, b) ((a) < (b) ? (a) : (b)) 7 | #define MAX_TA(a, b) ((a) > (b) ? (a) : (b)) 8 | #define MINMAX_TA(a,b) MIN_TA( MAX_TA(a,0) , b-1 ) 9 | 10 | #ifdef __cplusplus 11 | extern "C" { 12 | #endif 13 | 14 | 15 | /********** STRUCTURES *********/ 16 | 17 | /* structure for 1-channel image */ 18 | typedef struct image_s 19 | { 20 | int width; /* Width of the image */ 21 | int height; /* Height of the image */ 22 | int stride; /* Width of the memory (width + paddind such that it is a multiple of 4) */ 23 | float *c1; /* Image data, aligned */ 24 | } image_t; 25 | 26 | /* structure for 3-channels image stored with one layer per color, it assumes that c2 = c1+width*height and c3 = c2+width*height. */ 27 | typedef struct color_image_s 28 | { 29 | int width; /* Width of the image */ 30 | int height; /* Height of the image */ 31 | int stride; /* Width of the memory (width + paddind such that it is a multiple of 4) */ 32 | float *c1; /* Color 1, aligned */ 33 | float *c2; /* Color 2, consecutive to c1*/ 34 | float *c3; /* Color 3, consecutive to c2 */ 35 | } color_image_t; 36 | 37 | /* structure for color image pyramid */ 38 | typedef struct color_image_pyramid_s 39 | { 40 | float scale_factor; /* difference of scale between two levels */ 41 | int min_size; /* minimum size for width or height at the coarsest level */ 42 | int size; /* number of levels in the pyramid */ 43 | color_image_t **images; /* list of images with images[0] the original one, images[size-1] the finest one */ 44 | } color_image_pyramid_t; 45 | 46 | /* structure for convolutions */ 47 | typedef struct convolution_s 48 | { 49 | int order; /* Order of the convolution */ 50 | float *coeffs; /* Coefficients */ 51 | float *coeffs_accu; /* Accumulated coefficients */ 52 | } convolution_t; 53 | 54 | /********** Create/Delete **********/ 55 | 56 | /* allocate a new image of size width x height */ 57 | image_t *image_new(const int width, const int height); 58 | 59 | /* allocate a new image and copy the content from src */ 60 | image_t *image_cpy(const image_t *src); 61 | 62 | /* set all pixels values to zeros */ 63 | void image_erase(image_t *image); 64 | 65 | /* free memory of an image */ 66 | void image_delete(image_t *image); 67 | 68 | /* multiply an image by a scalar */ 69 | void image_mul_scalar(image_t *image, const float scalar); 70 | 71 | /* allocate a new color image of size width x height */ 72 | color_image_t *color_image_new(const int width, const int height); 73 | 74 | /* allocate a new color image and copy the content from src */ 75 | color_image_t *color_image_cpy(const color_image_t *src); 76 | 77 | /* set all pixels values to zeros */ 78 | void color_image_erase(color_image_t *image); 79 | 80 | /* free memory of a color image */ 81 | void color_image_delete(color_image_t *image); 82 | 83 | /* reallocate the memory of an image to fit the new width height */ 84 | void resize_if_needed_newsize(image_t *im, const int w, const int h); 85 | 86 | /************ Resizing *********/ 87 | 88 | /* resize an image with bilinear interpolation */ 89 | image_t *image_resize_bilinear(const image_t *src, const float scale); 90 | 91 | /* resize an image with bilinear interpolation to fit the new weidht, height ; reallocation is done if necessary */ 92 | void image_resize_bilinear_newsize(image_t *dst, const image_t *src, const int new_width, const int new_height); 93 | 94 | /* resize a color image with bilinear interpolation */ 95 | color_image_t *color_image_resize_bilinear(const color_image_t *src, const float scale); 96 | 97 | /************ Convolution ******/ 98 | 99 | /* return half coefficient of a gaussian filter */ 100 | float *gaussian_filter(const float sigma, int *fSize); 101 | 102 | /* create a convolution structure with a given order, half_coeffs, symmetric or anti-symmetric according to even parameter */ 103 | convolution_t *convolution_new(int order, const float *half_coeffs, const int even); 104 | 105 | /* perform an horizontal convolution of an image */ 106 | void convolve_horiz(image_t *dest, const image_t *src, const convolution_t *conv); 107 | 108 | /* perform a vertical convolution of an image */ 109 | void convolve_vert(image_t *dest, const image_t *src, const convolution_t *conv); 110 | 111 | /* free memory of a convolution structure */ 112 | void convolution_delete(convolution_t *conv); 113 | 114 | /* perform horizontal and/or vertical convolution to a color image */ 115 | void color_image_convolve_hv(color_image_t *dst, const color_image_t *src, const convolution_t *horiz_conv, const convolution_t *vert_conv); 116 | 117 | /* perform horizontal and/or vertical convolution to a single band image */ 118 | void image_convolve_hv(image_t *dst, const image_t *src, const convolution_t *horiz_conv, const convolution_t *vert_conv); 119 | 120 | 121 | /************ Pyramid **********/ 122 | 123 | /* create a pyramid of color images using a given scale factor, stopping when one dimension reach min_size and with applying a gaussian smoothing of standard deviation spyr (no smoothing if 0) */ 124 | color_image_pyramid_t *color_image_pyramid_create(const color_image_t *src, const float scale_factor, const int min_size, const float spyr); 125 | 126 | /* delete the structure of a pyramid of color images */ 127 | void color_image_pyramid_delete(color_image_pyramid_t *pyr); 128 | 129 | #ifdef __cplusplus 130 | } 131 | #endif 132 | 133 | 134 | #endif 135 | 136 | 137 | -------------------------------------------------------------------------------- /src/Utils/FastOpticalFlow/opticalflow_aux.h: -------------------------------------------------------------------------------- 1 | #ifndef __OPTICALFLOW_AUX_ 2 | #define __OPTICALFLOW_AUX_ 3 | #pragma once 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | #include 9 | 10 | #include "image.h" 11 | 12 | #if (SELECTCHANNEL==1 | SELECTCHANNEL==2) // use single band image 13 | /* warp a color image according to a flow. src is the input image, wx and wy, the input flow. dst is the warped image and mask contains 0 or 1 if the pixels goes outside/inside image boundaries */ 14 | void image_warp(image_t *dst, image_t *mask, const image_t *src, const image_t *wx, const image_t *wy); 15 | 16 | /* compute image first and second order spatio-temporal derivatives of a color image */ 17 | void get_derivatives(const image_t *im1, const image_t *im2, const convolution_t *deriv, image_t *dx, image_t *dy, image_t *dt, image_t *dxx, image_t *dxy, image_t *dyy, image_t *dxt, image_t *dyt); 18 | 19 | #else // use RGB image_new 20 | /* warp a color image according to a flow. src is the input image, wx and wy, the input flow. dst is the warped image and mask contains 0 or 1 if the pixels goes outside/inside image boundaries */ 21 | void image_warp(color_image_t *dst, image_t *mask, const color_image_t *src, const image_t *wx, const image_t *wy); 22 | 23 | /* compute image first and second order spatio-temporal derivatives of a color image */ 24 | void get_derivatives(const color_image_t *im1, const color_image_t *im2, const convolution_t *deriv, color_image_t *dx, color_image_t *dy, color_image_t *dt, color_image_t *dxx, color_image_t *dxy, color_image_t *dyy, color_image_t *dxt, color_image_t *dyt); 25 | 26 | #endif 27 | 28 | 29 | /* compute the smoothness term */ 30 | void compute_smoothness(image_t *dst_horiz, image_t *dst_vert, const image_t *uu, const image_t *vv, const convolution_t *deriv_flow, const float quarter_alpha); 31 | // void compute_smoothness_SF(image_t *dst_horiz, image_t *dst_vert, const image_t *xx1, const image_t *xx2, const image_t *yy, const image_t *xx3, const convolution_t *deriv_flow, const float quarter_alpha); 32 | 33 | /* sub the laplacian (smoothness term) to the right-hand term */ 34 | void sub_laplacian(image_t *dst, const image_t *src, const image_t *weight_horiz, const image_t *weight_vert); 35 | 36 | /* compute the dataterm and the matching term 37 | a11 a12 a22 represents the 2x2 diagonal matrix, b1 and b2 the right hand side 38 | other (color) images are input */ 39 | void compute_data_and_match(image_t *a11, image_t *a12, image_t *a22, image_t *b1, image_t *b2, image_t *mask, image_t *wx, image_t *wy, image_t *du, image_t *dv, image_t *uu, image_t *vv, color_image_t *Ix, color_image_t *Iy, color_image_t *Iz, color_image_t *Ixx, color_image_t *Ixy, color_image_t *Iyy, color_image_t *Ixz, color_image_t *Iyz, image_t *desc_weight, image_t *desc_flow_x, image_t *desc_flow_y, const float half_delta_over3, const float half_beta, const float half_gamma_over3); 40 | 41 | /* compute the dataterm and ... REMOVED THE MATCHING TERM 42 | a11 a12 a22 represents the 2x2 diagonal matrix, b1 and b2 the right hand side 43 | other (color) images are input */ 44 | #if (SELECTCHANNEL==1 | SELECTCHANNEL==2) // use single band image_delete 45 | void compute_data(image_t *a11, image_t *a12, image_t *a22, image_t *b1, image_t *b2, image_t *mask, image_t *wx, image_t *wy, image_t *du, image_t *dv, image_t *uu, image_t *vv, image_t *Ix, image_t *Iy, image_t *Iz, image_t *Ixx, image_t *Ixy, image_t *Iyy, image_t *Ixz, image_t *Iyz, const float half_delta_over3, const float half_beta, const float half_gamma_over3); 46 | #else 47 | void compute_data(image_t *a11, image_t *a12, image_t *a22, image_t *b1, image_t *b2, image_t *mask, image_t *wx, image_t *wy, image_t *du, image_t *dv, image_t *uu, image_t *vv, color_image_t *Ix, color_image_t *Iy, color_image_t *Iz, color_image_t *Ixx, color_image_t *Ixy, color_image_t *Iyy, color_image_t *Ixz, color_image_t *Iyz, const float half_delta_over3, const float half_beta, const float half_gamma_over3); 48 | #endif 49 | 50 | #if (SELECTCHANNEL==1 | SELECTCHANNEL==2) // use single band image_delete 51 | void compute_data_DE(image_t *a11, image_t *b1, image_t *mask, image_t *wx, image_t *du, image_t *uu, image_t *Ix, image_t *Iy, image_t *Iz, image_t *Ixx, image_t *Ixy, image_t *Iyy, image_t *Ixz, image_t *Iyz, const float half_delta_over3, const float half_beta, const float half_gamma_over3); 52 | #else 53 | void compute_data_DE(image_t *a11, image_t *b1, image_t *mask, image_t *wx, image_t *du, image_t *uu, color_image_t *Ix, color_image_t *Iy, color_image_t *Iz, color_image_t *Ixx, color_image_t *Ixy, color_image_t *Iyy, color_image_t *Ixz, color_image_t *Iyz, const float half_delta_over3, const float half_beta, const float half_gamma_over3); 54 | #endif 55 | 56 | 57 | /* resize the descriptors to the new size using a weighted mean */ 58 | void descflow_resize(image_t *dst_flow_x, image_t *dst_flow_y, image_t *dst_weight, const image_t *src_flow_x, const image_t *src_flow_y, const image_t *src_weight); 59 | 60 | /* resize the descriptors to the new size using a nearest neighbor method while keeping the descriptor with the higher weight at the end */ 61 | void descflow_resize_nn(image_t *dst_flow_x, image_t *dst_flow_y, image_t *dst_weight, const image_t *src_flow_x, const image_t *src_flow_y, const image_t *src_weight); 62 | 63 | #ifdef __cplusplus 64 | } 65 | #endif 66 | 67 | 68 | #endif 69 | -------------------------------------------------------------------------------- /src/Utils/FastOpticalFlow/patch.h: -------------------------------------------------------------------------------- 1 | 2 | // Class implements step (3.) in Algorithm 1 of the paper: 3 | // It finds the displacement of one patch from reference/template image to the closest-matching patch in target image via gradient descent. 4 | 5 | #pragma once 6 | #ifndef PAT_HEADER 7 | #define PAT_HEADER 8 | 9 | //#include // needed for verbosity >= 3, DISVISUAL 10 | //#include // needed for verbosity >= 3, DISVISUAL 11 | //#include // needed for verbosity >= 3, DISVISUAL 12 | 13 | #include "oflow.h" // For camera intrinsic and opt. parameter struct 14 | 15 | namespace OFC 16 | { 17 | 18 | 19 | typedef struct 20 | { 21 | bool hasconverged; 22 | bool hasoptstarted; 23 | 24 | // reference/template patch 25 | Eigen::Matrix pdiff; // image error to reference image 26 | Eigen::Matrix pweight; // absolute error image 27 | 28 | #if (SELECTMODE==1) // Optical Flow 29 | Eigen::Matrix Hes; // Hessian for optimization 30 | Eigen::Vector2f p_in, p_iter, delta_p; // point position, displacement to starting position, iteration update 31 | #else // Depth from Stereo 32 | Eigen::Matrix Hes; // Hessian for optimization 33 | Eigen::Matrix p_in, p_iter, delta_p; // point position, displacement to starting position, iteration update 34 | #endif 35 | 36 | // start positions, current point position, patch norm 37 | Eigen::Matrix normtmp; 38 | Eigen::Vector2f pt_iter; 39 | Eigen::Vector2f pt_st; 40 | 41 | float delta_p_sqnorm = 1e-10; 42 | float delta_p_sqnorm_init = 1e-10; 43 | float mares = 1e20; // mares: Mean Absolute RESidual 44 | float mares_old = 1e20; 45 | int cnt=0; 46 | bool invalid=false; 47 | } patchstate; 48 | 49 | 50 | 51 | class PatClass 52 | { 53 | 54 | public: 55 | PatClass(const camparam* cpt_in, 56 | const camparam* cpo_in, 57 | const optparam* op_in, 58 | const int patchid_in); 59 | 60 | ~PatClass(); 61 | 62 | void InitializePatch(Eigen::Map * im_ao_in, Eigen::Map * im_ao_dx_in, Eigen::Map * im_ao_dy_in, const Eigen::Vector2f pt_ref_in); 63 | void SetTargetImage(Eigen::Map * im_bo_in, Eigen::Map * im_bo_dx_in, Eigen::Map * im_bo_dy_in); 64 | 65 | #if (SELECTMODE==1) // Optical Flow 66 | void OptimizeIter(const Eigen::Vector2f p_in_arg, const bool untilconv); 67 | #else // Depth from Stereo 68 | void OptimizeIter(const Eigen::Matrix p_in_arg, const bool untilconv); 69 | #endif 70 | 71 | inline const bool isConverged() const { return pc->hasconverged; } 72 | inline const bool hasOptStarted() const { return pc->hasoptstarted; } 73 | inline const Eigen::Vector2f GetPointPos() const { return pc->pt_iter; } // get current iteration patch position (in this frame's opposite camera for OF, Depth) 74 | inline const bool IsValid() const { return (!pc->invalid) ; } 75 | inline const float * GetpWeightPtr() const {return (float*) pc->pweight.data(); } // Return data pointer to image error patch, used in efficient indexing for densification in patchgrid class 76 | 77 | #if (SELECTMODE==1) // Optical Flow 78 | inline const Eigen::Vector2f* GetParam() const { return &(pc->p_iter); } // get current iteration parameters 79 | #else // Depth from Stereo 80 | inline const Eigen::Matrix* GetParam() const { return &(pc->p_iter); } // get current iteration parameters 81 | #endif 82 | 83 | #if (SELECTMODE==1) // Optical Flow 84 | inline const Eigen::Vector2f* GetParamStart() const { return &(pc->p_in); } 85 | #else // Depth from Stereo 86 | inline const Eigen::Matrix* GetParamStart() const { return &(pc->p_in); } 87 | #endif 88 | 89 | private: 90 | 91 | #if (SELECTMODE==1) // Optical Flow 92 | void OptimizeStart(const Eigen::Vector2f p_in_arg); 93 | #else // Depth from Stereo 94 | void OptimizeStart(const Eigen::Matrix p_in_arg); 95 | #endif 96 | 97 | void OptimizeComputeErrImg(); 98 | void paramtopt(); 99 | void ResetPatch(); 100 | void ComputeHessian(); 101 | void CreateStatusStruct(patchstate * psin); 102 | void LossComputeErrorImage(Eigen::Matrix* patdest, Eigen::Matrix* wdest, const Eigen::Matrix* patin, const Eigen::Matrix* tmpin); 103 | 104 | // Extract patch on integer position, and gradients, No Bilinear interpolation 105 | void getPatchStaticNNGrad (const float* img, const float* img_dx, const float* img_dy, const Eigen::Vector2f* mid_in, Eigen::Matrix* tmp_in, Eigen::Matrix* tmp_dx_in, Eigen::Matrix* tmp_dy_in); 106 | // Extract patch on float position with bilinear interpolation, no gradients. 107 | void getPatchStaticBil(const float* img, const Eigen::Vector2f* mid_in, Eigen::Matrix* tmp_in_e); 108 | 109 | Eigen::Vector2f pt_ref; // reference point location 110 | Eigen::Matrix tmp; 111 | Eigen::Matrix dxx_tmp; // x derivative, doubles as steepest descent image for OF, Depth, SF 112 | Eigen::Matrix dyy_tmp; // y derivative, doubles as steepest descent image for OF, SF 113 | 114 | Eigen::Map * im_ao, * im_ao_dx, * im_ao_dy; 115 | Eigen::Map * im_bo, * im_bo_dx, * im_bo_dy; 116 | 117 | const camparam* cpt; 118 | const camparam* cpo; 119 | const optparam* op; 120 | const int patchid; 121 | 122 | patchstate * pc = nullptr; // current patch state 123 | 124 | }; 125 | 126 | 127 | } 128 | 129 | #endif /* PAT_HEADER */ 130 | 131 | 132 | -------------------------------------------------------------------------------- /src/Utils/FastOpticalFlow/patchgrid.h: -------------------------------------------------------------------------------- 1 | 2 | // Class implements step (3.) in Algorithm 1 of the paper: 3 | // I holds all patch objects on a specific scale, and organizes 1) the dense inverse search, 2) densification 4 | #pragma once 5 | #ifndef PATGRID_HEADER 6 | #define PATGRID_HEADER 7 | 8 | #include "patch.h" 9 | #include "oflow.h" // For camera intrinsic and opt. parameter struct 10 | 11 | 12 | namespace OFC 13 | { 14 | 15 | class PatGridClass 16 | { 17 | 18 | public: 19 | PatGridClass(const camparam* cpt_in, 20 | const camparam* cpo_in, 21 | const optparam* op_in); 22 | 23 | ~PatGridClass(); 24 | 25 | void InitializeGrid(const float * im_ao_in, const float * im_ao_dx_in, const float * im_ao_dy_in); 26 | void SetTargetImage(const float * im_bo_in, const float * im_bo_dx_in, const float * im_bo_dy_in); 27 | void InitializeFromCoarserOF(const float * flow_prev); 28 | 29 | void AggregateFlowDense(float *flowout) const; 30 | 31 | // Optimizes grid to convergence of each patch 32 | void Optimize(); 33 | //Optimize each patch in grid for one iteration, visualize displacement vector, repeat 34 | //void OptimizeAndVisualize(const float sc_fct_tmp); // needed for verbosity >= 3, DISVISUAL 35 | 36 | void SetComplGrid(PatGridClass *cg_in); 37 | 38 | inline const int GetNoPatches() const { return nopatches; } 39 | inline const int GetNoph() const { return noph; } 40 | inline const int GetNopw() const { return nopw; } 41 | 42 | inline const Eigen::Vector2f GetRefPatchPos(int i) const { return pt_ref[i]; } // Get reference patch position 43 | inline const Eigen::Vector2f GetQuePatchPos(int i) const { return pat[i]->GetPointPos(); } // Get target/query patch position 44 | inline const Eigen::Vector2f GetQuePatchDis(int i) const { return pt_ref[i]-pat[i]->GetPointPos(); } // Get query patch displacement from reference patch 45 | 46 | private: 47 | 48 | const float * im_ao, * im_ao_dx, * im_ao_dy; 49 | const float * im_bo, * im_bo_dx, * im_bo_dy; 50 | 51 | Eigen::Map * im_ao_eg, * im_ao_dx_eg, * im_ao_dy_eg; 52 | Eigen::Map * im_bo_eg, * im_bo_dx_eg, * im_bo_dy_eg; 53 | 54 | const camparam* cpt; 55 | const camparam* cpo; 56 | const optparam* op; 57 | 58 | int steps; 59 | int nopw; 60 | int noph; 61 | int nopatches; 62 | 63 | std::vector pat; // Patch Objects 64 | std::vector pt_ref; // Midpoints for reference patches 65 | #if (SELECTMODE==1) 66 | std::vector p_init; // starting parameters for query patches, use only 1 for depth, 2 for OF, all 4 for scene flow 67 | #else 68 | std::vector> p_init; // starting parameters for query patches, use only 1 for depth, 2 for OF, all 4 for scene flow 69 | #endif 70 | 71 | const PatGridClass * cg=nullptr; 72 | }; 73 | 74 | 75 | } 76 | 77 | #endif /* PATGRID_HEADER */ 78 | 79 | 80 | -------------------------------------------------------------------------------- /src/Utils/FastOpticalFlow/refine_variational.h: -------------------------------------------------------------------------------- 1 | #ifndef VARREF_HEADER 2 | #define VARREF_HEADER 3 | #pragma once 4 | #include "image.h" 5 | #include "opticalflow_aux.h" 6 | #include "solver.h" 7 | 8 | #include "oflow.h" 9 | 10 | namespace OFC 11 | { 12 | 13 | typedef __v4sf v4sf; 14 | 15 | typedef struct 16 | { 17 | float alpha; // smoothness weight 18 | float beta; // matching weight 19 | float gamma; // gradient constancy assumption weight 20 | float delta; // color constancy assumption weight 21 | int n_inner_iteration; // number of inner fixed point iterations 22 | int n_solver_iteration; // number of solver iterations 23 | float sor_omega; // omega parameter of sor method 24 | 25 | float tmp_quarter_alpha; 26 | float tmp_half_gamma_over3; 27 | float tmp_half_delta_over3; 28 | float tmp_half_beta; 29 | 30 | } TVparams; 31 | 32 | 33 | class VarRefClass 34 | { 35 | 36 | public: 37 | VarRefClass(const float * im_ao_in, const float * im_ao_dx_in, const float * im_ao_dy_in, // expects #sc_f_in pointers to float arrays for images and gradients. 38 | const float * im_bo_in, const float * im_bo_dx_in, const float * im_bo_dy_in, 39 | const camparam* cpt_in, const camparam* cpo_in,const optparam* op_in, float *flowout); 40 | ~VarRefClass(); 41 | 42 | private: 43 | 44 | convolution_t *deriv, *deriv_flow; 45 | 46 | 47 | #if (SELECTCHANNEL==1 | SELECTCHANNEL==2) // Intensity image, or gradient image 48 | void copyimage(const float* img, image_t * img_t); 49 | void RefLevelOF(image_t *wx, image_t *wy, const image_t *im1, const image_t *im2); 50 | void RefLevelDE(image_t *wx, const image_t *im1, const image_t *im2); 51 | #else // 3-Color RGB image 52 | void copyimage(const float* img, color_image_t * img_t); 53 | void RefLevelOF(image_t *wx, image_t *wy, const color_image_t *im1, const color_image_t *im2); 54 | void RefLevelDE(image_t *wx, const color_image_t *im1, const color_image_t *im2); 55 | #endif 56 | 57 | TVparams tvparams; 58 | 59 | const camparam* cpt; 60 | const camparam* cpo; 61 | const optparam* op; 62 | 63 | }; 64 | 65 | } 66 | 67 | #endif /* VARREF_HEADER */ 68 | 69 | 70 | -------------------------------------------------------------------------------- /src/Utils/FastOpticalFlow/solver.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include "image.h" 5 | 6 | #ifdef __cplusplus 7 | extern "C" { 8 | #endif 9 | 10 | // Perform n iterations of the sor_coupled algorithm for a system of the form as described in opticalflow.c 11 | void sor_coupled(image_t *du, image_t *dv, image_t *a11, image_t *a12, image_t *a22, const image_t *b1, const image_t *b2, const image_t *dpsis_horiz, const image_t *dpsis_vert, const int iterations, const float omega); 12 | 13 | void sor_coupled_slow_but_readable(image_t *du, image_t *dv, image_t *a11, image_t *a12, image_t *a22, const image_t *b1, const image_t *b2, const image_t *dpsis_horiz, const image_t *dpsis_vert, const int iterations, const float omega); 14 | 15 | void sor_coupled_slow_but_readable_DE(image_t *du, const image_t *a11, const image_t *b1, const image_t *dpsis_horiz, const image_t *dpsis_vert, const int iterations, const float omega); 16 | 17 | #ifdef __cplusplus 18 | } 19 | #endif 20 | -------------------------------------------------------------------------------- /src/Utils/GlobalDataPool.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by aska on 2019/9/26. 3 | // 4 | 5 | #include "GlobalDataPool.h" 6 | 7 | 8 | GlobalDataPool::GlobalDataPool() {} 9 | 10 | #ifdef USE_GUI 11 | 12 | void GlobalDataPool::DrawModelPoints(pangolin::GlBuffer* gl_buffer) { 13 | model_points_mutex_.lock(); 14 | glColor3f(1.0, 1.0, 1.0); 15 | std::vector data_to_draw; 16 | float x_offset = 0.0; 17 | for (const auto& pr : mp_model_points_) { 18 | for (int i = 0; i < pr.second.size(); i += 3) { 19 | data_to_draw.emplace_back(pr.second[i] + x_offset); 20 | data_to_draw.emplace_back(pr.second[i + 1]); 21 | data_to_draw.emplace_back(pr.second[i + 2]); 22 | } 23 | x_offset += 1.5; 24 | } 25 | gl_buffer->Upload(data_to_draw.data(), data_to_draw.size() * sizeof(float)); 26 | model_points_mutex_.unlock(); 27 | } 28 | 29 | void GlobalDataPool::UpdateModelPoints(void* model_ptr, const std::vector& points) { 30 | model_points_mutex_.lock(); 31 | std::vector& model_points = mp_model_points_[model_ptr]; 32 | model_points.resize(points.size() * 3); 33 | for (int i = 0; i < points.size(); i++) { 34 | for (int j = 0; j < 3; j++) { 35 | model_points[i * 3 + j] = points[i](j); 36 | } 37 | } 38 | model_points_mutex_.unlock(); 39 | } 40 | 41 | int GlobalDataPool::n_points() { 42 | int ret = 0; 43 | for (const auto& pr : mp_model_points_) { 44 | ret += pr.second.size(); 45 | } 46 | return ret; 47 | } 48 | 49 | void GlobalDataPool::DrawImage(pangolin::GlTexture* image_texture) { 50 | last_frame_mutex_.lock(); 51 | image_texture->Upload(last_frame_.data(), GL_RGB,GL_UNSIGNED_BYTE); 52 | last_frame_mutex_.unlock(); 53 | } 54 | 55 | void GlobalDataPool::UpdateImageData(const cv::Mat& image) { 56 | last_frame_mutex_.lock(); 57 | last_frame_.resize(image.cols * image.rows * image.channels()); 58 | std::memcpy(last_frame_.data(), image.data, last_frame_.size()); 59 | last_frame_mutex_.unlock(); 60 | } 61 | 62 | 63 | void GlobalDataPool::UpdateCameras(void* model_ptr, 64 | const std::vector& K_invs, 65 | const std::vector& Wfs, 66 | const std::vector>& width_and_heights) { 67 | cameras_mutex_.lock(); 68 | auto& camera_motion_info = mp_cameras_[model_ptr]; 69 | camera_motion_info.K_invs_ = K_invs; 70 | camera_motion_info.Wfs_ = Wfs; 71 | camera_motion_info.width_and_heights_ = width_and_heights; 72 | cameras_mutex_.unlock(); 73 | } 74 | 75 | void GlobalDataPool::DrawCameras() { 76 | cameras_mutex_.lock(); 77 | glColor3f(1.0, 1.0, 0.0); 78 | double offset = 0.0; 79 | for (const auto& pr : mp_cameras_) { 80 | const auto& camera_motion_info = pr.second; 81 | const auto& K_invs_ = camera_motion_info.K_invs_; 82 | const auto& Wfs_ = camera_motion_info.Wfs_; 83 | const auto& width_and_heights_ = camera_motion_info.width_and_heights_; 84 | CHECK_EQ(K_invs_.size(), Wfs_.size()); 85 | CHECK_EQ(K_invs_.size(), width_and_heights_.size()); 86 | for (int i = 0; i < camera_motion_info.K_invs_.size(); i++) { 87 | Eigen::Matrix4d current_frame = Wfs_[i]; 88 | current_frame(0, 3) += offset; 89 | pangolin::glDrawFrustum(K_invs_[i], width_and_heights_[i].first, width_and_heights_[i].second, current_frame, 0.05); 90 | } 91 | offset += 1.5; 92 | } 93 | cameras_mutex_.unlock(); 94 | } 95 | 96 | void GlobalDataPool::DrawPlotting(pangolin::DataLog* log) { 97 | plotting_data_mutex_.lock(); 98 | if (plotting_data_refreshed_) { 99 | if (plotting_data_.size() == 1) { 100 | log->Log(plotting_data_[0]); 101 | } 102 | else if (plotting_data_.size() == 2) { 103 | log->Log(plotting_data_[0], plotting_data_[1]); 104 | } 105 | else { 106 | LOG(FATAL) << "Two many items."; 107 | } 108 | plotting_data_refreshed_ = false; 109 | } 110 | plotting_data_mutex_.unlock(); 111 | } 112 | 113 | void GlobalDataPool::UpdatePlottingData(const std::vector& plotting_data){ 114 | plotting_data_mutex_.lock(); 115 | plotting_data_ = plotting_data; 116 | plotting_data_refreshed_ = true; 117 | plotting_data_mutex_.unlock(); 118 | } 119 | 120 | void GlobalDataPool::DeleteModel(void *model_ptr) { 121 | cameras_mutex_.lock(); 122 | mp_cameras_.erase(model_ptr); 123 | cameras_mutex_.unlock(); 124 | 125 | model_points_mutex_.lock(); 126 | mp_model_points_.erase(model_ptr); 127 | model_points_mutex_.unlock(); 128 | } 129 | 130 | #endif 131 | -------------------------------------------------------------------------------- /src/Utils/GlobalDataPool.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by aska on 2019/9/26. 3 | // 4 | 5 | #pragma once 6 | #include 7 | #include 8 | #ifdef USE_GUI 9 | #include 10 | #endif 11 | 12 | #include "Common.h" 13 | 14 | struct CameraMotionInfo { 15 | std::vector K_invs_; 16 | std::vector Wfs_; 17 | std::vector> width_and_heights_; 18 | }; 19 | 20 | class GlobalDataPool { 21 | public: 22 | GlobalDataPool(); 23 | #ifdef USE_GUI 24 | void DeleteModel(void* model_ptr); 25 | void DrawModelPoints(pangolin::GlBuffer* gl_buffer); 26 | void UpdateModelPoints(void* model_ptr, const std::vector& points); 27 | void DrawCameras(); 28 | void UpdateCameras(void* model_ptr, 29 | const std::vector& K_invs, 30 | const std::vector& Wfs, 31 | const std::vector>& width_and_heights); 32 | void DrawImage(pangolin::GlTexture* image_texture); 33 | void UpdateImageData(const cv::Mat& image); 34 | void DrawPlotting(pangolin::DataLog* log); 35 | void UpdatePlottingData(const std::vector& plotting_data); 36 | 37 | int n_points(); 38 | 39 | public: 40 | std::map> mp_model_points_; 41 | std::mutex model_points_mutex_; 42 | std::mutex last_frame_mutex_; 43 | std::vector last_frame_; 44 | 45 | std::vector plotting_data_; 46 | bool plotting_data_refreshed_ = false; 47 | std::mutex plotting_data_mutex_; 48 | 49 | std::mutex cameras_mutex_; 50 | std::map mp_cameras_; 51 | #endif 52 | }; 53 | -------------------------------------------------------------------------------- /src/Utils/Graph.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by aska on 2019/10/22. 3 | // 4 | #pragma once 5 | 6 | #include "Common.h" 7 | #include "OctreeNew.h" 8 | #include 9 | 10 | enum GraphType { 11 | UNKNOWN, TREE, TREE_WITH_CIRCLE, TREE_WITH_BRANCH_LINK, RAW_GRAPH 12 | }; 13 | 14 | class Graph { 15 | public: 16 | Graph() = default; 17 | virtual void GetPaths(std::vector>* paths) = 0; 18 | // virtual void GetSmoothPaths(std::vector>* pahts); 19 | virtual void GetLinkedPaths(const std::vector& points, 20 | std::vector>* paths, 21 | double cos_thres = -0.7, 22 | int max_degree = 10, 23 | bool jump_junctions = true); 24 | virtual void GetLinkedPathsWithSameDirection(const std::vector& points, 25 | std::vector>* paths, 26 | double cos_thres = -0.7, 27 | int max_degree = 10, 28 | bool jump_junctions = true); 29 | // virtual void GetSmoothLikedPaths(); 30 | 31 | int Degree(int u) { 32 | return edges_[u].size(); 33 | } 34 | 35 | const std::vector>& OutPoints(int u) const { 36 | return edges_[u]; 37 | } 38 | 39 | const std::vector>>& Edges() const { 40 | return edges_; 41 | } 42 | 43 | std::vector>> edges_; 44 | int n_points_; 45 | }; 46 | 47 | class SpanningTree : public Graph { 48 | public: 49 | SpanningTree(const std::vector& points, 50 | OctreeNew* octree, 51 | double r, 52 | double hope_dist, 53 | int max_degree = 4, 54 | const std::vector* const points_radius = nullptr); 55 | void GetPaths(std::vector>* paths) final; 56 | double r_; 57 | double hope_dist_; 58 | int max_degree_; 59 | const std::vector* points_; 60 | }; 61 | 62 | class IronTown : public Graph { 63 | public: 64 | IronTown(const std::vector& points, 65 | OctreeNew* octree, 66 | double r, 67 | double hope_dist, 68 | const std::vector* const points_radius = nullptr); 69 | IronTown(const std::vector& points, 70 | const std::vector>>& edges); 71 | void GetPaths(std::vector>* paths) final; 72 | double r_; 73 | double hope_dist_; 74 | const std::vector* points_; 75 | }; 76 | 77 | class SelfDefinedGraph : public Graph { 78 | public: 79 | SelfDefinedGraph(const std::vector& points, 80 | const std::vector>>& edges, 81 | const std::vector>& paths); 82 | void GetPaths(std::vector>* paths) final; 83 | 84 | const std::vector* points_; 85 | std::vector> paths_; 86 | }; 87 | -------------------------------------------------------------------------------- /src/Utils/ICP.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by aska on 2019/11/9. 3 | // 4 | 5 | #include "ICP.h" 6 | 7 | ICP::ICP(std::vector& points, const std::vector& normals, const std::vector& weights) : 8 | points_(points), quad_tree_(new QuadTree(points)), normals_(normals), weights_(weights) { 9 | n_points_ = points_.size(); 10 | CHECK_EQ(n_points_, normals.size()); 11 | CHECK_EQ(n_points_, weights.size()); 12 | } 13 | 14 | void ICP::FitRT(const std::vector& world_points, 15 | Eigen::Matrix3d* R, 16 | Eigen::Vector3d* T, 17 | int max_iter_num) { 18 | double increament = 1e9; 19 | int cnt = 0; 20 | // LOG(INFO) << "Before: " << std::endl << *R << std::endl << T->transpose() << std::endl; 21 | while (cnt++ < max_iter_num && increament > 1e-4) { 22 | increament = FitRTSingleStep(world_points, R, T); 23 | // LOG(INFO) << "After: " << std::endl << *R << std::endl << T->transpose() << std::endl; 24 | } 25 | // LOG(INFO) << "After: " << std::endl << *R << std::endl << T->transpose() << std::endl; 26 | // LOG(INFO) << "weights_size!!!: " << weights_.size(); 27 | } 28 | 29 | double ICP::FitRTSingleStep(const std::vector& world_points, Eigen::Matrix3d* R, Eigen::Vector3d* T) { 30 | Eigen::MatrixXd A(world_points.size() + 6, 6); 31 | A = Eigen::MatrixXd::Zero(world_points.size() + 6, 6); 32 | Eigen::VectorXd B(world_points.size() + 6); 33 | B = Eigen::VectorXd::Zero(world_points.size() + 6); 34 | 35 | // LOG(INFO) << "weight size:" << weights_.size(); 36 | int n_world_points = world_points.size(); 37 | int idx; 38 | #pragma omp parallel for private(idx) default(none) shared(R, T, world_points, n_world_points, points_, A, B) // schedule (dynamic,2) 39 | for (idx = 0; idx < n_world_points; idx++) { 40 | const auto& world_pt = world_points[idx]; 41 | Eigen::Vector3d pt_3d = *R * world_pt + *T; 42 | // CHECK(pt_3d(2) > 1e-9); 43 | Eigen::Vector2d pt_2d(pt_3d(0) / pt_3d(2), pt_3d(1) / pt_3d(2)); 44 | // for (int i = 0; i < 2; i++) { 45 | // CHECK(pt_2d(i) > -100 && pt_2d(i) < 100); 46 | // } 47 | int nearest_idx = quad_tree_->NearestIdx(pt_2d); 48 | // CHECK(nearest_idx >= 0 && nearest_idx < weights_.size()); 49 | // LOG(INFO) << "nearest_idx: " << nearest_idx; 50 | double weight = weights_[nearest_idx]; 51 | // CHECK(weight > 0.5); 52 | double dx = points_[nearest_idx](0); 53 | double dy = points_[nearest_idx](1); 54 | double dz = 1.0; 55 | 56 | double nx = normals_[nearest_idx](0); 57 | double ny = normals_[nearest_idx](1); 58 | double nz = normals_[nearest_idx](2); 59 | 60 | // template point 61 | double sx = pt_3d(0); 62 | double sy = pt_3d(1); 63 | double sz = pt_3d(2); 64 | 65 | // setup least squares system 66 | A(idx, 0) = weight * (nz * sy - ny * sz); 67 | A(idx, 1) = weight * (nx * sz - nz * sx); 68 | A(idx, 2) = weight * (ny * sx - nx * sy); 69 | A(idx, 3) = weight * nx; 70 | A(idx, 4) = weight * ny; 71 | A(idx, 5) = weight * nz; 72 | B(idx) = weight * (nx * dx + ny * dy + nz * dz - nx * sx - ny * sy - nz * sz); 73 | // LOG(INFO) << A.block(idx, 0, 1, 6); 74 | // LOG(INFO) << B(idx); 75 | } 76 | 77 | // regularization 78 | double reg_weight = 0.1; 79 | int reg_idx = n_world_points - 1; 80 | for (int u = 0; u < 6; u++) { 81 | reg_idx++; 82 | A(reg_idx, u) = reg_weight; 83 | B(reg_idx) = 0.0; 84 | } 85 | 86 | // Eigen::MatrixXd A_; 87 | // A_ = A.transpose() * A; 88 | // LOG(INFO) << A_; 89 | // Eigen::VectorXd B_; 90 | // B_ = A.transpose() * B; 91 | // LOG(INFO) << B_; 92 | // LOG(INFO) << "Sollll"; 93 | Eigen::VectorXd delta_p; 94 | delta_p = A.bdcSvd(Eigen::ComputeThinU | Eigen::ComputeThinV).solve(B); 95 | // delta_p = A.colPivHouseholderQr().solve(-B); 96 | // LOG(INFO) << "delta_p: " << delta_p.transpose(); 97 | // rotation matrix 98 | Eigen::Matrix3d R_inc = Eigen::Matrix3d::Identity(); 99 | R_inc(0, 1) = -delta_p(2); 100 | R_inc(1, 0) = +delta_p(2); 101 | R_inc(0, 2) = +delta_p(1); 102 | R_inc(2, 0) = -delta_p(1); 103 | R_inc(1, 2) = -delta_p(0); 104 | R_inc(2, 1) = +delta_p(0); 105 | 106 | Eigen::Vector3d T_inc(delta_p(3), delta_p(4), delta_p(5)); 107 | Eigen::Matrix3d U; 108 | Eigen::Matrix3d V; 109 | Eigen::JacobiSVD svd(R_inc, Eigen::ComputeFullU | Eigen::ComputeFullV); 110 | U = svd.matrixU(); 111 | V = svd.matrixV(); 112 | // A = svd.singularValues(); 113 | R_inc = U * V.transpose(); 114 | 115 | if (R_inc.determinant() < 0) { 116 | Eigen::Matrix3d tmp = Eigen::Matrix3d::Identity(); 117 | tmp(2, 2) = R_inc.determinant(); 118 | R_inc = V * tmp * U.transpose(); 119 | } 120 | *R = R_inc * *R; 121 | *T = R_inc * *T + T_inc; 122 | return std::max((R_inc - Eigen::Matrix3d::Identity()).norm(), T_inc.norm()); 123 | } 124 | 125 | std::pair ICP::NearestRayNormal(const Eigen::Vector2d& point) { 126 | int idx = quad_tree_->NearestIdx(point); 127 | return { Eigen::Vector3d(points_[idx](0), points_[idx](1), 1.0), normals_[idx] }; 128 | } 129 | 130 | std::pair ICP::RayNormalByIdx(int idx) { 131 | return { Eigen::Vector3d(points_[idx](0), points_[idx](1), 1.0), normals_[idx] }; 132 | } -------------------------------------------------------------------------------- /src/Utils/ICP.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by aska on 2019/11/9. 3 | // 4 | 5 | #pragma once 6 | #include "Common.h" 7 | #include "QuadTree.h" 8 | #include 9 | 10 | class ICP { 11 | public: 12 | ICP(std::vector& points, 13 | const std::vector& normals, 14 | const std::vector& weights); 15 | 16 | void FitRT(const std::vector& world_points, 17 | Eigen::Matrix3d* R, 18 | Eigen::Vector3d* T, 19 | int max_iter_num = 20); 20 | double FitRTSingleStep(const std::vector& world_points, Eigen::Matrix3d* R, Eigen::Vector3d* T); 21 | std::pair NearestRayNormal(const Eigen::Vector2d& point); 22 | std::pair RayNormalByIdx(int idx); 23 | std::unique_ptr quad_tree_; 24 | std::vector normals_; 25 | std::vector weights_; 26 | std::vector points_; 27 | int n_points_; 28 | }; -------------------------------------------------------------------------------- /src/Utils/KMeansClustering.h: -------------------------------------------------------------------------------- 1 | /*========================================================================= 2 | * 3 | * Copyright David Doria 2012 daviddoria@gmail.com 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0.txt 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * 17 | *=========================================================================*/ 18 | 19 | /* 20 | KMeans clustering is a method in which to form K (known) clusters of points from 21 | an unorganized set of input points. 22 | Data in this class is stored as an Eigen matrix, where the data points are column vectors. 23 | That is, if we have P N-D points, the matrix is N rows by P columns. 24 | Likewise, objects returned have the same structure (e.g. GetClusterCenters() returns an NxK matrix). 25 | */ 26 | 27 | #ifndef KMeansClustering_h 28 | #define KMeansClustering_h 29 | 30 | // STL 31 | #include 32 | 33 | // Eigen 34 | #include 35 | 36 | class KMeansClustering 37 | { 38 | public: 39 | 40 | /** Constructor. */ 41 | KMeansClustering(); 42 | 43 | /** Set the number of clusters to find. */ 44 | void SetK(const unsigned int k); 45 | 46 | /** Get the number of clusters to find. */ 47 | unsigned int GetK(); 48 | 49 | /** Get the cluster centers.*/ 50 | Eigen::MatrixXd GetClusterCenters() const; 51 | 52 | /** Set the cluster centers.*/ 53 | void SetClusterCenters(const Eigen::MatrixXd& clusterCenters); 54 | 55 | /** Get the point ids with a specified cluster membership. */ 56 | std::vector GetIndicesWithLabel(const unsigned int label) const; 57 | 58 | /** Get the points with a specified cluster membership. */ 59 | Eigen::MatrixXd GetPointsWithLabel(const unsigned int label) const; 60 | 61 | /** If this function is called, the randomness is removed for repeatability for testing. */ 62 | void SetRandom(const bool r); 63 | 64 | /** Set the points to cluster. */ 65 | void SetPoints(const Eigen::MatrixXd& points); 66 | 67 | /** Get the cluster membership of every point. */ 68 | std::vector GetLabels() const; 69 | 70 | /** Set which initialization method to use. */ 71 | void SetInitMethod(const int method); 72 | 73 | /** Choices of initialization methods */ 74 | enum InitMethodEnum{RANDOM, KMEANSPP, MANUAL}; 75 | 76 | /** Actually perform the clustering. */ 77 | void Cluster(); 78 | 79 | /** Compute the maximum likelihood estimate (MLE) of the variance. 80 | This assumes a spherical Gaussian model (as this is the basis of KMeans), 81 | which means the variance is a scalar, rather than a diagonal covariance matrix 82 | or a full covariance matrix.*/ 83 | float ComputeMLEVariance() const; 84 | 85 | /** Compute the maximum likelihood estimate (MLE) of the variance of just one cluster. */ 86 | float ComputeMLEVariance(const unsigned int clusterId) const; 87 | 88 | /** Compute the Bayesian Information Criterion as a measure of how well the model represents the data. */ 89 | float ComputeBIC() const; 90 | 91 | /** Compute the Bayesian Information Criterion as a measure of how well the model represents the data. */ 92 | float ComputeBIC(const unsigned int clusterId) const; 93 | 94 | protected: 95 | 96 | /** Randomly initialize cluster centers. */ 97 | void RandomInit(); 98 | 99 | /** Initialize cluster centers using the KMeans++ algorithm. */ 100 | void KMeansPPInit(); 101 | 102 | /** Get the membership of 'queryPoint'. */ 103 | unsigned int ClosestCluster(const Eigen::VectorXd& queryPoint); 104 | 105 | /** Get the id of the closest point to 'queryPoint'. */ 106 | unsigned int ClosestPointIndex(const Eigen::VectorXd& queryPoint); 107 | 108 | /** Get the distance between 'queryPoint' and its closest point. */ 109 | double ClosestPointDistance(const Eigen::VectorXd& queryPoint); 110 | 111 | /** Get the distance between 'queryPoint' and its closest point excluding 'excludedId'. */ 112 | double ClosestPointDistanceExcludingId(const Eigen::VectorXd& queryPoint, const unsigned int excludedId); 113 | 114 | /** Get the distance between 'queryPoint' and its closest point excluding 'excludedIds'. */ 115 | double ClosestPointDistanceExcludingIds(const Eigen::VectorXd& queryPoint, const std::vector excludedIds); 116 | 117 | /** Based on the current cluster membership, compute the cluster centers. */ 118 | void EstimateClusterCenters(); 119 | 120 | /** Construct an array of the closest cluster center to each point. */ 121 | void AssignLabels(); 122 | 123 | /** Determine if the membership of any point has changed. */ 124 | bool CheckChanged(const std::vector& labels, const std::vector& oldLabels); 125 | 126 | /** Get a random point inside the bounding box of the points. */ 127 | Eigen::VectorXd GetRandomPointInBounds(); 128 | 129 | /** Select a random index, with the probability of choosing an index weighted by the 'weights' vector. */ 130 | unsigned int SelectWeightedIndex(const Eigen::VectorXd weights); 131 | 132 | private: 133 | 134 | /** The label (cluster membership) of each point. */ 135 | std::vector Labels; 136 | 137 | /** Should the computation be random? If false, then it is repeatable (for testing). */ 138 | bool Random = true; 139 | 140 | /** The initialization method to use. */ 141 | int InitMethod = RANDOM; 142 | 143 | /** The number of clusters to find. */ 144 | unsigned int K = 3; 145 | 146 | /** The points to cluster. */ 147 | Eigen::MatrixXd Points; 148 | 149 | /** The current cluster centers. */ 150 | Eigen::MatrixXd ClusterCenters; 151 | }; 152 | 153 | #endif 154 | -------------------------------------------------------------------------------- /src/Utils/LSQR/lsqrSparse.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by aska on 2019/8/5. 3 | // 4 | 5 | #include "lsqrSparse.h" 6 | 7 | void lsqrSparse::SetMatrix(const std::vector &coord_r, 8 | const std::vector &coord_c, 9 | const std::vector &values) { 10 | coord_r_ = coord_r; 11 | coord_c_ = coord_c; 12 | values_ = values; 13 | } 14 | 15 | void lsqrSparse::Aprod1(unsigned int m, unsigned int n, const double *x, double *y) const { 16 | for (unsigned i = 0; i < coord_r_.size(); i++) { 17 | y[coord_r_[i]] += x[coord_c_[i]] * values_[i]; 18 | } 19 | } 20 | 21 | void lsqrSparse::Aprod2(unsigned int m, unsigned int n, double *x, const double *y) const { 22 | for (unsigned i = 0; i < coord_r_.size(); i++) { 23 | x[coord_c_[i]] += y[coord_r_[i]] * values_[i]; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/Utils/LSQR/lsqrSparse.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by aska on 2019/8/5. 3 | // 4 | 5 | #pragma once 6 | #include "lsqrBase.h" 7 | 8 | #include 9 | 10 | class lsqrSparse : public lsqrBase { 11 | public: 12 | lsqrSparse() = default; 13 | ~lsqrSparse() = default; 14 | void SetMatrix(const std::vector &coord_r, 15 | const std::vector &coord_c, 16 | const std::vector &values); 17 | void Aprod1(unsigned int m, unsigned int n, const double * x, double * y ) const; 18 | void Aprod2(unsigned int m, unsigned int n, double * x, const double * y ) const; 19 | private: 20 | std::vector coord_r_; 21 | std::vector coord_c_; 22 | std::vector values_; 23 | }; 24 | -------------------------------------------------------------------------------- /src/Utils/Loader.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by aska on 2019/4/12. 3 | // 4 | 5 | #include "Loader.h" 6 | -------------------------------------------------------------------------------- /src/Utils/Math.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by aska on 2019/9/4. 3 | // 4 | 5 | #include "Math.h" 6 | 7 | namespace Math { 8 | 9 | double CrossProd(const Eigen::Vector2d& a, const Eigen::Vector2d& b) { 10 | return a(0) * b(1) - a(1) * b(0); 11 | } 12 | 13 | double CrossProdAbs(const Eigen::Vector2d& a, const Eigen::Vector2d& b) { 14 | return std::abs(a(0) * b(1) - a(1) * b(0)); 15 | } 16 | 17 | std::pair GetOrthVectors(const Eigen::Vector3d& u) { 18 | Eigen::Vector3d v, w; 19 | if (u(0) * u(0) + u(1) * u(1) > 1e-9) { 20 | v = Eigen::Vector3d(u(1), -u(0), 0.0).normalized(); 21 | } else { 22 | v = Eigen::Vector3d(0.0, u(2), -u(1)).normalized(); 23 | } 24 | w = u.cross(v).normalized(); 25 | return {v, w}; 26 | } 27 | 28 | } -------------------------------------------------------------------------------- /src/Utils/Math.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by aska on 2019/9/4. 3 | // 4 | 5 | #pragma once 6 | #include 7 | 8 | #include 9 | 10 | namespace Math { 11 | 12 | double CrossProd(const Eigen::Vector2d& a, const Eigen::Vector2d& b); 13 | double CrossProdAbs(const Eigen::Vector2d& a, const Eigen::Vector2d& b); 14 | std::pair GetOrthVectors(const Eigen::Vector3d& u); 15 | } -------------------------------------------------------------------------------- /src/Utils/MeshICP.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by aska on 2020/1/1. 3 | // 4 | 5 | #ifndef ARAP_MESHICP_H 6 | #define ARAP_MESHICP_H 7 | 8 | #include "Common.h" 9 | #include "OctreeNew.h" 10 | #include 11 | #include 12 | 13 | struct MeshEvaluationResult { 14 | double average_distance; 15 | double max_distance; 16 | double global_scale; 17 | }; 18 | 19 | class MeshICP { 20 | public: 21 | MeshICP(const std::vector& my_points, 22 | const std::vector>& my_faces, 23 | const std::vector& gt_points, 24 | const std::vector>& gt_faces); 25 | MeshEvaluationResult Evaluate(std::vector* points_distances = nullptr); 26 | void FitRT(); 27 | double FitRTSingleStep(); 28 | double FitScaleSingleStep(); 29 | std::vector my_points_, gt_points_; 30 | std::vector> my_faces_, gt_faces_; 31 | std::vector>> gt_faces_at_points_; 32 | std::vector> gt_normals_; 33 | int sum_normals_; 34 | std::unique_ptr octree_; 35 | Eigen::Matrix3d R_; 36 | Eigen::Vector3d T_; 37 | double scale_ = 1.0; 38 | }; 39 | 40 | #endif //ARAP_MESHICP_H -------------------------------------------------------------------------------- /src/Utils/OctreeNew.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by aska on 2020/1/1. 3 | // 4 | 5 | #include "OctreeNew.h" 6 | 7 | OctreeNew::OctreeNew(const std::vector& points) : points_(points) { 8 | CHECK(!points_.empty()); 9 | n_points_ = points_.size(); 10 | Eigen::Vector3d ma(-1e10, -1e10, -1e10); 11 | Eigen::Vector3d mi(1e10, 1e10, 1e10); 12 | for (const auto& pt : points) { 13 | for (int t = 0; t < 3; t++) { 14 | ma(t) = std::max(ma(t), pt(t)); 15 | mi(t) = std::min(mi(t), pt(t)); 16 | } 17 | } 18 | corner_ = mi - Eigen::Vector3d(1e-8, 1e-8, 1e-8); 19 | double r = std::max({ ma(0) - mi(0), ma(1) - mi(1), ma(2) - mi(2) }) * (0.50 + 1e-4); 20 | p_.resize(n_points_); 21 | std::iota(p_.begin(), p_.end(), 0); 22 | 23 | root_ = BuildTreeNode(corner_, r, 0, n_points_); 24 | } 25 | 26 | OctreeNew::~OctreeNew() { 27 | delete root_; 28 | } 29 | 30 | OctreeNode* OctreeNew::BuildTreeNode(const Eigen::Vector3d& corner, double r, int l_bound, int r_bound) { 31 | if (l_bound >= r_bound) { 32 | return nullptr; 33 | } 34 | 35 | // LOG(INFO) << l_bound << " " << r_bound << " " << " " << corner(0) << " " << r; 36 | 37 | auto u = new OctreeNode(); 38 | u->r_ = r; 39 | u->o_ = corner + Eigen::Vector3d(r, r, r); 40 | 41 | if (l_bound + 1 == r_bound || r < 1e-9) { 42 | u->u_idx_ = p_[l_bound]; 43 | return u; 44 | } 45 | 46 | for (int i = l_bound; i < r_bound; i++) { 47 | int v = p_[i]; 48 | for (int k = 0; k < 3; k++) { 49 | CHECK(corner(k) < points_[v](k) + 1e-7); 50 | CHECK(corner(k) + r * 2.0 > points_[v](k) - 1e-7); 51 | } 52 | } 53 | 54 | std::vector sub_sizes(8, 0); 55 | for (int t = l_bound; t < r_bound; t++) { 56 | const auto& pt = points_[p_[t]]; 57 | int sub_idx = 0; 58 | for (int k = 0; k < 3; k++) { 59 | sub_idx |= (int(pt(k) > u->o_(k)) << k); 60 | } 61 | sub_sizes[sub_idx]++; 62 | } 63 | // LOG(INFO) << "sub_sizes: "; 64 | // for (int i = 0; i < 8; i++) { 65 | // LOG(INFO) << sub_sizes[i]; 66 | // } 67 | std::vector sub_sizes_cp = sub_sizes; 68 | for (int i = 1; i < 8; i++) { 69 | sub_sizes[i] += sub_sizes[i - 1]; 70 | } 71 | CHECK_EQ(sub_sizes.back(), r_bound - l_bound); 72 | std::vector p_cp; 73 | for (int t = l_bound; t < r_bound; t++) { 74 | p_cp.emplace_back(p_[t]); 75 | } 76 | // LOG(INFO) << "bf: " << p_[0] << " " << p_[1] << " " << p_[2] << " " << p_[3] << " " << p_[4]; 77 | // LOG(INFO) << "sub_sizes: " << sub_sizes[0] << " " << sub_sizes[7]; 78 | for (int t = l_bound; t < r_bound; t++) { 79 | const auto& pt = points_[p_cp[t - l_bound]]; 80 | int sub_idx = 0; 81 | for (int k = 0; k < 3; k++) { 82 | sub_idx |= (int(pt(k) > u->o_(k)) << k); 83 | } 84 | sub_sizes[sub_idx]--; 85 | int new_idx = sub_sizes[sub_idx] + l_bound; 86 | // LOG(INFO) << "sub_idx: " << sub_idx << " new_idx: " << new_idx << " p_cp[t]: " << p_cp[t]; 87 | p_[new_idx] = p_cp[t - l_bound]; 88 | } 89 | // LOG(INFO) << "af: " << p_[0] << " " << p_[1] << " " << p_[2] << " " << p_[3] << " " << p_[4]; 90 | 91 | int acc = 0; 92 | for (int t = 0; t < 8; t++) { 93 | u->sons_[t] = BuildTreeNode(corner + Eigen::Vector3d(t & 1, t >> 1 & 1, t >> 2 & 1) * r, 94 | r * 0.5, 95 | l_bound + acc, 96 | l_bound + acc + sub_sizes_cp[t]); 97 | acc += sub_sizes_cp[t]; 98 | } 99 | // CHECK_EQ(acc, r_bound - l_bound); 100 | return u; 101 | } 102 | 103 | int OctreeNew::NearestIdx(const Eigen::Vector3d& point) { 104 | /* 105 | double dis = 1e10; 106 | int ret = -1; 107 | for (int i = 0; i < n_points_; i++) { 108 | if (dis > (point - points_[i]).norm()) { 109 | dis = (point - points_[i]).norm(); 110 | ret = i; 111 | } 112 | } 113 | return ret; 114 | */ 115 | // CHECK_LT((points_[idx] - point).norm(), dis + 1e-6) << idx << " " << ret << " " 116 | // << points_[idx].transpose() << " " << points_[ret].transpose() << " " << point.transpose(); 117 | // CHECK_EQ(ret, NearestIdx(root_, point, 1e10)); 118 | int idx = NearestIdx(root_, point, 1e10); 119 | return idx; 120 | } 121 | 122 | int OctreeNew::NearestIdx(OctreeNode* u, const Eigen::Vector3d& point, double dis) { 123 | if (u == nullptr) { 124 | return -1; 125 | } 126 | double bound = 127 | std::max({ std::abs(point(0) - u->o_(0)), std::abs(point(1) - u->o_(1)), std::abs(point(2) - u->o_(2))}); 128 | // std::cout << point.transpose() << std::endl; 129 | // std::cout << u->o_.transpose() << std::endl; 130 | // std::cout << bound << " " << dis << " " << u->r_ << std::endl; 131 | if (bound > dis + u->r_) { 132 | return -1; 133 | } 134 | if (u->u_idx_ != -1) { 135 | return u->u_idx_; 136 | } 137 | int a = (point(0) > u->o_(0) - 1e-9); 138 | int b = (point(1) > u->o_(1) - 1e-9); 139 | int c = (point(2) > u->o_(2) - 1e-9); 140 | int idx = a + b * 2 + c * 4; 141 | int ret = -1; 142 | if (u->sons_[idx] != nullptr) { 143 | int tmp_ret = NearestIdx(u->sons_[idx], point, dis); 144 | double tmp_dis = 1e10; 145 | if (tmp_ret >= 0) { 146 | tmp_dis = (points_[tmp_ret] - point).norm(); 147 | } 148 | if (dis > tmp_dis) { 149 | dis = tmp_dis; 150 | ret = tmp_ret; 151 | } 152 | } 153 | for (int i = 0; i < 8; i++) { 154 | if (i != idx && u->sons_[i] != nullptr) { 155 | int tmp_ret = NearestIdx(u->sons_[i], point, dis); 156 | double tmp_dis = 1e10; 157 | if (tmp_ret >= 0) { 158 | tmp_dis = (points_[tmp_ret] - point).norm(); 159 | } 160 | if (dis > tmp_dis) { 161 | dis = tmp_dis; 162 | ret = tmp_ret; 163 | } 164 | } 165 | } 166 | return ret; 167 | } 168 | 169 | void OctreeNew::SearchingR(const Eigen::Vector3d& o, double r, std::vector* neighbors) { 170 | // for (int i = 0; i < n_points_; i++) { 171 | // if ((points_[i] - o).norm() < r) { 172 | // neighbors->emplace_back(i); 173 | // } 174 | // } 175 | SearchingR(root_, o, r, neighbors); 176 | } 177 | 178 | void OctreeNew::SearchingR(OctreeNode* u, const Eigen::Vector3d& o, double r, std::vector* neighbors) { 179 | Eigen::Vector3d bias = o - u->o_; 180 | double single_bias = 0.0; 181 | for (int t = 0; t < 3; t++) { 182 | single_bias = std::max(single_bias, std::abs(bias(t))); 183 | } 184 | if (single_bias > r + u->r_) { 185 | return; 186 | } 187 | if (u->u_idx_ != -1) { 188 | if ((points_[u->u_idx_] - o).norm() < r + 1e-9) { 189 | neighbors->emplace_back(u->u_idx_); 190 | } 191 | return; 192 | } 193 | for (int i = 0; i < 8; i++) { 194 | if (u->sons_[i] != nullptr) { 195 | SearchingR(u->sons_[i], o, r, neighbors); 196 | } 197 | } 198 | } 199 | -------------------------------------------------------------------------------- /src/Utils/OctreeNew.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by aska on 2020/1/1. 3 | // 4 | 5 | #pragma once 6 | #include "Common.h" 7 | #include 8 | #include 9 | 10 | struct OctreeNode { 11 | OctreeNode() = default; 12 | ~OctreeNode() { 13 | for (int i = 0; i < 8; i++) { 14 | if (sons_[i] != nullptr) { 15 | delete(sons_[i]); 16 | } 17 | } 18 | } 19 | OctreeNode* sons_[8] = { nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr }; 20 | Eigen::Vector3d o_; 21 | int u_idx_ = -1; 22 | double r_ = 0.0; 23 | }; 24 | 25 | class OctreeNew { 26 | public: 27 | OctreeNew(const std::vector& points); 28 | ~OctreeNew(); 29 | OctreeNode* BuildTreeNode(const Eigen::Vector3d& corner, double r, int l_bound, int r_bound); 30 | int NearestIdx(const Eigen::Vector3d& point); 31 | int NearestIdx(OctreeNode* u, const Eigen::Vector3d& point, double dis); 32 | void SearchingR(const Eigen::Vector3d& o, double r, std::vector* neighbors); 33 | void SearchingR(OctreeNode* u, const Eigen::Vector3d& o, double r, std::vector* neighbors); 34 | // data. 35 | OctreeNode* root_ = nullptr; 36 | double fineness_ = 0.0; 37 | std::vector points_; 38 | std::vector p_; 39 | Eigen::Vector3d corner_; 40 | int n_points_; 41 | }; 42 | -------------------------------------------------------------------------------- /src/Utils/QuadTree.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by aska on 2019/10/19. 3 | // 4 | 5 | #include "QuadTree.h" 6 | 7 | #include 8 | 9 | QuadTree::QuadTree(const std::vector& points) : points_(points) { 10 | CHECK(!points_.empty()); 11 | n_points_ = points_.size(); 12 | Eigen::Vector2d ma(-1e9, -1e9); 13 | Eigen::Vector2d mi(1e9, 1e9); 14 | for (const auto& pt : points) { 15 | for (int t = 0; t < 2; t++) { 16 | ma(t) = std::max(ma(t), pt(t)); 17 | mi(t) = std::min(mi(t), pt(t)); 18 | } 19 | } 20 | corner_ = mi - Eigen::Vector2d(1e-8, 1e-8); 21 | double r = std::max(ma(0) - mi(0), ma(1) - mi(1)) * (0.50 + 1e-4); 22 | p_.resize(n_points_); 23 | std::iota(p_.begin(), p_.end(), 0); 24 | 25 | root_ = BuildTreeNode(corner_, r, 0, n_points_); 26 | } 27 | 28 | QuadTree::~QuadTree() { 29 | delete root_; 30 | } 31 | 32 | QuadTreeNode* QuadTree::BuildTreeNode(const Eigen::Vector2d& corner, double r, int l_bound, int r_bound) { 33 | if (l_bound >= r_bound) { 34 | return nullptr; 35 | } 36 | auto u = new QuadTreeNode(); 37 | u->r_ = r; 38 | u->o_ = corner + Eigen::Vector2d(r, r); 39 | 40 | if (l_bound + 1 == r_bound || r < 1e-9) { 41 | u->u_idx_ = p_[l_bound]; 42 | return u; 43 | } 44 | 45 | for (int i = l_bound; i < r_bound; i++) { 46 | int v = p_[i]; 47 | CHECK(corner(0) < points_[v](0) + 1e-7); 48 | CHECK(corner(1) < points_[v](1) + 1e-7); 49 | CHECK(corner(0) + r * 2.0 > points_[v](0) - 1e-7); 50 | CHECK(corner(1) + r * 2.0 > points_[v](1) - 1e-7); 51 | } 52 | 53 | int mid = l_bound; 54 | { 55 | int tmp_l = l_bound; 56 | int tmp_r = r_bound; 57 | while (true) { 58 | while (tmp_l < tmp_r && points_[p_[tmp_l]](0) < u->o_(0)) { 59 | tmp_l++; 60 | } 61 | while (tmp_l < tmp_r && points_[p_[tmp_r - 1]](0) >= u->o_(0)) { 62 | tmp_r--; 63 | } 64 | if (tmp_l >= tmp_r) { 65 | break; 66 | } 67 | std::swap(p_[tmp_l], p_[tmp_r - 1]); 68 | } 69 | CHECK_EQ(tmp_l, tmp_r); 70 | mid = tmp_l; 71 | } 72 | 73 | int l_sec = l_bound; 74 | { 75 | int tmp_l = l_bound; 76 | int tmp_r = mid; 77 | while (true) { 78 | while (tmp_l < tmp_r && points_[p_[tmp_l]](1) < u->o_(1)) { 79 | tmp_l++; 80 | } 81 | while (tmp_l < tmp_r && points_[p_[tmp_r - 1]](1) >= u->o_(1)) { 82 | tmp_r--; 83 | } 84 | if (tmp_l >= tmp_r) { 85 | break; 86 | } 87 | std::swap(p_[tmp_l], p_[tmp_r - 1]); 88 | } 89 | CHECK_EQ(tmp_l, tmp_r); 90 | l_sec = tmp_l; 91 | } 92 | int r_sec = mid; 93 | { 94 | int tmp_l = mid; 95 | int tmp_r = r_bound; 96 | while (true) { 97 | while (tmp_l < tmp_r && points_[p_[tmp_l]](1) < u->o_(1)) { 98 | tmp_l++; 99 | } 100 | while (tmp_l < tmp_r && points_[p_[tmp_r - 1]](1) >= u->o_(1)) { 101 | tmp_r--; 102 | } 103 | if (tmp_l >= tmp_r) { 104 | break; 105 | } 106 | std::swap(p_[tmp_l], p_[tmp_r - 1]); 107 | } 108 | CHECK_EQ(tmp_l, tmp_r); 109 | r_sec = tmp_l; 110 | } 111 | u->sons_[0] = BuildTreeNode(corner, r * 0.5, l_bound, l_sec); 112 | u->sons_[1] = BuildTreeNode(corner + Eigen::Vector2d(0.0, r), r * 0.5, l_sec, mid); 113 | u->sons_[2] = BuildTreeNode(corner + Eigen::Vector2d(r, 0.0), r * 0.5, mid, r_sec); 114 | u->sons_[3] = BuildTreeNode(corner + Eigen::Vector2d(r, r), r * 0.5, r_sec, r_bound); 115 | return u; 116 | } 117 | 118 | Eigen::Vector2d QuadTree::NearestPoint(const Eigen::Vector2d& point) { 119 | return points_[NearestIdx(point)]; 120 | } 121 | 122 | int QuadTree::NearestIdx(const Eigen::Vector2d& point) { 123 | int idx = NearestIdx(root_, point, 1e9); 124 | return idx; 125 | } 126 | 127 | int QuadTree::NearestIdx(QuadTreeNode* u, const Eigen::Vector2d& point, double dis) { 128 | if (u == nullptr) { 129 | return -1; 130 | } 131 | double bound = std::max(std::abs(point(0) - u->o_(0)), std::abs(point(1) - u->o_(1))); 132 | // std::cout << point.transpose() << std::endl; 133 | // std::cout << u->o_.transpose() << std::endl; 134 | // std::cout << bound << " " << dis << " " << u->r_ << std::endl; 135 | if (bound > dis + u->r_) { 136 | return -1; 137 | } 138 | if (u->u_idx_ != -1) { 139 | return u->u_idx_; 140 | } 141 | int a = (point(0) > u->o_(0) - 1e-9); 142 | int b = (point(1) > u->o_(1) - 1e-9); 143 | int idx = a * 2 + b; 144 | int ret = -1; 145 | if (u->sons_[idx] != nullptr) { 146 | int tmp_ret = NearestIdx(u->sons_[idx], point, dis); 147 | double tmp_dis = 1e9; 148 | if (tmp_ret >= 0) { 149 | tmp_dis = (points_[tmp_ret] - point).norm(); 150 | } 151 | if (dis > tmp_dis) { 152 | dis = tmp_dis; 153 | ret = tmp_ret; 154 | } 155 | } 156 | for (int i = 0; i < 4; i++) { 157 | if (i != idx && u->sons_[i] != nullptr) { 158 | int tmp_ret = NearestIdx(u->sons_[i], point, dis); 159 | double tmp_dis = 1e9; 160 | if (tmp_ret >= 0) { 161 | tmp_dis = (points_[tmp_ret] - point).norm(); 162 | } 163 | if (dis > tmp_dis) { 164 | dis = tmp_dis; 165 | ret = tmp_ret; 166 | } 167 | } 168 | } 169 | return ret; 170 | } 171 | 172 | void QuadTree::SearchingR(const Eigen::Vector2d& o, double r, std::vector* neighbors) { 173 | for (int i = 0; i < n_points_; i++) { 174 | // if ((points_[i] - o).norm() < r) { 175 | // neighbors->emplace_back(i); 176 | // } 177 | } 178 | SearchingR(root_, o, r, neighbors); 179 | } 180 | 181 | void QuadTree::SearchingR(QuadTreeNode* u, const Eigen::Vector2d& o, double r, std::vector* neighbors) { 182 | Eigen::Vector2d bias = o - u->o_; 183 | double single_bias = 0.0; 184 | for (int t = 0; t < 2; t++) { 185 | single_bias = std::max(single_bias, std::abs(bias(t))); 186 | } 187 | if (single_bias > r + u->r_) { 188 | return; 189 | } 190 | if (u->u_idx_ != -1) { 191 | if ((points_[u->u_idx_] - o).norm() < r + 1e-9) { 192 | neighbors->emplace_back(u->u_idx_); 193 | } 194 | return; 195 | } 196 | for (int i = 0; i < 4; i++) { 197 | if (u->sons_[i] != nullptr) { 198 | SearchingR(u->sons_[i], o, r, neighbors); 199 | } 200 | } 201 | } 202 | -------------------------------------------------------------------------------- /src/Utils/QuadTree.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by aska on 2019/10/19. 3 | // 4 | #pragma once 5 | #include "Common.h" 6 | 7 | #include 8 | 9 | struct QuadTreeNode { 10 | QuadTreeNode() = default; 11 | ~QuadTreeNode() { 12 | for (int i = 0; i < 4; i++) { 13 | if (sons_[i] != nullptr) { 14 | delete(sons_[i]); 15 | } 16 | } 17 | } 18 | QuadTreeNode* sons_[4] = { nullptr, nullptr, nullptr, nullptr }; 19 | Eigen::Vector2d o_; 20 | int u_idx_ = -1; 21 | double r_ = 0.0; 22 | }; 23 | 24 | class QuadTree { 25 | public: 26 | QuadTree(const std::vector& points); 27 | ~QuadTree(); 28 | QuadTreeNode* BuildTreeNode(const Eigen::Vector2d& corner, double r, int l_bound, int r_bound); 29 | Eigen::Vector2d NearestPoint(const Eigen::Vector2d& point); 30 | int NearestIdx(const Eigen::Vector2d& point); 31 | int NearestIdx(QuadTreeNode* u, const Eigen::Vector2d& point, double dis); 32 | void SearchingR(const Eigen::Vector2d& o, double r, std::vector* neighbors); 33 | void SearchingR(QuadTreeNode* u, const Eigen::Vector2d& o, double r, std::vector* neighbors); 34 | // data. 35 | QuadTreeNode* root_ = nullptr; 36 | double fineness_ = 0.0; 37 | std::vector points_; 38 | std::vector p_; 39 | Eigen::Vector2d corner_; 40 | int n_points_; 41 | }; -------------------------------------------------------------------------------- /src/Utils/SegmentQuadTree.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by aska on 2019/12/13. 3 | // 4 | #pragma once 5 | #include "Common.h" 6 | 7 | struct SegmentQuadTreeNode { 8 | SegmentQuadTreeNode(const Eigen::Vector2d& o, double r) : o_(o), r_(r) {}; 9 | Eigen::Vector2d o_; 10 | double r_ = -1.0; 11 | SegmentQuadTreeNode* sons_[4] = { nullptr, nullptr, nullptr, nullptr }; 12 | std::vector indexes_; 13 | }; 14 | 15 | class SegmentQuadTree { 16 | public: 17 | SegmentQuadTree(const std::vector>& segments, 18 | const std::vector& tangs); 19 | void InsertSegment(SegmentQuadTreeNode* u, int seg_idx); 20 | void FindIntersections(const Eigen::Vector2d& o, 21 | const Eigen::Vector2d& v, 22 | double t_min, 23 | double t_max, 24 | std::vector>* intersections); 25 | void FindIntersections(SegmentQuadTreeNode* u, 26 | const Eigen::Vector2d& o, 27 | const Eigen::Vector2d& v, 28 | double t_min, 29 | double t_max, 30 | std::vector>* intersections); 31 | double FindIntersectionsTwoSegment(const Eigen::Vector2d& o, 32 | const Eigen::Vector2d& v, 33 | double t_min, 34 | double t_max, 35 | const std::pair& segment); 36 | bool IsSegmentInsideBox(const Eigen::Vector2d& o, 37 | double r, 38 | const std::pair& segment); 39 | bool IsSegmentIntersectBox(const Eigen::Vector2d& o, 40 | double r, 41 | const std::pair& segment); 42 | bool IsSegmentIntersectBox(const Eigen::Vector2d& o, 43 | double r, 44 | const Eigen::Vector2d& seg_o, 45 | const Eigen::Vector2d& seg_v, 46 | double t_min, 47 | double t_max); 48 | std::vector> segments_; 49 | std::vector tangs_; 50 | std::vector> node_pool_; 51 | SegmentQuadTreeNode* root_; 52 | }; -------------------------------------------------------------------------------- /src/Utils/SimpleRenderer.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by aska on 2019/4/12. 3 | // 4 | 5 | #include "SimpleRenderer.h" 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | SimpleRenderer::SimpleRenderer(int height, int width, double focal_length): 12 | height_(height), width_(width), focal_length_(focal_length) { 13 | } 14 | 15 | void SimpleRenderer::CacheData() { 16 | n_points_ = points_loader_->size(); 17 | n_traces_ = traces_loader_->size(); 18 | points_.clear(); 19 | for (int i = 0; i < n_points_; i++) { 20 | points_.push_back((*points_loader_)[i]); 21 | } 22 | traces_.clear(); 23 | for (int i = 0; i < n_traces_; i++) { 24 | traces_.push_back((*traces_loader_)[i]); 25 | } 26 | } 27 | 28 | void SimpleRenderer::CalcRays(int idx, std::vector &rays, double add_error) { 29 | rays.clear(); 30 | Vector3d pos = traces_[idx].block(0, 0, 3, 1); 31 | Vector3d to = traces_[idx].block(0, 1, 3, 1); 32 | Vector3d up = traces_[idx].block(0, 2, 3, 1); 33 | Vector3d axis_y = -up / up.norm(); 34 | Vector3d axis_z = to / to.norm(); 35 | Vector3d axis_x = axis_y.cross(axis_z); 36 | auto Rand = [](double L, double R) { 37 | return (double) std::rand() / (double) RAND_MAX * (R - L) + L; 38 | }; 39 | for (const auto &point : points_) { 40 | Vector3d bias = point - pos; 41 | Vector3d pt(bias.dot(axis_x), bias.dot(axis_y), bias.dot(axis_z)); 42 | pt /= pt(2); 43 | pt += Eigen::Vector3d(Rand(-add_error, add_error), Rand(-add_error, add_error), 0.0); 44 | rays.emplace_back(pt); 45 | } 46 | } 47 | 48 | void SimpleRenderer::OutputAllImages(std::string dir_path, double add_noise) { 49 | if (dir_path.back() != '/') { 50 | dir_path += '/'; 51 | } 52 | for (int idx = 0; idx < n_traces_; idx++) { 53 | cv::Mat img(height_, width_, CV_8UC1); 54 | std::memset(img.data, 0, height_ * width_); 55 | Vector3d pos = traces_[idx].block(0, 0, 3, 1); 56 | Vector3d to = traces_[idx].block(0, 1, 3, 1); 57 | Vector3d up = traces_[idx].block(0, 2, 3, 1); 58 | Vector3d axis_y = -up / up.norm(); 59 | Vector3d axis_z = to / to.norm(); 60 | Vector3d axis_x = axis_y.cross(axis_z); 61 | for (const auto &point : points_) { 62 | Vector3d bias = point - pos; 63 | Vector3d pt(bias.dot(axis_x), bias.dot(axis_y), bias.dot(axis_z)); 64 | pt /= pt(2); 65 | int a = std::round(pt(1) * focal_length_ + height_ * 0.5); 66 | int b = std::round(pt(0) * focal_length_ + width_ * 0.5); 67 | if (a >= 0 && a < height_ && b >= 0 && b < width_) { 68 | img.data[a * width_ + b] = 255; 69 | } 70 | } 71 | cv::imwrite(dir_path + std::to_string(idx) + ".png", img); 72 | } 73 | } 74 | 75 | void SimpleRenderer::OutputAllMats(std::string dir_path) { 76 | if (dir_path.back() != '/') { 77 | dir_path += '/'; 78 | } 79 | for (int idx = 0; idx < n_traces_; idx++) { 80 | cv::Mat img(height_, width_, CV_8UC1); 81 | std::memset(img.data, 0, height_ * width_); 82 | Vector3d pos = traces_[idx].block(0, 0, 3, 1); 83 | Vector3d to = traces_[idx].block(0, 1, 3, 1); 84 | Vector3d up = traces_[idx].block(0, 2, 3, 1); 85 | Vector3d axis_y = -up / up.norm(); 86 | Vector3d axis_z = to / to.norm(); 87 | Vector3d axis_x = axis_y.cross(axis_z); 88 | // pt = R(point - pos) 89 | // pt = R(point) - R(pos); 90 | Eigen::Matrix3d R; 91 | R.block(0, 0, 1, 3) = axis_x.transpose(); 92 | R.block(1, 0, 1, 3) = axis_y.transpose(); 93 | R.block(2, 0, 1, 3) = axis_z.transpose(); 94 | Eigen::Vector3d T; 95 | T = -R * pos; 96 | 97 | std::ofstream f(dir_path + std::to_string(idx) + ".txt"); 98 | for (int i = 0; i < 3; i++) { 99 | for (int j = 0; j < 3; j++) { 100 | f << R(i, j) << " "; 101 | } 102 | f << std::endl; 103 | } 104 | for (int i = 0; i < 3; i++) { 105 | f << T(i) << " "; 106 | } 107 | f << std::endl; 108 | f << width_ << " " << height_ << std::endl << focal_length_ << std::endl; 109 | f.close(); 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /src/Utils/SimpleRenderer.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by aska on 2019/4/12. 3 | // 4 | 5 | #pragma once 6 | #include 7 | #include 8 | #include "Loader.h" 9 | 10 | using Vector3d = Eigen::Vector3d; 11 | using Matrix3d = Eigen::Matrix3d; 12 | 13 | class SimpleRenderer { 14 | public: 15 | SimpleRenderer(int height, int weigth, double focal_length); 16 | void CacheData(); 17 | void CalcRays(int idx, std::vector &rays, double add_error = 0.0); 18 | void OutputAllImages(std::string dir_path, double add_noise = 0.0); 19 | void OutputAllMats(std::string dir_path); 20 | // data 21 | std::vector points_; 22 | std::vector traces_; 23 | PointsLoader *points_loader_; 24 | TracesLoader *traces_loader_; 25 | int height_, width_; 26 | int n_points_, n_traces_; 27 | double focal_length_; 28 | }; -------------------------------------------------------------------------------- /src/Utils/StopWatch.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by aska on 2019/9/11. 3 | // 4 | 5 | #include "StopWatch.h" 6 | 7 | StopWatch::StopWatch() { 8 | t_point_ = std::chrono::steady_clock::now(); 9 | } 10 | 11 | double StopWatch::TimeDuration() { 12 | std::chrono::steady_clock::time_point new_point = std::chrono::steady_clock::now(); 13 | std::chrono::duration time_span = 14 | std::chrono::duration_cast>(new_point - t_point_); 15 | t_point_ = new_point; 16 | return time_span.count(); 17 | } -------------------------------------------------------------------------------- /src/Utils/StopWatch.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by aska on 2019/9/11. 3 | // 4 | 5 | #pragma once 6 | #include 7 | 8 | class StopWatch { 9 | public: 10 | StopWatch(); 11 | ~StopWatch() = default; 12 | double TimeDuration(); 13 | std::chrono::steady_clock::time_point t_point_; 14 | }; 15 | -------------------------------------------------------------------------------- /src/Utils/Streamer.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by aska on 2019/9/11. 3 | // 4 | 5 | #include "Streamer.h" 6 | 7 | // ------------------------------ ImageStreamer --------------------------------------- 8 | 9 | ImageStreamer::ImageStreamer(const std::string& img_path, int n_images): 10 | n_images_(n_images), img_path_(img_path) { 11 | if (img_path_.back() != '/') { 12 | img_path_ += "/"; 13 | } 14 | Reset(); 15 | SwitchToNextFrame(); 16 | } 17 | 18 | void ImageStreamer::Reset() { 19 | current_img_idx_ = -1; 20 | idx_direction_ = 1; 21 | } 22 | 23 | int ImageStreamer::SwitchToNextFrame() { 24 | if (current_img_idx_ + idx_direction_ >= n_images_) { 25 | idx_direction_ = -1; 26 | } else if (current_img_idx_ + idx_direction_ < 0) { 27 | idx_direction_ = 1; 28 | } 29 | current_img_idx_ += idx_direction_; 30 | LOG(INFO) << img_path_ + std::to_string(current_img_idx_) + ".png"; 31 | img_ = cv::imread(img_path_ + std::to_string(current_img_idx_) + ".png"); 32 | if (current_img_idx_ > 0) { 33 | CHECK_EQ(img_.rows, height_); 34 | CHECK_EQ(img_.cols, width_); 35 | CHECK_EQ(img_.channels(), channels_); 36 | } else { 37 | height_ = img_.rows; 38 | width_ = img_.cols; 39 | channels_ = img_.channels(); 40 | } 41 | return 0; 42 | } 43 | 44 | uchar* ImageStreamer::CurrentPixelAt(int a, int b) { 45 | return ((uchar*) img_.data) + a * width_ + b; 46 | } 47 | 48 | uchar* ImageStreamer::CurrentFrame() { 49 | return (uchar*) img_.data; 50 | } 51 | 52 | // ------------------------------ SingleImageStreamer --------------------------------------- 53 | 54 | SingleImageStreamer::SingleImageStreamer(const std::string& img_path) { 55 | img_ = cv::imread(img_path); 56 | height_ = img_.rows; 57 | width_ = img_.cols; 58 | channels_ = img_.channels(); 59 | } 60 | 61 | uchar* SingleImageStreamer::CurrentPixelAt(int a, int b) { 62 | return ((uchar*) img_.data) + a * width_ + b; 63 | } 64 | 65 | uchar* SingleImageStreamer::CurrentFrame() { 66 | return (uchar*) img_.data; 67 | } -------------------------------------------------------------------------------- /src/Utils/Streamer.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by aska on 2019/9/11. 3 | // 4 | #pragma once 5 | 6 | #include "Common.h" 7 | 8 | class StreamerBase { 9 | public: 10 | StreamerBase() = default; 11 | virtual ~StreamerBase() = default; 12 | virtual int Height() = 0; 13 | virtual int Width() = 0; 14 | virtual int Channels() = 0; 15 | virtual uchar* CurrentFrame() = 0; 16 | virtual uchar* CurrentPixelAt(int a, int b) = 0; 17 | virtual int SwitchToNextFrame() { return 0; } 18 | virtual void Reset() {}; 19 | }; 20 | 21 | class ImageStreamer : public StreamerBase { 22 | public: 23 | ImageStreamer(const std::string& img_path, int n_images); 24 | ~ImageStreamer() final = default; 25 | int Height() final { return height_; } 26 | int Width() final { return width_; } 27 | int Channels() final { return channels_; } 28 | uchar* CurrentFrame() final; 29 | uchar* CurrentPixelAt(int a, int b) final; 30 | int SwitchToNextFrame() final; 31 | void Reset() final; 32 | std::string img_path_; 33 | int n_images_ = 0; 34 | int current_img_idx_ = -1; 35 | int idx_direction_ = 1; 36 | int height_; 37 | int width_; 38 | int channels_; 39 | cv::Mat img_; 40 | }; 41 | 42 | class SingleImageStreamer : public StreamerBase { 43 | public: 44 | SingleImageStreamer(const std::string& img_path); 45 | ~SingleImageStreamer() final = default; 46 | int Height() final { return height_; } 47 | int Width() final { return width_; } 48 | int Channels() final { return channels_; } 49 | uchar* CurrentFrame() final; 50 | uchar* CurrentPixelAt(int a, int b) final; 51 | std::string img_path_; 52 | int height_; 53 | int width_; 54 | int channels_; 55 | cv::Mat img_; 56 | }; -------------------------------------------------------------------------------- /src/Utils/Thinning.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Code for thinning a binary image using Zhang-Suen algorithm. 3 | * 4 | * Author: Nash (nash [at] opencv-code [dot] com) 5 | * Website: http://opencv-code.com 6 | */ 7 | #include 8 | 9 | /** 10 | * Perform one thinning iteration. 11 | * Normally you wouldn't call this function directly from your code. 12 | * 13 | * Parameters: 14 | * im Binary image with range = [0,1] 15 | * iter 0=even, 1=odd 16 | */ 17 | void thinningIteration(cv::Mat& img, int iter) 18 | { 19 | CV_Assert(img.channels() == 1); 20 | CV_Assert(img.depth() != sizeof(uchar)); 21 | CV_Assert(img.rows > 3 && img.cols > 3); 22 | 23 | cv::Mat marker = cv::Mat::zeros(img.size(), CV_8UC1); 24 | 25 | int nRows = img.rows; 26 | int nCols = img.cols; 27 | 28 | if (img.isContinuous()) { 29 | nCols *= nRows; 30 | nRows = 1; 31 | } 32 | 33 | int x, y; 34 | uchar *pAbove; 35 | uchar *pCurr; 36 | uchar *pBelow; 37 | uchar *nw, *no, *ne; // north (pAbove) 38 | uchar *we, *me, *ea; 39 | uchar *sw, *so, *se; // south (pBelow) 40 | 41 | uchar *pDst; 42 | 43 | // initialize row pointers 44 | pAbove = NULL; 45 | pCurr = img.ptr(0); 46 | pBelow = img.ptr(1); 47 | 48 | for (y = 1; y < img.rows-1; ++y) { 49 | // shift the rows up by one 50 | pAbove = pCurr; 51 | pCurr = pBelow; 52 | pBelow = img.ptr(y+1); 53 | 54 | pDst = marker.ptr(y); 55 | 56 | // initialize col pointers 57 | no = &(pAbove[0]); 58 | ne = &(pAbove[1]); 59 | me = &(pCurr[0]); 60 | ea = &(pCurr[1]); 61 | so = &(pBelow[0]); 62 | se = &(pBelow[1]); 63 | 64 | for (x = 1; x < img.cols-1; ++x) { 65 | // shift col pointers left by one (scan left to right) 66 | nw = no; 67 | no = ne; 68 | ne = &(pAbove[x+1]); 69 | we = me; 70 | me = ea; 71 | ea = &(pCurr[x+1]); 72 | sw = so; 73 | so = se; 74 | se = &(pBelow[x+1]); 75 | 76 | int A = (*no == 0 && *ne == 1) + (*ne == 0 && *ea == 1) + 77 | (*ea == 0 && *se == 1) + (*se == 0 && *so == 1) + 78 | (*so == 0 && *sw == 1) + (*sw == 0 && *we == 1) + 79 | (*we == 0 && *nw == 1) + (*nw == 0 && *no == 1); 80 | int B = *no + *ne + *ea + *se + *so + *sw + *we + *nw; 81 | int m1 = iter == 0 ? (*no * *ea * *so) : (*no * *ea * *we); 82 | int m2 = iter == 0 ? (*ea * *so * *we) : (*no * *so * *we); 83 | 84 | if (A == 1 && (B >= 2 && B <= 6) && m1 == 0 && m2 == 0) 85 | pDst[x] = 1; 86 | } 87 | } 88 | 89 | img &= ~marker; 90 | } 91 | 92 | /** 93 | * Function for thinning the given binary image 94 | * 95 | * Parameters: 96 | * src The source image, binary with range = [0,255] 97 | * dst The destination image 98 | */ 99 | void thinning(const cv::Mat& src, cv::Mat& dst) 100 | { 101 | dst = src.clone(); 102 | dst /= 255; // convert to binary image 103 | 104 | cv::Mat prev = cv::Mat::zeros(dst.size(), CV_8UC1); 105 | cv::Mat diff; 106 | 107 | do { 108 | thinningIteration(dst, 0); 109 | thinningIteration(dst, 1); 110 | cv::absdiff(dst, prev, diff); 111 | dst.copyTo(prev); 112 | } 113 | while (cv::countNonZero(diff) > 0); 114 | 115 | dst *= 255; 116 | } 117 | 118 | double CalcThinnedRatio(const cv::Mat& src, const cv::Mat& dst) { 119 | int n_edge_pixels = 0; 120 | int n_thinned_pixels = 0; 121 | int height = src.rows; 122 | int width = src.cols; 123 | for (int a = 0; a < height; a++) { 124 | for (int b = 0; b < width; b++) { 125 | if (!src.data[a * width + b]) { 126 | continue; 127 | } 128 | if (!dst.data[a * width + b]) { 129 | n_thinned_pixels++; 130 | } 131 | bool is_edge = false; 132 | for (int x = std::max(0, a - 1); !is_edge && x <= std::min(height - 1, a + 1); x++) { 133 | for (int y = std::max(0, b - 1); !is_edge && y <= std::min(width - 1, b + 1); y++) { 134 | if (!src.data[x * width + b]) { 135 | is_edge = true; 136 | } 137 | } 138 | } 139 | if (is_edge) { 140 | n_edge_pixels++; 141 | } 142 | } 143 | } 144 | if (!n_edge_pixels) { 145 | return 0.0; 146 | } 147 | return double(n_thinned_pixels) / double(n_edge_pixels); 148 | } 149 | 150 | void PartialThinning(const cv::Mat& src, cv::Mat& dst, double thershold = 0.2) { 151 | dst = src.clone(); 152 | dst /= 255; 153 | 154 | cv::Mat prev = cv::Mat::zeros(dst.size(), CV_8UC1); 155 | dst.copyTo(prev); 156 | 157 | double thinned_ratio = 1.0; 158 | do { 159 | thinningIteration(dst, 0); 160 | thinned_ratio = CalcThinnedRatio(prev, dst); 161 | // std::cout << thinned_ratio << std::endl; 162 | // cv::imshow("haha", dst * 255); 163 | // cv::waitKey(-1); 164 | dst.copyTo(prev); 165 | 166 | thinningIteration(dst, 1); 167 | thinned_ratio = CalcThinnedRatio(prev, dst); 168 | // std::cout << thinned_ratio << std::endl; 169 | // cv::imshow("haha", dst * 255); 170 | // cv::waitKey(-1); 171 | dst.copyTo(prev); 172 | } while (thinned_ratio > thershold); 173 | 174 | dst *= 255; 175 | } 176 | 177 | /** 178 | * This is an example on how to call the thinning funciton above 179 | */ 180 | /* 181 | int main() 182 | { 183 | cv::Mat src = cv::imread("image.png"); 184 | if (!src.data) 185 | return -1; 186 | 187 | cv::Mat bw; 188 | cv::cvtColor(src, bw, CV_BGR2GRAY); 189 | cv::threshold(bw, bw, 10, 255, CV_THRESH_BINARY); 190 | 191 | thinning(bw, bw); 192 | 193 | cv::imshow("src", src); 194 | cv::imshow("dst", bw); 195 | cv::waitKey(); 196 | return 0; 197 | } 198 | */ -------------------------------------------------------------------------------- /src/Utils/Utils.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by aska on 19-2-1. 3 | // 4 | 5 | #pragma once 6 | #include 7 | #include 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | namespace Utils { 14 | void SavePointsAsPly(std::string save_path, const std::vector &points); 15 | void SolveLinearSqrLSQR(int rows, 16 | int cols, 17 | const std::vector& coord_r, 18 | const std::vector& coord_c, 19 | const std::vector& values, 20 | const std::vector& B, 21 | std::vector &solution); 22 | void SolveLinearSqrStable(int rows, 23 | int cols, 24 | const std::vector& coord_r, 25 | const std::vector& coord_c, 26 | const std::vector& values, 27 | const std::vector& B, 28 | std::vector& solution); 29 | int QuadraticFitting(const std::vector& xs, const std::vector& ys, double *a, double *b, double* c); 30 | int LinearFitting(const std::vector& xs, const std::vector &ys, double *a, double *b); 31 | void SplineFitting(const std::vector& in_path, 32 | double resample_step, 33 | std::vector* out_path); 34 | void GetOpticalFlow(const cv::Mat &img_0, const cv::Mat &img_1, cv::Mat* flow_img, bool blur = true); 35 | Eigen::Matrix3d GetLeftCrossProdMatrix(const Eigen::Vector3d &X); 36 | Eigen::Matrix3d GetRightCrossProdMatrix(const Eigen::Vector3d &X); 37 | void OutputCurves(std::string save_path, 38 | const std::vector > &curves); 39 | void OutputCurvesAsOBJ(const std::string& save_path, 40 | const std::vector& points, 41 | const std::vector>& edges); 42 | void OutputTriMeshAsOBJ(const std::string& save_path, 43 | const Eigen::MatrixXd& verts, 44 | const Eigen::MatrixXi& faces); //nenglun 45 | void OutputTriMeshAsOBJ(const std::string& save_path, 46 | const std::vector& points, 47 | const std::vector>& faces); 48 | void MergeTriMeshes(std::vector& in_verts_list, 49 | std::vector& in_faces_list, 50 | Eigen::MatrixXd& res_verts, 51 | Eigen::MatrixXi& res_faces);//nenglun 52 | 53 | void ReadOBJMesh(const std::string& file_name, 54 | std::vector* points, 55 | std::vector>* faces); 56 | void ReadOBJCurves(const std::string& file_name, 57 | std::vector* points, 58 | std::vector>* edges); 59 | 60 | Eigen::Vector3d ImageCoordToCamera(const Eigen::Vector2d& x, int height, int width, double focal_length); 61 | // double CompareTwoPointCloud(const std::vector& A, const std::vector& B); 62 | std::pair GetAABB(const std::vector& points); 63 | std::pair GetAABB(const std::vector& points); 64 | } 65 | -------------------------------------------------------------------------------- /static/teaser.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Totoro97/Vid2Curve/47c379dec5cca2e2de123a392e0b1f93ceb1048a/static/teaser.png --------------------------------------------------------------------------------