Skip to content

Commit

Permalink
ENH: Refactor VTK Cam loader for JSON files
Browse files Browse the repository at this point in the history
  • Loading branch information
NicerNewerCar committed Sep 25, 2023
1 parent c2ab3cb commit 3f724c9
Show file tree
Hide file tree
Showing 4 changed files with 90 additions and 105 deletions.
1 change: 1 addition & 0 deletions SuperBuild.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
set(Autoscoper_DEPENDENCIES
GLEW
TIFF
JsonCpp
)
if(Autoscoper_RENDERING_BACKEND STREQUAL "OpenCL")
if(Autoscoper_OPENCL_USE_ICD_LOADER)
Expand Down
66 changes: 66 additions & 0 deletions Superbuild/External_JsonCpp.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@

set(proj JsonCpp)

set(${proj}_DEPENDENCIES "")

# Include dependent projects if any
ExternalProject_Include_Dependencies(${proj} PROJECT_VAR proj DEPENDS_VAR ${proj}_DEPENDENCIES)

if(Autoscoper_USE_SYSTEM_${proj})
message(FATAL_ERROR "Enabling Autoscoper_USE_SYSTEM_${proj} is not supported !")
endif()

# Sanity checks
if(DEFINED JsonCpp_INCLUDE_DIR AND NOT EXISTS ${JsonCpp_INCLUDE_DIR})
message(FATAL_ERROR "JsonCpp_INCLUDE_DIR variable is defined but corresponds to nonexistent directory")
endif()
if(DEFINED JsonCpp_LIBRARY AND NOT EXISTS ${JsonCpp_LIBRARY})
message(FATAL_ERROR "JsonCpp_LIBRARY variable is defined but corresponds to nonexistent file")
endif()

if((NOT DEFINED JsonCpp_INCLUDE_DIR
OR NOT DEFINED JsonCpp_LIBRARY) AND NOT Autoscoper_USE_SYSTEM_${proj})

set(EP_SOURCE_DIR ${CMAKE_BINARY_DIR}/${proj})
set(EP_BINARY_DIR ${CMAKE_BINARY_DIR}/${proj}-build)
set(EP_INSTALL_DIR ${CMAKE_BINARY_DIR}/${proj}-install)

set(EXTERNAL_PROJECT_OPTIONAL_CMAKE_CACHE_ARGS)

ExternalProject_Add(${proj}
${${proj}_EP_ARGS}
GIT_REPOSITORY https://github.com/open-source-parsers/jsoncpp.git
GIT_TAG 5defb4ed1a4293b8e2bf641e16b156fb9de498cc # 1.9.5
SOURCE_DIR ${EP_SOURCE_DIR}
BINARY_DIR ${EP_BINARY_DIR}
INSTALL_DIR ${EP_INSTALL_DIR}
CMAKE_CACHE_ARGS
# Compiler settings
-DCMAKE_C_COMPILER:FILEPATH=${CMAKE_C_COMPILER}
-DCMAKE_CXX_COMPILER:FILEPATH=${CMAKE_CXX_COMPILER}
-DCMAKE_CXX_EXTENSIONS:BOOL=${CMAKE_CXX_EXTENSIONS}
-DCMAKE_CXX_STANDARD:STRING=${CMAKE_CXX_STANDARD}
-DCMAKE_CXX_STANDARD_REQUIRED:BOOL=${CMAKE_CXX_STANDARD_REQUIRED}
# Options
-DJSONCPP_WITH_TESTS:BOOL=OFF
-DJSONCPP_WITH_POST_BUILD_UNITTEST:BOOL=OFF
-DJSONCPP_WITH_WARNING_AS_ERROR:BOOL=OFF
-DJSONCPP_WITH_PKGCONFIG_SUPPORT:BOOL=OFF
-DJSONCPP_WITH_CMAKE_PACKAGE:BOOL=ON
-DBUILD_SHARED_LIBS:BOOL=ON
-DBUILD_STATIC_LIBS:BOOL=OFF
# Install directories
-DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR>
-DCMAKE_INSTALL_BINDIR:STRING=${Autoscoper_BIN_DIR}
-DCMAKE_INSTALL_LIBDIR:STRING=${Autoscoper_LIB_DIR}
${EXTERNAL_PROJECT_OPTIONAL_CMAKE_CACHE_ARGS}
DEPENDS
${${proj}_DEPENDENCIES}
)
set(JSONCPP_DIR ${EP_INSTALL_DIR})
set(JSONCPP_SOURCE_DIR ${EP_SOURCE_DIR})
set(JSONCPP_INCLUDE_DIR ${JSONCPP_DIR}/include)
set(JSONCPP_LIBRARY ${JSONCPP_DIR}/lib/${CMAKE_SHARED_LIBRARY_PREFIX}jsoncpp${CMAKE_SHARED_LIBRARY_SUFFIX})

mark_as_superbuild(JSONCPP_DIR JSONCPP_SOURCE_DIR JSONCPP_INCLUDE_DIR JSONCPP_LIBRARY)
endif()
3 changes: 3 additions & 0 deletions libautoscoper/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,9 @@ find_package(TIFF REQUIRED MODULE)
target_link_libraries(libautoscoper PUBLIC TIFF::TIFF)
target_compile_definitions(libautoscoper PUBLIC -DUSE_LIBTIFF)

find_package(JsonCpp REQUIRED)
target_link_libraries(libautoscoper PUBLIC JsonCpp::JsonCpp)

target_include_directories(libautoscoper PUBLIC
${CMAKE_CURRENT_BINARY_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/src
Expand Down
125 changes: 20 additions & 105 deletions libautoscoper/src/Camera.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,14 @@
#define M_PI 3.14159265358979323846
#endif

#define VTK_SCHEMA_URL "https://autoscoperm.slicer.org/vtk-schema-1.0.json"

#include <algorithm>
#include <fstream>
#include <iostream>
#include <sstream>
#include <stdexcept>
#include <json/json.h>

#include "Camera.hpp"

Expand Down Expand Up @@ -131,7 +134,7 @@ Camera::Camera(const std::string& mayacam) : mayacam_(mayacam)
}
std::string ext = mayacam_.substr(ext_pos + 1);
// if its a yaml file load it as a vtk camera
if (ext.compare("yaml") == 0) {
if (ext.compare("json") == 0) {
loadVTKCamera(mayacam_);
}
else {
Expand Down Expand Up @@ -384,133 +387,45 @@ Camera::Camera(const std::string& mayacam) : mayacam_(mayacam)
}

void Camera::loadVTKCamera(const std::string& filename) {
// Open and parse the file
double version = -1.0, view_angle = -1.0, image_width = -1.0 , image_height = -1.0;
double focal_point[3] = {-1.0, -1.0, -1.0}, camera_position[3] = { -1.0, -1.0, -1.0 }, view_up[3] = { -1.0, -1.0, -1.0 };
std::cout << "Loading VTKCam file: " << filename << std::endl;
std::fstream file(filename.c_str(), std::ios::in);
if (!file.is_open()) {
throw std::runtime_error("Error opening VTKCam file: " + filename);
}
std::string line;
// The file is a series of key value pairs separated by a colon, # denotes a comment
int line_num = 1;
while (safeGetline(file, line)) {
// Ignore comments and empty lines
if (line.empty() || line[0] == '#') {
line_num++;
continue;
}
// Split the line into key and value
std::string key, value;
std::istringstream line_stream(line);
if (!getline(line_stream, key, ':')) {
file.close();
throw std::runtime_error(vtkCamReadingError("1", line_num, filename, "Error parsing key."));
}
if (!getline(line_stream, value, ':')) {
file.close();
throw std::runtime_error(vtkCamReadingError("1", line_num, filename, "Error parsing value."));
}
// Parse the key value pair
if (key == "version") {
std::istringstream value_stream(value);
if (!(value_stream >> version)) {
file.close();
throw std::runtime_error(vtkCamReadingError("1", line_num, filename, "Error parsing version number."));
}
}
else if (key == "focal-point") {
if (!parseArray(value, focal_point, 3)) {
file.close();
throw std::runtime_error(vtkCamReadingError("1", line_num, filename, "Error parsing focal-point."));
}
}
else if (key == "camera-position") {
if (!parseArray(value, camera_position, 3)) {
file.close();
throw std::runtime_error(vtkCamReadingError("1", line_num, filename, "Error parsing camera-position."));
}
}
else if (key == "view-up") {
if (!parseArray(value, view_up, 3)) {
file.close();
throw std::runtime_error(vtkCamReadingError("1", line_num, filename, "Error parsing view-up."));
}
}
else if (key == "view-angle") {
std::istringstream value_stream(value);
if (!(value_stream >> view_angle)) {
file.close();
throw std::runtime_error(vtkCamReadingError("1", line_num, filename, "Error parsing view-angle."));
}
}
else if (key == "image-width") {
std::istringstream value_stream(value);
if (!(value_stream >> image_width)) {
file.close();
throw std::runtime_error(vtkCamReadingError("1", line_num, filename, "Error parsing image-width."));
}
}
else if (key == "image-height") {
std::istringstream value_stream(value);
if (!(value_stream >> image_height)) {
file.close();
throw std::runtime_error(vtkCamReadingError("1", line_num, filename, "Error parsing image-height."));
}
}
line_num++;
}

// Close the file
Json::Value calibrationFile;
file >> calibrationFile;
file.close();

// Check that all the values were read
if (version == -1.0) {
throw std::runtime_error(vtkCamReadingError("1", -1, filename, "Missing version number."));
}
if (view_angle == -1.0) {
throw std::runtime_error(vtkCamReadingError("1", -1, filename, "Missing view-angle."));
}
if (image_width == -1.0) {
throw std::runtime_error(vtkCamReadingError("1", -1, filename, "Missing image-width."));
}
if (image_height == -1.0) {
throw std::runtime_error(vtkCamReadingError("1", -1, filename, "Missing image-height."));
}
if (focal_point[0] == -1.0) {
throw std::runtime_error(vtkCamReadingError("1", -1, filename, "Missing focal-point."));
}
if (camera_position[0] == -1.0) {
throw std::runtime_error(vtkCamReadingError("1", -1, filename, "Missing camera-position."));
}
if (view_up[0] == -1.0) {
throw std::runtime_error(vtkCamReadingError("1", -1, filename, "Missing view-up."));
// Check the schema
if (calibrationFile["@schema"].asString() != VTK_SCHEMA_URL) {
throw std::runtime_error(vtkCamReadingError("1", -1, filename, "Unsupported schema. " + calibrationFile["@schema"].asString() + " is not " + VTK_SCHEMA_URL));
}

// Check the version number
if (version != 1.0) {
throw std::runtime_error(vtkCamReadingError("1", -1, filename, "Unsupported version number."));
if (calibrationFile["version"].asDouble() != 1.0) {
throw std::runtime_error(vtkCamReadingError("1", -1, filename, "Unsupported version number. "+ calibrationFile["version"].asString() + " is not 1.0"));
}


// Set the size
size_[0] = image_width;
size_[1] = image_height;
size_[0] = calibrationFile["image-width"].asDouble();
size_[1] = calibrationFile["image-height"].asDouble();

Vec3d cam_pos(camera_position);
Vec3d focal(focal_point);
Vec3d up(view_up);
Vec3d cam_pos(calibrationFile["camera-position"][0].asDouble(), calibrationFile["camera-position"][1].asDouble(), calibrationFile["camera-position"][2].asDouble());
Vec3d focal(calibrationFile["focal-point"][0].asDouble(), calibrationFile["focal-point"][1].asDouble(), calibrationFile["focal-point"][2].asDouble());
Vec3d up(calibrationFile["view-up"][0].asDouble(), calibrationFile["view-up"][1].asDouble(), calibrationFile["view-up"][2].asDouble());
double rot[9] = { 0.0 };
calculateLookAtMatrix(cam_pos, focal, up, rot);
coord_frame_ = CoordFrame(rot, cam_pos);

// Calculate the focal length
double focal_lengths[2] = { 0.0 };
calculateFocalLength(view_angle, focal_lengths);
calculateFocalLength(calibrationFile["view-angle"].asDouble(), focal_lengths);

// Calculate the principal point
double cx = image_width / 2.0;
double cy = image_height / 2.0;
double cx = size_[0] / 2.0;
double cy = size_[1] / 2.0;

// Calculate the viewport
calculateViewport(cx, cy , focal_lengths[0], focal_lengths[1]);
Expand Down

0 comments on commit 3f724c9

Please sign in to comment.