138 lines
5.2 KiB
Python
138 lines
5.2 KiB
Python
import argparse
|
|
import json
|
|
import os
|
|
import ray
|
|
import hytools as ht
|
|
from hytools.io.envi import WriteENVI
|
|
from hytools.brdf import calc_brdf_coeffs
|
|
|
|
|
|
def build_anc_mapping(anc_file, anc_names):
|
|
return dict(zip(anc_names, [[anc_file, i] for i in range(len(anc_names))]))
|
|
|
|
|
|
def build_brdf_config(args):
|
|
mask = [["ndi", {"band_1": args.ndi_band_1, "band_2": args.ndi_band_2, "min": args.ndi_min, "max": args.ndi_max}]]
|
|
brdf = {
|
|
"type": args.brdf_type,
|
|
"grouped": False,
|
|
"geometric": args.geometric,
|
|
"volume": args.volume,
|
|
"b/r": args.b_r,
|
|
"h/b": args.h_b,
|
|
"sample_perc": args.sample_perc,
|
|
"calc_mask": mask,
|
|
"apply_mask": mask,
|
|
"solar_zn_type": args.solar_zn_type
|
|
}
|
|
if args.brdf_type == "universal":
|
|
brdf["diagnostic_plots"] = False
|
|
brdf["diagnostic_waves"] = []
|
|
if args.brdf_type == "flex":
|
|
brdf["interp_kind"] = "linear"
|
|
brdf["bin_type"] = "dynamic"
|
|
brdf["num_bins"] = args.num_bins
|
|
brdf["ndvi_bin_min"] = args.ndvi_bin_min
|
|
brdf["ndvi_bin_max"] = args.ndvi_bin_max
|
|
brdf["ndvi_perc_min"] = args.ndvi_perc_min
|
|
brdf["ndvi_perc_max"] = args.ndvi_perc_max
|
|
return brdf
|
|
|
|
|
|
def export_brdf_corrected(hy_obj, args):
|
|
header_dict = hy_obj.get_header()
|
|
header_dict["data ignore value"] = hy_obj.no_data
|
|
header_dict["data type"] = 4
|
|
output_name = os.path.join(
|
|
args["output_dir"],
|
|
f"{os.path.splitext(os.path.basename(hy_obj.file_name))[0]}_{args['suffix']}"
|
|
)
|
|
writer = WriteENVI(output_name, header_dict)
|
|
iterator = hy_obj.iterate(by="line", corrections=hy_obj.corrections)
|
|
while not iterator.complete:
|
|
line = iterator.read_next()
|
|
writer.write_line(line, iterator.current_line)
|
|
writer.close()
|
|
|
|
|
|
def export_brdf_coeffs(hy_obj, args):
|
|
output_name = os.path.join(
|
|
args["output_dir"],
|
|
f"{os.path.splitext(os.path.basename(hy_obj.file_name))[0]}_brdf_coeffs_{args['suffix']}.json"
|
|
)
|
|
with open(output_name, "w") as outfile:
|
|
json.dump(hy_obj.brdf, outfile)
|
|
|
|
|
|
def main():
|
|
parser = argparse.ArgumentParser(description="BRDF correction for ENVI BIP images")
|
|
parser.add_argument("image", type=str)
|
|
parser.add_argument("anc_file", type=str)
|
|
parser.add_argument("output_dir", type=str)
|
|
parser.add_argument("--anc-map", type=str, default="")
|
|
parser.add_argument("--anc-names", type=str, default="path_length,sensor_az,sensor_zn,solar_az,solar_zn,phase,slope,aspect,cosine_i,utc_time")
|
|
parser.add_argument("--brdf-type", type=str, default="universal", choices=["universal", "flex"])
|
|
parser.add_argument("--suffix", type=str, default="brdf")
|
|
parser.add_argument("--num-cpus", type=int, default=1)
|
|
parser.add_argument("--bad-bands-json", type=str, default="")
|
|
parser.add_argument("--solar-zn-type", type=str, default="scene")
|
|
parser.add_argument("--geometric", type=str, default="li_dense_r")
|
|
parser.add_argument("--volume", type=str, default="ross_thick")
|
|
parser.add_argument("--b-r", type=float, default=2.5)
|
|
parser.add_argument("--h-b", type=float, default=2.0)
|
|
parser.add_argument("--sample-perc", type=float, default=0.1)
|
|
parser.add_argument("--ndi-band-1", type=float, default=850.0)
|
|
parser.add_argument("--ndi-band-2", type=float, default=660.0)
|
|
parser.add_argument("--ndi-min", type=float, default=0.05)
|
|
parser.add_argument("--ndi-max", type=float, default=1.0)
|
|
parser.add_argument("--num-bins", type=int, default=18)
|
|
parser.add_argument("--ndvi-bin-min", type=float, default=0.05)
|
|
parser.add_argument("--ndvi-bin-max", type=float, default=1.0)
|
|
parser.add_argument("--ndvi-perc-min", type=float, default=10.0)
|
|
parser.add_argument("--ndvi-perc-max", type=float, default=95.0)
|
|
parser.add_argument("--export-coeffs", action="store_true")
|
|
args = parser.parse_args()
|
|
|
|
os.makedirs(args.output_dir, exist_ok=True)
|
|
|
|
if args.anc_map:
|
|
with open(args.anc_map, "r") as infile:
|
|
anc_map = json.load(infile)
|
|
else:
|
|
anc_names = [x.strip() for x in args.anc_names.split(",") if x.strip()]
|
|
anc_map = build_anc_mapping(args.anc_file, anc_names)
|
|
|
|
config_dict = {
|
|
"file_type": "envi",
|
|
"input_files": [args.image],
|
|
"anc_files": {args.image: anc_map},
|
|
"corrections": ["brdf"],
|
|
"brdf": build_brdf_config(args),
|
|
"num_cpus": args.num_cpus
|
|
}
|
|
|
|
if args.bad_bands_json:
|
|
config_dict["bad_bands"] = json.loads(args.bad_bands_json)
|
|
|
|
if ray.is_initialized():
|
|
ray.shutdown()
|
|
ray.init(num_cpus=config_dict["num_cpus"])
|
|
|
|
HyTools = ray.remote(ht.HyTools)
|
|
actor = HyTools.remote()
|
|
ray.get(actor.read_file.remote(args.image, "envi", anc_map))
|
|
if "bad_bands" in config_dict:
|
|
ray.get(actor.create_bad_bands.remote(config_dict["bad_bands"]))
|
|
|
|
calc_brdf_coeffs([actor], config_dict)
|
|
|
|
ray.get(actor.do.remote(export_brdf_corrected, {"output_dir": args.output_dir, "suffix": args.suffix}))
|
|
if args.export_coeffs:
|
|
ray.get(actor.do.remote(export_brdf_coeffs, {"output_dir": args.output_dir, "suffix": args.suffix}))
|
|
|
|
ray.shutdown()
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|