Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

omvg fix #160

Merged
merged 10 commits into from
Feb 8, 2025
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ A free and open source implementation of 3D [gaussian splatting](https://www.you
<img src="https://github.com/pierotofy/OpenSplat/assets/1951843/c9327c7c-31ad-402d-a5a5-04f7602ca5f5" width="49%" />
<img src="https://github.com/pierotofy/OpenSplat/assets/1951843/eba4ae75-2c88-4c9e-a66b-608b574d085f" width="49%" />

OpenSplat takes camera poses + sparse points in [COLMAP](https://colmap.github.io/), [OpenSfM](https://github.com/mapillary/OpenSfM), [ODM](https://github.com/OpenDroneMap/ODM) or [nerfstudio](https://docs.nerf.studio/quickstart/custom_dataset.html) project format and computes a [scene file](https://drive.google.com/file/d/12lmvVWpFlFPL6nxl2e2d-4u4a31RCSKT/view?usp=sharing) (.ply or .splat) that can be later imported for [viewing](https://antimatter15.com/splat/?url=https://splat.uav4geo.com/banana.splat), editing and rendering in other [software](https://github.com/MrNeRF/awesome-3D-gaussian-splatting?tab=readme-ov-file#open-source-implementations).
OpenSplat takes camera poses + sparse points in [COLMAP](https://colmap.github.io/), [OpenSfM](https://github.com/mapillary/OpenSfM), [ODM](https://github.com/OpenDroneMap/ODM) [OpenMVG](https://github.com/OpenMVG/OpenMVG) or [nerfstudio](https://docs.nerf.studio/quickstart/custom_dataset.html) project format and computes a [scene file](https://drive.google.com/file/d/12lmvVWpFlFPL6nxl2e2d-4u4a31RCSKT/view?usp=sharing) (.ply or .splat) that can be later imported for [viewing](https://antimatter15.com/splat/?url=https://splat.uav4geo.com/banana.splat), editing and rendering in other [software](https://github.com/MrNeRF/awesome-3D-gaussian-splatting?tab=readme-ov-file#open-source-implementations).

Graphics card recommended, but not required! OpenSplat runs the fastest on NVIDIA, AMD and Apple (Metal) GPUs, but can also run entirely on the CPU (~100x slower).

Expand Down
1 change: 1 addition & 0 deletions model.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include <iostream>
#include <torch/torch.h>
#include <torch/csrc/api/include/torch/version.h>
#include <ATen/ATen.h>
eokeeffe marked this conversation as resolved.
Show resolved Hide resolved
#include "nerfstudio.hpp"
#include "kdtree_tensor.hpp"
#include "spherical_harmonics.hpp"
Expand Down
55 changes: 40 additions & 15 deletions openmvg.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include "tensor_math.hpp"
#include <stdexcept>
#include <string>
#include <bits/stdc++.h>
eokeeffe marked this conversation as resolved.
Show resolved Hide resolved

namespace fs = std::filesystem;
using json = nlohmann::json;
Expand Down Expand Up @@ -176,18 +177,43 @@ bool read_poses(const json& data, std::unordered_map<uint32_t, Pose> &poses){
}
}
*/

/*
OpenMVG rotation data is stored as columns, must convert to rows
*/

auto scene_poses = data["extrinsics"];
for(auto item: scene_poses){

std::uint32_t id = item["key"].get<std::uint32_t>();
auto value = item["value"];

Pose pose;
std::vector<float> omvg_rotation;

for(auto row: value["rotation"]){
for(auto r: row){
pose.rotation.push_back( r.get<float>() );
omvg_rotation.push_back( r.get<float>() );
}
}

pose.rotation = std::vector<float>(9);

// convert cols to rows

pose.rotation[0] = omvg_rotation[0];
pose.rotation[1] = omvg_rotation[3];
pose.rotation[2] = omvg_rotation[6];

pose.rotation[3] = omvg_rotation[1];
pose.rotation[4] = omvg_rotation[4];
pose.rotation[5] = omvg_rotation[7];

pose.rotation[6] = omvg_rotation[2];
pose.rotation[7] = omvg_rotation[5];
pose.rotation[8] = omvg_rotation[8];


for(auto c: value["center"]){
pose.center.push_back( c.get<float>() );
}
Expand Down Expand Up @@ -256,24 +282,26 @@ InputData inputDataFromOpenMVG(const std::string &projectRoot){
for (const auto &p : poses){
std::uint32_t pose_id = p.first;
Pose pose = p.second;

torch::Tensor R = torch::from_blob(pose.rotation.data(), {static_cast<long>(pose.rotation.size())}, torch::kFloat32);
R = R.reshape({3, 3});

torch::Tensor rotation = rodriguesToRotation(torch::from_blob(pose.rotation.data(), {static_cast<long>(pose.rotation.size())}, torch::kFloat32));
torch::Tensor translation = torch::from_blob(pose.center.data(), {static_cast<long>(pose.center.size())}, torch::kFloat32);
torch::Tensor w2c = torch::eye(4, torch::kFloat32);
w2c.index_put_({Slice(None, 3), Slice(None, 3)}, rotation);
w2c.index_put_({Slice(None, 3), Slice(3,4)}, translation.reshape({3, 1}));

unorientedPoses[i] = torch::linalg::inv(w2c);

std::cout << pose_id << " " << i;
torch::Tensor T = torch::from_blob(pose.center.data(), {static_cast<long>(pose.center.size())}, torch::kFloat32);
T = T.reshape({3, 1});

torch::Tensor Rinv = R.transpose(0, 1);
torch::Tensor Tinv = torch::matmul(-Rinv, T);

// because the maps are unordered, need this to keep track of which pose in the tensor is the pose we need
pose_indexes[pose_id] = i;

// Convert OpenSfM's camera CRS (OpenCV) to OpenGL
unorientedPoses[i].index_put_({Slice(None, 3), Slice(None, 3)}, R);
unorientedPoses[i].index_put_({Slice(None, 3), Slice(3, 4)}, Tinv);
unorientedPoses[i][3][3] = 1.0f;

// Convert OpenMVG's camera CRS (OpenCV) to OpenGL
unorientedPoses[i].index_put_({Slice(0, 3), Slice(1,3)}, unorientedPoses[i].index({Slice(0, 3), Slice(1,3)}) * -1.0f);
i++;

}

std::cout << " " << std::endl;
Expand All @@ -296,11 +324,8 @@ InputData inputDataFromOpenMVG(const std::string &projectRoot){
fs::path thisRoot(image_root_path);
fs::path image_path = thisRoot/ v.s_Img_path;


std::uint32_t current_pose = pose_indexes.at(v.id_pose);

std::cout << view_id << " " << v.s_Img_path << " pose " << current_pose << std::endl;

float normalizer = static_cast<float>((std::max)(intrinsic.width, intrinsic.height));
ret.cameras.emplace_back(Camera(intrinsic.width, intrinsic.height,
static_cast<float>(intrinsic.fx * normalizer), static_cast<float>(intrinsic.fy * normalizer),
Expand Down
Loading