4

I'm using OpenCV in C++ to create a multidimensional mat (to use as an accumulator) over an image.

I create the 3d accumulator like this:

const int accumSize[] = {sx, sy, sr};
cv::Mat accum(3, accumSize, CV_64F, cv::Scalar::all(0));

I need to extract an n*n*n ROI from this accumulator so I can get the maximum within each ROI using cv::minMaxIdx.

Since this is 3d, the usual method of using a cv::Rect to get the ROI doesn't work. Nor does:

accum(cv::Range(x1,x2), cv::Range(y1,y2), cv::Range(r1,r2));

Anyone know how to easily get a 3d submatrix without having to explicitly allocate it and copy element by element?

herohuyongtao
  • 49,413
  • 29
  • 133
  • 174
eculeus
  • 1,230
  • 12
  • 17

2 Answers2

2

You can use the () operator, however you need to provide an array of ranges, like this:

cv::Range ranges[3];
ranges[0] = cv::Range(x1, x2);
ranges[1] = cv::Range(y1, y2);
ranges[2] = cv::Range(z1, z2);

accum(ranges)
Andrzej Pronobis
  • 33,828
  • 17
  • 76
  • 92
  • 2
    Note that using ranges seem to be a different order. If my Rect was `Rect(x,y,w,h)`, then the Ranges for those first two dimensions would have to be ordered: `{Range(y, y+h), Range(x, x+w), ...}` – ferrouswheel Aug 04 '16 at 01:37
-1

Let's say you are working with n channels and each channel has a matrix of a x b. Merge these channels to create a new Mat of depth = n and size = a x b. Use Rect to define and crop the ROI.

vector<Mat> channels;

// populate this vector with number of channels you desire

Mat mergedChannels, croppedChannels;
Rect roi(x1, y1, x2-x1, y2-y1);

merge(channels, mergedChannels);
croppedChannels = mergedChannels(roi);

printf("%d %d %d\n", croppedChannels.cols, croppedChannels.rows, croppedChannels.channels());
Froyo
  • 17,947
  • 8
  • 45
  • 73