Exemplo n.º 1
0
def get_external_contour(points, resolution=None):
    """ takes a list of `points` defining a linear ring, which can be 
    self-intersecting, and returns an approximation to the external contour """
    if resolution is None:
        # determine resolution from minimal distance of consecutive points
        dist_min = np.inf
        for p1, p2 in itertools.izip(np.roll(points, 1, axis=0), points):
            dist = curves.point_distance(p1, p2)
            if dist > 0:
                dist_min = min(dist_min, dist)
        resolution = 0.5*dist_min
        
        # limit the resolution such that there are at most 2048 points
        dim_max = np.max(np.ptp(points, axis=0)) #< longest dimension
        resolution = max(resolution, dim_max/2048)

    # build a linear ring with integer coordinates
    ps_int = np.array(np.asarray(points)/resolution, np.int)
    ring = geometry.LinearRing(ps_int)

    # get the image of the linear ring by plotting it into a mask
    x_min, y_min, x_max, y_max = ring.bounds
    shape = ((y_max - y_min) + 3, (x_max - x_min) + 3)
    x_off, y_off = int(x_min - 1), int(y_min - 1)
    mask = np.zeros(shape, np.uint8)
    cv2.fillPoly(mask, [ps_int], 255, offset=(-x_off, -y_off))

    # find the contour of this mask to recover the exterior contour
    contours = cv2.findContours(mask, cv2.RETR_EXTERNAL,
                                cv2.CHAIN_APPROX_SIMPLE,
                                offset=(x_off, y_off))[1]
    return np.array(np.squeeze(contours))*resolution
Exemplo n.º 2
0
def get_external_contour(points, resolution=None):
    """ takes a list of `points` defining a linear ring, which can be 
    self-intersecting, and returns an approximation to the external contour """
    if resolution is None:
        # determine resolution from minimal distance of consecutive points
        dist_min = np.inf
        for p1, p2 in itertools.izip(np.roll(points, 1, axis=0), points):
            dist = curves.point_distance(p1, p2)
            if dist > 0:
                dist_min = min(dist_min, dist)
        resolution = 0.5 * dist_min

        # limit the resolution such that there are at most 2048 points
        dim_max = np.max(np.ptp(points, axis=0))  #< longest dimension
        resolution = max(resolution, dim_max / 2048)

    # build a linear ring with integer coordinates
    ps_int = np.array(np.asarray(points) / resolution, np.int)
    ring = geometry.LinearRing(ps_int)

    # get the image of the linear ring by plotting it into a mask
    x_min, y_min, x_max, y_max = ring.bounds
    shape = ((y_max - y_min) + 3, (x_max - x_min) + 3)
    x_off, y_off = int(x_min - 1), int(y_min - 1)
    mask = np.zeros(shape, np.uint8)
    cv2.fillPoly(mask, [ps_int], 255, offset=(-x_off, -y_off))

    # find the contour of this mask to recover the exterior contour
    contours = cv2.findContours(mask,
                                cv2.RETR_EXTERNAL,
                                cv2.CHAIN_APPROX_SIMPLE,
                                offset=(x_off, y_off))[1]
    return np.array(np.squeeze(contours)) * resolution
Exemplo n.º 3
0
def get_ray_hitpoint(point_anchor, point_far, line_string, ret_dist=False):
    """ returns the point where a ray anchored at point_anchor hits the polygon
    given by line_string. The ray extends out to point_far, which should be a
    point beyond the polygon.
    If ret_dist is True, the distance to the hit point is also returned.
    """
    # define the ray
    ray = geometry.LineString((point_anchor, point_far))

    # find the intersections between the ray and the burrow contour
    try:
        inter = line_string.intersection(ray)
    except geos.TopologicalError:
        inter = None

    # process the result
    if isinstance(inter, geometry.Point):
        if ret_dist:
            # also return the distance
            dist = curves.point_distance(inter.coords[0], point_anchor)
            return inter.coords[0], dist
        else:
            return inter.coords[0]

    elif inter is not None and not inter.is_empty:
        # find closest intersection if there are many points
        dists = [
            curves.point_distance(p.coords[0], point_anchor) for p in inter
        ]
        k_min = np.argmin(dists)
        if ret_dist:
            return inter[k_min].coords[0], dists[k_min]
        else:
            return inter[k_min].coords[0]

    else:
        # return empty result
        if ret_dist:
            return None, np.nan
        else:
            return None
Exemplo n.º 4
0
def get_ray_hitpoint(point_anchor, point_far, line_string, ret_dist=False):
    """ returns the point where a ray anchored at point_anchor hits the polygon
    given by line_string. The ray extends out to point_far, which should be a
    point beyond the polygon.
    If ret_dist is True, the distance to the hit point is also returned.
    """
    # define the ray
    ray = geometry.LineString((point_anchor, point_far))
    
    # find the intersections between the ray and the burrow contour
    try:
        inter = line_string.intersection(ray)
    except geos.TopologicalError:
        inter = None
    
    # process the result    
    if isinstance(inter, geometry.Point):
        if ret_dist:
            # also return the distance
            dist = curves.point_distance(inter.coords[0], point_anchor)
            return inter.coords[0], dist
        else:
            return inter.coords[0]

    elif inter is not None and not inter.is_empty:
        # find closest intersection if there are many points
        dists = [curves.point_distance(p.coords[0], point_anchor) for p in inter]
        k_min = np.argmin(dists)
        if ret_dist:
            return inter[k_min].coords[0], dists[k_min]
        else:
            return inter[k_min].coords[0]
        
    else:
        # return empty result
        if ret_dist:
            return None, np.nan
        else:
            return None
 def get_closest_node(self, point):
     """ get the node that is closest to a given point.
     This function returns three values:
         * the id of the closest node
         * its coordinates
         * the distance of this node to the given point
     """
     node_min, coord_min, dist_min = None, None, np.inf
     for node, data in self.nodes_iter(data=True):
         dist = curves.point_distance(point, data['coords'])
         if dist < dist_min:
             node_min, coord_min, dist_min = node, data['coords'], dist
     
     return node_min, coord_min, dist_min
    def from_skeleton(cls, skeleton, copy=True, post_process=True):
        """ determines the morphological graph from the image `skeleton`
        `copy` determines whether the skeleton is copied before its modified
        `post_process` determines whether some post processing is performed
            that removes spurious edges and nodes
        """
        if copy:
            skeleton = skeleton.copy()
        graph = cls()
        
        # count how many neighbors each point has
        kernel = np.ones((3, 3), np.uint8)
        kernel[1, 1] = 0
        neighbors = cv2.filter2D(skeleton, -1, kernel) * skeleton

        # find an point with minimal neighbors to start iterating from
        neighbors_min = neighbors[neighbors > 0].min()
        ps = np.nonzero(neighbors == neighbors_min)        
        start_point = (ps[1][0], ps[0][0])
        
        # initialize graph by adding first node
        start_node  = graph.add_node_point(start_point)
        edge_seeds = {start_point: start_node}
        
        # iterate over all edges
        while edge_seeds:
            # pick new point from edge_seeds and initialize the point list
            p, start_node = edge_seeds.popitem()
            points = [graph.node[start_node]['coords']]
            
            # iterate along the edge
            while True:
                # handle the current point
                points.append(p)
                skeleton[p[1], p[0]] = 0
                
                # look at the neighborhood of the current point
                ps_n = skeleton[p[1]-1 : p[1]+2, p[0]-1 : p[0]+2]
                neighbor_count = ps_n.sum()
                #print neighbor_count
                
                if neighbor_count == 1:
                    # find the next point along this edge
                    dy, dx = np.nonzero(ps_n)
                    p = (p[0] + dx[0] - 1, p[1] + dy[0] - 1)
                else:
                    # the current point ends the edge
                    break
                
            # check whether we are close to another edge seed
            for p_seed in edge_seeds:
                dist = curves.point_distance(p, p_seed)
                if dist < 1.5:
                    # distance should be either 1 or sqrt(2)
                    if dist > 0:
                        points.append(p_seed)
                    node = edge_seeds.pop(p_seed)
                    points.append(graph.node[node]['coords'])
                    break
            else:
                # could not find a close edge seed => this is an end point
                node = graph.add_node_point(p)
                    
                # check whether we have to branch off other edges
                if neighbor_count > 0:
                    assert neighbor_count > 1
                    # current points is a crossing => branch off new edge seeds
                    # find all points from which we have to branch off
                    dps = np.transpose(np.nonzero(ps_n))
                    # initialize all edge seeds
                    seeds = set([(p[0] + dx - 1, p[1] + dy - 1)
                                 for dy, dx in dps])
                    while seeds:
                        # check the neighbor hood of the seed point
                        p_seed = seeds.pop()
                        skeleton[p_seed[1], p_seed[0]] = 0
                        ps_n = skeleton[p_seed[1]-1 : p_seed[1]+2,
                                        p_seed[0]-1 : p_seed[0]+2]
                        neighbor_count = ps_n.sum()
                        #print 'test_seed', p_seed, neighbor_count
                        if neighbor_count == 1:
                            edge_seeds[p_seed] = node
                        else:
                            # add more seeds
                            dps = np.transpose(np.nonzero(ps_n))
                            for dy, dx in dps:
                                p = (p_seed[0] + dx - 1, p_seed[1] + dy - 1)
                                if p not in seeds and p not in edge_seeds:
                                    seeds.add(p)
                
            # add the edge to the graph
            graph.add_edge_line(start_node, node, points)
              
        if post_process:
            # remove small edges and self-loops
            graph.remove_short_edges(4)
            # remove nodes of degree 2
            graph.simplify()
              
        return graph
        # Finding the max values of the contour i.e. the outline points of the mask.
        # if hierarchy[0][1] != []:

        c = cnts[0]  #max(cnts , key = cv2.contourArea)
        min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(img2, mask=thresh2)
        # Defining the most bottom extreme point of the mask

        bottom = tuple(c[c[:, :, 1].argmax()][0])
        Botx.append(bottom[0])
        Boty.append(bottom[1])
        # Appending the most bottom point coordinates after each iteration and calculating the actual distance moved.
        # Also recording the passing frames to compare against time.
        Bottom_x.append(bottom[0])
        Bottom_y.append(bottom[1])
        bot_distance = 5 * 5.86 * point_distance(
            (Bottom_x[0], Bottom_y[0]), bottom)
        Bot_dist.append(bot_distance)
        Frame_count.append(i)

#==============================================================================
#==============================================================================
#cv2.circle(gray,bottom,5,(255,255,255),-1)
#==============================================================================
#==============================================================================
# Fitting an eclipse around the contour points or the mask.

    for c in cons:

        # Fitting only starts if there are 5 or more outline points as opencv requires this amount for fitting. Also
        # fitting starts only after the flash has passed.