A tool to construct HDR-images from a series of exposures.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. #ifndef HAADER_ILUCF4Z0
  2. #define HAADER_ILUCF4Z0
  3. #include <vector>
  4. #include <iostream>
  5. #include "image.h"
  6. namespace haader {
  7. class ResponseFunction {
  8. friend class InverseResponseFunction;
  9. public:
  10. // Returns a pixel value (0-255) given the logarithm of a luminance value.
  11. int lookup(double value) const;
  12. // Write the lookup table in CSV-format to the given stream
  13. void to_csv_stream(std::ostream &stream) const;
  14. private:
  15. // minimum log of luminance value
  16. double m_min_value;
  17. // maximum log of luminance value
  18. double m_max_value;
  19. // Precomputed value:
  20. // 1.0 / (m_max_value - m_min_value)
  21. double m_recip_range;
  22. // Response function is implemented as a lookup table of with 256 values
  23. std::vector<int> m_lookup_table;
  24. };
  25. class InverseResponseFunction {
  26. friend class HdrImageStack;
  27. public:
  28. // Return logarithm of luminance given a pixel value (0-255)
  29. double lookup(int index) const;
  30. // The inverse of the lookup function:
  31. // y == lookup(x) -> x == inverse_lookup(y)
  32. // O(n) complexity, proportional to size of lookup table.
  33. int inverse_lookup(double value) const;
  34. // Construct a ResponseFunction object that allows efficient O(1) inverse_lookup.
  35. // bins: Size of the lookup table for the response function
  36. ResponseFunction to_response_function(int bins=1024);
  37. // Write the lookup table in CSV-format to the given stream
  38. void to_csv_stream(std::ostream &stream) const;
  39. private:
  40. // Returns true if a monotonically increasing lookup table without missing values
  41. // can be constructed.
  42. bool repair();
  43. // Remove missing values by linear interpolation of neighboring values
  44. void fill_zeros();
  45. // Apply binomial low pass filter
  46. void low_pass_filter();
  47. // Returns true if values are monotonically increasing
  48. bool is_monotonic();
  49. // Inverse response function is implemented as a lookup table with 256 values
  50. std::vector<double> m_lookup_table;
  51. };
  52. // High Dynamic Range Image.
  53. // Stores the logarithm of the scene luminance for each pixel/channel in a high resolution.
  54. class HdrImage {
  55. friend class HdrImageStack;
  56. public:
  57. HdrImage();
  58. // Construct low dynamic range image with the logarithm of the scene luminance.
  59. Image get_log_image();
  60. // Construct low dynamic range image by a simulated exposure with a given response function.
  61. // exposure_time: Exposure time in seconds
  62. // compression:
  63. // A value > 1.0 will compress the luminace values and give more contrast.
  64. // A value < 1.0 will reduce the contrast but lower the risk of
  65. // under-/overexposure in parts of the image.
  66. Image expose(double exposure_time, const ResponseFunction &rf, double compression=1.0);
  67. private:
  68. // Pixel values (logarithm of scene luminance). The channels are interleaved (RGBRGBRGB...).
  69. std::vector<double> m_image_data;
  70. // Width in pixels
  71. unsigned int m_width;
  72. // Height in pixels
  73. unsigned int m_height;
  74. // Number of channels (usually 3 for RGB images)
  75. unsigned int m_components;
  76. };
  77. // A stack of images/photographs of the same scene, with the same resolution but different exposure times.
  78. class HdrImageStack {
  79. public:
  80. HdrImageStack();
  81. // Read images from the given array of file paths
  82. bool read_from_files(char * const* file_paths, int number_of_paths);
  83. // Add an image from the given file path
  84. bool add_from_file_path(const char* file_path);
  85. bool get_average_image(Image &output);
  86. bool get_average_image_slow(Image &output);
  87. // Approximate the inverse response function from samples of random pixel locations.
  88. // num_samples: Number of samples
  89. // Returns true if a well-formed inverse response function could be found.
  90. bool get_inverse_response_function(InverseResponseFunction &output, unsigned int num_samples);
  91. // Return a HDR-image given an inverse response function
  92. HdrImage get_hdr_image(const InverseResponseFunction &invRespFunc);
  93. private:
  94. // Sort the images by exposure time
  95. void sort_by_exposure();
  96. // The images
  97. std::vector<Image> m_images;
  98. };
  99. }
  100. #endif // HAADER_ILUCF4Z0