Esempio n. 1
0
def find_centerline_from_loop(loop, ap_coords):
    """Given a loop or lariat structure, do as good a job as possible in finding
    a plausible start/end point for the centerline, then return path coordinates
    along that line."""
    # Basic strategy: assume that the worm nose/tail comes together at some point
    # on the loop. Assume that this point is midway between the lowest and highest
    # value of the ap_coords array along that loop. Then break the loop at that
    # point, and find the shortest path from the nose to tail.
    # This doesn't deal wonderfully with lariat structures, but that's a really hard
    # problem to solve correctly unless the ap coordinate image is really reliable
    # which it currently is not...
    masked_coords = ap_coords.copy()
    masked_coords[~loop] = numpy.nan
    low = numpy.unravel_index(numpy.nanargmin(masked_coords),
                              masked_coords.shape)
    high = numpy.unravel_index(numpy.nanargmax(masked_coords),
                               masked_coords.shape)
    costs = numpy.array(loop, dtype=numpy.float32)
    costs[~loop] = numpy.inf
    path, cost = graph.route_through_array(costs, low, high, geometric=False)
    midpoint = len(path) // 2
    costs[tuple(numpy.transpose(path[midpoint - 1:midpoint +
                                     2]))] = numpy.inf  # break the loop
    path, cost = graph.route_through_array(costs,
                                           path[midpoint - 2],
                                           path[midpoint + 2],
                                           geometric=False)
    return numpy.array(path)
Esempio n. 2
0
def crossover(route1, route2, timeGrid):
  """
    combines two routes of the population to two new routes

    Parameters
    ----------
    route1 : array
      first route which should be used
    route2 : array
      second route which schould be used
    timeGrid: array
      a grid containing the time for one specific context of bearing and speed
    """
  timeGridNew= [[random.random() for i in range(timeGrid.shape[1])] for j in range(timeGrid.shape[0])]
  timeGridNew = np.where(timeGrid >999, timeGrid, timeGridNew)
  
  index1 = math.floor(random.random()*min(len(route1), len(route2)))
  index2 = min(len(route2) -1, len(route1)-1, (index1 + math.floor(random.random()*(len(route1) -index1)+ 10)))

  crossoverPoint1 = route1[index1]

  crossoverPoint2 = route2[index2]

  
  crossoverRoute1, weight = route_through_array(timeGridNew, crossoverPoint1[0:2], crossoverPoint2[0:2], fully_connected=False, geometric=True)
  crossoverRoute1= makeArrays(crossoverRoute1)


  crossoverPoint1 = route2[index1]

  crossoverPoint2 = route1[index2]
  crossoverRoute2, weight = route_through_array(timeGridNew, crossoverPoint1[0:2], crossoverPoint2[0:2], fully_connected=False, geometric=True)
  crossoverRoute2= makeArrays(crossoverRoute2)

      
  child1= []
  child2= []
  for i in range(index1-1):
    child1.append(route1[i])
    child2.append(route2[i])
  for x in crossoverRoute1:
    child1.append(x)
  for x in crossoverRoute2:
    child2.append(x)
  for i in range(index2 +1,len(route2)):
    child1.append(route2[i])
  for i in range(index2 +1,len(route1)):
    child2.append(route1[i])
  return[child1, child2, crossoverRoute1]
Esempio n. 3
0
    def __init__(self, image):
        digit_seg = image > 20
        self._skeleton = morphology.skeletonize(digit_seg)
        morphology.remove_small_objects(self._skeleton, min_size=8, connectivity=2, in_place=True)

        self.top_left = max_score_point(lambda i, j: -1 * (i ** 2 + j ** 2), self._skeleton)
        self.top_right = max_score_point(lambda i, j: -1 * (i ** 2 + (SIZE - 3 - j) ** 2), self._skeleton)
        self.bottom = max_score_point(lambda i, j: i, self._skeleton)
        g = np.where(self._skeleton, 1, 300)
        top, _ = graph.route_through_array(g, self.top_left, self.top_right, geometric=False)
        leg, _ = graph.route_through_array(g, self.top_right, self.bottom, geometric=False)
        self.features = {
            'top': segment_path(top, digit_seg, width=5),
            'leg': segment_path(leg, digit_seg, width=5),
        }
Esempio n. 4
0
    def create_path(self, raster, costSurfaceArray, start, end):
        """
        Calculate the least cost path
        :param raster: Raster file
        :param costSurfaceArray: raster file as numeric array
        :param start: start point
        :param end: end point
        :return: least cost path as grid array
        """

        # coordinates to array index
        startCoordX = start.x
        startCoordY = start.y
        startIndexX, startIndexY = self.coord2pixeloffset(
            raster, startCoordX, startCoordY)

        stopCoordX = end.x
        stopCoordY = end.y
        stopIndexX, stopIndexY = self.coord2pixeloffset(
            raster, stopCoordX, stopCoordY)

        # create path
        indices, weight = route_through_array(costSurfaceArray,
                                              (startIndexY, startIndexX),
                                              (stopIndexY, stopIndexX),
                                              geometric=True,
                                              fully_connected=True)
        indices = np.array(indices).T
        path = np.zeros_like(costSurfaceArray)
        path[indices[0], indices[1]] = 1
        return path
Esempio n. 5
0
def createPath(CostSurfacefn, costSurfaceArray, startCoord, stopCoord):

    # coordinates to array index
    startCoordX = startCoord[0]
    startCoordY = startCoord[1]
    startIndexX, startIndexY = coord2pixelOffset(CostSurfacefn, startCoordX,
                                                 startCoordY)

    stopCoordX = stopCoord[0]
    stopCoordY = stopCoord[1]
    stopIndexX, stopIndexY = coord2pixelOffset(CostSurfacefn, stopCoordX,
                                               stopCoordY)

    # create path
    indices, weight = route_through_array(costSurfaceArray,
                                          (startIndexY, startIndexX),
                                          (stopIndexY, stopIndexX),
                                          geometric=False,
                                          fully_connected=True)
    #mcp_init = MCP(costSurfaceArray, offsets=None, fully_connected=True, sampling=None)
    #indices, weight = mcp_init.find_costs(costSurfaceArray, (startIndexY,startIndexX), (stopIndexY,stopIndexX))
    indices = np.array(indices).T
    path = np.zeros_like(costSurfaceArray)
    path[indices[0], indices[1]] = 1
    return path
Esempio n. 6
0
def createPath(CostSurfacefn,
               costSurfaceArray,
               startCoord,
               stopCoord,
               pathValue=255):
    print np.min(costSurfaceArray)
    print costSurfaceArray.shape

    print startCoord
    print stopCoord
    # coordinates to array index
    startCoordX = startCoord[0]
    startCoordY = startCoord[1]
    startIndexX, startIndexY = coord2pixelOffset(CostSurfacefn, startCoordX,
                                                 startCoordY)

    stopCoordX = stopCoord[0]
    stopCoordY = stopCoord[1]
    stopIndexX, stopIndexY = coord2pixelOffset(CostSurfacefn, stopCoordX,
                                               stopCoordY)

    print startIndexX, startIndexY, stopIndexX, stopIndexY
    # create path
    indices, weight = route_through_array(costSurfaceArray,
                                          (startIndexY, startIndexX),
                                          (stopIndexY, stopIndexX),
                                          geometric=True,
                                          fully_connected=True)
    indices = np.array(indices).T
    path = np.zeros_like(costSurfaceArray)
    path[indices[0], indices[1]] = pathValue
    return path, weight
Esempio n. 7
0
def leastCostSolution(imgArr, boundarySide1indices, boundarySide2indices,
                      step):
    weight = 1e22
    indices = []
    for b1 in range(len(boundarySide1indices)):
        if b1 % step == 0:
            startPoint = np.array(boundarySide1indices[b1], dtype=int)
            #if b1 % step == 0:
            #    print('    '+str(b1+1)+' of '+str(len(boundarySide1indices))+' indices tested')
            for b2 in range(len(boundarySide2indices)):
                if b2 % step == 0:
                    endPoint = np.array(boundarySide2indices[b2], dtype=int)
                    testIndices, testWeight = route_through_array(imgArr, (startPoint[1], startPoint[0]),\
                        (endPoint[1], endPoint[0]), geometric=True,\
                        fully_connected=True)
                    tmpIndices = np.array(testIndices)
                    testIndices = np.hstack([
                        np.reshape(tmpIndices[:, 1],
                                   (np.shape(tmpIndices)[0], 1)),
                        np.reshape(tmpIndices[:, 0],
                                   (np.shape(tmpIndices)[0], 1))
                    ])

                    if testWeight < weight:
                        weight = testWeight
                        indices = testIndices
    return (indices)
Esempio n. 8
0
def get_path_from_cost_surface(cost_dataset, start_point, dest_point):
    CostSurfacefn = "C:\\Users\\Diego\\Desktop\\python_workspace\\10x10_bsp.tif"
    # coordinates to array index
    startCoordX = start_point.x
    startCoordY = start_point.y
    startIndexX, startIndexY = cookbook.coord2pixelOffset(
        CostSurfacefn, startCoordX, startCoordY)

    stopCoordX = dest_point.x
    stopCoordY = dest_point.y
    stopIndexX, stopIndexY = cookbook.coord2pixelOffset(
        CostSurfacefn, stopCoordX, stopCoordY)

    costSurfaceArray = convert_Tiff_raster_to_array(CostSurfacefn)
    _display_array(costSurfaceArray)
    print("##############")
    # create path
    indices, weight = route_through_array(costSurfaceArray,
                                          (startIndexY, startIndexX),
                                          (stopIndexY, stopIndexX),
                                          geometric=True,
                                          fully_connected=True)
    indices = numpy.array(indices).T
    path = numpy.zeros_like(costSurfaceArray)
    path[indices[0], indices[1]] = 1
    _display_array(path)
    return path
Esempio n. 9
0
def createPath(CostSurfacefn,costSurfaceArray,selectedCell,gridfn):   
    # get index of selected cell
    selectedCellIndexX,selectedCellIndexY = cellID2cellIndex(selectedCell,gridfn,CostSurfacefn)
    
    # get index of existing road (first point that occurs)
    StraightLineDict = {}
    count = 0
    roadIndexY, roadIndexX = np.where(costSurfaceArray == 0)
    while count < len(roadIndexY):
        dist =  sqrt((selectedCellIndexY-roadIndexY[count])**2+(selectedCellIndexX-roadIndexX[count])**2)
        index = (roadIndexY[count],roadIndexX[count])        
        StraightLineDict[index] = dist
        count +=1
        
    roadIndex = min(StraightLineDict, key=StraightLineDict.get)

    # create path
    indices, weight = route_through_array(costSurfaceArray, (selectedCellIndexY,selectedCellIndexX), roadIndex)
    indices = np.array(indices).T
    path = np.zeros_like(costSurfaceArray)
    path[indices[0], indices[1]] = 1
    
    # merge path with existing roads
    costSurfaceArray[path == 1] = 0
    return costSurfaceArray
def calculate_path_minimum_profile(de_Lab, start_location, end_location,
                                   r_exp_mm, h_ref_microns):

    [RR, HH] = np.meshgrid(r_exp_mm, h_ref_microns)

    r_start_index = np.array(np.where(r_exp_mm == start_location[0]))
    h_start_index = np.array(np.where(h_ref_microns == start_location[1]))

    r_end_index = np.array(np.where(r_exp_mm == end_location[0]))
    h_end_index = np.array(np.where(h_ref_microns == end_location[1]))

    indices, weight = route_through_array(de_Lab,
                                          [h_start_index, r_start_index],
                                          [h_end_index, r_end_index],
                                          fully_connected=True,
                                          geometric=True)
    indices1 = np.asarray(indices)

    r_path = RR[indices1[:, 0], indices1[:, 1]]
    h_path = HH[indices1[:, 0], indices1[:, 1]]

    path = np.array([r_path, h_path]).T
    points = np.array([start_location, end_location])

    return path, points
Esempio n. 11
0
def least_cost(image, start, end):
	
	indices, cost = route_through_array(image, start, end)
	indices = np.array(indices).T
	path = np.zeros_like(image)
	path[indices[0], indices[1]] = 1
	return path, cost
Esempio n. 12
0
def createPath(costSurfaceArray, startIndexX, startIndexY, stopIndexX,
               stopIndexY):
    indices, weight = route_through_array(costSurfaceArray,
                                          (startIndexY, startIndexX),
                                          (stopIndexY, stopIndexX),
                                          geometric=True,
                                          fully_connected=True)
    indices = np.array(indices).T
    return indices
Esempio n. 13
0
def highlight(img, nodes):
    #axon = np.load('data/s3m0v0/coordinates_axon.npy')
    axon = []
    for startP, endP in nodes:
        cost = np.array(route_through_array(img, startP, endP)[0])
        for i in cost:
            img[tuple(i)] = 255
            axon.append(i)
    return img, axon
Esempio n. 14
0
def plot_tracks(image, trk_averages, trk_points):
    '''
    '''

    if trk_averages is None:
        print('No averages (possibly only one track).')
        return None

    image_rgb = gray2rgb(image)

    # preparing the plot window.
    fig, ax = plt.subplots(nrows=1, ncols=1)

    label_text = ''

    for trk_idx, trk_pt in enumerate(trk_points):

        # calculating route and distances.
        route, _ = route_through_array(~image, trk_pt[0], trk_pt[1])
        distances, _, _ = track_parameters(trk_pt[0], trk_pt[1], route)

        # generating minimal distance line.
        rows, cols = line(trk_pt[0][0], trk_pt[0][1],
                          trk_pt[1][0], trk_pt[1][1])
        image_rgb[rows, cols] = [0, 255, 0]

        # plotting minimal distance and route.
        ax.imshow(image_rgb, cmap='gray')

        for rt_pt in route:
            ax.scatter(rt_pt[1], rt_pt[0], c='b')

        #plotting extreme points.
        for pt in trk_pt:
            ax.scatter(pt[1], pt[0], c='g')

        # preparing the label text.
        label_text += 'Track index: ' + str(trk_idx) + \
                      '\n Extreme points: ' + str(trk_pt[0]) + ', '  + str(trk_pt[1]) + \
                      '\n Length (route): ' + str(len(route)) + \
                      '\n Euclidean distance: ' + str(distances[0]) + \
                      '\n Difference: ' + str(distances[1]) + '\n\n'

    # removing plot ticks.
    ax.axes.get_xaxis().set_ticks([])
    ax.axes.get_yaxis().set_ticks([])

    # removing plot 'spines'.
    ax.spines['top'].set_visible(False)
    ax.spines['bottom'].set_visible(False)
    ax.spines['left'].set_visible(False)
    ax.spines['right'].set_visible(False)

    # setting x label.
    ax.set_xlabel(label_text)

    return None
def plot_and_count(image_bin, intensity_image=None, ax=None):
    """
    """

    if ax is None:
        ax = plt.gca()

    total_tracks = 0
    props = regionprops(label(image_bin))

    img_skel = skeletonize_3d(image_bin)
    rows, cols = np.where(img_skel != 0)

    if intensity_image is not None:
        img_rgb = gray2rgb(img_as_ubyte(intensity_image))
    else:
        img_rgb = gray2rgb(img_as_ubyte(image_bin))

    img_rgb[rows, cols] = [255, 0, 255]

    for prop in props:
        obj_info = []
        aux = skeletonize_3d(prop.image)
        trk_area, trk_px = tracks_classify(aux)
        count_auto = count_by_region(regions_and_skel(prop.image))

        total_tracks += np.sum(count_auto[2])

        x_min, y_min, x_max, y_max = prop.bbox
        obj_info.append(
            [prop.centroid[0], prop.centroid[1],
             str(count_auto[2][0][0])])
        for obj in obj_info:
            ax.text(obj[1],
                    obj[0],
                    obj[2],
                    family='monospace',
                    color='yellow',
                    size='medium',
                    weight='bold')

        if trk_area is not None:
            for px in trk_px:
                route, _ = route_through_array(~aux, px[0], px[1])

                for rx in route:
                    ax.scatter(y_min + rx[1], x_min + rx[0], s=20, c='b')
                for p in px:
                    ax.scatter(y_min + p[1], x_min + p[0], s=20, c='g')

                rows, cols = line(x_min + px[0][0], y_min + px[0][1],
                                  x_min + px[1][0], y_min + px[1][1])
                img_rgb[rows, cols] = [0, 255, 0]

    ax.imshow(img_rgb, cmap='gray')

    return ax, total_tracks
Esempio n. 16
0
    def __init__(self, image):
        digit_seg = image > 20
        self._skeleton = morphology.skeletonize(digit_seg)
        morphology.remove_small_objects(self._skeleton, 8, connectivity=2, in_place=True)
        self.top_left = self._find_top_left()
        self.top_right = max_score_point(lambda x, y: -1 * (x ** 2 + (SIZE - y) ** 2), self._skeleton)
        self.bottom_left = self._find_bottom_left()
        self.bottom_right = max_score_point(lambda x, y: -1 * ((SIZE - x) ** 2 + (SIZE - y) ** 2), self._skeleton)
        self.center = self._find_center()

        g = np.where(self._skeleton, 1, 300)
        top1, _ = graph.route_through_array(g, self.top_left, self.top_right, geometric=False)
        top2, _ = graph.route_through_array(g, self.top_right, self.center, geometric=False)
        bottom1, _ = graph.route_through_array(g, self.bottom_left, self.bottom_right, geometric=False)
        bottom2, _ = graph.route_through_array(g, self.bottom_right, self.center, geometric=False)
        self.features = {
            'top_half': segment_path(top1 + top2, digit_seg),
            'bottom_half': segment_path(bottom1 + bottom2, digit_seg),
        }
Esempio n. 17
0
 def shortest_path(self,p1,p2):
     # Based on Dijkstra's minimum cost path algorithm
     start = self.coord2pixelOffset(*p1)[::-1] #We need to reverse them for the route_to_array
     end = self.coord2pixelOffset(*p2)[::-1]
     indices, weight = route_through_array(
         self.costRaster, start,end,geometric=True,fully_connected=True)
     indices = np.array(indices).T
     path = np.zeros_like(self.costRaster)
     path[indices[0], indices[1]] = 1
     return path, weight
def tracks_classify(image):
    """
    """

    px_ext, px_int = pixels_interest(image)
    trk_areas, trk_points = [], []

    # first, checking the extreme pixels.
    if len(px_ext) == 2:  # only one track (two extreme points).
        return None, None

    while len(px_ext) != 0:
        areas, points = [], []
        if len(px_ext) >= 2:
            for i, j in product(px_ext, px_ext):
                if ((j, i) not in points) and (i is not j):
                    route, _ = route_through_array(~image, i, j)
                    points.append([i, j])
                    areas.append(tracks_by_area(i, j, route, image.shape))

        else:
            # then, checking extreme vs. intersection pixels.
            for i, j in product(px_ext, px_int):
                if ((j, i) not in points) and (i is not j):
                    route, _ = route_through_array(~image, i, j)
                    points.append([i, j])
                    areas.append(tracks_by_area(i, j, route, image.shape))

            # check if an extreme pixel united with an intersection pixel
            # has another part (constituted by an inter px + an ext px)

        # get the best candidate, erase the points and repeat.
        min_idx = min(enumerate(areas), key=itemgetter(1))[0]

        trk_areas.append(areas[min_idx])
        trk_points.append(points[min_idx])

        for point in points[min_idx]:
            if point in px_ext:
                px_ext.remove(point)

    return trk_areas, trk_points
Esempio n. 19
0
def mblur(inpts,image):
    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    blurred = cv2.GaussianBlur(gray, (3, 3), 0)
    edges = auto_canny(blurred)
    edges[-1,:] = 255
    edges[0,:] = 255
    edges[:,-1] = 255
    edges[:,0] = 255
    totpt = len(inpts)
    path = np.zeros_like(edges)
    H,W = edges.shape
    x,y = np.meshgrid(np.arange(W),np.arange(H))
    for i in range(totpt):
        sigma2 = ((inpts[(i+1)%totpt][1]-inpts[i][1])**2 + (inpts[(i+1)%totpt][0]-inpts[i][0])**2 )/4
        gmask = np.exp(-((x-inpts[i][1])**2 + (y-inpts[i][0])**2)/(2.0*100.0))
        gmask += np.exp(-((x-inpts[(i+1)%totpt][1])**2 + (y-inpts[(i+1)%totpt][0])**2)/(2.0*sigma2))
        emask = np.multiply(gmask,edges)/gmask.max()
        emask = 255 - emask
        indices, weight = route_through_array(emask, inpts[i],inpts[(i+1)%totpt])
        indices = np.array(indices).T
        path[indices[0], indices[1]] = 1
    cent = ndimage.measurements.center_of_mass(path)
    h,w = path.shape
    mask = np.zeros((h+2,w+2),dtype=np.uint8)
    cv2.floodFill(path, mask, (int(cent[1]),int(cent[0])), 1)
    skeleton = morphology.skeletonize(path)
    kernel = cv2.getStructuringElement(cv2.MORPH_RECT,(3,3))
    dilim = cv2.dilate(path,kernel,iterations=10)
    erodim = cv2.erode(path,kernel,iterations=5)
    dilb = cv2.dilate(dilim,kernel) - dilim
    im2, contours, hierarchy = cv2.findContours(dilim,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
    x,y,w,h = cv2.boundingRect(contours[0])
    grabmask = np.zeros_like(path)
    # grabmask[y:y+h,x:x+w] = 2
    grabmask[dilim==1] = 3
    grabmask[dilb==1] = 2
    grabmask[skeleton==1] = 1
    bgdModel = np.zeros((1,65),np.float64)
    fgdModel = np.zeros((1,65),np.float64)
    grabmask, bgdModel, fgdModel = cv2.grabCut(image,grabmask,None,bgdModel,fgdModel,1,cv2.GC_INIT_WITH_MASK)
    mask2 = np.where((grabmask==2) | (grabmask==0),0,1).astype('uint8')
    out1 = image*mask2[:,:,np.newaxis]
    mask2 = np.bitwise_or(mask2,erodim)
    out = image*mask2[:,:,np.newaxis]
    ksize = 31
    kernel = np.zeros((ksize,ksize))
    kernel[int((ksize-1)/2),:] = np.ones(ksize)
    kernel/=ksize
    bimg = cv2.filter2D(image,-1,kernel)
    bimg[mask2==1] = 0
    bimg = bimg + out
    plt.imsave("bImg",bimg)
    return bimg
Esempio n. 20
0
def get_perimeter(image_cost, waypoints):
    path = []

    for idx in range(0, len(waypoints)):
        start_point = waypoints[idx]
        end_point = waypoints[(idx + 1) % len(waypoints)]

        path_segment, cost = graph.route_through_array(image_cost, start_point,
                                                       end_point)
        for e in path_segment:
            path.append(e)

    return path
Esempio n. 21
0
def route_through(ips, snap, poins,para):
    para['max']=True
    para['lcost']=2
    img = snap.astype('float32')
    if para['max']: img *= -1
    np.add(img, para['lcost']-img.min(), casting='unsafe', out=img)
    minv, maxv = ips.range
    routes = []
    for line in poins:
        pts = np.array(list(zip(line[:-1], line[1:])))
        for p0, p1 in pts[:,:,::-1].astype(int):
            indices, weight = route_through_array(img, p0, p1)
            routes.append(indices)
    return routes
Esempio n. 22
0
def postGetPath():
    import cv2
    import numpy
    from skimage import graph

    import cells.images.filter

    project_hash = request.form['project_hash']
    project = get_project(project_hash)

    task_hash = request.form['task_hash']
    task_hash_decoded = base64.urlsafe_b64decode(task_hash.encode("ascii"))
    task_type = task_hash_decoded.split("::")[0]
    task_key = task_hash_decoded.split("::")[1]

    image_name = task_key
    image_file = os.path.join(project.get_input_image_directory(), image_name)

    point_1_x = int(request.form['point_1_x'])
    point_1_y = int(request.form['point_1_y'])
    point_2_x = int(request.form['point_2_x'])
    point_2_y = int(request.form['point_2_y'])

    start_r, start_c = point_1_y, point_1_x
    end_r, end_c = point_2_y, point_2_x

    start_point = point_1_y, point_1_x
    end_point = point_2_y, point_2_x

    input_image = cv2.imread(image_file)

    cost_image = cells.images.filter.generate_cost_image_perimeter(input_image)
    # image_intensity = cv2.cvtColor(input_image, cv2.COLOR_BGR2GRAY)

    #cost_image = image_intensity.copy()
    #cost_image = (numpy.max(cost_image) - cost_image)

    print start_point, end_point

    path_segment, cost = graph.route_through_array(cost_image, start_point,
                                                   end_point)

    path = []
    x_y_path = []

    for e in path_segment:
        path.append(e)
        x_y_path.append([e[1], e[0]])

    return jsonify(x_y_path)
Esempio n. 23
0
 def shortest_path(self, p1, p2):
     # Based on Dijkstra's minimum cost path algorithm
     start = self.coord2pixelOffset(
         *p1)[::-1]  #We need to reverse them for the route_to_array
     end = self.coord2pixelOffset(*p2)[::-1]
     indices, weight = route_through_array(self.costRaster,
                                           start,
                                           end,
                                           geometric=True,
                                           fully_connected=True)
     indices = np.array(indices).T
     path = np.zeros_like(self.costRaster)
     path[indices[0], indices[1]] = 1
     return path, weight
Esempio n. 24
0
    def shortest_path(self):
        self.paths = []
        #if segments is empty then don't do anything
        if len(self.segments) == 0:
            return []
        for s in self.segments:
            imshape = self.im.shape
            xmin = min(s[0][0], s[1][0])
            xmax = max(s[0][0], s[1][0])
            ymin = min(s[0][1], s[1][1])
            ymax = max(s[0][1], s[1][1])

            #Calculate local image to compute shortet path, including a buffer around the points of 100px (maybe this should be base?)
            buffer_v = 100
            xmin = int(
                max(xmin - buffer_v, 0)
            )  #n.b. min/max args ensure bounds remain within the image...
            ymin = int(max(ymin - buffer_v, 0))
            xmax = int(min(xmax + buffer_v, self.imshape[0]))
            ymax = int(min(ymax + buffer_v, self.imshape[1]))

            #extract local image
            im = self.im[xmin:xmax, ymin:ymax]

            #get start and end points in local-image coords
            start = [int(s[0][0] - xmin), int(s[0][1] - ymin)]
            end = [int(s[1][0] - xmin), int(s[1][1] - ymin)]

            #compute shortest path
            path, cost = route_through_array(im,
                                             start,
                                             end,
                                             fully_connected=True,
                                             geometric=True)

            if len(self.paths) > 0:
                if path[0][0] + xmin != self.paths[-1][0] or \
                    path[0][1] + ymin != self.paths[-1][1]:
                    for p in reversed(path):
                        self.paths.append([p[0] + xmin, p[1] + ymin])
                else:
                    for p in path:
                        self.paths.append([p[0] + xmin, p[1] + ymin])
            else:
                for p in path:
                    self.paths.append([p[0] + xmin, p[1] + ymin])

            #paths2 = []
        return self.paths  #self.segments
Esempio n. 25
0
    def __find_paths(self):

        logger.debug("Generating Internal Edges...")

        # By using the object image as a mask we find only internal edges and disregard silhouette edges.
        edge_image = feature.canny(self.surface.z_image,
                                   sigma=1,
                                   mask=self.surface.obj_image.astype(bool))

        # Identify all continuous lines.
        labels = measure.label(edge_image, connectivity=2)

        for region in measure.regionprops(labels):
            image = region.image

            if image.shape < (3, 3):
                continue

            # Condition the line to ensure each cell has only one or two neighbours (remove "L"s).
            image = morphology.skeletonize(image)

            # A cell with only one neighbour can be considered as the end of a continuous line, i.e
            # the sum of a cell's 8 surrounding neighbours will equal 1.
            kernel = [[1, 1, 1], [1, 0, 1], [1, 1, 1]]
            convolved = ndimage.convolve(image.astype(float),
                                         kernel,
                                         mode="constant")
            # Refine the convolution to only contain cells which were present in the original image.
            convolved[util.invert(image)] = 0

            # Extract the region coordinates of cells which meet the condition for being a start/end position.
            terminator_pair = np.argwhere(convolved == 1)

            if len(terminator_pair) < 2:
                # Unable to extract two meaningful points.
                continue

            # Make edges have a value of 0 ("cheap").
            image = util.invert(image)

            # An ordered list of coordinates for each line is now found by computing the cheapest route between each
            # terminator_pair.
            route, cost = graph.route_through_array(image, terminator_pair[0],
                                                    terminator_pair[1])

            # Convert regional route coords back to global coords.
            region_offset = [region.bbox[0], region.bbox[1]]
            coords = np.array(route) + region_offset
            self.paths.append(Path(coords, is_rc=True))
Esempio n. 26
0
def cellbody_skeletonization(distmap, threshold, maxthre, physicspacing):
    """
    Function to extract the cell body skeleton after madial axis transform thresholding.
    :param distmap:
    :param threshold:
    :return:
    """
    skelCellBody = {
        'skeleton': [],
        'endpointCoord': [],
        'paths': [],
        'legnths': [],
        'physical-space': physicspacing,
        'threshold': threshold,
        'maxthreshold': maxthre
    }

    BodyThreshInd = distmap < threshold
    distCellBody = deepcopy(distmap)
    distCellBody[BodyThreshInd] = 0

    # if more separate regions are selected, choose the longest one as cell body skeleton by label each separated region
    # and disacrding the shortest ones.
    structure = np.ones(
        (3, 3), dtype=np.int)  # in this case we allow any kind of connection
    labeled, ncomponents = label(distCellBody, structure)
    regprop = regionprops(labeled)

    len_region = [i.perimeter for i in regprop]
    skelCellBody['skeleton'] = labeled == (np.argmax(len_region) + 1)

    # cell body edge detection
    skelCellBody['endpointCoord'] = edgepoint_detect(skelCellBody['skeleton'])

    pathCellBody = []
    cellBodyLengths = []
    for coord in skelCellBody['endpointCoord'][1:]:
        Path, _ = route_through_array(skelCellBody['skeleton'] == 0,
                                      start=skelCellBody['endpointCoord'][0],
                                      end=coord)
        Path = np.array(Path)
        pathCellBody.append(Path)
        Length = path_length(Path, skelCellBody['skeleton'], physicspacing)
        cellBodyLengths.append(Length)

    skelCellBody['paths'] = pathCellBody
    skelCellBody['lengths'] = cellBodyLengths

    return skelCellBody
Esempio n. 27
0
        def compute_linestrings(direction):
            log.ODM_INFO("Computing %s cutlines" % direction)
            # Initialize cost map
            cost_map = np.full((height, width), 1, dtype=np.float32)

            # Write edges to cost map
            cost_map[edges == True] = 0  # Low cost

            # Write "barrier, floor is lava" costs
            if direction == 'vertical':
                lines = [((i, 0), (i, height - 1))
                         for i in range(line_hor_offset, width -
                                        line_hor_offset, line_hor_offset)]
                points = []
                pad_x = int(line_hor_offset / 2.0)
                for i in range(0, len(lines)):
                    a, b = lines[i]
                    points.append(((a[0] - pad_x, a[1]), (b[0] - pad_x, b[1])))
                a, b = lines[-1]
                points.append(((a[0] + pad_x, a[1]), (b[0] + pad_x, b[1])))
            else:
                lines = [((0, j), (width - 1, j))
                         for j in range(line_ver_offset, height -
                                        line_ver_offset, line_ver_offset)]
                points = []
                pad_y = int(line_ver_offset / 2.0)
                for i in range(0, len(lines)):
                    a, b = lines[i]
                    points.append(((a[0], a[1] - pad_y), (b[0], b[1] - pad_y)))
                a, b = lines[-1]
                points.append(((a[0], a[1] + pad_y), (b[0], b[1] + pad_y)))

            for a, b in lines:
                rr, cc = line(*a, *b)
                cost_map[cc, rr] = 9999  # Lava

            # Calculate route
            for a, b in points:
                line_coords, cost = route_through_array(cost_map, (a[1], a[0]),
                                                        (b[1], b[0]),
                                                        fully_connected=True,
                                                        geometric=True)

                # Convert to geographic
                geo_line_coords = [f.xy(*c) for c in line_coords]

                # Simplify
                ls = LineString(geo_line_coords)
                linestrings.append(ls.simplify(0.05, preserve_topology=False))
Esempio n. 28
0
def find_route(skeleton, begin, end):
    """ Perform shortest path algorithm on skeleton image

    Find the shortest route on a skeleton between 2 pixels using graph
    shortest path algorithm
    :param skeleton: (numpy 2D array of binary uint8) representing the skeleton
    of side view image of a maize plant
    :param begin: (list of 2 int) pixel of the bottom of the stem
    :param end: (list of 2 int) pixel of the top of the stem
    :return: (list of list of 2 int) list of all the pixels to follow to get
    the shortest path between begin and end
    """
    skeleton_inverted = np.array(skeleton)
    skeleton_inverted[skeleton_inverted == 0] = 255
    return graph.route_through_array(skeleton_inverted, begin, end)[0]
Esempio n. 29
0
def find_path(start, end, skel):
    """Find the shortest path along the skeleton from point to point."""
    # route_through_array treats zeros as having zero cost.  In our case, zeros
    # are points off the path.  Mark them as -1 so route_through_array ignores
    # them.
    skel = np.where(skel > 0, 1, -1)

    # TODO: Why do matplotlib/skimage not agree on array shapes?
    route, cost = graph.route_through_array(skel,
            [start[1], start[0]],
            [end[1], end[0]],
            fully_connected=True)
    ys, xs = zip(*route)
    xs, ys = np.asarray(xs), np.asarray(ys)

    return xs, ys, cost
def _plot_aux(image, ax=None):
    """
    """

    if ax is None:
        ax = plt.gca()

    img_skel = skeletonize_3d(image)
    rows, cols = np.where(img_skel != 0)
    img_rgb = gray2rgb(img_as_ubyte(image))
    img_rgb[rows, cols] = [255, 0, 255]

    ax.imshow(img_rgb, cmap='gray')

    props = regionprops(label(image))

    for prop in props:

        aux = skeletonize_3d(prop.image)
        trk_area, trk_px = ds.tracks_classify(aux)
        x_min, y_min, x_max, y_max = prop.bbox

        if trk_area is not None:
            for px in trk_px:
                route, _ = route_through_array(~aux, px[0], px[1])

                # plotting route.
                for rx in route:
                    ax.scatter(y_min + rx[1],
                               x_min + rx[0],
                               c='b',
                               s=SCATTER_SIZE + 25)

                # plotting extreme points.
                for p in px:
                    ax.scatter(y_min + p[1],
                               x_min + p[0],
                               c='g',
                               s=SCATTER_SIZE + 25)

                rows, cols = line(x_min + px[0][0], y_min + px[0][1],
                                  x_min + px[1][0], y_min + px[1][1])
                img_rgb[rows, cols] = [0, 255, 0]

    return ax
def createPath(costSurfaceArray,startCoord,stopCoord):   

    # coordinates to array index
    startCoordX = startCoord[0]
    startCoordY = startCoord[1]
    startIndexX,startIndexY = coord2pixelOffset(startCoordX,startCoordY)

    stopCoordX = stopCoord[0]
    stopCoordY = stopCoord[1]
    stopIndexX,stopIndexY = coord2pixelOffset(stopCoordX,stopCoordY)

    # create path
    indices, weight = route_through_array(costSurfaceArray, (startIndexY,startIndexX), (stopIndexY,stopIndexX),geometric=True,fully_connected=True)
    indices = np.array(indices).T
    indices = indices.astype(float)
    indices[1] = indices[1]*pixelWidth + originX
    indices[0] = indices[0]*pixelHeight + originY
    return indices
def compute_lcps(node_dict, cost_map, snow):
    # for each node compute LCPs to all other nodes
    for k in node_dict:
        lcp_start = node_dict[k]['src']
        for d in node_dict[k]['dsts']:
            lcp_stop = node_dict[k]['dsts'][d]['coords']
            indices, weight = graph.route_through_array(cost_map,
                                                        lcp_start,
                                                        lcp_stop,
                                                        fully_connected=True,
                                                        geometric=True)
            node_dict[k]['dsts'][d]['lcp indices'] = indices
            node_dict[k]['dsts'][d]['lcp cost'] = weight
            indices = np.array(indices).T
            path = np.zeros_like(snow)
            path[indices[0], indices[1]] = 1
            node_dict[k]['dsts'][d]['route'] = path
    return node_dict
Esempio n. 33
0
def createPath(cost_surface_path, startCoord,stopCoord):

    costSurfaceArray = raster2array(cost_surface_path)
    # coordinates to array index
    startCoordX = startCoord[0]
    startCoordY = startCoord[1]
    startIndexX,startIndexY = coord2pixelOffset(cost_surface_path,startCoordX,startCoordY)

    stopCoordX = stopCoord[0]
    stopCoordY = stopCoord[1]
    stopIndexX,stopIndexY = coord2pixelOffset(cost_surface_path,stopCoordX,stopCoordY)
    # create path
    indices, weight = route_through_array(costSurfaceArray, 
                                          (startIndexY,startIndexX), 
                                          (stopIndexY,stopIndexX),geometric=True,fully_connected=True)
    indiceT = np.array(indices).T
    path = np.zeros_like(costSurfaceArray)
    path[indiceT[0], indiceT[1]] = 1
    
    return path, indices
Esempio n. 34
0
def mutation(crossover_child, timeGrid):
    """
    mutates one route, so changes a random part of it

    Parameters
    ----------
    crossover_child : array
      one route the ship is going, returned by the crossover
    """
    timeGridNew = [[random.random() for i in range(timeGrid.shape[1])]
                   for j in range(timeGrid.shape[0])]
    timeGridNew = np.where(timeGrid > 999, timeGrid, timeGridNew)

    crossover_child_split_list = []

    crossover_child = makeArrays(crossover_child)
    #split crossover over child into 3 lists
    randomNumber = random.random() * len(crossover_child)
    startIndex = math.floor(randomNumber)
    startpoint = crossover_child[startIndex]
    endIndex = math.floor(startIndex + (random.random() *
                                        (len(crossover_child) - startIndex)))
    endpoint = crossover_child[endIndex]

    # recalculate route from end point of list 1 to sarting point of list 3
    route, weight = route_through_array(timeGridNew,
                                        startpoint[0:2],
                                        endpoint[0:2],
                                        fully_connected=False,
                                        geometric=True)
    route_list = makeArrays(route)
    first_component = makeArrays(crossover_child[0:startIndex])
    second_component = route_list[
        0:-1]  #filter out starting point and endpoint from the new mid list
    third_component = makeArrays(
        crossover_child[endIndex:len(crossover_child)])
    #combine all the sections to a final mutated route
    mutated_child = first_component + second_component + third_component
    #print(mutated_child)

    return mutated_child
Esempio n. 35
0
def splitTwo(pred, subCCs, cc):
    if pred.shape[0] > 1 and pred.shape[1] > 1:
        midY = subCCs.shape[0] / 2

        g = np.zeros(pred.shape)
        for x in range(0, subCCs.shape[1]):
            for y in range(0, subCCs.shape[0]):
                if subCCs[y, x] == cc:
                    g[y, x] = 100
                else:
                    g[y, x] = 0.01 + abs(y - midY) * 0.001
        indices, weight = route_through_array(g, (midY, 0),
                                              (midY, subCCs.shape[1] - 1),
                                              fully_connected=False)
        #print '--------------------'
        #print indices
        #print '--------------------'
        for p in indices:
            if subCCs[p] == cc:
                subCCs[p] = 0
                pred[p] = 0
Esempio n. 36
0
 def skeletonizeWorm(self):
     self.skeletonizedWormImage = morphology.skeletonize(self.bwWormImage)
     skeletonEnds = wp.find1Cpixels(self.skeletonizedWormImage)
     skeletonEndPts = cv2.findNonZero(np.uint8(skeletonEnds))
     if skeletonEndPts is None:
         skeletonEndPts = []
     nEndPts = len(skeletonEndPts)
     if nEndPts < 2:  # skeleton is a cirle (Omega turn)
         self.badSkeletonization = True
         self.crossedWorm = True
     elif nEndPts > 2:  # skeleton has spurs
         self.badSkeletonization = True
     else:
         skeletonInverted = np.logical_not(self.skeletonizedWormImage)
         skeletonPts, cost = \
             graph.route_through_array(np.uint8(skeletonInverted),
                                       np.flipud(skeletonEndPts[0][0]),
                                       np.flipud(skeletonEndPts[1][0]),
                                       geometric=True)
         self.skeleton = np.array([[pt[0], pt[1]] for pt in skeletonPts])
         self.badSkeletonization = False
Esempio n. 37
0
def createPath(CostSurfacefn,costSurfaceArray,startCoord,stopCoord,pathValue=255):
    print np.min(costSurfaceArray)
    print costSurfaceArray.shape
    
    print startCoord
    print stopCoord
    # coordinates to array index
    startCoordX = startCoord[0]
    startCoordY = startCoord[1]
    startIndexX,startIndexY = coord2pixelOffset(CostSurfacefn,startCoordX,startCoordY)

    stopCoordX = stopCoord[0]
    stopCoordY = stopCoord[1]
    stopIndexX,stopIndexY = coord2pixelOffset(CostSurfacefn,stopCoordX,stopCoordY)

    print startIndexX,startIndexY,stopIndexX,stopIndexY
    # create path
    indices, weight = route_through_array(costSurfaceArray, (startIndexY,startIndexX), (stopIndexY,stopIndexX),geometric=True,fully_connected=True)
    indices = np.array(indices).T
    path = np.zeros_like(costSurfaceArray)
    path[indices[0], indices[1]] = pathValue
    return path, weight
    def _walk_through_graph(graph, heatmap,
                            start_end_vertices, method='shortest-path',
                            verbose=True):
        """Find path through the path with different a-priori.

        Parameters
        ----------
        graph : ndarray, shape (n_serie * nb_bins, n_serie * nb_bins)
            Fully connected graph computed from the heatmap.

        heatmap : ndarray, shape (n_serie, nb_bins)
            The heatmap from which the graph will be built.

        start_end_vertices : tuple, shape ((start_vertice, end_vertice))
            Tuple containing the starting and ending vertices to enter and exit
            the graph.

        method : str, optional (default='shortest-path')
            Method to use to walk through the graph. The following
            possibilities:
            - 'shortest-path' : find shortest-path using scipy implementation.
            - 'route-through-graph' : find the path using MCP algorithm from
                skimage.

        verbose : bool
            Show the processing stage.

        Returns
        -------
        path : ndarray, shape (n_serie, 2)
            The path found to walk through the graph.

        """
        # Split the starting and ending vertices
        start_tuple = start_end_vertices[0]
        end_tuple = start_end_vertices[1]

        if method == 'shortest-path':
            # Define a function to go from px to vertices
            def px2v(px, im_shape):
                return np.ravel_multi_index(px, im_shape)

            # Define a function to go from vertices to px
            def v2px(v, im_shape):
                return np.unravel_index(v, im_shape)

            # Compute the shortest path for the whole graph
            d, p = shortest_path(graph, return_predecessors=True)
            # Initialize the path
            path_list = [end_tuple]
            # Find the shortest path thorugh an iterative process
            while end_tuple != start_tuple:
                # Convert coord from px to v
                s_v = px2v(start_tuple, heatmap.shape)
                e_v = px2v(end_tuple, heatmap.shape)

                # Find the predecessor
                pred_v = p[s_v, e_v]

                # Convert into pixel
                pred_px = v2px(pred_v, heatmap.shape)
                path_list.append(pred_px)

                # Update the last point of the path
                end_tuple = pred_px
        elif method == 'route-through-graph':
            # Call the function from skimage
            indices, weight = route_through_array(heatmap,
                                                  start_tuple,
                                                  end_tuple,
                                                  geometric=True)
            path_list = np.array(indices)
        else:
            raise NotImplementedError

        # Convert the list into array
        path_list = np.array(path_list)

        # Clean the path serie by serie to have a unique value
        cleaned_path = []
        for t_serie in range(heatmap.shape[0]):
            # Find all the intensities corresponding to this serie
            poi = path_list[np.nonzero(path_list[:, 0] == t_serie)]

            # Compute the median of the second column
            med_path = np.median(poi[:, 1])
            cleaned_path.append([t_serie, med_path])

        if verbose:
            print 'Walked through the graph ...'

        # Convert list to array
        return np.round(np.array(cleaned_path))
Esempio n. 39
0
def compute_downstream_lines(gdir):
    """Compute the lines continuing the glacier (one per divide).

    The idea is simple: starting from the glacier tail, compute all the routes
    to all local minimas found at the domain edge. The cheapest is the One.

    Parameters
    ----------
    gdir: GlacierDir object

    I/O
    ---
    Generates::
        - downstream_line.p: line instance as pickle
    """

    log.info('%s: downstream lines', gdir.rgi_id)

    with netCDF4.Dataset(gdir.get_filepath('grids', div_id=0)) as nc:
        topo = nc.variables['topo_smoothed'][:]

    # Variables we gonna need
    xmesh, ymesh = np.meshgrid(np.arange(0, gdir.grid.nx, 1),
                               np.arange(0, gdir.grid.ny, 1))
    _h = [topo[:, 0], topo[0, :], topo[:, -1], topo[-1, :]]
    _x = [xmesh[:, 0], xmesh[0, :], xmesh[:, -1], xmesh[-1, :]]
    _y = [ymesh[:, 0], ymesh[0, :], ymesh[:, -1], ymesh[-1, :]]

    # First we have to find the "major" divide
    heads = []
    heigts = []
    div_ids = list(gdir.divide_ids)
    for div_id in div_ids:
        head = gdir.read_pickle('centerlines', div_id=div_id)[-1].tail
        heigts.append(topo[head.y, head.x])
        heads.append((head.y, head.x))

    # Now the lowest first
    aso = np.argsort(heigts)
    major_id = aso[0]
    a = aso[0]
    head = heads[a]
    head_h = heigts[a]
    # Find all local minimas and their coordinates
    min_cost = np.Inf
    line = None
    min_thresold = 100
    while True:
        for h, x, y in zip(_h, _x, _y):
            ids = scipy.signal.argrelmin(h, order=10, mode='wrap')
            for i in ids[0]:
                if topo[y[i], x[i]] > (head_h-min_thresold):
                    continue
                lids, cost = route_through_array(topo, head, (y[i], x[i]))
                if cost < min_cost:
                    min_cost = cost
                    line = shpg.LineString(np.array(lids)[:, [1, 0]])
        if line is None:
            min_thresold -= 10
        else:
            break
        if min_thresold < 0:
            raise RuntimeError('Downstream line not found')

    # Write the data
    gdir.write_pickle(line, 'downstream_line', div_id=div_ids[a])
    if len(div_ids) == 1:
        return

    # If we have divides, there is just one route and we have to interrupt
    # It at the glacier boundary
    with netCDF4.Dataset(gdir.get_filepath('grids', div_id=div_ids[a])) as nc:
        mask = nc.variables['glacier_mask'][:]
        ext = nc.variables['glacier_ext'][:]
    mask[np.where(ext==1)] = 0
    tail = head
    topo[np.where(mask==1)] = 0
    for a in aso[1:]:
        head = heads[a]
        lids, _ = route_through_array(topo, head, tail)
        lids = [l for l in lids if mask[l[0], l[1]] == 0][0:-1]
        line = shpg.LineString(np.array(lids)[:, [1, 0]])
        gdir.write_pickle(line, 'downstream_line', div_id=div_ids[a])
    fn = gdir.get_filepath('major_divide', div_id=0)
    with open(fn, 'w') as text_file:
        text_file.write('{}'.format(div_ids[major_id]))
Esempio n. 40
0
def compute_downstream_lines(gdir):
    """Compute the lines continuing the glacier (one per divide).

    The idea is simple: starting from the glacier tail, compute all the routes
    to all local minimas found at the domain edge. The cheapest is "the One".

    The task also determines the so-called "major flowline" which is the
    only line flowing out of the domain. The other ones are flowing into the
    branch. The rest of the job (merging all centerlines + downstreams into
    one single glacier is realized by
    :py:func:`~oggm.tasks.init_present_time_glacier`).

    Parameters
    ----------
    gdir : oggm.GlacierDirectory
    """

    with netCDF4.Dataset(gdir.get_filepath('gridded_data', div_id=0)) as nc:
        topo = nc.variables['topo_smoothed'][:]

    # Make going up very costy
    topo = topo**10

    # Variables we gonna need
    xmesh, ymesh = np.meshgrid(np.arange(0, gdir.grid.nx, 1, dtype=np.int64),
                               np.arange(0, gdir.grid.ny, 1, dtype=np.int64))
    _h = [topo[:, 0], topo[0, :], topo[:, -1], topo[-1, :]]
    _x = [xmesh[:, 0], xmesh[0, :], xmesh[:, -1], xmesh[-1, :]]
    _y = [ymesh[:, 0], ymesh[0, :], ymesh[:, -1], ymesh[-1, :]]

    # First we have to find the "major" divide
    heads = []
    heigts = []
    div_ids = list(gdir.divide_ids)
    for div_id in div_ids:
        head = gdir.read_pickle('centerlines', div_id=div_id)[-1].tail
        heigts.append(topo[int(head.y), int(head.x)])
        heads.append((int(head.y), int(head.x)))

    # Now the lowest first
    aso = np.argsort(heigts)
    major_id = aso[0]
    a = aso[0]
    head = heads[a]
    head_h = heigts[a]
    # Find all local minimas and their coordinates
    min_cost = np.Inf
    line = None
    min_thresold = 50
    while True:
        for h, x, y in zip(_h, _x, _y):
            ids = scipy.signal.argrelmin(h, order=10, mode='wrap')
            for i in ids[0]:
                # Prevent very high local minimas
                # if topo[y[i], x[i]] > ((head_h-min_thresold)**10):
                #     continue
                lids, cost = route_through_array(topo, head, (y[i], x[i]),
                                                 geometric=True)
                if cost < min_cost:
                    min_cost = cost
                    line = shpg.LineString(np.array(lids)[:, [1, 0]])
        if line is None:
            min_thresold -= 10
        else:
            break
        if min_thresold < 0:
            raise RuntimeError('Downstream line not found')

    # Write the data
    mdiv = div_ids[major_id]
    gdir.write_pickle(mdiv, 'major_divide', div_id=0)
    fn = gdir.get_filepath('major_divide')
    gdir.write_pickle(line, 'downstream_line', div_id=div_ids[a])
    if len(div_ids) == 1:
        return

    # If we have divides, there is just one route and we have to interrupt
    # It at the glacier boundary
    fpath = gdir.get_filepath('gridded_data', div_id=div_ids[a])
    with netCDF4.Dataset(fpath) as nc:
        mask = nc.variables['glacier_mask'][:]
        ext = nc.variables['glacier_ext'][:]
    mask[np.where(ext==1)] = 0
    tail = head
    topo[np.where(mask==1)] = 0
    for a in aso[1:]:
        head = heads[a]
        lids, _ = route_through_array(topo, head, tail)
        lids = [l for l in lids if mask[l[0], l[1]] == 0][0:-1]
        line = shpg.LineString(np.array(lids)[:, [1, 0]])
        gdir.write_pickle(line, 'downstream_line', div_id=div_ids[a])
Esempio n. 41
0
def compute_centerlines(gdir, div_id=None):
    """Compute the centerlines following Kienholz et al., (2014).

    They are then sorted according to the modified Strahler number:
    http://en.wikipedia.org/wiki/Strahler_number

    Parameters
    ----------
    gdir : oggm.GlacierDirectory
    """
    # open
    geom = gdir.read_pickle('geometries', div_id=div_id)
    grids_file = gdir.get_filepath('gridded_data', div_id=div_id)
    with netCDF4.Dataset(grids_file) as nc:
        # Variables
        glacier_mask = nc.variables['glacier_mask'][:]
        glacier_ext = nc.variables['glacier_ext'][:]
        topo = nc.variables['topo_smoothed'][:]
        poly_pix = geom['polygon_pix']

    # Find for local maximas on the outline
    x, y = tuple2int(poly_pix.exterior.xy)
    ext_yx = tuple(reversed(poly_pix.exterior.xy))
    zoutline = topo[y[:-1], x[:-1]]  # last point is first point

    # Size of the half window to use to look for local maximas
    maxorder = np.rint(cfg.PARAMS['localmax_window'] / gdir.grid.dx)
    maxorder = np.clip(maxorder, 5., np.rint((len(zoutline) / 5.)))
    heads_idx = scipy.signal.argrelmax(zoutline, mode='wrap',
                                       order=maxorder.astype(np.int64))
    if (not cfg.PARAMS['use_multiple_flowlines']) or len(heads_idx[0]) <= 1:
        # small glaciers with one or less heads: take the absolute max
        heads_idx = (np.atleast_1d(np.argmax(zoutline)),)

    # Remove the heads that are too low
    zglacier = topo[np.where(glacier_mask)]
    head_threshold = np.percentile(zglacier, (1./3.)*100)
    heads_idx = heads_idx[0][np.where(zoutline[heads_idx] > head_threshold)]
    heads = np.asarray(ext_yx)[:, heads_idx]
    heads_z = zoutline[heads_idx]
    # careful, the coords are in y, x order!
    heads = [shpg.Point(x, y) for y, x in zip(heads[0, :],
                                              heads[1, :])]

    # get radius of the buffer according to Kienholz eq. (1)
    radius = cfg.PARAMS['q1'] * geom['polygon_area'] + cfg.PARAMS['q2']
    radius = np.clip(radius, 0, cfg.PARAMS['rmax'])
    radius /= gdir.grid.dx # in raster coordinates
    # Plus our criteria, quite usefull to remove short lines:
    radius += cfg.PARAMS['flowline_junction_pix'] * cfg.PARAMS['flowline_dx']
    log.debug('%s: radius in raster coordinates: %.2f',
              gdir.rgi_id, radius)

    # OK. Filter and see.
    log.debug('%s: number of heads before radius filter: %d',
              gdir.rgi_id, len(heads))
    heads, heads_z = _filter_heads(heads, heads_z, radius, poly_pix)
    log.debug('%s: number of heads after radius filter: %d',
              gdir.rgi_id, len(heads))

    # Cost array
    costgrid = _make_costgrid(glacier_mask, glacier_ext, topo)

    # Terminus
    t_coord = np.asarray(ext_yx)[:, np.argmin(zoutline)].astype(np.int64)

    # Compute the routes
    lines = []
    for h in heads:
        h_coord = np.asarray(h.xy)[::-1].astype(np.int64)
        indices, _ = route_through_array(costgrid, h_coord, t_coord)
        lines.append(shpg.LineString(np.array(indices)[:, [1, 0]]))
    log.debug('%s: computed the routes', gdir.rgi_id)

    # Filter the shortest lines out
    radius = cfg.PARAMS['flowline_junction_pix'] * cfg.PARAMS['flowline_dx']
    radius += 6 * cfg.PARAMS['flowline_dx']
    olines, _ = _filter_lines(lines, heads, cfg.PARAMS['kbuffer'], radius)
    log.debug('%s: number of heads after lines filter: %d',
              gdir.rgi_id, len(olines))

    # And rejoin the cutted tails
    olines = _join_lines(olines)

    # Adds the line level
    for cl in olines:
        cl.order = _line_order(cl)

    # And sort them per order !!! several downstream tasks  rely on this
    cls = []
    for i in np.argsort([cl.order for cl in olines]):
        cls.append(olines[i])

    # Final check
    if len(cls) == 0:
        raise RuntimeError('{} : no centerline found!'.format(gdir.rgi_id))

    # Write the data
    gdir.write_pickle(cls, 'centerlines', div_id=div_id)

    # Netcdf
    with netCDF4.Dataset(grids_file, 'a') as nc:
        v = nc.createVariable('cost_grid', 'f4', ('y', 'x', ), zlib=True)
        v.units = '-'
        v.long_name = 'Centerlines cost grid'
        v[:] = costgrid
Esempio n. 42
0
def catchment_area(gdir, div_id=None):
    """Compute the catchment areas of each tributary line.

    The idea is to compute the route of lowest cost for any point on the
    glacier to rejoin a centerline. These routes are then put together if
    they belong to the same centerline, thus creating "catchment areas" for
    each centerline.

    Parameters
    ----------
    gdir : oggm.GlacierDirectory
    """

    # Variables
    cls = gdir.read_pickle('centerlines', div_id=div_id)
    geoms = gdir.read_pickle('geometries', div_id=div_id)
    glacier_pix = geoms['polygon_pix']
    fpath = gdir.get_filepath('gridded_data', div_id=div_id)
    with netCDF4.Dataset(fpath) as nc:
        costgrid = nc.variables['cost_grid'][:]
        mask = nc.variables['glacier_mask'][:]

    # If we have only one centerline this is going to be easy: take the
    # mask and return
    if len(cls) == 1:
        cl_catchments = [np.array(np.nonzero(mask == 1)).T]
        gdir.write_pickle(cl_catchments, 'catchment_indices', div_id=div_id)
        return

    # Initialise costgrid and the "catching" dict
    cost_factor = 0.  # Make it cheap
    dic_catch = dict()
    for i, cl in enumerate(cls):
        x, y = tuple2int(cl.line.xy)
        costgrid[y, x] = cost_factor
        for x, y in [(int(x), int(y)) for x, y in cl.line.coords]:
            assert (y, x) not in dic_catch
            dic_catch[(y, x)] = set([(y, x)])

    # It is much faster to make the array as small as possible (especially
    # with divides). We have to trick:
    pm = np.nonzero(mask == 1)
    ymi, yma = np.min(pm[0])-1, np.max(pm[0])+2
    xmi, xma = np.min(pm[1])-1, np.max(pm[1])+2
    costgrid = costgrid[ymi:yma, xmi:xma]
    mask = mask[ymi:yma, xmi:xma]

    # Where did we compute the path already?
    computed = np.where(mask == 1, 0, np.nan)

    # Coords of Terminus (converted)
    endcoords = np.array(cls[0].tail.coords[0])[::-1].astype(np.int64)
    endcoords -= [ymi, xmi]

    # Start with all the paths at the boundaries, they are more likely
    # to cover much of the glacier
    for headx, heady in tuple2int(glacier_pix.exterior.coords):
        headcoords = np.array([heady-ymi, headx-xmi])  # convert
        indices, _ = route_through_array(costgrid, headcoords, endcoords)
        inds = np.array(indices).T
        computed[inds[0], inds[1]] = 1
        set_dump = set([])
        for y, x in indices:
            y, x = y+ymi, x+xmi  # back to original
            set_dump.add((y, x))
            if (y, x) in dic_catch:
                dic_catch[(y, x)] = dic_catch[(y, x)].union(set_dump)
                break

    # Repeat for the not yet computed pixels
    while True:
        not_computed = np.where(computed == 0)
        if len(not_computed[0]) == 0:  # All points computed !!
            break
        headcoords = np.array([not_computed[0][0], not_computed[1][0]]).astype(np.int64)
        indices, _ = route_through_array(costgrid, headcoords, endcoords)
        inds = np.array(indices).T
        computed[inds[0], inds[1]] = 1
        set_dump = set([])
        for y, x in indices:
            y, x = y+ymi, x+xmi  # back to original
            set_dump.add((y, x))
            if (y, x) in dic_catch:
                dic_catch[(y, x)] = dic_catch[(y, x)].union(set_dump)
                break

    # For each centerline, make a set of all points flowing into it
    cl_catchments = []
    for cl in cls:
        # Union of all
        cl_catch = set()
        for x, y in [(int(x), int(y)) for x, y in cl.line.coords]:
            cl_catch = cl_catch.union(dic_catch[(y, x)])
        cl_catchments.append(cl_catch)

    # The higher order centerlines will get the points from the upstream
    # ones too. The idea is to store the points which are unique to each
    # centerline: now, in decreasing line order we remove the indices from
    # the tributaries
    cl_catchments = cl_catchments[::-1]
    for i, cl in enumerate(cl_catchments):
        cl_catchments[i] = np.array(list(cl.difference(*cl_catchments[i+1:])))
    cl_catchments = cl_catchments[::-1]  # put it back in order

    # Write the data
    gdir.write_pickle(cl_catchments, 'catchment_indices', div_id=div_id)
Esempio n. 43
0
def compute_centerlines(gdir, div_id=None):
    """Compute the centerlines from a pre-processed directory.

    It follows quite closely Kienholz et al. (2014).

    Modified Strahler number
    http://en.wikipedia.org/wiki/Strahler_number

    Parameters
    ----------
    gdir: GlacierDir object
    div_id: the divide ID to process (should be left to None)

    I/O
    ---
    Generates::
        - centerlines.p: list of centerline instances as pickle
    Updates::
        - grids.nc with the costgrid
    """

    if div_id is None:
        for i in gdir.divide_ids:
            log.info('%s: centerlines, divide %d', gdir.rgi_id, i)
            compute_centerlines(gdir, div_id=i)
        return

    # open
    geom = gdir.read_pickle('geometries', div_id=div_id)
    grids_file = gdir.get_filepath('grids', div_id=div_id)
    nc = netCDF4.Dataset(grids_file)

    # Variables
    glacier_mask = nc.variables['glacier_mask'][:]
    glacier_ext = nc.variables['glacier_ext'][:]
    topo = nc.variables['topo_smoothed'][:]
    poly_pix = geom['polygon_pix']
    nc.close()

    # Find for local maximas on the outline
    ext_yx = tuple(reversed(poly_pix.exterior.xy))
    ext_yx = (ext_yx[0][:-1], ext_yx[1][:-1])  # last point is first point
    zoutline = topo[ext_yx]

    # Size of the half window to use to look for local maximas
    maxorder = np.rint(cfg.params['localmax_window'] / gdir.grid.dx)
    maxorder = np.clip(maxorder, 5., np.rint((len(zoutline) / 5.)))
    heads_idx = scipy.signal.argrelmax(zoutline, mode='wrap',
                                       order=maxorder.astype(np.int64))
    if len(heads_idx[0]) <= 1:
        # small glaciers with one or less heads: take the absolute max
        heads_idx = (np.atleast_1d(np.argmax(zoutline)),)

    # Remove the heads that are too low
    zglacier = topo[np.where(glacier_mask)]
    head_threshold = np.percentile(zglacier, (1./3.)*100)
    heads_idx = heads_idx[0][np.where(zoutline[heads_idx] > head_threshold)]
    heads = np.asarray(ext_yx)[:, heads_idx]
    heads_z = zoutline[heads_idx]
    # careful, the coords are in y, x order!
    heads = [shpg.Point(x, y) for y, x in zip(heads[0, :],
                                              heads[1, :])]

    # get radius of the buffer according to Kienholz eq. (1)
    radius = cfg.params['q1'] * geom['polygon_area'] + cfg.params['q2']
    radius = np.clip(radius, 0, cfg.params['rmax'])
    radius /= gdir.grid.dx # in raster coordinates
    # Plus our criteria, quite usefull to remove short lines:
    radius += cfg.params['flowline_junction_pix'] * cfg.params['flowline_dx']
    log.debug('%s: radius in raster coordinates: %.2f',
              gdir.rgi_id, radius)

    # OK. Filter and see.
    log.debug('%s: number of heads before radius filter: %d',
              gdir.rgi_id, len(heads))
    heads, heads_z = _filter_heads(heads, heads_z, radius, poly_pix)
    log.debug('%s: number of heads after radius filter: %d',
              gdir.rgi_id, len(heads))

    # Cost array
    costgrid = _make_costgrid(glacier_mask, glacier_ext, topo)

    # Terminus
    t_coord = np.asarray(ext_yx)[:, np.argmin(zoutline)]

    # Compute the routes
    lines = []
    for h in heads:
        h_coord = np.asarray(h.xy)[::-1]
        indices, _ = route_through_array(costgrid, h_coord, t_coord)
        lines.append(shpg.LineString(np.array(indices)[:, [1, 0]]))
    log.debug('%s: computed the routes', gdir.rgi_id)

    # Filter the shortest lines out
    radius = cfg.params['flowline_junction_pix'] * cfg.params['flowline_dx']
    radius += 6 * cfg.params['flowline_dx']
    olines, _ = _filter_lines(lines, heads, cfg.params['kbuffer'], radius)
    log.debug('%s: number of heads after lines filter: %d',
              gdir.rgi_id, len(olines))

    # And rejoin the cutted tails
    olines = _join_lines(olines)

    # Adds the line level
    for cl in olines:
        cl.order = _line_order(cl)

    # And sort them per order !!! several tools downstream rely on this
    cls = []
    for i in np.argsort([cl.order for cl in olines]):
        cls.append(olines[i])

    # Final check
    if len(cls) == 0:
        raise RuntimeError('No centerline found!')

    # Write the data
    gdir.write_pickle(cls, 'centerlines', div_id=div_id)

    # Netcdf
    nc = netCDF4.Dataset(grids_file, 'a')
    v = nc.createVariable('cost_grid', 'f4', ('y', 'x', ), zlib=True)
    v.units = '-'
    v.long_name = 'Centerlines cost grid'
    v[:] = costgrid
    nc.close()
Esempio n. 44
0
def catchment_area(gdir, div_id=None):
    """Compute the catchment areas of each tributary line.

    The idea is to compute the route of lowest cost for any point on the
    glacier to rejoin a centerline. These routes are then put together if
    they belong to the same centerline, thus creating "catchment areas" for
    each centerline.

    Parameters
    ----------
    gdir: GlacierDir object
    div_id: the divide ID to process (should be left to None)

    I/O
    ---
    catchment_indices.p: a list of
    """

    if div_id is None:
        for i in gdir.divide_ids:
            log.info('%s: catchment areas, divide %d', gdir.rgi_id, i)
            catchment_area(gdir, div_id=i)
        return

    # Variables
    cls = gdir.read_pickle('centerlines', div_id=div_id)
    geoms = gdir.read_pickle('geometries', div_id=div_id)
    glacier_pix = geoms['polygon_pix']
    nc = netCDF4.Dataset(gdir.get_filepath('grids', div_id=div_id))
    costgrid = nc.variables['cost_grid'][:]
    mask = nc.variables['glacier_mask'][:]
    nc.close()

    # If we have only one centerline this is going to be easy: take the
    # mask and return
    if len(cls) == 1:
        cl_catchments = [np.array(np.where(mask == 1)).T]
        gdir.write_pickle(cl_catchments, 'catchment_indices', div_id=div_id)
        return

    # Initialise costgrid and the "catching" dict
    cost_factor = 0.  # Make it cheap
    dic_catch = dict()
    for i, cl in enumerate(cls):
        x, y = cl.line.xy
        costgrid[y, x] *= cost_factor
        for x, y in [(int(x), int(y)) for x, y in cl.line.coords]:
            assert (y, x) not in dic_catch
            dic_catch[(y, x)] = set([(y, x)])

    # Where did we compute the path already?
    computed = np.where(mask == 1, 0, np.nan)

    # Coords of Terminus
    endcoords = np.array(cls[0].tail.coords[0])[::-1]

    # Start with all the paths at the boundaries, they are more likely
    # to cover much of the glacier
    for headx, heady in glacier_pix.exterior.coords:
        indices, _ = route_through_array(costgrid, np.array([heady, headx]),
                                         endcoords)
        inds = np.array(indices).T
        computed[inds[0], inds[1]] = 1
        set_dump = set([])
        for y, x in indices:
            set_dump.add((y, x))
            if (y, x) in dic_catch:
                dic_catch[(y, x)] = dic_catch[(y, x)].union(set_dump)
                break

    # Repeat for the not yet computed pixels
    while True:
        not_computed = np.where(computed == 0)
        if len(not_computed[0]) == 0:  # All points computed !!
            break
        headcoords = np.array([not_computed[0][0], not_computed[1][0]])
        indices, _ = route_through_array(costgrid, headcoords, endcoords)
        inds = np.array(indices).T
        computed[inds[0], inds[1]] = 1
        set_dump = set([])
        for y, x in indices:
            set_dump.add((y, x))
            if (y, x) in dic_catch:
                dic_catch[(y, x)] = dic_catch[(y, x)].union(set_dump)
                break

    # For each centerline, make a set of all points flowing into it
    cl_catchments = []
    for cl in cls:
        # Union of all
        cl_catch = set()
        for x, y in [(int(x), int(y)) for x, y in cl.line.coords]:
            cl_catch = cl_catch.union(dic_catch[(y, x)])
        cl_catchments.append(cl_catch)

    # The higher order centerlines will get the points from the upstream
    # ones too. The idea is to store the points which are unique to each
    # centerline: now, in decreasing line order we remove the indices from
    # the tributaries
    cl_catchments = cl_catchments[::-1]
    for i, cl in enumerate(cl_catchments):
        cl_catchments[i] = np.array(list(cl.difference(*cl_catchments[i+1:])))
    cl_catchments = cl_catchments[::-1]  # put it back in order

    # Write the data
    gdir.write_pickle(cl_catchments, 'catchment_indices', div_id=div_id)