diff --git a/.github/workflows/build-mac.yml b/.github/workflows/build-mac.yml index ee3b4841bc..1e8c315619 100644 --- a/.github/workflows/build-mac.yml +++ b/.github/workflows/build-mac.yml @@ -77,7 +77,8 @@ jobs: sqlite3 \ ccache \ libomp \ - cli11 + cli11 \ + simdjson brew link --force libomp - name: Configure and build diff --git a/.github/workflows/build-ubuntu.yml b/.github/workflows/build-ubuntu.yml index f1b527b1a2..3002351100 100644 --- a/.github/workflows/build-ubuntu.yml +++ b/.github/workflows/build-ubuntu.yml @@ -184,6 +184,7 @@ jobs: libcurl4-openssl-dev \ libmkl-full-dev \ libcli11-dev \ + libsimdjson-dev \ xvfb # Fix issue in Ubuntu's openimageio CMake config. diff --git a/cmake/FindDependencies.cmake b/cmake/FindDependencies.cmake index f70563c1da..c08a938a5e 100644 --- a/cmake/FindDependencies.cmake +++ b/cmake/FindDependencies.cmake @@ -20,6 +20,8 @@ find_package(Boost ${COLMAP_FIND_TYPE} COMPONENTS OPTIONAL_COMPONENTS system) +find_package(simdjson ${COLMAP_FIND_TYPE}) + find_package(CLI11 ${COLMAP_FIND_TYPE}) find_package(Eigen3 ${COLMAP_FIND_TYPE}) diff --git a/src/colmap/exe/database.cc b/src/colmap/exe/database.cc index 3f6cd61100..71306e3f1a 100644 --- a/src/colmap/exe/database.cc +++ b/src/colmap/exe/database.cc @@ -35,9 +35,6 @@ #include "colmap/scene/rig.h" #include "colmap/util/file.h" -#include -#include - namespace colmap { int RunDatabaseCleaner(int argc, char** argv) { diff --git a/src/colmap/exe/sfm.cc b/src/colmap/exe/sfm.cc index b64a480bd4..8ac6973217 100644 --- a/src/colmap/exe/sfm.cc +++ b/src/colmap/exe/sfm.cc @@ -45,9 +45,6 @@ #include "colmap/util/misc.h" #include "colmap/util/opengl_utils.h" -#include -#include - namespace colmap { namespace { diff --git a/src/colmap/scene/CMakeLists.txt b/src/colmap/scene/CMakeLists.txt index 1f6d1d0b00..57f3b5adcb 100644 --- a/src/colmap/scene/CMakeLists.txt +++ b/src/colmap/scene/CMakeLists.txt @@ -74,6 +74,7 @@ COLMAP_ADD_LIBRARY( colmap_util Eigen3::Eigen SQLite3::SQLite3 + simdjson::simdjson PRIVATE_LINK_LIBS colmap_optim ) diff --git a/src/colmap/scene/rig.cc b/src/colmap/scene/rig.cc index e3975795dc..035a5aa296 100644 --- a/src/colmap/scene/rig.cc +++ b/src/colmap/scene/rig.cc @@ -31,8 +31,7 @@ #include "colmap/geometry/pose.h" -#include -#include +#include namespace colmap { namespace { @@ -262,72 +261,108 @@ void CopyCameraIntrinsics(const Camera& src, Camera& dst) { std::vector ReadRigConfig( const std::filesystem::path& rig_config_path) { - boost::property_tree::ptree pt; - boost::property_tree::read_json(rig_config_path.string().c_str(), pt); + simdjson::ondemand::parser parser; + auto padded = simdjson::padded_string::load(rig_config_path.string()); + THROW_CHECK_EQ(padded.error(), simdjson::SUCCESS) + << "Failed to read JSON file: " << rig_config_path; std::vector configs; - for (const auto& rig_node : pt) { - RigConfig& config = configs.emplace_back(); + auto doc = parser.iterate(padded.value()); + + for (auto rig_elem : doc.get_array()) { + simdjson::ondemand::object rig_obj; + THROW_CHECK_EQ(rig_elem.get(rig_obj), simdjson::SUCCESS); + + RigConfig config; bool has_ref_sensor = false; - for (const auto& camera : rig_node.second.get_child("cameras")) { - RigConfig::RigCamera& config_camera = config.cameras.emplace_back(); - config_camera.image_prefix = - camera.second.get("image_prefix"); + for (auto camera_elem : rig_obj["cameras"].get_array()) { + simdjson::ondemand::object camera_obj; + THROW_CHECK_EQ(camera_elem.get(camera_obj), simdjson::SUCCESS); - auto cam_from_rig_rotation_node = - camera.second.get_child_optional("cam_from_rig_rotation"); - auto cam_from_rig_translation_node = - camera.second.get_child_optional("cam_from_rig_translation"); - if (cam_from_rig_rotation_node && cam_from_rig_translation_node) { - Rigid3d cam_from_rig; + RigConfig::RigCamera config_camera; + + { + std::string_view image_prefix; + THROW_CHECK_EQ(camera_obj["image_prefix"].get(image_prefix), + simdjson::SUCCESS) + << "Camera must have 'image_prefix'"; + config_camera.image_prefix = std::string(image_prefix); + } + + bool has_cam_from_rig_rotation = false; + Eigen::Vector4d cam_from_rig_wxyz; + { + simdjson::ondemand::value rot_val; + if (camera_obj["cam_from_rig_rotation"].get(rot_val) == + simdjson::SUCCESS) { + has_cam_from_rig_rotation = true; + int idx = 0; + for (auto v : rot_val.get_array()) { + cam_from_rig_wxyz(idx++) = double(v); + } + } + } - int index = 0; - Eigen::Vector4d cam_from_rig_wxyz; - for (const auto& node : cam_from_rig_rotation_node.get()) { - cam_from_rig_wxyz[index++] = node.second.get_value(); + bool has_cam_from_rig_translation = false; + Eigen::Vector3d cam_from_rig_trans; + { + simdjson::ondemand::value trans_val; + if (camera_obj["cam_from_rig_translation"].get(trans_val) == + simdjson::SUCCESS) { + has_cam_from_rig_translation = true; + int idx = 0; + for (auto v : trans_val.get_array()) { + cam_from_rig_trans(idx++) = double(v); + } } + } + + if (has_cam_from_rig_rotation && has_cam_from_rig_translation) { + Rigid3d cam_from_rig; cam_from_rig.rotation() = Eigen::Quaterniond(cam_from_rig_wxyz(0), cam_from_rig_wxyz(1), cam_from_rig_wxyz(2), cam_from_rig_wxyz(3)); - - THROW_CHECK(cam_from_rig_translation_node); - index = 0; - for (const auto& node : cam_from_rig_translation_node.get()) { - cam_from_rig.translation()(index++) = node.second.get_value(); - } + cam_from_rig.translation() = cam_from_rig_trans; config_camera.cam_from_rig = cam_from_rig; } - auto ref_sensor_node = camera.second.get_child_optional("ref_sensor"); - if (ref_sensor_node && ref_sensor_node.get().get_value()) { - THROW_CHECK(!cam_from_rig_rotation_node && - !cam_from_rig_translation_node) - << "Reference sensor must not have cam_from_rig"; - THROW_CHECK(!has_ref_sensor) - << "Rig must only have one reference sensor"; - config_camera.ref_sensor = true; - has_ref_sensor = true; + { + simdjson::ondemand::value ref_val; + if (camera_obj["ref_sensor"].get(ref_val) == simdjson::SUCCESS) { + bool ref_sensor = ref_val.get_bool().value(); + if (ref_sensor) { + THROW_CHECK(!has_cam_from_rig_rotation && + !has_cam_from_rig_translation) + << "Reference sensor must not have cam_from_rig"; + THROW_CHECK(!has_ref_sensor) + << "Rig must only have one reference sensor"; + config_camera.ref_sensor = true; + has_ref_sensor = true; + } + } } - auto camera_model_name_node = - camera.second.get_child_optional("camera_model_name"); - auto camera_params_node = - camera.second.get_child_optional("camera_params"); - if (camera_model_name_node && camera_params_node) { - config_camera.camera = std::make_optional(); - config_camera.camera->model_id = CameraModelNameToId( - camera.second.get("camera_model_name")); + simdjson::ondemand::value model_val; + simdjson::ondemand::value params_val; + if (camera_obj["camera_model_name"].get(model_val) == simdjson::SUCCESS && + camera_obj["camera_params"].get(params_val) == simdjson::SUCCESS) { + config_camera.camera.emplace(); + std::string_view model_name = model_val.get_string(); + config_camera.camera->model_id = + CameraModelNameToId(std::string(model_name)); config_camera.camera->has_prior_focal_length = true; - for (const auto& node : camera_params_node.get()) { - config_camera.camera->params.push_back( - node.second.get_value()); + for (auto v : params_val.get_array()) { + config_camera.camera->params.push_back(double(v)); } } + + config.cameras.push_back(std::move(config_camera)); } THROW_CHECK(has_ref_sensor) << "Rig must have one reference sensor"; + configs.push_back(std::move(config)); } return configs; diff --git a/src/colmap/scene/rig_test.cc b/src/colmap/scene/rig_test.cc index c6b90fd6bc..4a91c9f8ed 100644 --- a/src/colmap/scene/rig_test.cc +++ b/src/colmap/scene/rig_test.cc @@ -63,7 +63,7 @@ TEST(ReadRigConfig, MissingImagePrefix) { { "cameras": [ { - "ref_sensor": true, + "ref_sensor": true } ] } @@ -78,11 +78,11 @@ TEST(ReadRigConfig, InvalidRefSensor) { "cameras": [ { "image_prefix": "rig1/camera1/", - "ref_sensor": true, + "ref_sensor": true }, { "image_prefix": "rig1/camera2/", - "ref_sensor": true, + "ref_sensor": true } ] } @@ -93,10 +93,10 @@ TEST(ReadRigConfig, InvalidRefSensor) { { "cameras": [ { - "image_prefix": "rig1/camera1/", + "image_prefix": "rig1/camera1/" }, { - "image_prefix": "rig1/camera2/", + "image_prefix": "rig1/camera2/" } ] } diff --git a/src/colmap/util/string.cc b/src/colmap/util/string.cc index 540a3e5f8b..f33acf2dcf 100644 --- a/src/colmap/util/string.cc +++ b/src/colmap/util/string.cc @@ -248,19 +248,21 @@ std::string StringGetAfter(const std::string& str, const std::string& key) { std::vector StringSplit(const std::string& str, const std::string& delim) { std::vector elems; - std::string::size_type start = 0; - std::string::size_type end = 0; - while ((end = str.find_first_of(delim, start)) != std::string::npos) { - if (end != start) { - elems.emplace_back(str.substr(start, end - start)); + while (true) { + const auto end = str.find_first_of(delim, start); + if (end == std::string::npos) { + break; + } + elems.emplace_back(str.substr(start, end - start)); + start = str.find_first_not_of(delim, end); + if (start == std::string::npos) { + elems.emplace_back(""); + return elems; } - start = end + 1; - } - if (start < str.size()) { - elems.emplace_back(str.substr(start)); } + elems.emplace_back(str.substr(start)); return elems; } diff --git a/vcpkg.json b/vcpkg.json index fa6fe839ec..20de1e3db1 100644 --- a/vcpkg.json +++ b/vcpkg.json @@ -8,7 +8,7 @@ "boost-graph", "boost-heap", "boost-property-map", - "boost-property-tree", + "simdjson", { "name": "ceres", "features": [