2

I have been trying to find some sample codes in C++ to gain insight on how to use cv_bridge for ROS2 however the only examples i'm getting are the ones coming from ROS1. Given that it uses sharedPtr instead of the default ones. Can anyone enlighten me by sharing how to do the similar task said in the cv_bridge tutorials which is subscribing from sensor_msgs::msg::Image and convert it to something that can be manipulated by openCV functions? Any advice is appreciated and I attached my code in this mail.

#include <memory>

#include "rclcpp/rclcpp.hpp"
#include "std_msgs/msg/string.hpp"
#include "sensor_msgs/msg/image.hpp"
#include <image_transport/image_transport.hpp>

#include <memory>
#include "cv_bridge/cv_bridge.h"
#include <opencv2/opencv.hpp>
// #include <sensor_msgs/msg/image_encodings.h>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>


#include "rclcpp/rclcpp.hpp"
#include "std_msgs/msg/string.hpp"
using std::placeholders::_1;

class MinimalSubscriber : public rclcpp::Node
{
  public:
    MinimalSubscriber()
    : Node("minimal_subscriber")
    {
      subscription_ = this->create_subscription<sensor_msgs::msg::Image>(
      "topic", 10, std::bind(&MinimalSubscriber::topic_callback, this, _1));
    }

  private:
    void topic_callback(const sensor_msgs::msg::Image::SharedPtr msg) const
    {     
   cv_bridge::CvImagePtr cv_ptr;

      cv_ptr = cv_bridge::toCvCopy(msg,'BGR8' );
     if (cv_ptr->image.rows > 60 && cv_ptr->image.cols > 60)
      cv::circle(cv_ptr->image, cv::Point(50, 50), 10, CV_RGB(255,0,0));
   
    }
    rclcpp::Subscription<sensor_msgs::msg::Image>::SharedPtr subscription_;
    
};

int main(int argc, char * argv[])
{
  rclcpp::init(argc, argv);
  rclcpp::spin(std::make_shared<MinimalSubscriber>());
  rclcpp::shutdown();
  return 0;
}
Confused One
  • 21
  • 1
  • 2
  • Got it fixed by manually adding dependency in ament_target_dependencies – Confused One Jan 28 '21 at 18:15
  • 1
    Good to know this is working. You should consider using `msg->encoding` instead of the hard-coded `'BGR8'`. If the publisher sends images in the wrong encoding, you can catch errors instead of messing up the image data. – Hermann Mar 10 '21 at 17:08

1 Answers1

0

Maybe the answer is a bit late, but it seems to be a frequently asked question

First of all to build your package with the correct dependencies for OpenCV and CVBridge you need to include them in your CMakeList.txt

find_package(cv_bridge REQUIRED)
find_package(OpenCV REQUIRED)

add_subdirectory (../lib lib)

include_directories(
  include
  ${OpenCV_INCLUDE_DIRS}
)

And include for every target you install:

ament_target_dependencies(node
  "rclcpp"
  "cv_bridge"
)
  
target_link_libraries(node
  ${OpenCV_LIBS}
)

Next include the libraries in your Header file:

#include <cv_bridge/cv_bridge.h>
#include <opencv2/highgui.hpp>

And finally use the cv bridge (with some example code):

cv_bridge::CvImagePtr cv_ptr;

cv_ptr = cv_bridge::toCvCopy(request->depth_image, request->depth_image.encoding);

cv::patchNaNs(cv_ptr->image, 0.0);

// Datatype depends on your camera image encoding!
if (cv_ptr->image.at<float>(row, col) >= 0.001)
{
    depth = cv_ptr->image.at<float>(row, col);
    return true;
}


Andyza
  • 74
  • 3