我在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包创建一个Graph:
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')
为此,我必须遍历节点,提取形状的center
,提取其他形状的points
(不是他们自己,这没用)并制作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 inside triangle
)或某些错误的关系(如pentagon inside square
)
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
答案 0 :(得分:5)
这是您的多边形的图像
首先,不需要将节点转换为字典,我们可以直接迭代它们。此代码基于this example
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
构建凸性检查,有关详细信息,请参阅this blog。