14

The OpenCV function cvtColor converts the color space of a matrix (e.g. from RGB to grayscale). The function's C++ signature is

void cvtColor(InputArray src, OutputArray dst, int code, int dstCn=0 )

Can this function be used convert a matrix in place, i.e. with src the same object as dst?

cv::Mat mat = getColorImage();
cvtColor(mat, mat, CV_RGB2GRAY);

(I'm aware that either way, as the destination has a different number of channels than the source, it will still need to allocate a new block of memory for the destination.)

More generally, is there a convention within the OpenCV API to determine when a function may be used in this way?

Tim MB
  • 4,413
  • 4
  • 38
  • 48
  • 1
    It can be done when the source and destination have same number of channels. e.g RGB to YUV, RGB to YCbCr, or vice versa etc... – sgarizvi Mar 11 '13 at 17:23

3 Answers3

14

Maybe it’s too late for answering, but I want to say that I don’t agree with some things that have been written here.
You can place the same exact Mat as source and destination, with no problem, even if the destination matrix has not “the same number of channel”, or even if the dest matrix has not been created yet.
OpenCV programmers designed it thoroughly.
All users of this function have to do is to take care that the source Mat is correct, as to number of channels and type of data, and remember that after the function call they could change.

The proof comes from looking at source code, on line 2406, just the first line inside the cv::cvtColor(…) function,

Mat src = _src.getMat();

is called, then Mat dst is created (and dst=_dst=_scr).
So the situation inside cv::cvtColor(…) is the following when making in-place calling: src points to the old matrix, _src, _dst, dst all point to the same new allocated matrix, which will be the destination matrix.
This means than now new variables src and dst (not the ones from function call _src and _dst) are ready to be passed to the real converting function.
When function void cv::cvtColor(…) is done, src is disposed and _src, _dst and dst all point to the same Mat and refcount of _dst will go to 1.

Dimitar
  • 4,402
  • 4
  • 31
  • 47
Giuseppe Dini
  • 762
  • 7
  • 19
  • Yes I agree with this although I don't have time to actually test it at the moment. But as I can see, passing by InputArray is equivalent to passing by value with cv::Mat, which means two matrices point to the same set of data. If there is a need to reallocate then this will not affect the original matrix header that points to the original data. – Tim MB Jan 04 '16 at 12:29
  • Yes and after reallocation the new matrix is the destination Mat, while the source Mat is temporary and will be lost when the function ends. I've just tested it and this in-place scheme seems to be usual (almost a standard) in the OpenCv framework. – Giuseppe Dini Jan 04 '16 at 18:37
3

If you have a look at the code here, you will see that on line 2420, a create is called on the matrix dst. This means the data section as well as the headers for this matrix is rewritten. So it might not be advisable to call this function with the same matrix in src and dst.

As for a convention in OpenCV, have a look at the InputArray and OutputArray, these seem to suggest that whenever function calls exist with these as data types of input and output, you should probably use different Mat variables.

ssb
  • 7,422
  • 10
  • 36
  • 61
  • Hmm I see what you mean. But it might be the case that when a matrix is converted to an InputArray it receives a new header? Providing a new header is created with a pointer. Also, looking at the header for _InputArray https://github.com/Itseez/opencv/blob/9b7dfd677db5818b8dd699e2059c886a1e7ce24f/modules/core/include/opencv2/core/core.hpp suggests that the getMat() function also returns a Mat with its own header rather than a reference to the same header data. – Tim MB Mar 12 '13 at 08:57
  • yes... exactly... so you should probably use different Mat variables... debugging these applications can be a little tricky if you do not have a clear idea as to where the header is changing and where data is. – ssb Mar 13 '13 at 12:11
3

It have to work in-place in sense that dst will contain correctly converted matrix after the call to cv::cvtColor. But if the number of channels on input differs from the number of channels of output then the data of matrix will be reallocated.

If you have a sample where dst does not have correctly converted image after in-place call to cvtColor then please submit it as a bug on http://code.opencv.org

More generally, is there a convention within the OpenCV API to determine when a function may be used in this way?

There is no such convention. But you can expect that most of basic image processing functions can work in-place. So all conversions, filters, thresholds, affine/perspective transformations are known to support in-place calls.

Andrey Kamaev
  • 29,582
  • 6
  • 94
  • 88