ros2中传输图像的接口
sensor_msgs/msg/Image
ros2的image接口需要配合而opencv和cv_bridge一起使用。
案例(发布,订阅和保存和显示):
发布:
#include <rclcpp/rclcpp.hpp>
#include <sensor_msgs/msg/image.hpp>
#include <opencv2/opencv.hpp>
#include <cv_bridge/cv_bridge.h>
class ImagePublisher : public rclcpp::Node {
public:
ImagePublisher() : Node("image_publisher") {
RCLCPP_INFO(this->get_logger(), "Image publisher node has been started.");
this->declare_parameter<std::string>("image_abs_path", "");
image_abs_path_ = this->get_parameter("image_abs_path").as_string();
publisher_ = this->create_publisher<sensor_msgs::msg::Image>("camera/image", 10);
timer_ = this->create_wall_timer(std::chrono::seconds(3), std::bind(&ImagePublisher::publishImage, this));
}
private:
void publishImage() {
RCLCPP_INFO(this->get_logger(), "image_abs_path: %s", image_abs_path_.c_str());
cv::Mat image = cv::imread(image_abs_path_, cv::IMREAD_COLOR); // 读取图像文件
if (!image.empty()) {
sensor_msgs::msg::Image msg;
cv_bridge::CvImage(std_msgs::msg::Header(), "bgr8", image).toImageMsg(msg); // 转换为ROS Image消息类型
publisher_->publish(msg); // 发布图像消息
RCLCPP_INFO(this->get_logger(), "Image has been published.");
} else {
RCLCPP_ERROR(this->get_logger(), "Image loading failed!");
}
}
private:
std::string image_abs_path_{""};
rclcpp::Publisher<sensor_msgs::msg::Image>::SharedPtr publisher_;
rclcpp::TimerBase::SharedPtr timer_;
};
int main(int argc, char** argv) {
rclcpp::init(argc, argv);
rclcpp::spin(std::make_shared<ImagePublisher>());
rclcpp::shutdown();
return 0;
}
订阅:
#include <rclcpp/rclcpp.hpp>
#include <sensor_msgs/msg/image.hpp>
#include <opencv2/opencv.hpp>
#include <cv_bridge/cv_bridge.h>
#include <functional>
class ImageSubscriber : public rclcpp::Node {
public:
ImageSubscriber() : Node("image_subscriber") {
declare_parameter("image_save_path", "");
declare_parameter("image_name", "");
image_save_path_ = get_parameter("image_save_path").as_string();
image_name_ = get_parameter("image_name").as_string();
subscription_ = this->create_subscription<sensor_msgs::msg::Image>(
"camera/image",10, std::bind(&ImageSubscriber::image_callback, this, std::placeholders::_1));
}
private:
void image_callback(const sensor_msgs::msg::Image::SharedPtr msg) {
cv_bridge::CvImagePtr cv_ptr;
try {
cv_ptr = cv_bridge::toCvCopy(msg, sensor_msgs::image_encodings::BGR8);
} catch (cv_bridge::Exception& e) {
RCLCPP_ERROR(this->get_logger(), "Failed to convert image: %s", e.what());
return;
}
cv::imshow("Image window", cv_ptr->image);
cv::waitKey(2);
if (image_save_path_!= "" && image_name_!= "") {
cv::imwrite(image_save_path_ + image_name_ + ".jpg", cv_ptr->image);
RCLCPP_INFO(this->get_logger(), "Image saved to %s", (image_save_path_ + image_name_ + ".jpg").c_str());
}
}
private:
std::string image_save_path_{""};
std::string image_name_{""};
rclcpp::Subscription<sensor_msgs::msg::Image>::SharedPtr subscription_;
};
int main(int argc, char *argv[]) {
rclcpp::init(argc, argv);
rclcpp::spin(std::make_shared<ImageSubscriber>());
rclcpp::shutdown();
return 0;
}