假设矩阵/图像中只有一条曲线,并且曲线上的每个点都有 1 到 2 个邻居,以下函数将提供您需要的结果。
它的工作原理是获取最靠近左上角的点,并通过迭代查找尚未访问过的最近点来形成点链,直到没有其他点为止。对于闭合曲线,链上第一个/最后一个点之间的平方欧几里得距离将小于 2。
import numpy as np
def find_chain(mat):
locs=np.column_stack(np.nonzero(mat))
chain=[np.array([0,0])]
while locs.shape[0]>0:
dists=((locs-np.vstack([chain[-1]]*locs.shape[0]))**2).sum(axis=1)
next=dists.argmin()
if dists.min()<=2 or len(chain)==1:
chain.append(locs[next,:])
locs=locs[np.arange(locs.shape[0])!=next,:]
else:
chain=[chain[0]]+chain[1::][::-1]
return np.vstack(chain[1::]),((chain[1]-chain[-1])**2).sum()<=2
对于开放曲线:
>>> mat1=np.array([[0, 0, 0, 0, 0, 0, 0],
... [0, 1, 0, 0, 1, 0, 0],
... [0, 0, 1, 0, 0, 1, 0],
... [0, 0, 0, 1, 1, 0, 0],
... [0, 0, 0, 0, 0, 0, 0]])
>>> points,isclosed=find_chain(mat1)
>>> points
array([[1, 1],
[2, 2],
[3, 3],
[3, 4],
[2, 5],
[1, 4]])
>>> isclosed
False
对于闭合曲线:
>>> mat2=np.array([[0, 0, 0, 0, 0],
... [0, 0, 1, 0, 0],
... [0, 1, 0, 1, 0],
... [0, 1, 0, 1, 0],
... [0, 0, 1, 0, 0],
... [0, 0, 0, 0, 0]])
>>> points,isclosed=find_chain(mat2)
>>> points
array([[1, 2],
[2, 1],
[3, 1],
[4, 2],
[3, 3],
[2, 3]])
>>> isclosed
True
还有一条曲线,起点(离原点最近的点)将曲线一分为二。
>>> mat3=np.array([[0, 0, 0, 0, 0],
... [0, 1, 1, 1, 0],
... [0, 1, 0, 0, 0],
... [0, 1, 0, 0, 0],
... [0, 0, 0, 0, 0],
... [0, 0, 0, 0, 0]])
>>> points,isclosed=find_chain(mat3)
>>> points
array([[1, 3],
[1, 2],
[1, 1],
[2, 1],
[3, 1]])
>>> isclosed
False