Ask Your Question
2

[SOLVED] how to average N matrices into 1?

asked 2014-09-25 10:51:04 -0600

pmh4514 gravatar image

updated 2014-09-25 13:48:55 -0600

Hello, this is probably pretty straightforward, but I am very new to OpenCV.

I have a camera frame grabber application where the user is allowed to "average" N frames into a single frame (as a way to reduce signal to noise ratio)

So I have 3 (or N) Mat's all the same size (16bit grayscale) and I want to combine them all into one such that the result is the "average" of the 3.. So this isn't really a blending of unique images, each frame is going to be nearly identical, the goal is to average them to reduce the signal to noise.

What's the best way to do this?

edit: I tried cvAccumulate, but it fails, I'm thinking because the documentation says it works only for 8 or 32bit images.

I did make this work by brute-force (non OpenCV) looping, summing, averaging and then setting those values into my final/averaged matrix.. but is there a better way with OpenCV?

Thanks

edit retag flag offensive close merge delete

1 answer

Sort by ยป oldest newest most voted
5

answered 2014-09-25 13:29:29 -0600

berak gravatar image

updated 2014-09-25 13:30:19 -0600

this is a bit tricky. since adding up 8 or 16 bit images might lead to overflow, you need an image with a type larger than your single pics to hold the accumulated values.

Mat img = imread("lena.jpg", 0); // grayscale for simplicity
Mat acc(img.size(), CV_64F, Scalar(0)); // all black, *double* image
accumulate(img,acc);
accumulate(img,acc);
accumulate(img,acc);
accumulate(img,acc);
Mat avg; 
acc.convertTo(avg, CV_8U, 1.0/4); // back to u8 land, divide by count
imshow("average", avg);
waitKey();
edit flag offensive delete link more

Comments

Thank you for the reply. This is interesting. But I don't follow how the overflow may happen. I'm not summing the images, I want to produce one that is the average of 3. So if my pixel values all fit in the 16bit matrix, the average value of 3 16bit values is still a 16bit value, no?

pmh4514 gravatar imagepmh4514 ( 2014-09-25 13:32:21 -0600 )edit

the average sure fits, but to achieve that, you have to take the (temporary) sum, which will not.

berak gravatar imageberak ( 2014-09-25 13:33:46 -0600 )edit
1

if you don't care about that, it would be just : Mat a,b,c,d; Mat avg = (a+b+c+d)/4; // nice & short, but suffers heavily from saturation

berak gravatar imageberak ( 2014-09-25 13:37:31 -0600 )edit

oh I see. And then to convert my accumulated (CV_64F) matrix back to 16bit (not 8) does this still apply: acc.convertTo(avg, CV_16UC, 1.0/4)

pmh4514 gravatar imagepmh4514 ( 2014-09-25 13:38:21 -0600 )edit

yea, sorry. the 8bit example was more for reading 8bit grayscale imread() examples.

the scale factor here is just 1/count, so : acc.convertTo(avg, CV_16U, 1.0/4);

berak gravatar imageberak ( 2014-09-25 13:41:06 -0600 )edit

Thanks for the help, this works perfectly!

pmh4514 gravatar imagepmh4514 ( 2014-09-25 13:48:38 -0600 )edit

sorry I just noticed your earlier comment about just (a+b+c+d)/4 and suffering heavily from saturation.. I had tried that, and noticed the ugliness, but can you explain why that was the case and why cvAccumulate solves that problem?

pmh4514 gravatar imagepmh4514 ( 2014-09-25 13:50:31 -0600 )edit

(sorry for making it an 8bit example again, it's just easier to demonstrate)

sum=0; // as long as sum can't be larger than 255(has to fit into 8bit), we got a problem

a=125; // fictional pixel value

sum += a // sum is 125, still fits into 8bit

b = 132; // it get's hot

sum += b:

sum == 125 + 132 == 257; // opencv will saturate to the largest valid value(255) here

c = 5;

sum += c; // whatever you add here, it's already lost. sum just *can't get larger than 255

...

(it's all about getting enough leeway for the summation)

berak gravatar imageberak ( 2014-09-25 14:28:57 -0600 )edit

ahh I see.. thanks!

pmh4514 gravatar imagepmh4514 ( 2014-09-25 14:36:03 -0600 )edit
  1. sure, feel free to add anything helpful to others (that's the purpose of this site, no ?) ;)
  2. would this answer it ?
berak gravatar imageberak ( 2014-09-26 04:26:48 -0600 )edit

Question Tools

Stats

Asked: 2014-09-25 10:51:04 -0600

Seen: 3,799 times

Last updated: Sep 25 '14