Ask Your Question
1

Most efficient way to clear an image with C++ interface?

asked 2016-02-22 06:06:25 -0600

iko79 gravatar image

I'm currently porting my old OpenCV C code to the C++ interface of OpenCV 2/3 and I'm not quite sure about some equivalents for old functions. Pretty early I ran into an issue with cvZero. The only possibility I found was to set the matrix content via Mat::setTo. Now, having to be able to manage multi-channel scalars and different data types, setTo iterates through all elements of the matrix and sets them one after another while cvZero basically did a memset. Also, I read that using setTo is a lot slower compared to simply doing this:

myMat = cv::Mat::zeros( myMat.size(), myMat.type() );

Still, I'm not sure if this allocates a new matrix and frees the old one, which I also wouldn't want. Of course I could always write

memset( myMat.data, 0, myMat.size().width * myMat.size().height * myMat.depth() );

but isn't there a proper convenience function for this?

So, I am wondering what would be the recommended way for using the C++ interface, in case I just want to clear my image black.

Thanks!

edit retag flag offensive close merge delete

Comments

the equivalent for cvZero you can find it here (that you probably saw). Why do you think that it is slower than the cvZero function? How do you use cvZero and what do you think it does (is there any doc about it?)?

thdrksdfthmn gravatar imagethdrksdfthmn ( 2016-02-22 06:21:53 -0600 )edit
2

please take another look at setTo(), it does not iterate over pixels, but over planes and consecutive blocks, and then does a memset.

also, a simple memset might be inappropriate for non-continuous data (i.e. a ROI)

berak gravatar imageberak ( 2016-02-22 06:24:09 -0600 )edit

thanks, I misread. not sure what blocks are for, though. As a matter of fact, setTo is a lot slower, compared to cvZero. Here is the output of a very basic benchmark I did (image size is Full HD, 8 bit single channel):

1000 x testMat.setTo( cv::Scalar( 0x00 ) ); took 99.3829ms
1000 x testMat = cv::Mat::zeros( testMat.size(), testMat.type() ); took 58.3239ms
1000 x cvZero( im ); took 60.2803ms

Mat::zeros is, however, faster than cvZero. Mat::setTo on the other hand is a lot faster than the old C API's cvSet:

1000 x testMat.setTo( cv::Scalar( 0xff ) ); took 100.06ms
1000 x cvSet( im, cvScalar( 0xff ) ); took 470.597ms
iko79 gravatar imageiko79 ( 2016-02-23 08:50:16 -0600 )edit

IMHO cv::Mat::zeros is the equivalent to cvZero and cv::Mat::setTo is the equivalent to cvSet. But could you be more explicit about the cvZero( im )? How do you use it? Why would it be a problem if it allocates a new Mat and deallocates the old one? Normally, if you still have some other Mat that use the initial one, you will not arrive in the case of lost pointer, because the Mat is a smart pointer, it will be deallocated only if no-one is using that memory.

thdrksdfthmn gravatar imagethdrksdfthmn ( 2016-02-23 09:41:12 -0600 )edit

Frankly, I don't understand what you're asking - I use cvZero exactly as I wrote above, how else would I use it? cvZero( im ); The reason I am worried about unnecessary memory allocation and deallocation is of course performance, which is traditionally a consideration in most computer vision applications. I don't want to allocate and deallocate hundreds of matrixes each frame. When I use a computer vision library, I really try to use it in the most efficient way and to avoid unnecessary operations.

iko79 gravatar imageiko79 ( 2016-02-24 03:22:29 -0600 )edit

1 answer

Sort by ยป oldest newest most voted
3

answered 2016-02-24 07:40:24 -0600

iko79 gravatar image

updated 2016-02-24 07:43:23 -0600

Okay, in case anybody else is wondering about the same, here are my findings:

As pointed out in the comments already (thanks), cv::Mat::zeros seems to replace cvZero and cv::Mat::setTo replaces cvSet. What I now learned about memory management in the C++ interface here clarifies some obscurity. From diving into the source code, I learned that e.g. myMat = cv::Mat::zeros( ... );, while looking totally like an inefficient assignment, in reality isn't one. It rather creates an expression which in combination with the overloaded assignment operator for Mat = MatExp just applies an operation on the existing matrix, in case size and format match.

I must say, while being convenient, the C++ interface is not really intuitive. Things like that aren't self-explanatory and I think they should be pointed out much clearer to OpenCV beginners, especially to those with strong C++ background. To a general programming beginner it might be fine, but for experienced C++ programmers, writing some expressions surely sets off the alarm bells. In case I missed a detailled explaination about those mechanisms in the documentation, I would be glad about somebody pointing me to it.

edit flag offensive delete link more

Question Tools

1 follower

Stats

Asked: 2016-02-22 06:06:25 -0600

Seen: 16,317 times

Last updated: Feb 24 '16