├── insight3d ├── todo.txt ├── remake ├── ui_state.cpp ├── ui_treeview.h ├── core_constants.cpp ├── core_constants.h ├── core_structures.cpp ├── tool_typical_includes.h ├── ui_list.h ├── cv_extensions.h ├── tool_image.h ├── ui_epipolars.h ├── geometry_textures.h ├── tool_extrude.h ├── main.cpp ├── portability.h ├── mvg_normalization.h ├── ui_icons.h ├── tool_coordinates.h ├── core_state.cpp ├── tool_matching.h ├── tool_resection.h ├── gui_style.h ├── mvg_decomposition.h ├── tool_points.h ├── tool_edit.h ├── tool_file.h ├── Makefile ├── tool_polygons.h ├── geometry_routines.h ├── mvg_autocalibration.h ├── interface_sdl.h ├── mvg_camera.h ├── ui_shot_mode.h ├── application.h ├── mvg_thresholds.h ├── tool_plane_extraction.h ├── tool_triangulation.h ├── actions.h ├── interface_opengl.h ├── ui_inspection_mode.h ├── core_state.h ├── core_debug.h ├── ui_list.cpp ├── geometry_export.h ├── OpenCV_Release.props ├── geometry_queries.h ├── ui_visualization_helpers.h ├── tool_calibration.h ├── ui_workflow.h ├── interface_opengl.cpp ├── ui_events.h ├── tool_selection.h ├── ui_visualization_point.h ├── mvg_matching.h ├── interface_filesystem.h ├── OpenCV_Debug.props ├── geometry_publish.h ├── mvg_normalization.cpp ├── ui_context.h ├── ui_constants.h ├── interface_sdl.cpp ├── ui_selection.h ├── ui_constants.cpp ├── geometry_loader.h ├── tool_coordinates.cpp ├── ui_epipolars.cpp ├── mvg_resection.h ├── application.cpp ├── mvg_decomposition.cpp ├── ui_core.h ├── mvg_camera.cpp ├── core_debug.cpp ├── ui_state.h ├── tool_resection.cpp ├── ui_visualization_helpers.cpp ├── geometry_queries.cpp ├── interface_opencv.h ├── core_math_routines.h ├── tool_polygons.cpp ├── interface_filesystem.cpp ├── mvg_triangulation.h ├── core_image_loader.h ├── geometry_textures.cpp ├── tool_extrude.cpp ├── tool_edit.cpp ├── geometry_routines.cpp ├── ui_shot_mode.cpp ├── ui_visualization.h ├── actions.cpp ├── tool_file.cpp ├── core_structures.h ├── cv_extensions.cpp ├── tool_image.cpp └── ui_workflow.cpp ├── slam.png ├── slam_and_editor_ui.png ├── .gitignore ├── README.txt ├── README.md ├── HOW_TO_BUILD_WINDOWS_VISUALSTUDIO.txt └── insight3d.sln /insight3d/todo.txt: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /insight3d/remake: -------------------------------------------------------------------------------- 1 | make clean; make 2 | -------------------------------------------------------------------------------- /slam.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lukasmach/insight3d/HEAD/slam.png -------------------------------------------------------------------------------- /slam_and_editor_ui.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lukasmach/insight3d/HEAD/slam_and_editor_ui.png -------------------------------------------------------------------------------- /insight3d/ui_state.cpp: -------------------------------------------------------------------------------- 1 | #include "ui_state.h" 2 | 3 | DYNAMIC_STRUCTURE(Groups, Group); 4 | 5 | UI_State ui_state; 6 | -------------------------------------------------------------------------------- /insight3d/ui_treeview.h: -------------------------------------------------------------------------------- 1 | void ui_treeview_initialize(); 2 | void ui_treeview_unfold_pictures(); 3 | void ui_treeview_poll(AG_Event * event); 4 | void ui_treeview_changed(AG_Event * event); 5 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files 2 | *.slo 3 | *.lo 4 | *.o 5 | 6 | # Compiled Dynamic libraries 7 | *.so 8 | *.dylib 9 | 10 | # Compiled Static libraries 11 | *.lai 12 | *.la 13 | *.a 14 | -------------------------------------------------------------------------------- /insight3d/core_constants.cpp: -------------------------------------------------------------------------------- 1 | #include "core_constants.h" 2 | 3 | // enviroment variables and constants 4 | const double CORE_PI = 3.14159265358979323846; 5 | const double CORE_PRECISION = 0.000001; 6 | -------------------------------------------------------------------------------- /insight3d/core_constants.h: -------------------------------------------------------------------------------- 1 | #ifndef __CORE_CONSTANTS 2 | #define __CORE_CONSTANTS 3 | 4 | // enviroment variables and constants 5 | extern const double CORE_PI; 6 | extern const double CORE_PRECISION; 7 | enum Core_Axes { X, Y, Z, W }; 8 | 9 | #endif 10 | -------------------------------------------------------------------------------- /insight3d/core_structures.cpp: -------------------------------------------------------------------------------- 1 | #include "core_structures.h" 2 | #include 3 | 4 | pthread_mutex_t print_mutex = PTHREAD_MUTEX_INITIALIZER; 5 | 6 | // simple routines 7 | bool dyn_found(const size_t index) 8 | { 9 | return index != SIZE_MAX; 10 | } 11 | -------------------------------------------------------------------------------- /insight3d/tool_typical_includes.h: -------------------------------------------------------------------------------- 1 | #ifndef __TOOL_TYPICAL_INCLUDES 2 | #define __TOOL_TYPICAL_INCLUDES 3 | 4 | #include "geometry_queries.h" 5 | #include "ui_core.h" 6 | #include "ui_context.h" 7 | #include "tool_core.h" 8 | #include "tool_selection.h" 9 | 10 | #endif 11 | -------------------------------------------------------------------------------- /insight3d/ui_list.h: -------------------------------------------------------------------------------- 1 | #ifndef __UI_LIST 2 | #define __UI_LIST 3 | 4 | #include "ui_state.h" 5 | #include "ui_core.h" 6 | 7 | void ui_list_update(); 8 | void ui_next_shot(const GUI_Event_Descriptor event); 9 | void ui_prev_shot(const GUI_Event_Descriptor event); 10 | 11 | #endif 12 | -------------------------------------------------------------------------------- /insight3d/cv_extensions.h: -------------------------------------------------------------------------------- 1 | #ifndef __CV_EXTENSIONS 2 | #define __CV_EXTENSIONS 3 | 4 | #include "interface_opencv.h" 5 | 6 | void cvComputeRQDecomposition(CvMat * matrixM, CvMat * matrixR, CvMat * matrixQ, CvMat * matrixQx, CvMat * matrixQy, CvMat * matrixQz, CvPoint3D64f * eulerAngles); 7 | 8 | #endif 9 | -------------------------------------------------------------------------------- /insight3d/tool_image.h: -------------------------------------------------------------------------------- 1 | #ifndef __TOOL_IMAGE 2 | #define __TOOL_IMAGE 3 | 4 | #include "tool_typical_includes.h" 5 | #include 6 | #include 7 | #include "geometry_routines.h" 8 | 9 | void tool_image_create(); 10 | void tool_image_colorize(); 11 | void tool_image_pinhole_deform(); 12 | 13 | #endif 14 | -------------------------------------------------------------------------------- /insight3d/ui_epipolars.h: -------------------------------------------------------------------------------- 1 | #ifndef __UI_EPIPOLARS 2 | #define __UI_EPIPOLARS 3 | 4 | #include "core_debug.h" 5 | #include "geometry_structures.h" 6 | #include "ui_state.h" 7 | #include "ui_core.h" 8 | 9 | // displays epipolars 10 | void ui_epipolars_display(const size_t shot_id, const size_t point_id); 11 | 12 | #endif 13 | -------------------------------------------------------------------------------- /insight3d/geometry_textures.h: -------------------------------------------------------------------------------- 1 | #ifndef __GEOMETRY_TEXTURES 2 | #define __GEOMETRY_TEXTURES 3 | 4 | #include "core_structures.h" 5 | #include "core_image_loader.h" 6 | #include "geometry_structures.h" 7 | 8 | void geometry_extract_all_textures(); 9 | void geometry_extract_texture(const size_t polygon_id); 10 | 11 | #endif 12 | 13 | -------------------------------------------------------------------------------- /insight3d/tool_extrude.h: -------------------------------------------------------------------------------- 1 | #ifndef __TOOL_EXTRUDE 2 | #define __TOOL_EXTRUDE 3 | 4 | #include "core_math_routines.h" 5 | #include "geometry_structures.h" 6 | 7 | // do extrusion on the ordered set of selected vertices 8 | bool tool_extrude_to_ground(double * ground, Selected_Items * selected_vertices, size_t group = 0); 9 | 10 | #endif 11 | -------------------------------------------------------------------------------- /insight3d/main.cpp: -------------------------------------------------------------------------------- 1 | #include "application.h" 2 | 3 | FILE _iob[] = { *stdin, *stdout, *stderr }; 4 | extern "C" FILE * __cdecl __iob_func(void) { return _iob; } 5 | 6 | int main(int argc, char* argv[]) 7 | { 8 | // start, do stuff and finish happily 9 | return initialization() && main_loop() && release() ? EXIT_SUCCESS : EXIT_FAILURE; 10 | } 11 | -------------------------------------------------------------------------------- /insight3d/portability.h: -------------------------------------------------------------------------------- 1 | 2 | // some compillers don't define SIZE_MAX 3 | #ifndef SIZE_MAX 4 | #define SIZE_MAX ((size_t)-1) 5 | #endif 6 | 7 | // comparing strings 8 | #ifndef _MSC_VER 9 | #define strcmpi strcasecmp 10 | #endif 11 | 12 | // define LINUX if we're on real operating system 13 | #ifndef _MSC_VER 14 | #define LINUX 15 | #endif 16 | 17 | -------------------------------------------------------------------------------- /insight3d/mvg_normalization.h: -------------------------------------------------------------------------------- 1 | #ifndef __NORMALIZATION 2 | #define __NORMALIZATION 3 | 4 | #include "core_debug.h" 5 | #include "interface_opencv.h" 6 | 7 | // normalize image points so that their centroid and typical magnitude of 8 | // the vector is (1, 1) 9 | bool mvg_normalize_points(CvMat * points, CvMat * H, double * output_scale = NULL); 10 | 11 | #endif 12 | -------------------------------------------------------------------------------- /insight3d/ui_icons.h: -------------------------------------------------------------------------------- 1 | const int UI_ICON_WIDTH = 16; 2 | const int UI_ICON_HEIGHT = 16; 3 | enum UI_ICONS_QUALITY{ UI_ICONS_NEUTRAL = 0, UI_ICONS_GOODGOOD = 1, UI_ICONS_GOOD = 2, UI_ICONS_BAD = 3, UI_ICONS_BADBAD = 4 }; 4 | enum UI_ICONS_BOOL { UI_ICONS_TRUE = 0, UI_ICONS_FALSE = 5 }; 5 | const int UI_ICONS_QUALITY_COUNT = 5; 6 | const int UI_ICONS_COUNT = 10; 7 | 8 | bool ui_icons_initialize(); 9 | -------------------------------------------------------------------------------- /insight3d/tool_coordinates.h: -------------------------------------------------------------------------------- 1 | #ifndef __TOOL_COORDINATES 2 | #define __TOOL_COORDINATES 3 | 4 | #include "tool_typical_includes.h" 5 | #include "geometry_routines.h" 6 | 7 | void tool_coordinates_create(); 8 | void coordinates_reorient_using_current_camera(); 9 | bool coordinates_rotate_all_cameras(size_t shot_id); 10 | bool coordinates_apply_homography_to_cameras(CvMat * H); 11 | 12 | #endif 13 | -------------------------------------------------------------------------------- /insight3d/core_state.cpp: -------------------------------------------------------------------------------- 1 | #include "core_state.h" 2 | 3 | Core_State core_state; 4 | 5 | // initialize core state 6 | bool core_initialize() 7 | { 8 | memset(&core_state, 0, sizeof(core_state)); 9 | 10 | // initialize random number generator and timing 11 | srand(time(NULL)); 12 | core_state.last_ticks = SDL_GetTicks(); 13 | core_state.ticks = SDL_GetTicks(); 14 | core_state.running = true; 15 | 16 | return true; 17 | } 18 | -------------------------------------------------------------------------------- /insight3d/tool_matching.h: -------------------------------------------------------------------------------- 1 | #ifndef __TOOL_MATCHING 2 | #define __TOOL_MATCHING 3 | 4 | #include "tool_typical_includes.h" 5 | #include "ui_list.h" 6 | #include "mvg_matching.h" 7 | 8 | // tool registration and public routines 9 | void tool_matching_create(); 10 | void tool_matching_standard(); 11 | void tool_matching_remove_conflicts(); 12 | 13 | // additional shot info 14 | struct Matching_Shot 15 | { 16 | int width, height; // size of loaded shot 17 | }; 18 | 19 | #endif 20 | -------------------------------------------------------------------------------- /insight3d/tool_resection.h: -------------------------------------------------------------------------------- 1 | #ifndef __TOOL_RESECTION 2 | #define __TOOL_RESECTION 3 | 4 | #include "tool_typical_includes.h" 5 | #include "geometry_routines.h" 6 | #include "ui_list.h" 7 | #include "actions.h" 8 | #include "sba.h" 9 | 10 | void tool_resection_create(); 11 | void tool_resection_current_camera(); 12 | void tool_resection_all_uncalibrated(); 13 | void tool_resection_all(); 14 | void tool_resection_all_enough(); 15 | void tool_resection_all_lattice(); 16 | void tool_resection_sydney(); 17 | 18 | #endif 19 | 20 | -------------------------------------------------------------------------------- /insight3d/gui_style.h: -------------------------------------------------------------------------------- 1 | #ifndef GUI_STYLE 2 | #define GUI_STYLE 3 | 4 | #include "gui.h" 5 | 6 | void gui_style_menu_item(GUI_Panel * panel); 7 | void gui_style_background(GUI_Panel * panel); 8 | void gui_style_tab_button(GUI_Panel * panel); 9 | void gui_style_tab_content(GUI_Panel * panel); 10 | void gui_style_label(GUI_Panel * panel); 11 | void gui_style_checkbox(GUI_Panel * panel); 12 | void gui_style_radio(GUI_Panel * panel); 13 | void gui_style_button(GUI_Panel * panel); 14 | void gui_style_separator(GUI_Panel * panel); 15 | 16 | #endif 17 | -------------------------------------------------------------------------------- /insight3d/mvg_decomposition.h: -------------------------------------------------------------------------------- 1 | #ifndef __MVG_DECOMPOSITION 2 | #define __MVG_DECOMPOSITION 3 | 4 | #include "core_debug.h" 5 | #include "interface_opencv.h" 6 | 7 | // decomposition of projection matrix into rotation, translation and internal calibration 8 | bool mvg_finite_projection_matrix_decomposition(CvMat * const P, CvMat * const K, CvMat * const R, CvMat * const T); 9 | 10 | // assemble projection matrix 11 | void mvg_assemble_projection_matrix(CvMat * internal_calibration, CvMat * rotation, CvMat * translation, CvMat * projection); 12 | 13 | #endif 14 | -------------------------------------------------------------------------------- /insight3d/tool_points.h: -------------------------------------------------------------------------------- 1 | #ifndef __TOOL_POINTS 2 | #define __TOOL_POINTS 3 | 4 | #include "tool_typical_includes.h" 5 | 6 | void tool_points_create(); 7 | void tool_points_key(); 8 | bool tool_points_mouse_down(double x, double y, int button); 9 | void tool_points_move(double x, double y); 10 | void tool_points_dragging(double x, double y, int button); 11 | void tool_points_dragging_done(double x1, double y1, double x2, double y2, int button); 12 | void tool_points_click(double x, double y, int button); 13 | void tool_points_begin(); 14 | void tool_points_end(); 15 | 16 | #endif 17 | -------------------------------------------------------------------------------- /insight3d/tool_edit.h: -------------------------------------------------------------------------------- 1 | #ifndef __TOOL_EDIT 2 | #define __TOOL_EDIT 3 | 4 | #include "tool_typical_includes.h" 5 | #include "interface_opengl.h" 6 | #include "geometry_structures.h" 7 | #include "geometry_loader.h" 8 | #include "geometry_export.h" 9 | #include "ui_core.h" 10 | #include "ui_inspection_mode.h" 11 | #include "ui_shot_mode.h" 12 | #include "ui_visualization_helpers.h" 13 | #include "ui_visualization_point.h" 14 | #include "ui_visualization.h" 15 | #include "ui_selection.h" 16 | #include "ui_list.h" 17 | #include "ui_epipolars.h" 18 | 19 | void tool_edit_create(); 20 | 21 | #endif 22 | -------------------------------------------------------------------------------- /insight3d/tool_file.h: -------------------------------------------------------------------------------- 1 | #ifndef __TOOL_FILE 2 | #define __TOOL_FILE 3 | 4 | #include "tool_typical_includes.h" 5 | #include "interface_opengl.h" 6 | #include "geometry_structures.h" 7 | #include "geometry_loader.h" 8 | #include "geometry_export.h" 9 | #include "ui_core.h" 10 | #include "ui_inspection_mode.h" 11 | #include "ui_shot_mode.h" 12 | #include "ui_visualization_helpers.h" 13 | #include "ui_visualization_point.h" 14 | #include "ui_visualization.h" 15 | #include "ui_selection.h" 16 | #include "ui_list.h" 17 | #include "ui_epipolars.h" 18 | 19 | void tool_file_create(); 20 | 21 | #endif 22 | -------------------------------------------------------------------------------- /insight3d/Makefile: -------------------------------------------------------------------------------- 1 | SOURCES=$(wildcard *.cpp) 2 | OBJECTS=$(patsubst %.cpp,%.o,$(SOURCES)) 3 | DEBUG= -O3 4 | ANN_INCLUDE= -I./ann_1.1.1/include/ 5 | 6 | all: insight 7 | 8 | insight: $(OBJECTS) sift_detector 9 | g++ $(DEBUG) -o insight *.o `pkg-config --libs opencv libxml-2.0 sdl gtk+-2.0` ./sift/lib/libfeat.a $(AGARLIB) -llapack -lblas -lGL -lGLU ./sba/libsba.a ./ann_1.1.1/lib/libANN.a 10 | 11 | sift_detector: 12 | make -C ./sift 13 | 14 | %.o: %.cpp 15 | g++ $(DEBUG) -c `pkg-config --cflags opencv libxml-2.0 sdl gtk+-2.0` $(ANN_INCLUDE) $< 16 | 17 | clean: 18 | rm *.o 19 | rm ./insight 20 | 21 | 22 | -------------------------------------------------------------------------------- /insight3d/tool_polygons.h: -------------------------------------------------------------------------------- 1 | #ifndef __TOOL_POLYGONS 2 | #define __TOOL_POLYGONS 3 | 4 | #include "tool_typical_includes.h" 5 | #include "tool_points.h" 6 | 7 | void tool_polygons_create(); 8 | void tool_polygons_key(); 9 | bool tool_polygons_mouse_down(double x, double y, int button); 10 | void tool_polygons_move(double x, double y); 11 | void tool_polygons_dragging(double x, double y, int button); 12 | void tool_polygons_dragging_done(double x1, double y1, double x2, double y2, int button); 13 | void tool_polygons_click(double x, double y, int button); 14 | void tool_polygons_begin(); 15 | void tool_polygons_end(); 16 | 17 | #endif 18 | -------------------------------------------------------------------------------- /insight3d/geometry_routines.h: -------------------------------------------------------------------------------- 1 | #ifndef __GEOMETRY_ROUTINES 2 | #define __GEOMETRY_ROUTINES 3 | 4 | #include "core_debug.h" 5 | #include "geometry_structures.h" 6 | #include "mvg_decomposition.h" 7 | 8 | // decompose projective matrix into rotation, translation and internal calibration matrix 9 | // note check this 10 | bool geometry_calibration_from_P(const size_t shot_id); 11 | 12 | // assemble projective matrix from rotation, translation and internal calibration matrix 13 | void geometry_calibration_from_decomposed_matrices(const size_t shot_id); 14 | 15 | // lattice test 16 | // todo check for points out of picture 17 | bool geometry_lattice_test(const size_t shot_id); 18 | 19 | #endif 20 | -------------------------------------------------------------------------------- /insight3d/mvg_autocalibration.h: -------------------------------------------------------------------------------- 1 | #ifndef __MVG_AUTOCALIBRATION 2 | #define __MVG_AUTOCALIBRATION 3 | 4 | #include "core_debug.h" 5 | #include "interface_opencv.h" 6 | #include "mvg_decomposition.h" 7 | 8 | // perform autocalibration using absolute quadric 9 | bool mvg_autocalibration(CvMat ** Ps, double * principal_points, const size_t n, CvMat ** Xs, const size_t m); 10 | 11 | // get the coefficient in autocalibrating equations 12 | double q(CvMat * P, int i, int j, int c); 13 | 14 | // perform autocalibration using absolute quadric 15 | bool mvg_autocalibration_2(CvMat ** Ps, double * principal_points, const size_t n, CvMat ** Xs, const size_t m, CvMat ** pi_infinity = NULL, bool affine = false); 16 | 17 | #endif 18 | -------------------------------------------------------------------------------- /insight3d/interface_sdl.h: -------------------------------------------------------------------------------- 1 | #ifndef __INTERFACE_SDL 2 | #define __INTERFACE_SDL 3 | 4 | #include "SDL/SDL.h" 5 | 6 | // SDL initialization 7 | // note unused when using AgarGUI, but might be useful someday 8 | void sdl_initialize(int window_width, int window_height); 9 | 10 | // reset keys status to false 11 | void sdl_clear_keys(Uint8 * keys, bool * clear_keys, size_t keys_length); 12 | 13 | // map rgb color defined as vector 14 | Uint32 sdl_map_rgb_vector(const SDL_PixelFormat * const format, const double color[3]); 15 | 16 | // button is mouse wheel 17 | bool sdl_wheel_button(int button); 18 | 19 | // get modifiers 20 | bool sdl_shift_pressed(); 21 | bool sdl_ctrl_pressed(); 22 | bool sdl_alt_pressed(); 23 | 24 | #endif 25 | -------------------------------------------------------------------------------- /insight3d/mvg_camera.h: -------------------------------------------------------------------------------- 1 | #ifndef __MVG_CAMERA 2 | #define __MVG_CAMERA 3 | 4 | #include "core_debug.h" 5 | #include "interface_opencv.h" 6 | 7 | // computes projective depth of a point X with respect to finite camera P 8 | double mvg_projective_depth(CvMat * P, CvMat * X); 9 | 10 | // returns true if the point is in front of finite camera 11 | bool mvg_point_in_front_of_camera(CvMat * P, CvMat * X); 12 | 13 | // extracts canonical pair of projective matrices from fundamental matrix 14 | bool mvg_extract_Ps_from_F(CvMat * F, CvMat * P1, CvMat * P2); 15 | 16 | // calculates fundamental matrix for a pair of views given their projective matrices 17 | bool mvg_calculate_F_from_Ps(CvMat * P1, CvMat * P2, CvMat * F); 18 | 19 | #endif 20 | -------------------------------------------------------------------------------- /insight3d/ui_shot_mode.h: -------------------------------------------------------------------------------- 1 | #ifndef __UI_SHOT_MODE 2 | #define __UI_SHOT_MODE 3 | 4 | #include "interface_sdl.h" 5 | #include "core_structures.h" 6 | #include "core_math_routines.h" 7 | #include "ui_state.h" 8 | #include "ui_selection.h" 9 | 10 | // mode switching 11 | void ui_switch_to_shot_mode(); 12 | 13 | // process mouse click events in shot mode 14 | void ui_shot_mouse_click(); 15 | 16 | // respond to selection box in shot mode 17 | void ui_shot_mouse_selection(); 18 | 19 | // switch current shot (when the user works in shot mode and decides to switch to another image/camera) 20 | bool ui_switch_shot(size_t shot_id); 21 | 22 | // process user input (in shot mode) 23 | void ui_update_shot(const Uint32 delta_time); 24 | 25 | #endif 26 | -------------------------------------------------------------------------------- /insight3d/application.h: -------------------------------------------------------------------------------- 1 | #ifndef __APPLICATION 2 | #define __APPLICATION 3 | 4 | #include "geometry_structures.h" 5 | #include "core_image_loader.h" 6 | #include "gui.h" 7 | #include "ui_core.h" 8 | #include "ui_visualization.h" 9 | 10 | extern bool mousealreadydown; 11 | extern double delta_time; // time elapsed since last frame rendering\ 12 | 13 | // initialize debuging (at this point simply prints out some info about 14 | // application data structures) 15 | bool debug_initialize(); 16 | 17 | // initialize application subsystems 18 | bool initialization(); 19 | 20 | // main loop 21 | bool main_loop(); 22 | 23 | // deallocate program structures 24 | bool release(); 25 | 26 | // error reporting routine 27 | bool report_error(); 28 | 29 | #endif 30 | -------------------------------------------------------------------------------- /insight3d/mvg_thresholds.h: -------------------------------------------------------------------------------- 1 | #ifndef __MVG_THRESHOLDS 2 | #define __MVG_THRESHOLDS 3 | 4 | // RANSAC 5 | const int MVG_RANSAC_TRIALS = 500; 6 | const int MVG_RANSAC_TRIANGULATION_TRIALS = 25; 7 | const double MVG_RANSAC_PROBABILITY = 0.999; 8 | 9 | /*// image measurement 10 | const double MVG_MEASUREMENT_THRESHOLD = 4.0; 11 | 12 | // vertices 13 | const int 14 | MVG_MIN_INLIERS_TO_TRIANGULATE = 6, 15 | MVG_MIN_INLIERS_TO_TRIANGULATE_WEAKER = 4 // when there are no outliers in the dataset 16 | ;*/ 17 | 18 | // image measurement 19 | const double MVG_MEASUREMENT_THRESHOLD = 10.0; 20 | 21 | // vertices 22 | const int 23 | MVG_MIN_INLIERS_TO_TRIANGULATE = 2, 24 | MVG_MIN_INLIERS_TO_TRIANGULATE_WEAKER = 2 // when there are no outliers in the dataset 25 | ; 26 | 27 | #endif 28 | -------------------------------------------------------------------------------- /insight3d/tool_plane_extraction.h: -------------------------------------------------------------------------------- 1 | #ifndef __TOOL_PLANE_EXTRACTION 2 | #define __TOOL_PLANE_EXTRACTION 3 | 4 | #include "interface_opencv.h" 5 | #include "core_math_routines.h" 6 | #include "geometry_structures.h" 7 | 8 | // find major plane in point cloud using RANSAC 9 | // todo time bounds 10 | // todo normalization 11 | // todo refactor code (look at RANSAC implementation from OpenCV) 12 | // todo check that we have at least 3 _reconstructed_ vertices 13 | // todo optimize this (sqrt...) 14 | double * tool_plane_extraction(Vertices & vertices, double threshold = 0.5, bool flatten_inliers = false, size_t group = 0); 15 | 16 | // version using only a subset of vertices 17 | double * tool_plane_extraction_subset(Vertices & vertices, size_t * ids, size_t count); 18 | 19 | #endif 20 | -------------------------------------------------------------------------------- /insight3d/tool_triangulation.h: -------------------------------------------------------------------------------- 1 | #ifndef __TOOL_TRIANGULATION 2 | #define __TOOL_TRIANGULATION 3 | 4 | #include "tool_typical_includes.h" 5 | #include "tool_plane_extraction.h" 6 | #include "core_math_routines.h" 7 | #include "actions.h" 8 | #include "mvg_triangulation.h" 9 | // #include "ANN/ANN.h" 10 | #include 11 | #include 12 | 13 | void tool_triangulation_create(); 14 | void tool_triangulate_vertices_user(); 15 | void tool_triangulate_vertices(); 16 | void tool_triangulate_vertices_trusted(); 17 | void tool_triangulate_vertices_using_selected_shots(); 18 | void tool_triangulate_clear(); 19 | // void tool_triangulate_compute_normals(); 20 | // void compute_vertex_normal_from_pointcloud(const size_t vertex_id, ANNkd_tree * ann_kdtree, size_t * vertices_reindex); 21 | 22 | #endif 23 | -------------------------------------------------------------------------------- /insight3d/actions.h: -------------------------------------------------------------------------------- 1 | #ifndef __ACTIONS 2 | #define __ACTIONS 3 | 4 | #include "geometry_structures.h" 5 | #include "geometry_publish.h" 6 | #include "geometry_routines.h" 7 | #include "mvg_thresholds.h" 8 | #include "mvg_triangulation.h" 9 | #include "mvg_resection.h" 10 | 11 | // triangulates vertices given current projection matrices and vertex projections 12 | bool action_triangulate_vertices(bool * shots_to_use = NULL, const int min_inliers = MVG_MIN_INLIERS_TO_TRIANGULATE, const int min_inliers_weaker = MVG_MIN_INLIERS_TO_TRIANGULATE_WEAKER, const bool only_manual = false, const double measurement_threshold = MVG_MEASUREMENT_THRESHOLD); 13 | 14 | // compute projection matrix of current camera from 3d to 2d correspondences 15 | bool action_camera_resection(size_t shot_id, const bool enforce_square_pixels, const bool enforce_zero_skew); 16 | 17 | #endif 18 | -------------------------------------------------------------------------------- /README.txt: -------------------------------------------------------------------------------- 1 | INSIGHT 3D, VERSION 0.3.2 2 | ------------------------- 3 | 4 | COMPILING UNDEX LINUX 5 | --------------------- 6 | 7 | To compile insight3d under Linux, you must have the following libraries: 8 | 9 | - opencv (which is pretty standard computer vision toolkit) 10 | - opengl 11 | - SDL 12 | - freetype2 13 | - libxml2 (to parse xml files) 14 | - lapack and blas (to do some math) 15 | - libgtk+-2.0 16 | 17 | And this should be pretty much everything. Some of them have additional 18 | requirements (opencv needs libpng, libtiff, ...) but these should be trivial. 19 | 20 | Also, pkg-config should know about those libraries. 21 | 22 | Makefile and source code is in the "insight3d" subdirectory. 23 | 24 | COMPILING ON WINDOWS 25 | -------------------- 26 | 27 | Please, refer to the file HOW_TO_BUILD_WINDOWS_VISUALSTUDIO.txt. -------------------------------------------------------------------------------- /insight3d/interface_opengl.h: -------------------------------------------------------------------------------- 1 | #ifndef __INTERFACE_OPENGL 2 | #define __INTERFACE_OPENGL 3 | 4 | #ifdef _MSC_VER 5 | #include "windows.h" 6 | #endif 7 | 8 | #include "SDL/SDL.h" 9 | #include "SDL/SDL_opengl.h" 10 | #include "pthread.h" 11 | 12 | extern pthread_mutex_t opengl_mutex; 13 | 14 | // #include "GL/gl.h" 15 | // #include "GL/glu.h" 16 | 17 | // drawing options (for drawing polygons, correspodences, etc.) 18 | struct Drawing_Style { 19 | float color[3], line_width, point_size, opacity; 20 | }; 21 | 22 | // go to 2d mode 23 | void opengl_2d_mode(double x1, double y1, double x2, double y2); 24 | 25 | // restore saved matrices 26 | void opengl_end_2d_mode(); 27 | 28 | // set drawing style 29 | void opengl_drawing_style(const Drawing_Style & style); 30 | 31 | // saves settings of some common OpenGL attributes 32 | void opengl_push_attribs(); 33 | 34 | #endif 35 | -------------------------------------------------------------------------------- /insight3d/ui_inspection_mode.h: -------------------------------------------------------------------------------- 1 | #ifndef __UI_INSPECTION_MODE 2 | #define __UI_INSPECTION_MODE 3 | 4 | #include "geometry_structures.h" 5 | #include "ui_visualization.h" 6 | #include "ui_selection.h" 7 | #include "tool_plane_extraction.h" 8 | 9 | // mode switching 10 | void ui_switch_to_inspection_mode(); 11 | 12 | // initialize "ground" inspection mode 13 | bool ui_inspection_ground_initialization(); 14 | 15 | // process user input (in inspection mode) 16 | void ui_update_inspection(const Uint32 delta_time); 17 | 18 | // respond to mouse click in inspection mode 19 | void ui_inspection_mouse_click(); 20 | 21 | // respond to selection box in inspection mode 22 | void ui_inspection_mouse_selection(); 23 | 24 | // handle mouse button down event in inspection mode 25 | void ui_inspection_mouse_button_down(); 26 | 27 | // handle mouse movement in inspection mode 28 | void ui_inspection_mouse_move(); 29 | 30 | #endif 31 | -------------------------------------------------------------------------------- /insight3d/core_state.h: -------------------------------------------------------------------------------- 1 | #ifndef __CORE_STATE 2 | #define __CORE_STATE 3 | 4 | #include "interface_sdl.h" 5 | #include 6 | 7 | // possible errors 8 | enum CORE_ERROR { 9 | CORE_NO_ERROR, 10 | CORE_ERROR_GUI_INITIALIZATION, 11 | CORE_ERROR_OUT_OF_MEMORY, 12 | CORE_ERROR_UNABLE_TO_OPEN_FILE, 13 | CORE_ERROR_UNABLE_TO_CREATE_THREAD 14 | }; 15 | 16 | // core application state info 17 | struct Core_State 18 | { 19 | // information about OS interaction, timing, etc. 20 | bool running; 21 | bool visible; 22 | bool mouse_focus; 23 | bool keyboard_focus; 24 | Uint32 ticks, last_ticks; 25 | 26 | // error management 27 | CORE_ERROR error; 28 | }; 29 | 30 | extern Core_State core_state; 31 | 32 | // error handling macro 33 | // todo think about using assertions for this 34 | #define CHECK_ERROR(condition, error_code) if ((condition)) { core_state.error = (error_code); return false; } 35 | 36 | // initialize core state 37 | bool core_initialize(); 38 | 39 | #endif 40 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | insight3d 2 | ========= 3 | 4 | insight3d lets you create 3D models from photographs. You give it a series of photos of a real scene (e.g., of a building), it automatically matches them and then calculates positions in space from which each photo has been taken (plus camera’s optical parameters) along with a 3D pointcloud of the scene. You can then use insight3d’s modeling tools to create textured polygonal model. 5 | 6 | ![SLAM UI](slam_and_editor_ui.png) 7 | 8 | ![SLAM](slam.png) 9 | 10 | We have a [tutorial available](https://insight3d.sourceforge.net/insight3d_tutorial.pdf). 11 | 12 | Also note that some good people have forked insight3d and started the insight3dng project. You might want to check that out. 13 | 14 | Disclaimer: This software is intended for educational purposes. Potential users in countries that allow software patents must first investigate whether or not this software package uses any algorithms patented in their respective countries and if so, refrain from using it. 15 | 16 | Feel free to mail me: [lukas.mach@gmail.com](mailto:lukas.mach@gmail.com) 17 | -------------------------------------------------------------------------------- /insight3d/core_debug.h: -------------------------------------------------------------------------------- 1 | #ifndef __CORE_DEBUG 2 | #define __CORE_DEBUG 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #define CORE_DEBUG_QUOTE_HELPER(x) #x 9 | #define CORE_DEBUG_QUOTE(x) CORE_DEBUG_QUOTE_HELPER(x) 10 | #define ASSERT(statement, error_message) ((statement) ? 0 : (printf("%s, %d: %s\n", __FILE__, __LINE__, (error_message)), core_abort())) 11 | #define ALLOC(type, count) (type *)malloc(sizeof(type) * (count)) 12 | // (type *)allocate_memory(sizeof(type) * (count), CORE_DEBUG_QUOTE(type), CORE_DEBUG_QUOTE(__FILE__), CORE_DEBUG_QUOTE(__LINE__)) 13 | // (type *)malloc(sizeof(type) * (count)) 14 | #define FREE(p) free(p) 15 | // free_memory(p) 16 | 17 | bool core_debug_initialize(); 18 | int core_abort(); 19 | 20 | void debug(const char * message); 21 | 22 | void * allocate_memory(size_t size, const char * description, const char * file, const char * line); 23 | void free_memory(void * p); 24 | bool check_chunk(const size_t id); 25 | void check_all_chunks(); 26 | void report_invalid_chunk(const size_t id, const char * situation); 27 | 28 | #endif 29 | 30 | -------------------------------------------------------------------------------- /insight3d/ui_list.cpp: -------------------------------------------------------------------------------- 1 | #include "ui_list.h" 2 | 3 | // update the list of shots 4 | // note: currently doesn't do anything 5 | void ui_list_update() 6 | { 7 | } 8 | 9 | // switch to next shot 10 | void ui_next_shot(const GUI_Event_Descriptor event) 11 | { 12 | if (!INDEX_IS_SET(ui_state.current_shot)) 13 | { 14 | ui_workflow_default_shot(); 15 | } 16 | else 17 | { 18 | for (size_t shot_id = ui_state.current_shot + 1; shot_id < shots.count; shot_id++) 19 | { 20 | if (validate_shot(shot_id)) 21 | { 22 | ui_workflow_select_shot(shot_id); 23 | return; 24 | } 25 | } 26 | } 27 | } 28 | 29 | // switch to previous shot 30 | void ui_prev_shot(const GUI_Event_Descriptor event) 31 | { 32 | // note remove this in release 33 | if (!INDEX_IS_SET(ui_state.current_shot)) 34 | { 35 | ui_workflow_default_shot(); 36 | } 37 | else 38 | { 39 | for (size_t shot_id = ui_state.current_shot; shot_id > 0;) 40 | { 41 | shot_id--; 42 | 43 | if (validate_shot(shot_id)) 44 | { 45 | ui_workflow_select_shot(shot_id); 46 | return; 47 | } 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /insight3d/geometry_export.h: -------------------------------------------------------------------------------- 1 | #ifndef __GEOMETRY_EXPORT 2 | #define __GEOMETRY_EXPORT 3 | 4 | #include "interface_filesystem.h" 5 | #include "core_math_routines.h" 6 | #include "geometry_structures.h" 7 | #include "ui_visualization.h" 8 | #include 9 | #include 10 | 11 | // save insight3d project 12 | bool geometry_save(const char * filename); 13 | 14 | // export scene into VRML 15 | bool geometry_export_vrml(const char * filename, Vertices & vertices, Polygons_3d & polygons, bool export_vertices = false, bool export_polygons = true, size_t restrict_vertices_by_group = 0); 16 | 17 | // export scene into Sandy3D ActionScript file 18 | bool geometry_export_sandy3d(const char * filename, Vertices & vertices, Polygons_3d & polygons, bool export_vertices = false); 19 | 20 | // debugging export for calibration into VRLM 21 | bool geometry_export_vrml_calibration(const char * filename, Calibration &calibration); 22 | 23 | // exports calibration into RealVIZ exchange format supported by both ImageModeler and MatchMover 24 | bool geometry_export_rzml(const char * filename, Shots & shots); 25 | 26 | #endif 27 | -------------------------------------------------------------------------------- /insight3d/OpenCV_Release.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | $(OPENCV_DIR)$\..\..\include 9 | 10 | 11 | $(OPENCV_DIR)\lib 12 | opencv_calib3d2413.lib;opencv_contrib2413.lib;opencv_core2413.lib;opencv_features2d2413.lib;opencv_flann2413.lib;opencv_gpu2413.lib;opencv_highgui2413.lib;opencv_imgproc2413.lib;opencv_legacy2413.lib;opencv_ml2413.lib;opencv_nonfree2413.lib;opencv_objdetect2413.lib;opencv_ocl2413.lib;opencv_photo2413.lib;opencv_stitching2413.lib;opencv_superres2413.lib;opencv_ts2413.lib;opencv_video2413.lib;opencv_videostab2413.lib;%(AdditionalDependencies) 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /insight3d/geometry_queries.h: -------------------------------------------------------------------------------- 1 | #ifndef __GEOMETRY_QUERIES 2 | #define __GEOMETRY_QUERIES 3 | 4 | #include "geometry_structures.h" 5 | #include "core_math_routines.h" 6 | 7 | // determine if all of contour's vertices have been reconstructed 8 | bool query_is_contour_reconstructed(const Contour & contour, const Points & points, const Vertices & vertices); 9 | 10 | // determine if all polygon's vertices have been reconstructed 11 | bool query_is_polygon_reconstructed(const Polygon_3d & polygon, const Vertices & vertices); 12 | 13 | // find point corresponding to a vertex on a given shot 14 | bool query_find_point_on_shot_by_vertex_id(size_t shot_id, size_t vertex_id, size_t & point_id); 15 | 16 | // find nearest point on shot, returns squared distance in image pixels 17 | double query_nearest_point(const size_t shot_id, const double x, const double y, size_t & point_id, bool skipping_auto = false); 18 | 19 | // count the number of reconstructed points on this shot 20 | size_t query_count_reconstructed_points_on_shot(const size_t shot_id); 21 | 22 | // count the number of vertex's points 23 | size_t query_count_points_by_vertex(const size_t vertex_id); 24 | 25 | #endif 26 | -------------------------------------------------------------------------------- /insight3d/ui_visualization_helpers.h: -------------------------------------------------------------------------------- 1 | #ifndef __UI_VISUALIZATION_HELPERS 2 | #define __UI_VISUALIZATION_HELPERS 3 | 4 | #include "interface_opengl.h" 5 | #include "core_debug.h" 6 | #include "core_math_routines.h" 7 | #include "ui_constants.h" 8 | #include "ui_state.h" 9 | #include "ui_core.h" 10 | 11 | // draw helper cuber 12 | void visualization_helper_cube(); 13 | 14 | // square vertices 15 | void visualization_helper_square(double x, double y, double side); 16 | 17 | // convert x axis distance from pixels to opengl coordinates 18 | double visualization_calc_dx(const double screen_distance_x); 19 | 20 | // convert y axis distance from pixels to opengl coordinates 21 | double visualization_calc_dy(const double screen_distance_y); 22 | 23 | // absolute version of visualization_calc_dx 24 | double visualization_calc_x(const double shot_x, const double screen_distance_x); 25 | 26 | // absolute version of visualization_calc_dy 27 | double visualization_calc_y(const double shot_y, const double screen_distance_y); 28 | 29 | // recalculate squared distance from image pixels to screen pixels 30 | double visualization_calc_screen_distance_sq(double distance); 31 | 32 | #endif 33 | -------------------------------------------------------------------------------- /insight3d/tool_calibration.h: -------------------------------------------------------------------------------- 1 | #ifndef __TOOL_CALIBRATION 2 | #define __TOOL_CALIBRATION 3 | 4 | #include "tool_typical_includes.h" 5 | #include "geometry_publish.h" 6 | #include "geometry_export.h" 7 | #include "mvg_triangulation.h" 8 | #include "mvg_resection.h" 9 | #include "mvg_normalization.h" 10 | #include "mvg_camera.h" 11 | #include "mvg_autocalibration.h" 12 | 13 | // methods 14 | void tool_calibration_create(); 15 | void tool_calibration_pair(); 16 | void tool_calibration_next(); 17 | void tool_calibration_prev(); 18 | void tool_calibration_add_views(); 19 | void tool_calibration_refine(); 20 | void tool_calibration_refine_strict(); 21 | void tool_calibration_metric(); 22 | void tool_calibration_print(); 23 | void tool_calibration_use(); 24 | void tool_calibration_affine(); 25 | void tool_calibration_triangulate(); 26 | void tool_calibration_triangulate_trusted(); 27 | void tool_calibration_debug_export(); 28 | void tool_calibration_clear(); 29 | void tool_calibration_bundle(); 30 | void tool_calibration_auto(); 31 | void tool_calibration_auto_begin(); 32 | void tool_calibration_auto_step(); 33 | void tool_calibration_auto_end(); 34 | void tool_calibration_test_rectification(); 35 | 36 | #endif 37 | -------------------------------------------------------------------------------- /insight3d/ui_workflow.h: -------------------------------------------------------------------------------- 1 | #ifndef __UI_WORKFLOW 2 | #define __UI_WORKFLOW 3 | 4 | #include "geometry_queries.h" 5 | #include "ui_state.h" 6 | #include "ui_visualization.h" 7 | #include "tool_core.h" 8 | 9 | // cancels processing of a vertex, this usually results in a new vertex being created 10 | void ui_workflow_no_vertex(); 11 | 12 | // next vertex to be processed 13 | void ui_workflow_next_vertex(); 14 | 15 | // next vertex to be processed 16 | void ui_workflow_prev_vertex(); 17 | 18 | // first vertex to be processed 19 | void ui_workflow_first_vertex(); 20 | 21 | // next polygon to be processed 22 | void ui_workflow_next_polygon(); 23 | 24 | // prev polygon to be processed 25 | void ui_workflow_prev_polygon(); 26 | 27 | // sets focused point 28 | void ui_workflow_set_focused_point(const size_t point_id); 29 | 30 | // unsets focused point 31 | void ui_workflow_unset_focused_point(); 32 | 33 | // switches to another image 34 | void ui_workflow_select_shot(size_t shot_id); 35 | 36 | // set current shot to default value (if necessary) 37 | // this function is called after any modification to the image sequence (i.e., addition or 38 | // removal of images) 39 | void ui_workflow_default_shot(); 40 | 41 | #endif 42 | -------------------------------------------------------------------------------- /HOW_TO_BUILD_WINDOWS_VISUALSTUDIO.txt: -------------------------------------------------------------------------------- 1 | Terms 2 | ----- 3 | 4 | - "application directory" is the directory with the executable file insight3d.exe 5 | - "project directory" is the directory with the source files (main.cpp, application.h, etc.) 6 | 7 | List of DLLs 8 | ------------ 9 | 10 | The following dlls need to be either copied to the application directory or located where the system can find them (e.g., a location listed in the PATH variable): 11 | 12 | - the opencv dll files 13 | - SDL dll files 14 | - pthreadVC2.dll 15 | - shared version x64 of the LAPACK and BLAS libraries, can be downloaded from this website http://www.fi.muni.cz/~xsvobod2/misc/lapack/ (as of October, 2016) 16 | 17 | How to build under Windows 18 | -------------------------- 19 | 20 | The following libraries are necessary for building in Microsoft Visual Studio: 21 | 22 | - opencv 23 | - opengl 24 | - opensift 25 | - SDL 26 | - lapack and blas 27 | - pthreads 28 | 29 | The OpenCV_Debug.props file inside the project directory contains relevant compiler and linker configuration. It expects that the OpenCV library can be found using the %(OPENCV_DIR) system variable and that the remaining libraries are inside the project directory. 30 | 31 | -------------------------------------------------------------------------------- /insight3d/interface_opengl.cpp: -------------------------------------------------------------------------------- 1 | #include "interface_opengl.h" 2 | 3 | pthread_mutex_t opengl_mutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP; 4 | 5 | // go to 2d mode 6 | void opengl_2d_mode(double x1, double y1, double x2, double y2) 7 | { 8 | x1 = x1 * 2 - 1; 9 | y1 = y1 * 2 - 1; 10 | x2 = x2 * 2 - 1; 11 | y2 = y2 * 2 - 1; 12 | 13 | glMatrixMode(GL_MODELVIEW); 14 | glPushMatrix(); 15 | glLoadIdentity(); 16 | 17 | glMatrixMode(GL_PROJECTION); 18 | glPushMatrix(); 19 | glLoadIdentity(); 20 | glFrustum(0.1 * x1, 0.1 * x2, 0.1 * y1, 0.1 * y2, 0.1, 1000.0); 21 | 22 | glPushAttrib(GL_DEPTH_BUFFER_BIT); 23 | glDisable(GL_DEPTH_TEST); 24 | } 25 | 26 | // restore saved matrices 27 | void opengl_end_2d_mode() 28 | { 29 | glPopAttrib(); 30 | glMatrixMode(GL_PROJECTION); 31 | glPopMatrix(); 32 | glMatrixMode(GL_MODELVIEW); 33 | glPopMatrix(); 34 | } 35 | 36 | // set drawing style 37 | void opengl_drawing_style(const Drawing_Style & style) 38 | { 39 | glColor4f(style.color[0], style.color[1], style.color[2], style.opacity); 40 | glPointSize(style.point_size); 41 | glLineWidth(style.line_width); 42 | } 43 | 44 | // saves settings of some common OpenGL attributes 45 | void opengl_push_attribs() 46 | { 47 | glPushAttrib(GL_ENABLE_BIT | GL_CURRENT_BIT | GL_TEXTURE_BIT | GL_POINT_BIT | GL_LINE_BIT); 48 | } 49 | -------------------------------------------------------------------------------- /insight3d/ui_events.h: -------------------------------------------------------------------------------- 1 | #ifndef __EVENTS 2 | #define __EVENTS 3 | 4 | #include "application.h" 5 | #include "interface_opengl.h" 6 | #include "geometry_structures.h" 7 | #include "geometry_loader.h" 8 | #include "geometry_export.h" 9 | #include "ui_core.h" 10 | #include "ui_inspection_mode.h" 11 | #include "ui_shot_mode.h" 12 | #include "ui_visualization_helpers.h" 13 | #include "ui_visualization_point.h" 14 | #include "ui_visualization.h" 15 | #include "ui_selection.h" 16 | #include "ui_list.h" 17 | #include "ui_epipolars.h" 18 | #include "tool_selection.h" 19 | 20 | void ui_event_redraw(); 21 | void ui_event_key_down(const SDL_Event * const event); 22 | void ui_event_key_up(const SDL_Event * const event); 23 | void ui_event_mouse_button_down(Uint8 button, Uint16 x, Uint16 y); 24 | void ui_event_agar_button_down(const GUI_Event_Descriptor event); 25 | void ui_event_mouse_move(Uint16 x, Uint16 y); 26 | void ui_event_agar_motion(const GUI_Event_Descriptor event); 27 | void ui_event_mouse_button_up(Uint8 button, Uint16 x, Uint16 y) ; 28 | void ui_event_agar_button_up(const SDL_Event * const event); 29 | void ui_event_update(const Uint32 delta_time); 30 | void ui_event_update_shot(const Uint32 delta_time); 31 | void ui_event_resize(); 32 | void ui_event_motion(const GUI_Event_Descriptor event); 33 | void ui_event_mouse_out(const GUI_Event_Descriptor event); 34 | 35 | #endif 36 | -------------------------------------------------------------------------------- /insight3d/tool_selection.h: -------------------------------------------------------------------------------- 1 | #ifndef __TOOL_SELECTION 2 | #define __TOOL_SELECTION 3 | 4 | #include "core_math_routines.h" 5 | #include "geometry_textures.h" 6 | #include "ui_core.h" 7 | #include "ui_context.h" 8 | #include "ui_visualization.h" 9 | #include "ui_selection.h" 10 | #include "ui_workflow.h" 11 | #include "tool_core.h" 12 | 13 | // selection tool handles viewing options which are read by other tools and the rest of the application 14 | extern bool option_show_dualview, option_thumbs_only_for_selected, option_hide_automatic; 15 | 16 | // selection tool routines 17 | void tool_selection_create(); 18 | bool tool_selection_mouse_down(double x, double y, int button); 19 | void tool_selection_move(double x, double y); 20 | void tool_selection_dragging(double x, double y, int button); 21 | void tool_selection_dragging_done(double x1, double y1, double x2, double y2, int button); 22 | void tool_selection_click(double x, double y, int button); 23 | void tool_selection_key(); 24 | void tool_selection_begin(); 25 | void tool_selection_end(); 26 | 27 | // switching options 28 | void selection_option_show_dualview(); 29 | void selection_option_thumbs_only_for_selected(); 30 | void selection_option_show_automatic_points(); 31 | 32 | // some debugging functions 33 | void debug_print_Ps(); 34 | void debug_save_initial_solution(); 35 | void debug_save_vertices(); 36 | 37 | #endif 38 | -------------------------------------------------------------------------------- /insight3d/ui_visualization_point.h: -------------------------------------------------------------------------------- 1 | #ifndef __UI_VISUALIZATION_POINT 2 | #define __UI_VISUALIZATION_POINT 3 | 4 | #include "interface_opengl.h" 5 | #include "ui_visualization_helpers.h" 6 | 7 | extern const double VISUALIZATION_POINT_SIZE; 8 | extern const double VISUALIZATION_FOCUSED_POINT_SIZE; 9 | extern const unsigned int VISUALIZATION_DEFAULT; 10 | extern const unsigned int VISUALIZATION_FOCUSED; 11 | extern const unsigned int VISUALIZATION_SELECTED; 12 | extern const unsigned int VISUALIZATION_PROCESSED; 13 | extern const unsigned int VISUALIZATION_OUTLIER; 14 | extern const unsigned int VISUALIZATION_AUTO; 15 | 16 | // draw point 17 | void visualization_point(double x, double y, unsigned int style); 18 | 19 | // draw line segment visualizing reprojection error in image 20 | void visualization_reprojection(const double x, const double y, const double rx, const double ry, const bool outlier = false); 21 | 22 | // show reprojection of point's vertex 23 | void visualization_point_reprojection(const size_t shot_id, const size_t point_id); 24 | 25 | // show reprojection of point's vertex in chosen calibration 26 | void visualization_point_reprojection_calibration( 27 | const size_t shot_id, const size_t point_id, const size_t calibration_id, 28 | const size_t P_id, const size_t X_id, const bool outlier 29 | ); 30 | 31 | // show 2d points in shot mode 32 | void visualization_shot_points(); 33 | 34 | #endif 35 | -------------------------------------------------------------------------------- /insight3d.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 14 4 | VisualStudioVersion = 14.0.25420.1 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "insight3d", "insight3d\insight3d.vcxproj", "{518C700B-7DAC-4BE1-8CED-D5AA0FA0DAC0}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Win32 = Debug|Win32 11 | Debug|x64 = Debug|x64 12 | Release|Win32 = Release|Win32 13 | Release|x64 = Release|x64 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {518C700B-7DAC-4BE1-8CED-D5AA0FA0DAC0}.Debug|Win32.ActiveCfg = Debug|Win32 17 | {518C700B-7DAC-4BE1-8CED-D5AA0FA0DAC0}.Debug|Win32.Build.0 = Debug|Win32 18 | {518C700B-7DAC-4BE1-8CED-D5AA0FA0DAC0}.Debug|x64.ActiveCfg = Debug|x64 19 | {518C700B-7DAC-4BE1-8CED-D5AA0FA0DAC0}.Debug|x64.Build.0 = Debug|x64 20 | {518C700B-7DAC-4BE1-8CED-D5AA0FA0DAC0}.Release|Win32.ActiveCfg = Release|Win32 21 | {518C700B-7DAC-4BE1-8CED-D5AA0FA0DAC0}.Release|Win32.Build.0 = Release|Win32 22 | {518C700B-7DAC-4BE1-8CED-D5AA0FA0DAC0}.Release|x64.ActiveCfg = Release|x64 23 | {518C700B-7DAC-4BE1-8CED-D5AA0FA0DAC0}.Release|x64.Build.0 = Release|x64 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | EndGlobal 29 | -------------------------------------------------------------------------------- /insight3d/mvg_matching.h: -------------------------------------------------------------------------------- 1 | #ifndef __MVG_MATCHING 2 | #define __MVG_MATCHING 3 | 4 | #include "core_debug.h" 5 | #include "interface_opencv.h" 6 | #include "core_math_routines.h" 7 | #include "geometry_structures.h" 8 | 9 | // we have to reference the type containing the structure 10 | #define MVG_FEATURE struct feature 11 | 12 | size_t * mvg_index_buckets( 13 | MVG_FEATURE * features, 14 | double scale, 15 | size_t count, 16 | int bucket_size, 17 | int bucket_cols, 18 | int bucket_rows 19 | ); 20 | 21 | size_t * mvg_build_buckets( 22 | MVG_FEATURE * features, 23 | const double scale, 24 | size_t count, 25 | int bucket_size, 26 | int buckets_x, 27 | int buckets_y 28 | ); 29 | 30 | size_t mvg_guided_matching( 31 | MVG_FEATURE * features1, const size_t count1, const int width1, const int height1, const double scale1, 32 | MVG_FEATURE * features2, const size_t count2, const int width2, const int height2, const double scale2, 33 | CvMat * F, 34 | const double threshold, 35 | const double fsor_threshold, 36 | int * matches 37 | ); 38 | 39 | size_t mvg_guided_matching_translation( 40 | MVG_FEATURE * features1, const size_t count1, const int width1, const int height1, const double scale1, 41 | MVG_FEATURE * features2, const size_t count2, const int width2, const int height2, const double scale2, 42 | const double T_x, const double T_y, 43 | const double threshold, 44 | const double fsor_threshold, 45 | int * matches 46 | ); 47 | 48 | #endif 49 | -------------------------------------------------------------------------------- /insight3d/interface_filesystem.h: -------------------------------------------------------------------------------- 1 | #ifndef __INTERFACE_FILESYSTEM 2 | #define __INTERFACE_FILESYSTEM 3 | 4 | const char * const FILESYSTEM_PATH_SEPARATORS = "\\/"; // note somewhat platform dependent 5 | #ifndef _MSC_VER 6 | const char * const FILESYSTEM_PATH_SEPARATOR = "/"; 7 | #else 8 | const char * const FILESYSTEM_PATH_SEPARATOR = "\\"; 9 | #endif 10 | 11 | #include "core_debug.h" 12 | #include "stdlib.h" 13 | #include "stdio.h" 14 | #include "string.h" 15 | #include "portability.h" 16 | 17 | // returns file's directory, NULL is returned if filename ends with path separator 18 | char * interface_filesystem_dirpath(const char * const filename); 19 | 20 | // returns file name without basepath 21 | char * interface_filesystem_extract_filename(const char * filename); 22 | 23 | // cleans up "/C:/something/..." to "C:/something/..." if necessary 24 | char * interface_filesystem_cleanup_windows_filename(const char * filename); 25 | 26 | // cleans up path file path and converts relative path to absolute 27 | char * interface_filesystem_cleanup_filename(const char * fn, const char * directory); 28 | 29 | // compares two filenames based on the name of the file without basepath 30 | bool interface_filesystem_compare_filenames(const char * f1, const char * f2); 31 | 32 | // adjusts filename for export into RealVIZ file format 33 | char * interface_filesystem_realviz_filename(const char * filename); 34 | 35 | // determines if path is absolute or relative 36 | bool interface_filesystem_is_relative(const char * filename); 37 | 38 | #endif 39 | -------------------------------------------------------------------------------- /insight3d/OpenCV_Debug.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | $(OPENCV_DIR)$\..\..\include;$(OPENCV_DIR)$\..\..\include\opencv;SDL\include;pthreads\include;sba-1.6 9 | HAVE_STRUCT_TIMESPEC;%(PreprocessorDefinitions) 10 | MultiThreaded 11 | 12 | 13 | $(OPENCV_DIR)\lib;SDL\lib\x64;pthreads\lib\x64;sba-1.6 14 | opencv_calib3d2413d.lib;opencv_contrib2413d.lib;opencv_core2413d.lib;opencv_features2d2413d.lib;opencv_flann2413d.lib;opencv_gpu2413d.lib;opencv_highgui2413d.lib;opencv_imgproc2413d.lib;opencv_legacy2413d.lib;opencv_ml2413d.lib;opencv_nonfree2413d.lib;opencv_objdetect2413d.lib;opencv_ocl2413d.lib;opencv_photo2413d.lib;opencv_stitching2413d.lib;opencv_superres2413d.lib;opencv_ts2413d.lib;opencv_video2413d.lib;opencv_videostab2413d.lib;SDL.lib;SDLmain.lib;opengl32.lib;glu32.lib;pthreadVC2.lib;sba.lib;cbia.lib.blas.dyn.dbg.x64.12.lib;cbia.lib.lapack.dyn.dbg.x64.12.lib;%(AdditionalDependencies) 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /insight3d/geometry_publish.h: -------------------------------------------------------------------------------- 1 | #ifndef __GEOMETRY_PUBLISH 2 | #define __GEOMETRY_PUBLISH 3 | 4 | #include "interface_opencv.h" 5 | #include "geometry_structures.h" 6 | #include "geometry_queries.h" 7 | 8 | // exports data from application structures into structures suitable for OpenCV and MVG 9 | // note opencv should be locked 10 | bool publish_triangulation_data( 11 | const Vertex_Incidence & incidence, size_t vertex_id, const CvMat * * & projection_matrices, CvMat * & points, bool * shots_to_use 12 | ); 13 | 14 | // exports data from application structures of given calibration into structures suitable for OpenCV and MVG 15 | // note opencv should be locked 16 | bool publish_triangulation_data_from_calibration( 17 | const size_t calibration_id, const Vertex_Incidence & incidence, size_t vertex_id, 18 | const CvMat * * & projection_matrices, CvMat * & points, size_t * & indices 19 | ); 20 | 21 | // export data for the computation of fundamental matrix 22 | // note opencv should be locked 23 | bool publish_2_view_reconstruction_data( 24 | const size_t shot_id1, const size_t shot_id2, CvMat ** points1, CvMat ** points2, 25 | size_t ** points1_indices, size_t ** points2_indices 26 | ); 27 | 28 | // export data for resection of given camera, vertices' coordinates are inhomogeneous 29 | // but the coordinates of points are homogeneous vectors 30 | // note opencv should be locked 31 | bool publish_resection_data_from_calibration( 32 | const size_t calibration_id, const size_t shot_id, 33 | CvMat ** points, CvMat ** vertices, size_t ** points_indices 34 | ); 35 | 36 | // export polygon 37 | CvMat * publish_polygon(const size_t shot_id, const size_t polygon_id); 38 | 39 | #endif 40 | -------------------------------------------------------------------------------- /insight3d/mvg_normalization.cpp: -------------------------------------------------------------------------------- 1 | #include "mvg_normalization.h" 2 | 3 | // normalize image points so that their centroid and typical magnitude of 4 | // the vector is (1, 1) 5 | bool mvg_normalize_points(CvMat * points, CvMat * H, double * output_scale) 6 | { 7 | double sum_x = 0, sum_y = 0; 8 | 9 | // initialize normalizing homography 10 | cvZero(H); 11 | OPENCV_ELEM(H, 0, 0) = 1; 12 | OPENCV_ELEM(H, 1, 1) = 1; 13 | OPENCV_ELEM(H, 2, 2) = 1; 14 | 15 | // find centroid 16 | for (size_t i = 0; i < points->cols; i++) 17 | { 18 | sum_x += OPENCV_ELEM(points, 0, i); 19 | sum_y += OPENCV_ELEM(points, 1, i); 20 | } 21 | 22 | const double avg_x = sum_x / (double)points->cols, avg_y = sum_y / (double)points->cols; 23 | 24 | // move centroid to origin 25 | double sum = 0; 26 | for (size_t i = 0; i < points->cols; i++) 27 | { 28 | OPENCV_ELEM(points, 0, i) -= avg_x; 29 | OPENCV_ELEM(points, 1, i) -= avg_y; 30 | const double a = OPENCV_ELEM(points, 0, i), b = OPENCV_ELEM(points, 1, i); 31 | sum += sqrt(a * a + b * b); 32 | } 33 | 34 | // calculate variance 35 | const double avg = sum / (double)points->cols; 36 | 37 | double scale = 1; 38 | if (avg < -1.0e-6 || avg > 1.0e-6) 39 | { 40 | scale = sqrt((double)2) / avg; 41 | } 42 | 43 | for (size_t i = 0; i < points->cols; i++) 44 | { 45 | OPENCV_ELEM(points, 0, i) *= scale; 46 | OPENCV_ELEM(points, 1, i) *= scale; 47 | } 48 | 49 | // translation 50 | OPENCV_ELEM(H, 0, 2) = -avg_x; 51 | OPENCV_ELEM(H, 1, 2) = -avg_y; 52 | 53 | // scale 54 | if (output_scale) *output_scale = scale; 55 | CvMat * S = opencv_create_I_matrix(3); 56 | OPENCV_ELEM(S, 0, 0) = scale; 57 | OPENCV_ELEM(S, 1, 1) = scale; 58 | 59 | // compute final normalizing homography, release and return 60 | cvMatMul(S, H, H); 61 | cvReleaseMat(&S); 62 | 63 | return true; 64 | } 65 | -------------------------------------------------------------------------------- /insight3d/ui_context.h: -------------------------------------------------------------------------------- 1 | #ifndef __UI_CONTEXT 2 | #define __UI_CONTEXT 3 | 4 | #include "core_image_loader.h" 5 | #include "ui_core.h" 6 | #include "ui_visualization_helpers.h" 7 | 8 | // decoration style 9 | enum Context_Content { UI_CONTEXT_THUMBNAIL, UI_CONTEXT_ZOOM }; 10 | enum Context_Decoration { UI_CONTEXT_NONE, UI_CONTEXT_CROSSHAIR }; 11 | 12 | // setting 13 | extern const double UI_CONTEXT_SCALE; 14 | 15 | // context popup items 16 | struct Context_Item 17 | { 18 | bool set; 19 | 20 | // content type 21 | Context_Content content; 22 | 23 | // image and position shown 24 | size_t shot_id; 25 | double x, y, width, height; 26 | 27 | // decoration 28 | Context_Decoration decoration; 29 | 30 | // request for this image sent to loading subsystem 31 | Image_Loader_Request_Handle request; 32 | }; 33 | 34 | DYNAMIC_STRUCTURE_DECLARATIONS(Context_Items, Context_Item); 35 | 36 | // provides info about context popup 37 | struct Context_State 38 | { 39 | // popup state 40 | bool visible; 41 | double x, y; // where is the context menu shown 42 | bool positive_x, positive_y; // direction in which the window is shown 43 | 44 | // settings 45 | double delay, timer; 46 | 47 | // popup content 48 | size_t count; 49 | Context_Items items; 50 | }; 51 | 52 | extern const size_t UI_CONTEXT_MAX_SHOWN_ITEMS; 53 | 54 | // routines 55 | bool ui_context_initialize(); 56 | void ui_context_show(); 57 | void ui_context_hide(); 58 | void ui_context_display(double shot_x, double shot_y); 59 | void ui_context_add_thumbnail(const size_t shot_id, const double x, const double y, const double width, const double height, Context_Decoration decoration); 60 | void ui_context_add_zoom(const double width, const double height, Context_Decoration decoration); 61 | void ui_context_clear(); 62 | void ui_context_set_delay(const double delay); 63 | 64 | #endif 65 | -------------------------------------------------------------------------------- /insight3d/ui_constants.h: -------------------------------------------------------------------------------- 1 | #ifndef __UI_CONSTANTS 2 | #define __UI_CONSTANTS 3 | 4 | #include "interface_opengl.h" 5 | 6 | // * drawing styles * 7 | 8 | // background 9 | extern const float UI_STYLE_BACKGROUND[3]; 10 | 11 | // 3d rendering 12 | extern const Drawing_Style UI_STYLE_VERTEX; 13 | extern const Drawing_Style UI_STYLE_POLYGON; 14 | 15 | // 2d drawing 16 | extern const Drawing_Style UI_STYLE_POINT; 17 | extern const Drawing_Style UI_STYLE_POINT_NOT_CREDIBLE; 18 | extern const Drawing_Style UI_STYLE_POLYGON_JOINING_POINTS; 19 | extern const Drawing_Style UI_STYLE_CONTOUR; 20 | 21 | // special objects 22 | extern const Drawing_Style UI_STYLE_CAMERA; 23 | 24 | // selected items 25 | extern const Drawing_Style UI_STYLE_SELECTED_POINT; 26 | extern const Drawing_Style UI_STYLE_SELECTED_VERTEX; 27 | extern const Drawing_Style UI_STYLE_SELECTED_POLYGON; 28 | 29 | // helpers 30 | extern const Drawing_Style UI_STYLE_HELPERS; 31 | 32 | // user interaction 33 | extern const Drawing_Style UI_STYLE_SELECTION_BOX; 34 | extern const Drawing_Style UI_STYLE_SELECTION_BORDER; 35 | 36 | // * user interface * 37 | 38 | // UI behavior 39 | extern const double UI_CLICK_DELAY; 40 | extern const double UI_CLICK_DISTANCE_SQ; 41 | extern const double UI_GROUND_ANGLE_DRAGGING_STEP; 42 | extern const double UI_FOCUS_PIXEL_DISTANCE_SQ; 43 | 44 | // shadows 45 | extern const double UI_SHADOW_DISTANCE; 46 | extern const double UI_SHADOW_ALPHA; 47 | extern const double UI_SHADOW_SIZE; 48 | extern const int UI_SHADOW_PRECISION; 49 | 50 | // note take a loot at http://www.sapdesignguild.org/editions/philosophy_articles/colors.asp 51 | // note http://kuler.adobe.com/ (nice palettes are: "warm lounge", "old man winter" by nine70, 52 | // "warm" by dario88, "the balloons" by whoneycutt, "fabric spot test | 02" by whoneycutt, 53 | // "orange on gray" by mats.holmberg, "oddend" by martin, "1944mustang" by nathaniel, 54 | // "Howard Johnsons" by johnl) 55 | 56 | #endif 57 | -------------------------------------------------------------------------------- /insight3d/interface_sdl.cpp: -------------------------------------------------------------------------------- 1 | #include "interface_sdl.h" 2 | 3 | // SDL initialization 4 | // note unused when using AgarGUI, but might be useful someday 5 | void sdl_initialize(int window_width, int window_height) 6 | { 7 | const SDL_VideoInfo * info = NULL; 8 | 9 | if (SDL_Init(SDL_INIT_VIDEO) < 0) 10 | { 11 | fprintf(stderr, "Video initialization failed: %s\n", SDL_GetError()); 12 | exit(1); 13 | } 14 | 15 | atexit(SDL_Quit); 16 | 17 | info = SDL_GetVideoInfo(); 18 | if (!info) 19 | { 20 | fprintf(stderr, "Video query failed: %s\n", SDL_GetError()); 21 | exit(1); 22 | } 23 | 24 | SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 5); 25 | SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 5); 26 | SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 5); 27 | SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16); 28 | SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); 29 | 30 | int bpp = info->vfmt->BitsPerPixel; 31 | int flags = SDL_OPENGL;// | SDL_RESIZABLE; // debug 32 | 33 | if (SDL_SetVideoMode(window_width, window_height, bpp, flags) == 0) 34 | { 35 | fprintf(stderr, "Video mode set failed: %s\n", SDL_GetError()); 36 | exit(1); 37 | } 38 | 39 | SDL_WM_SetCaption("OpenGL window", NULL); 40 | } 41 | 42 | // reset keys status to false 43 | void sdl_clear_keys(Uint8 * keys, bool * clear_keys, size_t keys_length) 44 | { 45 | for (size_t i = 0; i < keys_length; i++) 46 | if (clear_keys[i]) 47 | keys[i] = 0; 48 | } 49 | 50 | // map rgb color defined as vector 51 | Uint32 sdl_map_rgb_vector(const SDL_PixelFormat * const format, const double color[3]) 52 | { 53 | return SDL_MapRGB(format, (Uint32)(255 * color[0]), (Uint32)(255 * color[1]), (Uint32)(255 * color[2])); 54 | } 55 | 56 | // button is mouse wheel 57 | bool sdl_wheel_button(int button) 58 | { 59 | return button == SDL_BUTTON_WHEELUP || button == SDL_BUTTON_MIDDLE || button == SDL_BUTTON_WHEELDOWN; 60 | } 61 | 62 | // get modifiers 63 | bool sdl_shift_pressed() 64 | { 65 | SDLMod mod = SDL_GetModState(); 66 | return (bool)(mod & KMOD_SHIFT); 67 | } 68 | 69 | bool sdl_ctrl_pressed() 70 | { 71 | SDLMod mod = SDL_GetModState(); 72 | return (bool)(mod & KMOD_CTRL); 73 | } 74 | bool sdl_alt_pressed() 75 | { 76 | SDLMod mod = SDL_GetModState(); 77 | return (bool)(mod & KMOD_ALT); 78 | } 79 | -------------------------------------------------------------------------------- /insight3d/ui_selection.h: -------------------------------------------------------------------------------- 1 | #ifndef __UI_SELECTION 2 | #define __UI_SELECTION 3 | 4 | #include "core_structures.h" 5 | #include "geometry_structures.h" 6 | #include "ui_core.h" 7 | 8 | // selection box can perform following set operations 9 | enum Selection_Type { SELECTION_TYPE_REPLACEMENT, SELECTION_TYPE_UNION, SELECTION_TYPE_INTERSECTION, SELECTION_TYPE_REMOVE }; 10 | 11 | // check which shots user selected in GUI 12 | void ui_get_selection(); 13 | 14 | // get ids of the first n selected shots 15 | size_t ui_selected_shots_n(size_t * const selected, const size_t count); 16 | 17 | // throw all items out of selection list 18 | void ui_empty_selection_list(); 19 | 20 | // add vertex to selection list 21 | bool ui_add_vertex_to_selection(const size_t vertex_id); 22 | 23 | // remove vertex from selection box 24 | void ui_remove_vertex_from_selection(const size_t selection_id); 25 | 26 | // add point to selection box 27 | bool ui_add_point_to_selection(const size_t shot_id, const size_t point_id); 28 | 29 | // remove point from selection 30 | void ui_remove_point_from_selection(const size_t selection_id); 31 | 32 | // select all points on shot 33 | void ui_select_points_on_shot(const size_t shot_id); 34 | 35 | // select all points (everywhere) 36 | void ui_select_all_points(); 37 | 38 | // select points with reconstructed vertices 39 | void ui_select_points_with_reconstructed_vertices(); 40 | 41 | // finds point on current shot under position [x,y] (if there is any) 42 | // uses UI_FOCUS_PIXEL_DISTANCE to determine if the point is close enough 43 | bool ui_selection_get_point_by_position(const double x, const double y, size_t & point_id); 44 | 45 | // does this vertex belong to an invisible group? 46 | bool ui_vertex_invisible(size_t vertex_id); 47 | 48 | // perform 3d selection of vertices 49 | void ui_3d_selection_box(double x1, double y1, double x2, double y2, Selection_Type operation); 50 | 51 | // perform 2d selection of points 52 | void ui_2d_selection_box(double x1, double y1, double x2, double y2, Selection_Type operation); 53 | 54 | // delete selected points (only on current shot) 55 | void ui_delete_selected_points(bool dont_restrict_to_current_shot = false); 56 | 57 | // show selection box 58 | void ui_selection_box(); 59 | 60 | #endif 61 | -------------------------------------------------------------------------------- /insight3d/ui_constants.cpp: -------------------------------------------------------------------------------- 1 | #include "ui_constants.h" 2 | 3 | // * drawing styles * 4 | 5 | // todo UI_STYLE_ constants are now somewhat unused since the UI was being redone, integrate this 6 | 7 | // background 8 | const float UI_STYLE_BACKGROUND[3] = { 0.0F, 0.0F, 0.0F }; 9 | 10 | // 3d rendering 11 | const Drawing_Style UI_STYLE_VERTEX = { { 1.0F, 0.44F, 1.0F }, 1.0F, 2.0F, 1.0F }; // { { 1, 0.44, 1 }, 1, 2, 1 }; 12 | const Drawing_Style UI_STYLE_POLYGON = { { 1.0F, 1.0F, 1.0F }, 1.0F, 1.0F, 1.0F }; // { { 0.6, 0.6, 1 }, 1.5, 1, 0.4 }; 13 | 14 | // 2d drawing 15 | const Drawing_Style UI_STYLE_POINT = { { 1.0F, 1.0F, 1.0F }, 1.0F, 2.0F, 1.0F }; 16 | const Drawing_Style UI_STYLE_POINT_NOT_CREDIBLE = { { 0.7F, 0.7F, 0.7F }, 1.0F, 2.0F, 1.0F }; 17 | const Drawing_Style UI_STYLE_POLYGON_JOINING_POINTS = { { 1.0F, 1.0F, 1.0F }, 1.0F, 1.0F, 1.0F }; 18 | const Drawing_Style UI_STYLE_CONTOUR = { { 0.7F, 0.7F, 0.7F }, 1.0F, 1.0F, 1.0F }; // todo 19 | 20 | // special objects 21 | const Drawing_Style UI_STYLE_CAMERA = { { 1.0F, 1.0F, 1.0F }, 1.0F, 2.0F, 1.0F }; 22 | 23 | // selected items 24 | const Drawing_Style UI_STYLE_SELECTED_POINT = { { 1.0F, 1.0F, 0.44F }, 1.0F, 2.0F, 1.0F }; 25 | const Drawing_Style UI_STYLE_SELECTED_VERTEX = { { 0.0F, 1.0F, 0.44F }, 1.0F, 2.0F, 1.0F }; 26 | const Drawing_Style UI_STYLE_SELECTED_POLYGON = { { 1.0F, 1.0F, 0.44F }, 1.0F, 2.0F, 1.0F }; 27 | 28 | // helpers 29 | const Drawing_Style UI_STYLE_HELPERS = { { 0.8F, 0.8F, 0.6F }, 1.0F, 1.0F, 1.0F }; 30 | 31 | // user interaction 32 | const Drawing_Style UI_STYLE_SELECTION_BORDER = { { 1.0F, 1.0F, 0.44F }, 1.0F, 1.0F, 1.0F }; 33 | 34 | // * user interface * 35 | 36 | // UI behavior 37 | const double UI_CLICK_DELAY = 350; 38 | const double UI_CLICK_DISTANCE_SQ = 64; 39 | const double UI_GROUND_ANGLE_DRAGGING_STEP = 0.01; 40 | const double UI_FOCUS_PIXEL_DISTANCE_SQ = 64; 41 | 42 | // shadows 43 | const double UI_SHADOW_DISTANCE = 0; 44 | const double UI_SHADOW_ALPHA = 0.05; 45 | const double UI_SHADOW_SIZE = 0.0075; 46 | const int UI_SHADOW_PRECISION = 4; 47 | 48 | // note take a loot at http://www.sapdesignguild.org/editions/philosophy_articles/colors.asp 49 | // note http://kuler.adobe.com/ (nice palettes are: "warm lounge", "old man winter" by nine70, 50 | // "warm" by dario88, "the balloons" by whoneycutt, "fabric spot test | 02" by whoneycutt, 51 | // "orange on gray" by mats.holmberg, "oddend" by martin, "1944mustang" by nathaniel, 52 | // "Howard Johnsons" by johnl) 53 | -------------------------------------------------------------------------------- /insight3d/geometry_loader.h: -------------------------------------------------------------------------------- 1 | #ifndef __GEOMETRY_LOADER 2 | #define __GEOMETRY_LOADER 3 | 4 | #include "interface_filesystem.h" 5 | #include "core_math_routines.h" 6 | #include "geometry_structures.h" 7 | #include "geometry_routines.h" 8 | #include 9 | #include 10 | // #include "libxml/parser.h" 11 | 12 | // SAX state 13 | struct geometry_loader_SAX_state 14 | { 15 | // loaded file's filename and directory 16 | char * filename, * directory; 17 | 18 | // photos and camera data 19 | Shots * shots; 20 | 21 | // pointer to currently loaded shot 22 | Shot * current_shot; 23 | 24 | // first cammera's film back 25 | double first_film_back; 26 | 27 | // number of points currently loaded from the file 28 | size_t points_count; 29 | 30 | // points data 31 | Vertices * vertices; 32 | }; 33 | 34 | // process loaded data (compute focal length from fov, assemble projection matrices, ...) 35 | void geometry_process_data(Shots shots); 36 | 37 | // SAX callbacks 38 | /*void geometry_loader_SAX_start_element(geometry_loader_SAX_state * state, const xmlChar * name, const xmlChar ** attrs); 39 | void geometry_loader_SAX_end_element(geometry_loader_SAX_state * state, const xmlChar * name); 40 | void geometry_loader_SAX_characters(geometry_loader_SAX_state * state, const xmlChar * cdata, int len);*/ 41 | 42 | // load saved project 43 | bool geometry_load_project(const char * filename); 44 | 45 | // load data from realviz xml file 46 | /* void geometry_loader(const char * xml_filename, Shots & shots); */ 47 | 48 | // load data from realviz rz3 file 49 | bool geometry_loader_rz3(const char * xml_filename, Shots & shots); 50 | 51 | // load 3d vertices from text file (one vertex per line: ); returns true on success 52 | bool geometry_loader_vertices(const char * txt_filename, Vertices & vertices, size_t group = 0); 53 | 54 | // load contours 55 | bool geometry_loader_contours(const char * txt_filename, Shots & shots); 56 | 57 | // load points from text files 58 | bool geometry_loader_points(const char * pictures_filename, const char * tracks_filename, Shots & shots, Vertices & vertices, size_t group = 0); 59 | 60 | // add another image to the sequence 61 | bool geometry_loader_add_shot(const char * filename); 62 | 63 | // load IFL file (i.e., image file list) 64 | bool geometry_loader_ifl(const char * filename); 65 | 66 | // load points from *_points.txt and *_pictures.ifl imagepair 67 | bool geometry_loader_points_guess_filepair(char * const filename); 68 | 69 | #endif 70 | -------------------------------------------------------------------------------- /insight3d/tool_coordinates.cpp: -------------------------------------------------------------------------------- 1 | #include "tool_coordinates.h" 2 | 3 | // note that this small tool doesn't follow naming conventions of tool subsystem 4 | // and there's no real reason for this 5 | 6 | // create UI elements for changing coordinates 7 | void tool_coordinates_create() 8 | { 9 | tool_create(UI_MODE_UNSPECIFIED, "Coordinate frames", "Changing world-space coordinate frames"); 10 | tool_register_menu_function("Main menu|Modelling|Coordinate frame...|Reorient|", coordinates_reorient_using_current_camera); 11 | } 12 | 13 | // rotate the world-space so that the coordinate frame is orientet in the same direction as current camera 14 | // obtains LOCK_RW 15 | void coordinates_reorient_using_current_camera() 16 | { 17 | if (INDEX_IS_SET(ui_state.current_shot) && shots.data[ui_state.current_shot].calibrated) 18 | { 19 | coordinates_rotate_all_cameras(ui_state.current_shot); 20 | visualization_process_data(vertices, shots); 21 | } 22 | } 23 | 24 | // rotate space so that the coordinate frame coincides with chosen camera orientation 25 | bool coordinates_rotate_all_cameras(size_t shot_id) 26 | { 27 | ASSERT(validate_shot(shot_id), "invalid shot supplied when transforming calibration into camera's coordinate frame"); 28 | const Shot * const shot = shots.data + shot_id; 29 | CvMat * H; 30 | 31 | LOCK_RW(opencv) 32 | { 33 | H = cvCreateMat(4, 4, CV_64F); 34 | CvMat * I = cvCreateMat(4, 4, CV_64F); 35 | cvZero(I); 36 | cvZero(H); 37 | 38 | OPENCV_ELEM(I, 0, 0) = -1; 39 | OPENCV_ELEM(I, 1, 1) = 1; 40 | OPENCV_ELEM(I, 2, 2) = 1; 41 | OPENCV_ELEM(I, 3, 3) = 1; 42 | OPENCV_ELEM(H, 3, 3) = 1; 43 | for (int i = 0; i < 3; i++) 44 | { 45 | for (int j = 0; j < 3; j++) 46 | { 47 | OPENCV_ELEM(H, i, j) = OPENCV_ELEM(shot->rotation, j, i); 48 | } 49 | } 50 | 51 | cvMatMul(H, I, H); 52 | cvReleaseMat(&I); 53 | } 54 | UNLOCK_RW(opencv); 55 | 56 | printf("Coordinate frame aligned with camera.\n"); 57 | 58 | return coordinates_apply_homography_to_cameras(H); 59 | // todo release H 60 | } 61 | 62 | // applies homography to all calibrated cameras 63 | bool coordinates_apply_homography_to_cameras(CvMat * H) 64 | { 65 | for ALL(shots, i) 66 | { 67 | // consider only calibrated shots 68 | const Shot * const shot = shots.data + i; 69 | if (!shot->calibrated) continue; 70 | 71 | // multiply the projection matrix 72 | ATOMIC_RW(opencv, cvMatMul(shot->projection, H, shot->projection); ); 73 | 74 | // we need to decompose projection matrix to remain consistent 75 | geometry_calibration_from_P(i); 76 | } 77 | 78 | return true; 79 | } 80 | -------------------------------------------------------------------------------- /insight3d/ui_epipolars.cpp: -------------------------------------------------------------------------------- 1 | #include "ui_epipolars.h" 2 | 3 | // displays epipolars 4 | void ui_epipolars_display(const size_t shot_id, const size_t point_id) 5 | { 6 | ASSERT(validate_shot(shot_id), "invalid shot supplied"); 7 | ASSERT(validate_point(shot_id, point_id), "invalid point supplied"); 8 | Shot * const shot = shots.data + shot_id; 9 | const size_t vertex_id = shot->points.data[point_id].vertex; 10 | ASSERT_IS_SET(vertices_incidence, vertex_id); 11 | ASSERT(shots.data[shot_id].info_status >= GEOMETRY_INFO_DEDUCED, "image is displayed, but it's meta information wasn't stored"); 12 | 13 | // which calibration to use 14 | if (INDEX_IS_SET(ui_state.current_calibration)) 15 | { 16 | // find this shot in current calibration 17 | Calibration_Cameras * cameras = &calibrations.data[ui_state.current_calibration].Ps; 18 | bool found; 19 | size_t camera_id; 20 | LAMBDA_FIND(*cameras, camera_id, found, cameras->data[camera_id].shot_id == shot_id); 21 | 22 | if (found) 23 | { 24 | // * the shot is calibrated in this calibration, show epipolars * 25 | Calibration_Camera * camera = cameras->data + camera_id; 26 | 27 | // consider every fundamental matrix 28 | for ALL(camera->Fs, i) 29 | { 30 | Calibration_Fundamental_Matrix * fund = camera->Fs.data + i; 31 | const size_t first_shot_id = fund->first_shot_id; 32 | 33 | // check if we know the size of this image 34 | if (shots.data[first_shot_id].info_status < GEOMETRY_INFO_DEDUCED) continue; 35 | 36 | // check if this vertex is visible on this shot 37 | Double_Indices * ids = &vertices_incidence.data[vertex_id].shot_point_ids; 38 | bool first_shot_found; 39 | size_t first_shot_iter; 40 | LAMBDA_FIND(*ids, first_shot_iter, first_shot_found, ids->data[first_shot_iter].primary == first_shot_id); 41 | 42 | if (first_shot_found) 43 | { 44 | const size_t point_id = ids->data[first_shot_iter].secondary; 45 | 46 | // fundamental matrix is estimated and correspondence was marked on this shot 47 | double a, b, c; 48 | double 49 | x = shots.data[first_shot_id].points.data[point_id].x * shots.data[first_shot_id].width, 50 | y = shots.data[first_shot_id].points.data[point_id].y * shots.data[first_shot_id].height; 51 | 52 | // calculate epipolar 53 | opencv_epipolar(fund->F, x, y, a, b, c); 54 | 55 | // dipslay epipolar 56 | if (b != 0) 57 | { 58 | double x1 = 0, x2 = shots.data[first_shot_id].width; 59 | double y1 = (-a * x1 - c) / b, y2 = (-a * x2 - c) / b; 60 | x1 /= shots.data[first_shot_id].width; 61 | x2 /= shots.data[first_shot_id].width; 62 | y1 /= shots.data[first_shot_id].height; 63 | y2 /= shots.data[first_shot_id].height; 64 | 65 | ui_convert_xy_from_shot_to_opengl(x1, y1, x1, y1); 66 | ui_convert_xy_from_shot_to_opengl(x2, y2, x2, y2); 67 | 68 | LOCK_RW(opengl) 69 | { 70 | glBegin(GL_LINES); 71 | glVertex3d(x1, y1, -1); 72 | glVertex3d(x2, y2, -1); 73 | glEnd(); 74 | } 75 | UNLOCK_RW(opengl); 76 | } 77 | } 78 | } 79 | } 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /insight3d/mvg_resection.h: -------------------------------------------------------------------------------- 1 | #ifndef __MVG_RESECTION 2 | #define __MVG_RESECTION 3 | 4 | #include "core_debug.h" 5 | #include "interface_opencv.h" 6 | #include "mvg_decomposition.h" 7 | 8 | // computes projection matrix P given 3d points X and their projections x = PX 9 | // 10 | // computation is done using direct linear transform and SVD 11 | // 12 | // arguments: 13 | // 14 | // vertices - 3 x n or 4 x n, matrix with i-th column representing the i-th 15 | // 3d vertex in homogeneous or inhomogeneous coordinates respectively 16 | // projected - 2 x n matrix with i-th column representing the 2d point 17 | // on which the i-th 3d vertex is projected 18 | // P, K, R, T - allocated containers for the resulting matrices 19 | // sample - array of ns indices values specifying which correspondences 20 | // should be used 21 | // ns - number of samples 22 | // 23 | // returned value: 24 | // 25 | // true - if P has been successfully estimated 26 | // false - when it fails 27 | // 28 | // fails when: 29 | // 30 | // - vertices, projected, P are not allocated 31 | // - one of K, R, T is allocated, but not all of them 32 | // - the problem is underdetermined 33 | // - the size of matrices is inconsistent 34 | // - decomposition is required and the camera is infinite 35 | // 36 | bool mvg_resection_SVD( 37 | const CvMat * const vertices, 38 | const CvMat * const projected, 39 | CvMat * const P, 40 | CvMat * const K, 41 | CvMat * const R, 42 | CvMat * const T, 43 | bool normalize_A, 44 | int * samples = NULL, 45 | int ns = -1 46 | ); 47 | 48 | // robustly computes projection matrix P given 3d points X and their projections x = PX 49 | // 50 | // computation is done using RANSAC applied to mvg_resection_SVD 51 | // 52 | // arguments: 53 | // 54 | // vertices - 3 x n matrix with i-th column representing the coordinates 55 | // of the i-th 3d vertex 56 | // projected - 2 x n matrix with i-th column representing the 2d point 57 | // on which the i-th 3d vertex is projected 58 | // trials - number of trials/iterations to do 59 | // threshold - maximum value of reprojection error with which the vertex is 60 | // still considered inlier 61 | // inliers - (optional) array of n booleans used to mark which points 62 | // were considered to be inliers 63 | // 64 | // returned value: 65 | // 66 | // 3 x 4 projection matrix 67 | // 68 | // fails when: 69 | // 70 | // - whenever mvg_resection_SVD fails 71 | // - sufficiently large consensus set is not found 72 | // 73 | bool mvg_resection_RANSAC( 74 | const CvMat * const vertices, 75 | const CvMat * const projected, 76 | CvMat * const P, 77 | CvMat * const K, 78 | CvMat * const R, 79 | CvMat * const T, 80 | bool normalize_A = false, 81 | const int trials = 500, 82 | const double threshold = 4.0, 83 | bool * inliers = NULL 84 | ); 85 | 86 | // clamps down some values in internal calibration matrix 87 | bool mvg_restrict_calibration_matrix(CvMat * const K, const bool zero_skew, const bool square_pixels); 88 | 89 | #endif 90 | -------------------------------------------------------------------------------- /insight3d/application.cpp: -------------------------------------------------------------------------------- 1 | #include "application.h" 2 | 3 | double delta_time; // extern 4 | 5 | // initialize debuging (at this point simply prints out some info about 6 | // application data structures) 7 | bool debug_initialize() 8 | { 9 | /* printf("debug mode initialization\n"); 10 | printf("=========================\n"); 11 | printf("size of Point structure: %d\n", sizeof(Point)); 12 | printf("size of Vertex structure: %d\n", sizeof(Vertex)); 13 | printf("\n"); */ 14 | 15 | return true; 16 | } 17 | 18 | // initialize application subsystems 19 | bool initialization() 20 | { 21 | // GNU GPL license notification 22 | printf("insight3d 0.5, 2007-2010\n"); 23 | printf("licensed under GNU AGPL 3\n\n"); 24 | 25 | // note this crashes in debug on MSVC (2008 EE), for now avoid using strdup 26 | /*char * s = strdup("ahoy"); 27 | free(s);*/ 28 | 29 | // test memory allocation 30 | printf("testing memory allocation ... "); 31 | size_t * p = ALLOC(size_t, 100); 32 | FREE(p); 33 | p = ALLOC(size_t, 1); 34 | FREE(p); 35 | printf("ok\n"); // if we're still alive, everything's fine 36 | 37 | // initialize application structures 38 | printf("initializing application structures ... "); 39 | fflush(stdout); 40 | bool state = 41 | core_debug_initialize() && 42 | debug_initialize() && // todo merge this with core_debug 43 | core_initialize() && 44 | geometry_initialize() && 45 | image_loader_initialize(4, 32) && 46 | ui_initialize() && 47 | visualization_initialize() && 48 | ui_library_initialization() && 49 | ui_create() && 50 | image_loader_start_thread(); 51 | 52 | printf("ok\n"); 53 | 54 | // initialize the whole package 55 | return state; 56 | } 57 | 58 | static pthread_t gui_rendering_thread; 59 | 60 | // main loop 61 | bool main_loop() 62 | { 63 | bool is_active = true; 64 | Uint32 timestamp1 = SDL_GetTicks(), timestamp2 = 0; 65 | 66 | // create rendering thread 67 | printf("creating UI thread ... \n"); 68 | 69 | // start gui rendering thread 70 | gui_start_rendering_thread(); 71 | 72 | // respond to application events 73 | while (core_state.running) 74 | { 75 | GUI_Event_Descriptor event; 76 | 77 | // process event 78 | LOCK(geometry) 79 | { 80 | if (gui_poll_event(&event)) 81 | { 82 | // is this a GUI event? 83 | if (event.handler) 84 | { 85 | event.handler(event); 86 | } 87 | else // or is it an SDL event? 88 | { 89 | // handle an SDL event 90 | switch (event.sdl_event.type) 91 | { 92 | case SDL_KEYDOWN: 93 | { 94 | ui_state.key_state[event.sdl_event.key.keysym.sym] = 1; 95 | break; 96 | } 97 | 98 | case SDL_KEYUP: 99 | { 100 | ui_state.key_state[event.sdl_event.key.keysym.sym] = 0; 101 | break; 102 | } 103 | 104 | case SDL_MOUSEBUTTONUP: 105 | { 106 | ui_event_agar_button_up(&event.sdl_event); 107 | break; 108 | } 109 | 110 | case SDL_QUIT: 111 | { 112 | core_state.running = false; 113 | break; 114 | } 115 | } 116 | } 117 | } 118 | } 119 | UNLOCK(geometry); 120 | }; 121 | 122 | return true; 123 | } 124 | 125 | // deallocate program structures 126 | bool release() 127 | { 128 | geometry_release(); 129 | image_loader_release(); 130 | 131 | return true; 132 | } 133 | 134 | // error reporting routine 135 | bool report_error() 136 | { 137 | return false; 138 | } 139 | -------------------------------------------------------------------------------- /insight3d/mvg_decomposition.cpp: -------------------------------------------------------------------------------- 1 | #include "mvg_decomposition.h" 2 | #include "cv_extensions.h" 3 | 4 | // decomposition of projection matrix into rotation, translation and internal calibration 5 | bool mvg_finite_projection_matrix_decomposition(CvMat * const P, CvMat * const K, CvMat * const R, CvMat * const T) 6 | { 7 | // extract camera center, i.e. calculate the right null vector of P 8 | CvMat * W = cvCreateMat(4, 1, CV_64F), * V_transposed = cvCreateMat(4, 4, CV_64F); 9 | cvSVD(P, W, NULL, V_transposed, CV_SVD_V_T); // todo check singular values of P for numerical stability 10 | 11 | // check for camera at infinity 12 | const double w = OPENCV_ELEM(V_transposed, 3, 3); 13 | if (w == 0) 14 | { 15 | // deallocate and fail 16 | cvReleaseMat(&W); 17 | cvReleaseMat(&V_transposed); 18 | return false; 19 | } 20 | 21 | // camera center is the last row of V_transposed 22 | OPENCV_ELEM(T, 0, 0) = OPENCV_ELEM(V_transposed, 3, 0) / w; 23 | OPENCV_ELEM(T, 1, 0) = OPENCV_ELEM(V_transposed, 3, 1) / w; 24 | OPENCV_ELEM(T, 2, 0) = OPENCV_ELEM(V_transposed, 3, 2) / w; 25 | 26 | // fill in data for RQ decomposition 27 | CvMat * M = cvCreateMat(3, 3, CV_64F); 28 | for (int i = 0; i < 3; i++) 29 | { 30 | for (int j = 0; j < 3; j++) 31 | { 32 | OPENCV_ELEM(M, i, j) = OPENCV_ELEM(P, i, j); 33 | } 34 | } 35 | 36 | // allocate structures 37 | CvPoint3D64f euler = cvPoint3D64f(0, 0, 0); 38 | 39 | // perform decomposition 40 | CvMat * Qx = cvCreateMat(3, 3, CV_64F), * Qy = cvCreateMat(3, 3, CV_64F), * Qz = cvCreateMat(3, 3, CV_64F); 41 | cvComputeRQDecomposition(M, K, R, Qx, Qy, Qz, &euler); 42 | 43 | // multiply the calibration matrix so that [3, 3] entry is 1 44 | const double K33 = OPENCV_ELEM(K, 2, 2); 45 | if (K33 == 0) 46 | { 47 | // todo probably inifinite camera, we could handle this (and we've probably already done so, 48 | // since we check for inifinite cameras in the code above) 49 | cvReleaseMat(&V_transposed); 50 | cvReleaseMat(&W); 51 | cvReleaseMat(&M); 52 | cvReleaseMat(&Qx); 53 | cvReleaseMat(&Qy); 54 | cvReleaseMat(&Qz); 55 | return false; 56 | } 57 | const double lambda = 1 / K33; 58 | for (int i = 0; i < 3; i++) 59 | { 60 | for (int j = 0; j < 3; j++) 61 | { 62 | OPENCV_ELEM(K, i, j) *= lambda; 63 | } 64 | } 65 | OPENCV_ELEM(K, 2, 2) = 1; 66 | 67 | // release allocated data 68 | cvReleaseMat(&V_transposed); 69 | cvReleaseMat(&W); 70 | cvReleaseMat(&M); 71 | cvReleaseMat(&Qx); 72 | cvReleaseMat(&Qy); 73 | cvReleaseMat(&Qz); 74 | return true; 75 | } 76 | 77 | // assemble projection matrix 78 | void mvg_assemble_projection_matrix(CvMat * internal_calibration, CvMat * rotation, CvMat * translation, CvMat * projection) 79 | { 80 | // compute temporary matrices 81 | CvMat * M = cvCreateMat(3, 3, CV_64F); 82 | cvMatMul(internal_calibration, rotation, M); 83 | CvMat * minusC = cvCreateMat(3, 1, CV_64F); 84 | cvCopy(translation, minusC); 85 | OPENCV_ELEM(minusC, 0, 0) *= -1; 86 | OPENCV_ELEM(minusC, 1, 0) *= -1; 87 | OPENCV_ELEM(minusC, 2, 0) *= -1; 88 | CvMat * minusMC = cvCreateMat(3, 1, CV_64F); 89 | cvMatMul(M, minusC, minusMC); 90 | 91 | // save values 92 | for (size_t j = 0; j < 3; j++) 93 | { 94 | for (size_t k = 0; k < 3; k++) 95 | { 96 | OPENCV_ELEM(projection, j, k) = OPENCV_ELEM(M, j, k); 97 | } 98 | 99 | OPENCV_ELEM(projection, j, 3) = OPENCV_ELEM(minusMC, j, 0); 100 | } 101 | 102 | // release temporary matrices 103 | cvReleaseMat(&M); 104 | cvReleaseMat(&minusC); 105 | cvReleaseMat(&minusMC); 106 | } 107 | -------------------------------------------------------------------------------- /insight3d/ui_core.h: -------------------------------------------------------------------------------- 1 | #ifndef __UI_CORE 2 | #define __UI_CORE 3 | 4 | #include "portability.h" 5 | #include "core_structures.h" 6 | #include "geometry_structures.h" 7 | #include "ui_state.h" 8 | #include "ui_events.h" 9 | #include "gui_style.h" 10 | 11 | #ifdef LINUX 12 | #include 13 | #endif 14 | 15 | // ui core needs to see all tools to trigger their initialization 16 | #include "tool_core.h" 17 | #include "tool_file.h" 18 | #include "tool_edit.h" 19 | #include "tool_points.h" 20 | #include "tool_polygons.h" 21 | #include "tool_triangulation.h" 22 | #include "tool_resection.h" 23 | #include "tool_matching.h" 24 | #include "tool_calibration.h" 25 | #include "tool_coordinates.h" 26 | #include "tool_image.h" 27 | 28 | // GUI items 29 | enum UI_Item_Type { UI_ITEM_SHOT, UI_ITEM_VERTEX, UI_ITEM_SECTION }; 30 | 31 | struct UI_Meta 32 | { 33 | UI_Item_Type type; 34 | size_t index; 35 | }; 36 | 37 | struct UI_Shot_Meta 38 | { 39 | UI_Item_Type type; 40 | size_t index; 41 | bool selected; 42 | 43 | // special shot properties 44 | double view_center_x, view_center_y, view_zoom; // zooming and scrolling 45 | 46 | // GUI properties 47 | int list_id; // id in table displaying the list of all pictures 48 | }; 49 | 50 | struct UI_Section_Meta 51 | { 52 | UI_Item_Type type; 53 | size_t index; 54 | 55 | // special section properties 56 | bool unfolded; 57 | }; 58 | 59 | // initialize user interface 60 | bool ui_initialize(); 61 | 62 | // release allocated memory (called when program terminates) 63 | void ui_release(); 64 | 65 | // create new GUI item structure 66 | UI_Meta * ui_create_meta(UI_Item_Type type, size_t index); 67 | 68 | // create new GUI item structure for section 69 | UI_Section_Meta * ui_check_section_meta(UI_Section_Meta * & meta); 70 | 71 | // create new GUI item structure for shot 72 | UI_Shot_Meta * ui_check_shot_meta(size_t shot_id); 73 | 74 | // initialize GUI library 75 | bool ui_library_initialization(); 76 | 77 | // OpenGL settings 78 | bool ui_opengl_initialization(); 79 | 80 | // create dialogs for opening and saving files 81 | bool ui_create_file_dialogs(); 82 | 83 | // create additional dialogs 84 | bool ui_create_dialogs(); 85 | 86 | // create main window with glview and friends 87 | bool ui_create_main_window(); 88 | 89 | // create main application menu 90 | bool ui_create_menu(); 91 | 92 | // create tools 93 | bool ui_register_tools(); 94 | 95 | // finalize GUI creation 96 | bool ui_done(); 97 | 98 | // create gui structures and initialize 99 | bool ui_create(); 100 | 101 | // get viewport width and height in shot pixels 102 | // void ui_get_viewport_width_in_shot_coordinates(double & width, double & height); 103 | 104 | // converts screen coordinates to shot coordinate; if no shot is displayed, 105 | // convert to percentages of screen (aka virtual shot) 106 | void ui_convert_xy_from_screen_to_shot(Uint16 screen_x, Uint16 screen_y, double & x, double & y); 107 | 108 | // converts shot coordinates to opengl coordinates 109 | void ui_convert_xy_from_shot_to_opengl(const double shot_x, const double shot_y, double & x, double & y); 110 | 111 | // check if viewport is set 112 | bool ui_viewport_set(const size_t shot_id); 113 | 114 | // release dualview 115 | void ui_release_dualview(); 116 | 117 | // clears key state 118 | void ui_clear_key(int key); 119 | 120 | // prepare user interface for deletition of points, vertices or polygons 121 | void ui_prepare_for_deletition(bool points, bool vertices, bool polygons, bool shots, bool calibrations); 122 | 123 | #endif 124 | -------------------------------------------------------------------------------- /insight3d/mvg_camera.cpp: -------------------------------------------------------------------------------- 1 | #include "mvg_camera.h" 2 | 3 | // computes projective depth of a point X with respect to finite camera P 4 | double mvg_projective_depth(CvMat * P, CvMat * X) 5 | { 6 | // check if X is represented by a 4-vector or 3-vector 7 | const double T = X->rows == 4 ? OPENCV_ELEM(X, 3, 0) : 1; 8 | 9 | // retrieve 3x3 submatrix 10 | CvMat * M = cvCreateMat(3, 3, CV_64F); 11 | for (int i = 0; i < 3; i++) 12 | { 13 | for (int j = 0; j < 3; j++) 14 | { 15 | OPENCV_ELEM(M, j, i) = OPENCV_ELEM(P, j, i); 16 | } 17 | } 18 | 19 | // calculate the sign(det(M)) and w 20 | double d = cvDet(M); 21 | if (d != 0) d = d > 0 ? 1 : -1; else d = 0; 22 | const double w = 23 | OPENCV_ELEM(X, 0, 0) * OPENCV_ELEM(P, 2, 0) + 24 | OPENCV_ELEM(X, 1, 0) * OPENCV_ELEM(P, 2, 1) + 25 | OPENCV_ELEM(X, 2, 0) * OPENCV_ELEM(P, 2, 2) + 26 | T * OPENCV_ELEM(P, 2, 3); 27 | 28 | // and finally |M_3| 29 | double M3_norm = 0; 30 | for (int i = 0; i < 3; i++) 31 | { 32 | const double a = OPENCV_ELEM(M, 2, i); 33 | M3_norm += a * a; 34 | } 35 | cvReleaseMat(&M); 36 | M3_norm = cvSqrt(M3_norm); 37 | 38 | // check for division by zero 39 | double denominator = T * M3_norm; 40 | if (denominator == 0) return 1; // todo check if this happens iff P is camera at infini 41 | 42 | // return result 43 | return (d * w) / denominator; 44 | } 45 | 46 | // returns true if the point is in front of finite camera 47 | bool mvg_point_in_front_of_camera(CvMat * P, CvMat * X) 48 | { 49 | // which is iff the projective depth is non-negative 50 | return mvg_projective_depth(P, X) >= 0; 51 | } 52 | 53 | // create canonical camera 54 | void mvg_canonical_P(CvMat * P) 55 | { 56 | cvZero(P); 57 | 58 | for (size_t i = 0; i < 3; i++) 59 | { 60 | OPENCV_ELEM(P, i, i) = 1; 61 | } 62 | } 63 | 64 | // extracts canonical pair of projective matrices from fundamental matrix 65 | bool mvg_extract_Ps_from_F(CvMat * F, CvMat * P1, CvMat * P2) 66 | { 67 | // first extract left null vector of F 68 | CvMat * e_prime = opencv_left_null_vector(F); 69 | /*CvMat * e_prime_transposed = opencv_create_matrix(1, 3); 70 | cvTranspose(e_prime, e_prime_transposed); 71 | CvMat * r = opencv_create_matrix(1, 3); 72 | cvMatMul(e_prime_transposed, F, r); 73 | opencv_debug("Should be zero!", r);*/ 74 | mvg_canonical_P(P1); 75 | CvMat * Ex = opencv_create_cross_product_matrix(e_prime); 76 | CvMat * ExF = opencv_create_matrix(3, 3); 77 | cvMatMul(Ex, F, ExF); 78 | 79 | // assemble P2 80 | for (size_t i = 0; i < 3; i++) 81 | { 82 | for (size_t j = 0; j < 3; j++) 83 | { 84 | OPENCV_ELEM(P2, i, j) = OPENCV_ELEM(ExF, i, j); 85 | } 86 | 87 | OPENCV_ELEM(P2, i, 3) = OPENCV_ELEM(e_prime, i, 0); 88 | } 89 | 90 | // release resources 91 | cvReleaseMat(&e_prime); 92 | cvReleaseMat(&Ex); 93 | cvReleaseMat(&ExF); 94 | 95 | return true; 96 | } 97 | 98 | // calculates fundamental matrix for a pair of views given their projective matrices 99 | bool mvg_calculate_F_from_Ps(CvMat * P1, CvMat * P2, CvMat * F) 100 | { 101 | // find center of the first camera 102 | CvMat * C = opencv_right_null_vector(P1); 103 | 104 | // project it using P2 to find epipole e_prime 105 | CvMat * e_prime = opencv_create_matrix(3, 1); 106 | cvMatMul(P2, C, e_prime); 107 | 108 | // create cross product matrix for epipole 109 | CvMat * Ex = opencv_create_cross_product_matrix(e_prime); 110 | 111 | // calculate pseudoinverse of P1 112 | CvMat * P1_inverse = opencv_create_matrix(4, 3); 113 | cvInvert(P1, P1_inverse, CV_SVD); 114 | 115 | // F = Ex * P2 * P1_inverse 116 | CvMat * ExP2 = opencv_create_matrix(3, 4); 117 | cvMatMul(Ex, P2, ExP2); 118 | cvMatMul(ExP2, P1_inverse, F); 119 | 120 | // release memory 121 | cvReleaseMat(&C); 122 | cvReleaseMat(&e_prime); 123 | cvReleaseMat(&Ex); 124 | cvReleaseMat(&P1_inverse); 125 | cvReleaseMat(&ExP2); 126 | 127 | return true; 128 | } 129 | -------------------------------------------------------------------------------- /insight3d/core_debug.cpp: -------------------------------------------------------------------------------- 1 | #include "core_debug.h" 2 | 3 | struct Allocated_Memory 4 | { 5 | const char * description, * file, * line; 6 | void * p; 7 | size_t effective_size; 8 | bool active; 9 | }; 10 | 11 | const size_t core_magic_number = 0xDEADF00D; 12 | const size_t number_of_chunks = 500000; 13 | Allocated_Memory chunks[number_of_chunks]; 14 | size_t chunks_count; 15 | 16 | bool core_debug_initialize() 17 | { 18 | memset(chunks, 0, sizeof(Allocated_Memory) * number_of_chunks); 19 | chunks_count = 0; 20 | 21 | return true; 22 | } 23 | 24 | int core_abort() 25 | { 26 | abort(); 27 | return 1; 28 | } 29 | 30 | void debug(const char * message) 31 | { 32 | printf("%s\n", message); 33 | } 34 | 35 | void * allocate_memory(size_t size, const char * description, const char * file, const char * line) 36 | { 37 | // printf("Allocating #%d [%s:%s] %s\n", chunks_count, strrchr(file, '\\') ? strrchr(file, '\\') + 1 : file, line, description); 38 | const size_t chunk_size = sizeof(size_t) * 501 + size + sizeof(size_t) * 500; 39 | void * p = malloc(chunk_size); 40 | memset(p, 0, chunk_size); 41 | 42 | for (size_t i = 1; i < 501; i++) 43 | { 44 | ((size_t *)p)[i] = core_magic_number; 45 | } 46 | 47 | unsigned char * q = (unsigned char *)((size_t *)p + 501); 48 | 49 | for (size_t i = 0; i < size; i++) 50 | { 51 | q[i] = rand() % 256; 52 | } 53 | 54 | q += size; 55 | 56 | for (size_t i = 0; i < 500; i++) 57 | { 58 | ((size_t *)q)[i] = core_magic_number; 59 | /*if (rand() == 0) // deliberate corruption 60 | { 61 | ((size_t *)q)[i]++; 62 | }*/ 63 | } 64 | 65 | chunks[chunks_count].active = true; 66 | chunks[chunks_count].description = description; 67 | chunks[chunks_count].file = file; 68 | chunks[chunks_count].line = line; 69 | chunks[chunks_count].p = p; 70 | chunks[chunks_count].effective_size = size; 71 | *(size_t *)p = chunks_count++; 72 | return (size_t *)p + 501; 73 | } 74 | 75 | void free_memory(void * p) 76 | { 77 | size_t * c = (size_t *)p - 501; 78 | size_t id = *c; 79 | // printf("Free #%d ", id); 80 | // printf("[%s:%s] %s\n", strrchr(chunks[id].file, '\\') ? strrchr(chunks[id].file, '\\') + 1 : chunks[id].file, chunks[id].line, chunks[id].description); 81 | 82 | if (!check_chunk(id)) 83 | { 84 | report_invalid_chunk(id, "free"); 85 | ((char *)NULL)[0] = 1; 86 | // core_abort(); 87 | } 88 | 89 | chunks[id].active = false; 90 | } 91 | 92 | bool check_chunk(const size_t id) 93 | { 94 | // check the id is correct 95 | if (id >= chunks_count) 96 | { 97 | printf("Invalid chunk id.\n"); 98 | return false; 99 | } 100 | 101 | // the chunk must be active 102 | if (!chunks[id].active) 103 | { 104 | printf("Chunk free'd more than once.\n"); 105 | return false; 106 | } 107 | 108 | // check the front buffer 109 | for (size_t i = 1; i < 501; i++) 110 | { 111 | if (((size_t *)chunks[id].p)[i] != core_magic_number) 112 | { 113 | printf("Front buffer corrupted.\n"); 114 | return false; 115 | } 116 | } 117 | 118 | // check the back buffer 119 | char * p = (char *)((size_t *)chunks[id].p + 501); 120 | p += chunks[id].effective_size; 121 | for (size_t i = 0; i < 500; i++) 122 | { 123 | if ( 124 | ((size_t *)p)[i] != core_magic_number 125 | ) 126 | { 127 | printf("Back buffer corrupted.\n"); 128 | return false; 129 | } 130 | } 131 | 132 | return true; 133 | } 134 | 135 | void check_all_chunks() 136 | { 137 | printf("--\n"); 138 | printf("Checking allocated memory\n"); 139 | 140 | for (size_t i = 0; i < chunks_count; i++) 141 | { 142 | check_chunk(i); 143 | printf("."); 144 | } 145 | 146 | printf("\nFinished\n"); 147 | } 148 | 149 | void report_invalid_chunk(const size_t id, const char * situation) 150 | { 151 | printf( 152 | "WHAT: chunk #%d\nWHEN: on %s\nDESC: %s, %s:%s\n", 153 | id, 154 | situation, 155 | chunks[id].description, 156 | chunks[id].file, 157 | chunks[id].line 158 | ); 159 | } 160 | -------------------------------------------------------------------------------- /insight3d/ui_state.h: -------------------------------------------------------------------------------- 1 | #ifndef __UI_STATE 2 | #define __UI_STATE 3 | 4 | #include "gui.h" 5 | #include "geometry_structures.h" 6 | 7 | // application mode 8 | enum UI_Mode { UI_MODE_OVERVIEW, UI_MODE_INSPECTION, UI_MODE_SHOT, UI_MODE_CALCULATION, UI_MODE_UNSPECIFIED }; 9 | 10 | // object grouping 11 | struct Group 12 | { 13 | bool set; 14 | bool hidden; // true if the group is hidden 15 | char * title; // user can assign arbitrary name to a group 16 | GEOMETRY_ITEM_TYPE restriction; // group can be restricted to contain only some type of items (vertices, polygons, ...) // unused 17 | }; 18 | 19 | DYNAMIC_STRUCTURE_DECLARATIONS(Groups, Group); 20 | 21 | // user iterface state 22 | struct UI_State { 23 | 24 | // * global UI states * 25 | UI_Mode mode, previous_mode; 26 | 27 | // * GUI elements * 28 | 29 | // main application window, it's OpenGL widget and other layout widgets 30 | GUI_Panel 31 | * window, * pane, * pane_tools, * div_tools, * div_glview, 32 | * div_selections, * div_tabs, * vbox_selections, * vbox_tabs, 33 | * treeview, * treeview_shots, * treeview_vertices, /* * tabs, */ 34 | * div_toolbar, * toolbar, * list; 35 | 36 | // T gui transition elements 37 | GUI_Panel 38 | * root_panel, * top, * side, * gl, * side_top, * side_bottom, 39 | * side_top_last, * tabs 40 | ; 41 | 42 | // icons 43 | SDL_Surface * icons; 44 | 45 | // * SDL controls * 46 | 47 | // keyboard 48 | Uint8 * keys, * key_state; // pointer to array containing keys' state info (supplied by SDL) 49 | bool * inspection_clear_keys, * shot_clear_keys, * overview_clear_keys; // determines which key states should be automatically cleared 50 | int keys_length; // length of the keys_state array 51 | 52 | // mouse 53 | Uint8 mouse_button; 54 | int mouse_x, mouse_y, mouse_down_x, mouse_down_y; 55 | bool mouse_down; 56 | Uint32 mouse_down_ticks, mouse_dragging_ticks; 57 | bool mouse_no_dragging; 58 | bool mouse_over; 59 | 60 | // mouse coordinates for tools (recalculated into their own frame, with scrolling etc.) 61 | double tool_x, tool_y, tool_down_x, tool_down_y; 62 | 63 | // dragging 64 | double ground_phi_dragging_start, ground_alpha_dragging_start; // changing camera angle in ground inspection mode 65 | double ground_phi_dragging_speed, ground_alpha_dragging_speed; // todo 66 | double ground_POI_dragging_start[3]; // changing camera position in ground inspection mode 67 | 68 | // * workflow indices - current items and selections * 69 | 70 | // selection 71 | Selected_Items selection_list; 72 | 73 | // currently active items 74 | INDEX_DECLARATION(current_shot); 75 | 76 | // items currently being processed 77 | // for example, polygon is being processed when we're entering points corresponding 78 | // with it's vertices; after the user is done with the polygon, processed_polygon 79 | // index will jump to next polygon (or unset itself) 80 | INDEX_DECLARATION(processed_vertex); 81 | INDEX_DECLARATION(processed_polygon); 82 | int processed_vertex_stage; 83 | 84 | // focused items 85 | // these are the items under user's mouse cursor 86 | INDEX_DECLARATION(focused_point); 87 | 88 | // displayed calibration 89 | INDEX_DECLARATION(current_calibration); 90 | 91 | // * object grouping * 92 | Groups groups; 93 | 94 | // some special visualizations 95 | size_t dualview; 96 | bool dualview_set; 97 | 98 | // * options * 99 | const double inspection_camera_movement_speed; // movement speed (in space units per second) 100 | const double inspection_camera_rotation_speed; // rotation speed (in radians per second) 101 | const double ground_camera_movement_speed; 102 | 103 | // defaults 104 | UI_State(): 105 | inspection_camera_movement_speed(10), 106 | inspection_camera_rotation_speed(1), 107 | ground_camera_movement_speed(10) 108 | {} 109 | 110 | }; 111 | 112 | // global UI state variable 113 | extern UI_State ui_state; 114 | 115 | #endif 116 | -------------------------------------------------------------------------------- /insight3d/tool_resection.cpp: -------------------------------------------------------------------------------- 1 | #include "tool_resection.h" 2 | 3 | // register tool 4 | void tool_resection_create() 5 | { 6 | tool_create(UI_MODE_UNSPECIFIED, "Resection", "Estimate cameras using correspondence between reconstructred 3d vertices and their projection"); 7 | tool_register_menu_function("Main menu|Calibration|Camera resection|", tool_resection_current_camera); 8 | tool_register_menu_function("Main menu|Calibration|More resection...|Uncalibrated, lattice test|", tool_resection_all_lattice); 9 | tool_register_menu_function("Main menu|Calibration|More resection...|Uncalibrated, enough points|", tool_resection_all_enough); 10 | tool_register_menu_function("Main menu|Calibration|More resection...|Uncalibrated cameras|", tool_resection_all_uncalibrated); 11 | tool_register_menu_function("Main menu|Calibration|More resection...|All cameras|", tool_resection_all); 12 | tool_register_menu_function("Main menu|Calibration|More resection...|Sydney|", tool_resection_sydney); 13 | } 14 | 15 | // refresh GUI 16 | void resection_refresh() 17 | { 18 | ui_list_update(); 19 | visualization_process_data(vertices, shots); 20 | } 21 | 22 | // resection of current camera 23 | void tool_resection_current_camera() 24 | { 25 | if (!INDEX_IS_SET(ui_state.current_shot)) 26 | { 27 | return; 28 | } 29 | 30 | // call resectioning routine 31 | if (action_camera_resection(ui_state.current_shot, false, false)) 32 | { 33 | shots.data[ui_state.current_shot].resected = true; 34 | } 35 | 36 | resection_refresh(); 37 | } 38 | 39 | // resection of all uncalibrated cameras 40 | void tool_resection_all_uncalibrated() 41 | { 42 | for ALL(shots, i) 43 | { 44 | // check if this shot is uncalibrated 45 | if (!shots.data[i].calibrated) 46 | { 47 | // try camera calibration (will harmlessly fail when there are less than 6 points on the image) 48 | if (action_camera_resection(i, false, false)) 49 | { 50 | shots.data[i].resected = true; 51 | } 52 | } 53 | } 54 | 55 | resection_refresh(); 56 | } 57 | 58 | // resection of all cameras 59 | void tool_resection_all() 60 | { 61 | for ALL(shots, i) 62 | { 63 | // note just for now 64 | // if (!shots.data[i].resected) continue; 65 | 66 | // try camera calibration (will harmlessly fail when there are less than 6 points on the image) 67 | if (action_camera_resection(i, false, false)) 68 | { 69 | shots.data[i].resected = true; 70 | } 71 | } 72 | 73 | resection_refresh(); 74 | } 75 | 76 | void tool_resection_sydney() 77 | { 78 | // calculate the average focal length 79 | double avg_focal_length = 0; 80 | int shots_count = 0; 81 | 82 | for ALL(shots, i) 83 | { 84 | avg_focal_length += shots.data[i].f; 85 | shots_count++; 86 | } 87 | 88 | avg_focal_length /= shots_count; 89 | printf("%f\n", avg_focal_length); 90 | 91 | // adjust the focal length of the cameras 92 | /*for ALL(shots, i) 93 | { 94 | shots.data[i].f = avg_focal_length; 95 | geometry_calibration_from_P 96 | }*/ 97 | } 98 | 99 | // resection of all uncalibrated cameras with at least 12 (=2*6) points 100 | void tool_resection_all_enough() 101 | { 102 | for ALL(shots, i) 103 | { 104 | if (!shots.data[i].calibrated && query_count_reconstructed_points_on_shot(i) >= 12) 105 | { 106 | if (action_camera_resection(i, false, false)) // todo set .resection inside action_camera (in all ui_event_menu_resection_*) 107 | { 108 | shots.data[i].resected = true; 109 | } 110 | } 111 | } 112 | 113 | resection_refresh(); 114 | } 115 | 116 | // resection of all uncalibrated cameras satisfying lattice test 117 | void tool_resection_all_lattice() 118 | { 119 | for ALL(shots, i) 120 | { 121 | // check if this shot is uncalibrated and satisfies lattice test 122 | if (!shots.data[i].calibrated && geometry_lattice_test(i)) 123 | { 124 | if (action_camera_resection(i, false, false)) 125 | { 126 | shots.data[i].resected = true; 127 | } 128 | } 129 | } 130 | 131 | resection_refresh(); 132 | } 133 | 134 | -------------------------------------------------------------------------------- /insight3d/ui_visualization_helpers.cpp: -------------------------------------------------------------------------------- 1 | #include "ui_visualization_helpers.h" 2 | 3 | // draw helper cuber 4 | void visualization_helper_cube() 5 | { 6 | // draw cube 7 | opengl_drawing_style(UI_STYLE_HELPERS); 8 | glBegin(GL_LINES); 9 | glColor3f(1, 0, 0); 10 | glVertex3f(-1, -1, -1); glVertex3f(1, -1, -1); 11 | glColor3f(0, 1, 0); 12 | glVertex3f(-1, -1, -1); glVertex3f(-1, 1, -1); 13 | glColor3f(0, 0, 1); 14 | glVertex3f(-1, -1, -1); glVertex3f(-1, -1, 1); 15 | 16 | glColor3f(1, 1, 1); 17 | glVertex3f(1, 1, 1); glVertex3f(-1, 1, 1); 18 | glVertex3f(1, 1, 1); glVertex3f(1, -1, 1); 19 | glVertex3f(1, 1, 1); glVertex3f(1, 1, -1); 20 | glVertex3f(-1, -1, 1); glVertex3f(-1, -1, -1); 21 | glVertex3f(-1, -1, 1); glVertex3f(-1, 1, 1); 22 | glVertex3f(-1, -1, 1); glVertex3f(1, -1, 1); 23 | glVertex3f(-1, 1, -1); glVertex3f(1, 1, -1); 24 | glVertex3f(-1, 1, -1); glVertex3f(-1, -1, -1); 25 | glVertex3f(-1, 1, -1); glVertex3f(-1, 1, 1); 26 | glVertex3f(1, -1, -1); glVertex3f(-1, -1, -1); 27 | glVertex3f(1, -1, -1); glVertex3f(1, 1, -1); 28 | glVertex3f(1, -1, -1); glVertex3f(1, -1, 1); 29 | glEnd(); 30 | } 31 | 32 | // square vertices 33 | void visualization_helper_square(double x, double y, double side) 34 | { 35 | // draw square 36 | glVertex3d(x - side, y - side, -1); 37 | glVertex3d(x + side, y - side, -1); 38 | glVertex3d(x + side, y + side, -1); 39 | glVertex3d(x - side, y + side, -1); 40 | } 41 | 42 | // convert x axis distance from pixels to opengl coordinates 43 | double visualization_calc_dx(const double screen_distance_x) 44 | { 45 | ASSERT(INDEX_IS_SET(ui_state.current_shot), "cannot calculate coordinates with respect to image size when current shot is undefined"); 46 | ASSERT_IS_SET(shots, ui_state.current_shot); 47 | ASSERT(shots.data[ui_state.current_shot].info_status >= GEOMETRY_INFO_DEDUCED, "image proportions must be known when computing coordinates with respect to image size"); 48 | 49 | UI_Shot_Meta * meta = ui_check_shot_meta(ui_state.current_shot); 50 | // return screen_distance_x * ( * meta->view_zoom / ui_state.glview->wid.w); 51 | return 2 * screen_distance_x * ((shots.data[ui_state.current_shot].height / (double)shots.data[ui_state.current_shot].width) * 2 * meta->view_zoom / gui_get_height(ui_state.gl)); 52 | } 53 | 54 | // convert y axis distance from pixels to opengl coordinates 55 | double visualization_calc_dy(const double screen_distance_y) 56 | { 57 | ASSERT(INDEX_IS_SET(ui_state.current_shot), "cannot calculate coordinates with respect to image size when current shot is undefined"); 58 | ASSERT_IS_SET(shots, ui_state.current_shot); 59 | ASSERT(shots.data[ui_state.current_shot].info_status >= GEOMETRY_INFO_DEDUCED, "image proportions must be known when computing coordinates with respect to image size"); 60 | 61 | UI_Shot_Meta * meta = ui_check_shot_meta(ui_state.current_shot); 62 | return 2 * screen_distance_y * (2 * meta->view_zoom / gui_get_height(ui_state.gl)); 63 | } 64 | 65 | // absolute version of visualization_calc_dx 66 | double visualization_calc_x(const double shot_x, const double screen_distance_x) 67 | { 68 | return shot_x + visualization_calc_dx(screen_distance_x); 69 | } 70 | 71 | // absolute version of visualization_calc_dy 72 | double visualization_calc_y(const double shot_y, const double screen_distance_y) 73 | { 74 | return shot_y + visualization_calc_dy(screen_distance_y); 75 | } 76 | 77 | // recalculate squared distance from image pixels to screen pixels 78 | double visualization_calc_screen_distance_sq(double distance) 79 | { 80 | ASSERT(INDEX_IS_SET(ui_state.current_shot), "cannot calculate image distance current shot is undefined"); 81 | ASSERT_IS_SET(shots, ui_state.current_shot); 82 | ASSERT(shots.data[ui_state.current_shot].info_status >= GEOMETRY_INFO_DEDUCED, "image proportions must be known when computing coordinates with respect to image size"); 83 | 84 | UI_Shot_Meta * meta = ui_check_shot_meta(ui_state.current_shot); 85 | return sqr_value(sqrt(distance) * (gui_get_height(ui_state.gl) / (2 * meta->view_zoom * shots.data[ui_state.current_shot].height))); 86 | } 87 | -------------------------------------------------------------------------------- /insight3d/geometry_queries.cpp: -------------------------------------------------------------------------------- 1 | #include "geometry_queries.h" 2 | 3 | // determine if all of contour's vertices have been reconstructed 4 | bool query_is_contour_reconstructed(const Contour & contour, const Points & points, const Vertices & vertices) 5 | { 6 | for ALL(contour.vertices, i) 7 | { 8 | ASSERT_IS_SET(points, contour.vertices.data[i].value); 9 | const size_t vertex_id = points.data[contour.vertices.data[i].value].vertex; 10 | ASSERT_IS_SET(vertices, vertex_id); 11 | 12 | if (!vertices.data[vertex_id].reconstructed) return false; 13 | } 14 | 15 | return true; 16 | } 17 | 18 | // determine if all polygon's vertices have been reconstructed 19 | bool query_is_polygon_reconstructed(const Polygon_3d & polygon, const Vertices & vertices) 20 | { 21 | for ALL(polygon.vertices, i) 22 | { 23 | const size_t vertex_id = polygon.vertices.data[i].value; 24 | ASSERT_IS_SET(vertices, vertex_id); 25 | if (!vertices.data[vertex_id].reconstructed) return false; 26 | } 27 | 28 | return true; 29 | } 30 | 31 | // find point corresponding to a vertex on a given shot 32 | bool query_find_point_on_shot_by_vertex_id(size_t shot_id, size_t vertex_id, size_t & point_id) 33 | { 34 | // consistency check 35 | ASSERT_IS_SET(shots, shot_id); 36 | ASSERT_IS_SET(vertices, vertex_id); 37 | ASSERT_IS_SET(vertices_incidence, vertex_id); 38 | 39 | // go through all points of this vertex 40 | for ALL(vertices_incidence.data[vertex_id].shot_point_ids, i) 41 | { 42 | const Double_Index * const points_double_index = vertices_incidence.data[vertex_id].shot_point_ids.data + i; 43 | 44 | // if this point is on our shot 45 | if (points_double_index->primary == shot_id) 46 | { 47 | point_id = points_double_index->secondary; 48 | return true; 49 | } 50 | } 51 | 52 | // point was never found 53 | point_id = 0; 54 | return false; 55 | } 56 | 57 | // find nearest point on shot, returns squared distance in image pixels 58 | double query_nearest_point(const size_t shot_id, const double x, const double y, size_t & point_id, bool skipping_auto /*= false*/) 59 | { 60 | ASSERT(shots.data[shot_id].width > 0, "image has 0 width"); 61 | ASSERT(shots.data[shot_id].height > 0, "image has 0 height"); 62 | 63 | // go through all points on this shot and find the nearest one 64 | size_t i, best_point_id; 65 | double best_distance, d; 66 | bool best_found = false; 67 | 68 | LAMBDA( 69 | shots.data[shot_id].points, i, 70 | 71 | if (skipping_auto && vertices.data[shots.data[shot_id].points.data[i].vertex].vertex_type == GEOMETRY_VERTEX_AUTO) continue; 72 | 73 | d = distance_sq_2( 74 | shots.data[shot_id].points.data[i].x * shots.data[shot_id].width, 75 | shots.data[shot_id].points.data[i].y * shots.data[shot_id].height, 76 | x * shots.data[shot_id].width, 77 | y * shots.data[shot_id].height 78 | ); 79 | 80 | if (!best_found || d < best_distance) 81 | { 82 | best_distance = d; 83 | best_found = true; 84 | best_point_id = i; 85 | } 86 | ); 87 | 88 | if (best_found) 89 | { 90 | point_id = best_point_id; 91 | return best_distance; 92 | } 93 | else 94 | { 95 | point_id = SIZE_MAX; 96 | return -1.0; 97 | } 98 | } 99 | 100 | // count the number of reconstructed points on this shot 101 | size_t query_count_reconstructed_points_on_shot(const size_t shot_id) 102 | { 103 | ASSERT_IS_SET(shots, shot_id); 104 | const Shot * const shot = shots.data + shot_id; 105 | size_t count = 0; 106 | 107 | for ALL(shot->points, i) 108 | { 109 | const size_t vertex_id = shot->points.data[i].vertex; 110 | ASSERT_IS_SET(vertices, vertex_id); 111 | const Vertex * const vertex = vertices.data + vertex_id; 112 | if (vertex->reconstructed) count++; 113 | } 114 | 115 | return count; 116 | } 117 | 118 | // count the number of vertex's points 119 | size_t query_count_points_by_vertex(const size_t vertex_id) 120 | { 121 | ASSERT_IS_SET(vertices_incidence, vertex_id); 122 | 123 | size_t count = 0; 124 | for ALL(vertices_incidence.data[vertex_id].shot_point_ids, i) 125 | { 126 | count++; 127 | } 128 | 129 | return count; 130 | } 131 | -------------------------------------------------------------------------------- /insight3d/interface_opencv.h: -------------------------------------------------------------------------------- 1 | #ifndef __INTERFACE_OPENCV 2 | #define __INTERFACE_OPENCV 3 | 4 | #include "stdio.h" 5 | #include "pthread.h" 6 | #include "opencv/cv.h" 7 | #include "opencv/highgui.h" 8 | 9 | extern pthread_mutex_t opencv_mutex; 10 | 11 | const double OPENCV_PI = 3.14159265358979323846; 12 | 13 | // macro for accessing double precision matrix elements // todo avoid using OpenCV macro 14 | #define OPENCV_ELEM(matrix, i, j) (CV_MAT_ELEM((*(matrix)), double, (i), (j))) 15 | 16 | // create double precision matrix filled with zeros 17 | CvMat * opencv_create_matrix(const size_t rows, const size_t cols); 18 | 19 | // create double precision matrix filled with data from an array 20 | CvMat * opencv_create_matrix(const size_t rows, const size_t cols, double data[]); 21 | 22 | // new identity matrix 23 | CvMat * opencv_create_I_matrix(const size_t n); 24 | 25 | // create double precision column vector from array of doubles 26 | CvMat * opencv_create_vector(const double a[], const size_t length); 27 | 28 | // x axis rotation matrix 29 | // todo optimize 30 | // note these matrices are transposes of conventional mathematical rotation matrices 31 | // (which is ugly, but it just so happens, that we need it this way) 32 | CvMat * opencv_create_rotation_matrix_x(const double angle); 33 | 34 | // y axis rotation matrix 35 | // todo optimize 36 | CvMat * opencv_create_rotation_matrix_y(const double angle); 37 | 38 | // z axis rotation matrix 39 | // todo optimize 40 | CvMat * opencv_create_rotation_matrix_z(const double angle); 41 | 42 | // euler angles to rotation matrix 43 | // todo optimize 44 | CvMat * opencv_create_rotation_matrix_from_euler(const double euler[], bool reverse_order = true); 45 | 46 | // project vertex - used only for visualization purposes 47 | void opencv_vertex_projection_visualization(const CvMat * const P, const double x, const double y, const double z, double reprojection[]); 48 | 49 | // project vertex - used only for visualization purposes 50 | void opencv_vertex_projection_visualization(const CvMat * const P, const double x, const double y, const double z, const double w, double reprojection[]); 51 | 52 | // project vertex represented by homogeneous vector - used only for visualization purposes 53 | void opencv_vertex_projection_visualization(const CvMat * const P, const CvMat * X, double reprojection[]); 54 | 55 | // decompose rotation matrix into euler angles 56 | void opencv_rotation_matrix_to_angles(const CvMat * const R, double & ax, double & ay, double & az); 57 | 58 | // debug function prints matrix to standard output 59 | void opencv_debug(const char * title, CvMat * A); 60 | 61 | // downsize image 62 | void opencv_downsize(IplImage ** img, const int max_size); 63 | 64 | // create copy scaled down below some width threshold 65 | IplImage * opencv_downsize_copy(IplImage * img, const int max_size); 66 | 67 | // load image and scale it down below some width threshold 68 | IplImage * opencv_load_image(const char * filename, const int max_size); 69 | 70 | // creates trivial image 71 | IplImage * opencv_create_substitute_image(); 72 | 73 | // creates image with sides of the form 2^n 74 | IplImage * opencv_create_exp_image(const int width, const int height, const int depth, const int channels); 75 | 76 | // calculate right null-vector of matrix A 77 | CvMat * opencv_right_null_vector(CvMat * A); 78 | 79 | // calculate left null-vector of matrix A 80 | CvMat * opencv_left_null_vector(CvMat * A); 81 | 82 | // create cross product matrix for 3-vector x 83 | CvMat * opencv_create_cross_product_matrix(CvMat * x); 84 | 85 | // scale vector homogeneous vector so that it's last coordinate is 1 86 | void opencv_rescale_homogeneous_vector(CvMat * X); 87 | 88 | // normalize vector 89 | void opencv_normalize(CvMat * x); 90 | 91 | // normalize vector 92 | void opencv_normalize_inhomogeneous(CvMat * x); 93 | 94 | // normalize vector 95 | void opencv_normalize_homogeneous(CvMat * x); 96 | 97 | // calculate epipolar line 98 | void opencv_epipolar(const CvMat * const F, const double x, const double y, double & a, double & b, double & c); 99 | 100 | // point-in-polygon test 101 | bool opencv_pip(const double x, const double y, const CvMat * polygon); 102 | 103 | #endif 104 | -------------------------------------------------------------------------------- /insight3d/core_math_routines.h: -------------------------------------------------------------------------------- 1 | #ifndef __CORE_MATH_ROUTINES 2 | #define __CORE_MATH_ROUTINES 3 | 4 | #include 5 | #include "core_debug.h" 6 | #include "core_constants.h" 7 | 8 | // * basic math functionality * 9 | 10 | // returns true if the value's magnitude borders machine precision 11 | bool nearly_zero(const double x); 12 | 13 | // negate a variable 14 | void negate(bool & b); 15 | 16 | // signum 17 | signed char sgn(const double x); 18 | 19 | // square of a real number 20 | double sqr_value(const double x); 21 | 22 | // maximum of two values 23 | double max_value(const double x, const double y); 24 | 25 | // minimum of two values 26 | double min_value(const double x, const double y); 27 | 28 | // average of two values 29 | double average_value(const double a, const double b); 30 | 31 | // swap values of variables 32 | void swap_double(double & a, double & b); 33 | 34 | // swap size_t values 35 | void swap_size_t(size_t & a, size_t & b); 36 | 37 | // swap bool values 38 | void swap_bool(bool & a, bool & b); 39 | 40 | // value is inside closed interval 41 | bool inside_interval(const double value, double boundary1, double boundary2); 42 | 43 | // value is inside open interval 44 | bool inside_open_interval(const double value, double boundary1, double boundary2); 45 | 46 | // vector is inside rectangle 47 | bool inside_2d_interval(const double x, const double y, const double x1, const double y1, const double x2, const double y2); 48 | 49 | // convert radians to degrees 50 | double rad2deg(const double a); 51 | 52 | // convert degrees to radians 53 | double deg2rad(const double d); 54 | 55 | // substraction of two 3-vectors 56 | void sub_3(const double * a, const double * b, double * result); 57 | 58 | // addition of two 3-vectors 59 | void add_3(const double * a, const double * b, double * result); 60 | 61 | // multiply 3-vector by scalar 62 | void mul_3(const double x, const double * a, double * result); 63 | 64 | // add multiplied 3-vector to another 3-vector 65 | void add_mul_3(const double * a, const double x, const double * b, double * result); 66 | 67 | // dot product of two 3-vectors 68 | double dot_3(const double * a, const double * b); 69 | 70 | // dot product of two 3-vectors, the second one given by it's coordinates 71 | double dot_3xyz(const double * a, const double x, const double y, const double z); 72 | 73 | // cross product of two 3-vectors 74 | void cross_3(const double * a, const double * b, double * result); 75 | 76 | // linear combination of four 3-vectors 77 | void linear_combination_43(const double * a, const double * b, const double * c, const double * d, 78 | const double xa, const double xb, const double xc, const double xd, 79 | double * result); 80 | 81 | // linear combination of three 3-vectors 82 | void linear_combination_33(const double * a, const double * b, const double * c, 83 | const double xa, const double xb, const double xc, 84 | double * result); 85 | 86 | // linear combination of three 3-vectors 87 | void linear_combination_23(const double * a, const double * b, 88 | const double xa, const double xb, 89 | double * result); 90 | 91 | // vector L2 norm 92 | double vector_norm(double * x, size_t length); 93 | 94 | // L2 norm of a 3-vector 95 | double vector_norm_3(const double * x); 96 | 97 | // distance of two 3-vectors 98 | double distance_sq_3(const double * a, const double * b); 99 | 100 | // distance of two-3-vectors (different arguments) 101 | double distance_sq_3(const double x1, const double y1, const double z1, const double x2, const double y2, const double z2); 102 | 103 | // distance of two 2-vectors 104 | double distance_sq_2(const double * a, const double * b); 105 | 106 | // distance of two 2-vectors (different arguments) 107 | double distance_sq_2(const double x1, const double y1, const double x2, const double y2); 108 | 109 | // normalize vector to unit length 110 | void normalize_vector(double * x, size_t length); 111 | 112 | // normalize inhomogeneous part of homogeneous vector 113 | void normalize_inhomogeneous_part(double * v, size_t length); 114 | 115 | // normalize angle 116 | double normalize_angle(double a); 117 | 118 | // nearest point on plane 119 | void nearest_point_on_plane(const double * plane, const double * point, double * result); 120 | 121 | // estimate plane parameters from 3 points (first 3 of the inhomogeneous coordinates are normalized) 122 | bool plane_from_three_points(const double * a, const double * b, const double * c, double * normal); 123 | 124 | #endif 125 | -------------------------------------------------------------------------------- /insight3d/tool_polygons.cpp: -------------------------------------------------------------------------------- 1 | #include "tool_polygons.h" 2 | 3 | // tool's state structure 4 | struct Tool_Polygons 5 | { 6 | }; 7 | 8 | static Tool_Polygons tool_polygons; 9 | 10 | // create tool 11 | void tool_polygons_create() 12 | { 13 | tool_create(UI_MODE_SHOT, "Polygons creator", "Let's you join vertices into polygons"); 14 | 15 | tool_set_process_events_function(tool_requires_current_shot); 16 | tool_set_key_pressed_event_handler(tool_polygons_key); 17 | tool_set_mouse_down_handler(tool_polygons_mouse_down); 18 | tool_set_click_handler(tool_polygons_click); 19 | tool_set_move_handler(tool_polygons_move); 20 | tool_set_dragging_handler(tool_polygons_dragging); 21 | tool_set_dragging_done_handler(tool_polygons_dragging_done); 22 | tool_set_begin_handler(tool_polygons_begin); 23 | tool_set_end_handler(tool_polygons_end); 24 | 25 | tool_register_toolbar_button("Polygons creator"); 26 | } 27 | 28 | // tool activated 29 | void tool_polygons_begin() 30 | { 31 | memset(&tool_polygons, 0, sizeof(tool_polygons)); 32 | } 33 | 34 | // tool deactivated 35 | void tool_polygons_end() 36 | { 37 | } 38 | 39 | // user pressed mouse button 40 | bool tool_polygons_mouse_down(double x, double y, int button) 41 | { 42 | // there are events we don't care about and want to pass them to other tools 43 | if (sdl_wheel_button(button) || button == SDL_BUTTON_RIGHT) 44 | { 45 | TOOL_PASS_MOUSE_DOWN(selection); 46 | } 47 | 48 | if (sdl_ctrl_pressed()) 49 | { 50 | return true; 51 | } 52 | 53 | // if there is a focused point, add it to the polygon 54 | if (INDEX_IS_SET(ui_state.focused_point)) 55 | { 56 | // if no polygon is being processed, create a new one 57 | size_t polygon_id; 58 | if (!INDEX_IS_SET(ui_state.processed_polygon)) 59 | { 60 | geometry_new_polygon(polygon_id); 61 | INDEX_SET(ui_state.processed_polygon, polygon_id); 62 | } 63 | else 64 | { 65 | polygon_id = ui_state.processed_polygon; 66 | } 67 | 68 | // ok, check if this polygon already contains this vertex 69 | const size_t vertex_id = shots.data[ui_state.current_shot].points.data[ui_state.focused_point].vertex; 70 | ASSERT_IS_SET(vertices, vertex_id); 71 | 72 | bool found; 73 | size_t polygon_iter; 74 | LAMBDA_FIND(polygons.data[polygon_id].vertices, polygon_iter, found, 75 | polygons.data[polygon_id].vertices.data[polygon_iter].value == vertex_id); 76 | 77 | // if it is there and shift is pressed, remove it 78 | if (found) 79 | { 80 | if (sdl_shift_pressed()) // strong TODO!!! this can't be used here! 81 | { 82 | polygons.data[polygon_id].vertices.data[polygon_iter].set = false; 83 | } 84 | } 85 | else 86 | { 87 | // otherwise, add it to the polygon 88 | ADD(polygons.data[polygon_id].vertices); 89 | LAST(polygons.data[polygon_id].vertices).value = vertex_id; 90 | } 91 | } 92 | /*else // if there is no focused point, pass the event to points tool 93 | { 94 | TOOL_PASS_MOUSE_DOWN(points); 95 | }*/ 96 | 97 | return true; 98 | } 99 | 100 | // user pressed key 101 | void tool_polygons_key() 102 | { 103 | if (ui_state.key_state[SDLK_RETURN] || ui_state.key_state[SDLK_PAGEDOWN]) 104 | { 105 | ui_workflow_next_polygon(); 106 | ui_state.key_state[SDLK_RETURN] = false; 107 | ui_state.key_state[SDLK_PAGEDOWN] = false; 108 | } 109 | 110 | if (ui_state.key_state[SDLK_BACKSPACE] || ui_state.key_state[SDLK_PAGEUP]) 111 | { 112 | ui_workflow_prev_polygon(); 113 | ui_state.key_state[SDLK_BACKSPACE] = false; 114 | ui_state.key_state[SDLK_PAGEUP] = false; 115 | } 116 | 117 | TOOL_PASS_KEY(selection); 118 | } 119 | 120 | // user moves mouse - set focused point 121 | void tool_polygons_move(double x, double y) 122 | { 123 | size_t point_id; 124 | bool found = ui_selection_get_point_by_position(x, y, point_id); 125 | 126 | if (found) 127 | { 128 | ui_workflow_set_focused_point(point_id); 129 | } 130 | else if (INDEX_IS_SET(ui_state.focused_point)) 131 | { 132 | ui_workflow_unset_focused_point(); 133 | } 134 | } 135 | 136 | // user can move focused point when dragging (also, focused point will not change until dragging is over) 137 | void tool_polygons_dragging(double x, double y, int button) 138 | { 139 | // there are events we don't care about and want to pass them to other tools 140 | if (sdl_wheel_button(button)) 141 | { 142 | TOOL_PASS_DRAGGING(selection); 143 | } 144 | 145 | if (sdl_ctrl_pressed()) 146 | { 147 | TOOL_PASS_DRAGGING(points); 148 | } 149 | } 150 | 151 | // user finished dragging 152 | void tool_polygons_dragging_done(double x1, double y1, double x2, double y2, int button) 153 | { 154 | if (sdl_ctrl_pressed()) 155 | { 156 | TOOL_PASS_DRAGGING_DONE(points); 157 | } 158 | 159 | TOOL_PASS_DRAGGING_DONE(selection); 160 | } 161 | 162 | // mouse click 163 | void tool_polygons_click(double x, double y, int button) 164 | { 165 | /*if (!tool_points.new_point_created) 166 | { 167 | // pass this event to selection tool 168 | TOOL_PASS_CLICK(selection); 169 | } 170 | else 171 | { 172 | ui_empty_selection_list(); 173 | }*/ 174 | } 175 | -------------------------------------------------------------------------------- /insight3d/interface_filesystem.cpp: -------------------------------------------------------------------------------- 1 | #include "interface_filesystem.h" 2 | 3 | // returns file's directory, NULL is returned if filename ends with path separator 4 | char * interface_filesystem_dirpath(const char * const filename) 5 | { 6 | const size_t len = strlen(filename); 7 | 8 | // check if the last character is path separator 9 | if (strchr(FILESYSTEM_PATH_SEPARATORS, filename[len - 1])) 10 | { 11 | return NULL; 12 | } 13 | 14 | // find last path separator 15 | const char * last_separator = NULL, * separator = filename - 1; 16 | while (separator = strpbrk(separator + 1, FILESYSTEM_PATH_SEPARATORS)) 17 | { 18 | last_separator = separator; 19 | } 20 | 21 | // finally return the path to directory 22 | const size_t separator_offset = last_separator - filename; 23 | char * dirpath = ALLOC(char, separator_offset + 1); 24 | memcpy(dirpath, filename, separator_offset); 25 | dirpath[separator_offset] = '\0'; 26 | 27 | return dirpath; 28 | } 29 | 30 | // returns file name without basepath 31 | char * interface_filesystem_extract_filename(const char * filename) 32 | { 33 | const size_t len = strlen(filename); 34 | 35 | // check if the last character is path separator 36 | if (strchr(FILESYSTEM_PATH_SEPARATORS, filename[len - 1])) 37 | { 38 | return NULL; 39 | } 40 | 41 | // find last path separator 42 | const char * last_separator = NULL, * separator = filename; 43 | while (separator = strpbrk(++separator, FILESYSTEM_PATH_SEPARATORS)) 44 | { 45 | last_separator = separator; 46 | } 47 | 48 | if (!last_separator) 49 | { 50 | const size_t len = strlen(filename); 51 | char * p = ALLOC(char, len + 1); 52 | memcpy(p, filename, len + 1); 53 | return p; 54 | } 55 | 56 | // copy part of the filename 57 | const size_t separator_pos = last_separator - filename; 58 | const size_t filename_len = len - separator_pos; 59 | char * extracted = /*(char *)malloc(sizeof(char) * (filename_len + 1));*/ ALLOC(char, filename_len + 1); 60 | memcpy(extracted, last_separator + 1, sizeof(char) * (filename_len + 1)); 61 | extracted[filename_len] = '\0'; 62 | return extracted; 63 | } 64 | 65 | // cleans up "/C:/something/..." to "C:/something/..." if necessary 66 | char * interface_filesystem_cleanup_windows_filename(const char * filename) 67 | { 68 | const size_t len = strlen(filename); 69 | char * clean_filename; 70 | 71 | if (len >= 3 && filename[0] == '/' && filename[2] == ':') 72 | { 73 | clean_filename = ALLOC(char, len); 74 | memcpy(clean_filename, filename + 1, len); 75 | } 76 | else 77 | { 78 | char * str = ALLOC(char, len + 1); 79 | memcpy(str, filename, sizeof(char) * (len + 1)); 80 | str[len] = '\0'; 81 | clean_filename = str; 82 | } 83 | 84 | return clean_filename; 85 | } 86 | 87 | // cleans up path file path and converts relative path to absolute 88 | char * interface_filesystem_cleanup_filename(const char * fn, const char * directory) 89 | { 90 | // cleanup windows filename 91 | char * filename = interface_filesystem_cleanup_windows_filename(fn); 92 | if (!directory) return filename; 93 | 94 | // convert relative path to absolute 95 | if (filename[0] == '.') 96 | { 97 | // first take the directory part of the path 98 | const size_t directory_len = strlen(directory); 99 | char * relative_path = filename; 100 | const size_t relative_path_len = strlen(relative_path); 101 | 102 | // merge it 103 | filename = ALLOC(char, (directory_len + 1 + relative_path_len + 1)); 104 | filename[0] = '\0'; 105 | strcat(filename, directory); 106 | strcat(filename, "/"); 107 | strcat(filename, relative_path); 108 | 109 | // free helper string 110 | FREE(relative_path); 111 | } 112 | 113 | return filename; 114 | } 115 | 116 | // compares two filenames based on the name of the file without basepath 117 | bool interface_filesystem_compare_filenames(const char * f1, const char * f2) 118 | { 119 | char * e1 = interface_filesystem_extract_filename(f1), * e2 = interface_filesystem_extract_filename(f2); 120 | bool result = strcmp(e1, e2) == 0; 121 | FREE(e1); 122 | FREE(e2); 123 | return result; 124 | } 125 | 126 | // adjusts filename for export into RealVIZ file format 127 | char * interface_filesystem_realviz_filename(const char * filename) 128 | { 129 | // if it's not a unix-style filename, add root at the beginning 130 | if (filename[0] != '/') 131 | { 132 | const size_t len = strlen(filename); 133 | char * modified = ALLOC(char, len + 2); 134 | modified[0] = '/'; 135 | memcpy(modified + 1, filename, len + 1); 136 | return modified; 137 | } 138 | else 139 | { 140 | const size_t len = strlen(filename); 141 | char * copy = ALLOC(char, len + 1); 142 | memcpy(copy, filename, (len + 1) * sizeof(char)); 143 | copy[len] = '\0'; 144 | return copy; 145 | } 146 | } 147 | 148 | // determines if path is absolute or relative 149 | // note this is dirty... 150 | bool interface_filesystem_is_relative(const char * filename) 151 | { 152 | if (!filename) return true; // note really necessary 153 | return !(filename[0] == '/' || strlen(filename) > 1 && filename[1] == ':'); 154 | } 155 | -------------------------------------------------------------------------------- /insight3d/mvg_triangulation.h: -------------------------------------------------------------------------------- 1 | #ifndef __MVG_TRIANGULATION 2 | #define __MVG_TRIANGULATION 3 | 4 | #include "core_debug.h" 5 | #include "interface_opencv.h" 6 | #include "mvg_thresholds.h" 7 | 8 | // triangulates 3d position of a point given projection matrix of each camera 9 | // and the coordinates where the point is visible on each camera image 10 | // 11 | // computation is done using direct linear transform and SVD, assuming that 12 | // the point is finite; this triangulation method is fairly suitable if we're 13 | // in affine space 14 | // 15 | // arguments: 16 | // 17 | // projection_matrices - array of n projection matrices 18 | // projected_points - 2 x n matrix with i-th column representing the 19 | // coordinates on which the triangulated vertex 20 | // is visible on i-th camera 21 | // normalize_A - flag denotes if the matrix A and vector b should be 22 | // normalized 23 | // min_points - the minimum number of points required for triangulation 24 | // samples - pointer to indices of points that should be used, if NULL is 25 | // supplied, all of them are used 26 | // ns - number of samples 27 | // 28 | // returned value: 29 | // 30 | // 3-dimensional column vector holding inhomogeneous coordinates of 31 | // the reconstructed point 32 | // 33 | CvMat * mvg_triangulation_SVD_affine( 34 | const CvMat * projection_matrices[], 35 | const CvMat * projected_points, 36 | bool normalize_A = false, 37 | const unsigned int min_points = 2, 38 | int * samples = NULL, 39 | int ns = -1 40 | ); 41 | 42 | // triangulates 3d position of a point given projection matrix of each camera 43 | // and the coordinates where the point is visible on each camera image 44 | // 45 | // computation is done using direct linear transform and SVD, reconstructed 46 | // vertices are allowed to be infinite 47 | // 48 | // arguments: 49 | // 50 | // projection_matrices - array of n projection matrices 51 | // projected_points - 2 x n matrix with i-th column representing the 52 | // coordinates on which the triangulated vertex 53 | // is visible on i-th camera 54 | // normalize_A - flag denotes if the matrix A should be normalized // todo 55 | // min_points - the minimum number of points required for triangulation 56 | // samples - pointer to indices of points that should be used, if NULL is 57 | // supplied, all of them are used 58 | // ns - number of samples 59 | // 60 | // returned value: 61 | // 62 | // 4-dimensional column vector holding homogeneous coordinates of 63 | // the reconstructed point 64 | // 65 | CvMat * mvg_triangulation_SVD( 66 | const CvMat * projection_matrices[], 67 | const CvMat * projected_points, 68 | bool normalize_A = false, 69 | const unsigned int min_points = 2, 70 | int * samples = NULL, 71 | int ns = -1 72 | ); 73 | 74 | // robustly estimates the 3d position of a point given projection matrix of 75 | // each camera and the coordinates where the point is visible on each camera image 76 | // 77 | // computation is done via RANSAC applied to mvg_triangulation_SVD_affine 78 | // or mvg_triangulation_SVD 79 | // 80 | // arguments: 81 | // 82 | // projection_matrices - array of n projection matrices 83 | // projected_points - 2 x n matrix with i-th column representing the 84 | // coordinates on which the triangulated vertex 85 | // is visible on i-th camera 86 | // affine - true if affine triangulation should be used 87 | // normalize_A - apply normalization of matrix A (and, if applicable, 88 | // of vector b) 89 | // min_inliers_to_reconstruct - minimum number of inliers to reliably 90 | // reconstruct the vertex (used in final 91 | // triangulation) 92 | // trials - number of trials/iterations to do 93 | // threshold - maximum value of reprojection error with which the 94 | // point is still considered to be inlier 95 | // inliers - array of n bool values used to mark which points 96 | // are considered to be inliers 97 | // 98 | // returned value: 99 | // 100 | // 3- or 4-dimensional column vector holding (in)homogeneous coordinates of 101 | // the reconstructed point; inhomogeneous coordinates are used iff 102 | // the parameter affine was false 103 | // 104 | CvMat * mvg_triangulation_RANSAC( 105 | const CvMat * projection_matrices[], 106 | const CvMat * projected_points, 107 | const bool affine, 108 | const bool normalize_A = false, 109 | const int min_inliers_to_triangulate = MVG_MIN_INLIERS_TO_TRIANGULATE, 110 | const int min_inliers_to_triangulate_weaker = MVG_MIN_INLIERS_TO_TRIANGULATE_WEAKER, 111 | const int trials = MVG_RANSAC_TRIANGULATION_TRIALS, 112 | const double threshold = MVG_MEASUREMENT_THRESHOLD, 113 | bool * inliers = NULL 114 | ); 115 | 116 | #endif 117 | -------------------------------------------------------------------------------- /insight3d/core_image_loader.h: -------------------------------------------------------------------------------- 1 | #ifndef __CORE_IMAGE_LOADER 2 | #define __CORE_IMAGE_LOADER 3 | 4 | #include "interface_opengl.h" 5 | #include "interface_opencv.h" 6 | #include "interface_sdl.h" 7 | #include "core_state.h" 8 | #include "core_debug.h" 9 | #include "core_structures.h" 10 | #include 11 | 12 | // specifies the desired quality of requested image 13 | enum Image_Loader_Quality { IMAGE_LOADER_NOT_LOADED, IMAGE_LOADER_LOW_RESOLUTION, IMAGE_LOADER_FULL_RESOLUTION, IMAGE_LOADER_CONTINUOUS_LOADING }; 14 | enum Image_Loader_Content { IMAGE_LOADER_ALL, IMAGE_LOADER_CENTER, IMAGE_LOADER_REGION }; 15 | 16 | // small structure uniquely identifying single request 17 | struct Image_Loader_Request_Handle 18 | { 19 | size_t id, time; 20 | }; 21 | 22 | // request descriptor 23 | struct Image_Loader_Request 24 | { 25 | bool set; 26 | 27 | // what do we want to load 28 | size_t shot_id; 29 | Image_Loader_Quality quality; 30 | Image_Loader_Content content; 31 | double x, y, sx, sy; 32 | 33 | // result 34 | bool done; 35 | Image_Loader_Quality current_quality; 36 | GLuint gl_texture_id; 37 | Image_Loader_Quality gl_texture_quality; 38 | double gl_texture_min_x, gl_texture_min_y, gl_texture_max_x, gl_texture_max_y; 39 | IplImage * image; 40 | }; 41 | 42 | DYNAMIC_STRUCTURE_DECLARATIONS(Image_Loader_Requests, Image_Loader_Request); 43 | 44 | // we'll need to manage a set of images 45 | struct Image_Loader_Shot 46 | { 47 | bool set; 48 | 49 | // flag used to suggest that this shot might be potencially needed in the future 50 | bool suggested; 51 | 52 | // image meta 53 | const char * filename; 54 | int width, height; 55 | 56 | // full version 57 | IplImage * full; 58 | GLuint full_texture; 59 | int full_counter, full_unprocessed_counter; 60 | 61 | // low version 62 | IplImage * low; 63 | GLuint low_texture; 64 | int low_counter, low_unprocessed_counter; 65 | }; 66 | 67 | DYNAMIC_STRUCTURE_DECLARATIONS(Image_Loader_Shots, Image_Loader_Shot); 68 | 69 | // release unused image from memory (full resolution version) 70 | // global_lock must be locked 71 | // note we could use some more sophisticated releasing strategy 72 | // note that we could count requests on full and low versions separately 73 | void image_loader_free_full(); 74 | 75 | // release unused image from memory (low resolution version) 76 | // global_lock must be locked 77 | // note see the note to function above 78 | void image_loader_free_low(); 79 | 80 | // try to resolve request immediately 81 | // must be locked 82 | void image_loader_resolve_request(const size_t request_id); 83 | 84 | // thread function 85 | void * image_loader_thread_function(void * arg); 86 | 87 | // initialize image loader subsystem 88 | bool image_loader_initialize(const int cache_full_count, const int cache_low_count); 89 | bool image_loader_start_thread(); 90 | 91 | // release image loader subsystem 92 | // todo release also shots and requests 93 | void image_loader_release(); 94 | 95 | // creates new request to load shot image 96 | Image_Loader_Request_Handle image_loader_new_request( 97 | const size_t shot_id, 98 | const char * const filename, 99 | const Image_Loader_Quality quality, 100 | const Image_Loader_Content content = IMAGE_LOADER_ALL, 101 | const double x = -1, 102 | const double y = -1, 103 | const double sx = -1, 104 | const double sy = -1, 105 | const bool fake = false 106 | ); 107 | 108 | // check if the handle is nonempty 109 | bool image_loader_nonempty_handle(Image_Loader_Request_Handle handle); 110 | 111 | // cancel existing request 112 | void image_loader_cancel_request(Image_Loader_Request_Handle * handle); 113 | 114 | // determines if requested image is loaded into memory (at least low res version if we're ok with continuous loading) 115 | static bool image_loader_request_ready_nolock(Image_Loader_Request_Handle handle); 116 | 117 | // version of the above function for use outside of this lbrary 118 | bool image_loader_request_ready(Image_Loader_Request_Handle handle); 119 | 120 | // determines if the requested image is already waiting for us on gpu (checks for both low and full version of the texture) 121 | bool image_loader_opengl_upload_ready_dual( 122 | Image_Loader_Request_Handle handle, GLuint * full_texture, GLuint * low_texture, 123 | double * texture_min_x = NULL, double * texture_min_y = NULL, double * texture_max_x = NULL, double * texture_max_y = NULL 124 | ); 125 | 126 | // determined if the requested image is already on gpu 127 | bool image_loader_opengl_upload_ready( 128 | Image_Loader_Request_Handle handle, GLuint * texture, 129 | double * texture_min_x = NULL, double * texture_min_y = NULL, double * texture_max_x = NULL, double * texture_max_y = NULL 130 | ); 131 | 132 | // uploads texture to opengl 133 | // note if there are more requests for one image, it's cause multiple uploads to opengl 134 | void image_loader_upload_to_opengl(Image_Loader_Request_Handle handle); 135 | 136 | // get original dimensions of this request's image 137 | void image_loader_get_original_dimensions(Image_Loader_Request_Handle handle, int * width, int * height); 138 | 139 | // flush texture ids 140 | void image_loader_flush_texture_ids(); 141 | 142 | // clear all suggested flags 143 | void image_loaded_flush_suggested(); 144 | 145 | // cancel all requests 146 | void image_loader_cancel_all_requests(); 147 | 148 | #endif 149 | -------------------------------------------------------------------------------- /insight3d/geometry_textures.cpp: -------------------------------------------------------------------------------- 1 | #include "geometry_textures.h" 2 | 3 | // perform texture extraction of all vertices 4 | void geometry_extract_all_textures() 5 | { 6 | for ALL(polygons, i) 7 | { 8 | geometry_extract_texture(i); 9 | } 10 | } 11 | 12 | // extract texture for given polygon 13 | void geometry_extract_texture(const size_t polygon_id) 14 | { 15 | Polygon_3d * const polygon = polygons.data + polygon_id; 16 | 17 | // are there shots with all of it's vertices marked? 18 | size_t * count = ALLOC(size_t, shots.count); 19 | memset(count, 0, sizeof(size_t) * shots.count); 20 | size_t total_vertices = 0; 21 | 22 | for ALL(polygon->vertices, j) 23 | { 24 | const size_t vertex_id = polygon->vertices.data[j].value; 25 | total_vertices++; 26 | 27 | for ALL(vertices_incidence.data[vertex_id].shot_point_ids, k) 28 | { 29 | const size_t shot_id = vertices_incidence.data[vertex_id].shot_point_ids.data[k].primary; 30 | count[shot_id]++; 31 | } 32 | } 33 | 34 | // don't extract textures from degenerate polygons 35 | if (total_vertices < 3) return; 36 | 37 | // go through those shots 38 | size_t best_shot; 39 | double best_area = 0; 40 | bool best_shot_set = false; 41 | for ALL(shots, i) 42 | { 43 | if (count[i] == total_vertices) 44 | { 45 | // todo * check if it's not self-intersecting * 46 | // ... 47 | 48 | // * count the area * 49 | double area = 0; 50 | bool not_first = false; 51 | double prev_x, prev_y; 52 | for ALL(polygon->vertices, j) 53 | { 54 | const size_t vertex_id = polygon->vertices.data[j].value; 55 | 56 | // find this vertex on this shot 57 | bool found = false; 58 | size_t point_iter = 0; 59 | LAMBDA_FIND( 60 | vertices_incidence.data[vertex_id].shot_point_ids, 61 | point_iter, 62 | found, 63 | vertices_incidence.data[vertex_id].shot_point_ids.data[point_iter].primary == i 64 | ); 65 | 66 | ASSERT(found, "polygon's vertex not found on shot even though entire polygon should be visible"); 67 | 68 | // obtain the values 69 | const size_t point_id = vertices_incidence.data[vertex_id].shot_point_ids.data[point_iter].secondary; 70 | const double 71 | x = shots.data[i].points.data[point_id].x, 72 | y = shots.data[i].points.data[point_id].y; 73 | 74 | // area of non-intersecting polygon is computed easily 75 | if (not_first) 76 | { 77 | area += prev_x * y - x * prev_y; 78 | } 79 | else 80 | { 81 | not_first = true; 82 | } 83 | 84 | prev_x = x; 85 | prev_y = y; 86 | } 87 | 88 | // keep track of maximum 89 | if (best_area < area || !best_shot_set) 90 | { 91 | best_area = area; 92 | best_shot = i; 93 | best_shot_set = true; 94 | } 95 | } 96 | } 97 | 98 | // extract the texture from best view 99 | if (best_shot_set) 100 | { 101 | const size_t i = best_shot; 102 | 103 | ASSERT(count[i] == total_vertices, "the shot chosen for texture extraction doesn't have all polygon's vertices marked"); 104 | 105 | // calculate bounding box and texture coordinates 106 | double * texture_coords = ALLOC(double, 2 * total_vertices); 107 | size_t v = 0; 108 | double min_x = 1000, min_y = 1000, max_x = -1000, max_y = -1000; // todo dirty 109 | for ALL(polygon->vertices, j) 110 | { 111 | const size_t vertex_id = polygon->vertices.data[j].value; 112 | 113 | // find this vertex on this shot 114 | bool found = false; 115 | size_t point_iter = 0; 116 | LAMBDA_FIND( 117 | vertices_incidence.data[vertex_id].shot_point_ids, 118 | point_iter, 119 | found, 120 | vertices_incidence.data[vertex_id].shot_point_ids.data[point_iter].primary == i 121 | ); 122 | 123 | ASSERT(found, "polygon's vertex not found on shot even though entire polygon should be visible"); 124 | 125 | // obtain the values 126 | const size_t point_id = vertices_incidence.data[vertex_id].shot_point_ids.data[point_iter].secondary; 127 | const double 128 | x = shots.data[i].points.data[point_id].x, 129 | y = shots.data[i].points.data[point_id].y; 130 | 131 | // save the texturing coordinates 132 | texture_coords[2 * v + 0] = x; 133 | texture_coords[2 * v + 1] = y; 134 | 135 | // update the bounding box 136 | if (x < min_x) min_x = x; 137 | if (x > max_x) max_x = x; 138 | if (y < min_y) min_y = y; 139 | if (y > max_y) max_y = y; 140 | 141 | v++; 142 | } 143 | 144 | const double width = max_x - min_x, height = max_y - min_y; 145 | 146 | // eventually free previously allocated data 147 | if (image_loader_nonempty_handle(polygon->image_loader_request)) 148 | { 149 | image_loader_cancel_request(&polygon->image_loader_request); 150 | } 151 | 152 | if (polygon->texture_coords) 153 | { 154 | FREE(polygon->texture_coords); 155 | } 156 | 157 | // recalculate texture coordinates 158 | for (v = 0; v < total_vertices; v++) 159 | { 160 | texture_coords[2 * v + 0] = (texture_coords[2 * v + 0] - min_x) / width; 161 | texture_coords[2 * v + 1] = (texture_coords[2 * v + 1] - min_y) / height; 162 | } 163 | 164 | // send request for this image region and save texturing coordinates 165 | polygon->image_loader_request = image_loader_new_request(i, shots.data[i].image_filename, IMAGE_LOADER_CONTINUOUS_LOADING, IMAGE_LOADER_REGION, min_x, min_y, max_x, max_y); 166 | polygon->texture_coords = texture_coords; 167 | } 168 | 169 | FREE(count); 170 | } 171 | 172 | -------------------------------------------------------------------------------- /insight3d/tool_extrude.cpp: -------------------------------------------------------------------------------- 1 | #include "tool_extrude.h" 2 | 3 | // do extrusion on the ordered set of selected vertices 4 | bool tool_extrude_to_ground(double * ground, Selected_Items * selected_vertices, size_t group /*= 0*/) 5 | { 6 | /* 7 | 8 | Description 9 | =========== 10 | 11 | Go through all selected vertices and for each create shadow point lying 12 | on ground plane. Then create polygons forming the extrusion from ground 13 | to selected vertices. 14 | 15 | Specification 16 | ============= 17 | 18 | 1) Create dynamic array of indices. 19 | 2) Go through all vertices in selection list and for each one create new vertex, 20 | store its index in the dynamic array and position it on the closest point on 21 | the ground plane to the original vertex. 22 | 3) Go once again through all vertices and create polygons connecting 23 | neighbouring vertices and their shadow vertices. 24 | 4) Finally create polygon between the last and the first applicable vertex in the 25 | list of selected vertices. 26 | 27 | Notes 28 | ===== 29 | 30 | We might want to do extrusion on other set's than current selection list. This 31 | function should take a list of vertices as a parameter. 32 | 33 | */ 34 | 35 | // Check that ground plane has been reconstructed, otherwise we don't have anything to do. 36 | if (!ground) return false; 37 | 38 | // Create two dynamic arrays of indices, one for storing the set of vertices that are 39 | // being extruded and the other to store newly created copies (shadow vertices) of every 40 | // one of them. 41 | Indices original_vertices, shadow_vertices; 42 | DYN_INIT(original_vertices); 43 | DYN_INIT(shadow_vertices); 44 | 45 | // Go through all items in the selection list, 46 | for ALL(*selected_vertices, i) 47 | { 48 | const Selected_Item * selected_item = selected_vertices->data + i; 49 | 50 | // while skipping everything but vertices 51 | if (selected_item->item_type != GEOMETRY_VERTEX) continue; 52 | 53 | // that are reconstructed. 54 | ASSERT_IS_SET(vertices, selected_item->item_id); 55 | if (!vertices.data[selected_item->item_id].reconstructed) continue; 56 | 57 | // Take each of these vertices 58 | const Vertex * vertex = vertices.data + selected_item->item_id; 59 | 60 | // and create a new one - shadow vertex. 61 | size_t shadow_vertex_id; 62 | geometry_new_vertex(shadow_vertex_id); 63 | Vertex * const shadow_vertex = vertices.data + shadow_vertex_id; 64 | 65 | // Position it on the closest point on the ground plane to the original vertex. 66 | double nearest_point[3]; 67 | const double temp[3] = { vertex->x, vertex->y, vertex->z }; 68 | nearest_point_on_plane(ground, temp, nearest_point); 69 | shadow_vertex->x = nearest_point[0]; 70 | shadow_vertex->y = nearest_point[1]; 71 | shadow_vertex->z = nearest_point[2]; 72 | 73 | // Also mark it as reconstructed and set it's group. 74 | shadow_vertex->reconstructed = true; 75 | shadow_vertex->group = group; 76 | 77 | // Store index of each vertex in the first dynamic array, 78 | ADD(original_vertices); 79 | LAST(original_vertices).value = selected_item->item_id; 80 | 81 | // and index of it's 'shadow' counterpart in the other array. 82 | ADD(shadow_vertices); 83 | LAST(shadow_vertices).value = shadow_vertex_id; 84 | } 85 | 86 | // If there were less than 3 vertices, we can't perform the extrusion. 87 | if (original_vertices.count < 3) return false; 88 | 89 | // Go once again through the same set of original vertices. 90 | for ALL(original_vertices, i) 91 | { 92 | // Take each original vertex, 93 | const Index * original_vertex_index = original_vertices.data + i; 94 | 95 | // the one next to it 96 | const size_t j = (i + 1) % original_vertices.count; 97 | const Index * next_original_vertex_index = original_vertices.data + j; 98 | 99 | // and their shadow counterparts on ground. 100 | const Index * shadow_vertex_index = shadow_vertices.data + i; 101 | const Index * next_shadow_vertex_index = shadow_vertices.data + j; 102 | 103 | // (Check consistency.) 104 | ASSERT_IS_SET(shadow_vertices, j); 105 | ASSERT_IS_SET(original_vertices, j); 106 | ASSERT_IS_SET(shadow_vertices, j); 107 | ASSERT_IS_SET(vertices, original_vertex_index->value); 108 | ASSERT_IS_SET(vertices, next_original_vertex_index->value); 109 | ASSERT_IS_SET(vertices, shadow_vertex_index->value); 110 | ASSERT_IS_SET(vertices, next_shadow_vertex_index->value); 111 | ASSERT(vertices.data[original_vertex_index->value].reconstructed, "only reconstructed vertices should be here"); 112 | ASSERT(vertices.data[next_original_vertex_index->value].reconstructed, "only reconstructed vertices should be here"); 113 | ASSERT(vertices.data[shadow_vertex_index->value].reconstructed, "only reconstructed vertices should be here"); 114 | ASSERT(vertices.data[next_shadow_vertex_index->value].reconstructed, "only reconstructed vertices should be here"); 115 | 116 | // Finally make a polygon 117 | size_t polygon_id; 118 | geometry_new_polygon(polygon_id); 119 | 120 | // connecting neighbouring vertices and their shadow vertices. 121 | geometry_polygon_add_vertex(polygon_id, original_vertex_index->value); 122 | geometry_polygon_add_vertex(polygon_id, next_original_vertex_index->value); 123 | geometry_polygon_add_vertex(polygon_id, next_shadow_vertex_index->value); 124 | geometry_polygon_add_vertex(polygon_id, shadow_vertex_index->value); 125 | } 126 | 127 | return true; 128 | } 129 | -------------------------------------------------------------------------------- /insight3d/tool_edit.cpp: -------------------------------------------------------------------------------- 1 | #include "tool_edit.h" 2 | 3 | // tool's state structure 4 | struct Tool_Edit 5 | { 6 | }; 7 | 8 | static Tool_Edit tool_edit; 9 | 10 | void tool_edit_overview_mode() 11 | { 12 | ui_state.mode = UI_MODE_OVERVIEW; 13 | } 14 | 15 | void tool_edit_inspection_mode() 16 | { 17 | ui_switch_to_inspection_mode(); 18 | } 19 | 20 | void tool_edit_shot_mode() 21 | { 22 | ui_switch_to_shot_mode(); 23 | } 24 | 25 | void tool_edit_select_points_on_current_shot() 26 | { 27 | if (INDEX_IS_SET(ui_state.current_shot)) 28 | { 29 | ui_empty_selection_list(); 30 | ui_select_points_on_shot(ui_state.current_shot); 31 | } 32 | } 33 | 34 | void tool_edit_reconstructed_points() 35 | { 36 | ui_empty_selection_list(); 37 | ui_select_points_with_reconstructed_vertices(); 38 | } 39 | 40 | void tool_edit_select_all_points() 41 | { 42 | ui_empty_selection_list(); 43 | ui_select_all_points(); 44 | } 45 | 46 | // select points corresponding to vertex which has at least one of it's corresponding points selected 47 | void tool_edit_all_corresponding_points() 48 | { 49 | for ALL(ui_state.selection_list, i) 50 | { 51 | const Selected_Item * const item = ui_state.selection_list.data + i; 52 | 53 | if (item->item_type == GEOMETRY_POINT) 54 | { 55 | ASSERT_IS_SET(shots, item->shot_id); 56 | ASSERT_IS_SET(shots.data[item->shot_id].points, item->item_id); 57 | 58 | // obtain vertex id 59 | const size_t vertex_id = shots.data[item->shot_id].points.data[item->item_id].vertex; 60 | ASSERT_IS_SET(vertices_incidence, vertex_id); 61 | 62 | // go through all points of this vertex and select the remaining unselected 63 | for ALL(vertices_incidence.data[vertex_id].shot_point_ids, j) 64 | { 65 | Double_Index * index = vertices_incidence.data[vertex_id].shot_point_ids.data + j; 66 | ASSERT_IS_SET(shots, index->primary); 67 | ASSERT_IS_SET(shots.data[index->primary].points, index->secondary); 68 | 69 | // if this point is unselected, select it 70 | if (!shots.data[index->primary].points.data[index->secondary].selected) 71 | { 72 | ui_add_point_to_selection(index->primary, index->secondary); 73 | } 74 | } 75 | } 76 | } 77 | } 78 | 79 | void tool_edit_deselect_all() 80 | { 81 | ui_empty_selection_list(); 82 | } 83 | 84 | void tool_edit_erase_selected_points() 85 | { 86 | // copy the indices of points 87 | size_t * ids = ALLOC(size_t, 2 * ui_state.selection_list.count); 88 | size_t count = 0; 89 | for ALL(ui_state.selection_list, i) 90 | { 91 | Selected_Item * item = ui_state.selection_list.data + i; 92 | if (item->item_type == GEOMETRY_POINT) 93 | { 94 | ids[2 * count + 0] = item->item_id; 95 | ids[2 * count + 1] = item->shot_id; 96 | count++; 97 | } 98 | } 99 | 100 | // prepare for deletition 101 | ui_prepare_for_deletition(true, true, true, false, false); 102 | 103 | // delete the points 104 | for (size_t i = 0; i < 2 * count; i += 2) 105 | { 106 | const size_t vertex_id = shots.data[ids[i + 1]].points.data[ids[i]].vertex; 107 | geometry_delete_point(ids[i + 1], ids[i]); 108 | 109 | // was this the last point of that vertex? 110 | bool last = true; 111 | for ALL(vertices_incidence.data[vertex_id].shot_point_ids, j) 112 | { 113 | last = false; 114 | break; 115 | } 116 | 117 | // if it was last, delete the vertex 118 | if (last) 119 | { 120 | geometry_delete_vertex(vertex_id); 121 | } 122 | } 123 | 124 | // release resources 125 | FREE(ids); 126 | } 127 | 128 | void tool_edit_erase_current_polygon() 129 | { 130 | if (!INDEX_IS_SET(ui_state.processed_polygon)) return; 131 | 132 | size_t id = ui_state.processed_polygon; 133 | ui_prepare_for_deletition(false, false, true, false, false); 134 | geometry_delete_polygon(id); 135 | } 136 | 137 | void tool_edit_erase_all_vertices_and_points() 138 | { 139 | ui_prepare_for_deletition(true, true, true, false, false); 140 | 141 | // delete all polygons 142 | DYN_FREE(polygons); 143 | 144 | // delete all points 145 | for ALL(shots, i) 146 | { 147 | Shot * const shot = shots.data + i; 148 | 149 | // erase all points 150 | DYN_FREE(shot->points); 151 | } 152 | 153 | // delete all vertices 154 | DYN_FREE(vertices); 155 | 156 | // delete the incidence structures 157 | for ALL(vertices_incidence, i) 158 | { 159 | DYN_FREE(vertices_incidence.data[i].shot_point_ids); 160 | } 161 | 162 | DYN_FREE(vertices_incidence); 163 | 164 | // go through all calibrations and release all triangulated points 165 | for ALL(calibrations, i) 166 | { 167 | Calibration * calibration = calibrations.data + i; 168 | DYN_FREE(calibration->Xs); 169 | } 170 | 171 | ui_list_update(); 172 | } 173 | 174 | void tool_edit_create() 175 | { 176 | tool_register_menu_function("Main menu|Edit|Mode...|Overview mode|", tool_edit_overview_mode); 177 | tool_register_menu_function("Main menu|Edit|Mode...|Inspection mode|", tool_edit_inspection_mode); 178 | tool_register_menu_function("Main menu|Edit|Mode...|Shot mode|", tool_edit_shot_mode); 179 | tool_register_menu_function("Main menu|Edit|Select...|Points on current shot|", tool_edit_select_points_on_current_shot); 180 | tool_register_menu_function("Main menu|Edit|Select...|Reconstructed points|", tool_edit_reconstructed_points); 181 | tool_register_menu_function("Main menu|Edit|Select...|Add corresponding points|", tool_edit_all_corresponding_points); 182 | tool_register_menu_function("Main menu|Edit|Select...|All points|", tool_edit_select_all_points); 183 | tool_register_menu_function("Main menu|Edit|Deselect all|", tool_edit_deselect_all); 184 | tool_register_menu_function("Main menu|Edit|Erase selected points|", tool_edit_erase_selected_points); 185 | tool_register_menu_function("Main menu|Edit|Erase current polygon|", tool_edit_erase_current_polygon); 186 | tool_register_menu_function("Main menu|Edit|Erase...|All vertices and points|", tool_edit_erase_all_vertices_and_points); 187 | } 188 | -------------------------------------------------------------------------------- /insight3d/geometry_routines.cpp: -------------------------------------------------------------------------------- 1 | #include "geometry_routines.h" 2 | 3 | // decompose projective matrix into rotation, translation and internal calibration matrix 4 | // note check this 5 | // obtains LOCK_RW(opencv) 6 | bool geometry_calibration_from_P(const size_t shot_id) 7 | { 8 | ASSERT(validate_shot(shot_id), "invalid shot suppiled when decomposing P"); 9 | Shot * const shot = shots.data + shot_id; 10 | ASSERT(shot->projection, "projection matrix not allocated"); 11 | 12 | if (shot->calibrated) 13 | { 14 | ASSERT(shot->rotation, "rotation matrix not allocated"); 15 | ASSERT(shot->translation, "translation vector allocated"); 16 | ASSERT(shot->internal_calibration, "internal calibration matrix not allocated"); 17 | } 18 | else 19 | { 20 | ASSERT(!shot->rotation, "rotation matrix allocated on uncalibrated shot" ); 21 | ASSERT(!shot->translation, "translation vector allocated on uncalibrated shot" ); 22 | ASSERT(!shot->internal_calibration, "internal calibration matrix allocated on uncalibrated shot" ); 23 | 24 | shot->rotation = opencv_create_matrix(3, 3); 25 | shot->translation = opencv_create_matrix(4, 1); 26 | shot->internal_calibration = opencv_create_matrix(3, 3); 27 | } 28 | 29 | LOCK_RW(opencv) 30 | { 31 | // decompose projection matrix 32 | const bool finite = mvg_finite_projection_matrix_decomposition( 33 | shot->projection, 34 | shot->internal_calibration, 35 | shot->rotation, 36 | shot->translation 37 | ); 38 | 39 | // we'll yet have to create a routine for decomposition of cameras at infinity 40 | if (!finite) 41 | { 42 | // if it wasn't calibrated before, deallocated newly calibrated matrices 43 | if (!shot->calibrated) 44 | { 45 | cvReleaseMat(&shot->rotation); 46 | cvReleaseMat(&shot->translation); 47 | cvReleaseMat(&shot->internal_calibration); 48 | } 49 | 50 | UNLOCK_RW(opencv); 51 | return false; 52 | } 53 | 54 | // * we have everything decomposed, now just recalculate helper vectors * 55 | 56 | // decompose rotation matrix into euler angles for OpenGL 57 | opencv_rotation_matrix_to_angles(shot->rotation, shot->R_euler[0], shot->R_euler[1], shot->R_euler[2]); 58 | shot->R_euler[0] = -(shot->R_euler[0] + OPENCV_PI); 59 | if (shot->R_euler[0] > 2 * OPENCV_PI) shot->R_euler[0] -= 2 * OPENCV_PI; 60 | shot->R_euler[1] = -(shot->R_euler[1]); 61 | shot->R_euler[2] = -(shot->R_euler[2]); 62 | } 63 | UNLOCK_RW(opencv); 64 | 65 | // translation vector as C array 66 | shot->T[0] = OPENCV_ELEM(shot->translation, 0, 0); 67 | shot->T[1] = OPENCV_ELEM(shot->translation, 1, 0); 68 | shot->T[2] = OPENCV_ELEM(shot->translation, 2, 0); 69 | shot->T[3] = 1.0; 70 | 71 | // internal calibration holds principal points coordinates 72 | shot->pp_x = OPENCV_ELEM(shot->internal_calibration, 0, 2); 73 | shot->pp_y = OPENCV_ELEM(shot->internal_calibration, 1, 2); 74 | 75 | return true; 76 | } 77 | 78 | // assemble projective matrix from rotation, translation and internal calibration matrix 79 | // obtains LOCK_RW(opencv) 80 | void geometry_calibration_from_decomposed_matrices(const size_t shot_id) 81 | { 82 | LOCK_RW(opencv) 83 | { 84 | // todo add checking for allocated P... we probably want to be consistent with the previous function 85 | ASSERT(validate_shot(shot_id), "assembling projection matrix for invalid shot"); 86 | Shot * const shot = shots.data + shot_id; 87 | 88 | shot->projection = opencv_create_matrix(3, 4); 89 | mvg_assemble_projection_matrix(shot->internal_calibration, shot->rotation, shot->translation, shot->projection); 90 | 91 | // * we have everything assembled, now just recalculate helper vectors * 92 | 93 | // decompose rotation matrix into euler angles for OpenGL 94 | opencv_rotation_matrix_to_angles(shot->rotation, shot->R_euler[0], shot->R_euler[1], shot->R_euler[2]); 95 | shot->R_euler[0] = -(shot->R_euler[0] + OPENCV_PI); 96 | if (shot->R_euler[0] > 2 * OPENCV_PI) shot->R_euler[0] -= 2 * OPENCV_PI; 97 | shot->R_euler[1] = -(shot->R_euler[1]); 98 | shot->R_euler[2] = -(shot->R_euler[2]); 99 | 100 | // translation vector as C array 101 | shot->T[0] = OPENCV_ELEM(shot->translation, 0, 0); 102 | shot->T[1] = OPENCV_ELEM(shot->translation, 1, 0); 103 | shot->T[2] = OPENCV_ELEM(shot->translation, 2, 0); 104 | shot->T[3] = 1.0; 105 | 106 | // internal calibration holds principal points coordinates 107 | shot->pp_x = OPENCV_ELEM(shot->internal_calibration, 0, 2); 108 | shot->pp_y = OPENCV_ELEM(shot->internal_calibration, 1, 2); 109 | } 110 | UNLOCK_RW(opencv); 111 | } 112 | 113 | // lattice test 114 | // todo check for points out of picture 115 | bool geometry_lattice_test(const size_t shot_id) 116 | { 117 | ASSERT(validate_shot(shot_id), "invalid shot supplied for lattice test"); 118 | 119 | // clear lattice array 120 | const int lattice_no = 4; 121 | const int lattice_no_sq = 16; 122 | int lattice_count[lattice_no_sq]; 123 | memset(lattice_count, 0, sizeof(int) * lattice_no_sq); 124 | 125 | // go through all points on this image 126 | for ALL(shots.data[shot_id].points, i) 127 | { 128 | const Shot * const shot = shots.data + shot_id; 129 | const Point * const point = shot->points.data + i; 130 | 131 | ASSERT(validate_vertex(point->vertex), "invalid vertex when checking for lattice test"); 132 | const Vertex * const vertex = vertices.data + point->vertex; 133 | 134 | // count reconstructed vertices 135 | if (vertex->reconstructed) 136 | { 137 | const int 138 | lattice_x = (int)(point->x * lattice_no), 139 | lattice_y = (int)(point->y * lattice_no); 140 | 141 | lattice_count[lattice_y * lattice_no + lattice_x]++; 142 | } 143 | } 144 | 145 | // count parts of lattice with nonzero number of vertices 146 | int ok = 0; 147 | for (int i = 0; i < lattice_no_sq; i++) 148 | { 149 | if (lattice_count[i] >= 1) 150 | { 151 | ok++; 152 | } 153 | } 154 | 155 | // todo remove 156 | printf("%d ", ok); 157 | 158 | return ok >= 6; 159 | } 160 | -------------------------------------------------------------------------------- /insight3d/ui_shot_mode.cpp: -------------------------------------------------------------------------------- 1 | #include "ui_shot_mode.h" 2 | 3 | // mode switching 4 | void ui_switch_to_shot_mode() 5 | { 6 | // if current shot isn't set, we'll pick the first one 7 | // todo switch to the nearest camera (or better to a camera with a similar view, seeing similar set of features, etc) 8 | if (!INDEX_IS_SET(ui_state.current_shot)) 9 | { 10 | const size_t first_shot = dyn_first(shots); 11 | 12 | if (dyn_found(first_shot)) 13 | { 14 | INDEX_SET(ui_state.current_shot, first_shot); 15 | } 16 | } 17 | 18 | // finally change the mode 19 | ui_state.mode = UI_MODE_SHOT; 20 | } 21 | 22 | // process mouse click events in shot mode 23 | void ui_shot_mouse_click() 24 | { 25 | } 26 | 27 | // respond to selection box in shot mode 28 | void ui_shot_mouse_selection() 29 | { 30 | // if no shot is currently displayed, we don't have anything to do 31 | if (!validate_shot(ui_state.current_shot)) return; 32 | 33 | // obtain coordinates 34 | double x1, y1, x2, y2; 35 | x1 = ui_state.mouse_down_x; 36 | y1 = ui_state.mouse_down_y; 37 | x2 = ui_state.mouse_x; 38 | y2 = ui_state.mouse_y; 39 | if (x1 > x2) swap_double(x1, x2); 40 | if (y1 > y2) swap_double(y1, y2); 41 | 42 | // selection box modifiers 43 | Selection_Type operation = SELECTION_TYPE_REPLACEMENT; 44 | 45 | if (ui_state.keys[SDLK_LSHIFT] || ui_state.keys[SDLK_RSHIFT]) 46 | { 47 | operation = SELECTION_TYPE_UNION; 48 | } 49 | else if (ui_state.keys[SDLK_LCTRL] || ui_state.keys[SDLK_RCTRL]) 50 | { 51 | operation = SELECTION_TYPE_INTERSECTION; 52 | } 53 | 54 | // empty selection list 55 | if (operation == SELECTION_TYPE_REPLACEMENT) 56 | { 57 | ui_empty_selection_list(); 58 | } 59 | 60 | // perform selection 61 | #ifdef LANG_CORRECTION 62 | ui_3d_selection_box(x1, y1, x2, y2, operation); 63 | #else 64 | ui_2d_selection_box(x1, y1, x2, y2, operation); 65 | #endif 66 | } 67 | 68 | // switch current shot (when the user works in shot mode and decides to switch to another image/camera) 69 | bool ui_switch_shot(size_t shot_id) 70 | { 71 | // first check this shot actually exists 72 | if (!validate_shot(shot_id)) return false; 73 | 74 | // switch to it 75 | ui_state.current_shot = shot_id; 76 | 77 | return true; 78 | } 79 | 80 | // process user input (in shot mode) 81 | void ui_update_shot(const Uint32 delta_time) 82 | { 83 | // shift changes behavior of cursor keys (translation vs. rotation) 84 | if (!ui_state.keys[SDLK_LSHIFT] && !ui_state.keys[SDLK_RSHIFT]) 85 | { 86 | // * deleting selected points * 87 | if (ui_state.keys[SDLK_DELETE]) 88 | { 89 | // ui_delete_selected_points(); 90 | } 91 | 92 | // * switching shots * 93 | 94 | // find the shot wanted by the user 95 | // size_t shot_id = 0; 96 | // bool exists = false; 97 | 98 | // if it exists, switch to it 99 | // if (exists) ui_switch_shot(shot_id); 100 | } 101 | } 102 | 103 | // displays small thumbnails of areas around currently selected/created vertex 104 | // note unused 105 | /*void ui_shot_thumbs() 106 | { 107 | // * we're going to display helpers only for the first selected point * 108 | 109 | // obtain vertex id 110 | size_t vertex_id = 0; 111 | bool vertex_found = false; 112 | 113 | if (INDEX_IS_SET(ui_state.processed_polygon)) 114 | { 115 | const size_t polygon_id = ui_state.processed_polygon; 116 | 117 | // todo obsolete code, use LAMBDA_FIND 118 | for ALL(polygons.data[polygon_id].vertices, i) 119 | { 120 | const size_t polygons_vertex_id = polygons.data[polygon_id].vertices.data[i].value; 121 | 122 | // check if this vertex is localised on this shot 123 | size_t point_id; 124 | if (!query_find_point_on_shot_by_vertex_id(ui_state.current_shot, polygons_vertex_id, point_id)) 125 | { 126 | // this vertex is not marked on current shot yet 127 | vertex_found = true; 128 | vertex_id = polygons_vertex_id; 129 | break; 130 | } 131 | } 132 | } 133 | else 134 | { 135 | for ALL(ui_state.selection_list, i) 136 | { 137 | if (ui_state.selection_list.data[i].item_type == GEOMETRY_POINT) 138 | { 139 | // obtain ids 140 | size_t point_id = ui_state.selection_list.data[i].item_id; 141 | size_t shot_id = ui_state.selection_list.data[i].shot_id; 142 | 143 | // consistency check 144 | ASSERT_IS_SET(shots, shot_id); 145 | ASSERT_IS_SET(shots.data[shot_id].points, point_id); 146 | 147 | // obtain vertex id 148 | vertex_id = shots.data[shot_id].points.data[point_id].vertex; 149 | vertex_found = true; 150 | break; 151 | } 152 | } 153 | } 154 | 155 | // if no point is selected, we don't have anything to show 156 | if (!vertex_found) return; 157 | 158 | // go through all shots on which this vertex was marked 159 | size_t j = 0; 160 | ASSERT_IS_SET(vertices_incidence, vertex_id); 161 | for ALL(vertices_incidence.data[vertex_id].shot_point_ids, i) 162 | { 163 | // for every occurence of this vertex on some shot, obtain shot's id 164 | const size_t shot_id = vertices_incidence.data[vertex_id].shot_point_ids.data[i].primary; 165 | const size_t point_id = vertices_incidence.data[vertex_id].shot_point_ids.data[i].secondary; 166 | ASSERT_IS_SET(shots, shot_id); 167 | ASSERT_IS_SET(shots.data[shot_id].points, point_id); 168 | const Shot * const shot = shots.data + shot_id; 169 | 170 | // we don't want to display thumbnail for current shot, since it's visible anyway 171 | if (shot_id == ui_state.current_shot) continue; 172 | 173 | // we won't display points located (for some strange reason) outside of image plane 174 | if (!inside_2d_interval(shot->points.data[point_id].x, shot->points.data[point_id].y, 0, 0, 1, 1)) continue; 175 | 176 | // we won't display points, which aren't credible 177 | if (shot->points.data[point_id].data_origin < 0) continue; // note this has to be thought about... 178 | 179 | // display thumbnail 180 | visualization_shot_thumb(j, true, shot_id, point_id, shot->points.data[point_id].x, shot->points.data[point_id].y, 0.04); 181 | 182 | if (++j >= 11) break; 183 | } 184 | }*/ 185 | -------------------------------------------------------------------------------- /insight3d/ui_visualization.h: -------------------------------------------------------------------------------- 1 | #ifndef __UI_VISUALIZATION 2 | #define __UI_VISUALIZATION 3 | 4 | #include "interface_opengl.h" 5 | #include "core_constants.h" 6 | #include "core_math_routines.h" 7 | #include "ui_constants.h" 8 | #include "ui_core.h" 9 | #include "geometry_structures.h" 10 | #include "geometry_queries.h" 11 | 12 | // visualization state value 13 | struct Visualization_State { 14 | 15 | // statistics 16 | double shots_T_mean[3], shots_T_deviation[3], max_dev; // mean and variance of the cameras' positions 17 | size_t finite_shots_count; 18 | 19 | // inspection mode 20 | double T[3]; // user camera position in space 21 | double R[3]; // user camera orientation (radians) 22 | double point_of_focus[3]; // position of the point on which user camera is focused 23 | 24 | // continuous image loading 25 | double continuous_loading_alpha; 26 | 27 | // inspection mode - orientation using ground plane 28 | bool ground_mode; // ground inspection is on/off 29 | double * ground; // homogeneous coordinates of ground plane (inhomogeneous part, i.e. first 3 values, 30 | // is always normalized and thus forms unit length normal vector of the plane) 31 | // note maybe check that it always points 'upwards' 32 | double ground_POI[3]; // point of interest 33 | double ground_axis_x[3], ground_axis_y[3], ground_axis_z[3]; // perpendicular unit vectors lying on ground plane and specifying 34 | // (together with plane's normal vector) coordinate frame 35 | double ground_alpha, ground_phi, ground_distance; // distance and angles used to orient in space while in ground plane inspection 36 | 37 | // opengl state variables 38 | GLdouble opengl_modelview[16], opengl_projection[16]; 39 | int opengl_viewport[4]; 40 | 41 | }; 42 | 43 | extern Visualization_State visualization_state; 44 | 45 | // initialize visualization 46 | bool visualization_initialize(); 47 | 48 | // save opengl transformation matrices into visualization state structure 49 | void visualization_export_opengl_matrices(); 50 | 51 | // prepare inspection projection 52 | void visualization_prepare_inspection_projection(double fovx); 53 | 54 | // calculate the view_zoom factor in x axis // todo write better description 55 | const double visualization_get_zoom_x(); 56 | 57 | // calculate the viewport coordinates on OpenGL clipping plane (using current zooming and scrolling settings) 58 | void visualization_viewport_in_shot_coordinates(double & x1, double & y1, double & x2, double & y2); 59 | 60 | // prepare drawing using perspective projection 61 | void visualization_prepare_projection(); 62 | 63 | // prepare drawing in image space 64 | void visualization_prepare_planar_drawing(); 65 | 66 | // end drawing in image space 67 | void visualization_end_planar_drawing(); 68 | 69 | // processes data so that they can be eventually nicely displayed (mean and deviance of camera centers, etc.) 70 | bool visualization_process_data_cameras(Shots shots); 71 | bool visualization_process_data_vertices(Vertices vertices); 72 | void visualization_process_data(Vertices vertices, Shots shots); 73 | 74 | // normalize coordinate 75 | double visualization_normalize(const double x, const Core_Axes axis); 76 | double visualization_normalize_linear(const double x, const Core_Axes axis); 77 | 78 | // denormalize coordiante 79 | double visualization_denormalize(const double x, const Core_Axes axis); 80 | 81 | // denormalize 3-vector 82 | void visualization_denormalize_vector(double * point); 83 | 84 | // calculate distance between two points in shot coordinates in screen pixels 85 | // unused because query_nearest_point is flexible enough; might be useful someday though 86 | double visualization_screen_distance_sq(const double x1, const double y1, const double x2, const double y2); 87 | 88 | // find nearest point on shot 89 | double visualization_nearest_point(const size_t shot_id, const double x, const double y, size_t & point_id); 90 | 91 | // show selection box 92 | void visualization_selection_box(double x1, double y1, double x2, double y2); 93 | 94 | // displays camera centers as points in normalized space 95 | // conditions: visualization_process_data has to be run before the first time calling this function on modified (or newly constructed) data 96 | void visualization_cameras(const Shots shots, const double world_scale = 1); 97 | 98 | // display vertices using normalization from visualization_state 99 | void visualization_vertices(const Vertices & vertices, double world_scale = 1); 100 | 101 | // display reconstructed polygons 102 | void visualization_polygons(const Polygons_3d & polygons, const double world_scale = 1); 103 | 104 | // display 3d reconstruction contours (which are 2d shots' polygons) 105 | void visualization_contours(const Shots & shots, const Vertices & vertices, const double world_scale = 1); 106 | 107 | // place user camera (image plane mode) 108 | void visualization_shot_user_camera(const double world_scale = 1); 109 | 110 | // show shot 111 | void visualization_shot_image(Shot & shot); 112 | 113 | // show dualview 114 | void visualization_show_dualview(size_t current_shot_id, size_t dual_shot_id, const double x, const double y); 115 | 116 | // draw rectangle with shadow 117 | void visualization_rect_with_shadow(double left, double top, double right, double bottom, double texture_left, double texture_top, double texture_right, double texture_bottom, double alpha); 118 | 119 | // show polygons in shot mode 120 | void visualization_shot_polygons(const size_t shot_id); 121 | 122 | // show all of the contours 123 | void visualization_shot_contours(const size_t shot_id); 124 | 125 | // place user camera (inspection mode) 126 | void visualization_inspection_user_camera(double world_scale = 1); 127 | 128 | // fit image to viewport 129 | void visualization_fit_to_viewport(); 130 | 131 | // move image into viewport - if the user scrolls zooms or scrolls out of image, we want to contrain him (that's what she said!) 132 | void visualization_move_into_viewport(bool x_axis = true, bool y_axis = true); 133 | 134 | #endif 135 | 136 | -------------------------------------------------------------------------------- /insight3d/actions.cpp: -------------------------------------------------------------------------------- 1 | #include "tool_core.h" 2 | #include "actions.h" 3 | 4 | // triangulates vertices given current projection matrices and vertex projections 5 | bool action_triangulate_vertices( 6 | bool * shots_to_use /*= NULL*/, 7 | const int min_inliers /*= MVG_MIN_INLIERS_TO_TRIANGULATE*/, 8 | const int min_inliers_weaker /*= MVG_MIN_INLIERS_TO_TRIANGULATE_WEAKER*/, 9 | const bool only_manual /*= false*/, 10 | const double measurement_threshold /*= MVG_MEASUREMENT_THRESHOLD*/ 11 | ) 12 | { 13 | // count vertices to reconstruct 14 | size_t vertex_count = 0; 15 | for ALL(vertices, i) 16 | { 17 | Vertex * vertex = vertices.data + i; 18 | 19 | if (only_manual && vertex->vertex_type != GEOMETRY_VERTEX_USER) continue; 20 | if (IS_SET(vertices_incidence, i)) 21 | { 22 | vertex_count++; 23 | } 24 | } 25 | 26 | // * reconstruct all vertices * 27 | 28 | // progressbar support 29 | tool_start_progressbar(); 30 | size_t vertex_counter = 0; 31 | 32 | // go through all vertices 33 | for ALL(vertices, i) 34 | { 35 | Vertex * vertex = vertices.data + i; 36 | CvMat * reconstructed_vertex = NULL; 37 | vertex_counter++; 38 | 39 | if (only_manual && vertex->vertex_type != GEOMETRY_VERTEX_USER) continue; 40 | 41 | // if incidence is defined (i.e., if the vertex has some 2d points) 42 | if (IS_SET(vertices_incidence, i)) 43 | { 44 | tool_show_progress(vertex_counter / (double)vertex_count); 45 | 46 | // feed the data inside appropriate matrices 47 | const CvMat * * projection_matrices; 48 | CvMat * points; 49 | 50 | // locking call 51 | bool publish_status = publish_triangulation_data(vertices_incidence.data[i], i, projection_matrices, points, shots_to_use); 52 | 53 | // call reconstruction algorithm 54 | if (publish_status) 55 | { 56 | LOCK_RW(opencv); 57 | { 58 | reconstructed_vertex = mvg_triangulation_RANSAC( 59 | projection_matrices, points, true, false, 60 | min_inliers, 61 | min_inliers_weaker, 62 | MVG_RANSAC_TRIANGULATION_TRIALS, 63 | MVG_MEASUREMENT_THRESHOLD 64 | ); 65 | FREE(projection_matrices); 66 | cvReleaseMat(&points); 67 | } 68 | UNLOCK_RW(opencv); 69 | } 70 | } 71 | 72 | // if the reconstruction succeeded 73 | if (reconstructed_vertex) 74 | { 75 | if (reconstructed_vertex->rows == 4) 76 | { 77 | LOCK_RW(opencv) 78 | { 79 | opencv_normalize_homogeneous(reconstructed_vertex); 80 | } 81 | UNLOCK_RW(opencv); 82 | } 83 | 84 | // save calculated coordinates 85 | vertex->reconstructed = true; 86 | vertex->x = OPENCV_ELEM(reconstructed_vertex, 0, 0); 87 | vertex->y = OPENCV_ELEM(reconstructed_vertex, 1, 0); 88 | vertex->z = OPENCV_ELEM(reconstructed_vertex, 2, 0); 89 | } 90 | else 91 | { 92 | // mark as unreconstructed 93 | vertex->reconstructed = false; 94 | vertex->x = 0; 95 | vertex->y = 0; 96 | vertex->z = 0; 97 | } 98 | 99 | // release resources 100 | ATOMIC_RW(opencv, cvReleaseMat(&reconstructed_vertex); ); 101 | } 102 | 103 | tool_end_progressbar(); 104 | 105 | return true; 106 | } 107 | 108 | // compute projection matrix of current camera from 3d to 2d correspondences 109 | bool action_camera_resection(size_t shot_id, const bool enforce_square_pixels, const bool enforce_zero_skew) 110 | { 111 | ASSERT_IS_SET(shots, shot_id); 112 | Shot * const shot = shots.data + shot_id; 113 | 114 | // first count how many points on this shot have their vertices reconstructed 115 | size_t n = 0; 116 | for ALL(shots.data[shot_id].points, i) 117 | { 118 | const Point * const point = shots.data[shot_id].points.data + i; 119 | if (vertices.data[point->vertex].reconstructed) 120 | { 121 | n++; 122 | } 123 | } 124 | 125 | if (n < 6) 126 | { 127 | return false; 128 | } 129 | 130 | // go through all points on this shot and fill them and their vertices 131 | // into respective matrices 132 | ATOMIC_RW(opencv, 133 | CvMat * mat_vertices = cvCreateMat(3, n, CV_64F); 134 | CvMat * mat_projected = cvCreateMat(2, n, CV_64F); 135 | ); 136 | 137 | n = 0; 138 | for ALL(shots.data[shot_id].points, i) 139 | { 140 | const Point * const point = shots.data[shot_id].points.data + i; 141 | const Vertex * const vertex = vertices.data + point->vertex; 142 | if (!vertex->reconstructed) continue; 143 | 144 | // copy the values into matrices 145 | OPENCV_ELEM(mat_vertices, 0, n) = vertex->x; 146 | OPENCV_ELEM(mat_vertices, 1, n) = vertex->y; 147 | OPENCV_ELEM(mat_vertices, 2, n) = vertex->z; 148 | OPENCV_ELEM(mat_projected, 0, n) = point->x * shots.data[shot_id].width; 149 | OPENCV_ELEM(mat_projected, 1, n) = point->y * shots.data[shot_id].height; 150 | n++; 151 | } 152 | 153 | // perform the calculation 154 | bool ok; 155 | ATOMIC_RW(opencv, 156 | CvMat * R = opencv_create_matrix(3, 3); 157 | CvMat * K = opencv_create_matrix(3, 3); 158 | CvMat * T = opencv_create_matrix(3, 1); 159 | CvMat * P = opencv_create_matrix(3, 4); 160 | 161 | ok = mvg_resection_RANSAC(mat_vertices, mat_projected, P, K, R, T, false); 162 | ); 163 | 164 | // check result and optionally enforce some constraints 165 | if (ok) 166 | { 167 | LOCK_RW(opencv) 168 | { 169 | // enforce restrictions on calibration matrix 170 | if (!mvg_restrict_calibration_matrix(K, enforce_zero_skew, enforce_square_pixels)) 171 | { 172 | cvReleaseMat(&R); 173 | cvReleaseMat(&K); 174 | cvReleaseMat(&T); 175 | cvReleaseMat(&P); 176 | cvReleaseMat(&mat_vertices); 177 | cvReleaseMat(&mat_projected); 178 | UNLOCK_RW(opencv); 179 | return false; 180 | } 181 | 182 | // if it has been calibrated before, release previous calibration 183 | if (shot->calibrated) 184 | { 185 | cvReleaseMat(&shot->projection); 186 | cvReleaseMat(&shot->rotation); 187 | cvReleaseMat(&shot->translation); 188 | cvReleaseMat(&shot->internal_calibration); 189 | } 190 | 191 | // save estimated matrices into shot structure 192 | shot->projection = P; 193 | shot->rotation = R; 194 | shot->translation = T; 195 | shot->internal_calibration = K; 196 | 197 | // fill in the rest of the calibration 198 | geometry_calibration_from_decomposed_matrices(shot_id); 199 | 200 | // mark as calibrated 201 | shot->calibrated = true; 202 | } 203 | UNLOCK_RW(opencv); 204 | } 205 | 206 | // release resources 207 | LOCK_RW(opencv) 208 | { 209 | cvReleaseMat(&mat_vertices); 210 | cvReleaseMat(&mat_projected); 211 | } 212 | UNLOCK_RW(opencv); 213 | 214 | return ok; 215 | } 216 | -------------------------------------------------------------------------------- /insight3d/tool_file.cpp: -------------------------------------------------------------------------------- 1 | #include "tool_file.h" 2 | 3 | // tool's state structure 4 | struct Tool_File 5 | { 6 | }; 7 | 8 | static Tool_File tool_file; 9 | 10 | void tool_file_new() 11 | { 12 | ui_prepare_for_deletition(true, true, true, true, true); 13 | image_loader_cancel_all_requests(); 14 | 15 | for ALL(shots, i) 16 | { 17 | memset(&shots.data[i].image_loader_request, 0, sizeof(Image_Loader_Request)); 18 | } 19 | 20 | geometry_release(); 21 | ui_list_update(); 22 | ui_workflow_default_shot(); 23 | } 24 | 25 | void tool_file_open_project() 26 | { 27 | char * const filename = tool_choose_file(); 28 | 29 | // if no file has been selected, there's nothing to do 30 | if (!filename) return; 31 | 32 | // detete everything 33 | ui_prepare_for_deletition(true, true, true, true, true); 34 | image_loader_cancel_all_requests(); 35 | 36 | for ALL(shots, i) 37 | { 38 | memset(&shots.data[i].image_loader_request, 0, sizeof(Image_Loader_Request)); 39 | } 40 | 41 | geometry_release(); 42 | ui_list_update(); 43 | ui_workflow_default_shot(); 44 | 45 | // load something new 46 | geometry_load_project(filename); 47 | ui_list_update(); 48 | ui_workflow_default_shot(); 49 | visualization_process_data(vertices, shots); 50 | 51 | FREE(filename); 52 | } 53 | 54 | void tool_file_save_project() 55 | { 56 | char * filename = tool_choose_new_file(); 57 | if (!filename) return; 58 | 59 | geometry_save(filename); 60 | 61 | FREE(filename); 62 | } 63 | 64 | void tool_file_add_list_of_images() 65 | { 66 | char * filename = tool_choose_file(); 67 | if (!filename) return; 68 | 69 | geometry_loader_ifl(filename); 70 | ui_list_update(); 71 | ui_workflow_default_shot(); 72 | 73 | FREE(filename); 74 | } 75 | 76 | void tool_file_add_image() 77 | { 78 | char * filename = tool_choose_file(); 79 | if (!filename) return; 80 | 81 | geometry_loader_add_shot(filename); 82 | ui_list_update(); 83 | ui_workflow_default_shot(); 84 | 85 | FREE(filename); 86 | } 87 | 88 | void tool_file_import_realviz_project() 89 | { 90 | /* char * filename = tool_choose_file(); 91 | if (!filename) return; 92 | 93 | geometry_loader(filename, shots); 94 | visualization_process_data(vertices, shots); 95 | ui_list_update(); 96 | ui_workflow_default_shot(); 97 | visualization_process_data(vertices, shots); 98 | 99 | FREE(filename); */ 100 | } 101 | 102 | void tool_file_import_points() 103 | { 104 | char * filename = tool_choose_file(); 105 | if (!filename) return; 106 | 107 | bool success = geometry_loader_points_guess_filepair(filename); // {} 108 | ui_list_update(); 109 | 110 | FREE(filename); 111 | } 112 | 113 | void tool_file_import_pointcloud() 114 | { 115 | char * filename = tool_choose_file(); 116 | if (!filename) return; 117 | 118 | bool success = geometry_loader_vertices(filename, vertices); 119 | visualization_process_data(vertices, shots); 120 | 121 | FREE(filename); 122 | } 123 | 124 | void tool_file_export_vrml() 125 | { 126 | char * filename = tool_choose_new_file(); 127 | if (!filename) return; 128 | 129 | bool success = geometry_export_vrml(filename, vertices, polygons, !option_hide_automatic, true); // {} 130 | 131 | FREE(filename); 132 | } 133 | 134 | void tool_file_export_sandy3d() 135 | { 136 | char * filename = tool_choose_new_file(); 137 | if (!filename) return; 138 | 139 | bool success = geometry_export_sandy3d(filename, vertices, polygons, !option_hide_automatic); // {} 140 | 141 | FREE(filename); 142 | } 143 | 144 | void tool_file_export_realviz_project() 145 | { 146 | char * filename = tool_choose_new_file(); 147 | if (!filename) return; 148 | 149 | bool success = geometry_export_rzml(filename, shots); // {} 150 | 151 | FREE(filename); 152 | } 153 | 154 | void tool_file_export_pointcloud() 155 | { 156 | char * filename = tool_choose_new_file(); 157 | if (!filename) return; 158 | 159 | FILE * fp = fopen(filename, "w"); 160 | // fprintf(fp, "# insight3d vertices export; line format = x y z nx ny nz r g b"); 161 | 162 | for ALL(vertices, i) 163 | { 164 | const Vertex * vertex = vertices.data + i; 165 | if (!vertex->reconstructed) continue; 166 | 167 | fprintf( 168 | fp, 169 | "%lf %lf %lf %lf %lf %lf %lf %lf %lf\n", 170 | vertex->x, vertex->y, vertex->z, 171 | vertex->nx, vertex->ny, vertex->nz, 172 | vertex->color[0], vertex->color[1], vertex->color[2] 173 | ); 174 | } 175 | 176 | fclose(fp); 177 | 178 | FREE(filename); 179 | } 180 | 181 | void tool_file_export_cameras() 182 | { 183 | char * filename = tool_choose_new_file(); 184 | if (!filename) return; 185 | 186 | 187 | FILE * fp = fopen(filename, "w"); 188 | // fprintf(fp, "# insight3d camera export; line format = x y z nx ny nz r g b"); 189 | 190 | for ALL(shots, i) 191 | { 192 | const Shot * shot = shots.data + i; 193 | if (!shot->projection) continue; 194 | const CvMat * P = shot->projection; 195 | 196 | // print projection matrix 197 | for (int i = 0; i < P->rows; i++) 198 | { 199 | for (int j = 0; j < P->cols; j++) 200 | { 201 | fprintf(fp, "%lf ", OPENCV_ELEM(P, i, j)); 202 | } 203 | } 204 | fprintf(fp, "\n"); 205 | } 206 | 207 | fclose(fp); 208 | 209 | FREE(filename); 210 | } 211 | 212 | void tool_file_quit() 213 | { 214 | core_state.running = false; 215 | } 216 | 217 | void tool_file_create() 218 | { 219 | tool_register_menu_function("Main menu|File|New|", tool_file_new); 220 | tool_register_menu_function("Main menu|File|Open project (.i3d)|", tool_file_open_project); 221 | tool_register_menu_function("Main menu|File|Save project (.i3d)|", tool_file_save_project); 222 | tool_register_menu_function("Main menu|File|Add list of images (.ifl)|", tool_file_add_list_of_images); 223 | tool_register_menu_function("Main menu|File|Add image (.jpg, .png)|", tool_file_add_image); 224 | tool_register_menu_function("Main menu|File|Import RealVIZ project (.rzml, .rzi)|", tool_file_import_realviz_project); 225 | tool_register_menu_function("Main menu|File|Import points (file pair)|", tool_file_import_points); 226 | tool_register_menu_function("Main menu|File|Import pointcloud (.txt)|", tool_file_import_pointcloud); 227 | tool_register_menu_function("Main menu|File|Export VRML (.vrml)|", tool_file_export_vrml); 228 | tool_register_menu_function("Main menu|File|Export Sandy3D ActionScript (.as)|", tool_file_export_sandy3d); 229 | tool_register_menu_function("Main menu|File|Export RealVIZ project (.rzml, .rzi)|", tool_file_export_realviz_project); 230 | tool_register_menu_function("Main menu|File|Export cameras (.txt)|", tool_file_export_cameras); 231 | tool_register_menu_function("Main menu|File|Export pointcloud (.txt)|", tool_file_export_pointcloud); 232 | tool_register_menu_function("Main menu|File|Quit|", tool_file_quit); 233 | } 234 | -------------------------------------------------------------------------------- /insight3d/core_structures.h: -------------------------------------------------------------------------------- 1 | #ifndef __CORE_STRUCTURES 2 | #define __CORE_STRUCTURES 3 | 4 | #include 5 | #include "pthread.h" 6 | #include "core_debug.h" 7 | 8 | #ifndef SIZE_MAX 9 | #define SIZE_MAX ((size_t)-1) 10 | #endif 11 | 12 | // macros for smart(er) indexing variables 13 | #define INDEX_DECLARATION(indexing_variable) size_t indexing_variable; bool indexing_variable##_set 14 | #define INDEX_CLEAR(indexing_variable) (indexing_variable) = 0; (indexing_variable##_set) = false 15 | #define INDEX_SET(indexing_variable, value) (indexing_variable) = (value); (indexing_variable##_set) = true 16 | #define INDEX_IS_SET(indexing_variable) (indexing_variable##_set) 17 | #define INDEX_IS_SET_AND_VALID(indexing_variable, indexed_dyn_array) (INDEX_IS_SET(indexing_variable) && IS_SET(indexed_dyn_array, indexing_variable)) 18 | 19 | // accessing dynamically allocated array 20 | #define DYN_INIT(variable_name) (dyn_initialize(&(variable_name))) 21 | #define DYN_FREE(variable_name) (dyn_free(&(variable_name))) 22 | #define DYN(variable_name, index) (dyn(&(variable_name), (index))) 23 | #define ADD(variable_name) (DYN((variable_name), ((variable_name).count))) 24 | #define LAST(variable_name) ((variable_name).data[((variable_name).count) - 1]) 25 | #define LAST_INDEX(variable_name) (((variable_name).count) - 1) 26 | #define IS_SET(variable_name, index) (((index) < (variable_name).count) && (index >= 0) && ((variable_name).data[(index)].set)) 27 | #define ASSERT_IS_SET(variable_name, index) (IS_SET((variable_name), (index)) ? 0 : (printf("%s, %d: accessing undefined index %d in dynamic array", __FILE__, __LINE__, (index)), core_abort())) 28 | #define ALL(variable_name, iterator) (size_t (iterator) = 0; (iterator) < (variable_name).count; ++(iterator)) if ((variable_name).data[(iterator)].set) 29 | #define LAMBDA_FROM(variable_name, from, iterator, function) for ((iterator) = (from); (iterator) < (variable_name).count; ++(iterator)) if ((variable_name).data[(iterator)].set) { function } 30 | #define LAMBDA(variable, iterator, function) LAMBDA_FROM((variable), 0, (iterator), function) 31 | #define LAMBDA_FIND_FROM(variable, from, iterator, found, condition) \ 32 | (found) = false; \ 33 | LAMBDA_FROM((variable), (from), (iterator), if (condition) { found = true; break; }) \ 34 | if (!(found)) { (iterator) = SIZE_MAX; } 35 | #define LAMBDA_FIND(variable, iterator, found, condition) LAMBDA_FIND_FROM((variable), 0, (iterator), (found), (condition)) 36 | 37 | // simple routines 38 | bool dyn_found(const size_t index); 39 | 40 | // threading 41 | extern pthread_mutex_t print_mutex; 42 | 43 | #define ATOMIC_DEBUG_IN(resource) // pthread_mutex_lock(&print_mutex); printf("%s\t(%s:%d) ", #resource, __FILE__ + 30, __LINE__); pthread_mutex_unlock(&print_mutex); 44 | #define ATOMIC_DEBUG_OUT() // pthread_mutex_lock(&print_mutex); printf("[*]\n"); pthread_mutex_unlock(&print_mutex); 45 | #define LOCK_RW(resource) ATOMIC_DEBUG_IN(resource); pthread_mutex_lock(&(resource##_mutex)); ATOMIC_DEBUG_OUT(); 46 | #define LOCK_R(resource) ATOMIC_DEBUG_IN(resource); pthread_mutex_lock(&(resource##_mutex)); ATOMIC_DEBUG_OUT(); 47 | #define LOCK(resource) LOCK_RW(resource) 48 | #define UNLOCK_RW(resource) pthread_mutex_unlock(&(resource##_mutex)); 49 | #define UNLOCK_R(resource) pthread_mutex_unlock(&(resource##_mutex)); 50 | #define UNLOCK(resource) UNLOCK_RW(resource) 51 | #define UPGRADE_TO_RW(resource) 52 | #define WAS_UNLOCKED_RW(resource) 53 | #define WAS_UNLOCKED_R(resource) 54 | #define ATOMIC_RW(resource, code) LOCK_RW(resource); code; UNLOCK_RW(resource); 55 | #define ATOMIC_R(resource, code) LOCK_R(resource); code; UNLOCK_R(resource); 56 | #define ATOMIC(resource, code) ATOMIC_RW(resource, code) 57 | 58 | // template for safe dynamically allocated array (I for one welcome our new macro overlords...) 59 | #define DYNAMIC_STRUCTURE_DECLARATIONS(structure_name, structure_type) \ 60 | struct structure_name { \ 61 | size_t allocated, count; \ 62 | structure_type * data; \ 63 | }; \ 64 | \ 65 | void dyn_initialize(structure_name * dynamic_structure); \ 66 | void dyn_free(structure_name * dynamic_structure); \ 67 | structure_name * dyn(structure_name * dynamic_structure, size_t index); \ 68 | size_t dyn_next(const structure_name & dynamic_structure, const size_t from); \ 69 | size_t dyn_first(const structure_name & dynamic_structure); \ 70 | size_t * dyn_build_reindex(const structure_name & dynamic_structure); 71 | 72 | #define DYNAMIC_STRUCTURE(structure_name, structure_type) \ 73 | \ 74 | void dyn_initialize(structure_name * dynamic_structure) \ 75 | { \ 76 | dynamic_structure->allocated = 0; \ 77 | dynamic_structure->count = 0; \ 78 | dynamic_structure->data = NULL; \ 79 | } \ 80 | \ 81 | void dyn_free(structure_name * dynamic_structure) \ 82 | { \ 83 | if (dynamic_structure->data) free(dynamic_structure->data); \ 84 | dyn_initialize(dynamic_structure); \ 85 | } \ 86 | \ 87 | structure_name * dyn(structure_name * dynamic_structure, size_t index) \ 88 | { \ 89 | \ 90 | if (dynamic_structure->count <= index) dynamic_structure->count = index + 1; \ 91 | \ 92 | if (index < dynamic_structure->allocated) \ 93 | { \ 94 | if (!(dynamic_structure->data[index].set)) \ 95 | { \ 96 | memset(dynamic_structure->data + index, 0, sizeof(structure_type)); \ 97 | } \ 98 | dynamic_structure->data[index].set = true; \ 99 | return dynamic_structure; \ 100 | } \ 101 | else \ 102 | { \ 103 | size_t previously_allocated = dynamic_structure->allocated; \ 104 | \ 105 | if (dynamic_structure->allocated > 0) \ 106 | { \ 107 | dynamic_structure->allocated += dynamic_structure->allocated / 2; \ 108 | } \ 109 | else \ 110 | { \ 111 | dynamic_structure->allocated = 4; \ 112 | } \ 113 | \ 114 | structure_type * q; \ 115 | if (NULL == (q = (structure_type *)realloc(dynamic_structure->data, dynamic_structure->allocated * sizeof(structure_type)))) \ 116 | { \ 117 | dynamic_structure->allocated = 0; \ 118 | dynamic_structure->count = 0; \ 119 | dynamic_structure->data = NULL; \ 120 | return NULL; \ 121 | } \ 122 | else \ 123 | { \ 124 | dynamic_structure->data = q; \ 125 | memset(dynamic_structure->data + previously_allocated, 0, (dynamic_structure->allocated - previously_allocated) * sizeof(structure_type)); \ 126 | return dyn(dynamic_structure, index); \ 127 | } \ 128 | } \ 129 | }\ 130 | \ 131 | size_t dyn_next(const structure_name & dynamic_structure, const size_t from)\ 132 | {\ 133 | for (size_t i = from; i < dynamic_structure.count; ++i) if (dynamic_structure.data[i].set)\ 134 | {\ 135 | return i;\ 136 | }\ 137 | \ 138 | return SIZE_MAX;\ 139 | }\ 140 | \ 141 | size_t dyn_first(const structure_name & dynamic_structure)\ 142 | {\ 143 | return dyn_next(dynamic_structure, 0);\ 144 | }\ 145 | \ 146 | size_t * dyn_build_reindex(const structure_name & dynamic_structure)\ 147 | {\ 148 | size_t * reindex = (size_t *)malloc(sizeof(size_t) * dynamic_structure.count);\ 149 | memset(reindex, 0, sizeof(size_t) * dynamic_structure.count);\ 150 | size_t new_id = 0;\ 151 | for ALL(dynamic_structure, i)\ 152 | {\ 153 | reindex[i] = new_id++;\ 154 | }\ 155 | return reindex;\ 156 | }\ 157 | \ 158 | size_t * dyn_empty_index(const structure_name & dynamic_structure)\ 159 | {\ 160 | return (size_t *)malloc(sizeof(size_t) * dynamic_structure.count);\ 161 | }; 162 | 163 | #endif 164 | 165 | -------------------------------------------------------------------------------- /insight3d/cv_extensions.cpp: -------------------------------------------------------------------------------- 1 | #include "cv_extensions.h" 2 | #define CV_VERYSMALLDOUBLE 1.0e-10 3 | 4 | void cvComputeRQDecomposition(CvMat *matrixM, CvMat *matrixR, CvMat *matrixQ, CvMat *matrixQx, CvMat *matrixQy, CvMat *matrixQz, CvPoint3D64f *eulerAngles) 5 | { 6 | 7 | CvMat *tmpMatrix1 = 0; 8 | CvMat *tmpMatrix2 = 0; 9 | CvMat *tmpMatrixM = 0; 10 | CvMat *tmpMatrixR = 0; 11 | CvMat *tmpMatrixQ = 0; 12 | CvMat *tmpMatrixQx = 0; 13 | CvMat *tmpMatrixQy = 0; 14 | CvMat *tmpMatrixQz = 0; 15 | double tmpEulerAngleX, tmpEulerAngleY, tmpEulerAngleZ; 16 | 17 | CV_FUNCNAME("cvRQDecomp3x3"); 18 | __BEGIN__; 19 | 20 | /* Validate parameters. */ 21 | if(matrixM == 0 || matrixR == 0 || matrixQ == 0) 22 | CV_ERROR(CV_StsNullPtr, "Some of parameters is a NULL pointer!"); 23 | 24 | if(!CV_IS_MAT(matrixM) || !CV_IS_MAT(matrixR) || !CV_IS_MAT(matrixQ)) 25 | CV_ERROR(CV_StsUnsupportedFormat, "Input parameters must be a matrices!"); 26 | 27 | if(matrixM->cols != 3 || matrixM->rows != 3 || matrixR->cols != 3 || matrixR->rows != 3 || matrixQ->cols != 3 || matrixQ->rows != 3) 28 | CV_ERROR(CV_StsUnmatchedSizes, "Size of matrices must be 3x3!"); 29 | 30 | CV_CALL(tmpMatrix1 = cvCreateMat(3, 3, CV_64F)); 31 | CV_CALL(tmpMatrix2 = cvCreateMat(3, 3, CV_64F)); 32 | CV_CALL(tmpMatrixM = cvCreateMat(3, 3, CV_64F)); 33 | CV_CALL(tmpMatrixR = cvCreateMat(3, 3, CV_64F)); 34 | CV_CALL(tmpMatrixQ = cvCreateMat(3, 3, CV_64F)); 35 | CV_CALL(tmpMatrixQx = cvCreateMat(3, 3, CV_64F)); 36 | CV_CALL(tmpMatrixQy = cvCreateMat(3, 3, CV_64F)); 37 | CV_CALL(tmpMatrixQz = cvCreateMat(3, 3, CV_64F)); 38 | 39 | cvCopy(matrixM, tmpMatrixM); 40 | 41 | /* Find Givens rotation Q_x for x axis. */ 42 | /* 43 | ( 1 0 0 ) 44 | Qx = ( 0 c -s ), cos = -m33/sqrt(m32^2 + m33^2), cos = m32/sqrt(m32^2 + m33^2) 45 | ( 0 s c ) 46 | */ 47 | 48 | double x, y, z, c, s; 49 | x = cvmGet(tmpMatrixM, 2, 1); 50 | y = cvmGet(tmpMatrixM, 2, 2); 51 | z = x * x + y * y; 52 | assert(z != 0); // Prevent division by zero. 53 | c = -y / sqrt(z); 54 | s = x / sqrt(z); 55 | 56 | cvSetIdentity(tmpMatrixQx); 57 | cvmSet(tmpMatrixQx, 1, 1, c); 58 | cvmSet(tmpMatrixQx, 1, 2, -s); 59 | cvmSet(tmpMatrixQx, 2, 1, s); 60 | cvmSet(tmpMatrixQx, 2, 2, c); 61 | 62 | tmpEulerAngleX = acos(c) * 180.0 / CV_PI; 63 | 64 | /* Multiply M on the right by Q_x. */ 65 | 66 | cvMatMul(tmpMatrixM, tmpMatrixQx, tmpMatrixR); 67 | cvCopy(tmpMatrixR, tmpMatrixM); 68 | 69 | assert(cvmGet(tmpMatrixM, 2, 1) < CV_VERYSMALLDOUBLE && cvmGet(tmpMatrixM, 2, 1) > -CV_VERYSMALLDOUBLE); // Should actually be zero. 70 | 71 | if(cvmGet(tmpMatrixM, 2, 1) != 0.0) 72 | cvmSet(tmpMatrixM, 2, 1, 0.0); // Rectify arithmetic precision error. 73 | 74 | /* Find Givens rotation for y axis. */ 75 | /* 76 | ( c 0 s ) 77 | Qy = ( 0 1 0 ), cos = m33/sqrt(m31^2 + m33^2), cos = m31/sqrt(m31^2 + m33^2) 78 | (-s 0 c ) 79 | */ 80 | 81 | x = cvmGet(tmpMatrixM, 2, 0); 82 | y = cvmGet(tmpMatrixM, 2, 2); 83 | z = x * x + y * y; 84 | assert(z != 0); // Prevent division by zero. 85 | c = y / sqrt(z); 86 | s = x / sqrt(z); 87 | 88 | cvSetIdentity(tmpMatrixQy); 89 | cvmSet(tmpMatrixQy, 0, 0, c); 90 | cvmSet(tmpMatrixQy, 0, 2, s); 91 | cvmSet(tmpMatrixQy, 2, 0, -s); 92 | cvmSet(tmpMatrixQy, 2, 2, c); 93 | 94 | tmpEulerAngleY = acos(c) * 180.0 / CV_PI; 95 | 96 | /* Multiply M*Q_x on the right by Q_y. */ 97 | 98 | cvMatMul(tmpMatrixM, tmpMatrixQy, tmpMatrixR); 99 | cvCopy(tmpMatrixR, tmpMatrixM); 100 | 101 | assert(cvmGet(tmpMatrixM, 2, 0) < CV_VERYSMALLDOUBLE && cvmGet(tmpMatrixM, 2, 0) > -CV_VERYSMALLDOUBLE); // Should actually be zero. 102 | 103 | if(cvmGet(tmpMatrixM, 2, 0) != 0.0) 104 | cvmSet(tmpMatrixM, 2, 0, 0.0); // Rectify arithmetic precision error. 105 | 106 | /* Find Givens rotation for z axis. */ 107 | /* 108 | ( c -s 0 ) 109 | Qz = ( s c 0 ), cos = -m22/sqrt(m21^2 + m22^2), cos = m21/sqrt(m21^2 + m22^2) 110 | ( 0 0 1 ) 111 | */ 112 | 113 | x = cvmGet(tmpMatrixM, 1, 0); 114 | y = cvmGet(tmpMatrixM, 1, 1); 115 | z = x * x + y * y; 116 | assert(z != 0); // Prevent division by zero. 117 | c = -y / sqrt(z); 118 | s = x / sqrt(z); 119 | 120 | cvSetIdentity(tmpMatrixQz); 121 | cvmSet(tmpMatrixQz, 0, 0, c); 122 | cvmSet(tmpMatrixQz, 0, 1, -s); 123 | cvmSet(tmpMatrixQz, 1, 0, s); 124 | cvmSet(tmpMatrixQz, 1, 1, c); 125 | 126 | tmpEulerAngleZ = acos(c) * 180.0 / CV_PI; 127 | 128 | /* Multiply M*Q_x*Q_y on the right by Q_z. */ 129 | 130 | cvMatMul(tmpMatrixM, tmpMatrixQz, tmpMatrixR); 131 | 132 | assert(cvmGet(tmpMatrixR, 1, 0) < CV_VERYSMALLDOUBLE && cvmGet(tmpMatrixR, 1, 0) > -CV_VERYSMALLDOUBLE); // Should actually be zero. 133 | 134 | if(cvmGet(tmpMatrixR, 1, 0) != 0.0) 135 | cvmSet(tmpMatrixR, 1, 0, 0.0); // Rectify arithmetic precision error. 136 | 137 | /* Calulate orthogonal matrix. */ 138 | /* 139 | Q = QzT * QyT * QxT 140 | */ 141 | 142 | cvTranspose(tmpMatrixQz, tmpMatrix1); 143 | cvTranspose(tmpMatrixQy, tmpMatrix2); 144 | cvMatMul(tmpMatrix1, tmpMatrix2, tmpMatrixQ); 145 | cvCopy(tmpMatrixQ, tmpMatrix1); 146 | cvTranspose(tmpMatrixQx, tmpMatrix2); 147 | cvMatMul(tmpMatrix1, tmpMatrix2, tmpMatrixQ); 148 | 149 | /* Solve decomposition ambiguity. */ 150 | /* 151 | Diagonal entries of R should be positive, so swap signs if necessary. 152 | */ 153 | 154 | if(cvmGet(tmpMatrixR, 0, 0) < 0.0) { 155 | cvmSet(tmpMatrixR, 0, 0, -1.0 * cvmGet(tmpMatrixR, 0, 0)); 156 | cvmSet(tmpMatrixQ, 0, 0, -1.0 * cvmGet(tmpMatrixQ, 0, 0)); 157 | cvmSet(tmpMatrixQ, 0, 1, -1.0 * cvmGet(tmpMatrixQ, 0, 1)); 158 | cvmSet(tmpMatrixQ, 0, 2, -1.0 * cvmGet(tmpMatrixQ, 0, 2)); 159 | } 160 | if(cvmGet(tmpMatrixR, 1, 1) < 0.0) { 161 | cvmSet(tmpMatrixR, 0, 1, -1.0 * cvmGet(tmpMatrixR, 0, 1)); 162 | cvmSet(tmpMatrixR, 1, 1, -1.0 * cvmGet(tmpMatrixR, 1, 1)); 163 | cvmSet(tmpMatrixQ, 1, 0, -1.0 * cvmGet(tmpMatrixQ, 1, 0)); 164 | cvmSet(tmpMatrixQ, 1, 1, -1.0 * cvmGet(tmpMatrixQ, 1, 1)); 165 | cvmSet(tmpMatrixQ, 1, 2, -1.0 * cvmGet(tmpMatrixQ, 1, 2)); 166 | } 167 | 168 | /* Enforce det(Q) = 1 */ 169 | if (cvDet(tmpMatrixQ) < 0) 170 | { 171 | for (int i = 0; i < 3; i++) 172 | { 173 | for (int j = 0; j < 3; j++) 174 | { 175 | cvmSet(tmpMatrixQ, j, i, -cvmGet(tmpMatrixQ, j, i)); 176 | } 177 | } 178 | } 179 | 180 | /* Save R and Q matrices. */ 181 | 182 | cvCopy(tmpMatrixR, matrixR); 183 | cvCopy(tmpMatrixQ, matrixQ); 184 | 185 | if(matrixQx && CV_IS_MAT(matrixQx) && matrixQx->cols == 3 || matrixQx->rows == 3) 186 | cvCopy(tmpMatrixQx, matrixQx); 187 | if(matrixQy && CV_IS_MAT(matrixQy) && matrixQy->cols == 3 || matrixQy->rows == 3) 188 | cvCopy(tmpMatrixQy, matrixQy); 189 | if(matrixQz && CV_IS_MAT(matrixQz) && matrixQz->cols == 3 || matrixQz->rows == 3) 190 | cvCopy(tmpMatrixQz, matrixQz); 191 | 192 | /* Save Euler angles. */ 193 | 194 | if(eulerAngles) 195 | *eulerAngles = cvPoint3D64f(tmpEulerAngleX, tmpEulerAngleY, tmpEulerAngleZ); 196 | 197 | __END__; 198 | 199 | cvReleaseMat(&tmpMatrix1); 200 | cvReleaseMat(&tmpMatrix2); 201 | cvReleaseMat(&tmpMatrixM); 202 | cvReleaseMat(&tmpMatrixR); 203 | cvReleaseMat(&tmpMatrixQ); 204 | cvReleaseMat(&tmpMatrixQx); 205 | cvReleaseMat(&tmpMatrixQy); 206 | cvReleaseMat(&tmpMatrixQz); 207 | 208 | } 209 | -------------------------------------------------------------------------------- /insight3d/tool_image.cpp: -------------------------------------------------------------------------------- 1 | #include "tool_image.h" 2 | 3 | // generate textures 4 | void tool_image_generate_textures() 5 | { 6 | geometry_extract_all_textures(); 7 | } 8 | 9 | // colorize vertices 10 | void tool_image_colorize() 11 | { 12 | // allocate memory for accumulators 13 | int 14 | * accum_red = ALLOC(int, vertices.count), 15 | * accum_green = ALLOC(int, vertices.count), 16 | * accum_blue = ALLOC(int, vertices.count); 17 | int 18 | * count = ALLOC(int, vertices.count); 19 | 20 | memset(accum_red, 0, sizeof(int) * vertices.count); 21 | memset(accum_green, 0, sizeof(int) * vertices.count); 22 | memset(accum_blue, 0, sizeof(int) * vertices.count); 23 | memset(count, 0, sizeof(int) * vertices.count); 24 | 25 | // go through all photos 26 | int loaded_img_counter = 0; 27 | for ALL(shots, shot_id) 28 | { 29 | const Shot * const shot = shots.data + shot_id; 30 | 31 | // load the image 32 | IplImage * img = NULL; 33 | 34 | // take every point on this image 35 | for ALL(shot->points, point_id) 36 | { 37 | Point * point = shot->points.data + point_id; 38 | 39 | if (!img) 40 | { 41 | ATOMIC_RW(opencv, img = cvLoadImage(shot->image_filename); ); 42 | if (!img) continue; 43 | } 44 | 45 | const int 46 | x = (int)(point->x * img->width), 47 | y = (int)(point->y * img->height); 48 | 49 | accum_red[point->vertex] += ((uchar*)(img->imageData + img->widthStep*y))[x*3+2]; 50 | accum_green[point->vertex] += ((uchar*)(img->imageData + img->widthStep*y))[x*3+1]; 51 | accum_blue[point->vertex] += ((uchar*)(img->imageData + img->widthStep*y))[x*3+0]; 52 | count[point->vertex]++; 53 | } 54 | 55 | // release resources 56 | if (img) 57 | { 58 | printf("[%d]", loaded_img_counter); 59 | ATOMIC_RW(opencv, cvReleaseImage(&img); ); 60 | loaded_img_counter++; 61 | 62 | // debug 63 | // if (loaded_img_counter >= 200) break; 64 | } 65 | } 66 | 67 | // colorize vertices 68 | for ALL(vertices, vertex_id) 69 | { 70 | Vertex * const vertex = vertices.data + vertex_id; 71 | 72 | vertex->color[0] = accum_red[vertex_id] / ((float)count[vertex_id] * 255); 73 | vertex->color[1] = accum_green[vertex_id] / ((float)count[vertex_id] * 255); 74 | vertex->color[2] = accum_blue[vertex_id] / ((float)count[vertex_id] * 255); 75 | } 76 | 77 | printf("\n"); 78 | 79 | // release resources 80 | FREE(accum_red); 81 | FREE(accum_green); 82 | FREE(accum_blue); 83 | FREE(count); 84 | 85 | /*// take each vertex 86 | for ALL(vertices, i) 87 | { 88 | ASSERT_IS_SET(vertices_incidence, i); 89 | 90 | unsigned int accum_red = 0, accum_green = 0, accum_blue = 0; 91 | unsigned int count = 0; 92 | 93 | // go through all shots where this vertex is marked 94 | for ALL(vertices_incidence.data[i].shot_point_ids, j) 95 | { 96 | const Double_Index * index = vertices_incidence.data[i].shot_point_ids.data + j; 97 | 98 | // what is the color of this point 99 | ASSERT(validate_shot 100 | IplImage * img = shots.data[ 101 | accum_blue += ((uchar*)(img->imageData + img->widthStep*pt.y))[pt.x*3+0]; 102 | accum_green += ((uchar*)(img->imageData + img->widthStep*pt.y))[pt.x*3+1]; 103 | accum_red += ((uchar*)(img->imageData + img->widthStep*pt.y))[pt.x*3+2]; 104 | 105 | count++; 106 | } 107 | 108 | // calculate the color 109 | vertices.data[i].color[0] = accum_red / (float)count; 110 | vertices.data[i].color[1] = accum_green / (float)count; 111 | vertices.data[i].color[2] = accum_blue / (float)count; 112 | }*/ 113 | } 114 | 115 | // deform image so that the calibrated cameras all have the same internal calibration 116 | void tool_image_pinhole_deform() 117 | { 118 | if (!INDEX_IS_SET(ui_state.current_shot)) return; 119 | 120 | // take the camera calibration of the first calibrated camera 121 | size_t first_calibrated = 0; 122 | bool found = false; 123 | LAMBDA_FIND( 124 | shots, 125 | first_calibrated, 126 | found, 127 | shots.data[first_calibrated].calibrated && first_calibrated == 0 /*!shots.data[first_calibrated].resected*/ 128 | ); 129 | if (!found) return; 130 | const Shot * const first_shot = shots.data + first_calibrated; 131 | 132 | LOCK_RW(opencv) 133 | { 134 | for ALL(shots, i) 135 | { 136 | Shot * const shot = shots.data + i; 137 | 138 | // we only care about calibrated cameras 139 | if (shot->calibrated && /*shot->resected // note temporary */ i > 0) 140 | { 141 | // compute homography 142 | CvMat * H = cvCreateMat(3, 3, CV_64F), * K_inv = cvCreateMat(3, 3, CV_64F); 143 | cvInvert(shot->internal_calibration, K_inv); 144 | cvMatMul(first_shot->internal_calibration, K_inv, H); 145 | 146 | CvMat * A = cvCreateMat(3, 3, CV_64F); 147 | cvMatMul(H, shot->internal_calibration, A); 148 | 149 | // replace this K with the one from first shot 150 | cvCopy(first_shot->internal_calibration, shot->internal_calibration); 151 | shot->fovx = first_shot->fovx; 152 | shot->film_back = first_shot->film_back; 153 | shot->pp_x = first_shot->pp_x; 154 | shot->pp_y = first_shot->pp_y; 155 | shot->f = first_shot->f; 156 | UNLOCK_RW(opencv) 157 | { 158 | geometry_calibration_from_decomposed_matrices(i); 159 | } 160 | LOCK_RW(opencv); 161 | 162 | // perform the deformation 163 | IplImage * full_image = NULL; 164 | int cnter = 0; 165 | while (!full_image) 166 | { 167 | full_image = cvLoadImage(shot->image_filename); 168 | cnter++; 169 | if (cnter > 10) break; 170 | } 171 | 172 | if (cnter < 10) 173 | { 174 | IplImage * deformed = cvCreateImage(cvSize(full_image->width, full_image->height), full_image->depth, full_image->nChannels); 175 | for (int y = 0; y < deformed->height; y++) 176 | { 177 | for (int x = 0; x < deformed->width; x++) 178 | { 179 | ((uchar*)(deformed->imageData + deformed->widthStep*y))[x*3] = 0; 180 | ((uchar*)(deformed->imageData + deformed->widthStep*y))[x*3+1] = 255; 181 | ((uchar*)(deformed->imageData + deformed->widthStep*y))[x*3+2] = 0; 182 | } 183 | } 184 | cvWarpPerspective(full_image, deformed, H); 185 | printf("deforming %s ... ", shot->image_filename); 186 | 187 | cvSaveImage(shot->image_filename, deformed); 188 | printf("done\n"); 189 | 190 | std::ofstream H_out((std::string(shot->image_filename) + ".H.txt").c_str()); 191 | for (int i = 0; i < 3; i++) 192 | { 193 | for (int j = 0; j < 3; j++) 194 | { 195 | H_out << OPENCV_ELEM(H, i, j) << " "; 196 | } 197 | H_out << std::endl; 198 | } 199 | H_out.close(); 200 | 201 | // update internal calibration matrix 202 | cvCopy(first_shot->internal_calibration, shot->internal_calibration); 203 | 204 | cvReleaseImage(&deformed); 205 | } 206 | 207 | // release data 208 | cvReleaseMat(&H); 209 | cvReleaseMat(&K_inv); 210 | cvReleaseImage(&full_image); 211 | } 212 | } 213 | } 214 | UNLOCK_RW(opencv); 215 | } 216 | 217 | // register tool 218 | void tool_image_create() 219 | { 220 | tool_create(UI_MODE_UNSPECIFIED, "Resection", "Estimate cameras using correspondence between reconstructred 3d vertices and their projection"); 221 | tool_register_menu_function("Main menu|Image|Colorize vertices|", tool_image_colorize); 222 | tool_register_menu_function("Main menu|Image|Generate textures|", tool_image_generate_textures); 223 | // tool_register_menu_function("Main menu|Image|Pinhole correction|", tool_image_pinhole_deform); 224 | } 225 | -------------------------------------------------------------------------------- /insight3d/ui_workflow.cpp: -------------------------------------------------------------------------------- 1 | #include "ui_workflow.h" 2 | 3 | // cancels processing of a vertex, this usually results in a new vertex being created 4 | void ui_workflow_no_vertex() 5 | { 6 | ui_state.processed_vertex_stage = 2; 7 | INDEX_CLEAR(ui_state.processed_vertex); 8 | } 9 | 10 | // next vertex to be processed 11 | void ui_workflow_next_vertex() 12 | { 13 | ASSERT(validate_shot(ui_state.current_shot), "tried to proceed to next vertex on invalid shot"); 14 | 15 | // if we're at the end, we can't go to the next vertex 16 | if (ui_state.processed_vertex_stage == 2) return; 17 | 18 | // find the next one without correspondence on this image 19 | size_t vertex_id, point_id, from; 20 | bool found; 21 | 22 | // we want to go through manually entered vertices first 23 | if (INDEX_IS_SET(ui_state.processed_vertex)) 24 | { 25 | from = ui_state.processed_vertex + 1; 26 | } 27 | else 28 | { 29 | from = 0; 30 | } 31 | 32 | GEOMETRY_VERTEX_TYPE vertex_type = ui_state.processed_vertex_stage == 0 ? GEOMETRY_VERTEX_USER : GEOMETRY_VERTEX_AUTO; 33 | 34 | LAMBDA_FIND_FROM( 35 | vertices, 36 | from, 37 | vertex_id, 38 | found, 39 | vertices.data[vertex_id].vertex_type == vertex_type 40 | && !query_find_point_on_shot_by_vertex_id(ui_state.current_shot, vertex_id, point_id) 41 | ); 42 | 43 | if (found) 44 | { 45 | INDEX_SET(ui_state.processed_vertex, vertex_id); 46 | } 47 | else 48 | { 49 | if (ui_state.processed_vertex_stage == 0) 50 | { 51 | if (!option_hide_automatic) 52 | { 53 | ui_state.processed_vertex_stage = 1; 54 | INDEX_CLEAR(ui_state.processed_vertex); 55 | ui_workflow_next_vertex(); 56 | } 57 | else 58 | { 59 | ui_workflow_no_vertex(); 60 | } 61 | } 62 | else if (ui_state.processed_vertex_stage == 1) 63 | { 64 | ui_workflow_no_vertex(); 65 | } 66 | else 67 | { 68 | ASSERT(false, "invalid stage index in workflow module"); 69 | } 70 | } 71 | } 72 | 73 | // next vertex to be processed 74 | void ui_workflow_prev_vertex() 75 | { 76 | ASSERT(validate_shot(ui_state.current_shot), "tried to proceed to next vertex on invalid shot"); 77 | 78 | // find the previous one without correspondence on this image 79 | size_t vertex_id, point_id, from; 80 | bool found = false; 81 | 82 | // if we were at the end, start from automatically generated vertices 83 | if (ui_state.processed_vertex_stage == 2) 84 | { 85 | ui_state.processed_vertex_stage = !option_hide_automatic ? 1 : 0; 86 | 87 | ASSERT(!INDEX_IS_SET(ui_state.processed_vertex), "processed_vertex index should be cleared whenever stage 2 is reached"); 88 | } 89 | 90 | // we want to go through manually entered vertices first 91 | bool begin = false; 92 | if (INDEX_IS_SET(ui_state.processed_vertex)) 93 | { 94 | if (ui_state.processed_vertex == 0) 95 | { 96 | begin = true; 97 | } 98 | else 99 | { 100 | from = ui_state.processed_vertex - 1; 101 | } 102 | } 103 | else 104 | { 105 | if (vertices.count == 0) 106 | { 107 | begin = true; 108 | } 109 | else 110 | { 111 | from = vertices.count - 1; 112 | } 113 | } 114 | 115 | GEOMETRY_VERTEX_TYPE vertex_type = ui_state.processed_vertex_stage == 0 ? GEOMETRY_VERTEX_USER : GEOMETRY_VERTEX_AUTO; 116 | 117 | if (!begin) 118 | { 119 | for (vertex_id = from; true; vertex_id--) 120 | { 121 | if (!IS_SET(vertices, vertex_id)) 122 | { 123 | if (vertex_id == 0) break; else continue; 124 | } 125 | 126 | if ( 127 | vertices.data[vertex_id].vertex_type == vertex_type 128 | && !query_find_point_on_shot_by_vertex_id(ui_state.current_shot, vertex_id, point_id) 129 | ) 130 | { 131 | found = true; 132 | break; 133 | } 134 | 135 | if (vertex_id == 0) break; 136 | } 137 | } 138 | 139 | if (found) 140 | { 141 | INDEX_SET(ui_state.processed_vertex, vertex_id); 142 | } 143 | else 144 | { 145 | if (ui_state.processed_vertex_stage == 1) 146 | { 147 | ui_state.processed_vertex_stage = 0; 148 | INDEX_CLEAR(ui_state.processed_vertex); 149 | ui_workflow_prev_vertex(); 150 | } 151 | else if (ui_state.processed_vertex_stage == 0) 152 | { 153 | if (!INDEX_IS_SET(ui_state.processed_vertex)) 154 | { 155 | ui_workflow_no_vertex(); 156 | } 157 | } 158 | else if (ui_state.processed_vertex_stage != 2) 159 | { 160 | ASSERT(false, "invalid stage index in workflow module"); 161 | } 162 | } 163 | } 164 | 165 | // first vertex to be processed 166 | void ui_workflow_first_vertex() 167 | { 168 | ASSERT(validate_shot(ui_state.current_shot), "tried to find first unprocessed vertex on invalid shot"); 169 | 170 | // we're processing manually entered vertices first 171 | INDEX_CLEAR(ui_state.processed_vertex); 172 | ui_state.processed_vertex_stage = 0; 173 | 174 | ui_workflow_next_vertex(); 175 | } 176 | 177 | // prev polygon to be processed 178 | void ui_workflow_next_polygon() 179 | { 180 | if (INDEX_IS_SET(ui_state.processed_polygon)) 181 | { 182 | for (size_t id = ui_state.processed_polygon + 1; id < polygons.count; id++) 183 | { 184 | if (polygons.data[id].set) 185 | { 186 | INDEX_SET(ui_state.processed_polygon, id); 187 | return; 188 | } 189 | } 190 | 191 | INDEX_CLEAR(ui_state.processed_polygon); 192 | } 193 | } 194 | 195 | // next polygon to be processed 196 | void ui_workflow_prev_polygon() 197 | { 198 | size_t id = INDEX_IS_SET(ui_state.processed_polygon) ? ui_state.processed_polygon : polygons.count; 199 | 200 | while (id != 0) 201 | { 202 | id--; 203 | 204 | if (polygons.data[id].set) 205 | { 206 | INDEX_SET(ui_state.processed_polygon, id); 207 | return; 208 | } 209 | } 210 | } 211 | 212 | // sets focused point 213 | void ui_workflow_set_focused_point(const size_t point_id) 214 | { 215 | ASSERT(validate_point(ui_state.current_shot, point_id), "focus set to point which cannot be found on current shot"); 216 | INDEX_SET(ui_state.focused_point, point_id); 217 | } 218 | 219 | // unsets focused point 220 | void ui_workflow_unset_focused_point() 221 | { 222 | INDEX_CLEAR(ui_state.focused_point); 223 | } 224 | 225 | // switches to another image 226 | void ui_workflow_select_shot(size_t shot_id) 227 | { 228 | ASSERT(validate_shot(shot_id), "selecting invalid shot"); 229 | 230 | // end currently selected tool 231 | if (tools_state.tools[tools_state.current].end) 232 | { 233 | tools_state.tools[tools_state.current].end(); 234 | } 235 | 236 | // remove request for the image that is being replaced 237 | if (INDEX_IS_SET(ui_state.current_shot)) 238 | { 239 | ASSERT_IS_SET(shots, ui_state.current_shot); 240 | if (image_loader_nonempty_handle(shots.data[ui_state.current_shot].image_loader_request)) 241 | { 242 | image_loader_cancel_request(&shots.data[ui_state.current_shot].image_loader_request); 243 | } 244 | } 245 | 246 | // update state value 247 | INDEX_SET(ui_state.current_shot, shot_id); 248 | 249 | // deselect focused items 250 | ui_workflow_unset_focused_point(); 251 | 252 | // set default zoom and scrolling if necessary 253 | if (!ui_viewport_set(shot_id)) visualization_fit_to_viewport(); 254 | 255 | // update cursor of unprocessed items 256 | ui_workflow_first_vertex(); 257 | 258 | // begin working with current tool again 259 | if (tools_state.tools[tools_state.current].begin) 260 | { 261 | tools_state.tools[tools_state.current].begin(); 262 | } 263 | } 264 | 265 | // set current shot to default value (if necessary) 266 | // this function is called after any modification to the image sequence (i.e., addition or 267 | // removal of images) 268 | void ui_workflow_default_shot() 269 | { 270 | // if current shot was (for example) removed, we clear the value of current_shot 271 | if (INDEX_IS_SET(ui_state.current_shot) && !validate_shot(ui_state.current_shot)) 272 | { 273 | INDEX_CLEAR(ui_state.current_shot); 274 | } 275 | 276 | // scan the sequence of images and try to find a shot without meta info 277 | size_t shot_wo_meta_id; 278 | bool shot_wo_meta_found; 279 | LAMBDA_FIND(shots, shot_wo_meta_id, shot_wo_meta_found, shots.data[shot_wo_meta_id].info_status < GEOMETRY_INFO_DEDUCED); 280 | if (shot_wo_meta_found) 281 | { 282 | ui_workflow_select_shot(shot_wo_meta_id); 283 | return; 284 | } 285 | 286 | // if current shot is not set 287 | if (!INDEX_IS_SET(ui_state.current_shot)) 288 | { 289 | // find first valid shot in sequence 290 | size_t shot; 291 | bool found; 292 | LAMBDA_FIND(shots, shot, found, validate_shot(shot)); 293 | 294 | if (found) 295 | { 296 | // set it as current shot 297 | ui_workflow_select_shot(shot); 298 | } 299 | } 300 | 301 | // we probably want to ensure that the treeview shows 302 | // the list of pictures and the user can see the change 303 | // ui_treeview_unfold_pictures(); 304 | // todo remove the above comment 305 | } 306 | --------------------------------------------------------------------------------