# Adding Matrices without saturation

Is it possible to add two matrices (with values in [0, 255]) and store the result in a matrix with values in [0, 510]?

I would be adding up to 100 matrices that way, and want to keep the high precision (which rules out the use of cv::addWeighted()). A 16-bit int per pixel should suffice to contain these values.

I hoped this would work:

Mat A(10, 10, CV_8UC1, 200);
Mat B(10, 10, CV_8UC1, 200);
Mat C(10, 10, CV_32S, 0);


But the values in C are saturated to 255 (rather than value 400 being stored in some 16-bit data type).

Any suggestions are highly appreciated!

edit retag close merge delete

Sort by » oldest newest most voted

Afaik with cv::add or +-operator you'll always have a saturate cast, so if you want to use these functions you'd need to convert A and B to CV_32S first:

A.convertTo(C, CV_32S);
B.convertTo(B, CV_32S);
C += B;


However: What speaks really against cv::addWeighted? I don't get your reason. I doubt, that

cv::addWeighted(A, 1, B, 1, 0, C, C.type());


is less efficient than simple add.

At last, what you can always do: loop over the matrix-dimension by hand and add the matrix-values.

more

1

About addWeighted(): I was trying to work with integer numbers in [0, 255], and similarly integer numbers in [0, 100*255]. The code would run on an embedded platform, so I tried to do everything with plain 16-bit ints, and I could not tolerate any loss of precision (which might, theoretically, have been possible with CV_32F).

I didn't say that addWeighted() was less efficient, but I meant to say that it can be slightly less accurate.

( 2013-05-27 09:40:09 -0500 )edit
void add(InputArray src1, InputArray src2, OutputArray dst, InputArray mask=noArray(), int dtype=-1)


if you don't specify the dtype arg in cv::add() the 3rd arg will get reallocated to the type(and size) of the input operands, and your initialization of C will get completely ignored. if you check C.type() after the add(A,B,C) you'll find, that it's type is CV_8UC1, not CV_32S.

so, give it an empty mask param, and specify dtype:

Mat A(4, 4, CV_8UC1, 200);
Mat B(4, 4, CV_8UC1, 200);
Mat C; //(4, 4, CV_32S, 0);  // allocation will get ignored anyway(OutputArray)
cout << C.type() << endl;
cout << C << endl;


result:

4
[400, 400, 400, 400;
400, 400, 400, 400;
400, 400, 400, 400;
400, 400, 400, 400]

more

ah, didn't double-check the actual add-method :), seems the easiest solution

( 2013-05-23 05:23:42 -0500 )edit

didn't knew that before, too ;)

( 2013-05-23 05:26:12 -0500 )edit

Both solution work, thanks guys.

The first one (berak's) is more efficient without the conversions.

The second one (Guanta's) gets kudos for allowing the use of operator+ etc., looks better in code.

I also learned about OpenCV accumulator images meanwhile, worth a read for anyone interested.

more

+1 for the accumulator ;)

( was just scratching my head, how to get the mean of 500 face-images, when i saw your answer, so thanks ! )

( 2013-05-27 09:48:00 -0500 )edit

Official site

GitHub

Wiki

Documentation

## Stats

Asked: 2013-05-23 03:38:13 -0500

Seen: 2,496 times

Last updated: May 27 '13