emilyveenhuis commited on
Commit
4c7acca
1 Parent(s): 39fc5c4

Add app and supporting files

Browse files
README.md CHANGED
@@ -1,6 +1,6 @@
1
  ---
2
  title: NRTK
3
- emoji: 💻
4
  colorFrom: purple
5
  colorTo: blue
6
  sdk: gradio
 
1
  ---
2
  title: NRTK
3
+ emoji: 🕵️‍♂️
4
  colorFrom: purple
5
  colorTo: blue
6
  sdk: gradio
app.py ADDED
@@ -0,0 +1,478 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # This app explores integrating `nrtk` with `Gradio` to create an interactive interface for applying perturbations.
2
+
3
+ import numpy as np
4
+ import yaml
5
+ from pathlib import Path
6
+
7
+ from nrtk.impls.perturb_image.pybsm.scenario import PybsmScenario
8
+ from nrtk.impls.perturb_image.pybsm.sensor import PybsmSensor
9
+ from nrtk.impls.perturb_image.pybsm.perturber import PybsmPerturber
10
+
11
+ import gradio as gr # type: ignore
12
+
13
+ # Define default values for fields for initilization and button clicks
14
+ #
15
+ # Note, for this application we'll be focusing on the use case of satellite imagery, so we'll try to pick default
16
+ # values that work with images similar to those in the xView dataset. Perturbing images from other datasets or other
17
+ # operational tasks may not be successful without modification to these values; defining broad defaults is extremely
18
+ # difficult, if not impossible due to the physics-based nature of these perturbations.
19
+ default_values = {
20
+ "gsd": 0.3,
21
+ "scenario": {
22
+ "aircraftSpeed": 100.,
23
+ "altitude": 4000.,
24
+ "backgroundReflectance": 0.07,
25
+ "backgroundTemperature": 293.,
26
+ "cn2at1m": 1.7e-14,
27
+ "groundRange": 1000,
28
+ "haWindspeed": 21.,
29
+ "ihaze": 1,
30
+ "name": "",
31
+ "targetReflectance": 0.15,
32
+ "targetTemperature": 295.,
33
+ },
34
+ "sensor": {
35
+ "D": .029,
36
+ "bitdepth": 11.9,
37
+ "darkCurrent": 0.,
38
+ "dax": 0.0001,
39
+ "day": 0.0001,
40
+ "eta": 0.4,
41
+ "f": .27,
42
+ "intTime": 0.03,
43
+ "maxN": 96000,
44
+ "maxWellFill": 0.6,
45
+ "name": "",
46
+ "optTransWavelengths": [3.8e-07, 7.0e-07],
47
+ "opticsTransmission": [],
48
+ "px": 2.0e-05,
49
+ "qe": [0.05, 0.6, 0.75, 0.85, 0.85, 0.75, 0.5, 0.2, 0],
50
+ "qewavelengths": [3.0e-7, 4.0e-7, 5.0e-7, 6.0e-7, 7.0e-7, 8.0e-7, 9.0e-7, 1.0e-6, 1.1e-6],
51
+ "readNoise": 25.,
52
+ "sx": 0.,
53
+ "sy": 0.
54
+ }
55
+ }
56
+
57
+
58
+ def load_config(config):
59
+ """
60
+ Loads configuration from config dictionary to UI elements
61
+ """
62
+ scenario_config = config["scenario"]
63
+ default_scenario = default_values["scenario"]
64
+ sensor_config = config["sensor"]
65
+ default_sensor = default_values["sensor"]
66
+ return {
67
+ input_group: gr.Group(visible=True),
68
+ img_gsd: config["gsd"] if "gsd" in config else default_values["gsd"],
69
+ scenario_name: scenario_config["name"] if "name" in scenario_config else default_scenario["name"],
70
+ ihaze: scenario_config["ihaze"] if "ihaze" in scenario_config else default_scenario["ihaze"],
71
+ altitude_m: scenario_config["altitude"] if "altitude" in scenario_config else default_scenario["altitude"],
72
+ ground_range_m: scenario_config["groundRange"]
73
+ if "groundRange" in scenario_config else default_scenario["groundRange"],
74
+ aircraft_speed_m_Per_s: scenario_config["aircraftSpeed"]
75
+ if "aircraftSpeed" in scenario_config else default_scenario["aircraftSpeed"],
76
+ target_reflectance: scenario_config["targetReflectance"]
77
+ if "targetReflectance" in scenario_config else default_scenario["targetReflectance"],
78
+ target_temperature_K: scenario_config["targetTemperature"]
79
+ if "targetTemperature" in scenario_config else default_scenario["targetTemperature"],
80
+ bkgd_reflectance: scenario_config["backgroundReflectance"]
81
+ if "backgroundReflectance" in scenario_config else default_scenario["backgroundReflectance"],
82
+ bkgd_temperature_K: scenario_config["backgroundTemperature"]
83
+ if "backgroundTemperature" in scenario_config else default_scenario["backgroundTemperature"],
84
+ ha_windspeed_m_Per_s: scenario_config["haWindspeed"]
85
+ if "haWindspeed" in scenario_config else default_scenario["haWindspeed"],
86
+ cn2at1m: scenario_config["cn2at1m"]
87
+ if "cn2at1m" in scenario_config else default_scenario["cn2at1m"],
88
+ sensor_name: sensor_config["name"] if "name" in sensor_config else default_sensor["name"],
89
+ D_m: sensor_config["D"] if "D" in sensor_config else default_sensor["D"],
90
+ f_m: sensor_config["f"] if "f" in sensor_config else default_sensor["f"],
91
+ px_m: sensor_config["px"] if "px" in sensor_config else default_sensor["px"],
92
+ # Convert lists to comma separated text
93
+ optTransWavelengths_str: ", ".join(str(x) for x in sensor_config["optTransWavelengths"])
94
+ if "optTransWavelengths" in sensor_config and sensor_config["optTransWavelengths"] else "",
95
+ opticsTransmission_str: ", ".join(str(x) for x in sensor_config["opticsTransmission"])
96
+ if "opticsTransmission" in sensor_config and sensor_config["opticsTransmission"] else "",
97
+ eta: sensor_config["eta"] if "eta" in sensor_config else default_sensor["eta"],
98
+ int_time_s: sensor_config["intTime"] if "intTime" in sensor_config else default_sensor["intTime"],
99
+ dark_current: sensor_config["darkCurrent"] if "darkCurrent" in sensor_config else default_sensor["darkCurrent"],
100
+ read_noise: sensor_config["readNoise"] if "readNoise" in sensor_config else default_sensor["readNoise"],
101
+ max_N: sensor_config["maxN"] if "maxN" in sensor_config else default_sensor["maxN"],
102
+ bit_depth: sensor_config["bitdepth"] if "bitdepth" in sensor_config else default_sensor["bitdepth"],
103
+ max_well_fill: sensor_config["maxWellFill"] if "maxWellFill" in sensor_config else default_sensor["maxWellFill"],
104
+ sx: sensor_config["sx"] if "sx" in sensor_config else default_sensor["sx"],
105
+ sy: sensor_config["sy"] if "sy" in sensor_config else default_sensor["sy"],
106
+ dax: sensor_config["dax"] if "dax" in sensor_config else default_sensor["dax"],
107
+ day: sensor_config["day"] if "day" in sensor_config else default_sensor["day"],
108
+ # Convert lists to comma separated text
109
+ qe_str: ", ".join(str(x) for x in sensor_config["qe"]) if "qe" in sensor_config and sensor_config["qe"] else "",
110
+ qewavelengths_str: ", ".join(str(x) for x in sensor_config["qewavelengths"])
111
+ if "qewavelengths" in sensor_config and sensor_config["qewavelengths"] else ""
112
+ }
113
+
114
+
115
+ def generate_config(data):
116
+ """
117
+ Generate dictionary that can easily be transformed into sensor and scenario objects
118
+ """
119
+ # Input validation
120
+ if data[ihaze] not in PybsmScenario.ihaze_values:
121
+ raise gr.Error("Invalid ihaze value!")
122
+ if data[altitude_m] not in PybsmScenario.altitude_values:
123
+ raise gr.Error("Invalid altitude value!")
124
+ if data[ground_range_m] not in PybsmScenario.groundRange_values:
125
+ raise gr.Error("Invalid ground range value!")
126
+
127
+ scenario_config = {
128
+ "name": data[scenario_name],
129
+ "ihaze": data[ihaze],
130
+ "altitude": data[altitude_m],
131
+ "groundRange": data[ground_range_m],
132
+ "aircraftSpeed": data[aircraft_speed_m_Per_s],
133
+ "targetReflectance": data[target_reflectance],
134
+ "targetTemperature": data[target_temperature_K],
135
+ "backgroundReflectance": data[bkgd_reflectance],
136
+ "backgroundTemperature": data[bkgd_temperature_K],
137
+ "haWindspeed": data[ha_windspeed_m_Per_s],
138
+ "cn2at1m": data[cn2at1m]
139
+ }
140
+
141
+ # Convert text fields into lists of floats
142
+ optTransWavelengths = [float(w.strip()) for w in data[optTransWavelengths_str].split(",") if w.strip()]
143
+ opticsTransmission = [float(t.strip()) for t in data[opticsTransmission_str].split(",") if t.strip()]
144
+ opticsTransmission = None if not opticsTransmission else opticsTransmission
145
+ qe = [float(q.strip()) for q in data[qe_str].split(",") if q.strip()]
146
+ qe = None if not qe else qe
147
+ qewavelengths = [float(q.strip()) for q in data[qewavelengths_str].split(",") if q.strip()]
148
+ qewavelengths = None if not qewavelengths else qewavelengths
149
+
150
+ # More input validation
151
+ if len(optTransWavelengths) < 2:
152
+ raise gr.Error("At least 2 optical transmission wavelengths required!")
153
+ if optTransWavelengths[0] >= optTransWavelengths[-1]:
154
+ raise gr.Error("Optical transmission wavelengths should be entered least to greatest!")
155
+ if opticsTransmission is not None and len(opticsTransmission) != len(optTransWavelengths):
156
+ raise gr.Error("If provided, Optical Transmission must have the same number of values as Spectral Bandpass!")
157
+
158
+ sensor_config = {
159
+ "name": data[sensor_name],
160
+ "D": data[D_m],
161
+ "f": data[f_m],
162
+ "px": data[px_m],
163
+ "optTransWavelengths": optTransWavelengths,
164
+ "opticsTransmission": opticsTransmission,
165
+ "eta": data[eta],
166
+ "intTime": data[int_time_s],
167
+ "darkCurrent": data[dark_current],
168
+ "readNoise": data[read_noise],
169
+ "maxN": data[max_N],
170
+ "bitdepth": data[bit_depth],
171
+ "maxWellFill": data[max_well_fill],
172
+ "sx": data[sx],
173
+ "sy": data[sy],
174
+ "dax": data[dax],
175
+ "day": data[day],
176
+ "qe": qe,
177
+ "qewavelengths": qewavelengths
178
+ }
179
+
180
+ return {
181
+ "scenario": scenario_config,
182
+ "sensor": sensor_config,
183
+ "gsd" : data[img_gsd]
184
+ }
185
+
186
+
187
+ def gen_new_config():
188
+ """
189
+ Resets all fields to default values
190
+ """
191
+ return load_config(default_values)
192
+
193
+
194
+ def load_config_from_file(data):
195
+ """
196
+ Loads configuration from given file to UI elements
197
+ """
198
+ if not data[config_file]:
199
+ raise gr.Error("A file must be uploaded to load existing configuration!")
200
+ with open(data[config_file]) as file:
201
+ config = yaml.safe_load(file)
202
+
203
+ return load_config(config)
204
+
205
+
206
+ def submit(data):
207
+ """
208
+ Apply the perturbation and hide/show relevant UI elements as needed
209
+ """
210
+ config = generate_config(data)
211
+ scenario_config = config["scenario"]
212
+ sensor_config = config["sensor"]
213
+
214
+ # Sensor expects numpy arrays, but plain lists serialize better so convert here
215
+ if sensor_config["optTransWavelengths"]:
216
+ sensor_config["optTransWavelengths"] = np.asarray(sensor_config["optTransWavelengths"])
217
+ if sensor_config["opticsTransmission"]:
218
+ sensor_config["opticsTransmission"] = np.asarray(sensor_config["opticsTransmission"])
219
+ if sensor_config["qe"]:
220
+ sensor_config["qe"] = np.asarray(sensor_config["qe"])
221
+ if sensor_config["qewavelengths"]:
222
+ sensor_config["qewavelengths"] = np.asarray(sensor_config["qewavelengths"])
223
+ gsd = config["gsd"]
224
+
225
+ sensor = PybsmSensor(**sensor_config)
226
+ scenario = PybsmScenario(**scenario_config)
227
+ perturber = PybsmPerturber(sensor=sensor, scenario=scenario)
228
+
229
+ # Apply the perturbation and display
230
+ return {
231
+ output_col: gr.Column(visible=True),
232
+ out_img: perturber(image=data[input_img], additional_params={"img_gsd": gsd})
233
+ }
234
+
235
+
236
+ def save(data):
237
+ """
238
+ Saves current configuration at given path
239
+ """
240
+ if not data[file_path]:
241
+ raise gr.Error("A filename must be provided to save the configuration!")
242
+ path = Path(data[file_path])
243
+ path.parent.mkdir(parents=True, exist_ok=True)
244
+ config = generate_config(data)
245
+ with open(path, 'w') as yaml_file:
246
+ yaml.dump(config, yaml_file)
247
+ gr.Info(f"Saved config: {data[file_path]}")
248
+
249
+
250
+ # Lastly, we define the layout of the application and register the button click listener functions:
251
+ with gr.Blocks() as demo:
252
+ gr.Markdown(
253
+ """
254
+ # Apply pyBSM Perturbations with NRTK
255
+
256
+ Note: Default configuration options are tailored to satellite imagery (specifically xView).
257
+ Perturbing other datasets or other operational tasks may not be successful without modification
258
+ to some of these configuration options; defining broad defaults is extremely difficult, if not
259
+ impossible due to the physics-based nature of these perturbations.
260
+ """
261
+ )
262
+ with gr.Row():
263
+ with gr.Column() as input_col:
264
+ sample_img_path = "./assets/92_1920_2201_2432_2713.jpg"
265
+ input_img = gr.Image(
266
+ label="Input Image",
267
+ value=sample_img_path
268
+ )
269
+
270
+ gr.Examples(
271
+ examples=[
272
+ sample_img_path,
273
+ "./assets/99_384_0_896_512.jpg",
274
+ "./assets/125_1152_768_1664_1280.jpg",
275
+ "./assets/126_1920_1920_2432_2432.jpg"
276
+ ],
277
+ inputs=input_img
278
+ )
279
+
280
+ with gr.Row():
281
+ gen_config_btn = gr.Button("Generate New Configuration")
282
+ with gr.Column():
283
+ config_file = gr.File(label="Configuration File", file_types=[".yaml"])
284
+ load_config_btn = gr.Button("Load Configuration from File")
285
+
286
+ with gr.Group(visible=False) as input_group:
287
+ with gr.Accordion("Image Parameters", open=False):
288
+ img_gsd = gr.Number(
289
+ label="Image Ground Sample Distance (GSD) (m)",
290
+ info="The size of one pixel on the ground",
291
+ value=default_values["gsd"]
292
+ )
293
+
294
+ with gr.Accordion("Scenario Parameters") as scenario_params:
295
+ altitude_m = gr.Number(
296
+ label="Altitude (m)",
297
+ info="Sensor height above ground level in meters. The database includes the following " \
298
+ "altitude options: 2m 32.55m 75m 150m 225m 500m, 1000m to 12000m in 1000m steps, " \
299
+ "14000m to 20000m in 2000m steps, and 24500m",
300
+ value=default_values["scenario"]["altitude"]
301
+ )
302
+ ground_range_m = gr.Number(
303
+ label="Ground Range (m)",
304
+ info="Distance on the ground between the target and sensor in meters. The following " \
305
+ "ground ranges are included in the database at each altitude until the ground " \
306
+ "range exceeds the distance to the spherical earth horizon: 0m 100m 500m, 1000m to " \
307
+ "20000m in 1000m steps, 22000m to 80000m in 2000m steps, and 85000m to " \
308
+ "300000m in 5000m steps.",
309
+ value=default_values["scenario"]["groundRange"]
310
+ )
311
+
312
+ with gr.Accordion("Additional Scenario Parameters", open=False) as opt_scenario_params:
313
+ scenario_name = gr.Textbox(label="Scenario Name", value=default_values["scenario"]["name"])
314
+ ihaze = gr.Dropdown(
315
+ label="IHAZE",
316
+ info="MODTRAN code for visibility",
317
+ choices=[1, 2],
318
+ value=default_values["scenario"]["ihaze"]
319
+ )
320
+ aircraft_speed_m_Per_s = gr.Number(
321
+ label="Aircraft Speed (m/s)",
322
+ info="Ground speed of the aircraft",
323
+ value=default_values["scenario"]["aircraftSpeed"]
324
+ )
325
+ with gr.Row():
326
+ target_reflectance = gr.Number(
327
+ label="Target Reflectance",
328
+ info="Object reflectance",
329
+ value=default_values["scenario"]["targetReflectance"]
330
+ )
331
+ target_temperature_K = gr.Number(
332
+ label="Target Temperature (K)",
333
+ info="Object temperature (Kelvin)",
334
+ value=default_values["scenario"]["targetTemperature"]
335
+ )
336
+ with gr.Row():
337
+ bkgd_reflectance = gr.Number(
338
+ label="Background Reflectance",
339
+ info="Background reflectance",
340
+ value=default_values["scenario"]["backgroundReflectance"]
341
+ )
342
+ bkgd_temperature_K = gr.Number(
343
+ label="Background Temperature (K)",
344
+ info="Background temperature (Kelvin)",
345
+ value=default_values["scenario"]["backgroundTemperature"]
346
+ )
347
+ ha_windspeed_m_Per_s = gr.Number(
348
+ label="High Altitude Windspeed (m/s)",
349
+ info="Used to calculate the turbulence profile",
350
+ value=default_values["scenario"]["haWindspeed"]
351
+ )
352
+ cn2at1m = gr.Number(
353
+ label="Refractive Index Structure Parameter",
354
+ info='The refractive index structure parameter "near the ground" (e.g. ' \
355
+ 'at h = 1m). Used to calculate the turbulence profile',
356
+ value=default_values["scenario"]["cn2at1m"]
357
+ )
358
+
359
+ with gr.Accordion("Sensor Parameters") as sensor_params:
360
+ D_m = gr.Number(label="Effective Aperture Diameter (m)", value=default_values["sensor"]["D"])
361
+ f_m = gr.Number(label="Focal Length (m)", value=default_values["sensor"]["f"])
362
+ with gr.Accordion("Additional Sensor Parameters", open=False) as opt_sensor_parameters:
363
+ sensor_name = gr.Textbox(label="Sensor Name", value=default_values["sensor"]["name"])
364
+ px_m = gr.Number(label="Detector Center-to-Center Spacing (Pitch) (m)", value=default_values["sensor"]["px"])
365
+ optTransWavelengths_str = gr.Textbox(
366
+ label="Spectral Bandpass of the Camera (m)",
367
+ info="Enter a comma separated list. At minimum, a start and end wavelength should be specified",
368
+ value=", ".join(map(str, default_values["sensor"]["optTransWavelengths"]))
369
+ if default_values["sensor"]["optTransWavelengths"] else ""
370
+ )
371
+ opticsTransmission_str = gr.Textbox(
372
+ label="Full System In-Band Optical Transmission",
373
+ info="Enter a comma separated list. Loss due to any telescope obscuration should not be included",
374
+ value=", ".join(map(str, default_values["sensor"]["opticsTransmission"]))
375
+ if default_values["sensor"]["opticsTransmission"] else ""
376
+ )
377
+ eta = gr.Number(label="Relative Linear Obscuration", value=default_values["sensor"]["eta"])
378
+ int_time_s = gr.Number(
379
+ label="Integration Time (s)", info="Maximum integration time",
380
+ value=default_values["sensor"]["intTime"]
381
+ )
382
+ dark_current = gr.Number(label="Detector Dark Current (e-/s)", value=default_values["sensor"]["darkCurrent"])
383
+ read_noise = gr.Number(label="RMS Read Noise (RMS e-)", value=default_values["sensor"]["readNoise"])
384
+ max_N = gr.Number(label="Maximum ADC Level (e-)", value=default_values["sensor"]["maxN"])
385
+ bit_depth = gr.Number(
386
+ label="Bit Depth (bits)",
387
+ info="Resolution of the detector ADC",
388
+ value=default_values["sensor"]["bitdepth"]
389
+ )
390
+ max_well_fill = gr.Number(
391
+ label="Max Well Fill",
392
+ info="Desired well fill. i.e. maximum well size x desired fill fraction",
393
+ value=default_values["sensor"]["maxWellFill"]
394
+ )
395
+ with gr.Row():
396
+ sx = gr.Number(label="RMS Jitter Amplitude, X Direction (rad)", value=default_values["sensor"]["sx"])
397
+ sy = gr.Number(label="RMS Jitter Amplitude, Y Direction (rad)", value=default_values["sensor"]["sy"])
398
+ with gr.Row():
399
+ dax = gr.Number(
400
+ label="Line of Sight Angular Drift Rate, X Direction (rad/s)",
401
+ info="Drift rate during one integration time",
402
+ value=default_values["sensor"]["dax"]
403
+ )
404
+ day = gr.Number(
405
+ label="Line of Sight Angular Drift Rate, Y Direction (rad/s)",
406
+ info="Drift rate during one integration time",
407
+ value=default_values["sensor"]["day"]
408
+ )
409
+ qe_str = gr.Textbox(
410
+ label="Quantum Efficiency as a function of Wavelength (e-/photon)",
411
+ info="Enter a comma separated list",
412
+ value=", ".join(map(str, default_values["sensor"]["qe"])) if default_values["sensor"]["qe"] else ""
413
+ )
414
+ qewavelengths_str = gr.Textbox(
415
+ label="Wavelengths Corresponding to the Quantum Efficiency Array (microns)",
416
+ info="Enter a comma separated list",
417
+ value=", ".join(map(str, default_values["sensor"]["qewavelengths"]))
418
+ if default_values["sensor"]["qewavelengths"] else ""
419
+ )
420
+
421
+ submit_btn = gr.Button("Perturb Image")
422
+
423
+ with gr.Column(visible=False) as output_col:
424
+ out_img = gr.Image(label="Perturbed Image")
425
+ file_path = gr.Textbox(label="Config Filename")
426
+ save_btn = gr.Button("Save Configuration")
427
+
428
+ github_btn = gr.Button(
429
+ "Check out NRTK on GitHub!",
430
+ icon="./assets/github-badge.png",
431
+ link="https://github.com/Kitware/nrtk"
432
+ )
433
+
434
+
435
+ # Button listeners
436
+ gen_config_btn.click(
437
+ fn=gen_new_config,
438
+ inputs=None,
439
+ outputs=[
440
+ input_group, img_gsd, scenario_name, ihaze, altitude_m, ground_range_m, aircraft_speed_m_Per_s, target_reflectance,
441
+ target_temperature_K, bkgd_reflectance, bkgd_temperature_K, ha_windspeed_m_Per_s, cn2at1m, sensor_name,
442
+ D_m, f_m, px_m, optTransWavelengths_str, opticsTransmission_str, eta, int_time_s, dark_current, read_noise,
443
+ max_N, bit_depth, max_well_fill, sx, sy, dax, day, qe_str, qewavelengths_str
444
+ ]
445
+ )
446
+ load_config_btn.click(
447
+ fn=load_config_from_file,
448
+ inputs={config_file},
449
+ outputs=[
450
+ input_group, img_gsd, scenario_name, ihaze, altitude_m, ground_range_m, aircraft_speed_m_Per_s, target_reflectance,
451
+ target_temperature_K, bkgd_reflectance, bkgd_temperature_K, ha_windspeed_m_Per_s, cn2at1m, sensor_name,
452
+ D_m, f_m, px_m, optTransWavelengths_str, opticsTransmission_str, eta, int_time_s, dark_current, read_noise,
453
+ max_N, bit_depth, max_well_fill, sx, sy, dax, day, qe_str, qewavelengths_str
454
+ ]
455
+ )
456
+ submit_btn.click(
457
+ fn=submit,
458
+ inputs={
459
+ input_img, img_gsd, scenario_name, ihaze, altitude_m, ground_range_m, aircraft_speed_m_Per_s, target_reflectance,
460
+ target_temperature_K, bkgd_reflectance, bkgd_temperature_K, ha_windspeed_m_Per_s, cn2at1m, sensor_name,
461
+ D_m, f_m, px_m, optTransWavelengths_str, opticsTransmission_str, eta, int_time_s, dark_current, read_noise,
462
+ max_N, bit_depth, max_well_fill, sx, sy, dax, day, qe_str, qewavelengths_str
463
+ },
464
+ outputs=[out_img, output_col],
465
+ )
466
+ save_btn.click(
467
+ fn=save,
468
+ inputs={
469
+ input_img, img_gsd, scenario_name, ihaze, altitude_m, ground_range_m, aircraft_speed_m_Per_s, target_reflectance,
470
+ target_temperature_K, bkgd_reflectance, bkgd_temperature_K, ha_windspeed_m_Per_s, cn2at1m, sensor_name,
471
+ D_m, f_m, px_m, optTransWavelengths_str, opticsTransmission_str, eta, int_time_s, dark_current, read_noise,
472
+ max_N, bit_depth, max_well_fill, sx, sy, dax, day, qe_str, qewavelengths_str, file_path
473
+ },
474
+ outputs=None,
475
+ )
476
+
477
+
478
+ demo.launch(show_error=True, share=True)
assets/125_1152_768_1664_1280.jpg ADDED
assets/126_1920_1920_2432_2432.jpg ADDED
assets/92_1920_2201_2432_2713.jpg ADDED
assets/99_384_0_896_512.jpg ADDED
assets/github-badge.png ADDED
requirements.txt ADDED
@@ -0,0 +1 @@
 
 
1
+ nrtk