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)