我想从二进制血管树中得到一个1像素宽的骨架。应用代码后得到的骨架具有一些小的假分支,并且不是1像素宽。如何获得完美的骨骼?
使用Frangi过滤器增强船只,并在执行阈值设置后提取二叉树。这是当时的图像:
然后,执行细化处理以获取骨架:
% getting the skeleton
Iskel = bwmorph(Out,'thin',8);
figure,imshow(Iskel);
% because of the discontinuity in my skeleton, I've applied imdilate to create continuity
se = strel('square',2);
Skel = imdilate(Iskel, se);
figure,imshow(Skel); title('Skel 8');
我希望输出为一个像素宽的骨架,但实际上不确定我的宽度是否为一个像素宽,并且还存在小的假分支。
答案 0 :(得分:0)
我使用 Zhang-Suen 算法从原始图像创建骨架。但结果可能不是单像素骨架。所以,我决定创建一个算法来去除多余的像素。最后,我想得到了一个单像素骨架。您可以将我的代码视为解决方案。
这是我的 Python 实现(我还在下面添加了我的代码的结果):
import cv2
import numpy as np
import math
def check_condition(img, r, c):
top = max(0, r - 1)
right = min(img.shape[1] - 1, c + 1)
bottom = min(img.shape[0] - 1, r + 1)
left = max(0, c - 1)
sub_img = img[top: bottom + 1, left: right + 1]
if np.sum(sub_img) >= 255*5:
return True
return False
def check_near(coord1, coord2):
r1, c1 = coord1
r2, c2 = coord2
distance = math.sqrt((r1-r2)**2 + (c1-c2)**2)
if distance == 1:
return True
def remove_redudant(img, r, c):
coords = []
if img[r-1][c-1] == 255:
coords.append((r-1, c-1))
if img[r-1][c] == 255:
coords.append((r-1, c))
if img[r-1][c+1] == 255:
coords.append((r-1, c+1))
if img[r][c-1] == 255:
coords.append((r, c-1))
if img[r][c+1] == 255:
coords.append((r, c+1))
if img[r+1][c-1] == 255:
coords.append((r+1, c-1))
if img[r+1][c] == 255:
coords.append((r+1, c))
if img[r+1][c+1] == 255:
coords.append((r+1, c+1))
coords.append((r, c))
coord_count = []
for coord in coords[:-1]:
count = 0
for coord_ in coords:
if check_near(coord, coord_):
count += 1
coord_count.append((coord, count))
coord_count.sort(key=lambda x: (x[1], int(x[0] in coords)))
remove_r, remove_c = coord_count[-1][0]
# remove
img[remove_r][remove_c] = 0
def single_pixel(img):
while True:
# Find positions of non-zero pixels
(rows, cols) = np.nonzero(img)
# Initialize empty list of co-ordinates
coords = []
# For each non-zero pixel...
for (r, c) in zip(rows, cols):
if check_condition(img, r, c):
coords.append((r,c))
# saved a image with end-point to check
if len(coords) == 0:
break
for i, j in coords:
# check whether (i, j) point is removed or not
if img[i][j] == 255:
# check again:
if check_condition(img, i, j):
remove_redudant(img, i, j)
def single_pixel_skeleton(path):
image = cv2.imread(path, 0)
# using zhang suen algorithm
thinned = cv2.ximgproc.thinning(image)
# create single pixel skeleton
single_pixel(thinned)
return thinned
if __name__ == '__main__':
path = 'sample.png'
saved_path = 'skeleton.png'
out_img = single_pixel_skeleton(path)
cv2.imwrite(saved_path, out_img)