Esempio n. 1
0
def getGraph(img,basename):
    img = binariseImage(img) / 255
    ske = skeletonize(img).astype(np.uint16)
    # ske = img.astype('uint16')

    # build graph from skeleton
    graph = sknw.build_sknw(ske)

    # draw edges by pts
    for (s,e) in graph.edges():
        ps = graph[s][e]['pts']
        
    # draw node by o
    nodes = graph.nodes()
    ps = np.array([nodes[i]['o'] for i in nodes])   

    # print('EDGES',graph.edges())
    # print('NODES',graph.nodes())
    
    open('%s_edges.dat' % basename,'w').write(str(graph.edges()))
    open('%s_nodes.dat' % basename,'w').write(str(graph.nodes()))

    edges = np.array(graph.edges())

    return edges, nodes
Esempio n. 2
0
def graph_build():
    name = "Cables"
    thresh = 127
    threshold(name + ".jpg", thresh)
    img = img_as_bool(
        color.rgb2gray(io.imread("Cables_threshold_{}.jpg".format(thresh))))
    ske = skeletonize(~img).astype(np.uint16)
    # build graph from skeleton
    graph = sknw.build_sknw(ske)
    # draw image
    plt.imshow(img, cmap='gray')
    manager = plt.get_current_fig_manager()
    manager.resize(*manager.window.maxsize())
    # draw edges by pts
    for (s, e) in graph.edges():
        ps = graph[s][e]['pts']
        plt.plot(ps[:, 1], ps[:, 0], 'green')
    # draw node by o
    nodes = graph.nodes()
    ps = np.array([nodes[i]['o'] for i in nodes])
    plt.plot(ps[:, 1], ps[:, 0], 'r.')
    # title and show
    plt.title('')
    plt.axis('off')
    plt.show()
Esempio n. 3
0
def find_bridges_between_VLs(img,
                             points,
                             centerOfVLs,
                             result=[],
                             numOfBridges=0):
    src, des = points
    graph = sknw.build_sknw(img)
    # forkPoints = find_nodes(img)
    # show_img(img)
    try:
        # print("Finding the path...")
        path = nx.astar_path(graph, src, des)[1:-1]
        coordinates = np.array([
            coor for p in path for coor in get_node_coordinate(graph, p)
        ]).tolist()
        forkPoints = np.array(find_nodes(img)).tolist()
        forkPoints = [p[::-1] for p in forkPoints]
        voronoi_points = [
            coors for coors in coordinates if coors in forkPoints
        ]
        # print(voronoi_points)
        result.append(voronoi_points)
        for row, col in coordinates:
            img[row][col] = 0
        debug = convert_binary_to_normal_im(img)
        # cv2.imwrite("removed_nodes_{}.png".format(numOfBridges), debug)
    except:
        # print("Result: ", result)
        return result
    numOfBridges += 1
    return find_bridges_between_VLs(img, [src, des], centerOfVLs, result,
                                    numOfBridges)
def process_masks(mask_paths):
    lnstr_df = pd.DataFrame()
    with tqdm(total=len(mask_paths)) as pbar:
        for msk_pth in mask_paths:
            #print(msk_pth)
            msk = imread(msk_pth)
            msk = msk[6:1306, 6:1306]
            msk_nme = msk_pth.split('/')[-1]
            img_id = msk_nme[msk_nme.find('AOI'):msk_nme.find('.')]

            # open and skeletonize
            thresh = 30
            binary = (msk > thresh) * 1

            ske = skeletonize(binary).astype(np.uint16)

            # build graph from skeleton
            graph = sknw.build_sknw(ske, multi=True)
            segments = simplify_graph(graph)

            linestrings = segmets_to_linestrings(segments)
            local = pd.DataFrame()
            local['WKT_Pix'] = linestrings
            local['ImageId'] = img_id

            lnstr_df = pd.concat([lnstr_df, local], ignore_index=True)
            pbar.update(1)
    return lnstr_df
Esempio n. 5
0
def generate_characteristic_array():
    result_array = []
    file_path_array = eachFile('/Users/zkx/PycharmProjects/GraphProject/Base/')
    for path_str in file_path_array:
        result_array_without_type = []
        path_split = path_str.split('/')
        if path_str != '/Users/zkx/PycharmProjects/GraphProject/Base/.DS_Store':
            img = cv2.imread(path_str, 0)
            pic = cv2.resize(img, (300, 300), interpolation=cv2.INTER_CUBIC)

            image = transfer_matrix(pic)
            skeleton = skeletonize(image).astype(np.uint16)
            graph = sknw.build_sknw(skeleton, multi=False)

            draw_edges(graph)
            draw_nodes(graph)
            charac_object = generate_characteristic_set(graph)
            result_array_without_type.append(charac_object.num_node)
            result_array_without_type.append(charac_object.num_edge)
            result_array_without_type.append(charac_object.degree_1)
            result_array_without_type.append(charac_object.degree_2)

            charac_object.type = (path_split[len(path_split) -
                                             1]).split('_')[0]
            result_array_without_type.append(int(charac_object.type))

            result_array.append(result_array_without_type)
            #show_graph(image)

    result_array.sort(key=lambda x: x[4])

    #print(result_array)
    return result_array
Esempio n. 6
0
def find_bridges_between_VLs(img,
                             points,
                             centerOfVLs,
                             result=[],
                             numOfBridges=0):
    src, des = points
    graph = sknw.build_sknw(img)
    forkPoints = findingNodes(img)
    try:
        path = nx.astar_path(graph, src, des)[1:-1]
        coordinates = np.array([
            coor for p in path for coor in get_node_coordinate(graph, p)
        ]).tolist()
        forkPoints = np.array(findingNodes(segment_skeleton)).tolist()
        forkPoints = [p[::-1] for p in forkPoints]
        voronoi_points = [
            coors for coors in coordinates if coors in forkPoints
        ]
        result.append(voronoi_points)
        circle_image(img, coordinates, "bridge", numOfBridges)
        # print(voronoi_points)

        for row, col in coordinates:
            img[row][col] = 0
        debug = convert_binary_to_normal_im(img)
        cv2.imwrite(cwd + "/debug/debug.png", debug)
    except:
        return result
    numOfBridges += 1
Esempio n. 7
0
 def skel2graph(skel):
     """
     @brief Convert the pixel-wide skeleton into a networkx graph.
     @returns a ToolGraph representing the skeleton
              provided as input.
     """
     return endotip.graph.ToolGraph().from_sknw(sknw.build_sknw(skel))
Esempio n. 8
0
    def calculateNavigationGraph(self,
                                 resolution=0.1,
                                 level=0,
                                 safetyMarginEdges=0.1,
                                 algorithm='medial-axis',
                                 shortLeafEdgesThresh=0.5,
                                 squishedLeafNodesThresh=0.15,
                                 redundantNodesThresh=0.25,
                                 longEdgesThreshold=0.5,
                                 doRemoveInaccessibleNodes=True,
                                 zlim=(0.15, 1.50),
                                 isBoundedByFloorMap=True,
                                 roomIds=None):
        occupancyMap, xlim, ylim = self.calculateOccupancyMap(
            resolution, level, zlim, isBoundedByFloorMap, roomIds)

        if algorithm == 'medial-axis':
            skeletonMap = medial_axis(occupancyMap)
        elif algorithm == 'skeleton':
            skeletonMap = skeletonize(occupancyMap)
        else:
            raise Exception('Unsupported algorithm: %s' % (algorithm))

        distOccupancyMap = ndimage.distance_transform_edt(occupancyMap)

        factorX = occupancyMap.shape[0] / \
            (xlim[1] - xlim[0])  # pixel per meter
        factorY = occupancyMap.shape[1] / \
            (ylim[1] - ylim[0])  # pixel per meter
        assert np.allclose(factorX, factorY, atol=1e-6)
        nbSafetyPixels = int(safetyMarginEdges * factorX)
        skeletonMap[distOccupancyMap < nbSafetyPixels] = 0.0

        graph = sknw.build_sknw(skeletonMap)

        graph = getLargestGraphOnly(graph)

        # FIXME: should probably run a loop here for several iterations
        graph = removeSelfEdges(graph)
        graph = removeShortLeafEdges(graph,
                                     threshold=shortLeafEdgesThresh * factorX)
        graph = removeSquishedLeafNodes(graph,
                                        distOccupancyMap,
                                        threshold=squishedLeafNodesThresh *
                                        factorX)
        graph = subdiviseLongEdges(graph,
                                   threshold=longEdgesThreshold * factorX)
        graph = removeRedundantNodes(graph,
                                     threshold=redundantNodesThresh * factorX)
        if doRemoveInaccessibleNodes:
            graph = removeInaccessibleNodes(graph, occupancyMap)

        graph = getLargestGraphOnly(graph)

        graph = NavigationGraph.fromNx(graph, factorX, xlim, ylim)

        return graph, occupancyMap, xlim, ylim
Esempio n. 9
0
def skeleton(img1):
    start = time.time()
    ske = skeletonize(img1).astype(np.uint16)
    # build graph from skeleton
    graph = sknw.build_sknw(ske)
    # print('skeleton : ', time.time()-start)
    # draw image
    plt.imshow(img1, cmap='gray')
    return graph
Esempio n. 10
0
def fine_segmentation(image):
    # Step 1: Thin each oversized segment
    size = get_img_shape(image)
    AveWid = size[1] * 0.8
    segment_skeleton = morphology.skeletonize(image).astype(np.uint16)
    # show_img(segment_skeleton, "Skeleton")

    # Step 2: Draw vertical lines (VLs)
    h, w = shape = np.shape(segment_skeleton)
    # kernel = np.ones((8,1), np.uint8)
    # closingImg = cv2.morphologyEx(img_as_uint(segment_skeleton), cv2.MORPH_CLOSE, kernel)
    projection = [sum(segment_skeleton[:, i]) for i in range(w)]
    # plt.plot(projection)
    # plt.show()
    nMaximumPeaks = np.sort(projection)[w - int(np.ceil(w / AveWid)):w]
    maximumPeakPos = list(set([projection.index(i) for i in nMaximumPeaks]))

    for point in maximumPeakPos:
        segment_skeleton[:, point] = 1
        segment_skeleton[int(h / 2), point + 1] = 1
        segment_skeleton[int(h / 2), point - 1] = 1

    # show_img(segment_skeleton,"Skeleton with VLs")
    # Step 3: Seek and seperate the shortest bridges between every VL pair
    graph = sknw.build_sknw(segment_skeleton)
    node, nodes = graph.node, graph.nodes()
    coordinates = [get_node_coordinate(graph, n) for n in nodes]
    centerOfVLs = [[int(h / 2), p] for p in maximumPeakPos]

    nodesOfVLs = []
    for point in centerOfVLs:
        for index in range(len(coordinates)):
            if (point in coordinates[index].tolist()):
                nodesOfVLs.append(index)
    print("Center of VLs: ", np.sort(nodesOfVLs))
    # draw_point(segment_skeleton, [get_node_coordinate(graph,n) for n in [27]])
    vorPoints = find_bridges_between_VLs(segment_skeleton.copy(), [27, 28],
                                         centerOfVLs)
    print(vorPoints)
    # if (len(vorPoints[0])<4):
    # vorPoints[0].append(vorPoints[1][0])
    combinations = vorPoints
    try:
        combinations[0].append(combinations[1][0])
    except:
        pass
    print(combinations[0])
    # Step 4: Seperated by Voronoi diagrams
    # seperating_points = [voronoi.voronoi_edges(setPoints) for setPoints in combinations]
    seperating_points = voronoi.voronoi_edges(combinations[0])
    print(seperating_points)
    return seperating_points
Esempio n. 11
0
def skeleton(img, save_filepath=None):
    (height, width) = img.shape[:2]
    img = img // 255
    ske = skeletonize(img).astype(np.uint16)

    result = np.zeros((height, width), np.uint8)

    # build graph from skeleton
    graph = sknw.build_sknw(ske, multi=False)

    sknw.draw_graph(result, graph)

    result[result > 0] = 255
    save_image(result, save_filepath)
    return result
def mask_to_line_strings(mask: np.ndarray,
                         sigma: float = 0.5,
                         threshold: float = 0.3,
                         small_obj_size: int = 300,
                         dilation: int = 1):
    mask = prepare_mask(mask=mask,
                        sigma=sigma,
                        threshold=threshold,
                        small_obj_size=small_obj_size,
                        dilation=dilation)

    ske = np.array(skeletonize(mask), dtype="uint8")
    ske = ske[8:-8, 8:-8]
    graph = sknw.build_sknw(ske, multi=True)
    all_coords = prepare_graph_edges(graph)
    line_strings = get_line_strings_from_coords(all_coords)
    return line_strings
Esempio n. 13
0
    def segmentize_slow(self, binarized, min_len=0):

        ske = skeletonize(binarized > 0).astype(numpy.uint8)
        segments = [[]]

        graph = sknw.build_sknw(ske)
        for (s, e) in graph.edges():
            ps = graph[s][e]['pts']
            xx = ps[:, 1]
            yy = ps[:, 0]
            if self.line_length(xx[0], yy[0], xx[-1], yy[-1]) > min_len:
                segment = []
                for i in range(len(xx) - 1):
                    segment.append((xx[i], yy[i]))
                    #skeleton = cv2.line(skeleton, (xx[i], yy[i]), (xx[i + 1], yy[i + 1]), 255, thickness=1)
                segments.append(segment)

        segments = [numpy.array(s) for s in segments]
        return segments
Esempio n. 14
0
def make_graph(skel, image, org):
    graph = sknw.build_sknw(skel, multi=False)

    gr_sensitivity = 15
    gr_lb = np.array([60 - gr_sensitivity, 100, 50])
    gr_ub = np.array([60 + gr_sensitivity, 255, 255])

    rd_sensitivity = 15
    rd_lb = np.array([0 - rd_sensitivity, 50, 50])
    rd_ub = np.array([10 + rd_sensitivity, 255, 255])
    gr = color_coordinate(org, gr_lb, gr_ub)
    rd = color_coordinate(org, rd_lb, rd_ub)
    #print(gr, "    ", rd)

    add_node_to_graph(graph, [gr[1], gr[0]])
    add_node_to_graph(graph, [rd[1], rd[0]])
    add_edge_to_graph(graph, [gr[1], gr[0]], 2)
    add_edge_to_graph(graph, [rd[1], rd[0]], 1)
    return graph
Esempio n. 15
0
def generate_request_charac_array(file_path):
    img = cv2.imread(file_path, 0)
    pic = cv2.resize(img, (300, 300), interpolation=cv2.INTER_CUBIC)

    image = transfer_matrix(pic)
    skeleton = skeletonize(image).astype(np.uint16)
    graph = sknw.build_sknw(skeleton, multi=False)

    draw_edges(graph)
    draw_nodes(graph)
    charac_object = generate_characteristic_set(graph)

    req_result_array = []
    req_result_array.append(charac_object.num_node)
    req_result_array.append(charac_object.num_edge)
    req_result_array.append(charac_object.degree_1)
    req_result_array.append(charac_object.degree_2)

    #print(req_result_array)
    return req_result_array
Esempio n. 16
0
    def GetGraphFromImage(self, imageFileName):
        # open and skeletonize
        filePath = Closing2Folder + imageFileName;
        img24bit = imread(filePath)
        img =  np.array(Image.fromarray(img24bit).quantize(colors=2, method=2))
        # self.Show(img)

        binary = img > filters.threshold_otsu(img,100)

        #self.Show(img);

        self.binaryImg = binary
        ske = skeletonize(binary).astype(np.uint16)

        #self.ShowSkeleton(img,ske)
        self.SaveSkeleton(img, ske, imageFileName)

        # build graph from skeleton
        graph = sknw.build_sknw(ske)

        return graph
Esempio n. 17
0
def extract_centerlines_sknw(edges):
    skel = skeletonize(256 - edges > 128)
    skg = sknw.build_sknw(skel.astype(np.uint16),
                          multi=False,
                          iso=True,
                          ring=False)
    lines = []
    for (s, e) in skg.edges():
        ps = skg[s][e]['pts']
        lines.append(
            geom.LineString(ps[:, ::-1] * np.array([1, -1]) +
                            np.array([0, 256])))

    # prune lines too long/short
    lines = [
        line for line in lines if
        max(line.length,
            geom.Point(line.coords[0]).distance(geom.Point(
                line.coords[-1]))) > 4
    ]

    return lines
Esempio n. 18
0
def vectorize(blob):
    (skel, dist), path = blob

    logger.info(f"Vectorizing {path}...")
    graph = sknw.build_sknw(skel)

    df = gpd.GeoDataFrame(columns=['geometry', 'width'])

    ul, lr = get_geotiff_bbox(path)
    dy = ul[0] - lr[0]
    dx = lr[1] - ul[1]

    for s, e in graph.edges():
        H, W = dist.shape
        widths = [dist[tuple(pt)] for pt in graph[s][e]['pts']]
        width = np.percentile(widths, 33) / H * dy
        N = len(graph[s][e]['pts']) + 2
        pts = np.zeros((N, 2), dtype=np.float64)
        pts[0] = graph.node[s]['o']
        pts[-1] = graph.node[e]['o']
        pts[1:-1] = graph[s][e]['pts']

        pts[:, 0] = 1 - pts[:, 0] / H
        pts[:, 0] *= dy
        pts[:, 0] += lr[0]

        pts[:, 1] = pts[:, 1] / W
        pts[:, 1] *= dx
        pts[:, 1] += ul[1]

        df = df.append({
            'geometry': LineString(pts[:, ::-1]),
            'width': width
        },
                       ignore_index=True)
    return df
Esempio n. 19
0
def extract_centerlines_shapes_sknw(edges):
    shapes = vector_trace(edges)

    img = np.zeros((256, 256), dtype=np.uint8)

    shapes = (shape.buffer(0) for shape in shapes)
    polys = [
        poly for poly in shapes
        if type(poly) == geom.Polygon and type(poly.envelope) == geom.Polygon
    ]

    as_contour = [
        np.array(poly.exterior.coords).astype(np.int32) for poly in polys
    ]
    as_contour = [c[:, np.newaxis, :] for c in as_contour]
    cv2.drawContours(img, as_contour, -1, 255, -1)

    skel = skeletonize(img > 128)
    skg = sknw.build_sknw(skel.astype(np.uint16),
                          multi=False,
                          iso=True,
                          ring=False)
    lines = []
    for (s, e) in skg.edges():
        ps = skg[s][e]['pts']
        lines.append(geom.LineString(ps[:, ::-1]))

    # prune lines too long/short
    lines = [
        line for line in lines if
        max(line.length,
            geom.Point(line.coords[0]).distance(geom.Point(
                line.coords[-1]))) > 4
    ]

    return lines
Esempio n. 20
0
def nodes(mask):
    """
    Inputs
        mask -- thresholded query image
    Outputs
        new_node_centers -- coordinates of each branching point, which is the center of each roi
    """
    # Skeletonize tree and build graph network
    skeleton = skeletonize(mask // 255).astype(np.uint16)
    graph = sknw.build_sknw(skeleton)
    nodes = graph.nodes()
    node_centers = np.array([nodes[i]['o'] for i in nodes])

    # Filter out nodes at tips of branches, keeping only nodes that define the centers of each ROI
    copy = graph.copy()
    for i in range(len(node_centers)):
        conn = [n for n in graph.neighbors(i)]
        if len(conn) < 3:
            copy.remove_node(i)
    new_nodes = copy.nodes()
    new_node_centers = np.array([new_nodes[i]['o']
                                 for i in new_nodes]).astype(int)

    return new_node_centers
Esempio n. 21
0
# load the image, convert it to grayscale, blur it slightly,
# and threshold it
image = cv2.imread('moment.jpg')
image = image[167:972, 0:1920]
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
blurred = cv2.GaussianBlur(gray, (5, 5), 0)
thresh = cv2.threshold(blurred, 60, 255, cv2.THRESH_BINARY)[1]
#image = thresh

#roi = thresh[167:972, 0:1920]
roi = cv2.bitwise_not(thresh)
#cv2.rectangle(image,(0,166),(1920,972),(0,255,0),1)

skeleton = skeletonize_3d(roi)

graph = sknw.build_sknw(skeleton)
plt.imshow(image, cmap='gray')

for (s, e) in graph.edges():
    ps = graph[s][e]['pts']
    plt.plot(ps[:, 1], ps[:, 0], 'green')

# draw node by o
node, nodes = graph.node, graph.nodes()
ps = np.array([node[i]['o'] for i in nodes])
plt.plot(ps[:, 1], ps[:, 0], 'r.')

# title and show
plt.title('Build Graph')
plt.show()
Esempio n. 22
0
def extract_graphs(sillh_skel):
    G = sknw.build_sknw(sillh_skel[1])
    G.remove_nodes_from(list(nx.isolates(G)))
    return (sillh_skel[0], sillh_skel[1], G)
Esempio n. 23
0
img = cv2.imread("img_eroded.png")
kernel = np.ones((1, 1), np.uint8)

#Convert to GrayScaledImage
grayscaled = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

retval, threshold = cv2.threshold(grayscaled, 10, 255,
                                  cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)
retval, threshold2 = cv2.threshold(threshold, 10, 255, cv2.THRESH_BINARY_INV)
threshold2[threshold2 == 255] = 1

#Skeletonize the Thresholded Image
skel = skeletonize(threshold2)

#Build Graph from skeleton
graph = sknw.build_sknw(skel, multi=False)
G = nx.Graph(graph)

#plt.imshow(img, cmap='gray')
plt.axis('off')

#for (s,e) in graph.edges():
#        ps = graph[s][e]['pts']
#        plt.plot(ps[:,1], -ps[:,0], 'red')

#print(graph.edges())
print(nx.shortest_path(G, source=0, target=4))

#Draw Edges by 'pts'
i = 0
while i < (len(nx.shortest_path(G, source=0, target=4)) - 1):
Esempio n. 24
0
def to_line_strings(mask,
                    sigma=0.5,
                    threashold=0.3,
                    small_obj_size=300,
                    dilation=1):
    mask = gaussian(mask, sigma=sigma)
    mask = mask[..., 0]
    mask[mask < threashold] = 0
    mask[mask >= threashold] = 1
    mask = np.array(mask, dtype="uint8")
    mask = mask[:1300, :1300]
    mask = cv2.copyMakeBorder(mask, 8, 8, 8, 8, cv2.BORDER_REPLICATE)
    if dilation > 0:
        mask = binary_dilation(mask, iterations=dilation)
    mask, _ = ndimage.label(mask)
    mask = remove_small_objects(mask, small_obj_size)
    mask[mask > 0] = 1

    ske = np.array(skeletonize(mask), dtype="uint8")
    ske = ske[8:-8, 8:-8]
    graph = sknw.build_sknw(ske, multi=True)
    line_strings = []
    lines = []
    all_coords = []
    node, nodes = graph.node, graph.nodes()
    # draw edges by pts
    for (s, e) in graph.edges():
        for k in range(len(graph[s][e])):
            ps = graph[s][e][k]['pts']
            coords = []
            start = (int(nodes[s]['o'][1]), int(nodes[s]['o'][0]))
            all_points = set()

            for i in range(1, len(ps)):
                pt1 = (int(ps[i - 1][1]), int(ps[i - 1][0]))
                pt2 = (int(ps[i][1]), int(ps[i][0]))
                if pt1 not in all_points and pt2 not in all_points:
                    coords.append(pt1)
                    all_points.add(pt1)
                    coords.append(pt2)
                    all_points.add(pt2)
            end = (int(nodes[e]['o'][1]), int(nodes[e]['o'][0]))

            same_order = True
            if len(coords) > 1:
                same_order = np.math.hypot(
                    start[0] - coords[0][0],
                    start[1] - coords[0][1]) <= np.math.hypot(
                        end[0] - coords[0][0], end[1] - coords[0][1])
            if same_order:
                coords.insert(0, start)
                coords.append(end)
            else:
                coords.insert(0, end)
                coords.append(start)
            coords = simplify_coords(coords, 2.0)
            all_coords.append(coords)

    for coords in all_coords:
        if len(coords) > 0:
            line_obj = LineString(coords)
            lines.append(line_obj)
            line_string_wkt = line_obj.wkt
            line_strings.append(line_string_wkt)
    new_lines = remove_duplicates(lines)
    new_lines = filter_lines(new_lines, calculate_node_count(new_lines))
    line_strings = [l.wkt for l in new_lines]
    return line_strings
Esempio n. 25
0
def to_line_strings(mask, sigma=0.5, threashold=0.3, small_obj_size=300, dilation=1):
    mask = gaussian(mask, sigma=sigma)
    mask = mask[..., 0]
    mask[mask < threashold] = 0
    mask[mask >= threashold] = 1
    mask = np.array(mask, dtype="uint8")
    mask = mask[:1300, :1300]
    mask = cv2.copyMakeBorder(mask, 8, 8, 8, 8, cv2.BORDER_REPLICATE)
    if dilation > 0:
        mask = binary_dilation(mask, iterations=dilation)
    mask, _ = ndimage.label(mask)
    mask = remove_small_objects(mask, small_obj_size)
    mask[mask > 0] = 1

    ske = np.array(skeletonize(mask), dtype="uint8")
    ske=ske[8:-8,8:-8]
    graph = sknw.build_sknw(ske, multi=True)
    line_strings = []
    lines = []
    all_coords = []
    node, nodes = graph.node, graph.nodes()
    # draw edges by pts
    for (s, e) in graph.edges():
        for k in range(len(graph[s][e])):
            ps = graph[s][e][k]['pts']
            coords = []
            start = (int(nodes[s]['o'][1]), int(nodes[s]['o'][0]))
            all_points = set()

            for i in range(1, len(ps)):
                pt1 = (int(ps[i - 1][1]), int(ps[i - 1][0]))
                pt2 = (int(ps[i][1]), int(ps[i][0]))
                if pt1 not in all_points and pt2 not in all_points:
                    coords.append(pt1)
                    all_points.add(pt1)
                    coords.append(pt2)
                    all_points.add(pt2)
            end = (int(nodes[e]['o'][1]), int(nodes[e]['o'][0]))

            same_order = True
            if len(coords) > 1:
                same_order = np.math.hypot(start[0] - coords[0][0], start[1] - coords[0][1]) <= np.math.hypot(end[0] - coords[0][0], end[1] - coords[0][1])
            if same_order:
                coords.insert(0, start)
                coords.append(end)
            else:
                coords.insert(0, end)
                coords.append(start)
            coords = simplify_coords(coords, 2.0)
            all_coords.append(coords)

    for coords in all_coords:
        if len(coords) > 0:
            line_obj = LineString(coords)
            lines.append(line_obj)
            line_string_wkt = line_obj.wkt
            line_strings.append(line_string_wkt)
    new_lines = remove_duplicates(lines)
    new_lines = filter_lines(new_lines, calculate_node_count(new_lines))
    line_strings = [ l.wkt for l in new_lines]
    return line_strings
Esempio n. 26
0
    def analyze(self, plant, side, c_entry, min_area):

        self.plant = plant
        self.side = side
        self.c_entry = c_entry
        self.min_area = min_area
        self.progress = 0
        '''Does image analysis on the file and outputs the lengths'''

        self.overlay = self.img.copy()

        if self.plant == "coleoptile":
            img2 = cv2.cvtColor(self.img, cv2.COLOR_BGR2GRAY)
            median = cv2.medianBlur(img2, 5)
            blur = cv2.bilateralFilter(median, 9, 75, 75)
            _, mask = cv2.threshold(blur, 0, 255,
                                    cv2.THRESH_BINARY + cv2.THRESH_OTSU)

        elif self.plant == "seedling":
            img2 = cv2.cvtColor(self.img, cv2.COLOR_BGR2HSV)
            median = cv2.medianBlur(img2, 5)
            blur = cv2.bilateralFilter(median, 9, 75, 75)
            lower_thres = np.array(
                [self.hue_lower, self.sat_lower, self.val_lower])
            upper_thres = np.array(
                [self.hue_upper, self.sat_upper, self.val_upper])
            mask = cv2.inRange(blur, lower_thres, upper_thres)

        # Noise removal with opening and closing
        kernel = np.ones((5, 5), np.uint8)
        closing = cv2.morphologyEx(mask, cv2.MORPH_CLOSE, kernel)

        # Calibration
        if self.side == "right":
            cal = blur[self.img.shape[0]-self.img.shape[0]//5:,\
                self.img.shape[1]-self.img.shape[1]//5:]

        elif self.side == "left":
            cal = blur[self.img.shape[0]-self.img.shape[0]//5:,\
                :self.img.shape[1]//5]

        # Thresholding and stuff for calibrator
        if self.plant == "seedling":
            cal = cv2.split(cal)[2]  # Get grayscale

        _, calth = cv2.threshold(cal, 0, 255,
                                 cv2.THRESH_BINARY + cv2.THRESH_OTSU)
        calcont = cv2.findContours(calth, cv2.RETR_TREE,
                                   cv2.CHAIN_APPROX_SIMPLE)[1]

        maxArea = 0
        for contour in calcont:
            # Calibrator is the biggest contour in that region
            if cv2.contourArea(contour) > maxArea:
                scale = cv2.boundingRect(contour)[2]
                maxArea = cv2.contourArea(contour)

        # For displaying the results
        self.result = []
        self.firstline = "Calibration: {}mm={} pixels; 1 pixel={:.3f}mm\n\n".format(\
                      self.c_entry, scale, self.c_entry/scale)
        self.result.append(self.firstline)

        # Core of the program...one line
        contours = cv2.findContours(closing, cv2.RETR_TREE,
                                    cv2.CHAIN_APPROX_SIMPLE)[1]

        # Progress bar
        progress = len(
            [x for x in contours if cv2.contourArea(x) > self.min_area])
        print("Progress: [{}]".format(" " * 30), end='')
        print("\b" * 31, end='')
        stdout.flush()

        # Initialization
        cc = 0
        all_results = []

        for contour in contours:
            # Detects only large enough contours
            if cv2.contourArea(contour) < self.min_area:
                continue

            cc += 1
            temp_results = [str(cc)]

            # Draw just one contour and skeletonize it
            temp_array = np.zeros(closing.shape, dtype=np.uint8)
            cv2.fillPoly(temp_array, [contour], color=(255, 255, 255))
            skeltest = skeletonize(temp_array / 255)

            graph = sknw.build_sknw(skeltest)  # Build graph

            # Prune the graph only for seedlings
            if self.plant == "seedling":
                degree_list = [
                    node for node, degree in graph.degree if degree == 1
                ]  # List of terminal nodes

                while degree_list:
                    node = degree_list[0]
                    neighbor = list(graph.neighbors(node))[0]

                    # If the edge is shorter than a threshold and it's not the lowest node
                    # and there isn't just two nodes left...
                    if graph[node][neighbor]['weight'] < 50 and node != list(graph.nodes)[-1]\
                        and graph.degree(neighbor) != 1:
                        graph.remove_node(node)

                        # If neighbor becomes terminal node, add to the list
                        if graph.degree(neighbor) == 1:
                            degree_list.append(neighbor)

                    degree_list.pop(0)

                # Pruning again - remove repeat edges (RARE)
                for x, y in graph.edges:
                    if x == y:
                        graph.remove_edge(x, y)

            # Some useful values
            node, nodes = graph.nodes, list(graph.nodes)
            branch_pts = [key for key, value in graph.degree if value == 3]
            branch_pts.sort(reverse=True)

            # TOTAL SHOOT LENGTH
            # For coleoptile, get the longest path possible
            if self.plant == "coleoptile":
                length = max(nx.single_source_dijkstra_path_length(graph,\
                        nodes[-1]).values())
                branch_pts = []

            # For seedling, get length from lowest to highest node (= plant length)
            elif self.plant == "seedling":
                length = nx.dijkstra_path_length(graph, nodes[-1], nodes[0])

            temp_results.append(length * self.c_entry / scale)

            # LEAF LENGTHS AND INTERNODES
            for i in range(len(branch_pts)):
                branch_pt = branch_pts[i]

                # Select the two "higher" nodes from the neighbors
                n1, n2, _ = sorted(graph.neighbors(branch_pt))

                # If it's not the last branch
                if i != len(branch_pts) - 1:

                    # Internode length
                    interLength = nx.dijkstra_path_length(
                        graph, branch_pt, branch_pts[i + 1])

                    # Determine leaf node - it's the one NOT in the longest path
                    if n1 in nx.dijkstra_path(graph, nodes[-1], nodes[0]):
                        leaf_node = self.findTerminalNode(graph, branch_pt, n2)

                    else:
                        leaf_node = self.findTerminalNode(graph, branch_pt, n1)

                    # Append results without correction
                    if i != 0:
                        temp_results.append(interLength * self.c_entry / scale)

                # For the last branch, determine leaf using distance with internode line
                else:
                    # Approximate orientation by using 100 points below the branching point
                    # Main one: if there is more than one leaf
                    if len(branch_pts) != 1:
                        # Get all the internode points
                        inter = self.mergePoints(graph, branch_pt,
                                                 branch_pts[i - 1])

                        # If the internode is really short, use the first hundred points
                        if len(inter) < 150:
                            inter = inter[:100]

                        # This one uses points a bit further down -> more accurate
                        else:
                            inter = inter[49:149]

                        interApprox1 = inter[0][::-1]
                        interApprox2 = inter[-1][::-1]

                    # Only one branching point, use point above the branching point
                    else:
                        path = nx.dijkstra_path(graph, nodes[-1], nodes[0])

                        interApprox1 = node[branch_pt]['o'][::-1]
                        interApprox2 = graph[branch_pt][path[path.index(branch_pt)+1]]\
                                        ['pts'][-100:][0][::-1]

                    # Compare the distance at the same y point - determine long and short node
                    l_node, l_pts, s_node, s_pts = self.compareNodes(
                        n1, n2, graph, branch_pt)

                    # Starting point for longer node
                    try:
                        start_pt = list(l_pts[:, 0]).index(
                            round(node[s_node]['o'][0]))

                    except ValueError:
                        start_pt = 0

                    # Get the maximum distance from all points on node-branch point edge
                    # to the internode line
                    s_dist = max([self.distanceWiki(interApprox1, interApprox2, each_pt[::-1])\
                                for each_pt in s_pts])

                    l_dist = max([self.distanceWiki(interApprox1, interApprox2, each_pt[::-1])\
                                for each_pt in l_pts[start_pt:]])

                    # The one with the larger maximum distance is the leaf
                    if l_dist > s_dist:
                        leaf_node = l_node

                    else:
                        leaf_node = s_node

                leafLength = nx.dijkstra_path_length(graph, branch_pt,
                                                     leaf_node)

                # Draw leaf
                leaf_pts = self.mergePoints(graph, leaf_node, branch_pt)
                leaf_pts = np.concatenate((leaf_pts[:, [1]], leaf_pts[:, [0]]),
                                          1)
                cv2.polylines(self.overlay, np.int32([leaf_pts]), False,
                              (0, 255, 255), 5)

                # For the first branching point, correct the distance using the distance
                # from the lowest node to the first branch point
                if i == 0:
                    correction = nx.dijkstra_path_length(
                        graph, nodes[-1], branch_pt)

                    # More than one branching point, there is internode
                    if len(branch_pts) != 1:

                        # Fixed weighted average
                        interLength += 0.7 * correction
                        temp_results.append(interLength * self.c_entry / scale)

                    # Fixed weighted average
                    leafLength += 0.8 * correction

                temp_results.append(leafLength * self.c_entry / scale)

            x, y, w, h = cv2.boundingRect(contour)

            # Drawing bounding box and put text
            cv2.rectangle(self.overlay, (x, y), (x + w, y + h), (0, 0, 255), 5)
            cv2.putText(self.overlay,str(cc),(x-15,y-15),cv2.FONT_HERSHEY_SIMPLEX,\
                        4, (0,0,255),5)

            # Results order: total length, internode 1, leaf 1, internode 2, leaf 2, leaf 3, ...
            all_results.append(temp_results)

            # Progress bar :) (look at terminal)
            print('#' * (int(cc / progress * 30) - int(
                (cc - 1) / progress * 30)),
                  end='')
            stdout.flush()

            self.progress = (cc / progress) * 100

        self.results = {1: {'val': all_results}}  # For grouping
        self.calcStatistics()
        self.showText()

        # Display new image with bounding box
        b, g, r = cv2.split(self.overlay)
        temp = cv2.merge((r, g, b))
        #temp = Image.fromarray(temp)
        self.showImg(temp)
        #self.flushResults()

        # Checkpoint
        self.analyzed = True

        return True, self.results
Esempio n. 27
0
def build_graph_single(datapath,
                       debug=False,
                       threshes=0.5,
                       add_small=True,
                       fix_borders=False,
                       reverse=False,
                       inputTiff=None):
    city = os.path.splitext(datapath)[0].split('/')[-1]
    img_copy, ske = make_skeleton(datapath, debug, threshes, fix_borders,
                                  reverse)
    if ske is None:
        print(datapath)
        print('[I] ske is None')
        return city, [linestring.format("EMPTY")]
    G = sknw.build_sknw(ske, multi=True)
    remove_small_terminal(G)
    node_lines = graph2lines(G)
    if not node_lines:
        print(datapath)
        return city, [linestring.format("EMPTY")]
    node = G.node
    deg = G.degree()
    wkt = []
    terminal_points = [i for i, d in deg.items() if d == 1]

    terminal_lines = {}
    vertices = []
    for w in node_lines:
        coord_list = []
        additional_paths = []
        for s, e in pairwise(w):
            vals = flatten([[v] for v in G[s][e].values()])
            for ix, val in enumerate(vals):

                s_coord, e_coord = node[s]['o'], node[e]['o']
                pts = val.get('pts', [])
                if s in terminal_points:
                    terminal_lines[s] = (s_coord, e_coord)
                if e in terminal_points:
                    terminal_lines[e] = (e_coord, s_coord)

                ps = add_direction_change_nodes(pts, s, e, s_coord, e_coord)

                if len(ps.shape) < 2 or len(ps) < 2:
                    continue

                if len(ps) == 2 and np.all(ps[0] == ps[1]):
                    continue

                ps_ = np.zeros_like(ps) * 1.00
                dataset = gdal.Open(inputTiff)
                trans = dataset.GetGeoTransform()
                #print(ps)
                ps_[:, 1] = trans[0] * 1.0 + ps[:, 1] * 1.0 * trans[
                    1] + ps[:, 0] * 1.0 * trans[2]
                ps_[:, 0] = trans[3] * 1.0 + ps[:, 1] * 1.0 * trans[
                    4] + ps[:, 0] * 1.0 * trans[5]
                #print(ps_)
                line_strings = [
                    "{1:.10f} {0:.10f}".format(*c.tolist()) for c in ps_
                ]
                if ix == 0:
                    coord_list.extend(line_strings)
                else:
                    additional_paths.append(line_strings)

                vertices.append(ps_)

        if not len(coord_list):
            continue
        segments = remove_duplicate_segments(coord_list)
        for coord_list in segments:
            if len(coord_list) > 1:
                line = '(' + ", ".join(coord_list) + ')'
                wkt.append(linestring.format(line))
        for line_strings in additional_paths:
            line = ", ".join(line_strings)
            line_rev = ", ".join(reversed(line_strings))
            for s in wkt:
                if line in s or line_rev in s:
                    break
            else:
                wkt.append(linestring.format('(' + line + ')'))

    if add_small and len(terminal_points) > 1:
        pass
        #wkt.extend(add_small_segments(G, terminal_points, terminal_lines))

    if debug:
        vertices = flatten(vertices)
        visualize(img_copy, G, vertices)

    if not wkt:
        return city, [linestring.format("EMPTY")]
    return city, wkt
def extract_graphs(skeletons):
    graphs = [sknw.build_sknw(ske) for ske in skeletons]
    for G in graphs:
        G.remove_nodes_from(list(nx.isolates(G)))
    return graphs
Esempio n. 29
0
    for i in range(len(projection)):
        if projection[i] in nMaximumPeaks:
            maximumPeakPos.append(i)
    # print(maximumPeakPos)

    for point in maximumPeakPos:
        segment_skeleton[:, point] = 1
        segment_skeleton[int(h / 2), point + 1] = 1
        segment_skeleton[int(h / 2), point - 1] = 1
    # show_img(segment_skeleton)

    cv2.imwrite(cwd + "/debug/VL_image.png",
                convert_binary_to_normal_im(segment_skeleton))

    # Step 3: Seek and seperate the shortest bridges between every VL pair
    graph = sknw.build_sknw(segment_skeleton)
    node, nodes = graph.node, graph.nodes()
    coordinates = [get_node_coordinate(graph, n) for n in nodes]
    centerOfVLs = [[int(h / 2), p] for p in maximumPeakPos]

    nodesOfVLs = []
    for point in centerOfVLs:
        for index in range(len(coordinates)):
            if (point in coordinates[index].tolist()):
                nodesOfVLs.append(index)
    print(nodesOfVLs)

    result = find_bridges_between_VLs(segment_skeleton, graph, [25, 22])
    # # result = np.reshape(result, (len(result),1))
    # # print("Shape: ", np.shape(result))
    # x = [result[i][0] for i in range(len(result))]
def build_graph(root, fn, debug=False, threshes={'2': .3, '3': .3, '4': .3, '5': .2}, add_small=True, fix_borders=True):
    # city = os.path.splitext(fn)[0][5:]
    city = fn
    img_copy, ske = make_skeleton(root, fn, debug, threshes, fix_borders)
    if ske is None:
        return city, [linestring.format("EMPTY")]
    G = sknw.build_sknw(ske, multi=True)
    print(fn)
    print(G)
    remove_small_terminal(G)
    node_lines = graph2lines(G)
    if not node_lines:
        return city, [linestring.format("EMPTY")]
    node = G.node
    deg = G.degree()
    wkt = []
    # terminal_points = [i for i, d in deg.items() if d == 1]
    terminal_points = [i for i, d in dict(deg).items() if d == 1]

    terminal_lines = {}
    vertices = []
    for w in node_lines:
        coord_list = []
        additional_paths = []
        for s, e in pairwise(w):
            vals = flatten([[v] for v in G[s][e].values()])
            for ix, val in enumerate(vals):

                s_coord, e_coord = node[s]['o'], node[e]['o']
                pts = val.get('pts', [])
                if s in terminal_points:
                    terminal_lines[s] = (s_coord, e_coord)
                if e in terminal_points:
                    terminal_lines[e] = (e_coord, s_coord)

                ps = add_direction_change_nodes(pts, s, e, s_coord, e_coord)

                if len(ps.shape) < 2 or len(ps) < 2:
                    continue

                if len(ps) == 2 and np.all(ps[0] == ps[1]):
                    continue

                line_strings = ["{1:.1f} {0:.1f}".format(*c.tolist()) for c in ps]
                if ix == 0:
                    coord_list.extend(line_strings)
                else:
                    additional_paths.append(line_strings)

                vertices.append(ps)

        if not len(coord_list):
            continue
        segments = remove_duplicate_segments(coord_list)
        for coord_list in segments:
            if len(coord_list) > 1:
                line = '(' + ", ".join(coord_list) + ')'
                wkt.append(linestring.format(line))
        for line_strings in additional_paths:
            line = ", ".join(line_strings)
            line_rev = ", ".join(reversed(line_strings))
            for s in wkt:
                if line in s or line_rev in s:
                    break
            else:
                wkt.append(linestring.format('(' + line + ')'))

    if add_small and len(terminal_points) > 1:
        wkt.extend(add_small_segments(G, terminal_points, terminal_lines))

    if debug:
        vertices = flatten(vertices)
        visualize(img_copy, G, vertices)

    if not wkt:
        return city, [linestring.format("EMPTY")]
    return city, wkt
Esempio n. 31
0
def vectorize(blob):
    (skel, dist), path = blob

    logger.info(f"Vectorizing {path}...")
    graph = sknw.build_sknw(skel)
    df = gpd.GeoDataFrame(columns=['geometry', 'width'])

    ul, lr = get_geotiff_bbox(path)
    dy = ul[0] - lr[0]
    dx = lr[1] - ul[1]

    for s, e in graph.edges():
        H, W = dist.shape
        widths = [
            dist[tuple(pt)] for pt in graph[s][e]['pts'].astype(np.int32)
        ]
        width = np.percentile(widths, 33) / H * dy

    graph[s][e]['pts'] = simplify_coords(graph[s][e]['pts'], 2.0)

    # Pop short stubs
    pops = []
    for (s, e) in graph.edges():
        if graph[s][e]['weight'] < 10 and (len(graph[s]) == 1
                                           or len(graph[e]) == 1):
            pops += [(s, e)]
    for s, e in pops:
        graph.remove_edge(s, e)

    # Pop orphaned nodes
    pops = []
    for node in graph.nodes():
        if len(graph[node]) == 0:
            pops += [node]
    for node in pops:
        graph.remove_node(node)

    # Bind nearby point pairs
    for n1, n2 in combinations(graph.node, 2):
        diff = la.norm(graph.node[n1]['o'] - graph.node[n2]['o'])
        if diff < 20 and n2 not in graph[n1]:
            pts = np.zeros((3, 2))
            pts[0, :] = graph.node[n1]['o']
            pts[1, :] = (graph.node[n1]['o'] + graph.node[n2]['o']) / 2
            pts[2, :] = graph.node[n2]['o']
            graph.add_edge(n1, n2, pts=pts, weight=diff)

    # Bind points along a line
    for n1 in graph.node:
        pushes = []
        for n2 in graph[n1]:
            for n3 in graph.node:
                vec1 = graph.node[n1]['o'] - graph.node[n2]['o']
                vec2 = graph.node[n3]['o'] - graph.node[n1]['o']
                diff = la.norm(vec2)
                vec1 /= la.norm(vec1)
                vec2 /= diff
                try:
                    angle = np.arccos(vec1 @ vec2) * 180 / np.pi
                except:
                    logger.critical("Could not compute points on vector!")
                    angle = 90
                if abs(angle % 360) < 2 and diff < 150:
                    pts = np.zeros((3, 2))
                    pts[0, :] = graph.node[n1]['o']
                    pts[1, :] = (graph.node[n1]['o'] + graph.node[n3]['o']) / 2
                    pts[2, :] = graph.node[n3]['o']
                    pushes += [(n1, n3, pts, diff)]
        for n1, n2, pts, diff in pushes:
            graph.add_edge(n1, n2, pts=pts, weight=diff)

    for s, e in graph.edges():
        N = len(graph[s][e]['pts']) + 2
        pts = np.zeros((N, 2), dtype=np.float64)
        pts[0] = graph.node[s]['o']
        pts[-1] = graph.node[e]['o']
        pts[1:-1] = graph[s][e]['pts']

        pts[:, 0] = 1 - pts[:, 0] / H
        pts[:, 0] *= dy
        pts[:, 0] += lr[0]

        pts[:, 1] = pts[:, 1] / W
        pts[:, 1] *= dx
        pts[:, 1] += ul[1]

        df = df.append({
            'geometry': LineString(pts[:, ::-1]),
            'width': width
        },
                       ignore_index=True)
    return df