Skip to content

Commit 8efc527

Browse files
committed
Merge branch 'master' into mugamma/MET-32-fmb
2 parents 8582c5f + b4d4d7f commit 8efc527

File tree

21 files changed

+894
-25
lines changed

21 files changed

+894
-25
lines changed

CMakeLists.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,16 @@ set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
1414
################
1515

1616
add_library(genmetaballs_core
17+
genmetaballs/src/cuda/core/camera.cu
18+
genmetaballs/src/cuda/core/camera.cuh
1719
genmetaballs/src/cuda/core/utils.cu
1820
genmetaballs/src/cuda/core/utils.cuh
1921
genmetaballs/src/cuda/core/fmb.cuh
2022
genmetaballs/src/cuda/core/fmb.cu
2123
genmetaballs/src/cuda/core/geometry.cuh
2224
genmetaballs/src/cuda/core/geometry.cu
2325
genmetaballs/src/cuda/core/confidence.cuh
26+
genmetaballs/src/cuda/core/image.cuh
2427
)
2528

2629
# Set include directories for the core library

examples/run_fmb.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333
from tqdm import tqdm
3434

3535
# Import local utilities
36-
from genmetaballs.fmb.utils import DegradeLR, image_grid
36+
from genmetaballs.fmb.utils import DegradeLR, get_camera_rays, image_grid
3737

3838
CURRENT_DIR = Path(__file__).parent
3939
PROJECT_ROOT = CURRENT_DIR.parent
@@ -475,14 +475,12 @@ def main():
475475

476476
# Setup camera rays
477477
height, width = image_size
478-
K = np.array([[focal_length, 0, cx], [0, focal_length, cy], [0, 0, 1]])
479478
pixel_list = (
480479
(np.array(np.meshgrid(np.arange(width), height - np.arange(height) - 1, [0]))[:, :, :, 0])
481480
.reshape((3, -1))
482481
.T
483482
)
484-
camera_rays = (pixel_list - K[:, 2]) / np.diag(K)
485-
camera_rays[:, -1] = -1
483+
camera_rays = get_camera_rays(focal_length, focal_length, cx, cy, pixel_list)
486484
cameras_list = []
487485
for tran, quat in zip(trans, rand_quats, strict=False):
488486
R = transforms3d.quaternions.quat2mat(quat)

genmetaballs/src/cuda/bindings.cu

Lines changed: 97 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,22 @@
55
#include <nanobind/stl/tuple.h>
66
#include <nanobind/stl/vector.h>
77

8+
#include "core/blender.cuh"
9+
#include "core/camera.cuh"
810
#include "core/confidence.cuh"
911
#include "core/fmb.cuh"
1012
#include "core/geometry.cuh"
13+
#include "core/image.cuh"
1114
#include "core/utils.cuh"
1215

1316
namespace nb = nanobind;
1417

1518
template <typename T, MemoryLocation location>
1619
void bind_array2d(nb::module_& m, const char* name);
20+
template <MemoryLocation location>
21+
void bind_image(nb::module_& m, const char* name);
22+
template <MemoryLocation location>
23+
void bind_image_view(nb::module_& m, const char* name);
1724

1825
NB_MODULE(_genmetaballs_bindings, m) {
1926

@@ -82,18 +89,53 @@ NB_MODULE(_genmetaballs_bindings, m) {
8289
.def_rw("start", &Ray::start)
8390
.def_rw("direction", &Ray::direction);
8491

92+
/*
93+
* Camera module bindings
94+
*/
95+
nb::module_ camera = m.def_submodule("camera", "Camera intrinsics and extrinsics");
96+
nb::class_<Intrinsics>(camera, "Intrinsics")
97+
.def(nb::init<uint32_t, uint32_t, float, float, float, float>(), nb::arg("height"),
98+
nb::arg("width"), nb::arg("fx"), nb::arg("fy"), nb::arg("cx"), nb::arg("cy"))
99+
.def_ro("height", &Intrinsics::height)
100+
.def_ro("width", &Intrinsics::width)
101+
.def_ro("fx", &Intrinsics::fx)
102+
.def_ro("fy", &Intrinsics::fy)
103+
.def_ro("cx", &Intrinsics::cx)
104+
.def_ro("cy", &Intrinsics::cy)
105+
.def("get_ray_direction", &Intrinsics::get_ray_direction,
106+
"Get the direction of the ray going through pixel (px, py) in camera frame",
107+
nb::arg("px"), nb::arg("py"));
108+
109+
/*
110+
* Image module bindings
111+
*/
112+
nb::module_ image = m.def_submodule("image", "Image data structure for GenMetaballs");
113+
bind_image_view<MemoryLocation::HOST>(image, "CPUImageView");
114+
bind_image<MemoryLocation::HOST>(image, "CPUImage");
115+
bind_image_view<MemoryLocation::DEVICE>(image, "GPUImageView");
116+
bind_image<MemoryLocation::DEVICE>(image, "GPUImage");
117+
85118
/*
86119
* Confidence module bindings
87120
*/
88121

89122
nb::module_ confidence = m.def_submodule("confidence");
90123
nb::class_<ZeroParameterConfidence>(confidence, "ZeroParameterConfidence")
91124
.def(nb::init<>())
92-
.def("get_confidence", &ZeroParameterConfidence::get_confidence);
125+
.def("get_confidence", &ZeroParameterConfidence::get_confidence, nb::arg("sumexpd"),
126+
"Get the confidence value for a given sumexpd")
127+
.def("__repr__",
128+
[](const ZeroParameterConfidence& c) { return nb::str("ZeroParameterConfidence()"); });
93129

94130
nb::class_<TwoParameterConfidence>(confidence, "TwoParameterConfidence")
95131
.def(nb::init<float, float>())
96-
.def("get_confidence", &TwoParameterConfidence::get_confidence);
132+
.def_ro("beta4", &TwoParameterConfidence::beta4)
133+
.def_ro("beta5", &TwoParameterConfidence::beta5)
134+
.def("get_confidence", &TwoParameterConfidence::get_confidence, nb::arg("sumexpd"),
135+
"Get the confidence value for a given sumexpd")
136+
.def("__repr__", [](const TwoParameterConfidence& c) {
137+
return nb::str("TwoParameterConfidence(beta4={}, beta5={})").format(c.beta4, c.beta5);
138+
});
97139

98140
/*
99141
* Utils module bindings
@@ -102,6 +144,32 @@ NB_MODULE(_genmetaballs_bindings, m) {
102144
nb::module_ utils = m.def_submodule("utils");
103145
utils.def("sigmoid", sigmoid, nb::arg("x"), "Compute the sigmoid function: 1 / (1 + exp(-x))");
104146

147+
// blender submodule
148+
nb::module_ blender = m.def_submodule("blender");
149+
nb::class_<FourParameterBlender>(blender, "FourParameterBlender")
150+
.def(nb::init<float, float, float, float>())
151+
.def_ro("beta1", &FourParameterBlender::beta1)
152+
.def_ro("beta2", &FourParameterBlender::beta2)
153+
.def_ro("beta3", &FourParameterBlender::beta3)
154+
.def_ro("eta", &FourParameterBlender::eta)
155+
.def("blend", &FourParameterBlender::blend, nb::arg("t"), nb::arg("d"),
156+
"Blend two values with (t,d)")
157+
.def("__repr__", [](const FourParameterBlender& b) {
158+
return nb::str("FourParameterBlender(beta1={}, beta2={}, beta3={}, eta={})")
159+
.format(b.beta1, b.beta2, b.beta3, b.eta);
160+
});
161+
162+
nb::class_<ThreeParameterBlender>(blender, "ThreeParameterBlender")
163+
.def(nb::init<float, float, float>())
164+
.def_ro("beta1", &ThreeParameterBlender::beta1)
165+
.def_ro("beta2", &ThreeParameterBlender::beta2)
166+
.def_ro("eta", &ThreeParameterBlender::eta)
167+
.def("blend", &ThreeParameterBlender::blend, nb::arg("t"), nb::arg("d"),
168+
"Blend two values with (t,d)")
169+
.def("__repr__", [](const ThreeParameterBlender& b) {
170+
return nb::str("ThreeParameterBlender(beta1={}, beta2={}, eta={})")
171+
.format(b.beta1, b.beta2, b.eta);
172+
});
105173
bind_array2d<float, MemoryLocation::HOST>(utils, "CPUFloatArray2D");
106174
bind_array2d<float, MemoryLocation::DEVICE>(utils, "GPUFloatArray2D");
107175

@@ -137,3 +205,30 @@ void bind_array2d(nb::module_& m, const char* name) {
137205
.def_prop_ro("ndim", &Array2D<T, location>::ndim)
138206
.def_prop_ro("size", &Array2D<T, location>::size);
139207
}
208+
209+
template <MemoryLocation location>
210+
void bind_image_view(nb::module_& m, const char* name) {
211+
nb::class_<ImageView<location>>(m, name)
212+
.def(nb::init<const Array2D<float, location>&, const Array2D<float, location>&>(),
213+
nb::arg("confidence"), nb::arg("depth"))
214+
.def_prop_ro("confidence", [](const ImageView<location>& view) { return view.confidence; })
215+
.def_prop_ro("depth", [](const ImageView<location>& view) { return view.depth; })
216+
.def_prop_ro("num_rows", &ImageView<location>::num_rows)
217+
.def_prop_ro("num_cols", &ImageView<location>::num_cols)
218+
.def("__repr__", [=](const ImageView<location>& view) {
219+
return nb::str("{}(height={}, width={})")
220+
.format(name, view.num_rows(), view.num_cols());
221+
});
222+
}
223+
224+
template <MemoryLocation location>
225+
void bind_image(nb::module_& m, const char* name) {
226+
nb::class_<Image<location>>(m, name)
227+
.def(nb::init<uint32_t, uint32_t>(), nb::arg("height"), nb::arg("width"))
228+
.def_prop_ro("num_rows", &Image<location>::num_rows)
229+
.def_prop_ro("num_cols", &Image<location>::num_cols)
230+
.def("as_view", &Image<location>::as_view, "Get a view of the image data as ImageView")
231+
.def("__repr__", [=](const Image<location>& img) {
232+
return nb::str("{}(height={}, width={})").format(name, img.num_rows(), img.num_cols());
233+
});
234+
}
Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,27 @@
11
#pragma once
22

3-
#include "fmb.h"
4-
#include "geometry.h"
3+
#include <cmath>
4+
#include <cuda_runtime.h>
5+
6+
#include "utils.cuh"
7+
8+
struct FourParameterBlender {
9+
float beta1;
10+
float beta2;
11+
float beta3;
12+
float eta;
13+
14+
CUDA_CALLABLE __forceinline__ float blend(float t, float d) const {
15+
return expf((beta1 * d * sigmoid((beta3 / eta) * t)) - ((beta2 / eta) * t));
16+
}
17+
};
518

619
struct ThreeParameterBlender {
720
float beta1;
821
float beta2;
922
float eta;
1023

11-
CUDA_CALLABLE __forceinline__ // TODO inline?
12-
float
13-
blend(float t, float d, const FMB& fmb, const Ray& ray) const;
24+
CUDA_CALLABLE __forceinline__ float blend(float t, float d) const {
25+
return expf((beta1 * d) - ((beta2 / eta) * t));
26+
}
1427
};
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#include <cstdint>
2+
#include <cuda/std/ranges>
3+
#include <cuda_runtime.h>
4+
5+
#include "camera.cuh"
6+
#include "geometry.cuh"
7+
#include "utils.cuh"
8+
9+
CUDA_CALLABLE Vec3D Intrinsics::get_ray_direction(uint32_t px, uint32_t py) const {
10+
auto x = (static_cast<float>(px) - cx) / fx;
11+
auto y = (static_cast<float>(py) - cy) / fy;
12+
return Vec3D{x, y, -1.0f};
13+
}
Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,36 @@
11
#pragma once
22

33
#include <cstdint>
4+
#include <cuda_runtime.h>
5+
6+
#include "geometry.cuh"
7+
#include "utils.cuh"
48

59
struct Intrinsics {
6-
uint32_t height;
7-
uint32_t width;
10+
uint32_t height; // in x direction
11+
uint32_t width; // in y direction
812
float fx;
913
float fy;
1014
float cx;
1115
float cy;
12-
float near;
13-
float far;
16+
17+
// Returns the direction of the ray going through pixel (px, py) in camera frame.
18+
// For efficiency, this function does not check if the pixel is within bounds.
19+
CUDA_CALLABLE Vec3D get_ray_direction(uint32_t px, uint32_t py) const;
20+
21+
// Returns a 2D array of ray directions in camera frame in the specified pixel range
22+
// and store them in the provided buffer. By default, the full image is used
23+
template <MemoryLocation location>
24+
CUDA_CALLABLE Array2D<Vec3D, location>& get_ray_directions(Array2D<Vec3D, location>& buffer,
25+
uint32_t px_start = 0,
26+
uint32_t px_end = UINT32_MAX,
27+
uint32_t py_start = 0,
28+
uint32_t py_end = UINT32_MAX) const {
29+
for (auto i = max(0, px_start); i < min(height, px_end); ++i) {
30+
for (auto j = max(0, py_start); j < min(width, py_end); ++j) {
31+
buffer[i][j] = get_ray_direction(j, i);
32+
}
33+
}
34+
return buffer;
35+
}
1436
};

genmetaballs/src/cuda/core/fmb.cuh

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,4 +107,10 @@ public:
107107
CUDA_CALLABLE ConstIterator end() const {
108108
return ConstIterator(fmbs_ + size_, log_weights_ + size_);
109109
}
110+
CUDA_CALLABLE const FMB& get_fmb(uint32_t idx) const {
111+
return fmbs_[idx];
112+
}
113+
CUDA_CALLABLE size_t size() const {
114+
return size_;
115+
}
110116
};

genmetaballs/src/cuda/core/forward.cu

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ __global__ render_kernel(const Getter fmb_getter, const Blender blender,
4747
template <class Getter, class Intersector, class Blender, class Confidence>
4848
void render_fmbs(const FMBs& fmbs, const Intrinsics& intr, const Pose& extr) {
4949
// initialize the fmb_getter
50-
typename Getter::Getter fmb_getter(fmbs, intr, extr);
50+
typename Getter::Getter fmb_getter(fmbs, extr);
5151
auto kernel = render_kernel<Getter, Intersector, Blender, Confidence>;
5252
kernel<<<NUM_BLOCKS, THREADS_PER_BLOCK>>>(fmb_getter, fmbs, intr, extr);
5353
}

genmetaballs/src/cuda/core/geometry.cuh

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,11 +72,11 @@ public:
7272
return {rot, tran};
7373
}
7474

75-
CUDA_CALLABLE Rotation get_rot() const {
75+
CUDA_CALLABLE const Rotation& get_rot() const {
7676
return rot_;
7777
}
7878

79-
CUDA_CALLABLE Vec3D get_tran() const {
79+
CUDA_CALLABLE const Vec3D& get_tran() const {
8080
return tran_;
8181
}
8282

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
#pragma once
2+
3+
#include <cmath>
4+
#include <cuda_runtime.h>
5+
6+
#include "camera.cuh"
7+
#include "fmb.cuh"
8+
#include "geometry.cuh"
9+
#include "utils.cuh"
10+
11+
// This is the dummy version of getter, where all FMBs are relevant to any ray
12+
template <MemoryLocation location>
13+
struct AllGetter {
14+
FMBScene<location>& scene;
15+
Pose& extr; // Current assumption: rays are in camera frame
16+
17+
CUDA_CALLABLE AllGetter(FMBScene<location>& scene, Pose& extr)
18+
: scene(scene), extr(extr) {}
19+
20+
// It does not bother using the ray, because it simply returns all FMBs
21+
CUDA_CALLABLE FMBScene<location>& get_metaballs(const Ray& ray) const {
22+
return scene;
23+
}
24+
};

0 commit comments

Comments
 (0)