Python 重新排序图像骨架坐标以使interp1d更好地工作

Python 重新排序图像骨架坐标以使interp1d更好地工作,python,numpy,scipy,scikit-image,Python,Numpy,Scipy,Scikit Image,为了一个学校项目,我正在分析一些线虫图片的中心线。我已经成功地生成了一个合理的阈值,我正在使用skimage.morphology.skeletonize生成中心线: 然后,我使用np.nonzero获得中心线的坐标,最终目标是对这些点进行参数化,以了解中心线的几何结构 然而,当我使用scipy.interpolate.interp1d时,我得到了这样的混乱: 我相当肯定会发生这种情况,因为当np.nonzero查找非零值时,它会从下到上、从右到左排序点,这就是为什么我在插值过程中会得到锯齿效

为了一个学校项目,我正在分析一些线虫图片的中心线。我已经成功地生成了一个合理的阈值,我正在使用
skimage.morphology.skeletonize
生成中心线:

然后,我使用
np.nonzero
获得中心线的坐标,最终目标是对这些点进行参数化,以了解中心线的几何结构

然而,当我使用
scipy.interpolate.interp1d
时,我得到了这样的混乱: 我相当肯定会发生这种情况,因为当
np.nonzero
查找非零值时,它会从下到上、从右到左排序点,这就是为什么我在插值过程中会得到锯齿效果。是否有任何方法可以对这些点重新排序,以便
interp1d
能够很好地处理它们

这是我的密码:

import cv2
import numpy as np
from matplotlib import pyplot as plt
from scipy import ndimage
from scipy import stats
from scipy import misc
from skimage.morphology import skeletonize
from scipy.interpolate import interp1d

"""Curved Worm"""

img = misc.imread("model_image_crop_curved.tif")
plt.imshow(img)
plt.show()

imgThresh = img>200
plt.imshow(imgThresh)
plt.show()

misc.imsave('model_image_crop_curved_binary.tif',imgThresh)

imgSkel = skeletonize(imgThresh)
plt.imshow(imgSkel)
plt.show()
misc.imsave('model_image_crop_curved_skeleton.tif',imgSkel)

cv2Skel = cv2.imread('model_image_crop_curved_skeleton.tif',cv2.IMREAD_GRAYSCALE)

skelCoord = np.nonzero(imgSkel)

x = skelCoord[1]
y = skelCoord[0]

plt.plot(x,y,'.')
plt.show()

i = np.arange(len(x))
interp_i = np.linspace(0,i.max(),5*i.max())

interpKind = 'linear'

xi = interp1d(i,x,kind=interpKind)(interp_i)
yi = interp1d(i,y,kind=interpKind)(interp_i)

fig, ax = plt.subplots()
ax.plot(xi,yi,'b-')
ax.plot(x,y,'ko')
plt.show()
以下是我从
np.non-zero
中得到的要点:

[51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 45 46 47 48 49 50 68 69
 70 71 72 73 74 75 40 41 42 43 44 76 77 78 36 37 38 39 79 80 34 35 32 33 31
 30 30 29 28 28 27 27 27 27 27 27 27 27 26 26 26 26 26 26 27 27 27 27 27 27
 27 28 28 29 30 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
 50 51 52 53 54 55 56 56]
[16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 17 17 17 17 17 17 17 17
 17 17 17 17 17 17 18 18 18 18 18 18 18 18 19 19 19 19 19 19 20 20 21 21 22
 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
 48 49 50 51 52 53 54 55 56 57 58 58 59 59 60 61 61 61 62 62 62 63 64 64 65
 65 66 67 68 69 70 71 72]
编辑

为了解决订购问题,我遵循ev br的建议,从终点开始。我使用了一系列可能的端点方向和
ndimage.binary\u hit\u或\u miss
函数来隔离端点。然后,我编写了一个函数,通过检查每个像素的邻域来查找骨架中的下一个像素,移动到该像素,并保留一个运行列表来遍历骨架。这个运行列表成了我正在寻找的有序点集

然而,在经历了数小时的挫折之后,我终于完成了这项任务(包括花了整整半个小时的时间来苦思冥想一个问题,这个问题可以通过在我的
if
语句中用
替换
而轻松解决),我意识到,当我插值这些数据点时,它们实际上不会提供太多额外的信息。因为我通过沿着骨架行走收集的数据点本身是参数化的,所以我所做的任何参数化分析都可以使用这些点。所以,虽然我知道了如何对点进行排序是件好事,但插值并不是最终的目标


如果有人想看到我为实现这一点而编写的代码,请给我发一条消息,我很乐意与大家分享。

与其做1D插值,不如试试2D。这就是您的数据实际表示的内容,SciPy已经有了一个功能:


正如您所注意到的,您需要对非零像素进行排序。由于您已经对图像进行了骨架化,因此可以从一个端点(该端点正好有一个邻居)开始沿着路径行走,直到到达另一个端点。这样,您可以得到一个有序的像素坐标列表,然后进行插值。但是请注意,如何参数化曲线的问题并非无关紧要,您可能需要做的事情不仅仅是在
interp1d


搜索互联网的一个关键词是“分析骨架”

你能加一张图片吗?或者链接一个像维基百科一样的公共图片,你可以把它应用到?@roadrunner66我使用的图片是我问题的第一个。代码中称为“model_image_crop_curve_skeleton.tif”,我使用cv2将其读取为cv2Skel。我把它作为PNG发布,因为堆栈溢出不喜欢TIF。我正在考虑使用这个函数,但它很难。关于如何将其用于网格化数据,有很多例子,但我只是想将曲线拟合到多元非结构化数据。我看到了这样的结果图片,但没有相关的解释。为了更好地解释这一点,我想做一些类似于此人所问的事情: