本文介绍了如何将从cv2.findContours获得的NumPy数组转换为Shapely多边形?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用CV2从图像中查找轮廓,然后使用Shapely将其转换为多边形.我目前陷入困境,因为当我尝试将一个轮廓数组从Shapely放入Polygon()时,它将引发未指定的错误.

I am using CV2 to find contours from an image and then converting them into polygons using Shapely. I am currently stuck because when I try putting one of the contour arrays into Polygon() from Shapely it throws an unspecified error.

我已经仔细检查了是否导入了我需要的所有内容,以及当我手动输入数组坐标点时创建Shapely多边形的工作原理.

I have double-checked that I imported everything I needed, and that creating a Shapely polygon works when I manually enter the array coordinate points.

这是代码中有问题的部分:

Here is the problematic section of the code:

contours, hierarchy = cv2.findContours(thresh, cv2.RETR_CCOMP, cv2.CHAIN_APPROX_SIMPLE)
testcontour = contours[1]

ply = Polygon(testcontour)

轮廓列表如下:

contours = [np.array([[[700, 700]],
                      [[700, 899]],
                      [[899, 899]],
                      [[899, 700]]]),
            np.array([[[774, 775]],
                      [[775, 774]],
                      [[824, 774]],
                      [[825, 775]],
                      [[825, 824]],
                      [[824, 825]],
                      [[775, 825]],
                      [[774, 824]]]),
            np.array([[[200, 200]],
                      [[200, 399]],
                      [[399, 399]],
                      [[399, 200]]]),
            np.array([[[274, 275]],
                      [[275, 274]],
                      [[324, 274]],
                      [[325, 275]],
                      [[325, 324]],
                      [[324, 325]],
                      [[275, 325]],
                      [[274, 324]]])]

我得到的错误是:

---------------------------------------------------------------------------
AssertionError                            Traceback (most recent call last)
<ipython-input-65-4124f49b42e1> in <module>
----> 1 ply = Polygon(testcontour)

~\AppData\Local\Continuum\anaconda3\envs\geocomp\lib\site-packages\shapely\geometry\polygon.py in __init__(self, shell, holes)
    238
    239         if shell is not None:
--> 240             ret = geos_polygon_from_py(shell, holes)
    241             if ret is not None:
    242                 self._geom, self._ndim = ret

~\AppData\Local\Continuum\anaconda3\envs\geocomp\lib\site-packages\shapely\geometry\polygon.py in geos_polygon_from_py(shell, holes)
    492
    493     if shell is not None:
--> 494         ret = geos_linearring_from_py(shell)
    495         if ret is None:
    496             return None

~\AppData\Local\Continuum\anaconda3\envs\geocomp\lib\site-packages\shapely\speedups\_speedups.pyx in shapely.speedups._speedups.geos_linearring_from_py()

AssertionError:

推荐答案

问题是由于某些原因cv2.findContours将每个轮廓作为具有一个冗余尺寸的3D NumPy数组返回:

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

,但是Shapely希望采用这种形式的2D数组(请参阅文档):

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

生成的multipolygon将如下所示:

要从此处获取第二个多边形,您只需编写:

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

这篇关于如何将从cv2.findContours获得的NumPy数组转换为Shapely多边形?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-20 10:38