The problem is that for some reason cv2.findContours
returns each contour as a 3D NumPy array with one redundant dimension:
>>> contours[1]
array([[[774, 775]],
[[775, 774]],
[[824, 774]],
[[825, 775]],
[[825, 824]],
[[824, 825]],
[[775, 825]],
[[774, 824]]])
but Shapely expects a 2D array in this form (see the docs):
array([[774, 775],
[775, 774],
[824, 774],
[825, 775],
[825, 824],
[824, 825],
[775, 825],
[774, 824]])
So, what we can do is to use np.squeeze
to remove that redundant dimension, and use the result to obtain our polygon:
import numpy as np
from shapely.geometry import Polygon
contour = np.squeeze(contours[1])
polygon = Polygon(contour)
print(polygon.wkt)
# POLYGON ((774 775, 775 774, 824 774, 825 775, 825 824, 824 825, 775 825, 774 824, 774 775))
In case if you want to convert all of the contours at once, I would do it like this:
contours = map(np.squeeze, contours) # removing redundant dimensions
polygons = map(Polygon, contours) # converting to Polygons
multipolygon = MultiPolygon(polygons) # putting it all together in a MultiPolygon
The resulting multipolygon
will look like this:
And to get the second polygon from here you would just write:
my_polygon = multipolygon[1]
print(my_polygon.wkt)
# POLYGON ((774 775, 775 774, 824 774, 825 775, 825 824, 824 825, 775 825, 774 824, 774 775))