예제 #1
0
def get_edges(img_file, pt_file, write_file):
    """
    Analyze the vessels and the points sampled from the vessels, give the connection information.
    """

    with open(img_file, 'rb') as f, open(pt_file, 'rb') as p1:
        model = read_as_3d_array(f)
        pts = read_as_3d_array(p1).data
        pts_coords = np.transpose(dense_to_sparse(pts), (1, 0))
        import cc3d
        labels_in = np.array(model.data)
        labels_out = cc3d.connected_components(labels_in)

        N = np.max(labels_out)
        edge_list = []
        for segid in range(1, N+1):
            extracted_image = labels_out == segid
            skel = Skeleton(extracted_image)
            for i in range(skel.n_paths):
                coords = skel.path_coordinates(i)
                prev = None
                for c in coords:
                    c = np.array(c, dtype=int)
                    for j in range(len(pts_coords)):
                        if (c == pts_coords[j]).all():
                            if prev == None:
                                prev = j
                            else:
                                cur = j
                                edge_list.append([prev, cur])
                                prev = cur
                            break

        np.save(write_file, edge_list)
예제 #2
0
def skeletoniseSkimg(maskFilePath):
    image = io.imread(maskFilePath)

    image = rgb2gray(image)

    binary = image > 0

    # perform skeletonization
    skeleton = skeletonize(binary)
    summary = summarize(Skeleton(skeleton, spacing=1))

    # starting coordinate in y, x
    startCoord = [
        summary.iloc[0]['image-coord-src-0'],
        summary.iloc[0]['image-coord-src-1']
    ]
    endCoord = [
        summary.iloc[0]['image-coord-dst-0'],
        summary.iloc[0]['image-coord-dst-1']
    ]

    # c0 contains information of all points on the skeleton
    # g0 is the adjacency list
    g0, c0, _ = skeleton_to_csgraph(skeleton, spacing=1)
    all_pts = c0[1:]

    # get points along skeleton in the correct sequence
    pts = traverseSkeleton(startCoord, endCoord, g0.toarray(), all_pts)

    return pts.astype(int)
예제 #3
0
def build_skeleton(label_image, connectivity=1, detect_boundaries=True):
    """Builds skeleton connectivity of a label image.

    A single-pixel wide network is created, separating the labelled image regions. The resulting
    network contains information about how the regions are connected.

    Parameters
    ----------
    label_image : 2D ndarray with signed integer entries
        Label image, representing a segmented image.
    connectivity : {1,2}, optional
        A connectivity of 1 (default) means pixels sharing an edge will be considered neighbors.
        A connectivity of 2 means pixels sharing a corner will be considered neighbors.
    detect_boundaries : bool, optional
        When True, the image boundaries will be treated as part of the skeleton. This allows
        identifying boundary regions in the `skeleton2regions` function. The default is True.

    Returns
    -------
    skeleton_network : Skeleton
        Geometrical and topological information about the skeleton network of the input image.

    See Also
    --------
    :class:`skan.csr.Skeleton`

    """
    # 2D image, given as a numpy array is expected
    if type(label_image) != np.ndarray:
        raise Exception('Label image must be a numpy array (ndarray).')
    image_size = np.shape(label_image)
    if len(image_size) != 2:
        raise Exception('A 2D array is expected.')
    if not issubclass(label_image.dtype.type, np.signedinteger):
        raise Exception('Matrix entries must be positive integers.')

    # Surround the image with an outer region
    if detect_boundaries:
        label_image = np.pad(label_image,
                             pad_width=1,
                             mode='constant',
                             constant_values=-1)

    # Find the boundaries of the label image and then extract its skeleton
    boundaries = find_boundaries(label_image, connectivity=connectivity)
    skeleton = skeletonize(boundaries)

    # Build the skeleton network using `skan`
    skeleton_network = Skeleton(skeleton,
                                source_image=label_image,
                                keep_images=True)
    return skeleton_network
예제 #4
0
def test_find_main():
    skeleton = Skeleton(skeleton1)
    summary_df = summarize(skeleton, find_main_branch=True)

    non_main_edge_start = [2, 1]
    non_main_edge_finish = [3, 3]

    non_main_df = summary_df.loc[summary_df['main'] == False]
    assert non_main_df.shape[0] == 1
    coords = non_main_df[[
        'coord-src-0', 'coord-src-1', 'coord-dst-0', 'coord-dst-1'
    ]].to_numpy()
    assert (np.all(coords == non_main_edge_start + non_main_edge_finish)
            or np.all(coords == non_main_edge_finish + non_main_edge_start))
예제 #5
0
 def skan(self, n):
     blur = cv2.blur(self.mask, (5, 5))
     binary = blur > filters.threshold_otsu(blur)
     skeleton = morphology.skeletonize(binary)
     ax = plt.subplot(2, 2, 2 * n - 1)
     draw.overlay_skeleton_2d(blur, skeleton, dilate=1, axes=ax)
     branch_data = summarize(Skeleton(skeleton))
     ax = plt.subplot(2, 2, 2 * n)
     draw.overlay_euclidean_skeleton_2d(blur,
                                        branch_data,
                                        skeleton_color_source='branch-type',
                                        axes=ax)
     df1 = branch_data.loc[branch_data['branch-type'] == 1]
     return df1
예제 #6
0
파일: test_draw.py 프로젝트: mkcor/skan
def test_skeleton_class_overlay(test_image, test_skeleton):
    fig, axes = plt.subplots()
    skeleton = Skeleton(test_skeleton, source_image=test_image)
    draw.overlay_skeleton_2d_class(skeleton,
                                   skeleton_color_source='path_lengths')
    def filtered(skeleton):
        means = skeleton.path_means()
        low = means < 0.125
        just_right = (0.125 < means) & (means < 0.625)
        high = 0.625 < means
        return 0 * low + 1 * just_right + 2 * high
    fig, ax = plt.subplots()
    draw.overlay_skeleton_2d_class(skeleton,
                                   skeleton_color_source=filtered,
                                   vmin=0, vmax=2, axes=ax)
    with pytest.raises(ValueError):
        draw.overlay_skeleton_2d_class(skeleton,
                                       skeleton_color_source='filtered')
예제 #7
0
def test_pruning_comprehensive(branch_num):
    skeleton = Skeleton(skeleton0)
    pruned = skeleton.prune_paths([branch_num])
    print(pruned.skeleton_image.astype(int))
    assert pruned.n_paths == 1
예제 #8
0
def branch_classification(thres):
    """
    Predict the extent of branching
    
    Parameters
    ----------
        thres: array
            thresholded image to be analysed
    
    Returns
    -------
        skel: array
            skeletonised image
        is_main:
            help
        BLF: int/float
            branch length fraction
    """

    skeleton = skeletonize(thres)
    skel = Skeleton(skeleton, source_image=thres)
    summary = summarize(skel)

    is_main = np.zeros(summary.shape[0])
    us = summary['node-id-src']
    vs = summary['node-id-dst']
    ws = summary['branch-distance']

    edge2idx = {(u, v): i for i, (u, v) in enumerate(zip(us, vs))}

    edge2idx.update({(v, u): i for i, (u, v) in enumerate(zip(us, vs))})

    g = nx.Graph()

    g.add_weighted_edges_from(zip(us, vs, ws))

    for conn in nx.connected_components(g):
        curr_val = 0
        curr_pair = None
        h = g.subgraph(conn)
        p = dict(nx.all_pairs_dijkstra_path_length(h))
        for src in p:
            for dst in p[src]:
                val = p[src][dst]
                if (val is not None and np.isfinite(val) and val > curr_val):
                    curr_val = val
                    curr_pair = (src, dst)
        for i, j in tz.sliding_window(
                2,
                nx.shortest_path(h,
                                 source=curr_pair[0],
                                 target=curr_pair[1],
                                 weight='weight')):
            is_main[edge2idx[(i, j)]] = 1

    summary['main'] = is_main

    #Branch Length Fraction

    total_length = np.sum(skeleton)
    trunk_length = 0
    for i in range(summary.shape[0]):
        if summary['main'][i]:
            trunk_length += summary['branch-distance'][i]

    branch_length = total_length - trunk_length
    BLF = branch_length / total_length

    return skel, is_main, BLF
예제 #9
0
def to_graph(skeletony, img_):
    print("Creating graph", skeletony.dtype)

    w, h = skeletony.shape

    new_img = np.empty((w, h, 3), dtype=np.uint8)
    new_img[:, :, 0] = img_.astype(np.uint8) * 255
    new_img[:, :, 1] = img_.astype(np.uint8) * 255
    new_img[:, :, 2] = img_.astype(np.uint8) * 0

    previous_one_branches = 9999999

    for i in range(7):

        skeleton_obj = Skeleton(skeletony,
                                source_image=new_img,
                                keep_images=True,
                                unique_junctions=True)

        # https://github.com/jni/skan/issues/92
        branch_data = summarize(skeleton_obj)

        thres = 100

        bt = branch_data['branch-type'].value_counts()

        if 1 in bt.keys():
            num_ones = bt[1]
            if num_ones < previous_one_branches:
                previous_one_branches = bt[1]
            elif num_ones == previous_one_branches:
                print("Cleaned all 1 branches")
                break
        else:
            print("No 1 branches")

        nodes = {}
        outls = {}

        for ii in range(branch_data.shape[0]):
            branch_obj = branch_data.loc[ii]
            node_src = branch_obj.loc['node-id-src']
            node_dst = branch_obj.loc['node-id-dst']
            if node_src == node_dst:
                check_increment_dict(outls, branch_obj, node_dst)
            else:
                check_increment_dict(nodes, branch_obj, node_src)
                check_increment_dict(nodes, branch_obj, node_dst)

            if branch_data.loc[ii,
                               'branch-distance'] < thres and branch_data.loc[
                                   ii, 'branch-type'] == 1:

                integer_coords = tuple(
                    skeleton_obj.path_coordinates(ii)[1:-1].T.astype(int))
                skeletony[integer_coords] = 0

                # Filter pixels with only 1 neighbor
                # integer_coords_all = tuple(skeleton_obj.path_coordinates(ii).T.astype(int))
                # degrees = skeleton_obj.degrees_image[integer_coords_all]

                # for px in range(len(integer_coords_all[0])):
                #     if degrees[px] == 1:
                #         px_tuple = (integer_coords_all[0][px], integer_coords_all[1][px])
                #         skeletony[px_tuple] = 0

                # Filter pixels in branches with 2 pixels
                # pt_idx = skeleton_obj.path(ii)
                # if len(pt_idx) == 2:
                #     for pt in range(len(pt_idx)):
                #         a = sum(x.count(pt_idx[pt]) for x in p_list)
                #         if a == 1:
                #             px_tuple = (integer_coords_all[0][pt], integer_coords_all[1][pt])
                #             skeletony[px_tuple] = 0

        # zas_img = np.zeros((w, h), dtype=np.uint8)
        # # print("Node dict", nodes)
        # single_keys = []
        # # lengs = [single_keys.append(key) if len(nodes[key]) == 3 else '' for key in nodes.keys()]
        # lengs = [single_keys.append(key) for key in outls.keys()]
        # for kk in single_keys:
        #     for nn in nodes[kk]:
        #         if nn['branch-type'] == 3:
        #             print("Branch ", nn['branch-distance'], " ", nn['branch-type'])
        #             print(nn)
        #             integer_coords = tuple(skeleton_obj.path_coordinates(nn.name)[1:-1].T.astype(int))
        #             zas_img[integer_coords] = 255
        #
        # plt.figure()
        # plt.title("Branch type 2")
        # plt.imshow(zas_img)
        # plt.show()

        skeletony = morphology.remove_small_objects(skeletony,
                                                    min_size=2,
                                                    connectivity=2)

        print("New skeletonize")
        skeletony = morphology.binary_dilation(skeletony)
        skeletony = morphology.skeletonize(skeletony)
        print("New skeletonize done")

        # plt.figure()
        # plt.title("Remove branches")
        # plt.imshow(skeletony)
        # plt.show()

    # print("Branch stats", bs)
    # branch_data = summarize(Skeleton(skeletony, unique_junctions=True))
    # print(branch_data.loc[0])
    # draw.overlay_euclidean_skeleton_2d(img_, branch_data)

    return skeletony
예제 #10
0
파일: skanDraft.py 프로젝트: teethoe/Coral
#h, w = imgb.shape[:2]
#imgb = cv2.resize(imgb,(h,h), interpolation=cv2.INTER_CUBIC)
pbef = Process(imgb)
pbef.lowp = np.array([150, 60, 100])
pbef.highp = np.array([170, 255, 255])
pbef.loww = np.array([90, 15, 150])
pbef.highw = np.array([115, 255, 255])
maskb = pbef.mask(kernel)
resb = pbef.res(maskb)
maskb = cv2.blur(maskb, (5, 5))

binaryb = maskb > filters.threshold_otsu(maskb)
skeletonb = morphology.skeletonize(binaryb)
fig, ax = plt.subplots()
draw.overlay_skeleton_2d(maskb, skeletonb, dilate=1, axes=ax)

#graphb = csgraph_from_masked(binaryb)
#plt.imshow(graphb)
gb, cb, db = skeleton_to_csgraph(skeletonb)
draw.overlay_skeleton_networkx(gb, cb, image=maskb)
branch_datab = summarize(Skeleton(skeletonb))
dfb = branch_datab.loc[branch_datab['branch-type'] == 1]

#dfb.to_csv(r'./before.csv')
draw.overlay_euclidean_skeleton_2d(maskb,
                                   branch_datab,
                                   skeleton_color_source='branch-type')

plt.show()
cv2.waitKey(0)
cv2.destroyAllWindows()
예제 #11
0
    save_path = mkpath + '/'
    print("results_folder: " + save_path)

    source_image = cv2.cvtColor(cv2.imread(imgList[0]), cv2.COLOR_BGR2RGB)

    (image_mask, filename, abs_path) = load_image(imgList[0])

    image_skeleton = skeleton_bw(image_mask)

    result_file = (save_path + base_name + '_skeleton.' + ext)
    print(result_file)
    cv2.imwrite(result_file, img_as_ubyte(image_skeleton))

    fig = plt.plot()

    branch_data = summarize(Skeleton(image_skeleton))

    print(branch_data.head())

    fig = plt.plot()

    branch_data.hist(column='branch-distance', by='branch-type', bins=100)

    result_file = (save_path + base_name + '_hist.' + ext)

    plt.savefig(result_file,
                transparent=True,
                bbox_inches='tight',
                pad_inches=0)

    fig = plt.plot()
예제 #12
0
from skan import skeleton_to_csgraph
from skan import Skeleton, summarize

ipath = "your_ct_img_path"  #this is the path to your microCT image files
imgdir = "your_ct_img_folder"
outpath = "your_file_outpath"  #this is the path to where your output files go
"""
Processing
"""
Mint = np.load(outpath + imgdir + "Mint_r" + ".npy")
Mint_uint8 = Mint.astype('uint8')
skel3 = skeletonize_3d(Mint_uint8)
"""
Note:
#Mint is the 3d binary output of the internal void shape
#skel stands for skeleton
#needs a 0 or 1 binary array
"""

#section using skan package, see reference in manuscript for more information
pixel_graph, coordinates, degrees = skeleton_to_csgraph(skel3)
branch_data = summarize(Skeleton(skel3))
branch_data.head()

tot_blength = np.sum(branch_data["branch-distance"])

#output
np.save(outpath + imgdir + "3Dslen", tot_blength)
np.save(outpath + imgdir + "skel3_", skel3)

print("script complete")