-1

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?

waka_linux
  • 33
  • 5
  • cv::Mat already contain refcounting. the only thing you're affecting with an explicit reference is that *the object itself* can be affected by you, in terms of shape/size, element type, etc. – Christoph Rackwitz May 11 '23 at 19:47
  • Other than the premature (and unnecessary) optimization, why are you calling `inRange` on an empty `Mat`? Other than having a side effect of changing `hsvImage` (whatever that is, some global?) both of those variations of `HSV::apply` seem rather useless. – Dan Mašek May 12 '23 at 10:43
  • that part I just autocorrected with `s/hsvImage/image/` assuming there isn't an unseen member variable and OP meant the local – Christoph Rackwitz May 13 '23 at 10:37

2 Answers2

3

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.

Christoph Rackwitz
  • 11,317
  • 4
  • 27
  • 36
2

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.

john
  • 85,011
  • 4
  • 57
  • 81