将开放曲线转换为有序像素列表:使用numpy的Python测试代码

将开放曲线转换为有序像素列表:使用numpy的Python测试代码,python,numpy,shape,curve,Python,Numpy,Shape,Curve,我有一个numpy数组中的开放曲线的图像,我需要建立一个点坐标列表,这些点坐标按照它们在曲线上的位置排序。 我用numpy和mahotas写了一篇文章。它可能不是最优的 我知道OpenCV可以对闭合曲线执行此操作。OpenCV可以对开放曲线执行相同(更快)的操作吗 例如,如果原始曲线为: [[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]] 使用np.where(myarray

我有一个numpy数组中的开放曲线的图像,我需要建立一个点坐标列表,这些点坐标按照它们在曲线上的位置排序。 我用numpy和mahotas写了一篇文章。它可能不是最优的

我知道OpenCV可以对闭合曲线执行此操作。OpenCV可以对开放曲线执行相同(更快)的操作吗

例如,如果原始曲线为:

[[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]]
使用
np.where(myarray==1)
,我可以得到像素的索引:

(array([1, 1, 2, 2, 3, 3]), array([1, 4, 2, 5, 3, 4]))
但这不是我需要的。我的脚本根据曲线上像素的顺序生成索引:

i= 0 ( 1 , 1 )
i= 1 ( 2 , 2 )
i= 2 ( 3 , 3 )
i= 3 ( 3 , 4 )
i= 4 ( 2 , 5 )
i= 5 ( 1 , 4 )

我想优化我的脚本。有什么想法吗?

假设矩阵/图像中只有一条曲线,并且曲线上的每个点都有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
对于闭合曲线:

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

我已经写了另一个版本:亲爱的,我已经写了一个处理闭合曲线的扩展:[link]谢谢。你的代码确实比我的更紧凑。仅仅依靠numpy也是一个优势。为了处理通过形态学细化获得的曲线,需要进行一些预处理,因为一个像素可以有三个邻居。
>>> 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