# What's the middle dimension for the result of findCountours?

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).

2 Likes

just for the record, starting with 4.6.0, python bindings changed, the additional dimension (wrapping std::vector<T>) was removed, so we have:

• pre 4.6
std::vector<cv::Point> -> [N, 1, 2]
• post 4.6
std::vector<cv::Point> -> [N, 2]

(just saying, not all of the python samples might be up to date here !)

1 Like
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
2 Likes

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.

1 Like