# More efficient way to sum several images with Mat

Hello the community,

Actually, I need to sum five images, and keep the average value. My code is :

//image 1
cv::Mat OUT_IMAGE1 ;
cv::medianBlur (INT_IMAGE1, OUT_IMAGE1, Window ) ;

//image 2
cv::Mat OUT_IMAGE2 ;
cv::medianBlur (INT_IMAGE2, OUT_IMAGE2, Window ) ;

//image 3
cv::Mat OUT_IMAGE3 ;
cv::medianBlur (INT_IMAGE3, OUT_IMAGE3, Window ) ;

//image 4
cv::Mat OUT_IMAGE4 ;
cv::medianBlur (INT_IMAGE4, OUT_IMAGE4, Window ) ;

//image 5
cv::Mat OUT_IMAGE5 ;
cv::medianBlur (INT_IMAGE5, OUT_IMAGE5, Window ) ;

cv::Mat FINALE_IMAGE= Mat::zeros(height,width, CV_8U);
cv::Mat BLA= Mat::zeros(height,width, CV_8U);

for(int i=0 ; i<height ; i++){
for(int j=0 ; j<width ; j++){
FINALE_IMAGE.at<uchar>(i,j)=(OUT_IMAGE1.at<uchar>(i,j)+OUT_IMAGE2.at<uchar>(i,j)+OUT_IMAGE3.at<uchar>(i,j)+OUT_IMAGE4.at<uchar>(i,j)+OUT_IMAGE5.at<uchar>(i,j))/5;
}
}


I know that is not an efficient method, but despite all my research, I didn´t find a function which paralellize the task. Furthermore, I can´t use :

FINALE_IMAGE=OUT_IMAGE1+OUT_IMAGE2+OUT_IMAGE3+OUT_IMAGE4+OUT_IMAGE5 ; FINALE_IMAGE=FINALE_IMAGE/5 ;

With this method, I lost information when the sum of pixels is greater than 255. I can´t use to this method too, because of the lost conversion :

FINALE_IMAGE=OUT_IMAGE1/5 +OUT_IMAGE2/5 +OUT_IMAGE3/5 +OUT_IMAGE4/5 +OUT_IMAGE5/5 ;

Some of you have an idea ? thank you very much !

Sincerely

edit retag close merge delete

Sort by » oldest newest most voted

maybe you can use accumulate here, since it can handle larger result types like:

Mat a = imread("a.png",0);

Mat dst(a.size(), CV_32F, Scalar(0)); // large enough to hold sum
accumulate(a, dst);
accumulate(b, dst);
accumulate(c, dst);
accumulate(d, dst);
accumulate(e, dst);

Mat final;
dst.convertTo(final, 1.0/5);


(... and yea, don't write loops ...)

more

Thank you for your help !

I tried with the function accumulate, but actually I am working with the jetson TX2, and the function accumulate does not work ... I have the following error : C:\fakepath\Selection_001.png

I think the problem is the cuda´s version provides by nvidia ...

Do you that it can be interesting to use cuba ?

Sincerely

( 2020-02-14 05:27:51 -0500 )edit

what ?

you must be using different code, something with a std::vector ?

(and please NEVER post screenshots of code or errors, but paste the TEXT instead, thank you !)

( 2020-02-14 05:38:36 -0500 )edit

Thank for the tip ! Ok, I am sorry

Sincerely

( 2020-02-14 06:25:42 -0500 )edit

no, i mean -- show resp. part of code, please

( 2020-02-14 06:58:05 -0500 )edit

If you like the solution using accumulation, you can just try to accumulate using the + operator or cv::add() function, something like:
Mat dst; a.convertTo(dst, CV_16S); // create dst as CV_16S and init it using image a
Mat final; dst.convertTo(final, CV_8U, 0.2);

( 2020-02-14 07:20:56 -0500 )edit

@wisewolf76 -- if you go that way, you need to convert ALL images to 16s

(add() does not accept different types, different to accumulate())

( 2020-02-14 07:33:24 -0500 )edit

What a noob error! Thank you very much for your quick replay... that said, the more optimized solution can be the double for loops solution of NL37 maybe just using pointers instead of the at<> operator?

( 2020-02-14 08:07:20 -0500 )edit

avoid writing your own loops, pointers or not, its slow & error prone, e.g. it will break, once you change the underlying Mat type

( 2020-02-14 08:42:04 -0500 )edit

Official site

GitHub

Wiki

Documentation