编辑0:如果你说,骨架可以是任何方向的,让我们变得复杂:)。让我从我过去的一个类似问题开始。在那里,我需要一种方法来追踪骨架上给定两点之间的像素。请检查问题中接受的答案,并将这种方法牢记在心,因为我也会将它用于您的问题。
这是我针对您的问题所遵循的步骤。
- 获取骨架图像
- 通过使用tips周围的相邻像素数获取骨架的tips(即起点、终点)
- 通过BFS绘制起点和终点之间的路径
- 从绘制的路径中获取所需的索引(端点的第五个像素)
import numpy as np
import cv2
import os
import matplotlib.pyplot as plt
import sys
from collections import deque
from skimage.morphology import medial_axis
from itertools import combinations
img = cv2.imread('curvy_1.png',0)/255
skel = medial_axis(img, return_distance=False) # skeleton
img_conv = cv2.filter2D(skel.astype(np.uint8),-1,np.ones((3,3))) #
img_conv = img_conv*skel
img_tips = img_conv == 2
tips = np.array(np.nonzero(img_tips)).T
tip_combs = combinations(tips, 2) # get all the combinations of the tips in case the skeleton are branched
这是找到的提示。

# BFS
def findPathBwTwoPoints(img_binary,points):
'''
img_binary: skeleton image
points: (y_start_point,x_start_point),(y_end_point,x_end_point)
'''
height, width = img_binary.shape
# The start and end point you're looking at
# start, end = (31, 14), (34, 51)
start,end = points
# print(start,end)
# All 8 directions
delta = [(-1, -1), (-1, 0), (-1, 1), (0, 1), (1, 1), (1, 0), (1, -1), (0, -1)]
# Store the results of the BFS as the shortest distance to start
grid = [[sys.maxsize for _ in range(width)] for _ in range(height)]
grid[start[0]][start[1]] = 0
# The actual BFS algorithm
bfs = deque([start])
found = False
while len(bfs) > 0:
y, x = bfs.popleft()
# print(y,x)
# We've reached the end!
if (y, x) == end:
found = True
break
# Look all 8 directions for a good path
for dy, dx in delta:
yy, xx = y + dy, x + dx
# If the next position hasn't already been looked at and it's white
if 0 <= yy < height and 0 <= xx < width and grid[y][x] + 1 < grid[yy][xx] and img_binary[yy][xx] != 0:
grid[yy][xx] = grid[y][x] + 1
bfs.append((yy, xx))
if found:
# Now rebuild the path from the end to beginning
path = []
y, x = end
while grid[y][x] != 0:
for dy, dx in delta:
yy, xx = y + dy, x + dx
if 0 <= yy < height and 0 <= xx < width and grid[yy][xx] == grid[y][x] - 1:
path.append([yy, xx])
y, x = yy, xx
return np.array(path)
else:
# print(f'No path found between {start} and {end}')
return 0
让我们使用 BFS 获取找到的提示之间的路径。
for tip_comb in list(tip_combs):
start, end = tuple(tip_comb[0]), tuple(tip_comb[1])
paths = findPathBwTwoPoints(skel,points=[start,end]) # this will return the path between the start and end points
# ready to get the indices you are asking for
first_fifth = paths[4]
last_fifth = paths[-5]
middle = paths[int(len(paths)/2)]
fig,ax = plt.subplots(1)
ax.imshow(skel,'gray')
ax.scatter( [first_fifth[1],last_fifth[1],middle[1]],
[first_fifth[0],last_fifth[0],middle[0]],s=10,c='r')
plt.show()

以下是我的方法的更多示例输出。

如果您的骨架是分支的,这种方法将为您提供提示之间所有组合的索引。
