在Networkx中循环遍历节点并提取属性

11

我在Python中定义了一些形状和相应的角点,就像这样:

square = [[251, 184],
          [22, 192],
          [41, 350],
          [244, 346]]

triangle = [[250, 181],
            [133, 43],
            [21, 188]]

pentagon = [[131,  37],
            [11, 192],
            [37, 354],
            [247, 350],
            [256, 182]]

然后,我使用NetworkX包创建一个图:

G = nx.DiGraph()

接下来,我为每个形状在图表中创建一个节点:

G.add_node('square', points = square, center = (139, 265))
G.add_node('triangle', points = triangle, center = (139, 135))
G.add_node('pentagon', points = pentagon, center = (138, 223))

现在的问题是,如果符合以下条件,我必须创建一些连接两个节点的边缘: 如果一个形状的中心在另一个形状内或外,则创建这样的边缘:

G.add_edge('triangle', 'pentagon', relation = 'inside')
G.add_edge('triangle', 'square', relation = 'outside')
为了做到这一点,我必须循环遍历节点,提取形状的中心,提取其他形状(不是自己的)的,并进行pointPolygonTest
我已经尝试了很多次,但没有找到任何解决方案。我得到的最接近(并不是很有效)的解决方案是这个:
nodes_p=dict([((u),d['points']) for u,d in G.nodes(data=True)])
nodes_c=dict([((u),d['center']) for u,d in G.nodes(data=True)])
for z,c in nodes_c.items():
    print z + ' with center', c
    for z,p in nodes_p.items():
        p_array = np.asarray(p)
        if cv2.pointPolygonTest(p_array,c,False)>=0:
            print 'inside ' + z
            #create edge
        else:
            print 'outside ' + z
            #create edge

这会给我以下输出,但不太理想,因为存在一些应该避免的关系(比如 三角形内嵌三角形)或者一些错误的关系(比如 五边形内嵌正方形

triangle with center (139, 135)
inside triangle
outside square
inside pentagon
square with center (139, 265)
outside triangle
inside square
inside pentagon
pentagon with center (138, 223)
outside triangle
inside square
inside pentagon

我该如何解决这个问题?任何建议都将不胜感激。提醒一下:主要问题是如何循环遍历节点并提取信息。我为整个脚本导入的软件包有:

import numpy as np
import networkx as nx
import cv2

你应该将导入语句(numpycv2)添加到代码中,以帮助未来的读者。 - yardsale8
1个回答

8
这是多边形的图片 Polygon image 首先,我们不需要将节点转换为字典,可以直接迭代它们。这段代码基于这个例子编写。
for u,outer_d in G.nodes(data=True):
   center = outer_d['center']
   print u, "with center", center
   for v, inner_d in G.nodes(data=True):
        #Don't compare self to self
        if u != v:
            # Create a source image
            src = np.zeros((400,400),np.uint8)          
            # draw an polygon on image src
            points = np.array(inner_d['points'],np.int0)
            cv2.polylines(src,[points],True,255,3)
            contours,_ = cv2.findContours(src,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
            if cv2.pointPolygonTest(contours[0],center,True) <= 0:
                print 'outside',v
            else:
                print 'inside',v

输出结果为:

pentagon with center (138, 223)
inside square
outside triangle
square with center (139, 265)
inside pentagon
outside triangle
triangle with center (139, 135)
inside pentagon
outside square

既然目标是确定一个多边形是否完全在另一个多边形内部,那么我们需要检查一个多边形的所有顶点是否在另一个多边形内部。这里是一个初步的(可惜未经测试的)解决方案。

def checkPoint(point, poly,r=400):
    ''' determine if point is on the interior of poly'''
    # Create a source image
    src = np.zeros((r,r),np.uint8)       
    # draw an polygon on image src
    verts = np.array(poly,np.int0)
    cv2.polylines(src,[verts],True,255,3)
    contours,_ = cv2.findContours(src,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
    return cv2.pointPolygonTest(contours[0],tuple(point),True) > 0:


for u,outer_d in G.nodes(data=True):
    points = outer_d['points']
    center = outer_d['center']
    print u, "with center", center
    for v, inner_d in G.nodes(data=True):
        poly = inner_d['points']
        if u != v:
            if all([checkPoint(point,poly) for point in points]):
                print 'inside',v
            else:
                print 'outside',v

这个例子的输出结果如下,现在应该是正确的。
pentagon with center (138, 223)
outside square
outside triangle
square with center (139, 265)
inside pentagon
outside triangle
triangle with center (139, 135)
inside pentagon
outside square

请注意,我假设多边形是凸的。如果不是这样,那么您可以检查轮廓上的所有点而不仅仅是角点。您还可以使用cv2内置凸度检查功能,请参见此博客获取详细信息。

抱歉,我混淆了不等式。现在正确了吗? - yardsale8
输出结果是错误的。应该是:五边形在三角形外面,在正方形外面,正方形在五边形里面,在三角形外面,在五边形里面的三角形,在正方形外面。 - Francesco Sgaramella
你所说的其实是正确的。但是它和我正在进行实验的图像不一致。在这张图片中有一个五边形,其中包含一个正方形和一个三角形。正方形在三角形下面。所以输出结果并不完美。我不知道该怎么解决它。因为当使用pointPolygonTest来测试五边形与正方形时,返回的值是inside,但实际上应该是outside。 - Francesco Sgaramella
你放置的图像是完全正确的。因此,你可以看到五边形的重心位于正方形内部,但实际上五边形包含了正方形,这意味着五边形在正方形外面。如何解决这个问题? - Francesco Sgaramella
好的,一个解决方案是检查一个多边形的每个“点”是否在另一个多边形内。我会添加一个暂定的解决方案,但由于我的工作电脑上没有cv2,所以现在无法测试它。 - yardsale8
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接