Skip to content

Commit 0098d17

Browse files
authored
Merge pull request #18 from rerun-io/andreas/rerun-0.11
Update for Rerun 0.11
2 parents b7439e0 + a9d8650 commit 0098d17

File tree

4 files changed

+92
-60
lines changed

4 files changed

+92
-60
lines changed

CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ if(NOT DEFINED CMAKE_CXX_STANDARD)
99
endif()
1010

1111
include(FetchContent)
12-
FetchContent_Declare(rerun_sdk URL https://github.com/rerun-io/rerun/releases/download/0.10.1/rerun_cpp_sdk.zip)
12+
FetchContent_Declare(rerun_sdk URL https://build.rerun.io/commit/746dbf3/rerun_cpp_sdk.zip) # TODO: 2023-11-28. Update to latest commit.
1313
FetchContent_MakeAvailable(rerun_sdk)
1414

1515
find_package(Eigen3 REQUIRED)

src/batch_adapters.hpp

Lines changed: 0 additions & 41 deletions
This file was deleted.

src/collection_adapters.hpp

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
#pragma once
2+
3+
#include <rerun.hpp>
4+
5+
#include <eigen3/Eigen/Core>
6+
#include <opencv2/core.hpp>
7+
8+
#include <cassert>
9+
10+
// Adapters so we can log eigen vectors as rerun positions:
11+
template <>
12+
struct rerun::CollectionAdapter<rerun::Position3D, std::vector<Eigen::Vector3f>> {
13+
/// Borrow for non-temporary.
14+
Collection<rerun::Position3D> operator()(const std::vector<Eigen::Vector3f>& container) {
15+
return Collection<rerun::Position3D>::borrow(container.data(), container.size());
16+
}
17+
18+
// Do a full copy for temporaries (otherwise the data might be deleted when the temporary is destroyed).
19+
Collection<rerun::Position3D> operator()(std::vector<Eigen::Vector3f>&& container) {
20+
std::vector<rerun::Position3D> positions(container.size());
21+
memcpy(positions.data(), container.data(), container.size() * sizeof(Eigen::Vector3f));
22+
return Collection<rerun::Position3D>::take_ownership(std::move(positions));
23+
}
24+
};
25+
26+
// Adapters so we can log an eigen matrix as rerun positions:
27+
template <>
28+
struct rerun::CollectionAdapter<rerun::Position3D, Eigen::Matrix3Xf> {
29+
// Sanity check that this is binary compatible.
30+
static_assert(
31+
sizeof(rerun::Position3D) ==
32+
sizeof(Eigen::Matrix3Xf::Scalar) * Eigen::Matrix3Xf::RowsAtCompileTime
33+
);
34+
35+
/// Borrow for non-temporary.
36+
Collection<rerun::Position3D> operator()(const Eigen::Matrix3Xf& matrix) {
37+
static_assert(alignof(rerun::Position3D) <= alignof(Eigen::Matrix3Xf::Scalar));
38+
return Collection<rerun::Position3D>::borrow(
39+
// Cast to void because otherwise Rerun will try to do above sanity checks with the wrong type (scalar).
40+
reinterpret_cast<const void*>(matrix.data()),
41+
matrix.cols()
42+
);
43+
}
44+
45+
// Do a full copy for temporaries (otherwise the data might be deleted when the temporary is destroyed).
46+
Collection<rerun::Position3D> operator()(Eigen::Matrix3Xf&& matrix) {
47+
std::vector<rerun::Position3D> positions(matrix.cols());
48+
memcpy(positions.data(), matrix.data(), matrix.size() * sizeof(rerun::Position3D));
49+
return Collection<rerun::Position3D>::take_ownership(std::move(positions));
50+
}
51+
};
52+
53+
// Adapters so we can borrow an OpenCV image easily into Rerun images without copying:
54+
template <>
55+
struct rerun::CollectionAdapter<uint8_t, cv::Mat> {
56+
/// Borrow for non-temporary.
57+
Collection<uint8_t> operator()(const cv::Mat& img) {
58+
assert(
59+
"OpenCV matrix was expected have bit depth CV_U8" && CV_MAT_DEPTH(img.type()) == CV_8U
60+
);
61+
62+
return Collection<uint8_t>::borrow(img.data, img.total() * img.channels());
63+
}
64+
65+
// Do a full copy for temporaries (otherwise the data might be deleted when the temporary is destroyed).
66+
Collection<uint8_t> operator()(cv::Mat&& img) {
67+
assert(
68+
"OpenCV matrix was expected have bit depth CV_U8" && CV_MAT_DEPTH(img.type()) == CV_8U
69+
);
70+
71+
std::vector<uint8_t> img_vec(img.total() * img.channels());
72+
img_vec.assign(img.data, img.data + img.total() * img.channels());
73+
return Collection<uint8_t>::take_ownership(std::move(img_vec));
74+
}
75+
};

src/main.cpp

Lines changed: 16 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
#include <opencv2/imgproc.hpp>
99
#include <rerun.hpp>
1010

11-
#include "batch_adapters.hpp"
11+
#include "collection_adapters.hpp"
1212

1313
std::vector<Eigen::Vector3f> generate_random_points_vector(int num_points) {
1414
std::vector<Eigen::Vector3f> points(num_points);
@@ -18,6 +18,10 @@ std::vector<Eigen::Vector3f> generate_random_points_vector(int num_points) {
1818
return points;
1919
}
2020

21+
rerun::Collection<rerun::TensorDimension> tensor_shape(const cv::Mat& img) {
22+
return {img.rows, img.cols, img.channels()};
23+
};
24+
2125
int main() {
2226
const auto rec = rerun::RecordingStream("rerun_example_cpp");
2327
rec.spawn().exit_on_failure();
@@ -51,8 +55,8 @@ int main() {
5155
rec.log(
5256
"world/camera",
5357
rerun::Transform3D(
54-
rerun::datatypes::Vec3D(camera_position.data()),
55-
rerun::datatypes::Mat3x3(camera_orientation.data())
58+
rerun::Vec3D(camera_position.data()),
59+
rerun::Mat3x3(camera_orientation.data())
5660
)
5761
);
5862

@@ -64,21 +68,15 @@ int main() {
6468
return 1;
6569
}
6670

67-
// Log image to Rerun
68-
cv::cvtColor(img, img, cv::COLOR_BGR2RGB); // Rerun expects RGB format
69-
// NOTE currently we need to construct a vector to log an image, this will change in the future
70-
// see https://github.com/rerun-io/rerun/issues/3794
71-
std::vector<uint8_t> img_vec(img.total() * img.channels());
72-
img_vec.assign(img.data, img.data + img.total() * img.channels());
73-
rec.log(
74-
"image",
75-
rerun::Image(
76-
{static_cast<size_t>(img.rows),
77-
static_cast<size_t>(img.cols),
78-
static_cast<size_t>(img.channels())},
79-
std::move(img_vec)
80-
)
81-
);
71+
// Rerun expects RGB format
72+
cv::cvtColor(img, img, cv::COLOR_BGR2RGB);
73+
74+
// Log image to rerun using the tensor buffer adapter defined in `collection_adapters.hpp`.
75+
rec.log("image0", rerun::Image(tensor_shape(img), rerun::TensorBuffer::u8(img)));
76+
77+
// Or by passing a pointer to the image data.
78+
// The pointer cast here is redundant since `data` is already uint8_t in this case, but if you have e.g. a float image it may be necessary to cast to float*.
79+
rec.log("image1", rerun::Image(tensor_shape(img), reinterpret_cast<const uint8_t*>(img.data)));
8280

8381
return 0;
8482
}

0 commit comments

Comments
 (0)