Home > other >  Sequential picking of elements in openCV like Matlab
Sequential picking of elements in openCV like Matlab

Time:01-27

In MATLAB we can pick elements from a matrix using the : operator. We can also pick elements in any sequence like for example picking elements like

SubMat = Mat(1:2:end,1:2:end);  % Sequential picking in rows and columns 

My question is how can we do this in OpenCV without explicitly looping over Mat?

CodePudding user response:

cv::Mat contains some functionality allowing for extracting a sub-mat which is a limited view on the original Mat. By view I meant that the memory is not copied - it still points to the other Mat memory. There is a couple of ways - all involve calling a dedicated operators() which specifies a ROI:

Mat operator() (const Rect &roi) const;
Mat operator() (const Range *ranges) const;
Mat operator() (const std::vector< Range > &ranges) const;

There are also methods passing cols range or rows range:

Mat colRange (int startcol, int endcol) const;
Mat colRange (const Range &r) const;

Mat rowRange (int startrow, int endrow) const;
Mat rowRange (const Range &r) const;

For more info, please refer here

CodePudding user response:

So that MATLAB syntax is equivalent to a strided slice.

In Python, this would have been just the same using numpy, because numpy arrays support striding. The result would be a view, i.e. zero copying is required.

OpenCV itself can't do these stride tricks because cv::Mat doesn't support them (last I checked). The result will have to be a copy.

To replicate this in C with OpenCV, you'd need to use cv::warpAffine.

Here's some python (sorry, CBA to touch C right now) that shows what to do:

im = cv.imread(cv.samples.findFile("lena.jpg"))
(height, width) = im.shape[:2] 

M = np.zeros((2,3))
M[0,0] = M[1,1] = 1/2 # 2x3 scaling matrix, 1/stride

subsampled = cv.warpAffine(im, M=M, dsize=(width//2, height//2), flags=cv.INTER_NEAREST)

assert (im[0::2, 0::2] == subsampled).all()

If considering the forward transformation is bothersome, just define the backwards transformation (matrix calculates source index from output index) and pass WARP_INVERSE_MAP.

M = np.zeros((2,3))
M[0,0] = M[1,1] = 2 # stride 2
# M[0,2] = 0 # offset in j/x
# M[1,2] = 0 # offset in i/y

subsampled = cv.warpAffine(im, M=M, dsize=(width//2, height//2), flags=cv.INTER_NEAREST | cv.WARP_INVERSE_MAP)
  •  Tags:  
  • Related