Robert Kirchhoff
Robert Kirchhoff

Reputation: 517

Column sum of Opencv Matrix elements

I need to compute sum of elements in all columns separately.

Now I'm using:

Matrix cross_corr should be summed.

Mat cross_corr_summed;
for (int i=0;i<cross_corr.cols;i++)                                                     
    {
        double column_sum=0;
        for (int k=0;k<cross_corr.rows;k++)
        {
            column_sum +=cross_corr.at<float>(k,i);             
        }
        cross_corr_summed.push_back(column_sum);
    }

The problem is that my program takes quite a long time to run. This is one of parts that is suspicious to cause this. Can you advise any possible faster implementation???

Thanks!!!

Upvotes: 13

Views: 21567

Answers (3)

user3693028
user3693028

Reputation: 53

Mat originalMatrix;    
Mat columnSum;    
for (int i = 0; i<originalMatrix.cols; i++)    
     columnSum.push_back(cv::sum(originalMatrix.col(i))[0]);    

Upvotes: 0

Aurelius
Aurelius

Reputation: 11359

If you know that your data is continuous and single-channeled, you can access the matrix data directly:

int width = cross_corr.cols;
float* data = (float*)cross_corr.data;
Mat cross_corr_summed;
for (int i=0;i<cross_corr.cols;i++)
{
    double column_sum=0;
    for (int k=0;k<cross_corr.rows;k++)
    {
        column_sum += data[i + k*width];
    }
    cross_corr_summed.push_back(column_sum);
}

which will be faster than your use of .at_<float>(). In general I avoid the use of .at() whenever possible because it is slower than direct access.

Also, although cv::reduce() (suggested by Andrey) is much more readable, I have found it is slower than even your implementation in some cases.

Upvotes: 2

Andrey Kamaev
Andrey Kamaev

Reputation: 30142

You need a cv::reduce:

cv::reduce(cross_corr, cross_corr_summed, 0, CV_REDUCE_SUM, CV_32S);

Upvotes: 41

Related Questions