Ask Your Question
0

Best way not to have to copy a Mat back into an OutputArray

asked 2013-10-02 10:10:18 -0600

changelog gravatar image

I have this code that basically does a "dumb" background subtraction on two frames.

void FrameDifferenceBGS::operator()(cv::InputArray _image, cv::OutputArray _fgmask, double learningRate)
{
  cv::Mat img_input = _image.getMat();

  if(img_input.empty())
    return;

  _fgmask.create(img_input.size(), CV_8U);
  cv::Mat img_foreground = _fgmask.getMat();

  if(img_input_prev.empty())
  {
    img_input.copyTo(img_input_prev);
    return;
  }

  cv::absdiff(img_input_prev, img_input, img_foreground);

  if(img_foreground.channels() == 3)
    cv::cvtColor(img_foreground, img_foreground, CV_BGR2GRAY);

  if(enableThreshold)
    cv::threshold(img_foreground, img_foreground, threshold, 255, cv::THRESH_BINARY);

  if(showOutput)
    cv::imshow("Frame Difference", img_foreground);

  img_input.copyTo(img_input_prev);
  img_foreground.copyTo(_fgmask);
  firstTime = false;
}

If I don't add img_foreground.copyTo(_fgmask) in the end, the output array isn't updated with the result of img_foreground, resulting on a black image when this is called.

What am I doing wrong / should be doing here?

edit retag flag offensive close merge delete

3 answers

Sort by ยป oldest newest most voted
2

answered 2013-10-03 02:15:00 -0600

Michael Burdinov gravatar image

I think that the "Best way not to have to copy a Mat back into an OutputArray" is not using OutputArray in the first place. InputArray and OutputArray are used by OpenCV functions that can work with various different types. For example output can be either vector<point> or Mat. OpenCV users can simply pass Mat to such function. You shouldn't use those InputArray or OutputArray unless you have some kind of polymorphic behavior that you must implement. It seems to me that this is not the case.

edit flag offensive delete link more

Comments

I'm doing it this way because I need it to behave the same way as any other instance of BackgroundSubtractor.

changelog gravatar imagechangelog ( 2013-10-03 02:54:48 -0600 )edit

I see. Then you should take @Moster advice and use _image and _fgmask directly. There no need to create Mat headers for them. As far as I know you can pass OutputArray to parameter that expect InputArray without any problem.

Also you don't need to call create() function, OpenCV will do this for you whenever needed.

Michael Burdinov gravatar imageMichael Burdinov ( 2013-10-03 04:40:15 -0600 )edit
2

answered 2013-10-02 11:10:45 -0600

Moster gravatar image

updated 2013-10-02 11:20:49 -0600

I guess you are giving your function 2 Mat objects as an input, right?

Wouldnt it work, if you just use your outputArray in the last function that manipulates the img_foreground like this:

cv::threshold(img_foreground, _fgmask.getMat(), threshold, 255, cv::THRESH_BINARY);

edit: just using _fgmask instead of _fgmask.getMat() should also work. I havent used cv::OutputArray yet, but I dont see why not.

edit flag offensive delete link more
1

answered 2019-11-16 04:31:36 -0600

Freeman gravatar image

The more efficient approach is not to copy a Mat back into an OutputArray output, but to get a reference to the (previously sized) matrix and populate it:

cv::Mat& A = output.getMatRef();
edit flag offensive delete link more

Question Tools

1 follower

Stats

Asked: 2013-10-02 10:10:18 -0600

Seen: 5,262 times

Last updated: Nov 16 '19