Download scripts/eval_shapefiles.py from Egrt/Luuu: direct link, hf CLI and curl.
- Browser
- Download file 6.51 kB
-
https://huggingface.co/spaces/Egrt/Luuu/resolve/main/scripts/eval_shapefiles.py
- Command line
-
hf download hf://spaces/Egrt/Luuu/scripts/eval_shapefiles.py
-
curl -L -o eval_shapefiles.py https://huggingface.co/spaces/Egrt/Luuu/resolve/main/scripts/eval_shapefiles.py
6.51 kB
| #!/usr/bin/env python3 | |
| import os | |
| import fiona | |
| import numpy as np | |
| import shapely.geometry | |
| import argparse | |
| from multiprocess import Pool | |
| from functools import partial | |
| from tqdm import tqdm | |
| try: | |
| __import__("frame_field_learning.local_utils") | |
| except ImportError: | |
| print("ERROR: The frame_field_learning package is not installed! " | |
| "Execute script setup.sh to install local dependencies such as frame_field_learning in develop mode.") | |
| exit() | |
| from lydorn_utils import polygon_utils, python_utils, print_utils, geo_utils | |
| def get_args(): | |
| argparser = argparse.ArgumentParser(description=__doc__) | |
| argparser.add_argument( | |
| '--im_filepath', | |
| required=True, | |
| type=str, | |
| nargs='*', | |
| help='Path(s) to tiff images (to get projection info).') | |
| argparser.add_argument( | |
| '--gt_filepath', | |
| required=True, | |
| type=str, | |
| nargs='*', | |
| help='Path(s) to ground truth.') | |
| argparser.add_argument( | |
| '--pred_filepath', | |
| required=True, | |
| type=str, | |
| nargs='*', | |
| help='Path(s) to predictions.') | |
| argparser.add_argument( | |
| '--overwrite', | |
| action='store_true', | |
| help='The default behavior is to not re-compute a metric if it already has been computed. ' | |
| 'Add the --overwrite flag if you want to overwrite existing metric results.') | |
| args = argparser.parse_args() | |
| return args | |
| def load_geom(geom_filepath, im_filepath): | |
| ext = os.path.splitext(geom_filepath)[-1] | |
| if ext == ".geojson": | |
| file = fiona.open(geom_filepath) | |
| assert len(file) == 1, "There should be only one feature per file" | |
| feat = file[0] | |
| geoms = shapely.geometry.shape(feat["geometry"]) | |
| elif ext == ".shp": | |
| polygons, _ = geo_utils.get_polygons_from_shapefile(im_filepath, geom_filepath, progressbar=False) | |
| geoms = shapely.geometry.collection.GeometryCollection([shapely.geometry.Polygon(polygon[:, ::-1]) for polygon in polygons]) | |
| else: | |
| raise ValueError(f"Geometry can not be loaded from a {ext} file.") | |
| return geoms | |
| def extract_name(filepath): | |
| basename = os.path.basename(filepath) | |
| name = basename.split(".")[0] | |
| return name | |
| def match_im_gt_pred(im_filepaths, gt_filepaths, pred_filepaths): | |
| im_names = list(map(extract_name, im_filepaths)) | |
| gt_names = list(map(extract_name, gt_filepaths)) | |
| im_gt_pred_filepaths = [] | |
| for pred_filepath in pred_filepaths: | |
| name = extract_name(pred_filepath) | |
| im_index = im_names.index(name) | |
| gt_index = gt_names.index(name) | |
| im_gt_pred_filepaths.append((im_filepaths[im_index], gt_filepaths[gt_index], pred_filepath)) | |
| return im_gt_pred_filepaths | |
| def eval_one(im_gt_pred_filepath, overwrite=False): | |
| im_filepath, gt_filepath, pred_filepath = im_gt_pred_filepath | |
| metrics_filepath = os.path.splitext(pred_filepath)[0] + ".metrics.json" | |
| iou_filepath = os.path.splitext(pred_filepath)[0] + ".iou.json" | |
| metrics = False | |
| iou = False | |
| if not overwrite: | |
| # Try reading metrics and iou json | |
| metrics = python_utils.load_json(metrics_filepath) | |
| iou = python_utils.load_json(iou_filepath) | |
| if not metrics or not iou: | |
| # Have to compute at least one so load geometries | |
| gt_polygons = load_geom(gt_filepath, im_filepath) | |
| fixed_gt_polygons = polygon_utils.fix_polygons(gt_polygons, | |
| buffer=0.0001) # Buffer adds vertices but is needed to repair some geometries | |
| pred_polygons = load_geom(pred_filepath, im_filepath) | |
| fixed_pred_polygons = polygon_utils.fix_polygons(pred_polygons) | |
| if not metrics: | |
| # Compute and save metrics | |
| max_angle_diffs = polygon_utils.compute_polygon_contour_measures(fixed_pred_polygons, fixed_gt_polygons, | |
| sampling_spacing=1.0, min_precision=0.5, | |
| max_stretch=2, progressbar=True) | |
| max_angle_diffs = [value for value in max_angle_diffs if value is not None] | |
| max_angle_diffs = np.array(max_angle_diffs) | |
| max_angle_diffs = max_angle_diffs * 180 / np.pi # Convert to degrees | |
| metrics = { | |
| "max_angle_diffs": list(max_angle_diffs) | |
| } | |
| python_utils.save_json(metrics_filepath, metrics) | |
| if not iou: | |
| fixed_gt_polygon_collection = shapely.geometry.collection.GeometryCollection(fixed_gt_polygons) | |
| fixed_pred_polygon_collection = shapely.geometry.collection.GeometryCollection(fixed_pred_polygons) | |
| intersection = fixed_gt_polygon_collection.intersection(fixed_pred_polygon_collection).area | |
| union = fixed_gt_polygon_collection.union(fixed_pred_polygon_collection).area | |
| iou = { | |
| "intersection": intersection, | |
| "union": union | |
| } | |
| python_utils.save_json(iou_filepath, iou) | |
| return { | |
| "metrics": metrics, | |
| "iou": iou, | |
| } | |
| def main(): | |
| args = get_args() | |
| print_utils.print_info(f"INFO: evaluating {len(args.pred_filepath)} predictions.") | |
| # Match files together | |
| im_gt_pred_filepaths = match_im_gt_pred(args.im_filepath, args.gt_filepath, args.pred_filepath) | |
| pool = Pool() | |
| metrics_iou_list = list(tqdm(pool.imap(partial(eval_one, overwrite=args.overwrite), im_gt_pred_filepaths), desc="Compute eval metrics", total=len(im_gt_pred_filepaths))) | |
| # Aggregate metrics and IoU | |
| aggr_metrics = { | |
| "max_angle_diffs": [] | |
| } | |
| aggr_iou = { | |
| "intersection": 0, | |
| "union": 0 | |
| } | |
| for metrics_iou in metrics_iou_list: | |
| if metrics_iou["metrics"]: | |
| aggr_metrics["max_angle_diffs"] += metrics_iou["metrics"]["max_angle_diffs"] | |
| if metrics_iou["iou"]: | |
| aggr_iou["intersection"] += metrics_iou["iou"]["intersection"] | |
| aggr_iou["union"] += metrics_iou["iou"]["union"] | |
| aggr_iou["iou"] = aggr_iou["intersection"] / aggr_iou["union"] | |
| aggr_metrics_filepath = os.path.join(os.path.dirname(args.pred_filepath[0]), "aggr_metrics.json") | |
| aggr_iou_filepath = os.path.join(os.path.dirname(args.pred_filepath[0]), "aggr_iou.json") | |
| python_utils.save_json(aggr_metrics_filepath, aggr_metrics) | |
| python_utils.save_json(aggr_iou_filepath, aggr_iou) | |
| if __name__ == '__main__': | |
| main() | |