1.3.77
 
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 manufacturer;
57
59 std::string model;
60
62 std::string lens_make;
63
65 std::string lens_model;
66
68 std::string lens_specification;
69
72 std::string exposure;
73
76
78 std::string white_balance;
79
93
97 lens_focal_length = 0.05; // 50mm default
98 lens_diameter = 0.05;
99 FOV_aspect_ratio = 0.f; // Sentinel value: 0 means auto-calculate from camera_resolution
100 HFOV = 20.f;
101 sensor_width_mm = 35.f;
102 model = "generic";
103 exposure = "auto";
104 shutter_speed = 1.f / 125.f; // 1/125 second (standard default)
105 white_balance = "auto";
106 camera_zoom = 1.0f;
107 }
108
109 bool operator==(const CameraProperties &rhs) const {
113 }
114};
115
117
141
144
147
149 float coating_efficiency = 0.96f;
150
152 float ghost_intensity = 1.0f;
153
156
159
161 int ghost_count = 5;
162
163 bool operator==(const LensFlareProperties &rhs) const {
166 }
167
168 bool operator!=(const LensFlareProperties &rhs) const {
169 return !(rhs == *this);
170 }
171};
172
175
176 // Constructor
177 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) :
178 label(std::move(initlabel)), band_labels(band_label), position(initposition), lookat(initlookat), antialiasing_samples(initantialiasing_samples) {
179 for (const auto &band: band_label) {
180 band_spectral_response[band] = "uniform";
181 }
182 focal_length = camera_properties.focal_plane_distance; // working distance for ray generation
183 lens_focal_length = camera_properties.lens_focal_length; // optical focal length for aperture
184 resolution = camera_properties.camera_resolution;
185 lens_diameter = camera_properties.lens_diameter;
186 HFOV_degrees = camera_properties.HFOV;
187 FOV_aspect_ratio = camera_properties.FOV_aspect_ratio;
188 sensor_width_mm = camera_properties.sensor_width_mm;
189 manufacturer = camera_properties.manufacturer;
190 model = camera_properties.model;
191 lens_make = camera_properties.lens_make;
192 lens_model = camera_properties.lens_model;
193 lens_specification = camera_properties.lens_specification;
194 exposure = camera_properties.exposure;
195 shutter_speed = camera_properties.shutter_speed;
196 white_balance = camera_properties.white_balance;
197 camera_zoom = camera_properties.camera_zoom;
198 }
199
200 // Label for camera array
201 std::string label;
202 // Cartesian (x,y,z) position of camera array center
203 helios::vec3 position;
204 // Direction camera is pointed (normal vector of camera surface). This vector will automatically be normalized
205 helios::vec3 lookat;
206 // Physical dimensions of the camera lens
207 float lens_diameter;
208 // Resolution of camera sub-divisions (i.e., pixels)
209 helios::int2 resolution;
210 // camera focal length (working distance for ray generation)
211 float focal_length;
212 // lens optical focal length (for f-number and aperture calculations). This is the physical focal length, not the 35mm equivalent.
213 float lens_focal_length;
214 // camera horizontal field of view (degrees)
215 float HFOV_degrees;
216 // Ratio of camera horizontal field of view to vertical field of view
217 float FOV_aspect_ratio;
218 // Physical sensor width in mm
219 float sensor_width_mm;
221 std::string manufacturer;
222 // Camera model name
223 std::string model;
224 // Lens make/manufacturer
225 std::string lens_make;
226 // Lens model name
227 std::string lens_model;
228 // Lens specification
229 std::string lens_specification;
230 // Exposure mode: "auto", "ISOXXX" (e.g., "ISO100"), or "manual"
231 std::string exposure;
232 // Camera shutter speed in seconds
233 float shutter_speed;
234 // White balance mode: "auto" or "off"
235 std::string white_balance;
236 // Camera optical zoom multiplier
237 float camera_zoom;
238 // Camera type (rgb, spectral, or thermal)
239 std::string camera_type;
240 // Number of antialiasing samples per pixel
241 uint antialiasing_samples;
242
243 std::vector<std::string> band_labels;
244
245 std::map<std::string, std::string> band_spectral_response;
246
247 std::map<std::string, std::vector<float>> pixel_data;
248
249 std::vector<uint> pixel_label_UUID;
250 std::vector<float> pixel_depth;
251
254
256 helios::vec3 applied_white_balance_factors = helios::make_vec3(1.f, 1.f, 1.f);
257
259 bool lens_flare_enabled = false;
260
263
265 void normalizePixels();
266
268
275
281 void whiteBalance(const std::string &red_band_label, const std::string &green_band_label, const std::string &blue_band_label, float p = 5.0);
282
284
293 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);
294
296
303 void whiteBalanceWhitePatch(const std::string &red_band_label, const std::string &green_band_label, const std::string &blue_band_label, float percentile = 0.99f);
304
305
307
317 void whiteBalanceSpectral(const std::string &red_band_label, const std::string &green_band_label, const std::string &blue_band_label, helios::Context *context);
318
320
327 void reinhardToneMapping(const std::string &red_band_label, const std::string &green_band_label, const std::string &blue_band_label);
328
330
338 void applyGain(const std::string &red_band_label, const std::string &green_band_label, const std::string &blue_band_label, float percentile = 0.95f);
339
341
346 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);
347
349
354 // void applyCCM(const std::string &red_band_label, const std::string &green_band_label, const std::string &blue_band_label);
355
357
364 void gammaCompress(const std::string &red_band_label, const std::string &green_band_label, const std::string &blue_band_label);
365
373 void globalHistogramEqualization(const std::string &red_band_label, const std::string &green_band_label, const std::string &blue_band_label);
374
376
382 void autoExposure(const std::string &red_band_label, const std::string &green_band_label, const std::string &blue_band_label, float gain_multiplier);
383
385
397
399
411
413
420 void adjustBrightnessContrast(const std::string &red_band_label, const std::string &green_band_label, const std::string &blue_band_label, float brightness, float contrast);
421
423
429 void adjustSaturation(const std::string &red_band_label, const std::string &green_band_label, const std::string &blue_band_label, float saturation);
430
432
436 static float lin_to_srgb(float x) noexcept {
437 // Clamp negative values to 0, bright values > 1.0 to white (1.0)
438 if (x <= 0.0f)
439 return 0.0f;
440 if (x >= 1.0f)
441 return 1.0f; // Bright pixels clipped to white
442 return (x <= 0.0031308f) ? 12.92f * x : 1.055f * std::pow(x, 1.0f / 2.4f) - 0.055f;
443 }
444
446
450 static float srgb_to_lin(float v) noexcept {
451 return (v <= 0.04045f) ? v / 12.92f : std::pow((v + 0.055f) / 1.055f, 2.4f);
452 }
453
454private:
456
462 static float luminance(float red, float green, float blue) noexcept {
463 return 0.2126f * red + 0.7152f * green + 0.0722f * blue;
464 }
465};
466
472
475
477 std::string path;
478
481 int height;
482 int width;
484 std::string type;
486 std::string aperture;
489 std::string model;
490 std::string lens_make;
491 std::string lens_model;
492 std::string lens_specification;
493 std::string exposure;
495 std::string white_balance;
497 } camera_properties;
498
501 float latitude;
502 float longitude;
503 } location_properties;
504
507 std::string date;
508 std::string time;
512 std::string light_source;
513 } acquisition_properties;
514
520 float exposure_gain = 1.f;
521 helios::vec3 white_balance_factors = helios::make_vec3(1.f, 1.f, 1.f);
522 std::string color_space = "linear";
523 } image_processing;
524
527 std::vector<std::string> plant_species;
528 std::vector<int> plant_count;
529 std::vector<float> plant_height_m;
530 std::vector<float> plant_age_days;
531 std::vector<std::string> plant_stage;
532 std::vector<float> leaf_area_m2;
533 std::string weed_pressure;
534 } agronomic_properties;
535};
536
539
541 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)) {
542 directRayCount = directRayCount_default;
543 diffuseRayCount = diffuseRayCount_default;
544 diffuseFlux = diffuseFlux_default;
545 scatteringDepth = scatteringDepth_default;
546 minScatterEnergy = minScatterEnergy_default;
547 diffuseExtinction = 0.f;
548 diffuseDistNorm = 1.f;
549 emissionFlag = true;
551 }
552
554 std::string label;
555
558
561
564
567
570
573
577 helios::vec4 diffusePragueParams = helios::make_vec4(0, 0, 0, 0);
578
580 std::vector<helios::vec2> diffuse_spectrum;
581
584
587
590
593};
594
596enum 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 };
597
600public:
602 explicit RadiationSource(const helios::vec3 &position) : source_position(position) {
603 source_type = RADIATION_SOURCE_TYPE_COLLIMATED;
604
605 // initialize other unused variables
608 };
609
611 RadiationSource(const helios::vec3 &position, float width) : source_position(position) {
612 source_type = RADIATION_SOURCE_TYPE_SPHERE;
613
614 source_width = helios::make_vec2(width, width);
615
616 // initialize other unused variables
619 };
620
622 RadiationSource(const helios::vec3 &position, float position_scaling_factor, float width, float flux_scaling_factor) :
623 source_position(position), source_position_scaling_factor(position_scaling_factor), source_flux_scaling_factor(flux_scaling_factor) {
624 source_type = RADIATION_SOURCE_TYPE_SUN_SPHERE;
625 source_width = helios::make_vec2(width, width);
626 };
627
628
630 RadiationSource(const helios::vec3 &position, const helios::vec2 &size, const helios::vec3 &rotation) : source_position(position), source_width(size), source_rotation(rotation) {
631 source_type = RADIATION_SOURCE_TYPE_RECTANGLE;
632
633 // initialize other unused variables
636 };
637
639 RadiationSource(const helios::vec3 &position, float width, const helios::vec3 &rotation) : source_position(position), source_rotation(rotation) {
640 source_type = RADIATION_SOURCE_TYPE_DISK;
641
642 source_width = helios::make_vec2(width, width);
643
644 // initialize other unused variables
647 };
648
651
654
656 std::vector<helios::vec2> source_spectrum;
657
658 std::string source_spectrum_label = "none";
659
662
665
668
671
674
676 std::map<std::string, float> source_fluxes;
677};
678
681public:
684
687
688 // Move constructor and assignment for test support
689 RadiationModel(RadiationModel &&) = default;
690 RadiationModel &operator=(RadiationModel &&) = default;
691
692 // Disable copy operations (unique_ptr member makes this non-copyable)
693 RadiationModel(const RadiationModel &) = delete;
694 RadiationModel &operator=(const RadiationModel &) = delete;
695
697
700 static int selfTest(int argc = 0, char **argv = nullptr);
701
714 static bool isGPUBackendAvailable();
715
726 static RadiationModel createWithBackend(helios::Context *context, std::unique_ptr<helios::RayTracingBackend> backend);
727
729
732 void disableMessages();
733
735 void enableMessages();
736
738 std::string getBackendName() const;
739
741
744 void optionalOutputPrimitiveData(const char *label);
745
747
752 void setDirectRayCount(const std::string &label, size_t N);
753
755
760 void setDiffuseRayCount(const std::string &label, size_t N);
761
763
768 void setDiffuseRadiationFlux(const std::string &label, float flux);
769
771
778 void setDiffuseRadiationExtinctionCoeff(const std::string &label, float K, const helios::vec3 &peak_dir);
779
781
788 void setDiffuseRadiationExtinctionCoeff(const std::string &label, float K, const helios::SphericalCoord &peak_dir);
789
791
797 void setDiffuseSpectrumIntegral(float spectrum_integral);
798
800
808 void setDiffuseSpectrumIntegral(float spectrum_integral, float wavelength_min, float wavelength_max);
809
811
816 void setDiffuseSpectrumIntegral(const std::string &band_label, float spectrum_integral);
817
819
826 void setDiffuseSpectrumIntegral(const std::string &band_label, float spectrum_integral, float wavelength_min, float wavelength_max);
827
829
832 void addRadiationBand(const std::string &label);
833
835
840 void addRadiationBand(const std::string &label, float wavelength_min, float wavelength_max);
841
843
847 void copyRadiationBand(const std::string &old_label, const std::string &new_label);
848
850
856 void copyRadiationBand(const std::string &old_label, const std::string &new_label, float wavelength_min, float wavelength_max);
857
859
862 bool doesBandExist(const std::string &label) const;
863
865
868 void disableEmission(const std::string &label);
869
871
874 void enableEmission(const std::string &label);
875
877
881
883
888
890
895
897
902 uint addSphereRadiationSource(const helios::vec3 &position, float radius);
903
905
909
911
916
918
922 uint addSunSphereRadiationSource(const helios::vec3 &sun_direction);
923
925
931 uint addRectangleRadiationSource(const helios::vec3 &position, const helios::vec2 &size, const helios::vec3 &rotation_rad);
932
934
940 uint addDiskRadiationSource(const helios::vec3 &position, float radius, const helios::vec3 &rotation_rad);
941
943
946 void deleteRadiationSource(uint sourceID);
947
949
954 void setSourceSpectrumIntegral(uint source_ID, float source_integral);
955
957
964 void setSourceSpectrumIntegral(uint source_ID, float source_integral, float wavelength_min, float wavelength_max);
965
967
972 void setSourceFlux(uint source_ID, const std::string &band_label, float flux);
973
975
980 void setSourceFlux(const std::vector<uint> &source_ID, const std::string &band_label, float flux);
981
983
988 float getSourceFlux(uint source_ID, const std::string &band_label) const;
989
991
995 void setSourcePosition(uint source_ID, const helios::vec3 &position);
996
998
1003 void setSourcePosition(uint source_ID, const helios::SphericalCoord &position);
1004
1006
1010 helios::vec3 getSourcePosition(uint source_ID) const;
1011
1013
1017 void setSourceSpectrum(uint source_ID, const std::vector<helios::vec2> &spectrum);
1018
1020
1024 void setSourceSpectrum(const std::vector<uint> &source_ID, const std::vector<helios::vec2> &spectrum);
1025
1027
1031 void setSourceSpectrum(uint source_ID, const std::string &spectrum_label);
1032
1034
1038 void setSourceSpectrum(const std::vector<uint> &source_ID, const std::string &spectrum_label);
1039
1041
1045 void setDiffuseSpectrum(const std::string &spectrum_label);
1046
1048
1052 float getDiffuseFlux(const std::string &band_label) const;
1053
1056
1059
1062
1065
1067
1073 float integrateSpectrum(const std::vector<helios::vec2> &object_spectrum, float wavelength_min, float wavelength_max) const;
1074
1076
1080 float integrateSpectrum(const std::vector<helios::vec2> &object_spectrum) const;
1081
1083
1090 float integrateSpectrum(uint source_ID, const std::vector<helios::vec2> &object_spectrum, float wavelength_min, float wavelength_max) const;
1091
1093
1099 float integrateSpectrum(uint source_ID, const std::vector<helios::vec2> &object_spectrum, const std::vector<helios::vec2> &camera_spectrum) const;
1100
1102
1107 float integrateSpectrum(const std::vector<helios::vec2> &object_spectrum, const std::vector<helios::vec2> &camera_spectrum) const;
1108
1110
1116 float integrateSourceSpectrum(uint source_ID, float wavelength_min, float wavelength_max) const;
1117
1119
1124 void scaleSpectrum(const std::string &existing_global_data_label, const std::string &new_global_data_label, float scale_factor) const;
1125
1127
1131 void scaleSpectrum(const std::string &global_data_label, float scale_factor) const;
1132
1134
1140 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;
1141
1143
1149 void blendSpectra(const std::string &new_spectrum_label, const std::vector<std::string> &spectrum_labels, const std::vector<float> &weights) const;
1150
1152
1157 void blendSpectraRandomly(const std::string &new_spectrum_label, const std::vector<std::string> &spectrum_labels) const;
1158
1160
1171 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,
1172 const std::string &primitive_data_radprop_label);
1173
1175
1187 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);
1188
1190
1194 void setScatteringDepth(const std::string &label, uint depth);
1195
1197
1201 void setMinScatterEnergy(const std::string &label, uint energy);
1202
1204
1208 void enforcePeriodicBoundary(const std::string &boundary);
1209
1211
1219 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);
1220
1222
1230 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,
1231 uint antialiasing_samples);
1232
1234
1279 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,
1280 uint antialiasing_samples);
1281
1283
1292 void addSIFCamera(const std::string &camera_label, const std::vector<std::string> &emission_band_labels, const helios::vec3 &position, const helios::SphericalCoord &viewing_direction,
1293 const SIFCameraProperties &camera_properties, uint antialiasing_samples);
1294
1296
1300 [[nodiscard]] bool isSIFCamera(const std::string &camera_label) const;
1301
1302
1304
1310 void setCameraSpectralResponse(const std::string &camera_label, const std::string &band_label, const std::string &global_data);
1311
1313
1321 void setCameraSpectralResponseFromLibrary(const std::string &camera_label, const std::string &camera_library_name);
1322
1324
1342 void addRadiationCameraFromLibrary(const std::string &camera_label, const std::string &library_camera_label, const helios::vec3 &position, const helios::vec3 &lookat, uint antialiasing_samples);
1343
1345
1364 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);
1365
1367
1371 void setCameraPosition(const std::string &camera_label, const helios::vec3 &position);
1372
1374
1378 helios::vec3 getCameraPosition(const std::string &camera_label) const;
1379
1381
1385 void setCameraLookat(const std::string &camera_label, const helios::vec3 &lookat);
1386
1388
1392 helios::vec3 getCameraLookat(const std::string &camera_label) const;
1393
1395
1399 void setCameraOrientation(const std::string &camera_label, const helios::vec3 &direction);
1400
1402
1406 void setCameraOrientation(const std::string &camera_label, const helios::SphericalCoord &direction);
1407
1409
1413 helios::SphericalCoord getCameraOrientation(const std::string &camera_label) const;
1414
1416
1427 CameraProperties getCameraParameters(const std::string &camera_label) const;
1428
1430
1443 void updateCameraParameters(const std::string &camera_label, const CameraProperties &camera_properties);
1444
1446
1449 std::vector<std::string> getAllCameraLabels();
1450
1452
1457 void enableCameraMetadata(const std::string &camera_label);
1458
1460
1465 void enableCameraMetadata(const std::vector<std::string> &camera_labels);
1466
1468
1473 CameraMetadata getCameraMetadata(const std::string &camera_label) const;
1474
1476
1481 void setCameraMetadata(const std::string &camera_label, const CameraMetadata &metadata);
1482
1484
1490 void enableCameraLensFlare(const std::string &camera_label);
1491
1493
1496 void disableCameraLensFlare(const std::string &camera_label);
1497
1499
1503 [[nodiscard]] bool isCameraLensFlareEnabled(const std::string &camera_label) const;
1504
1506
1511 void setCameraLensFlareProperties(const std::string &camera_label, const LensFlareProperties &properties);
1512
1514
1518 [[nodiscard]] LensFlareProperties getCameraLensFlareProperties(const std::string &camera_label) const;
1519
1521
1525 void updateGeometry();
1526
1528
1533 void updateGeometry(const std::vector<uint> &UUIDs);
1534
1536
1541 void runBand(const std::string &label);
1542
1544
1549 void runBand(const std::vector<std::string> &labels);
1550
1552 std::vector<float> getTotalAbsorbedFlux();
1553
1555 float getSkyEnergy();
1556
1558
1563 float calculateGtheta(helios::Context *context, helios::vec3 view_direction);
1564
1565 void setCameraCalibration(CameraCalibration *CameraCalibration);
1566
1568
1576 void updateCameraResponse(const std::string &orginalcameralabel, const std::vector<std::string> &sourcelabels_raw, const std::vector<std::string> &cameraresponselabels, helios::vec2 &wavelengthrange,
1577 const std::vector<std::vector<float>> &truevalues, const std::string &calibratedmark);
1578
1580
1589 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,
1590 const std::vector<std::vector<float>> &truevalues);
1591
1593
1603 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,
1604 float fluxscale = 1, float diffusefactor = 0.0005, uint scatteringdepth = 4);
1605
1607
1617 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,
1618 float fluxscale = 1, float diffusefactor = 0.0005, uint scatteringdepth = 4);
1619
1621
1634 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,
1635 float contrast_adjustment = 1.f);
1636
1638 [[deprecated("Use applyCameraImageCorrections() instead")]]
1639 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,
1640 float contrast_adjustment = 1.f, float gain_adjustment = 1.f);
1641
1643
1650 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);
1651
1652
1654
1664 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);
1665
1667
1675 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);
1676
1678
1685 void writeCameraImageData(const std::string &camera, const std::string &band, const std::string &imagefile_base, const std::string &image_path = "./", int frame = -1);
1686
1688
1695 void writeCameraImageDataEXR(const std::string &camera, const std::string &band, const std::string &imagefile_base, const std::string &image_path = "./", int frame = -1);
1696
1698
1705 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);
1706
1708
1716 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);
1717
1719
1727 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);
1728
1730
1736 void writeDepthImageData(const std::string &cameralabel, const std::string &imagefile_base, const std::string &image_path = "./", int frame = -1);
1737
1739
1745 void writeDepthImageDataEXR(const std::string &cameralabel, const std::string &imagefile_base, const std::string &image_path = "./", int frame = -1);
1746
1748
1755 void writeNormDepthImage(const std::string &cameralabel, const std::string &imagefile_base, float max_depth, const std::string &image_path = "./", int frame = -1);
1756
1758
1767 [[deprecated]]
1768 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);
1769
1771
1780 [[deprecated]]
1781 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,
1782 int frame = -1);
1783
1785
1794 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",
1795 const std::string &image_path = "./");
1796
1798
1807 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",
1808 const std::string &image_path = "./");
1809
1811
1820 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",
1821 const std::string &image_path = "./");
1822
1824
1833 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,
1834 const std::string &classes_txt_file = "classes.txt", const std::string &image_path = "./");
1835
1837
1848 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,
1849 const std::vector<std::string> &data_attribute_labels = {}, bool append_file = false);
1850
1852
1863 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,
1864 const std::vector<std::string> &data_attribute_labels = {}, bool append_file = false);
1865
1867
1878 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,
1879 const std::vector<std::string> &data_attribute_labels = {}, bool append_file = false);
1880
1882
1893 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,
1894 const std::vector<std::string> &data_attribute_labels = {}, bool append_file = false);
1895
1896private:
1897 // Helper functions for COCO JSON handling
1898 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);
1899 nlohmann::json initializeCOCOJson(const std::string &filename, bool append_file, const std::string &cameralabel, const helios::int2 &camera_resolution, const std::string &image_file);
1900 void addCategoryToCOCO(nlohmann::json &coco_json, const std::vector<uint> &object_class_ID, const std::vector<std::string> &category_name);
1901 void writeCOCOJson(const nlohmann::json &coco_json, const std::string &filename);
1902
1903 // Helper functions for mask generation and boundary tracing
1904 std::map<int, std::vector<std::vector<bool>>> generateLabelMasks(const std::string &cameralabel, const std::string &data_label, bool use_object_data);
1905 std::pair<int, int> findStartingBoundaryPixel(const std::vector<std::vector<bool>> &mask, const helios::int2 &camera_resolution);
1906 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);
1907 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);
1908 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);
1909
1910 // Helper functions for camera metadata export
1911 std::string detectLightingType() const;
1912 float calculateCameraTiltAngle(const helios::vec3 &position, const helios::vec3 &lookat) const;
1913 void computeAgronomicProperties(const std::string &camera_label, CameraMetadata::AgronomicProperties &props) const;
1914 void populateCameraMetadata(const std::string &camera_label, CameraMetadata &metadata) const;
1915 std::string writeCameraMetadataFile(const std::string &camera_label, const std::string &output_path = "./") const;
1916
1918
1926 void populateImageEXIF(const std::string &camera_label, helios::ImageEXIFData &exif) const;
1927
1928public:
1930
1935 void setPadValue(const std::string &cameralabel, const std::vector<std::string> &bandlabels, const std::vector<float> &padvalues);
1936
1938
1947 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,
1948 const std::vector<std::vector<float>> &truevalues, const std::string &calibratedmark);
1949
1951
1957 void calibrateCamera(const std::string &originalcameralabel, const float scalefactor, const std::vector<std::vector<float>> &truevalues, const std::string &calibratedmark);
1958
1965
1967
1978 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,
1979 bool print_quality_report = false, ColorCorrectionAlgorithm algorithm = ColorCorrectionAlgorithm::MATRIX_3X3_AUTO, const std::string &ccm_export_file_path = "");
1980
1982 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);
1983
1985 std::vector<std::vector<float>> loadColorCorrectionMatrixXML(const std::string &file_path, std::string &camera_label_out);
1986
1988 std::vector<float> getCameraPixelData(const std::string &camera_label, const std::string &band_label);
1989
1991 void setCameraPixelData(const std::string &camera_label, const std::string &band_label, const std::vector<float> &pixel_data);
1992
1993private:
1995 RadiationModel(helios::Context *context_a, bool skip_backend_init);
1996
1998 size_t testBuildGeometryData();
1999
2001 helios::RayTracingBackend *getBackend();
2002
2004 helios::RayTracingGeometry &getGeometryData();
2005
2007 helios::RayTracingMaterial &getMaterialData();
2008
2010 std::vector<helios::RayTracingSource> &getSourceData();
2011
2013 void testBuildAllBackendData();
2014
2016 void queryBackendGPUMemory() const;
2017
2018protected:
2020 bool message_flag;
2021
2023 uint specular_reflection_mode = 0;
2024
2027
2028 CameraCalibration *cameracalibration;
2029 bool calibration_flag = false;
2030
2032 std::string getCurrentDateTime();
2033
2035 std::vector<uint> primitiveID;
2036
2038 std::vector<uint> context_UUIDs;
2039
2042 std::unordered_map<uint, size_t> uuid_to_position;
2043
2046 std::vector<uint> position_to_uuid;
2047
2048 // --- Radiation Band Variables --- //
2049
2050 std::map<std::string, RadiationBand> radiation_bands;
2051
2053 std::vector<helios::vec2> global_diffuse_spectrum;
2054
2056 std::string global_diffuse_spectrum_label = "none";
2057
2059 uint64_t global_diffuse_spectrum_version = 0;
2060
2061 std::map<std::string, bool> scattering_iterations_needed;
2062
2063 // --- Solar-induced fluorescence (SIF) v2 — Fluspect-B-based --- //
2064
2068 std::map<std::string, std::unordered_map<uint, float>> sif_emission_buffer;
2069
2073 std::map<std::string, std::unordered_map<uint, float>> sif_emission_buffer_bottom;
2074
2077 std::set<std::string> sif_emission_bands;
2078
2082 std::map<std::string, float> sif_band_bin_width;
2083
2085 std::set<std::string> sif_cameras;
2086
2090 struct FluspectCacheKey {
2091 std::string biochem_label;
2092 float excitation_step_nm;
2093 bool operator==(const FluspectCacheKey &o) const noexcept;
2094 };
2095 struct FluspectCacheKeyHash {
2096 std::size_t operator()(const FluspectCacheKey &k) const noexcept;
2097 };
2099 std::unordered_map<FluspectCacheKey, helios::FluspectKernel, FluspectCacheKeyHash> fluspect_cache;
2101 helios::FluspectOptipar fluspect_optipar;
2102 bool fluspect_optipar_loaded = false;
2103
2105 struct ExcitationSet {
2106 float bin_width_nm;
2107 uint scattering_depth = 0;
2108 std::vector<std::string> band_labels;
2109 std::vector<float> band_min_nm;
2110 std::vector<float> band_max_nm;
2112 std::unordered_map<uint, std::vector<float>> apar_buffer;
2114 bool populated = false;
2115 };
2117 std::map<float, ExcitationSet> excitation_sets;
2118
2120
2125 static float calculateFluorescenceYield(float J_over_Jmax, float T_leaf_K);
2126
2128 void ensureFluspectOptiparLoaded();
2129
2131
2136 const helios::FluspectKernel *getOrComputeFluspectKernel(uint UUID, float excitation_step_nm);
2137
2139
2143 ExcitationSet &ensureExcitationSet(float bin_width_nm, uint scattering_depth = 0);
2144
2148 void populateExcitationAPAR(ExcitationSet &exc);
2149
2152 void runExcitationBands();
2153
2156
2159 void computeSIFEmission(const std::string &emission_band);
2160
2161 // --- radiation source variables --- //
2162
2163 std::vector<RadiationSource> radiation_sources;
2164
2165 // --- Camera Variables --- //
2166
2168 std::map<std::string, RadiationCamera> cameras;
2169
2171 std::map<std::string, CameraMetadata> camera_metadata;
2172
2174 std::set<std::string> metadata_enabled_cameras;
2175
2177 std::map<std::string, std::vector<uint>> spectral_reflectivity_data;
2178
2180 std::map<std::string, std::vector<uint>> spectral_transmissivity_data;
2181
2183 struct SpectrumInterpolationConfig {
2184 std::unordered_set<uint> primitive_UUIDs; // Primitive UUIDs to apply this config to
2185 std::unordered_set<uint> object_IDs; // Object IDs to apply this config to
2186 std::vector<std::string> spectra_labels; // Global data labels for spectra
2187 std::vector<float> mapping_values; // Values corresponding to each spectrum
2188 std::string query_data_label; // Primitive/object data to query (e.g., "age")
2189 std::string target_data_label; // Primitive data to set (e.g., "reflectivity_spectrum")
2190 };
2191
2192 std::vector<SpectrumInterpolationConfig> spectrum_interpolation_configs;
2193
2194 std::vector<helios::vec2> generateGaussianCameraResponse(float FWHM, float mu, float centrawavelength, const helios::int2 &wavebandrange);
2195
2196 // --- Constants and Defaults --- //
2197
2199 float sigma = 5.6703744E-8;
2200
2202 float rho_default;
2203
2205 float tau_default;
2206
2208 float eps_default;
2209
2211 float kappa_default;
2212
2214 float sigmas_default;
2215
2217 float temperature_default;
2218
2220 size_t directRayCount_default;
2221
2223 size_t diffuseRayCount_default;
2224
2226 float diffuseFlux_default;
2227
2229 float minScatterEnergy_default;
2230
2232 uint scatteringDepth_default;
2233
2234 // --- Functions --- //
2235
2237 void initializeOptiX();
2238
2240
2245 void updateRadiativeProperties();
2246
2248
2264 std::vector<float> updateAtmosphericSkyModel(const std::vector<std::string> &band_labels, const RadiationCamera &camera);
2265
2267
2273 void updatePragueParametersForGeneralDiffuse(const std::vector<std::string> &band_labels);
2274
2276
2280 std::vector<helios::vec2> loadSpectralData(const std::string &global_data_label) const;
2281
2283
2284
2285 void buildLightModelGeometry(uint sourceID);
2286
2287 void buildCameraModelGeometry(const std::string &cameralabel);
2288
2289 void updateLightModelPosition(uint sourceID, const helios::vec3 &delta_position);
2290
2291 void updateCameraModelPosition(const std::string &cameralabel);
2292
2294
2303 helios::RayTracingLaunchParams buildCameraLaunchParams(const RadiationCamera &camera, uint camera_id, uint antialiasing_samples, const helios::int2 &tile_resolution, const helios::int2 &tile_offset);
2304
2306
2312 std::vector<CameraTile> computeCameraTiles(const RadiationCamera &camera, size_t maxRays);
2313
2315
2320 void buildGeometryData(const std::vector<uint> &UUIDs);
2321
2323
2328 void buildTextureData();
2329
2332 void buildUUIDMapping();
2333
2335 void buildMaterialData();
2336
2338 void buildSourceData();
2339
2341 std::map<uint, std::vector<uint>> source_model_UUIDs;
2343 std::map<std::string, std::vector<uint>> camera_model_UUIDs;
2344
2345 /* Backend abstraction layer */
2346
2348 std::unique_ptr<helios::RayTracingBackend> backend;
2349
2351 helios::RayTracingGeometry geometry_data;
2352
2354 helios::RayTracingMaterial material_data;
2355
2357 std::vector<helios::RayTracingSource> source_data;
2358
2359
2361 bool isgeometryinitialized;
2362
2364 helios::vec2 periodic_flag;
2365
2366 bool radiativepropertiesneedupdate = true;
2367
2368 std::vector<bool> isbandpropertyinitialized;
2369
2370 bool islightvisualizationenabled = false;
2371 bool iscameravisualizationenabled = false;
2372
2374 std::vector<std::string> output_prim_data;
2375
2376 std::vector<std::string> spectral_library_files;
2377
2378 // Helper methods for Prague Sky Model spectral integration from Context
2379 float integrateOverResponse(const std::vector<float> &wavelengths, const std::vector<float> &values, const std::vector<helios::vec2> &camera_response) const;
2380
2381 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;
2382
2383 float computeAngularNormalization(float circ_str, float circ_width, float horiz_bright) const;
2384};
2385
2386#endif