重新排序图像骨架坐标以使 interp1d 更好地工作
Reordering image skeleton coordinates to make interp1d work better
对于一个学校项目,我正在分析一些 C 的中心线。线虫 图片。我已经设法生成了一个合理的阈值,我正在使用 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.nonzero
中得到的分数:
[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_hit_or_miss
函数来隔离终点。然后我编写了一个函数,通过检查骨架中每个像素的下一个像素的邻居,移动到那个像素,并保留一个 运行 列表来沿着骨架走下去。这个 运行 列表变成了我正在寻找的有序点集。
然而,在经历了数小时的挫折之后(包括花了整整半小时苦苦思索一个问题,这个问题很容易通过在我的 if
语句),我意识到当我对这些数据点进行插值时,它们实际上并没有提供太多额外信息。由于我通过沿着骨架行走收集的数据点本身是参数化的,因此我进行的任何参数化分析都可以使用这些点。因此,虽然我知道如何对点进行排序是件好事,但无论如何插值并不是最终目标。
如果有人想看我为完成此任务而编写的代码,请给我发消息,我很乐意分享。
与其进行一维插值,不如尝试二维。这就是您的数据实际代表的内容,并且 SciPy 已经具有执行此操作的功能:
http://docs.scipy.org/doc/scipy-0.14.0/reference/generated/scipy.interpolate.interp2d.html
如您所见,您需要对非零像素进行排序。由于您已经对图像进行了骨架化,因此您可以从一个端点(whixh 恰好有一个邻居)开始并沿着路径行走,直到到达另一个端点。这样,您将获得一个有序的像素坐标列表,然后对其进行插值。请注意,如何参数化曲线的问题并非微不足道,您可能需要做的不仅仅是投入 interp1d
一个用于搜索 Internet 的关键字是 "analyze skeleton"。
对于一个学校项目,我正在分析一些 C 的中心线。线虫 图片。我已经设法生成了一个合理的阈值,我正在使用 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.nonzero
中得到的分数:
[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_hit_or_miss
函数来隔离终点。然后我编写了一个函数,通过检查骨架中每个像素的下一个像素的邻居,移动到那个像素,并保留一个 运行 列表来沿着骨架走下去。这个 运行 列表变成了我正在寻找的有序点集。
然而,在经历了数小时的挫折之后(包括花了整整半小时苦苦思索一个问题,这个问题很容易通过在我的 if
语句),我意识到当我对这些数据点进行插值时,它们实际上并没有提供太多额外信息。由于我通过沿着骨架行走收集的数据点本身是参数化的,因此我进行的任何参数化分析都可以使用这些点。因此,虽然我知道如何对点进行排序是件好事,但无论如何插值并不是最终目标。
如果有人想看我为完成此任务而编写的代码,请给我发消息,我很乐意分享。
与其进行一维插值,不如尝试二维。这就是您的数据实际代表的内容,并且 SciPy 已经具有执行此操作的功能:
http://docs.scipy.org/doc/scipy-0.14.0/reference/generated/scipy.interpolate.interp2d.html
如您所见,您需要对非零像素进行排序。由于您已经对图像进行了骨架化,因此您可以从一个端点(whixh 恰好有一个邻居)开始并沿着路径行走,直到到达另一个端点。这样,您将获得一个有序的像素坐标列表,然后对其进行插值。请注意,如何参数化曲线的问题并非微不足道,您可能需要做的不仅仅是投入 interp1d
一个用于搜索 Internet 的关键字是 "analyze skeleton"。