示例#1
0
    def generate_sample_grid(self):

        print('Generating samples...')

        # Compute sample size seed
        num_samples = self.target_sample_size / (self.x_cuts * self.y_cuts * 8)

        # Project the geometry into the target projection
        bounding_box = self.study_area.bounds(ee.ErrorMargin(1, 'projected'), self.projection) \
            .transform(self.projection) \
            .bounds(ee.ErrorMargin(1, 'projected'), self.projection)

        # Get the bounding box partitions
        partitions = self.__partition_bounding_box(bounding_box)

        # Get sample centroids
        sample_points = self.__get_sample_points(partitions, num_samples,
                                                 self.projection)

        # Compute the foot-prints for visualization purposes
        sample_tiles = self.__get_sample_tiles(sample_points)

        # Export all of the various ee.FeatureCollesctions to the input asset directory
        self.__export_compute_feature_collections(partitions, sample_points,
                                                  sample_tiles)
        print('Output number of Samples:', sample_points.size().getInfo())

        return None
def create_dataset_image(study_area, projection, x_cuts, y_cuts):

    # Project the geometry into the target projection
    bounding_box = study_area.bounds(ee.ErrorMargin(0.0001, 'projected'), projection) \
        .transform(projection) \
        .bounds(ee.ErrorMargin(1, 'projected'), projection)

    # Get the bounding box partitions
    partitions = partition_bounding_box(bounding_box, x_cuts, y_cuts,
                                        projection)

    # Randomly assign each partition to a set
    partitions = partitions.randomColumn()
    train = partitions.filterMetadata('random', 'less_than', 0.70)
    validation = partitions.filterMetadata('random', 'greater_than', 0.70) \
        .filterMetadata('random', 'less_than', 0.90)
    test = partitions.filterMetadata('random', 'greater_than', 0.90)

    # Adds the a property called "dataset_subset" to each feature
    train = add_model_set_property(train, 1)
    validation = add_model_set_property(validation, 2)
    test = add_model_set_property(test, 3)

    # Recombine the datasets
    combined = train.merge(validation).merge(test)

    # Create the binary image to sample
    dataset_image = ee.Image.constant(0).toByte().paint(combined, 'dataset_subset') \
        .rename('dataset_subset')

    return dataset_image
示例#3
0
def calc_validation_score(
    mask,
    val_poly_ir_crops,
    val_poly_ir_trees,
):
    """Calculates the validation score for a mask layer using validation polygons that were uploaded as assets to GEE
    beforehand"""
    def validate_irrigated_area(feature):
        total_pixels = mask.reduceRegion(reducer=ee.Reducer.count(),
                                         geometry=feature.geometry(),
                                         scale=30)

        irrigated_pixels = mask.reduceRegion(reducer=ee.Reducer.sum(),
                                             geometry=feature.geometry(),
                                             scale=30)

        score = ee.Number(irrigated_pixels.get('b1')).round().divide(
            ee.Number(total_pixels.get('b1')))
        score = ee.Algorithms.If(score.gt(1), 1, score)

        feature = feature.set({
            'total_pixels': total_pixels.get('b1'),
            'irrigated_pixels': irrigated_pixels.get('b1'),
            'score': score
        })
        return feature

    validation_areas_ir_crops = ee.FeatureCollection(
        val_poly_ir_crops.geometry().intersection(CdC.geometry(),
                                                  ee.ErrorMargin(1)))

    validation_areas_ir_trees = ee.FeatureCollection(
        val_poly_ir_trees.geometry().intersection(CdC.geometry(),
                                                  ee.ErrorMargin(1)))

    validation_areas_ir_crops = validation_areas_ir_crops.map(
        convert_to_polygons).flatten()
    validation_areas_ir_trees = validation_areas_ir_trees.map(
        convert_to_polygons).flatten()

    validation_areas_ir_crops = validation_areas_ir_crops.map(
        validate_irrigated_area)
    validation_areas_ir_trees = validation_areas_ir_trees.map(
        validate_irrigated_area)

    final_validation_score_ir_crops = validation_areas_ir_crops.reduceColumns(
        selectors=ee.List(['score']), reducer=ee.Reducer.mean())

    final_validation_score_ir_trees = validation_areas_ir_trees.reduceColumns(
        selectors=ee.List(['score']), reducer=ee.Reducer.mean())

    return final_validation_score_ir_crops.getInfo(
    )["mean"], final_validation_score_ir_trees.getInfo()["mean"]
示例#4
0
def generate_voronoi_polygons(points, scale, aoi):
    """
    Generates Voronoi polygons
    :param points:
    :param scale:
    :param aoi:
    :return:
    """

    error = ee.ErrorMargin(1, 'projected')
    # proj = ee.Projection('EPSG:3857').atScale(scale)
    proj = ee.Projection('EPSG:4326').atScale(scale)

    distance = ee.Image(0).float().paint(points, 1) \
        .fastDistanceTransform().sqrt().clip(aoi) \
        .reproject(proj)

    concavity = distance.convolve(ee.Kernel.laplacian8()) \
        .reproject(proj)

    concavity = concavity.multiply(distance)

    concavityTh = 0

    edges = concavity.lt(concavityTh)

    # label connected components
    connected = edges.Not() \
        .connectedComponents(ee.Kernel.circle(1), 256) \
        .clip(aoi) \
        .focal_max(scale * 3, 'circle', 'meters') \
        .focal_min(scale * 3, 'circle', 'meters') \
        .focal_mode(scale * 5, 'circle', 'meters') \
        .reproject(proj)

    # fixing reduceToVectors() bug, remap to smaller int
    def fixOverflowError(i):
        hist = i.reduceRegion(ee.Reducer.frequencyHistogram(), aoi, scale)
        uniqueLabels = ee.Dictionary(ee.Dictionary(hist).get('labels')).keys() \
            .map(lambda o: ee.Number.parse(o))

        labels = ee.List.sequence(0, uniqueLabels.size().subtract(1))

        return i.remap(uniqueLabels, labels).rename('labels').int()

    connected = fixOverflowError(connected).reproject(proj)

    polygons = connected.select('labels').reduceToVectors(
        **{
            "scale": scale,
            "crs": proj,
            "geometry": aoi,
            "eightConnected": True,
            "labelProperty": 'labels',
            "tileScale": 4
        })

    # polygons = polygons.map(lambda o: o.snap(error, proj))

    return {"polygons": polygons, "distance": distance}
示例#5
0
 def testDynamicConstructorCasting(self):
   """Test the behavior of casting with dynamic classes."""
   self.InitializeApi()
   result = ee.Geometry.Rectangle(1, 1, 2, 2).bounds(0, 'EPSG:4326')
   expected = (ee.Geometry.Polygon([[1, 2], [1, 1], [2, 1], [2, 2]])
               .bounds(ee.ErrorMargin(0), ee.Projection('EPSG:4326')))
   self.assertEqual(expected, result)
示例#6
0
def getChips(request):

	pt = ee.Geometry.Point(float(request.get('lon')), float(request.get('lat')))
    
	cloud_pcent = int(request.get('cloudpcent'))

	deltad = int(request.get('deltad'))
	end_date = ee.Date(request.get('end_period'))
	start_date = end_date.advance(-deltad, 'day')
    
	s2 = ee.ImageCollection('COPERNICUS/S2').filterBounds(pt).\
	  filterMetadata('CLOUDY_PIXEL_PERCENTAGE', 'less_than', cloud_pcent).\
	  filterDate(start_date, end_date).sort('system:time_start')

	chips_date = ee.List(s2.aggregate_array('system:time_start')).map(lambda t: ee.Date(t).format("YYYY-MM-dd"))

	projection = ee.Image(s2.first()).select('B2').projection()

	region = pt.transform(projection,1.0).buffer(640.0, ee.ErrorMargin(1.0)).bounds(1.0, projection)


	s2 = s2.map(lambda img: ee.Image(img).reproject(projection).clip(region).visualize(bands=['B8', 'B11', 'B4'], max=[6000, 6000, 4000]))
	#print s2.size().getInfo()
	
	url = ee.data.makeThumbUrl(ee.data.getThumbId({'image':s2.serialize(), 'dimensions': "128x128", 'format': 'png'}))

	#print chips_date.getInfo()
	chips= {'chips_dates': chips_date.getInfo(), 'thurl': url}
	

	return json.dumps(chips)
示例#7
0
        def partitions_pairs_to_partitions(pair):

            # Get the parameters from the input array
            x_coord = ee.Number(ee.List(pair).get(0)).toInt16()
            y_coord = ee.Number(ee.List(pair).get(1)).toInt16()
            id_str = ee.Number(ee.List(pair).get(2)).toInt16()

            # Retrieve the 4 verticies needed
            llh = ee.Feature(grid_vertices.filterMetadata('grid_x', 'equals', x_coord) \
                .filterMetadata('grid_y', 'equals', y_coord).first()).geometry()
            lrh = ee.Feature(grid_vertices.filterMetadata('grid_x', 'equals', x_coord.add(1)) \
                .filterMetadata('grid_y', 'equals', y_coord).first()).geometry()
            urh = ee.Feature(grid_vertices.filterMetadata('grid_x', 'equals', x_coord.add(1)) \
                .filterMetadata('grid_y', 'equals', y_coord.add(1)).first()).geometry()
            ulh = ee.Feature(grid_vertices.filterMetadata('grid_x', 'equals', x_coord) \
                .filterMetadata('grid_y', 'equals', y_coord.add(1)).first()).geometry()

            # Convert into a geometry
            partition_geo = ee.Geometry.Polygon([[llh.coordinates(), lrh.coordinates(), urh.coordinates(), ulh.coordinates()]], self.projection, False) \
                .buffer(-1 * erosion_dist/2, ee.ErrorMargin(1, 'projected'), self.projection)

            # Append the feature to the output
            partition = ee.Feature(
                partition_geo, {
                    'partition_id': id_str,
                    'partition_x': x_coord,
                    'partition_y': y_coord
                })

            return partition
    def _create_grid(self, ee_feature, grid_size_degrees):
        """
        Breaks down a feature into an N x N grid and returns a new list of ee.Features.
        :param ee_feature:  ee.Feature
        :param grid_size_degrees: Grid size in arc degrees
        :return: list of ee.Features
        """

        # Arc grid JS equivalent here https://code.earthengine.google.com/bdb4f409515d1fda0592a8330a0f6528

        # Get bounds of grid
        bounds = ee_feature.bounds().geometry().bounds().getInfo()

        x_coords = [b[0] for b in bounds["coordinates"][0]]
        y_coords = [b[1] for b in bounds["coordinates"][0]]

        lon_start = min(x_coords)
        lon_end = max(x_coords)
        lat_start = min(y_coords)
        lat_end = max(y_coords)

        lon_width = lon_end - lon_start
        lat_width = lat_end - lat_start

        # test grid size against bounding box
        if grid_size_degrees > lon_width and grid_size_degrees > lat_width:
            logger.info("Grid larger than feature. Skipping.")
            return [ee_feature]

        elif grid_size_degrees > lon_width / 2 and grid_size_degrees > lat_width / 2:
            logger.warning(
                "Expecting less than 4 grids. Consider using a smaller grid_size_degrees or larger area_threshold."
            )

        # Generate grid over ee_feature
        polys = []
        lon = lon_start
        while lon < lon_end:
            x1 = lon
            x2 = lon + grid_size_degrees
            lon += grid_size_degrees

            lat = lat_start
            while lat < lat_end:
                y1 = lat
                y2 = lat + grid_size_degrees
                lat += grid_size_degrees

                polys.append(
                    ee.Feature(ee.Geometry.Rectangle(x1, y1, x2, y2), {}))

        # Intersects grid against ee_feature
        intersected_feats = []
        for p in polys:
            intersection = p.intersection(ee_feature, ee.ErrorMargin(1))
            intersected_feats.append(
                ee.Feature(intersection).set(
                    {"area": intersection.area().divide(1000 * 1000).floor()}))

        return intersected_feats
示例#9
0
def calcCloudStats(img):
    imgPoly = ee.Algorithms.GeometryConstructors.Polygon(
        ee.Geometry(img.get('system:footprint')).coordinates())

    roi = ee.Geometry(img.get('ROI'))

    intersection = roi.intersection(imgPoly, ee.ErrorMargin(0.5))
    cloudMask = img.select(['cloudScore'
                            ]).gt(cloudThresh).clip(roi).rename('cloudMask')

    cloudAreaImg = cloudMask.multiply(ee.Image.pixelArea())

    stats = cloudAreaImg.reduceRegion(reducer=ee.Reducer.sum(),
                                      geometry=roi,
                                      scale=10,
                                      maxPixels=1e12)

    cloudPercent = ee.Number(stats.get('cloudMask')).divide(
        imgPoly.area(0.001)).multiply(100)
    coveragePercent = ee.Number(intersection.area()).divide(
        roi.area(0.001)).multiply(100)
    cloudPercentROI = ee.Number(stats.get('cloudMask')).divide(
        roi.area(0.001)).multiply(100)

    img = img.set('CLOUDY_PERCENTAGE', cloudPercent)
    img = img.set('ROI_COVERAGE_PERCENT', coveragePercent)
    img = img.set('CLOUDY_PERCENTAGE_ROI', cloudPercentROI)

    return img
示例#10
0
def calcCloudStats(img):
    imgPoly = ee.Algorithms.GeometryConstructors.Polygon(
        ee.Geometry(img.get("system:footprint")).coordinates())

    roi = ee.Geometry(img.get("ROI"))

    intersection = roi.intersection(imgPoly, ee.ErrorMargin(0.5))
    cloudMask = img.select(["cloudScore"
                            ]).gt(cloudThresh).clip(roi).rename("cloudMask")

    cloudAreaImg = cloudMask.multiply(ee.Image.pixelArea())

    stats = cloudAreaImg.reduceRegion(
        **{
            "reducer": ee.Reducer.sum(),
            "geometry": roi,
            "scale": 10,
            "maxPixels": 1e12
        })

    cloudPercent = ee.Number(stats.get("cloudMask")).divide(
        imgPoly.area()).multiply(100)
    coveragePercent = ee.Number(intersection.area()).divide(
        roi.area()).multiply(100)
    cloudPercentROI = ee.Number(stats.get("cloudMask")).divide(
        roi.area()).multiply(100)

    img = img.set("CLOUDY_PERCENTAGE", cloudPercent)
    img = img.set("ROI_COVERAGE_PERCENT", coveragePercent)
    img = img.set("CLOUDY_PERCENTAGE_ROI", cloudPercentROI)

    return img
示例#11
0
def add_coverage(image):
    footprint = ee.Feature(image.get('footprint'))
    image_footprint = footprint.geometry()
    aoi_area = aoi_footprint.area()
    intersect = aoi_footprint.intersection(image_footprint, ee.ErrorMargin(1))
    intersect_area = intersect.area()
    coverage = ee.Number(intersect_area.divide(aoi_area))
    return image.set('AOI_COVERAGE', coverage)
    def generate_sample_grid(self):

        print('Generating samples...')

        # Project the geometry into the target projection
        bounding_box = self.study_area.bounds(ee.ErrorMargin(1, 'projected'), self.projection) \
            .transform(self.projection) \
            .bounds(ee.ErrorMargin(1, 'projected'), self.projection)

        # Get the bounding box partitions
        partitions = self.__partition_bounding_box(bounding_box)

        # Export all of the various ee.FeatureCollesctions to the input asset directory
        self.__export_compute_feature_collections(partitions, sample_points,
                                                  sample_tiles)
        print('Output number of Samples:', sample_points.size().getInfo())

        return None
示例#13
0
def generate_perimeter_points(geom, step):
    """
    Generates points along interiors and exteriors
    :param geom:
    :param step:
    :return:
    """
    error = ee.ErrorMargin(1, 'meters')

    p = geom.perimeter(error)

    n = p.divide(step).int()

    step = p.divide(n)

    # map over exterior and interiors
    def wrap_ring(coords):
        ring = ee.Geometry.LineString(coords)
        distances = ee.List.sequence(0, ring.length(error), step)

        return ee.Feature(ring) \
                 .set({"distances": distances}) \
                 .set({"distancesCount": distances.length()})

    rings = geom.coordinates().map(wrap_ring)

    rings = ee.FeatureCollection(rings)

    def generate_points(ring):
        distances = ring.get('distances')
        segments = ring.geometry().cutLines(distances).geometries()

        segment_points = \
            segments.map(lambda g: ee.Feature(ee.Geometry(g).centroid(1)))

        return ee.FeatureCollection(segment_points)

    points = rings \
        .filter(ee.Filter.gt('distancesCount', 2)) \
        .map(generate_points) \
        .flatten()

    return ee.FeatureCollection(points)
示例#14
0
def calcCloudCoverage(img, cloudThresh=0.2):
    imgPoly = ee.Algorithms.GeometryConstructors.Polygon(
        ee.Geometry(img.get('system:footprint')).coordinates())

    roi = ee.Geometry(img.get('ROI'))
    #line below to used debug issue with export tile pipeline
    #     roi = img.geometry()

    intersection = roi.intersection(imgPoly, ee.ErrorMargin(0.5))
    cloudMask = img.select(['cloudScore'
                            ]).gt(cloudThresh).clip(roi).rename('cloudMask')

    cloudAreaImg = cloudMask.multiply(ee.Image.pixelArea())

    stats = cloudAreaImg.reduceRegion(
        reducer=ee.Reducer.sum(),
        geometry=roi,
        scale=10,
        maxPixels=1e12,
        ## bottom two not in the javascript version
        bestEffort=True,
        tileScale=16)

    ## maxAreaError not in the javascript version, which uses the default
    ## for the .area function calls
    maxAreaError = 10
    cloudPercent = ee.Number(stats.get('cloudMask')).divide(
        imgPoly.area(maxAreaError)).multiply(100)
    coveragePercent = ee.Number(intersection.area(maxAreaError)).divide(
        roi.area(maxAreaError)).multiply(100)
    cloudPercentROI = ee.Number(stats.get('cloudMask')).divide(
        roi.area(maxAreaError)).multiply(100)

    img = img.set('CLOUDY_PERCENTAGE', cloudPercent)
    img = img.set('ROI_COVERAGE_PERCENT', coveragePercent)
    img = img.set('CLOUDY_PERCENTAGE_ROI', cloudPercentROI)

    print("calculated cloud coverage values")

    return img
示例#15
0
    def addStats(img: ee.Image) -> ee.Image:
        patch = ee.Geometry(img.get('patch'))
        patch_area = patch.area(0.001)

        img_footprint = ee.Algorithms.GeometryConstructors.Polygon(
            ee.Geometry(img.get('system:footprint')).coordinates())
        intersection = patch.intersection(img_footprint, ee.ErrorMargin(0.001))
        intersection_area = intersection.area(0.001)
        coverage = ee.Number(intersection_area).divide(patch_area)

        cloud_area_img = img.select('clouds').multiply(ee.Image.pixelArea())
        stats = cloud_area_img.reduceRegion(reducer=ee.Reducer.sum(),
                                            geometry=patch,
                                            scale=10,
                                            maxPixels=1e12)
        cloud_area = stats.get('clouds')
        cloud_coverage = ee.Number(cloud_area).divide(patch_area)
        img = img.set('patchCoverage', coverage)
        img = img.set('patchCloudCoverage', cloud_coverage)

        score = coverage.multiply(cloud_coverage)
        img = img.set('patchScore', score)
        return img
def main():

    # Define the username
    username = "******"

    # Define the output location
    output_dir = "SERVIR/real_time_monitoring"

    # Define kernel size
    kernel_size = 64
    image_kernel = get_kernel(kernel_size)

    # Cloud Storage Parameters
    cloud_bucket = "kilbride_bucket_1"
    cloud_folder = "glad_alert_records/"

    # Get the projection that is needed for the study area
    projection = ee.Projection('EPSG:32648')

    # Load in the GLAD Alert Images
    glad_alerts = ee.Image(
        'users/JohnBKilbride/SERVIR/real_time_monitoring/glad_alerts_2019_to_2020'
    )

    # Load in the sample locations
    sample_locations = ee.FeatureCollection("users/JohnBKilbride/SERVIR/real_time_monitoring/sample_locations_2019_2020_train_val_test_50k") \
        .randomColumn(None, 43214).sort('random').limit(5)

    #################################### Ignore stuff below #######################

    # Load in the topographic metrics
    topography = load_topographic()

    # Loop through the points
    num_samples = sample_locations.size().getInfo()
    sample_list = sample_locations.toList(num_samples)
    print(
        '\nInitiating {num_exports} exports.'.format(num_exports=num_samples))
    for i in range(0, num_samples):

        print('\nExporting record {i}'.format(i=i))

        # Get the next feature by index and cast
        current_location = ee.Feature(sample_list.get(i))

        # Get the geometry from the current feature
        location_geo = current_location.geometry()

        # Get the dataset type
        dataset_subset = ee.Number(
            current_location.get('dataset_subset')).toInt8().getInfo()
        if dataset_subset == 1:
            dataset_name = 'train'
        elif dataset_subset == 2:
            dataset_name = 'validation'
        elif dataset_subset == 3:
            dataset_name = 'test'

        # Get the day and year of each of the dates
        before_day = ee.Number(current_location.get('start_day'))
        before_year = ee.Number(current_location.get('start_year'))
        after_day = ee.Number(current_location.get('alert_day'))
        after_year = ee.Number(current_location.get('alert_year'))

        # Get the Before and After Images
        sentinel = generate_before_after_image(before_day, after_day,
                                               before_year, after_year,
                                               location_geo)

        # Get the Labels
        glad_label = calculate_glad_label(glad_alerts, before_day, after_day,
                                          before_year, after_year)

        # Combine the labels
        all_bands = ee.Image.cat(sentinel, topography, glad_label).toFloat()

        # # Sample with point and neighborhoodToArray()
        # arrays = all_bands.neighborhoodToArray(image_kernel)
        # output = arrays.sampleRegions(
        #     collection = ee.FeatureCollection([current_location]),
        #     properties = ["VV_before","VH_before","VV_after","VH_after","glad_alert"],
        #     scale = 10,
        #     projection = projection,
        #     geometries = False
        #     )

        # # Export the example to Google Cloud Storage
        # task_1 = ee.batch.Export.table.toCloudStorage(
        #     collection = output,
        #     description = 'Export-GLAD-' + str(i),
        #     bucket = cloud_bucket,
        #     fileNamePrefix = cloud_folder + '/glad_alert_' + str(i),
        #     fileFormat = 'TFRecord',
        #     selectors = ["VV_before","VH_before","VV_after","VH_after","glad_alert"]
        #     )
        # task_1.start()

        # For debugging
        # if i < 10:
        export_geometry = location_geo.buffer(ee.Number(kernel_size/2).multiply(10), ee.ErrorMargin(0.0001, "projected"), projection) \
                .bounds(ee.ErrorMargin(0.0001, "projected"), projection)
        task_2 = ee.batch.Export.image.toDrive(
            image=all_bands,
            description='GLAD-Image-Export-' + str(i),
            folder='alert_' + str(kernel_size) + '_' + str(kernel_size) +
            '_before_after_delta_topo',
            fileNamePrefix='glad_' + dataset_name + '_' + str(i),
            region=export_geometry,
            scale=10,
            crs=projection,
            maxPixels=1e6)
        task_2.start()

        # Check for completed exports every 250 iterations
        if i % 250 == 0:
            check_for_monitor_capacity()

        EXPORT_MONITOR.add_task('export_' + str(i), task_2)

    # Run the monitoring of the exports
    EXPORT_MONITOR.monitor_tasks()
    EXPORT_MONITOR.reset_monitor()
    print('...export completed.')

    return None
示例#17
0
def get_water_network_properties():
    """
    Generates variables along water skeleton network polylines.
    """

    j = request.json

    region = ee.Geometry(j['region'])
    start = j['start']
    stop = j['stop']
    scale = j['scale']

    step = j['step']

    crs = j['crs']

    error = ee.ErrorMargin(scale / 2, 'meters')

    if 'network' in j:
        raise Exception(
            'TODO: re-using existing networks is not supported yet')

    # get water mask
    water_vector = get_water_mask_vector(region, scale, start, stop)

    # skeletonize
    output = river_functions.generate_skeleton_from_voronoi(
        scale, water_vector)
    centerline = ee.FeatureCollection(output["centerline"])
    distance = ee.Image(output["distance"])

    # generate width at every offset
    centerline = centerline.map(
        lambda line: line.set("length", line.length(error)))

    short_lines = centerline.filter(ee.Filter.lte('length', step))
    long_lines = centerline.filter(ee.Filter.gt('length', step))

    def process_long_line(line):
        line_length = line.length(error)
        distances = ee.List.sequence(0, line_length, step)
        segments = line.geometry().cutLines(distances, error)

        def generate_line_middle_point(pair):
            pair = ee.List(pair)

            s = ee.Geometry(pair.get(0))
            offset = ee.Number(pair.get(1))

            centroid = ee.Geometry.Point(s.coordinates().get(0))

            return ee.Feature(centroid) \
                .set("lineId", line.id()) \
                .set("offset", offset)

        segments = segments.geometries().zip(distances) \
            .map(generate_line_middle_point)

        return ee.FeatureCollection(segments)

    long_line_points = long_lines.map(process_long_line).flatten()

    def process_short_line(line):
        geom = line.geometry(error, 'EPSG:4326')

        geom = ee.Geometry.Point(geom.coordinates().get(0), 'EPSG:4326')

        return ee.Feature(geom) \
            .set("lineId", line.id()) \
            .set("offset", 0)

    short_line_points = short_lines.map(process_short_line)

    points = long_line_points.merge(short_line_points)

    fa = ee.Image('WWF/HydroSHEDS/15ACC')
    dem = ee.Image('JAXA/ALOS/AW3D30_V1_1').select('MED')

    def add_flow_accumulation(pt):
        flow_accumulation = fa.reduceRegion(reducer=ee.Reducer.max(),
                                            geometry=pt.geometry().buffer(
                                                scale * 10),
                                            scale=scale).values().get(0)

        return pt \
            .set("flow_accumulation", ee.Number(flow_accumulation))

    def add_width(pt):
        width = distance.reduceRegion(reducer=ee.Reducer.max(),
                                      geometry=pt.geometry(),
                                      scale=scale).values().get(0)

        return pt \
            .set("width", ee.Number(width).multiply(scale).multiply(2))

    def add_elevation(pt):
        elevation = dem.reduceRegion(reducer=ee.Reducer.median(),
                                     geometry=pt.geometry().buffer(scale * 10),
                                     scale=scale).values().get(0)

        return pt \
            .set("elevation", ee.Number(elevation))

    points = points.map(add_width)
    points = points.map(add_elevation)
    points = points.map(add_flow_accumulation)

    if crs and crs != 'EPSG:4326':
        points = points.map(transform_feature(crs, scale))

    # create response
    data = points.getInfo()

    return Response(json.dumps(data), status=200, mimetype='application/json')
示例#18
0
        continue

    saveFolder_ = saveFolder + "/" + feature['properties']['title']
    if not os.path.exists(saveFolder_):
        os.mkdir(saveFolder_)
    else:
        continue

    cor = feature['geometry']['coordinates']

    aoi = ee.Geometry.Polygon([
        cor[0][0][0:2], cor[0][1][0:2], cor[0][2][0:2], cor[0][3][0:2],
        cor[0][4][0:2]
    ], None, False)
    #buffer aoi
    aoi = aoi.buffer(100).bounds().simplify(ee.ErrorMargin(1, "meters"))

    epsg = get_utm_epsg(cor[0][0][0], cor[0][0][1])

    for year in [2018, 2019]:

        for m in range(1, 12):
            start_date = ee.Date.fromYMD(year, m, 1)
            end_date = ee.Date.fromYMD(year, m + 1, 1)

            s2_all = ee.ImageCollection('COPERNICUS/S2') \
                    .filterDate(start_date, end_date).filterBounds(aoi)

            print("the available s2 data for this roi and time: ",
                  s2_all.size().getInfo())
示例#19
0
 def inner_map(feat):
     return ee.Feature(feat).buffer(erosion_distance/2, ee.ErrorMargin(1,'projected'), self.projection) \
         .bounds(ee.ErrorMargin(1, 'projected'), self.projection)
示例#20
0
def generate_skeleton_from_voronoi(scale, water_vector):
    # step between points along perimeter
    step = scale * 10
    simplify_centerline_factor = 15

    error = ee.ErrorMargin(1, 'meters')

    # proj = ee.Projection('EPSG:3857').atScale(scale)
    proj = ee.Projection('EPSG:4326').atScale(scale)

    # turn water mask into a skeleton
    def add_coords_count(o):
        return ee.Feature(None, {"count": ee.List(o).length(), "values": o})

    c = water_vector.geometry().coordinates()
    exterior = c.get(0)

    interior = c.slice(1).map(add_coords_count)
    interior = ee.FeatureCollection(interior)
    interior = interior.filter(ee.Filter.gt('count', 5))
    interior = interior.toList(10000).map(
        lambda o: ee.Feature(o).get('values'))

    water_vector = ee.Feature(
        ee.Geometry.Polygon(ee.List([exterior]).cat(interior)))

    geometry = water_vector.geometry()

    geometry_buffer = geometry.buffer(scale * 4, error)

    perimeter_geometry = geometry_buffer \
        .difference(geometry_buffer.buffer(-scale * 2, error), error)

    geometry = geometry_buffer

    points = generate_perimeter_points(geometry, step)

    output = generate_voronoi_polygons(points, scale, geometry)

    polygons = output["polygons"]
    distance = output["distance"]

    dist_filter = ee.Filter.And(
        ee.Filter.intersects(
            **{"leftField": ".geo", "rightField": ".geo", "maxError": error}),
        ee.Filter.equals(
            **{"leftField": "labels", "rightField": "labels"}).Not()
    )

    dist_save_all = ee.Join.saveAll(**{"matchesKey": 'matches'})

    features = dist_save_all.apply(polygons, polygons, dist_filter)

    # find intersection with neighbouring polygons
    def find_neighbours(ff1):
        matches = ee.FeatureCollection(ee.List(ff1.get('matches')))

        def find_neighbours2(ff2):
            i = ff2.intersection(ff1, error, proj)
            t = i.intersects(perimeter_geometry, error, proj)
            m = i.intersects(geometry, error, proj)

            return i.set({"touchesPerimeter": t}).set(
                {"intersectsWithMask": m})

        return matches.map(find_neighbours2)

    features = features.map(find_neighbours).flatten()

    # find a centerline
    f = ee.Filter.And(ee.Filter.eq('touchesPerimeter', False),
                      ee.Filter.eq('intersectsWithMask', True))
    centerline = features.filter(f)
    centerline = centerline.geometry().dissolve(scale, proj) \
                                      .simplify(scale * simplify_centerline_factor, proj)
    centerline = centerline.geometries().map(
        lambda g: ee.Feature(ee.Geometry(g)))
    centerline = ee.FeatureCollection(centerline)
    centerline = centerline \
        .map(lambda o: o.set({"type": o.geometry().type()})) \
        .filter(ee.Filter.eq('type', 'LineString')) \
        # .map(lambda o: o.transform(ee.Projection('EPSG:4326').atScale(scale)), error)

    return {"centerline": centerline, "distance": distance}
示例#21
0
 def __init__(self, *args, **kwargs):
     super().__init__(*args, **kwargs)
     self.error_margin = ee.ErrorMargin(1)
     self.area_proj = "EPSG:5070"
示例#22
0
import geemap

# Create a map centered at (lat, lon).
Map = geemap.Map(center=[40, -100], zoom=4)

# Create two circular geometries.
poly1 = ee.Geometry.Point([-50, 30]).buffer(1e6)
poly2 = ee.Geometry.Point([-40, 30]).buffer(1e6)

# Display polygon 1 in red and polygon 2 in blue.
Map.setCenter(-45, 30)
Map.addLayer(poly1, {'color': 'FF0000'}, 'poly1')
Map.addLayer(poly2, {'color': '0000FF'}, 'poly2')

# Compute the intersection, display it in blue.
intersection = poly1.intersection(poly2, ee.ErrorMargin(1))
Map.addLayer(intersection, {'color': '00FF00'}, 'intersection')

# Compute the union, display it in magenta.
union = poly1.union(poly2, ee.ErrorMargin(1))
Map.addLayer(union, {'color': 'FF00FF'}, 'union')

# Compute the difference, display in yellow.
diff1 = poly1.difference(poly2, ee.ErrorMargin(1))
Map.addLayer(diff1, {'color': 'FFFF00'}, 'diff1')

# Compute symmetric difference, display in black.
symDiff = poly1.symmetricDifference(poly2, ee.ErrorMargin(1))
Map.addLayer(symDiff, {'color': '000000'}, 'symmetric difference')

示例#23
0
def f_clip_ranges(feature):
    return feature.intersection(aoi, ee.ErrorMargin(1))
示例#24
0
 def __init__(self, *args, **kwargs):
     super().__init__(*args, **kwargs)
     self.error_margin = ee.ErrorMargin(1)
     self.countries = ee.FeatureCollection(self.inputs["countries"]["ee_path"])
     self.ecoregions = ee.FeatureCollection(self.inputs["ecoregions"]["ee_path"])
     self.pas = ee.FeatureCollection(self.inputs["pas"]["ee_path"])
示例#25
0
    def __export_dataset_sample (self, sample, sample_num, num_exports):
        """
        Function exports an individual sample to google drive as a TFRecord. 
        These can be combined as a TensorFlow Dataset.

        Parameters
        ----------
        sample : ee.Feature
            A feature containing the following propertioes: 
                partition_id: a numerical ID indicating the sample's partition
                id_list: get 
        sample_num : integer
            A number which is appended to the file path to identify a sample uniquely.
        num_exports: integer
            The total number of exports. This is used when printing info about the export status

        Returns
        -------
        None.

        """
        # Cast the sample
        sample = ee.Feature(sample)
        
        # Get the partition coordinates from the sample
        # partition_id = str(ee.Number(sample.get('partition_id')).toInt16().getInfo())
                
        # Get all of the info needed for export
        sample_ids = ee.List(sample.get("id_list")).getInfo()
        model_set = ee.String(sample.get("model_set")).getInfo()
        
        if model_set == 'test':
            pass
        
        else: 
            
            print(model_set)
            
            # Get rid of the leading characters introduced by previous processing steps
            sample_ids_trimmed = []
            for sentinel_id in sample_ids:
                sample_ids_trimmed.append(sentinel_id)
            
            # Convert the IDs to images
            scenes = []
            alert_date = None
            for i in range(0, len(sample_ids_trimmed)):
            
                # Get the id from the list of ids
                scene = ee.Image("COPERNICUS/S1_GRD/"+sample_ids_trimmed[i])
                
                # Append the scene to the list
                scenes.append(scene)
                
                # Get the alert date
                if i == 0:
                    alert_date = scene.date()
                
            # Convert the list of images to an ee.ImageCollection and select the correct bands
            scenes = ee.ImageCollection.fromImages(scenes) \
                .select(self.output_bands) \
                .sort('system:time_start')
                   
            # Generate the features
            features = scenes.toBands().rename(self.model_feature_names) \
                .unmask(-50) .unitScale(-50, 1)
            
            # Load the GLAD Alert for the scene
            print(alert_date.get('year').getInfo(), alert_date.get('month').getInfo(), alert_date.get('day').getInfo())
            label = self.__retrieve_label(alert_date)
            
            # Stack the outputs
            labels_and_features = ee.Image.cat([features, label]).toFloat()
                    
            # Run the sampling
            output = self.__sample_model_data(labels_and_features, sample.geometry())
            
            # Create the export filename
            file_name = 'alert_record' + '_' + str(sample_num+1)
            
            # Export an image
            clip_geometry = sample.geometry().buffer(self.kernel_size / 2, ee.ErrorMargin(1, 'projected'), self.projection.atScale(10)) \
                .bounds(ee.ErrorMargin(1, 'projected'), self.projection.atScale(10))
            image_task = ee.batch.Export.image.toDrive(
                    image = labels_and_features.clip(clip_geometry).toFloat(), 
                    description = 'Export-GLAD-Label-' + str(sample_num+1), 
                    folder = 'GLAD_TEST',
                    fileNamePrefix = file_name,
                    scale = 10, 
                    maxPixels = 1e13
                    )
            image_task.start()
            
            # Initiate the export    
            task = ee.batch.Export.table.toCloudStorage(
                collection = ee.FeatureCollection([output]),
                description = "Export-Mekong-Alert-" + str(sample_num),  
                bucket = self.gcs_bucket,
                fileNamePrefix = self.gcs_export_folder + '/' + model_set + '/' + file_name, 
                fileFormat = "TFRecord", 
                selectors = labels_and_features.bandNames().getInfo()
                )
            
            # Check if the number of output features is correct
            # Number should be: self.model_feature_names + 2
            target_num_properties = len(self.model_feature_names) + 2 
            output_num_properties = output.propertyNames().length().getInfo()
            
            if target_num_properties == output_num_properties:
                print('Initating '+str(sample_num+1)+' of '+str(num_exports))            
                # task.start()
            else:
                print('Export for index ' + str(sample_num+1) + ' had too few features.')
    
            # Log the info in the exporter
            self.export_monitor.add_task('export_'+str(sample_num), task)
        
        return None