Tim MB
Tim MB

Reputation: 4521

Can the OpenCV function cvtColor be used to convert a matrix in place?

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?

Upvotes: 14

Views: 19614

Answers (4)

PavelS
PavelS

Reputation: 1

I just encountered case when opencv failed when input & output array were same. For the code

            cv::cvtColor(subimg, subimg, cv::COLOR_GRAY2BGR);

I received error:

OpenCV(4.2.0) Error: Assertion failed (!fixedType() || ((Mat*)obj)->type() == mtype) in cv::debug_build_guard::_OutputArray::create, file C:\build\master_winpack-build-win64-vc15\opencv\modules\core\src\matrix_wrap.cpp, line 1195

For some reason in some places of the application it works fine, but here it just didn't want to work.OpenCV exception was thrown:

I inspected the source image and it was OK.

see image properties here After changing that destination was different from source, it worked just fine. Which is odd.

Upvotes: 0

Giuseppe Dini
Giuseppe Dini

Reputation: 762

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.

Upvotes: 14

Andrey Kamaev
Andrey Kamaev

Reputation: 30122

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.

Upvotes: 3

ssb
ssb

Reputation: 7502

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.

Upvotes: 3

Related Questions