1.3.72
 
Loading...
Searching...
No Matches
RadiationModel.h
Go to the documentation of this file.
1
16#ifndef RADIATION_MODEL
17#define RADIATION_MODEL
18
19#include "CameraCalibration.h"
20#include "Context.h"
21#include "FluspectB.h"
22#include "RayTracingBackend.h"
23#include "json.hpp"
24
25#include <utility>
26
29
30 bool operator!=(const CameraProperties &rhs) const {
31 return !(rhs == *this);
32 }
33
36
39
42
45
47 float HFOV;
48
51
54
56 std::string model;
57
59 std::string lens_make;
60
62 std::string lens_model;
63
65 std::string lens_specification;
66
69 std::string exposure;
70
73
75 std::string white_balance;
76
90
94 lens_focal_length = 0.05; // 50mm default
95 lens_diameter = 0.05;
96 FOV_aspect_ratio = 0.f; // Sentinel value: 0 means auto-calculate from camera_resolution
97 HFOV = 20.f;
98 sensor_width_mm = 35.f;
99 model = "generic";
100 exposure = "auto";
101 shutter_speed = 1.f / 125.f; // 1/125 second (standard default)
102 white_balance = "auto";
103 camera_zoom = 1.0f;
104 }
105
106 bool operator==(const CameraProperties &rhs) const {
110 }
111};
112
114
138
141
144
146 float coating_efficiency = 0.96f;
147
149 float ghost_intensity = 1.0f;
150
153
156
158 int ghost_count = 5;
159
160 bool operator==(const LensFlareProperties &rhs) const {
163 }
164
165 bool operator!=(const LensFlareProperties &rhs) const {
166 return !(rhs == *this);
167 }
168};
169
172
173 // Constructor
174 RadiationCamera(std::string initlabel, const std::vector<std::string> &band_label, const helios::vec3 &initposition, const helios::vec3 &initlookat, const CameraProperties &camera_properties, uint initantialiasing_samples) :
175 label(std::move(initlabel)), band_labels(band_label), position(initposition), lookat(initlookat), antialiasing_samples(initantialiasing_samples) {
176 for (const auto &band: band_label) {
177 band_spectral_response[band] = "uniform";
178 }
179 focal_length = camera_properties.focal_plane_distance; // working distance for ray generation
180 lens_focal_length = camera_properties.lens_focal_length; // optical focal length for aperture
181 resolution = camera_properties.camera_resolution;
182 lens_diameter = camera_properties.lens_diameter;
183 HFOV_degrees = camera_properties.HFOV;
184 FOV_aspect_ratio = camera_properties.FOV_aspect_ratio;
185 sensor_width_mm = camera_properties.sensor_width_mm;
186 model = camera_properties.model;
187 lens_make = camera_properties.lens_make;
188 lens_model = camera_properties.lens_model;
189 lens_specification = camera_properties.lens_specification;
190 exposure = camera_properties.exposure;
191 shutter_speed = camera_properties.shutter_speed;
192 white_balance = camera_properties.white_balance;
193 camera_zoom = camera_properties.camera_zoom;
194 }
195
196 // Label for camera array
197 std::string label;
198 // Cartesian (x,y,z) position of camera array center
199 helios::vec3 position;
200 // Direction camera is pointed (normal vector of camera surface). This vector will automatically be normalized
201 helios::vec3 lookat;
202 // Physical dimensions of the camera lens
203 float lens_diameter;
204 // Resolution of camera sub-divisions (i.e., pixels)
205 helios::int2 resolution;
206 // camera focal length (working distance for ray generation)
207 float focal_length;
208 // lens optical focal length (for f-number and aperture calculations). This is the physical focal length, not the 35mm equivalent.
209 float lens_focal_length;
210 // camera horizontal field of view (degrees)
211 float HFOV_degrees;
212 // Ratio of camera horizontal field of view to vertical field of view
213 float FOV_aspect_ratio;
214 // Physical sensor width in mm
215 float sensor_width_mm;
216 // Camera model name
217 std::string model;
218 // Lens make/manufacturer
219 std::string lens_make;
220 // Lens model name
221 std::string lens_model;
222 // Lens specification
223 std::string lens_specification;
224 // Exposure mode: "auto", "ISOXXX" (e.g., "ISO100"), or "manual"
225 std::string exposure;
226 // Camera shutter speed in seconds
227 float shutter_speed;
228 // White balance mode: "auto" or "off"
229 std::string white_balance;
230 // Camera optical zoom multiplier
231 float camera_zoom;
232 // Camera type (rgb, spectral, or thermal)
233 std::string camera_type;
234 // Number of antialiasing samples per pixel
235 uint antialiasing_samples;
236
237 std::vector<std::string> band_labels;
238
239 std::map<std::string, std::string> band_spectral_response;
240
241 std::map<std::string, std::vector<float>> pixel_data;
242
243 std::vector<uint> pixel_label_UUID;
244 std::vector<float> pixel_depth;
245
248
250 helios::vec3 applied_white_balance_factors = helios::make_vec3(1.f, 1.f, 1.f);
251
253 bool lens_flare_enabled = false;
254
257
259 void normalizePixels();
260
262
269
275 void whiteBalance(const std::string &red_band_label, const std::string &green_band_label, const std::string &blue_band_label, float p = 5.0);
276
278
287 void whiteBalanceGrayEdge(const std::string &red_band_label, const std::string &green_band_label, const std::string &blue_band_label, int derivative_order = 1, float p = 5.0);
288
290
297 void whiteBalanceWhitePatch(const std::string &red_band_label, const std::string &green_band_label, const std::string &blue_band_label, float percentile = 0.99f);
298
299
301
311 void whiteBalanceSpectral(const std::string &red_band_label, const std::string &green_band_label, const std::string &blue_band_label, helios::Context *context);
312
314
321 void reinhardToneMapping(const std::string &red_band_label, const std::string &green_band_label, const std::string &blue_band_label);
322
324
332 void applyGain(const std::string &red_band_label, const std::string &green_band_label, const std::string &blue_band_label, float percentile = 0.95f);
333
335
340 void adjustSBC(const std::string &red_band_label, const std::string &green_band_label, const std::string &blue_band_label, float saturation, float brightness, float contrast);
341
343
348 // void applyCCM(const std::string &red_band_label, const std::string &green_band_label, const std::string &blue_band_label);
349
351
358 void gammaCompress(const std::string &red_band_label, const std::string &green_band_label, const std::string &blue_band_label);
359
367 void globalHistogramEqualization(const std::string &red_band_label, const std::string &green_band_label, const std::string &blue_band_label);
368
370
376 void autoExposure(const std::string &red_band_label, const std::string &green_band_label, const std::string &blue_band_label, float gain_multiplier);
377
379
391
393
405
407
414 void adjustBrightnessContrast(const std::string &red_band_label, const std::string &green_band_label, const std::string &blue_band_label, float brightness, float contrast);
415
417
423 void adjustSaturation(const std::string &red_band_label, const std::string &green_band_label, const std::string &blue_band_label, float saturation);
424
426
430 static float lin_to_srgb(float x) noexcept {
431 // Clamp negative values to 0, bright values > 1.0 to white (1.0)
432 if (x <= 0.0f)
433 return 0.0f;
434 if (x >= 1.0f)
435 return 1.0f; // Bright pixels clipped to white
436 return (x <= 0.0031308f) ? 12.92f * x : 1.055f * std::pow(x, 1.0f / 2.4f) - 0.055f;
437 }
438
440
444 static float srgb_to_lin(float v) noexcept {
445 return (v <= 0.04045f) ? v / 12.92f : std::pow((v + 0.055f) / 1.055f, 2.4f);
446 }
447
448private:
450
456 static float luminance(float red, float green, float blue) noexcept {
457 return 0.2126f * red + 0.7152f * green + 0.0722f * blue;
458 }
459};
460
466
469
471 std::string path;
472
475 int height;
476 int width;
478 std::string type;
480 std::string aperture;
483 std::string model;
484 std::string lens_make;
485 std::string lens_model;
486 std::string lens_specification;
487 std::string exposure;
489 std::string white_balance;
491 } camera_properties;
492
495 float latitude;
496 float longitude;
497 } location_properties;
498
501 std::string date;
502 std::string time;
506 std::string light_source;
507 } acquisition_properties;
508
514 float exposure_gain = 1.f;
515 helios::vec3 white_balance_factors = helios::make_vec3(1.f, 1.f, 1.f);
516 std::string color_space = "linear";
517 } image_processing;
518
521 std::vector<std::string> plant_species;
522 std::vector<int> plant_count;
523 std::vector<float> plant_height_m;
524 std::vector<float> plant_age_days;
525 std::vector<std::string> plant_stage;
526 std::vector<float> leaf_area_m2;
527 std::string weed_pressure;
528 } agronomic_properties;
529};
530
533
535 explicit RadiationBand(std::string a_label, size_t directRayCount_default, size_t diffuseRayCount_default, float diffuseFlux_default, uint scatteringDepth_default, float minScatterEnergy_default) : label(std::move(a_label)) {
536 directRayCount = directRayCount_default;
537 diffuseRayCount = diffuseRayCount_default;
538 diffuseFlux = diffuseFlux_default;
539 scatteringDepth = scatteringDepth_default;
540 minScatterEnergy = minScatterEnergy_default;
541 diffuseExtinction = 0.f;
542 diffuseDistNorm = 1.f;
543 emissionFlag = true;
545 }
546
548 std::string label;
549
552
555
558
561
564
567
571 helios::vec4 diffusePragueParams = helios::make_vec4(0, 0, 0, 0);
572
574 std::vector<helios::vec2> diffuse_spectrum;
575
578
581
584
587};
588
590enum RadiationSourceType { RADIATION_SOURCE_TYPE_COLLIMATED = 0, RADIATION_SOURCE_TYPE_SPHERE = 1, RADIATION_SOURCE_TYPE_SUN_SPHERE = 2, RADIATION_SOURCE_TYPE_RECTANGLE = 3, RADIATION_SOURCE_TYPE_DISK = 4 };
591
594public:
596 explicit RadiationSource(const helios::vec3 &position) : source_position(position) {
597 source_type = RADIATION_SOURCE_TYPE_COLLIMATED;
598
599 // initialize other unused variables
602 };
603
605 RadiationSource(const helios::vec3 &position, float width) : source_position(position) {
606 source_type = RADIATION_SOURCE_TYPE_SPHERE;
607
608 source_width = helios::make_vec2(width, width);
609
610 // initialize other unused variables
613 };
614
616 RadiationSource(const helios::vec3 &position, float position_scaling_factor, float width, float flux_scaling_factor) :
617 source_position(position), source_position_scaling_factor(position_scaling_factor), source_flux_scaling_factor(flux_scaling_factor) {
618 source_type = RADIATION_SOURCE_TYPE_SUN_SPHERE;
619 source_width = helios::make_vec2(width, width);
620 };
621
622
624 RadiationSource(const helios::vec3 &position, const helios::vec2 &size, const helios::vec3 &rotation) : source_position(position), source_width(size), source_rotation(rotation) {
625 source_type = RADIATION_SOURCE_TYPE_RECTANGLE;
626
627 // initialize other unused variables
630 };
631
633 RadiationSource(const helios::vec3 &position, float width, const helios::vec3 &rotation) : source_position(position), source_rotation(rotation) {
634 source_type = RADIATION_SOURCE_TYPE_DISK;
635
636 source_width = helios::make_vec2(width, width);
637
638 // initialize other unused variables
641 };
642
645
648
650 std::vector<helios::vec2> source_spectrum;
651
652 std::string source_spectrum_label = "none";
653
656
659
662
665
668
670 std::map<std::string, float> source_fluxes;
671};
672
675public:
677 explicit RadiationModel(helios::Context *context);
678
681
682 // Move constructor and assignment for test support
683 RadiationModel(RadiationModel &&) = default;
684 RadiationModel &operator=(RadiationModel &&) = default;
685
686 // Disable copy operations (unique_ptr member makes this non-copyable)
687 RadiationModel(const RadiationModel &) = delete;
688 RadiationModel &operator=(const RadiationModel &) = delete;
689
691
694 static int selfTest(int argc = 0, char **argv = nullptr);
695
708 static bool isGPUBackendAvailable();
709
720 static RadiationModel createWithBackend(helios::Context *context, std::unique_ptr<helios::RayTracingBackend> backend);
721
723
726 void disableMessages();
727
729 void enableMessages();
730
732 std::string getBackendName() const;
733
735
738 void optionalOutputPrimitiveData(const char *label);
739
741
746 void setDirectRayCount(const std::string &label, size_t N);
747
749
754 void setDiffuseRayCount(const std::string &label, size_t N);
755
757
762 void setDiffuseRadiationFlux(const std::string &label, float flux);
763
765
772 void setDiffuseRadiationExtinctionCoeff(const std::string &label, float K, const helios::vec3 &peak_dir);
773
775
782 void setDiffuseRadiationExtinctionCoeff(const std::string &label, float K, const helios::SphericalCoord &peak_dir);
783
785
791 void setDiffuseSpectrumIntegral(float spectrum_integral);
792
794
802 void setDiffuseSpectrumIntegral(float spectrum_integral, float wavelength_min, float wavelength_max);
803
805
810 void setDiffuseSpectrumIntegral(const std::string &band_label, float spectrum_integral);
811
813
820 void setDiffuseSpectrumIntegral(const std::string &band_label, float spectrum_integral, float wavelength_min, float wavelength_max);
821
823
826 void addRadiationBand(const std::string &label);
827
829
834 void addRadiationBand(const std::string &label, float wavelength_min, float wavelength_max);
835
837
841 void copyRadiationBand(const std::string &old_label, const std::string &new_label);
842
844
850 void copyRadiationBand(const std::string &old_label, const std::string &new_label, float wavelength_min, float wavelength_max);
851
853
856 bool doesBandExist(const std::string &label) const;
857
859
862 void disableEmission(const std::string &label);
863
865
868 void enableEmission(const std::string &label);
869
871
875
877
882
884
889
891
896 uint addSphereRadiationSource(const helios::vec3 &position, float radius);
897
899
903
905
910
912
916 uint addSunSphereRadiationSource(const helios::vec3 &sun_direction);
917
919
925 uint addRectangleRadiationSource(const helios::vec3 &position, const helios::vec2 &size, const helios::vec3 &rotation_rad);
926
928
934 uint addDiskRadiationSource(const helios::vec3 &position, float radius, const helios::vec3 &rotation_rad);
935
937
940 void deleteRadiationSource(uint sourceID);
941
943
948 void setSourceSpectrumIntegral(uint source_ID, float source_integral);
949
951
958 void setSourceSpectrumIntegral(uint source_ID, float source_integral, float wavelength_min, float wavelength_max);
959
961
966 void setSourceFlux(uint source_ID, const std::string &band_label, float flux);
967
969
974 void setSourceFlux(const std::vector<uint> &source_ID, const std::string &band_label, float flux);
975
977
982 float getSourceFlux(uint source_ID, const std::string &band_label) const;
983
985
989 void setSourcePosition(uint source_ID, const helios::vec3 &position);
990
992
997 void setSourcePosition(uint source_ID, const helios::SphericalCoord &position);
998
1000
1004 helios::vec3 getSourcePosition(uint source_ID) const;
1005
1007
1011 void setSourceSpectrum(uint source_ID, const std::vector<helios::vec2> &spectrum);
1012
1014
1018 void setSourceSpectrum(const std::vector<uint> &source_ID, const std::vector<helios::vec2> &spectrum);
1019
1021
1025 void setSourceSpectrum(uint source_ID, const std::string &spectrum_label);
1026
1028
1032 void setSourceSpectrum(const std::vector<uint> &source_ID, const std::string &spectrum_label);
1033
1035
1039 void setDiffuseSpectrum(const std::string &spectrum_label);
1040
1042
1046 float getDiffuseFlux(const std::string &band_label) const;
1047
1050
1053
1056
1059
1061
1067 float integrateSpectrum(const std::vector<helios::vec2> &object_spectrum, float wavelength_min, float wavelength_max) const;
1068
1070
1074 float integrateSpectrum(const std::vector<helios::vec2> &object_spectrum) const;
1075
1077
1084 float integrateSpectrum(uint source_ID, const std::vector<helios::vec2> &object_spectrum, float wavelength_min, float wavelength_max) const;
1085
1087
1093 float integrateSpectrum(uint source_ID, const std::vector<helios::vec2> &object_spectrum, const std::vector<helios::vec2> &camera_spectrum) const;
1094
1096
1101 float integrateSpectrum(const std::vector<helios::vec2> &object_spectrum, const std::vector<helios::vec2> &camera_spectrum) const;
1102
1104
1110 float integrateSourceSpectrum(uint source_ID, float wavelength_min, float wavelength_max) const;
1111
1113
1118 void scaleSpectrum(const std::string &existing_global_data_label, const std::string &new_global_data_label, float scale_factor) const;
1119
1121
1125 void scaleSpectrum(const std::string &global_data_label, float scale_factor) const;
1126
1128
1134 void scaleSpectrumRandomly(const std::string &existing_global_data_label, const std::string &new_global_data_label, float minimum_scale_factor, float maximum_scale_factor) const;
1135
1137
1143 void blendSpectra(const std::string &new_spectrum_label, const std::vector<std::string> &spectrum_labels, const std::vector<float> &weights) const;
1144
1146
1151 void blendSpectraRandomly(const std::string &new_spectrum_label, const std::vector<std::string> &spectrum_labels) const;
1152
1154
1165 void interpolateSpectrumFromPrimitiveData(const std::vector<uint> &primitive_UUIDs, const std::vector<std::string> &spectra, const std::vector<float> &values, const std::string &primitive_data_query_label,
1166 const std::string &primitive_data_radprop_label);
1167
1169
1181 void interpolateSpectrumFromObjectData(const std::vector<uint> &object_IDs, const std::vector<std::string> &spectra, const std::vector<float> &values, const std::string &object_data_query_label, const std::string &primitive_data_radprop_label);
1182
1184
1188 void setScatteringDepth(const std::string &label, uint depth);
1189
1191
1195 void setMinScatterEnergy(const std::string &label, uint energy);
1196
1198
1202 void enforcePeriodicBoundary(const std::string &boundary);
1203
1205
1213 void addRadiationCamera(const std::string &camera_label, const std::vector<std::string> &band_label, const helios::vec3 &position, const helios::vec3 &lookat, const CameraProperties &camera_properties, uint antialiasing_samples);
1214
1216
1224 void addRadiationCamera(const std::string &camera_label, const std::vector<std::string> &band_label, const helios::vec3 &position, const helios::SphericalCoord &viewing_direction, const CameraProperties &camera_properties,
1225 uint antialiasing_samples);
1226
1228
1273 void addSIFCamera(const std::string &camera_label, const std::vector<std::string> &emission_band_labels, const helios::vec3 &position, const helios::vec3 &lookat, const SIFCameraProperties &camera_properties,
1274 uint antialiasing_samples);
1275
1277
1286 void addSIFCamera(const std::string &camera_label, const std::vector<std::string> &emission_band_labels, const helios::vec3 &position, const helios::SphericalCoord &viewing_direction,
1287 const SIFCameraProperties &camera_properties, uint antialiasing_samples);
1288
1290
1294 [[nodiscard]] bool isSIFCamera(const std::string &camera_label) const;
1295
1296
1298
1304 void setCameraSpectralResponse(const std::string &camera_label, const std::string &band_label, const std::string &global_data);
1305
1307
1315 void setCameraSpectralResponseFromLibrary(const std::string &camera_label, const std::string &camera_library_name);
1316
1318
1336 void addRadiationCameraFromLibrary(const std::string &camera_label, const std::string &library_camera_label, const helios::vec3 &position, const helios::vec3 &lookat, uint antialiasing_samples);
1337
1339
1358 void addRadiationCameraFromLibrary(const std::string &camera_label, const std::string &library_camera_label, const helios::vec3 &position, const helios::vec3 &lookat, uint antialiasing_samples, const std::vector<std::string> &band_labels);
1359
1361
1365 void setCameraPosition(const std::string &camera_label, const helios::vec3 &position);
1366
1368
1372 helios::vec3 getCameraPosition(const std::string &camera_label) const;
1373
1375
1379 void setCameraLookat(const std::string &camera_label, const helios::vec3 &lookat);
1380
1382
1386 helios::vec3 getCameraLookat(const std::string &camera_label) const;
1387
1389
1393 void setCameraOrientation(const std::string &camera_label, const helios::vec3 &direction);
1394
1396
1400 void setCameraOrientation(const std::string &camera_label, const helios::SphericalCoord &direction);
1401
1403
1407 helios::SphericalCoord getCameraOrientation(const std::string &camera_label) const;
1408
1410
1421 CameraProperties getCameraParameters(const std::string &camera_label) const;
1422
1424
1437 void updateCameraParameters(const std::string &camera_label, const CameraProperties &camera_properties);
1438
1440
1443 std::vector<std::string> getAllCameraLabels();
1444
1446
1451 void enableCameraMetadata(const std::string &camera_label);
1452
1454
1459 void enableCameraMetadata(const std::vector<std::string> &camera_labels);
1460
1462
1467 CameraMetadata getCameraMetadata(const std::string &camera_label) const;
1468
1470
1475 void setCameraMetadata(const std::string &camera_label, const CameraMetadata &metadata);
1476
1478
1484 void enableCameraLensFlare(const std::string &camera_label);
1485
1487
1490 void disableCameraLensFlare(const std::string &camera_label);
1491
1493
1497 [[nodiscard]] bool isCameraLensFlareEnabled(const std::string &camera_label) const;
1498
1500
1505 void setCameraLensFlareProperties(const std::string &camera_label, const LensFlareProperties &properties);
1506
1508
1512 [[nodiscard]] LensFlareProperties getCameraLensFlareProperties(const std::string &camera_label) const;
1513
1515
1519 void updateGeometry();
1520
1522
1527 void updateGeometry(const std::vector<uint> &UUIDs);
1528
1530
1535 void runBand(const std::string &label);
1536
1538
1543 void runBand(const std::vector<std::string> &labels);
1544
1546 std::vector<float> getTotalAbsorbedFlux();
1547
1549 float getSkyEnergy();
1550
1552
1557 float calculateGtheta(helios::Context *context, helios::vec3 view_direction);
1558
1559 void setCameraCalibration(CameraCalibration *CameraCalibration);
1560
1562
1570 void updateCameraResponse(const std::string &orginalcameralabel, const std::vector<std::string> &sourcelabels_raw, const std::vector<std::string> &cameraresponselabels, helios::vec2 &wavelengthrange,
1571 const std::vector<std::vector<float>> &truevalues, const std::string &calibratedmark);
1572
1574
1583 float getCameraResponseScale(const std::string &orginalcameralabel, const std::vector<std::string> &cameraresponselabels, const std::vector<std::string> &bandlabels, const std::vector<std::string> &sourcelabels, helios::vec2 &wavelengthrange,
1584 const std::vector<std::vector<float>> &truevalues);
1585
1587
1597 void runRadiationImaging(const std::string &cameralabel, const std::vector<std::string> &sourcelabels, const std::vector<std::string> &bandlabels, const std::vector<std::string> &cameraresponselabels, helios::vec2 wavelengthrange,
1598 float fluxscale = 1, float diffusefactor = 0.0005, uint scatteringdepth = 4);
1599
1601
1611 void runRadiationImaging(const std::vector<std::string> &cameralabels, const std::vector<std::string> &sourcelabels, const std::vector<std::string> &bandlabels, const std::vector<std::string> &cameraresponselabels, helios::vec2 wavelengthrange,
1612 float fluxscale = 1, float diffusefactor = 0.0005, uint scatteringdepth = 4);
1613
1615
1628 void applyCameraImageCorrections(const std::string &cameralabel, const std::string &red_band_label, const std::string &green_band_label, const std::string &blue_band_label, float saturation_adjustment = 1.f, float brightness_adjustment = 1.f,
1629 float contrast_adjustment = 1.f);
1630
1632 [[deprecated("Use applyCameraImageCorrections() instead")]]
1633 void applyImageProcessingPipeline(const std::string &cameralabel, const std::string &red_band_label, const std::string &green_band_label, const std::string &blue_band_label, float saturation_adjustment = 1.f, float brightness_adjustment = 1.f,
1634 float contrast_adjustment = 1.f, float gain_adjustment = 1.f);
1635
1637
1644 void applyCameraColorCorrectionMatrix(const std::string &camera_label, const std::string &red_band_label, const std::string &green_band_label, const std::string &blue_band_label, const std::string &ccm_file_path);
1645
1646
1648
1658 std::string writeCameraImage(const std::string &camera, const std::vector<std::string> &bands, const std::string &imagefile_base, const std::string &image_path = "./", int frame = -1, float flux_to_pixel_conversion = 1.f);
1659
1661
1669 std::string writeNormCameraImage(const std::string &camera, const std::vector<std::string> &bands, const std::string &imagefile_base, const std::string &image_path = "./", int frame = -1);
1670
1672
1679 void writeCameraImageData(const std::string &camera, const std::string &band, const std::string &imagefile_base, const std::string &image_path = "./", int frame = -1);
1680
1682
1689 void writeCameraImageDataEXR(const std::string &camera, const std::string &band, const std::string &imagefile_base, const std::string &image_path = "./", int frame = -1);
1690
1692
1699 void writeCameraImageDataEXR(const std::string &camera, const std::vector<std::string> &bands, const std::string &imagefile_base, const std::string &image_path = "./", int frame = -1);
1700
1702
1710 void writePrimitiveDataLabelMap(const std::string &cameralabel, const std::string &primitive_data_label, const std::string &imagefile_base, const std::string &image_path = "./", int frame = -1, float padvalue = NAN);
1711
1713
1721 void writeObjectDataLabelMap(const std::string &cameralabel, const std::string &object_data_label, const std::string &imagefile_base, const std::string &image_path = "./", int frame = -1, float padvalue = NAN);
1722
1724
1730 void writeDepthImageData(const std::string &cameralabel, const std::string &imagefile_base, const std::string &image_path = "./", int frame = -1);
1731
1733
1739 void writeDepthImageDataEXR(const std::string &cameralabel, const std::string &imagefile_base, const std::string &image_path = "./", int frame = -1);
1740
1742
1749 void writeNormDepthImage(const std::string &cameralabel, const std::string &imagefile_base, float max_depth, const std::string &image_path = "./", int frame = -1);
1750
1752
1761 [[deprecated]]
1762 void writeImageBoundingBoxes(const std::string &cameralabel, const std::string &primitive_data_label, uint object_class_ID, const std::string &imagefile_base, const std::string &image_path = "./", bool append_label_file = false, int frame = -1);
1763
1765
1774 [[deprecated]]
1775 void writeImageBoundingBoxes_ObjectData(const std::string &cameralabel, const std::string &object_data_label, uint object_class_ID, const std::string &imagefile_base, const std::string &image_path = "./", bool append_label_file = false,
1776 int frame = -1);
1777
1779
1788 void writeImageBoundingBoxes(const std::string &cameralabel, const std::string &primitive_data_label, const uint &object_class_ID, const std::string &image_file, const std::string &classes_txt_file = "classes.txt",
1789 const std::string &image_path = "./");
1790
1792
1801 void writeImageBoundingBoxes(const std::string &cameralabel, const std::vector<std::string> &primitive_data_label, const std::vector<uint> &object_class_ID, const std::string &image_file, const std::string &classes_txt_file = "classes.txt",
1802 const std::string &image_path = "./");
1803
1805
1814 void writeImageBoundingBoxes_ObjectData(const std::string &cameralabel, const std::string &object_data_label, const uint &object_class_ID, const std::string &image_file, const std::string &classes_txt_file = "classes.txt",
1815 const std::string &image_path = "./");
1816
1818
1827 void writeImageBoundingBoxes_ObjectData(const std::string &cameralabel, const std::vector<std::string> &object_data_label, const std::vector<uint> &object_class_ID, const std::string &image_file,
1828 const std::string &classes_txt_file = "classes.txt", const std::string &image_path = "./");
1829
1831
1842 void writeImageSegmentationMasks(const std::string &cameralabel, const std::string &primitive_data_label, const uint &object_class_ID, const std::string &json_filename, const std::string &image_file,
1843 const std::vector<std::string> &data_attribute_labels = {}, bool append_file = false);
1844
1846
1857 void writeImageSegmentationMasks(const std::string &cameralabel, const std::vector<std::string> &primitive_data_label, const std::vector<uint> &object_class_ID, const std::string &json_filename, const std::string &image_file,
1858 const std::vector<std::string> &data_attribute_labels = {}, bool append_file = false);
1859
1861
1872 void writeImageSegmentationMasks_ObjectData(const std::string &cameralabel, const std::string &object_data_label, const uint &object_class_ID, const std::string &json_filename, const std::string &image_file,
1873 const std::vector<std::string> &data_attribute_labels = {}, bool append_file = false);
1874
1876
1887 void writeImageSegmentationMasks_ObjectData(const std::string &cameralabel, const std::vector<std::string> &object_data_label, const std::vector<uint> &object_class_ID, const std::string &json_filename, const std::string &image_file,
1888 const std::vector<std::string> &data_attribute_labels = {}, bool append_file = false);
1889
1890private:
1891 // Helper functions for COCO JSON handling
1892 std::pair<nlohmann::json, int> initializeCOCOJsonWithImageId(const std::string &filename, bool append_file, const std::string &cameralabel, const helios::int2 &camera_resolution, const std::string &image_file);
1893 nlohmann::json initializeCOCOJson(const std::string &filename, bool append_file, const std::string &cameralabel, const helios::int2 &camera_resolution, const std::string &image_file);
1894 void addCategoryToCOCO(nlohmann::json &coco_json, const std::vector<uint> &object_class_ID, const std::vector<std::string> &category_name);
1895 void writeCOCOJson(const nlohmann::json &coco_json, const std::string &filename);
1896
1897 // Helper functions for mask generation and boundary tracing
1898 std::map<int, std::vector<std::vector<bool>>> generateLabelMasks(const std::string &cameralabel, const std::string &data_label, bool use_object_data);
1899 std::pair<int, int> findStartingBoundaryPixel(const std::vector<std::vector<bool>> &mask, const helios::int2 &camera_resolution);
1900 std::vector<std::pair<int, int>> traceBoundaryMoore(const std::vector<std::vector<bool>> &mask, int start_x, int start_y, const helios::int2 &camera_resolution);
1901 std::vector<std::pair<int, int>> traceBoundarySimple(const std::vector<std::vector<bool>> &mask, int start_x, int start_y, const helios::int2 &camera_resolution);
1902 std::vector<std::map<std::string, std::vector<float>>> generateAnnotationsFromMasks(const std::map<int, std::vector<std::vector<bool>>> &label_masks, uint object_class_ID, const helios::int2 &camera_resolution, int image_id);
1903
1904 // Helper functions for camera metadata export
1905 std::string detectLightingType() const;
1906 float calculateCameraTiltAngle(const helios::vec3 &position, const helios::vec3 &lookat) const;
1907 void computeAgronomicProperties(const std::string &camera_label, CameraMetadata::AgronomicProperties &props) const;
1908 void populateCameraMetadata(const std::string &camera_label, CameraMetadata &metadata) const;
1909 std::string writeCameraMetadataFile(const std::string &camera_label, const std::string &output_path = "./") const;
1910
1911public:
1913
1918 void setPadValue(const std::string &cameralabel, const std::vector<std::string> &bandlabels, const std::vector<float> &padvalues);
1919
1921
1930 void calibrateCamera(const std::string &orginalcameralabel, const std::vector<std::string> &sourcelabels, const std::vector<std::string> &cameraresponselabels, const std::vector<std::string> &bandlabels, const float scalefactor,
1931 const std::vector<std::vector<float>> &truevalues, const std::string &calibratedmark);
1932
1934
1940 void calibrateCamera(const std::string &originalcameralabel, const float scalefactor, const std::vector<std::vector<float>> &truevalues, const std::string &calibratedmark);
1941
1948
1950
1961 std::string autoCalibrateCameraImage(const std::string &camera_label, const std::string &red_band_label, const std::string &green_band_label, const std::string &blue_band_label, const std::string &output_file_path,
1962 bool print_quality_report = false, ColorCorrectionAlgorithm algorithm = ColorCorrectionAlgorithm::MATRIX_3X3_AUTO, const std::string &ccm_export_file_path = "");
1963
1965 void exportColorCorrectionMatrixXML(const std::string &file_path, const std::string &camera_label, const std::vector<std::vector<float>> &matrix, const std::string &source_image_path, const std::string &colorboard_type, float average_delta_e);
1966
1968 std::vector<std::vector<float>> loadColorCorrectionMatrixXML(const std::string &file_path, std::string &camera_label_out);
1969
1971 std::vector<float> getCameraPixelData(const std::string &camera_label, const std::string &band_label);
1972
1974 void setCameraPixelData(const std::string &camera_label, const std::string &band_label, const std::vector<float> &pixel_data);
1975
1976private:
1978 RadiationModel(helios::Context *context_a, bool skip_backend_init);
1979
1981 size_t testBuildGeometryData();
1982
1984 helios::RayTracingBackend *getBackend();
1985
1987 helios::RayTracingGeometry &getGeometryData();
1988
1990 helios::RayTracingMaterial &getMaterialData();
1991
1993 std::vector<helios::RayTracingSource> &getSourceData();
1994
1996 void testBuildAllBackendData();
1997
1999 void queryBackendGPUMemory() const;
2000
2001protected:
2003 bool message_flag;
2004
2006 uint specular_reflection_mode = 0;
2007
2009 helios::Context *context;
2010
2011 CameraCalibration *cameracalibration;
2012 bool calibration_flag = false;
2013
2015 std::string getCurrentDateTime();
2016
2018 std::vector<uint> primitiveID;
2019
2021 std::vector<uint> context_UUIDs;
2022
2025 std::unordered_map<uint, size_t> uuid_to_position;
2026
2029 std::vector<uint> position_to_uuid;
2030
2031 // --- Radiation Band Variables --- //
2032
2033 std::map<std::string, RadiationBand> radiation_bands;
2034
2036 std::vector<helios::vec2> global_diffuse_spectrum;
2037
2039 std::string global_diffuse_spectrum_label = "none";
2040
2042 uint64_t global_diffuse_spectrum_version = 0;
2043
2044 std::map<std::string, bool> scattering_iterations_needed;
2045
2046 // --- Solar-induced fluorescence (SIF) v2 — Fluspect-B-based --- //
2047
2051 std::map<std::string, std::unordered_map<uint, float>> sif_emission_buffer;
2052
2056 std::map<std::string, std::unordered_map<uint, float>> sif_emission_buffer_bottom;
2057
2060 std::set<std::string> sif_emission_bands;
2061
2065 std::map<std::string, float> sif_band_bin_width;
2066
2068 std::set<std::string> sif_cameras;
2069
2073 struct FluspectCacheKey {
2074 std::string biochem_label;
2075 float excitation_step_nm;
2076 bool operator==(const FluspectCacheKey &o) const noexcept;
2077 };
2078 struct FluspectCacheKeyHash {
2079 std::size_t operator()(const FluspectCacheKey &k) const noexcept;
2080 };
2082 std::unordered_map<FluspectCacheKey, helios::FluspectKernel, FluspectCacheKeyHash> fluspect_cache;
2084 helios::FluspectOptipar fluspect_optipar;
2085 bool fluspect_optipar_loaded = false;
2086
2088 struct ExcitationSet {
2089 float bin_width_nm;
2090 uint scattering_depth = 0;
2091 std::vector<std::string> band_labels;
2092 std::vector<float> band_min_nm;
2093 std::vector<float> band_max_nm;
2095 std::unordered_map<uint, std::vector<float>> apar_buffer;
2097 bool populated = false;
2098 };
2100 std::map<float, ExcitationSet> excitation_sets;
2101
2103
2108 static float calculateFluorescenceYield(float J_over_Jmax, float T_leaf_K);
2109
2111 void ensureFluspectOptiparLoaded();
2112
2114
2119 const helios::FluspectKernel *getOrComputeFluspectKernel(uint UUID, float excitation_step_nm);
2120
2122
2126 ExcitationSet &ensureExcitationSet(float bin_width_nm, uint scattering_depth = 0);
2127
2131 void populateExcitationAPAR(ExcitationSet &exc);
2132
2135 void runExcitationBands();
2136
2139
2142 void computeSIFEmission(const std::string &emission_band);
2143
2144 // --- radiation source variables --- //
2145
2146 std::vector<RadiationSource> radiation_sources;
2147
2148 // --- Camera Variables --- //
2149
2151 std::map<std::string, RadiationCamera> cameras;
2152
2154 std::map<std::string, CameraMetadata> camera_metadata;
2155
2157 std::set<std::string> metadata_enabled_cameras;
2158
2160 std::map<std::string, std::vector<uint>> spectral_reflectivity_data;
2161
2163 std::map<std::string, std::vector<uint>> spectral_transmissivity_data;
2164
2166 struct SpectrumInterpolationConfig {
2167 std::unordered_set<uint> primitive_UUIDs; // Primitive UUIDs to apply this config to
2168 std::unordered_set<uint> object_IDs; // Object IDs to apply this config to
2169 std::vector<std::string> spectra_labels; // Global data labels for spectra
2170 std::vector<float> mapping_values; // Values corresponding to each spectrum
2171 std::string query_data_label; // Primitive/object data to query (e.g., "age")
2172 std::string target_data_label; // Primitive data to set (e.g., "reflectivity_spectrum")
2173 };
2174
2175 std::vector<SpectrumInterpolationConfig> spectrum_interpolation_configs;
2176
2177 std::vector<helios::vec2> generateGaussianCameraResponse(float FWHM, float mu, float centrawavelength, const helios::int2 &wavebandrange);
2178
2179 // --- Constants and Defaults --- //
2180
2182 float sigma = 5.6703744E-8;
2183
2185 float rho_default;
2186
2188 float tau_default;
2189
2191 float eps_default;
2192
2194 float kappa_default;
2195
2197 float sigmas_default;
2198
2200 float temperature_default;
2201
2203 size_t directRayCount_default;
2204
2206 size_t diffuseRayCount_default;
2207
2209 float diffuseFlux_default;
2210
2212 float minScatterEnergy_default;
2213
2215 uint scatteringDepth_default;
2216
2217 // --- Functions --- //
2218
2220 void initializeOptiX();
2221
2223
2228 void updateRadiativeProperties();
2229
2231
2247 std::vector<float> updateAtmosphericSkyModel(const std::vector<std::string> &band_labels, const RadiationCamera &camera);
2248
2250
2256 void updatePragueParametersForGeneralDiffuse(const std::vector<std::string> &band_labels);
2257
2259
2263 std::vector<helios::vec2> loadSpectralData(const std::string &global_data_label) const;
2264
2266
2267
2268 void buildLightModelGeometry(uint sourceID);
2269
2270 void buildCameraModelGeometry(const std::string &cameralabel);
2271
2272 void updateLightModelPosition(uint sourceID, const helios::vec3 &delta_position);
2273
2274 void updateCameraModelPosition(const std::string &cameralabel);
2275
2277
2286 helios::RayTracingLaunchParams buildCameraLaunchParams(const RadiationCamera &camera, uint camera_id, uint antialiasing_samples, const helios::int2 &tile_resolution, const helios::int2 &tile_offset);
2287
2289
2295 std::vector<CameraTile> computeCameraTiles(const RadiationCamera &camera, size_t maxRays);
2296
2298
2303 void buildGeometryData(const std::vector<uint> &UUIDs);
2304
2306
2311 void buildTextureData();
2312
2315 void buildUUIDMapping();
2316
2318 void buildMaterialData();
2319
2321 void buildSourceData();
2322
2324 std::map<uint, std::vector<uint>> source_model_UUIDs;
2326 std::map<std::string, std::vector<uint>> camera_model_UUIDs;
2327
2328 /* Backend abstraction layer */
2329
2331 std::unique_ptr<helios::RayTracingBackend> backend;
2332
2334 helios::RayTracingGeometry geometry_data;
2335
2337 helios::RayTracingMaterial material_data;
2338
2340 std::vector<helios::RayTracingSource> source_data;
2341
2342
2344 bool isgeometryinitialized;
2345
2347 helios::vec2 periodic_flag;
2348
2349 bool radiativepropertiesneedupdate = true;
2350
2351 std::vector<bool> isbandpropertyinitialized;
2352
2353 bool islightvisualizationenabled = false;
2354 bool iscameravisualizationenabled = false;
2355
2357 std::vector<std::string> output_prim_data;
2358
2359 std::vector<std::string> spectral_library_files;
2360
2361 // Helper methods for Prague Sky Model spectral integration from Context
2362 float integrateOverResponse(const std::vector<float> &wavelengths, const std::vector<float> &values, const std::vector<helios::vec2> &camera_response) const;
2363
2364 float weightedAverageOverResponse(const std::vector<float> &wavelengths, const std::vector<float> &param_values, const std::vector<float> &weight_values, const std::vector<helios::vec2> &camera_response) const;
2365
2366 float computeAngularNormalization(float circ_str, float circ_width, float horiz_bright) const;
2367};
2368
2369#endif