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