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

Save cameras.json #85

Merged
merged 3 commits into from
Apr 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,28 @@ set(OPENCV_DIR "OPENCV_DIR-NOTFOUND" CACHE PATH "Path to the OPENCV installation
set(OPENSPLAT_MAX_CUDA_COMPATIBILITY OFF CACHE BOOL "Build for maximum CUDA device compatibility")
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})

# Read version
file(READ "VERSION" APP_VERSION)

# Read git commit
set(GIT_REV "")
execute_process(COMMAND git rev-parse --short HEAD
WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
OUTPUT_VARIABLE GIT_REV
ERROR_QUIET)
string(REGEX REPLACE "\n$" "" GIT_REV "${GIT_REV}")
if (NOT "${GIT_REV}" STREQUAL "")
set(DAPP_VERSION "${APP_VERSION} (git commit ${GIT_REV})")
set(DAPP_REVISION "${GIT_REV}")
else()
set(DAPP_VERSION "${APP_VERSION}")
set(DAPP_REVISION "dev")
endif()

message("OpenSplat Version: ${DAPP_VERSION}")
add_compile_options("-DAPP_VERSION=\"${DAPP_VERSION}\"")
add_compile_options("-DAPP_REVISION=\"${DAPP_REVISION}\"")

# Don't complain about the override from NANOFLANN_BUILD_EXAMPLES
set(CMAKE_POLICY_DEFAULT_CMP0077 NEW)
# Use time-of-extraction for FetchContent'ed files modification time
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,7 @@ cd build
./opensplat /path/to/banana -n 2000
```

The program will generate an output `splat.ply` file which can then be dragged and dropped in one of the many [viewers](https://github.com/MrNeRF/awesome-3D-gaussian-splatting?tab=readme-ov-file#viewers) such as https://playcanvas.com/viewer. You can also edit/cleanup the scene using https://playcanvas.com/supersplat/editor
The program will generate an output `splat.ply` file which can then be dragged and dropped in one of the many [viewers](https://github.com/MrNeRF/awesome-3D-gaussian-splatting?tab=readme-ov-file#viewers) such as https://playcanvas.com/viewer. You can also edit/cleanup the scene using https://playcanvas.com/supersplat/editor. The program will also output a `cameras.json` file in the same directory which can be used by some viewers.

To run on your own data, choose the path to an existing [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. The project must have sparse points included (random initialization is not supported, see https://github.com/pierotofy/OpenSplat/issues/7).

Expand Down
1 change: 1 addition & 0 deletions VERSION
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
1.1.3
8 changes: 8 additions & 0 deletions constants.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,12 @@
#define PI 3.14159265358979323846
#define FLOAT_EPS 1e-9f

#ifndef APP_VERSION
#define APP_VERSION "dev"
#endif

#ifndef APP_REVISION
#define APP_REVISION "dev"
#endif

#endif
46 changes: 46 additions & 0 deletions input_data.cpp
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
#include <filesystem>
#include <nlohmann/json.hpp>
#include "input_data.hpp"
#include "cv_utils.hpp"

namespace fs = std::filesystem;
using namespace torch::indexing;
using json = nlohmann::json;

namespace ns{ InputData inputDataFromNerfStudio(const std::string &projectRoot); }
namespace cm{ InputData inputDataFromColmap(const std::string &projectRoot); }
Expand Down Expand Up @@ -145,3 +147,47 @@ std::tuple<std::vector<Camera>, Camera *> InputData::getCameras(bool validate, c
return std::make_tuple(cams, valCam);
}
}


void InputData::saveCameras(const std::string &filename, bool keepCrs){
json j = json::array();

for (size_t i = 0; i < cameras.size(); i++){
Camera &cam = cameras[i];

json camera = json::object();
camera["id"] = i;
camera["img_name"] = fs::path(cam.filePath).filename().string();
camera["width"] = cam.width;
camera["height"] = cam.height;
camera["fx"] = cam.fx;
camera["fy"] = cam.fy;

torch::Tensor R = cam.camToWorld.index({Slice(None, 3), Slice(None, 3)});
torch::Tensor T = cam.camToWorld.index({Slice(None, 3), Slice(3,4)}).squeeze();

// Flip z and y
R = torch::matmul(R, torch::diag(torch::tensor({1.0f, -1.0f, -1.0f})));

if (keepCrs) T = (T / scale) + translation;

std::vector<float> position(3);
std::vector<std::vector<float>> rotation(3, std::vector<float>(3));
for (int i = 0; i < 3; i++) {
position[i] = T[i].item<float>();
for (int j = 0; j < 3; j++) {
rotation[i][j] = R[i][j].item<float>();
}
}

camera["position"] = position;
camera["rotation"] = rotation;
j.push_back(camera);
}

std::ofstream of(filename);
of << j;
of.close();

std::cout << "Wrote " << filename << std::endl;
}
3 changes: 2 additions & 1 deletion input_data.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ struct Camera{
width(width), height(height), fx(fx), fy(fy), cx(cx), cy(cy),
k1(k1), k2(k2), k3(k3), p1(p1), p2(p2),
camToWorld(camToWorld), filePath(filePath) {}

torch::Tensor getIntrinsicsMatrix();
bool hasDistortionParameters();
std::vector<float> undistortionParameters();
Expand All @@ -57,6 +56,8 @@ struct InputData{
Points points;

std::tuple<std::vector<Camera>, Camera *> getCameras(bool validate, const std::string &valImage = "random");

void saveCameras(const std::string &filename, bool keepCrs);
};
InputData inputDataFromX(const std::string &projectRoot);

Expand Down
1 change: 0 additions & 1 deletion model.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,6 @@ torch::Tensor Model::forward(Camera& cam, int step){
const int height = static_cast<int>(static_cast<float>(cam.height) / scaleFactor);
const int width = static_cast<int>(static_cast<float>(cam.width) / scaleFactor);

// TODO: these can be moved to Camera and computed only once?
torch::Tensor R = cam.camToWorld.index({Slice(None, 3), Slice(None, 3)});
torch::Tensor T = cam.camToWorld.index({Slice(None, 3), Slice(3,4)});

Expand Down
11 changes: 10 additions & 1 deletion opensplat.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,14 @@
#include "input_data.hpp"
#include "utils.hpp"
#include "cv_utils.hpp"
#include "constants.hpp"
#include <cxxopts.hpp>

namespace fs = std::filesystem;
using namespace torch::indexing;

int main(int argc, char *argv[]){
cxxopts::Options options("opensplat", "Open Source 3D Gaussian Splats generator");
cxxopts::Options options("opensplat", "Open Source 3D Gaussian Splats generator - " APP_VERSION);
options.add_options()
("i,input", "Path to nerfstudio project", cxxopts::value<std::string>())
("o,output", "Path where to save output scene", cxxopts::value<std::string>()->default_value("splat.ply"))
Expand All @@ -37,6 +38,7 @@ int main(int argc, char *argv[]){
("split-screen-size", "Split gaussians that are larger than this percentage of screen space", cxxopts::value<float>()->default_value("0.05"))

("h,help", "Print usage")
("version", "Print version")
;
options.parse_positional({ "input" });
options.positional_help("[colmap/nerfstudio/opensfm/odm project path]");
Expand All @@ -50,11 +52,16 @@ int main(int argc, char *argv[]){
return EXIT_FAILURE;
}

if (result.count("version")){
std::cout << APP_VERSION << std::endl;
return EXIT_SUCCESS;
}
if (result.count("help") || !result.count("input")) {
std::cout << options.help() << std::endl;
return EXIT_SUCCESS;
}


const std::string projectRoot = result["input"].as<std::string>();
const std::string outputScene = result["output"].as<std::string>();
const int saveEvery = result["save-every"].as<int>();
Expand Down Expand Up @@ -94,6 +101,7 @@ int main(int argc, char *argv[]){

try{
InputData inputData = inputDataFromX(projectRoot);

parallel_for(inputData.cameras.begin(), inputData.cameras.end(), [&downScaleFactor](Camera &cam){
cam.loadImage(downScaleFactor);
});
Expand Down Expand Up @@ -146,6 +154,7 @@ int main(int argc, char *argv[]){
}
}

inputData.saveCameras((fs::path(outputScene).parent_path() / "cameras.json").string(), keepCrs);
model.save(outputScene);
// model.saveDebugPly("debug.ply");

Expand Down
8 changes: 7 additions & 1 deletion simple_trainer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ using namespace torch::indexing;
namespace fs = std::filesystem;

int main(int argc, char **argv){
cxxopts::Options options("simple_trainer", "Test program for gsplat execution");
cxxopts::Options options("simple_trainer", "Test program for gsplat execution - " APP_VERSION);
options.add_options()
("cpu", "Force CPU execution")
("width", "Test image width", cxxopts::value<int>()->default_value("256"))
Expand All @@ -32,6 +32,7 @@ int main(int argc, char **argv){
("lr", "Learning rate", cxxopts::value<float>()->default_value("0.01"))
("render", "Save rendered images to folder", cxxopts::value<std::string>()->default_value(""))
("h,help", "Print usage")
("version", "Print version")
;
cxxopts::ParseResult result;
try {
Expand All @@ -48,6 +49,11 @@ int main(int argc, char **argv){
return EXIT_SUCCESS;
}

if (result.count("version")) {
std::cout << APP_VERSION << std::endl;
return EXIT_SUCCESS;
}

int width = result["width"].as<int>(),
height = result["height"].as<int>();
int numPoints = result["points"].as<int>();
Expand Down
Loading