Skip to content

Commit a33aea0

Browse files
committed
also add color conversion utility node
1 parent 0db3008 commit a33aea0

2 files changed

Lines changed: 147 additions & 1 deletion

File tree

hydra_ros/CMakeLists.txt

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ endif()
1212
option(BUILD_SHARED_LIBS "Build shared libraries" ON)
1313

1414
find_package(ament_cmake REQUIRED)
15+
find_package(CLI11 REQUIRED)
1516
find_package(cv_bridge REQUIRED)
1617
find_package(geometry_msgs REQUIRED)
1718
find_package(gflags REQUIRED)
@@ -92,6 +93,9 @@ ament_target_dependencies(
9293
add_executable(hydra_ros_node app/hydra_node.cpp)
9394
target_link_libraries(hydra_ros_node ${PROJECT_NAME} ${gflags_LIBRARIES})
9495

96+
add_executable(color_to_label_node app/color_to_label_node.cpp)
97+
target_link_libraries(color_to_label_node ${PROJECT_NAME} cv_bridge::cv_bridge CLI11::CLI11)
98+
9599
rclcpp_components_register_node(
96100
${PROJECT_NAME}
97101
PLUGIN
@@ -113,7 +117,7 @@ install(
113117
LIBRARY DESTINATION lib
114118
RUNTIME DESTINATION lib/${PROJECT_NAME}
115119
)
116-
install(TARGETS hydra_ros_node RUNTIME DESTINATION lib/${PROJECT_NAME})
120+
install(TARGETS color_to_label_node hydra_ros_node RUNTIME DESTINATION lib/${PROJECT_NAME})
117121
install(
118122
PROGRAMS app/dsg_file_publisher
119123
app/dsg_republisher
Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
/* -----------------------------------------------------------------------------
2+
* Copyright 2022 Massachusetts Institute of Technology.
3+
* All Rights Reserved
4+
*
5+
* Redistribution and use in source and binary forms, with or without
6+
* modification, are permitted provided that the following conditions are met:
7+
*
8+
* 1. Redistributions of source code must retain the above copyright notice,
9+
* this list of conditions and the following disclaimer.
10+
*
11+
* 2. Redistributions in binary form must reproduce the above copyright notice,
12+
* this list of conditions and the following disclaimer in the documentation
13+
* and/or other materials provided with the distribution.
14+
*
15+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16+
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17+
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18+
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
19+
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20+
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21+
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
22+
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
23+
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24+
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25+
*
26+
* Research was sponsored by the United States Air Force Research Laboratory and
27+
* the United States Air Force Artificial Intelligence Accelerator and was
28+
* accomplished under Cooperative Agreement Number FA8750-19-2-1000. The views
29+
* and conclusions contained in this document are those of the authors and should
30+
* not be interpreted as representing the official policies, either expressed or
31+
* implied, of the United States Air Force or the U.S. Government. The U.S.
32+
* Government is authorized to reproduce and distribute reprints for Government
33+
* purposes notwithstanding any copyright notation herein.
34+
* -------------------------------------------------------------------------- */
35+
#include <hydra/common/semantic_color_map.h>
36+
#include <ianvs/spin_functions.h>
37+
38+
#include <filesystem>
39+
40+
#include <CLI/CLI.hpp>
41+
#include <cv_bridge/cv_bridge.hpp>
42+
#include <cv_bridge/cv_mat_sensor_msgs_image_type_adapter.hpp>
43+
#include <sensor_msgs/msg/image.hpp>
44+
45+
namespace hydra {
46+
47+
using sensor_msgs::msg::Image;
48+
using ImageAdapter = rclcpp::TypeAdapter<cv_bridge::ROSCvMatContainer, Image>;
49+
50+
struct ColorToLabelNode : public rclcpp::Node {
51+
explicit ColorToLabelNode(const std::filesystem::path& colormap_path,
52+
size_t queue_size = 1);
53+
54+
void callback(const std_msgs::msg::Header& header, const cv::Mat& msg);
55+
56+
int32_t default_label;
57+
std::unique_ptr<SemanticColorMap> colormap;
58+
rclcpp::Publisher<Image>::SharedPtr pub;
59+
rclcpp::Subscription<ImageAdapter>::SharedPtr sub;
60+
};
61+
62+
ColorToLabelNode::ColorToLabelNode(const std::filesystem::path& colormap_path,
63+
size_t queue_size)
64+
: Node("color_to_label_node"),
65+
default_label(-1),
66+
colormap(SemanticColorMap::fromCsv(colormap_path)),
67+
pub(create_publisher<Image>("labels", queue_size)) {
68+
const auto cb = [this](const cv_bridge::ROSCvMatContainer& container) {
69+
callback(container.header(), container.cv_mat());
70+
};
71+
72+
sub = create_subscription<ImageAdapter>("colors", queue_size, cb);
73+
}
74+
75+
void ColorToLabelNode::callback(const std_msgs::msg::Header& header,
76+
const cv::Mat& img) {
77+
if (!colormap) {
78+
RCLCPP_ERROR_STREAM(get_logger(), "Colormap is required!");
79+
return;
80+
}
81+
82+
if (img.empty() || img.channels() != 3) {
83+
RCLCPP_ERROR_STREAM(get_logger(), "Failed to decode color image to semantics!");
84+
return;
85+
}
86+
87+
cv::Mat labels(img.size(), CV_32SC1);
88+
for (int r = 0; r < img.rows; ++r) {
89+
for (int c = 0; c < img.cols; ++c) {
90+
const auto& pixel = img.at<cv::Vec3b>(r, c);
91+
const spark_dsg::Color color(pixel[0], pixel[1], pixel[2]);
92+
labels.at<int32_t>(r, c) =
93+
colormap->getLabelFromColor(color).value_or(default_label);
94+
}
95+
}
96+
97+
cv_bridge::CvImage to_pub(header, "32SC1", labels);
98+
const auto msg = to_pub.toImageMsg();
99+
pub->publish(*msg);
100+
}
101+
102+
} // namespace hydra
103+
104+
struct AppArgs {
105+
void add_to_app(CLI::App& app);
106+
107+
std::filesystem::path colormap_path;
108+
int32_t default_label = -1;
109+
};
110+
111+
void AppArgs::add_to_app(CLI::App& app) {
112+
app.add_option("colormap_path", colormap_path)
113+
->required()
114+
->check(CLI::ExistingPath)
115+
->description("Colormap to use");
116+
app.add_option("-l,--default-label", default_label);
117+
}
118+
119+
int main(int argc, char* argv[]) {
120+
CLI::App app("Utility node to convert labels stored by color to integer values");
121+
argv = app.ensure_utf8(argv);
122+
app.allow_extras();
123+
app.get_formatter()->column_width(50);
124+
125+
AppArgs args;
126+
args.add_to_app(app);
127+
try {
128+
app.parse(argc, argv);
129+
} catch (const CLI::ParseError& e) {
130+
return app.exit(e);
131+
}
132+
133+
rclcpp::init(argc, argv);
134+
{ // scope for node
135+
hydra::ColorToLabelNode remapper(args.colormap_path);
136+
ianvs::NodeHandle nh(remapper);
137+
ianvs::spinAndWait(nh);
138+
}
139+
140+
rclcpp::shutdown();
141+
return 0;
142+
}

0 commit comments

Comments
 (0)