waka_linux
waka_linux

Reputation: 33

Passing cv::Mat by reference

I have a function where instead of returning a cv::Mat I want to pass in a reference to an existing data structure. I am trying to reduce unnecessary copying of cv::Mat Function currently looks like:

cv::Mat HSV::apply(const cv::Mat& input) {
  cv::Mat image, output;

  cv::cvtColor(input, image, cv::COLOR_BGR2HSV);
  cv::inRange(image, m_Low, m_High, output);
  return output;
}

I am trying to convert it to -

void HSV::apply(const cv::Mat& input) {
  cv::Mat image, output;

  cv::cvtColor(input, image, cv::COLOR_BGR2HSV);
  cv::inRange(image, m_Low, m_High, output);
}

Now in another node, I used to call this function as follows:

Detection::Detection(ros::NodeHandle& nh)
    : m_Filter_(std::make_unique<HSV>()), { 
  m_ImageSub = nh.subscribe("/image_raw", 10, &Detector::inputCb, this);
}

void Detector::inputCb(const sensor_msgs::Image::ConstPtr& msg) {
  cv::Mat image = ImageConverter::convertToCvMat(msg);
  cv::Mat finalImage = m_Filter_->apply(image);
}

How can I call the function now if I am passing it by reference?

Upvotes: -1

Views: 513

Answers (2)

Christoph Rackwitz
Christoph Rackwitz

Reputation: 15575

cv::Mat already contain ref-counting. The instance contains some metadata and a reference to backing memory. Multiple instances can use the same backing memory.

Passing one "by value" merely creates a new Mat that uses the same memory as the Mat you passed in.

Same goes for returning a cv::Mat, independently of all the language-level shenanigans and optimizations that C++ offers.

Passing by (C++) reference is fine though. The only thing you're affecting (or could, if it weren't const) with an explicit reference is that the instance itself can be affected by you, in terms of shape/size, element type, etc.

Don't overcomplicate it. Measure first.

Upvotes: 3

john
john

Reputation: 88027

I don't think your converted function is correct. It should be

void HSV::apply(const cv::Mat& input, cv::Mat& output) {
  cv::Mat image;

  cv::cvtColor(input, hsvImage, cv::COLOR_BGR2HSV);
  cv::inRange(image, m_Low, m_High, output);
}

That function would be called like this

void Detector::inputCb(const sensor_msgs::Image::ConstPtr& msg) {
  cv::Mat image = ImageConverter::convertToCvMat(msg);
  cv::Mat finalImage;
  m_Filter_->apply(image, finalImage);
}

However please note that named return value optimization (NRVO) means that no copying occurs when you return output; so this might be an unnecessary change.

Upvotes: 2

Related Questions