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

C++ examples & roundtrip tests for image/segmentation-image/depth-image/tensor #3899

Merged
merged 24 commits into from
Oct 18, 2023
Merged
Show file tree
Hide file tree
Changes from 18 commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
79466db
Implement annotation_context_connections for C++
Wumpf Oct 17, 2023
e261fd1
annotation_context_segmentation sample for C++
Wumpf Oct 17, 2023
a62b9dc
unit test for SegmentationImage behavior
Wumpf Oct 17, 2023
6de4c7e
remove extremely helpful comment to satisfy spellchecker
Wumpf Oct 17, 2023
2f746b7
fix extra curly
Wumpf Oct 17, 2023
7d5a367
fix extra whitespaces on embedded examples
Wumpf Oct 17, 2023
ee4c7e2
add depth image and depth image simple examples for C++
Wumpf Oct 17, 2023
e8d0159
shorten examples with images a bit
Wumpf Oct 17, 2023
70b28fa
image_simple example
Wumpf Oct 17, 2023
cc09900
Merge remote-tracking branch 'origin/main' into andreas/cpp/images
Wumpf Oct 17, 2023
8ebbc74
More validation, add image tests
Wumpf Oct 17, 2023
b480315
segmentation image example for C++
Wumpf Oct 17, 2023
6993998
add roundtrip tests for depth & segmentation image, stubbed image bec…
Wumpf Oct 17, 2023
5abdf27
enable image and tensor roundtrip test
Wumpf Oct 17, 2023
19ee63e
tensor_simple example for c++
Wumpf Oct 17, 2023
87c8823
potentially missing headers
Wumpf Oct 17, 2023
d233e4e
shorten tensor-like archetype constructors by taking dimensions & dat…
Wumpf Oct 17, 2023
7a5605d
fix ci issues
Wumpf Oct 17, 2023
450902f
improve channel name comments and add overload for directly passing w…
Wumpf Oct 18, 2023
b7153a9
remove width,height ctors again
Wumpf Oct 18, 2023
2646509
rename with_names to with_dim_names
Wumpf Oct 18, 2023
143fe7e
rename to half_from_float
Wumpf Oct 18, 2023
3258eeb
fix ambiguous image size comments
Wumpf Oct 18, 2023
c324163
cpp formatting
Wumpf Oct 18, 2023
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
3 changes: 2 additions & 1 deletion crates/re_types/definitions/rerun/archetypes/depth_image.fbs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ namespace rerun.archetypes;
/// \example depth_image_simple !api title="Simple example" image="https://static.rerun.io/depth_image_simple/9598554977873ace2577bddd79184ac120ceb0b0/1200w.png"
/// \example depth_image_3d title="Depth to 3D example" image="https://static.rerun.io/depth_image_3d/f78674bdae0eb25786c6173307693c5338f38b87/1200w.png"
table DepthImage (
"attr.rust.derive": "PartialEq"
"attr.rust.derive": "PartialEq",
"attr.cpp.no_field_ctors"
) {
// --- Required ---

Expand Down
3 changes: 2 additions & 1 deletion crates/re_types/definitions/rerun/archetypes/image.fbs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ namespace rerun.archetypes;
///
/// \example image_simple image="https://static.rerun.io/image_simple/06ba7f8582acc1ffb42a7fd0006fad7816f3e4e4/1200w.png"
table Image (
"attr.rust.derive": "PartialEq"
"attr.rust.derive": "PartialEq",
"attr.cpp.no_field_ctors"
) {
// --- Required ---

Expand Down
2 changes: 1 addition & 1 deletion crates/re_types/src/archetypes/image_ext.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ impl Image {
assign_if_none(&mut data.shape[non_empty_dim_inds[1]].name, "width");
}
3 => match data.shape[non_empty_dim_inds[2]].size {
3 | 4 => {
1 | 3 | 4 => {
assign_if_none(&mut data.shape[non_empty_dim_inds[0]].name, "height");
assign_if_none(&mut data.shape[non_empty_dim_inds[1]].name, "width");
assign_if_none(&mut data.shape[non_empty_dim_inds[2]].name, "depth");
Expand Down
17 changes: 7 additions & 10 deletions docs/code-examples/annotation_context_segmentation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

#include <rerun.hpp>

#include <algorithm>

int main() {
auto rec = rerun::RecordingStream("rerun_example_annotation_context_connections");
rec.connect("127.0.0.1:9876").throw_on_failure();
Expand All @@ -19,17 +21,12 @@ int main() {
const int HEIGHT = 8;
const int WIDTH = 12;
std::vector<uint8_t> data(WIDTH * HEIGHT, 0);
for (auto y = 0; y < 4; ++y) { // top half
auto row = data.begin() + y * WIDTH;
std::fill(row, row + 6, 1); // left half
for (auto y = 0; y < 4; ++y) { // top half
std::fill_n(data.begin() + y * WIDTH, 6, 1); // left half
}
for (auto y = 4; y < 8; ++y) { // bottom half
auto row = data.begin() + y * WIDTH;
std::fill(row + 6, row + 12, 2); // right half
for (auto y = 4; y < 8; ++y) { // bottom half
std::fill_n(data.begin() + y * WIDTH + 6, 6, 2); // right half
}

rec.log(
"segmentation/image",
rerun::SegmentationImage(rerun::TensorData({HEIGHT, WIDTH}, std::move(data)))
);
rec.log("segmentation/image", rerun::SegmentationImage({HEIGHT, WIDTH}, std::move(data)));
}
35 changes: 35 additions & 0 deletions docs/code-examples/depth_image_3d.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// Create and log a depth image.

#include <rerun.hpp>

#include <algorithm>

int main() {
auto rec = rerun::RecordingStream("rerun_example_depth_image");
rec.connect("127.0.0.1:9876").throw_on_failure();

// Create a synthetic depth image.
const int HEIGHT = 8;
const int WIDTH = 12;
std::vector<uint16_t> data(WIDTH * HEIGHT, 65535);
for (auto y = 0; y < 4; ++y) { // top half
std::fill_n(data.begin() + y * WIDTH, 6, 20000); // left half
}
for (auto y = 4; y < 8; ++y) { // bottom half
std::fill_n(data.begin() + y * WIDTH + 6, 6, 45000); // right half
}

// If we log a pinhole camera model, the depth gets automatically back-projected to 3D
rec.log(
"world/camera",
rerun::Pinhole::focal_length_and_resolution(
{20.0f, 20.0f},
{static_cast<float>(WIDTH), static_cast<float>(HEIGHT)}
)
);

rec.log(
"world/camera/depth",
rerun::DepthImage({HEIGHT, WIDTH}, std::move(data)).with_meter(10000.0)
);
}
23 changes: 23 additions & 0 deletions docs/code-examples/depth_image_simple.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// Create and log a depth image.

#include <rerun.hpp>

#include <algorithm>

int main() {
auto rec = rerun::RecordingStream("rerun_example_depth_image");
rec.connect("127.0.0.1:9876").throw_on_failure();

// create a synthetic depth image.
const int HEIGHT = 8;
const int WIDTH = 12;
std::vector<uint16_t> data(WIDTH * HEIGHT, 65535);
for (auto y = 0; y < 4; ++y) { // top half
std::fill_n(data.begin() + y * WIDTH, 6, 20000); // left half
}
for (auto y = 4; y < 8; ++y) { // bottom half
std::fill_n(data.begin() + y * WIDTH + 6, 6, 45000); // right half
}

rec.log("depth", rerun::DepthImage({HEIGHT, WIDTH}, std::move(data)).with_meter(10000.0));
}
25 changes: 25 additions & 0 deletions docs/code-examples/image_simple.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// Create and log a image.

#include <rerun.hpp>

int main() {
auto rec = rerun::RecordingStream("rerun_example_image_simple");
rec.connect("127.0.0.1:9876").throw_on_failure();

// Create a synthetic image.
const int HEIGHT = 8;
const int WIDTH = 12;
std::vector<uint8_t> data(WIDTH * HEIGHT * 3, 0);
for (size_t i = 0; i < data.size(); i += 3) {
data[i] = 255;
}
for (auto y = 0; y < 4; ++y) { // top half
auto row = data.begin() + y * WIDTH * 3;
for (auto i = 0; i < 6 * 3; i += 3) { // left half
row[i] = 0;
row[i + 1] = 255;
}
}

rec.log("image", rerun::Image({HEIGHT, WIDTH, 3}, std::move(data)));
}
5 changes: 0 additions & 5 deletions docs/code-examples/roundtrips.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,16 +23,11 @@
"any_values": ["cpp", "rust"], # Not yet implemented
"asset3d_out_of_tree": ["cpp"], # TODO(#2919): Not yet implemented in C++
"custom_data": ["cpp"], # TODO(#2919): Not yet implemented in C++
"depth_image_3d": ["cpp"], # TODO(#2919): Not yet implemented in C++
"depth_image_simple": ["cpp"], # TODO(#2919): Not yet implemented in C++
"extra_values": ["cpp", "rust"], # Missing examples
"image_advanced": ["cpp", "rust"], # Missing examples
"image_simple": ["cpp"], # TODO(#2919): Not yet implemented in C++
"log_line": ["cpp", "rust", "py"], # Not a complete example -- just a single log line
"quick_start_connect": ["cpp"], # TODO(#3870): Not yet implemented in C++
"scalar_multiple_plots": ["cpp"], # TODO(#2919): Not yet implemented in C++
"segmentation_image_simple": ["cpp"], # TODO(#2919): Not yet implemented in C++
"tensor_simple": ["cpp"], # TODO(#2919): Not yet implemented in C++
"text_log_integration": ["cpp"], # TODO(#2919): Not yet implemented in C++

# This is this script, it's not an example.
Expand Down
32 changes: 32 additions & 0 deletions docs/code-examples/segmentation_image_simple.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// Create and log a segmentation image.

#include <rerun.hpp>

#include <algorithm>

int main() {
auto rec = rerun::RecordingStream("rerun_example_annotation_context_connections");
rec.connect("127.0.0.1:9876").throw_on_failure();

// Create a segmentation image
const int HEIGHT = 8;
const int WIDTH = 12;
std::vector<uint8_t> data(WIDTH * HEIGHT, 0);
for (auto y = 0; y < 4; ++y) { // top half
std::fill_n(data.begin() + y * WIDTH, 6, 1); // left half
}
for (auto y = 4; y < 8; ++y) { // bottom half
std::fill_n(data.begin() + y * WIDTH + 6, 6, 2); // right half
}

// create an annotation context to describe the classes
rec.log_timeless(
"/",
rerun::AnnotationContext({
rerun::AnnotationInfo(1, "red", rerun::Rgba32(255, 0, 0)),
rerun::AnnotationInfo(2, "green", rerun::Rgba32(0, 255, 0)),
})
);

rec.log("image", rerun::SegmentationImage({HEIGHT, WIDTH}, std::move(data)));
}
21 changes: 21 additions & 0 deletions docs/code-examples/tensor_simple.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// Create and log a tensor.

#include <rerun.hpp>

#include <random>

int main() {
auto rec = rerun::RecordingStream("rerun_example_tensor_simple");
rec.connect("127.0.0.1:9876").throw_on_failure();

std::default_random_engine gen;
std::uniform_int_distribution<uint8_t> dist(0, 255);

std::vector<uint8_t> data(8 * 6 * 3 * 5);
std::generate(data.begin(), data.end(), [&] { return dist(gen); });

rec.log(
"tensor",
rerun::Tensor({8, 6, 3, 5}, data).with_names({"batch", "channel", "height", "width"})
);
}
17 changes: 7 additions & 10 deletions rerun_cpp/src/rerun/archetypes/annotation_context.hpp

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

61 changes: 59 additions & 2 deletions rerun_cpp/src/rerun/archetypes/depth_image.hpp

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

47 changes: 47 additions & 0 deletions rerun_cpp/src/rerun/archetypes/depth_image_ext.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
#include "../error.hpp"
#include "depth_image.hpp"

// Uncomment for better auto-complete while editing the extension.
// #define EDIT_EXTENSION

namespace rerun {
namespace archetypes {

#ifdef EDIT_EXTENSION
// [CODEGEN COPY TO HEADER START]

/// New DepthImage from dimensions and tensor buffer.
///
/// Sets dimensions to width/height if they are not specified.
/// Calls Error::handle() if the shape is not rank 2.
DepthImage(
std::vector<rerun::datatypes::TensorDimension> shape,
rerun::datatypes::TensorBuffer buffer
)
: DepthImage(rerun::datatypes::TensorData(std::move(shape), std::move(buffer))) {}

/// New depth image from tensor data.
///
/// Sets dimensions to width/height if they are not specified.
/// Calls Error::handle() if the shape is not rank 2.
explicit DepthImage(rerun::components::TensorData _data);
// [CODEGEN COPY TO HEADER END]
#endif

DepthImage::DepthImage(rerun::components::TensorData _data) : data(std::move(_data)) {
auto& shape = data.data.shape;
if (shape.size() != 2) {
Error(ErrorCode::InvalidTensorDimension, "Shape must be rank 2.").handle();
return;
}

if (!shape[0].name.has_value()) {
shape[0].name = "height";
}
if (!shape[1].name.has_value()) {
shape[1].name = "width";
}
}

} // namespace archetypes
} // namespace rerun
Loading