findCountours returns a list of arrays.
What does the middle dimension for the contours represent?
contours[0].shape -> (136, 1, 2)
findCountours returns a list of arrays.
What does the middle dimension for the contours represent?
contours[0].shape -> (136, 1, 2)
It’s an array of 136 points and a point is an array of 1 row and 2 columns
Yes. We have: (point, ??, xy)
Why arity 3 indexes when 2, (point, xy), is sufficient?
Let me explain. It all begins in C++.
cv::Mat
is not quite a matrix. it’s an image container. it has a number of rows and columns, but also a number of channels.
each entry of the matrix can be a single number, but it can also be a “vector”, or cv::Scalar
(really a vector). for images, a cv::Mat has 3 channels or something like that.
This “Scalar” thing is convenient because now you can index a single element of the matrix and you get a Scalar/vector. you don’t need to “select the row”, as you would otherwise.
the result of findContours
is a list of contours. each contour is a Mat, containing the points. the points are put into the Mat as a “column vector” of points.
that means the Mat is Nx1, and 2-channel (CV_32SC2
perhaps), so it can hold (x,y) Points.
the mapping from cv::Mat
to numpy array always maps to (nrows, ncols, nchannels)
or (nrows, ncols)
if there’s just one channel (grayscale image or “actual” matrix data).
that’s why you get (N, 1, 2).
just for the record, starting with 4.6.0, python bindings changed, the additional dimension (wrapping std::vector<T>
) was removed, so we have:
std::vector<cv::Point> -> [N, 1, 2]
std::vector<cv::Point> -> [N, 2]
(just saying, not all of the python samples might be up to date here !)
import cv2 as cv
import numpy as np
img = np.zeros((256, 256), np.uint8)
cv.rectangle(img,(160, 100, 50, 20), 255, -1)
img = cv.circle(img, (50,50), 20, 255, -1)
ctr, _ =cv.findContours(img, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_NONE)
then ctr is a list
>>> len(ctr)
2
and
>>> ctr[0].shape
(136, 1, 2)
and
>>> print(cv.getBuildInformation())
General configuration for OpenCV 4.7.0-dev =====================================
Version control: 4.7.0-185-g61d255887c
Extra modules:
Location (extra): C:/lib/opencv_contrib/modules
Version control (extra): 4.7.0-31-g853144ef
that’s because std::vector<cv::Mat>
are returned, not vectors of cv::Points. I don’t believe that std::vector<cv::Point>
ever mapped to an additional dimension, so that is irrelevant to the situation.