def __init__(self, root, num_classes, cover=None): super().__init__() self.num_classes = num_classes self.tiles = [ path for tile, path in tiles_from_dir( os.path.join(root, "labels"), cover=cover, xyz_path=True) ] assert len(self.tiles), "Empty Dataset"
def test_slippy_map_directory(self): root = "tests/fixtures/images" tiles = [(tile, path) for tile, path in tiles_from_dir(root, xyz_path=True)] tiles.sort() self.assertEqual(len(tiles), 3) tile, path = tiles[0] self.assertEqual(type(tile), mercantile.Tile) self.assertEqual(path, "tests/fixtures/images/18/69105/105093.jpg")
def __init__(self, config, ts, root, cover=None, tiles_weights=None, mode=None, metatiles=False, keep_borders=False): super().__init__() self.mode = mode self.config = config self.tiles_weights = tiles_weights self.metatiles = metatiles self.da = True if "da" in self.config["train"].keys() and self.config["train"]["da"]["p"] > 0.0 else False assert mode in ["train", "eval", "predict"] path = os.path.join(root, config["channels"][0]["name"]) self.tiles_paths = [(tile, path) for tile, path in tiles_from_dir(path, cover=cover, xyz_path=True)] if metatiles: self.metatiles_paths = self.tiles_paths if not keep_borders: self.tiles_paths = [ (tile, path) for tile, path in self.metatiles_paths if tile_is_neighboured(tile, self.metatiles_paths) ] self.cover = {tile for tile, path in self.tiles_paths} assert len(self.tiles_paths), "Empty Dataset" self.tiles = {} num_channels = 0 for channel in config["channels"]: path = os.path.join(root, channel["name"]) self.tiles[channel["name"]] = [ (tile, path) for tile, path in tiles_from_dir(path, cover=self.cover, xyz_path=True) ] num_channels += len(channel["bands"]) self.shape_in = (num_channels,) + tuple(ts) # C,W,H self.shape_out = (len(config["classes"]),) + tuple(ts) # C,W,H if self.mode in ["train", "eval"]: path = os.path.join(root, "labels") self.tiles["labels"] = [(tile, path) for tile, path in tiles_from_dir(path, cover=self.cover, xyz_path=True)] for channel in config["channels"]: # Order images and labels accordingly self.tiles[channel["name"]].sort(key=lambda tile: tile[0]) self.tiles["labels"].sort(key=lambda tile: tile[0]) assert len(self.tiles), "Empty Dataset"
def main(args): config = load_config(args.config) check_classes(config) index = [ i for i in (list(range(len(config["classes"])))) if config["classes"][i]["title"] == args.type ] assert index, "Requested type {} not found among classes title in the config file.".format( args.type) masks = list(tiles_from_dir(args.masks, xyz_path=True)) assert len(masks), "empty masks directory: {}".format(args.masks) print("neo vectorize {} from {}".format(args.type, args.masks), file=sys.stderr, flush=True) if os.path.dirname(os.path.expanduser(args.out)): os.makedirs(os.path.dirname(os.path.expanduser(args.out)), exist_ok=True) out = open(args.out, "w", encoding="utf-8") assert out, "Unable to write in output file" out.write('{"type":"FeatureCollection","features":[') first = True for tile, path in tqdm(masks, ascii=True, unit="mask"): mask = (np.array(Image.open(path).convert("P"), dtype=np.uint8) == index).astype(np.uint8) try: C, W, H = mask.shape except: W, H = mask.shape transform = rasterio.transform.from_bounds( (*mercantile.bounds(tile.x, tile.y, tile.z)), W, H) for shape, value in rasterio.features.shapes(mask, transform=transform, mask=mask): geom = '"geometry":{{"type": "Polygon", "coordinates":{}}}'.format( json.dumps(shape["coordinates"])) out.write('{}{{"type":"Feature",{}}}'.format( "" if first else ",", geom)) first = False out.write("]}")
def main(args): if not args.masks or not args.labels: assert args.mode != "list", "Parameters masks and labels are mandatories in list mode." assert not (args.min or args.max), "Both --masks and --labels mandatory, for metric filtering." if args.min or args.max: config = load_config(args.config) args.out = os.path.expanduser(args.out) cover = [tile for tile in tiles_from_csv(os.path.expanduser(args.cover))] if args.cover else None args_minmax = set() args.min = {(m[0], m[1]): m[2] for m in args.min} if args.min else dict() args.max = {(m[0], m[1]): m[2] for m in args.max} if args.max else dict() args_minmax.update(args.min.keys()) args_minmax.update(args.max.keys()) minmax = dict() for mm in args_minmax: mm_min = float(args.min[mm]) if mm in args.min else 0.0 mm_max = float(args.max[mm]) if mm in args.max else 1.0 assert mm_min < mm_max, "--min must be lower than --max, on {}".format(mm) minmax[mm] = { "min": mm_min, "max": mm_max, "class_id": [c for c, classe in enumerate(config["classes"]) if classe["title"] == mm[0]][0], "module": load_module("neat_eo.metrics." + mm[1]), } if not args.workers: args.workers = os.cpu_count() print("neo compare {} on CPU, with {} workers".format(args.mode, args.workers), file=sys.stderr, flush=True) if args.images: tiles = [tile for tile in tiles_from_dir(args.images[0], cover=cover)] assert len(tiles), "Empty images dir: {}".format(args.images[0]) for image in args.images[1:]: assert sorted(tiles) == sorted([tile for tile in tiles_from_dir(image, cover=cover)]), "Unconsistent images dirs" if args.labels and args.masks: tiles_masks = [tile for tile in tiles_from_dir(args.masks, cover=cover)] tiles_labels = [tile for tile in tiles_from_dir(args.labels, cover=cover)] if args.images: assert sorted(tiles) == sorted(tiles_masks) == sorted(tiles_labels), "Unconsistent images/label/mask directories" else: assert len(tiles_masks), "Empty masks dir: {}".format(args.masks) assert len(tiles_labels), "Empty labels dir: {}".format(args.labels) assert sorted(tiles_masks) == sorted(tiles_labels), "Label and Mask directories are not consistent" tiles = tiles_masks tiles_list = [] tiles_compare = [] progress = tqdm(total=len(tiles), ascii=True, unit="tile") log = False if args.mode == "list" else Logs(os.path.join(args.out, "log")) with futures.ThreadPoolExecutor(args.workers) as executor: def worker(tile): x, y, z = list(map(str, tile)) if args.masks and args.labels: label = np.array(Image.open(os.path.join(args.labels, z, x, "{}.png".format(y)))) mask = np.array(Image.open(os.path.join(args.masks, z, x, "{}.png".format(y)))) assert label.shape == mask.shape, "Inconsistent tiles (size or dimensions)" metrics = dict() for mm in minmax: try: metrics[mm] = getattr(minmax[mm]["module"], "get")( torch.as_tensor(label, device="cpu"), torch.as_tensor(mask, device="cpu"), minmax[mm]["class_id"], ) except: progress.update() return False, tile if not (minmax[mm]["min"] <= metrics[mm] <= minmax[mm]["max"]): progress.update() return True, tile tiles_compare.append(tile) if args.mode == "side": for i, root in enumerate(args.images): img = tile_image_from_file(tile_from_xyz(root, x, y, z)[1], force_rgb=True) if i == 0: side = np.zeros((img.shape[0], img.shape[1] * len(args.images), 3)) side = np.swapaxes(side, 0, 1) if args.vertical else side image_shape = img.shape else: assert image_shape[0:2] == img.shape[0:2], "Unconsistent image size to compare" if args.vertical: side[i * image_shape[0] : (i + 1) * image_shape[0], :, :] = img else: side[:, i * image_shape[0] : (i + 1) * image_shape[0], :] = img tile_image_to_file(args.out, tile, np.uint8(side)) elif args.mode == "stack": for i, root in enumerate(args.images): tile_image = tile_image_from_file(tile_from_xyz(root, x, y, z)[1], force_rgb=True) if i == 0: image_shape = tile_image.shape[0:2] stack = tile_image / len(args.images) else: assert image_shape == tile_image.shape[0:2], "Unconsistent image size to compare" stack = stack + (tile_image / len(args.images)) tile_image_to_file(args.out, tile, np.uint8(stack)) elif args.mode == "list": tiles_list.append([tile, metrics]) progress.update() return True, tile for ok, tile in executor.map(worker, tiles): if not ok and log: log.log("Warning: skipping. {}".format(str(tile))) if args.mode == "list": with open(args.out, mode="w") as out: if args.geojson: out.write('{"type":"FeatureCollection","features":[') first = True for tile_list in tiles_list: tile, metrics = tile_list x, y, z = list(map(str, tile)) if args.geojson: prop = '"properties":{{"x":{},"y":{},"z":{}'.format(x, y, z) for metric in metrics: prop += ',"{}":{:.3f}'.format(metric, metrics[metric]) geom = '"geometry":{}'.format(json.dumps(feature(tile, precision=6)["geometry"])) out.write('{}{{"type":"Feature",{},{}}}}}'.format("," if not first else "", geom, prop)) first = False if not args.geojson: out.write("{},{},{}".format(x, y, z)) for metric in metrics: out.write("\t{:.3f}".format(metrics[metric])) out.write(os.linesep) if args.geojson: out.write("]}") out.close() base_url = args.web_ui_base_url if args.web_ui_base_url else "." if args.mode == "side" and not args.no_web_ui: template = "compare.html" if not args.web_ui_template else args.web_ui_template web_ui(args.out, base_url, tiles, tiles_compare, args.format, template, union_tiles=False) if args.mode == "stack" and not args.no_web_ui: template = "leaflet.html" if not args.web_ui_template else args.web_ui_template tiles = [tile for tile in tiles_from_dir(args.images[0])] web_ui(args.out, base_url, tiles, tiles_compare, args.format, template)