Skip to content
Snippets Groups Projects
Commit 64b0a921 authored by Sebastian Hahta's avatar Sebastian Hahta
Browse files

get camera matrix, python ctors

parent 95fd6227
No related branches found
No related tags found
No related merge requests found
Pipeline #33864 passed
......@@ -30,14 +30,15 @@ else()
endif()
set(VOLTU_SRCS
voltu.cpp
src/voltu.cpp
src/types/intrinsics.cpp
)
set(OPTIONAL_DEPENDENCIES)
if (WITH_OPENCV)
list(APPEND OPTIONAL_DEPENDENCIES ${OpenCV_LIBS})
list(APPEND VOLTU_SRCS voltu_cv.cpp)
list(APPEND VOLTU_SRCS src/voltu_cv.cpp)
set(CMAKE_REQUIRED_INCLUDES ${OpenCV_INCLUDE_DIRS})
endif()
......
......@@ -6,9 +6,14 @@
#pragma once
#include "../defines.hpp"
#include <Eigen/Eigen>
namespace voltu
{
/** Intrinsic camera paramters */
struct Intrinsics
{
unsigned int width;
......@@ -17,12 +22,20 @@ struct Intrinsics
float principle_y;
float focal_x;
float focal_y;
/** Projection matrix */
PY_API Eigen::Matrix3d matrix();
};
/** Stereo camera intrinsic parameters.
*
* Baseline can be used to estimate depth accuracy for known depth. Assuming 1px
* disparity accuracy, accuracy of given depth z, the accuracy of depth is
* z^2/(f*T), where f is focal length and T baseline.
*/
struct StereoIntrinsics : public Intrinsics
{
float baseline;
float doffs;
float min_depth;
float max_depth;
};
......
......@@ -39,7 +39,7 @@ build. Several (empty) macros are used in headers to annoate Python API details.
## Not supported (yet) in automatic binding generation:
* Nested classes
* Static members
* Constructors
* Constructors for non-POD structs.
* Automatic documentation (Doxygen)
* Generator does not verify that shared_ptr<> is used consistently/correctly
* Member variables of singleton classes
......@@ -50,12 +50,47 @@ def print_err(msg, loc=None):
msg += " " + get_loc_msg(loc)
print("gen.py error: %s" % msg, file=sys.stderr)
# Helpers ======================================================================
def is_singleton_class(ccls):
# covers both cases PY_SINGLETON and PY_SINGLETON_OBJECT
return "PY_SINGLETON" in ccls["debug"]
def is_member_of_singleton_class(func):
if func["parent"] is None:
return False
return is_singleton_class(func["parent"])
def include_in_api(data):
return "PY_API" in data["debug"]
def no_shared_ptr_cls(clsdata):
return (clsdata["declaration_method"] == "struct") or ("PY_NO_SHARED_PTR" in clsdata["debug"])
def rv_bind_lifetime_to_parent(func):
if "PY_RV_LIFETIME_PARENT" in func["debug"]:
if func["parent"] is None:
print_err("PY_RV_LIFETIME_PARENT can not be used for function or singleton", func)
sys.exit(2) # generated code most likely wrong and unsafe (crash/UB)
return False
if is_member_of_singleton_class(func):
print_warn(("Return value of %s lifetime bound to parent, but " +
"parent is singleton of %s. This is possibly an " +
"error (lifetime of the return value is the lifetime " +
"of the program).") %
(func["name"], func["parent"]["name"]))
return True
return False
def is_struct(clsdata):
return clsdata["declaration_method"] == "struct"
# Code generation ==============================================================
def create_enum_bindigs(enum, parent=[], pybind_handle="", export_values=False):
name_full = parent + [enum["name"]]
name_py = enum["name"]
......@@ -76,6 +111,35 @@ def create_enum_bindigs(enum, parent=[], pybind_handle="", export_values=False):
return "\n\t".join(cpp)
def create_struct_ctor(struct):
types = []
args = []
ctors = ["def(py::init<>())"]
for item in struct["properties"]["public"]:
types.append(item["type"])
arg = "py::arg(\"%s\")" % item["name"]
has_defaults = False
if "default" in item:
has_defaults = True
arg += "=%s" % item["default"]
args.append(arg)
if len(struct["inherits"]) > 0 or has_defaults:
# NOTE: Structs which inherit another struct require managing state,
# as base class possibly defines its own members from base
# class(es). Move everything to class?
# NOTE: Non-POD structs which do not inherit base class but set default
# values can be supported by generating lambda which assigns
# the values.
print_warn("Only aggregate initialization supported for structs")
return ctors
ctors.append("def(py::init<%s>(), %s)" % (", ".join(types), ", ".join(args)))
return ctors
def process_func_args(func):
args = []
......@@ -133,11 +197,7 @@ def create_function_bindings(func, parent=[], pybind_handle=None, bind_to_single
args += process_func_args(func)
if "PY_RV_LIFETIME_PARENT" in func["debug"]:
if func["parent"] is None or bind_to_singleton is not None:
print_err("PY_RV_LIFETIME_PARENT used for function or singleton", func)
raise ValueError()
if rv_bind_lifetime_to_parent(func):
args.append("py::return_value_policy::reference_internal")
cpp = "def({0})".format(", ".join(args))
......@@ -160,8 +220,8 @@ def create_class_bindings(clsdata, parent=[], pybind_handle=""):
cpp.append(cls_cpp.format(handle=pybind_handle, name=clsdata_name))
if clsdata["declaration_method"] == "struct":
cpp.append(".def(py::init<>())")
if is_struct(clsdata):
cpp += ["." + ctor for ctor in create_struct_ctor(clsdata)]
for method in clsdata["methods"]["public"]:
if include_in_api(method):
......@@ -172,6 +232,7 @@ def create_class_bindings(clsdata, parent=[], pybind_handle=""):
field_cpp = ".def_property_readonly(\"{name}\", &{cpp_name})"
else:
field_cpp = ".def_readwrite(\"{name}\", &{cpp_name})"
field_name = field["name"]
field_name_cpp = "::".join(full_name + [field_name])
cpp.append(field_cpp.format(name=field_name, cpp_name=field_name_cpp))
......
#include <voltu/types/intrinsics.hpp>
#include <Eigen/Eigen>
Eigen::Matrix3d voltu::Intrinsics::matrix() {
Eigen::Matrix3d K;
K << focal_x, 0.0, -principle_x,
0.0, focal_y, -principle_y,
0.0, 0.0, 1.0;
return K;
}
File moved
File moved
......@@ -13,3 +13,4 @@ function(add_python_test TEST_NAME TEST_SCRIPT)
endfunction()
add_python_test(Py_TestLoad test_load.py)
add_python_test(Py_TestIntrinsics test_intrinsics.py)
import unittest
import voltu
import numpy as np
class Intrinsics(unittest.TestCase):
def test_default_ctor(self):
intr = voltu.Intrinsics()
self.assertIsNotNone(intr)
def test_create(self):
fx = 2.0
fy = 3.0
cx = 4.0
cy = 5.0
intr = voltu.Intrinsics(
width = 6,
height = 7,
focal_x = fx,
focal_y = fy,
principle_x = -cx,
principle_y = -cy
)
K = np.array([
[fx , 0.0, cx],
[0.0, fy, cy],
[0.0, 0.0, 1.0],
])
self.assertTrue(np.array_equal(intr.matrix(), K))
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment