Skip to content

Commit e8af6cc

Browse files
Add Holoviz feature samples (#452)
* Add Holoviz feature samples - sRGB example - vsync example This is using cookiecutter to generate the various examples from a template. Signed-off-by: Andreas Heumann <aheumann@nvidia.com> * Update applications/holoviz/template/cookiecutter-holoviz/{{cookiecutter.project_slug}}/README.md Minor spelling fix Signed-off-by: Tom Birdsong <40648863+tbirdso@users.noreply.github.com> * Update applications/holoviz/holoviz_srgb/README.md Minor spelling fix Signed-off-by: Tom Birdsong <40648863+tbirdso@users.noreply.github.com> --------- Signed-off-by: Andreas Heumann <aheumann@nvidia.com> Signed-off-by: Tom Birdsong <40648863+tbirdso@users.noreply.github.com> Co-authored-by: Tom Birdsong <40648863+tbirdso@users.noreply.github.com>
1 parent fb8fb56 commit e8af6cc

23 files changed

+1044
-0
lines changed

applications/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,8 @@ add_subdirectory(h264)
5353
add_holohub_application(high_speed_endoscopy DEPENDS
5454
OPERATORS emergent_source)
5555

56+
add_subdirectory(holoviz)
57+
5658
add_holohub_application(hyperspectral_segmentation)
5759

5860
add_holohub_application(multiai_endoscopy)

applications/holoviz/CMakeLists.txt

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2+
# SPDX-License-Identifier: Apache-2.0
3+
#
4+
# Licensed under the Apache License, Version 2.0 (the "License");
5+
# you may not use this file except in compliance with the License.
6+
# You may obtain a copy of the License at
7+
#
8+
# http://www.apache.org/licenses/LICENSE-2.0
9+
#
10+
# Unless required by applicable law or agreed to in writing, software
11+
# distributed under the License is distributed on an "AS IS" BASIS,
12+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
# See the License for the specific language governing permissions and
14+
# limitations under the License.
15+
16+
add_holohub_application(holoviz_srgb)
17+
add_holohub_application(holoviz_vsync)
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
# SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2+
# SPDX-License-Identifier: Apache-2.0
3+
#
4+
# Licensed under the Apache License, Version 2.0 (the "License");
5+
# you may not use this file except in compliance with the License.
6+
# You may obtain a copy of the License at
7+
#
8+
# http://www.apache.org/licenses/LICENSE-2.0
9+
#
10+
# Unless required by applicable law or agreed to in writing, software
11+
# distributed under the License is distributed on an "AS IS" BASIS,
12+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
# See the License for the specific language governing permissions and
14+
# limitations under the License.
15+
16+
cmake_minimum_required(VERSION 3.20)
17+
18+
project(holoviz_srgb)
19+
20+
find_package(holoscan 2.3 REQUIRED CONFIG
21+
PATHS "/opt/nvidia/holoscan" "/workspace/holoscan-sdk/install")
22+
23+
add_executable(holoviz_srgb
24+
holoviz_srgb.cpp
25+
)
26+
27+
target_link_libraries(holoviz_srgb
28+
PRIVATE
29+
holoscan::core
30+
holoscan::ops::holoviz
31+
)
32+
33+
if(BUILD_TESTING)
34+
# Add test
35+
add_test(NAME holoviz_srgb_test
36+
COMMAND holoviz_srgb
37+
--count=10
38+
WORKING_DIRECTORY ${CMAKE_BINARY_DIR})
39+
set_tests_properties(holoviz_srgb_test PROPERTIES
40+
PASS_REGULAR_EXPRESSION "Application has finished running.")
41+
endif()
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
# Holoviz sRGB
2+
3+
![](holoviz_srgb.png)<br>
4+
This application demonstrates the handling of the sRGB color space supported by the Holoviz operator.
5+
6+
The Holoviz operator can convert sRGB input images to linear color space before rendering and also can convert from linear color space to sRGB before writing to the frame buffer.
7+
8+
sRGB color space can be enabled for input images and for the frame buffer independently. By default, the sRGB color space is disabled for both.
9+
10+
By default, the Holoviz operator is auto detecting the input image format. Auto detection always assumes linear color space for input images. To change this to sRGB color space explicitly set the `image_format_` member of the input spec for that input image to a format ending with `SRGB`:
11+
12+
```cpp
13+
// By default the image format is auto detected. Auto detection assumes linear color space,
14+
// but we provide an sRGB encoded image. Create an input spec and change the image format to
15+
// sRGB.
16+
ops::HolovizOp::InputSpec input_spec("image", ops::HolovizOp::InputType::COLOR);
17+
input_spec.image_format_ = ops::HolovizOp::ImageFormat::R8G8B8_SRGB;
18+
19+
auto holoviz = make_operator<ops::HolovizOp>(
20+
"holoviz",
21+
Arg("tensors", std::vector<ops::HolovizOp::InputSpec>{input_spec}));
22+
```
23+
24+
By default, the frame buffer is using linear color space. To use the sRGB color space, set the `framebuffer_srbg` argument of the Holoviz operator to `true`:
25+
26+
```cpp
27+
auto holoviz = make_operator<ops::HolovizOp>(
28+
"holoviz",
29+
// enable the sRGB frame buffer
30+
Arg("framebuffer_srbg", true));
31+
```
32+
33+
## Run Instructions
34+
35+
To build and start the application:
36+
37+
```bash
38+
./dev_container build_and_run holoviz_srgb
39+
```
Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
/*
2+
* SPDX-FileCopyrightText: Copyright (c) 2023 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
3+
* SPDX-License-Identifier: Apache-2.0
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
#include <holoscan/holoscan.hpp>
19+
#include <holoscan/operators/holoviz/holoviz.hpp>
20+
#include <string>
21+
22+
#include <getopt.h>
23+
24+
namespace holoscan::ops {
25+
26+
class SourceOp : public Operator {
27+
public:
28+
HOLOSCAN_OPERATOR_FORWARD_ARGS(SourceOp);
29+
30+
void initialize() override {
31+
shape_ = nvidia::gxf::Shape{64, 64, 3};
32+
element_type_ = nvidia::gxf::PrimitiveType::kUnsigned8;
33+
element_size_ = nvidia::gxf::PrimitiveTypeSize(element_type_);
34+
strides_ = nvidia::gxf::ComputeTrivialStrides(shape_, element_size_);
35+
36+
data_.resize(strides_[0] * shape_.dimension(0));
37+
38+
// create an RGB image with random values
39+
for (size_t y = 0; y < shape_.dimension(0); ++y) {
40+
for (size_t x = 0; x < shape_.dimension(1); ++x) {
41+
for (size_t component = 0; component < shape_.dimension(2); ++component) {
42+
float value;
43+
switch (component) {
44+
case 0:
45+
value = float(x) / shape_.dimension(1);
46+
break;
47+
case 1:
48+
value = float(y) / shape_.dimension(0);
49+
break;
50+
case 2:
51+
value = 1.f - (float(x) / shape_.dimension(1));
52+
break;
53+
default:
54+
value = 1.f;
55+
break;
56+
}
57+
58+
// inverse sRGB EOTF conversion from linear to non-linear
59+
// https://registry.khronos.org/DataFormat/specs/1.3/dataformat.1.3.html
60+
if (value < 0.04045f) {
61+
value /= 12.92f;
62+
} else {
63+
value = std::pow(((value + 0.055f) / 1.055f), 2.4f);
64+
}
65+
66+
data_[y * strides_[0] + x * strides_[1] + component] = uint8_t((value * 255.f) + 0.5f);
67+
}
68+
}
69+
}
70+
71+
Operator::initialize();
72+
}
73+
74+
void setup(OperatorSpec& spec) override { spec.output<holoscan::gxf::Entity>("output"); }
75+
76+
void compute(InputContext& input, OutputContext& output, ExecutionContext& context) override {
77+
auto entity = holoscan::gxf::Entity::New(&context);
78+
auto tensor = static_cast<nvidia::gxf::Entity&>(entity).add<nvidia::gxf::Tensor>("image");
79+
tensor.value()->wrapMemory(shape_,
80+
element_type_,
81+
element_size_,
82+
strides_,
83+
nvidia::gxf::MemoryStorageType::kSystem,
84+
data_.data(),
85+
nullptr);
86+
output.emit(entity, "output");
87+
}
88+
89+
private:
90+
nvidia::gxf::Shape shape_;
91+
nvidia::gxf::PrimitiveType element_type_;
92+
uint64_t element_size_;
93+
nvidia::gxf::Tensor::stride_array_t strides_;
94+
std::vector<uint8_t> data_;
95+
};
96+
97+
} // namespace holoscan::ops
98+
99+
class App : public holoscan::Application {
100+
public:
101+
explicit App(int count) : count_(count) {}
102+
App() = delete;
103+
104+
void compose() override {
105+
using namespace holoscan;
106+
107+
auto source =
108+
make_operator<ops::SourceOp>("source",
109+
// stop application count
110+
make_condition<CountCondition>("count-condition", count_));
111+
112+
// By default the image format is auto detected. Auto detection assumes linear color space,
113+
// but we provide an sRGB encoded image. Create an input spec and change the image format to
114+
// sRGB.
115+
ops::HolovizOp::InputSpec input_spec("image", ops::HolovizOp::InputType::COLOR);
116+
input_spec.image_format_ = ops::HolovizOp::ImageFormat::R8G8B8_SRGB;
117+
118+
auto holoviz = make_operator<ops::HolovizOp>(
119+
"holoviz",
120+
Arg("tensors", std::vector<ops::HolovizOp::InputSpec>{input_spec}),
121+
// enable the sRGB frame buffer
122+
Arg("framebuffer_srgb", true),
123+
Arg("window_title", std::string("Holoviz sRGB")),
124+
Arg("cuda_stream_pool", make_resource<CudaStreamPool>("cuda_stream_pool", 0, 0, 0, 1, 5)));
125+
126+
add_flow(source, holoviz, {{"output", "receivers"}});
127+
}
128+
129+
const int count_;
130+
};
131+
132+
int main(int argc, char** argv) {
133+
int count = -1;
134+
135+
struct option long_options[] = {
136+
{"help", no_argument, 0, 'h'}, {"count", optional_argument, 0, 'c'}, {0, 0, 0, 0}};
137+
138+
// parse options
139+
while (true) {
140+
int option_index = 0;
141+
142+
const int c = getopt_long(argc, argv, "hc:", long_options, &option_index);
143+
144+
if (c == -1) { break; }
145+
146+
const std::string argument(optarg ? optarg : "");
147+
switch (c) {
148+
case 'h':
149+
std::cout << "Holoscan ClaraViz volume renderer."
150+
<< "Usage: " << argv[0] << " [options]" << std::endl
151+
<< "Options:" << std::endl
152+
<< " -h, --help Display this information" << std::endl
153+
<< " -c <COUNT>, --count <COUNT> execute operators <COUNT> times (default "
154+
"'-1' for unlimited)"
155+
<< std::endl;
156+
return 0;
157+
158+
case 'c':
159+
count = stoi(argument);
160+
break;
161+
162+
case '?':
163+
// unknown option, error already printed by getop_long
164+
break;
165+
default:
166+
holoscan::log_error("Unhandled option '{}'", static_cast<char>(c));
167+
}
168+
}
169+
170+
auto app = holoscan::make_application<App>(count);
171+
app->run();
172+
173+
holoscan::log_info("Application has finished running.");
174+
return 0;
175+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
../template/cookiecutter-holoviz/holoviz_srgb.png
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
{
2+
"application": {
3+
"name": "Holoviz sRGB",
4+
"authors": [
5+
{
6+
"name": "Holoscan Team",
7+
"affiliation": "NVIDIA"
8+
}
9+
],
10+
"language": "C++",
11+
"version": "1.0.0",
12+
"changelog": {
13+
"1.0": "Initial Release"
14+
},
15+
"holoscan_sdk": {
16+
"minimum_required_version": "2.3",
17+
"tested_versions": [
18+
"2.3"
19+
]
20+
},
21+
"platforms": [
22+
"amd64",
23+
"arm64"
24+
],
25+
"tags": [
26+
"Holoviz sRGB"
27+
],
28+
"ranking": 1,
29+
"dependencies": {},
30+
"run": {
31+
"command": "<holohub_app_bin>/holoviz/holoviz_srgb",
32+
"workdir": "holohub_bin"
33+
}
34+
}
35+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
# SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2+
# SPDX-License-Identifier: Apache-2.0
3+
#
4+
# Licensed under the Apache License, Version 2.0 (the "License");
5+
# you may not use this file except in compliance with the License.
6+
# You may obtain a copy of the License at
7+
#
8+
# http://www.apache.org/licenses/LICENSE-2.0
9+
#
10+
# Unless required by applicable law or agreed to in writing, software
11+
# distributed under the License is distributed on an "AS IS" BASIS,
12+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
# See the License for the specific language governing permissions and
14+
# limitations under the License.
15+
16+
cmake_minimum_required(VERSION 3.20)
17+
18+
project(holoviz_vsync)
19+
20+
find_package(holoscan 2.3 REQUIRED CONFIG
21+
PATHS "/opt/nvidia/holoscan" "/workspace/holoscan-sdk/install")
22+
23+
add_executable(holoviz_vsync
24+
holoviz_vsync.cpp
25+
)
26+
27+
target_link_libraries(holoviz_vsync
28+
PRIVATE
29+
holoscan::core
30+
holoscan::ops::holoviz
31+
)
32+
33+
if(BUILD_TESTING)
34+
# Add test
35+
add_test(NAME holoviz_vsync_test
36+
COMMAND holoviz_vsync
37+
--count=10
38+
WORKING_DIRECTORY ${CMAKE_BINARY_DIR})
39+
set_tests_properties(holoviz_vsync_test PROPERTIES
40+
PASS_REGULAR_EXPRESSION "Application has finished running.")
41+
endif()
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# Holoviz vsync
2+
3+
![](holoviz_vsync.png)<br>
4+
This application demonstrates the capability of the Holoviz operator to wait for the vertical blank of the display before updating the current image. It prints the displayed frames per second to the console, if sync to vertical blank is enabled the frames per second are capped to the display refresh rate.
5+
6+
To enable syncing to vertical blank set the `vsync` parameter of the Holoviz operator to `true`:
7+
8+
```cpp
9+
auto holoviz = make_operator<ops::HolovizOp>(
10+
"holoviz",
11+
// enable synchronization to vertical blank
12+
Arg("vsync", true));
13+
```
14+
15+
By default, the Holoviz operator is not syncing to the vertical blank of the display.
16+
17+
## Run Instructions
18+
19+
To build and start the application:
20+
21+
```bash
22+
./dev_container build_and_run holoviz_vsync
23+
```

0 commit comments

Comments
 (0)