예제 #1
0
def pixelwise_vector_f1(gt: List[Polygon],
                        pred: List[Polygon],
                        v: bool = True):
    """
    Measures pixelwise f1-score, but for vector representation instead of raster.

    :param gt: list of shapely Polygons, represents ground truth;
    :param pred: list of shapely Polygons or Points (according to the 'format' param, represents prediction;
    :param format: 'vector' or 'point', means format of prediction and corresponding variant of algorithm;
    :param v: is_verbose
    :return: float, f1-score and string, log
    """
    log = ''
    gt_mp = MultiPolygon(gt)
    pred_mp = MultiPolygon(pred)

    # try making polygons valid
    gt_mp = gt_mp.buffer(0)
    pred_mp = pred_mp.buffer(0)

    tp = gt_mp.intersection(pred_mp).area
    fp = pred_mp.area - tp
    fn = gt_mp.area - tp

    if tp == 0:
        f1 = 0.
    else:
        precision = tp / (tp + fp)
        recall = tp / (tp + fn)
        f1 = 2 * (precision * recall) / (precision + recall)
    if v:
        log += 'True Positive = ' + str(tp) + ', False Negative = ' + str(
            fn) + ', False Positive = ' + str(fp) + '\n'

    return f1, log
예제 #2
0
def log_jaccard(im_id: str,
                cls: int,
                true_mask: np.ndarray,
                mask: np.ndarray,
                poly_mask: np.ndarray,
                true_poly: MultiPolygon,
                poly: MultiPolygon,
                valid_polygons=False):
    assert len(mask.shape) == 2
    pixel_jc = utils.mask_tp_fp_fn(mask, true_mask, 0.5)
    if valid_polygons:
        if not true_poly.is_valid:
            true_poly = utils.to_multipolygon(true_poly.buffer(0))
        if not poly.is_valid:
            poly = utils.to_multipolygon(poly.buffer(0))
        tp = true_poly.intersection(poly).area
        fn = true_poly.difference(poly).area
        fp = poly.difference(true_poly).area
        poly_jc = tp, fp, fn
    else:
        poly_jc = utils.mask_tp_fp_fn(poly_mask, true_mask, 0.5)
    logger.info(
        '{} cls-{} pixel jaccard: {:.5f}, polygon jaccard: {:.5f}'.format(
            im_id, cls, jaccard(pixel_jc), jaccard(poly_jc)))
    return pixel_jc, poly_jc
예제 #3
0
def X_and_Y_polygon(left: geometry.MultiPolygon,
                    right: geometry.MultiPolygon) -> float:
    try:
        return left.intersection(right).area
    except TopologicalError:
        logger.error(f"Polygonal error")
        return 0
예제 #4
0
def calculate_intersection(gj, gj1):
    g1 = MultiPolygon(
        [shape(feature["geometry"]).buffer(0) for feature in gj['features']])
    g2 = MultiLineString([
        shape(feature["geometry"]) for feature in gj1['features']
        if feature['geometry']['coordinates']
    ])
    return g1.intersection(g2)
def iou(target_bboxes, predicted_bboxes):
    target_polys = MultiPolygon([Polygon(i) for i in target_bboxes]).buffer(0)
    predicted_polys = MultiPolygon([Polygon(i)
                                    for i in predicted_bboxes]).buffer(0)
    intersection = target_polys.intersection(predicted_polys).area
    union = target_polys.union(predicted_polys).area

    try:
        return intersection / union
    except ZeroDivisionError as e:
        return 0
예제 #6
0
def test_intersection():
    polygon1 = Polygon([(0, 0), (0, 2), (2, 2), (2, 0)])
    polygon2 = Polygon([(1, 1), (1, 3), (3, 3), (3, 1)])

    # assert polygon1.intersection(polygon2).bounds == (1.0, 1.0, 2.0, 2.0)

    # Make sure intersection of just one multi is itself
    multi1 = MultiPolygon([polygon1])
    expected_inters = multi1
    inters = intersection(multi1, None)
    _compare_multipolygons(inters, expected_inters)

    # Basic test of two overlapping multis
    multi2 = MultiPolygon([polygon2])
    inters1 = intersection(multi1, multi2)
    expected_inters = MultiPolygon([Polygon([(1, 1), (1, 2), (2, 2), (2, 1)])])
    _compare_multipolygons(inters1, expected_inters)

    # Make sure polys of a multi are unioned before intersection with other multi is taken
    # (verifies fix for GTC-1236)
    polygon4 = Polygon([(2, 2), (2, 4), (4, 4), (4, 2)])
    multi3 = MultiPolygon([polygon1, polygon4])
    inters2 = intersection(multi2, multi3)
    expected_inters = MultiPolygon(
        [
            Polygon([(1, 1), (1, 2), (2, 2), (2, 1)]),
            Polygon([(2, 2), (2, 3), (3, 3), (3, 2)]),
        ]
    )
    _compare_multipolygons(inters2, expected_inters)

    # Sometimes Shapely generates GeometryCollections because of funky intersections
    # (for example when polygons intersect on an edge but also overlap elsewhere)
    # Our intersection function should filter out extraneous bits so the result fits in
    # a MultiPolygon
    multi6 = MultiPolygon(
        [
            Polygon([(0, 0), (0, 2), (1, 2), (1, 0)]).union(
                Polygon([(1, 0), (1, 1), (2, 1), (2, 0)])
            )
        ]
    )
    multi7 = MultiPolygon([Polygon([(1, 0), (1, 2), (2, 2), (2, 0)])])

    # This doesn't test OUR code, just making sure it does what I think it does
    geo_col = multi6.intersection(multi7)
    assert geo_col.type == "GeometryCollection"
    assert any(geo.type == "LineString" for geo in geo_col.geoms)

    # Now test our function
    inters3 = intersection(multi6, multi7)
    expected_inters = MultiPolygon([Polygon([(1, 0), (1, 1), (2, 1), (2, 0)])])
    _compare_multipolygons(inters3, expected_inters)
예제 #7
0
def getRemovedBuildings(year, shed):
    watershed = shape(shed)
    with fiona.open('data/shp/buildings.shp') as b_source:
        print 'Filtering buildings to ' + str(year)
        buildings = MultiPolygon([
            shape(b['geometry']) for b in b_source
            if b['properties']['FirstYear'] <= year
            and b['properties']['LastYear'] >= year
        ])

        print 'Clipping buildings to watershed'
        buildings_shed = buildings.intersection(watershed)
        with fiona.open('data/shp/buildings_test2.shp',
                        'w',
                        driver='ESRI Shapefile',
                        schema=b_source.schema) as w:
            w.writerecords(buildings_shed)
예제 #8
0
def intersection(a: MultiPolygon, b: Optional[MultiPolygon]) -> MultiPolygon:
    if not b:
        geom: MultiPolygon = a
    else:
        _geom = a.intersection(b)
        # Sometimes the intersection results in a GeometryCollection and
        # includes things like LineStrings (like when two polygons both share
        # an edge and overlap elsewhere), which we don't care about. Filter
        # that stuff out to return a MultiPolygon.
        if _geom.type == "GeometryCollection":
            geom_pieces: List[Union[MultiPolygon, Polygon]] = list()
            for g in _geom.geoms:
                if g.type == "MultiPolygon" or g.type == "Polygon":
                    geom_pieces.append(g)
            geom = unary_union(geom_pieces)
        else:
            geom = _geom

    if geom.type == "Polygon":
        geom = MultiPolygon([geom])

    return geom
예제 #9
0
def is_subset_polygon(left: geometry.MultiPolygon,
                      right: geometry.MultiPolygon) -> bool:
    area_union = left.union(right).area
    area_intersection = left.intersection(right).area
    area_left = left.area
    area_right = right.area

    result = math.isclose(area_intersection, area_right, abs_tol=0.03**2)

    jaccard_expected = (area_left - area_right) / area_left
    jaccard_actual = (area_union - area_intersection) / area_union

    if DEBUG:
        logger.debug(f"left, right -> {area_left}, {area_right}")
        logger.debug(
            f"Je = ({area_left:.2f} - {area_right:.2f}) / {area_left:.2f} = {jaccard_expected:.2f}"
        )
        logger.debug(
            f"Ja = ({area_union:.2f} - {area_intersection:.2f}) / {area_union:.2f} = {jaccard_actual:.2f}"
        )

        logger.debug(f"{jaccard_expected} == {jaccard_actual} -> {result}")
    result = math.isclose(jaccard_expected, jaccard_actual, abs_tol=0.1)
    return result
예제 #10
0
# first, calculate a bounding box to restrict the diagram
min_x = min(stops_pts[:,0]) - 5000
max_x = max(stops_pts[:,0]) + 5000
min_y = min(stops_pts[:,1]) - 5000
max_y = max(stops_pts[:,1]) + 5000
bbox = np.array([[min_x,min_y], [max_x,max_y], [min_x,max_y], [max_x,min_y]])

# find the voronoi
coords = np.vstack([stops_pts, bbox])
vor = Voronoi(coords)

# rearrange, so that regions are in the same order as their corresponding
# points, so the last four are the bbox dummy observations, and remove them
regions = np.array(vor.regions)[vor.point_region]
regions = regions[:-4]
clipped = []
for region in regions:
    region_vertices = vor.vertices[region]
    region_polygon = Polygon(region_vertices)

    if nyc.intersects(region_polygon):
        clipped.append(nyc.intersection(region_polygon))

clipped = GeoSeries(clipped)
stops = GeoDataFrame(stops)
stops.index = np.arange(stops.shape[0])
stops['region'] = clipped

pickle.dump(stops,open('save/stops.p','wb'))
pickle.dump(nyc,open('save/nyc.p','wb'))
예제 #11
0
min_x = min(stops_pts[:, 0]) - 5000
max_x = max(stops_pts[:, 0]) + 5000
min_y = min(stops_pts[:, 1]) - 5000
max_y = max(stops_pts[:, 1]) + 5000
bbox = np.array([[min_x, min_y], [max_x, max_y], [min_x, max_y],
                 [max_x, min_y]])

# find the voronoi
coords = np.vstack([stops_pts, bbox])
vor = Voronoi(coords)

# rearrange, so that regions are in the same order as their corresponding
# points, so the last four are the bbox dummy observations, and remove them
regions = np.array(vor.regions)[vor.point_region]
regions = regions[:-4]
clipped = []
for region in regions:
    region_vertices = vor.vertices[region]
    region_polygon = Polygon(region_vertices)

    if nyc.intersects(region_polygon):
        clipped.append(nyc.intersection(region_polygon))

clipped = GeoSeries(clipped)
stops = GeoDataFrame(stops)
stops.index = np.arange(stops.shape[0])
stops['region'] = clipped

pickle.dump(stops, open('save/stops.p', 'wb'))
pickle.dump(nyc, open('save/nyc.p', 'wb'))