Ask Your Question
0

More efficient way to sum several images with Mat

asked 2020-02-14 03:52:13 -0600

NL37 gravatar image

Hello the community,

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

//image 1
cv::Mat INT_IMAGE1 = imread("Original_Image/4wCcW.png", 0);
cv::Mat OUT_IMAGE1 ;
cv::medianBlur (INT_IMAGE1, OUT_IMAGE1, Window ) ;

//image 2
cv::Mat INT_IMAGE2 = imread("Original_Image/4wCcW.png", 0);
cv::Mat OUT_IMAGE2 ;
cv::medianBlur (INT_IMAGE2, OUT_IMAGE2, Window ) ;

//image 3
cv::Mat INT_IMAGE3 = imread("Original_Image/4wCcW.png", 0);
cv::Mat OUT_IMAGE3 ;
cv::medianBlur (INT_IMAGE3, OUT_IMAGE3, Window ) ;

//image 4
cv::Mat INT_IMAGE4 = imread("Original_Image/4wCcW.png", 0);
cv::Mat OUT_IMAGE4 ;
cv::medianBlur (INT_IMAGE4, OUT_IMAGE4, Window ) ;

//image 5
cv::Mat INT_IMAGE5 = imread("Original_Image/4wCcW.png", 0);
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 flag offensive close merge delete

1 answer

Sort by » oldest newest most voted
0

answered 2020-02-14 04:59:52 -0600

berak gravatar image

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

Mat a = imread("a.png",0);    
Mat b = imread("b.png",0);
Mat c = imread("c.png",0);    
Mat d = imread("d.png",0);
Mat e = imread("e.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 ...)

edit flag offensive delete link more

Comments

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

NL37 gravatar imageNL37 ( 2020-02-14 05:27:51 -0600 )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 !)

berak gravatar imageberak ( 2020-02-14 05:38:36 -0600 )edit

Thank for the tip ! Ok, I am sorry

Sincerely

NL37 gravatar imageNL37 ( 2020-02-14 06:25:42 -0600 )edit

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

berak gravatar imageberak ( 2020-02-14 06:58:05 -0600 )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
cv::add(dst, b, dst);
cv::add(dst, c, dst);
cv::add(dst, d, dst);
cv::add(dst, e, dst);
Mat final; dst.convertTo(final, CV_8U, 0.2);

wisewolf76 gravatar imagewisewolf76 ( 2020-02-14 07:20:56 -0600 )edit

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

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

berak gravatar imageberak ( 2020-02-14 07:33:24 -0600 )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?

wisewolf76 gravatar imagewisewolf76 ( 2020-02-14 08:07:20 -0600 )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

berak gravatar imageberak ( 2020-02-14 08:42:04 -0600 )edit

Question Tools

1 follower

Stats

Asked: 2020-02-14 03:52:13 -0600

Seen: 656 times

Last updated: Feb 14 '20