user18169293
user18169293

Reputation: 3

Problems with using accumulate in c++

I'm using OpenCV to access the color data of the pixels within a specified area and currently I'm trying to use the accumulate method in c++ to sum up all the data numbers obtained in that specified area. But right now it has only given me the sum of only a single pixel within the specified area and not the whole area. I'm sure it is giving me the sum of a single pixel because I have used the push_back method and it has given me double the amount in that pixel. Is there something that I have missed and have not written? I'm kind of new to c++ so I would appreciate if someone would point me in the right direction.

    //the rows of the image
    for(int j=0; j<image; j++){
      int step = j*cols*elemSize;
      //the columns for the image
      for(int i-0; i<image; i++){
        int elm = i*elemSize;
        //obtaining the color data of the pixels
        uchar blue = image.data[step + elm + 0];
        uchar green = image.data[step + elm + 1];
        uchar red = image.data[step + elm + 2];
        std::vector<int> v = {blue};
        std::vector<int> w = {green};
        std::vector<int> x = {red};
        //using accumulate to sum up all the data
        int sumofblue = accumulate(v.begin(), v.end(), 0);
        int sumofgreen = accumulate(w.begin(), w.end(), 0);
        int sumofred = accumulate(x.begin(), x.end(), 0);

The blue green red is the color data extracted(0-255) from the specified area and image.data is defined as the image used in the extraction.

Upvotes: 0

Views: 310

Answers (1)

Caleth
Caleth

Reputation: 63152

Is there something that I have missed and have not written?

you've missed the fact that you are still in the middle of your loop. You need to define v, w and x before the loop, and add each element, then accumulate after the loop.

std::vector<int> v;
std::vector<int> w;
std::vector<int> x;
//the rows of the image
for(int j=0; j<image/*??*/; j++){
  int step = j*cols*elemSize;
  //the columns for the image
  for(int i-0; i<image/*??*/; i++){
    int elm = i*elemSize;
    //obtaining the color data of the pixels
    v.push_back(image.data[step + elm + 0]);
    w.push_back(image.data[step + elm + 1]);
    x.push_back(image.data[step + elm + 2]);
  }
}

//using accumulate to sum up all the data
int sumofblue = accumulate(v.begin(), v.end(), 0);
int sumofgreen = accumulate(w.begin(), w.end(), 0);
int sumofred = accumulate(x.begin(), x.end(), 0);

However you might as well just use += in the loop

int sumofblue = 0;
int sumofgreen = 0;
int sumofred = 0;
//the rows of the image
for(int j=0; j<image/*??*/; j++){
  int step = j*cols*elemSize;
  //the columns for the image
  for(int i-0; i<image/*??*/; i++){
    int elm = i*elemSize;
    //obtaining the color data of the pixels
    sumofblue += image.data[step + elm + 0];
    sumofgreen += image.data[step + elm + 1];
    sumofred += image.data[step + elm + 2];
  }
}

If you have access to a ranges library with stride and drop, you don't need the nested loop at all. Depending on exactly what image.data is, you may need to wrap it in a std::span

std::span data { image.data, image.data_size }; // cols * rows * elemSize?
auto blue = data | views::stride(3);
auto green = data | views::drop(1) | views::stride(3);
auto red = data | views::drop(2)  | views::stride(3);
int sumofblue = std::accumulate(begin(blue), end(blue), 0);
int sumofgreen = std::accumulate(begin(green), end(green), 0);
int sumofred = std::accumulate(begin(red), end(red), 0);

Upvotes: 0

Related Questions