Kaynağa Gözat

Generate histograms for HDR and LDR images

Johannes Hofmann 7 yıl önce
ebeveyn
işleme
01766736b7
4 değiştirilmiş dosya ile 87 ekleme ve 15 silme
  1. 42
    12
      haader.cpp
  2. 11
    2
      haader.h
  3. 26
    1
      image.cpp
  4. 8
    0
      image.h

+ 42
- 12
haader.cpp Dosyayı Görüntüle

@@ -8,6 +8,9 @@
8 8
 
9 9
 #include "haader.h"
10 10
 
11
+#define max_number(a, b) (a) > (b) ? (a) : (b)
12
+#define min_number(a, b) (a) < (b) ? (a) : (b)
13
+
11 14
 using namespace std;
12 15
 using namespace haader;
13 16
 
@@ -262,6 +265,41 @@ Image HdrImage::expose(double exposure_time, const ResponseFunction &rf, double
262 265
     return output;
263 266
 }
264 267
 
268
+Histogram HdrImage::histogram(unsigned int number_of_bins) const {
269
+    Histogram hist;
270
+
271
+    hist.m_bins.resize(number_of_bins, 0);
272
+
273
+    if (m_image_data.size() == 0) {
274
+        return hist;
275
+    }
276
+
277
+    hist.m_min_value = m_image_data[0];
278
+    hist.m_max_value = m_image_data[0];
279
+
280
+    for (unsigned int i = 0; i < m_image_data.size(); i++) {
281
+        double val = m_image_data[i];
282
+        hist.m_min_value = min_number(hist.m_min_value, val);
283
+        hist.m_max_value = max_number(hist.m_max_value, val);
284
+    }
285
+
286
+    double scale = (double)number_of_bins / (hist.m_max_value - hist.m_min_value);
287
+
288
+    for (unsigned int i = 0; i < m_image_data.size(); i++) {
289
+        double val = m_image_data[i];
290
+        int bin = (val - hist.m_min_value) * scale;
291
+        bin = bin < 0 ? 0 : (bin >= (int)number_of_bins ? (number_of_bins - 1) : bin);
292
+        hist.m_bins[bin]++;
293
+    }
294
+
295
+    hist.m_max_freq = 0;
296
+    for (unsigned int i = 0; i < number_of_bins; i++) {
297
+        hist.m_max_freq = max_number(hist.m_max_freq, hist.m_bins[i]);
298
+    }
299
+
300
+    return hist;
301
+}
302
+
265 303
 
266 304
 HdrImageStack::HdrImageStack() {
267 305
 }
@@ -283,6 +321,7 @@ bool HdrImageStack::read_from_files(char * const* file_paths, int number_of_path
283 321
                      << file_paths[i]
284 322
                      << "\")"
285 323
                      << endl;
324
+                m_images.clear();
286 325
                 return false;
287 326
             }
288 327
             if (m_images[i].get_exposure_time() == 0.0) {
@@ -290,9 +329,11 @@ bool HdrImageStack::read_from_files(char * const* file_paths, int number_of_path
290 329
                      << file_paths[i]
291 330
                      << "\")"
292 331
                      << endl;
332
+                m_images.clear();
293 333
                 return false;
294 334
             }
295 335
         } else {
336
+            m_images.clear();
296 337
             return false;
297 338
         }
298 339
     }
@@ -475,18 +516,7 @@ bool HdrImageStack::get_inverse_response_function(InverseResponseFunction &outpu
475 516
         }
476 517
     }
477 518
 
478
-    if (output.repair()) {
479
-        cout << "Inverse response function" << endl;
480
-        cout << endl;
481
-        for (unsigned int i = 0; i < 256; i++) {
482
-            cout << i << "," << output.m_lookup_table[i] << endl;
483
-        }
484
-        cout << endl;
485
-
486
-        return true;
487
-    } else {
488
-        return false;
489
-    }
519
+    return output.repair();
490 520
 }
491 521
 
492 522
 HdrImage HdrImageStack::get_hdr_image(const InverseResponseFunction &invRespFunc) {

+ 11
- 2
haader.h Dosyayı Görüntüle

@@ -27,7 +27,7 @@ namespace haader {
27 27
             // 1.0 / (m_max_value - m_min_value)
28 28
             double m_recip_range;
29 29
 
30
-            // Response function is implemented as a lookup table of with 256 values
30
+            // Response function is implemented with a lookup table
31 31
             std::vector<int> m_lookup_table;
32 32
     };
33 33
 
@@ -69,6 +69,14 @@ namespace haader {
69 69
             std::vector<double> m_lookup_table;
70 70
     };
71 71
 
72
+    class Histogram {
73
+        public:
74
+            std::vector<unsigned int> m_bins;
75
+            double m_min_value;
76
+            double m_max_value;
77
+            unsigned int m_max_freq;
78
+    };
79
+
72 80
     // High Dynamic Range Image.
73 81
     // Stores the logarithm of the scene luminance for each pixel/channel in a high resolution.
74 82
     class HdrImage {
@@ -88,6 +96,8 @@ namespace haader {
88 96
             //     under-/overexposure in parts of the image.
89 97
             Image expose(double exposure_time, const ResponseFunction &rf, double compression=1.0);
90 98
 
99
+            Histogram histogram(unsigned int number_of_bins) const;
100
+
91 101
         private:
92 102
             // Pixel values (logarithm of scene luminance). The channels are interleaved (RGBRGBRGB...).
93 103
             std::vector<double> m_image_data;
@@ -131,7 +141,6 @@ namespace haader {
131 141
             // The images
132 142
             std::vector<Image> m_images;
133 143
     };
134
-
135 144
 }
136 145
 
137 146
 #endif // HAADER_ILUCF4Z0

+ 26
- 1
image.cpp Dosyayı Görüntüle

@@ -11,6 +11,9 @@
11 11
 #include "image.h"
12 12
 #include "exif.h"
13 13
 
14
+#define max_number(a, b) (a) > (b) ? (a) : (b)
15
+#define min_number(a, b) (a) < (b) ? (a) : (b)
16
+
14 17
 using namespace std;
15 18
 using namespace haader;
16 19
 
@@ -62,7 +65,7 @@ bool Image::read_from_file(const char *file_path) {
62 65
         cerr << "Can not read \"" << file_path << "\" as an image." << endl;
63 66
         return false;
64 67
     }
65
-    
68
+
66 69
     stbi_image_free(data);
67 70
 }
68 71
 
@@ -104,6 +107,28 @@ bool Image::save_as_ppm_file(const char *file_path, bool ascii) const {
104 107
     }
105 108
 }
106 109
 
110
+LdrHistogram Image::histogram() const {
111
+    LdrHistogram hist;
112
+
113
+    hist.m_bins.resize(256, 0);
114
+
115
+    if (m_image_data.size() == 0) {
116
+        return hist;
117
+    }
118
+
119
+    for (unsigned int i = 0; i < m_image_data.size(); i++) {
120
+        hist.m_bins[m_image_data[i]]++;
121
+    }
122
+
123
+    hist.m_max_freq = 0;
124
+    for (unsigned int i = 0; i < 256; i++) {
125
+        hist.m_max_freq = max_number(hist.m_max_freq, hist.m_bins[i]);
126
+    }
127
+
128
+    return hist;
129
+}
130
+
131
+
107 132
 unsigned int Image::get_width() const {
108 133
     return m_width;
109 134
 }

+ 8
- 0
image.h Dosyayı Görüntüle

@@ -6,6 +6,12 @@
6 6
 
7 7
 namespace haader {
8 8
 
9
+    class LdrHistogram {
10
+        public:
11
+            std::vector<unsigned int> m_bins;
12
+            unsigned int m_max_freq;
13
+    };
14
+
9 15
     // A low dynamic range image/photograph with an associated exposure time.
10 16
     class Image {
11 17
         friend class HdrImageStack;
@@ -19,6 +25,8 @@ namespace haader {
19 25
             bool read_from_file(const char *file_path);
20 26
             bool save_as_ppm_file(const char *file_path, bool ascii=false) const;
21 27
 
28
+            LdrHistogram histogram() const;
29
+
22 30
             unsigned int get_width() const;
23 31
             unsigned int get_height() const;
24 32
             unsigned int get_components() const;