00001 00060 #ifndef DOMINANT_COLOR_H_ 00061 #define DOMINANT_COLOR_H_ 00062 00063 #include <stdint.h> 00064 #include <math.h> 00065 #include <algorithm> 00066 #include <vector> 00067 00068 namespace cob_3d_mapping 00069 { 00079 template<typename T> 00080 inline T 00081 min3 (const T& a, const T& b, const T& c) 00082 { 00083 return (a < b ? std::min < T > (a, c) : std::min < T > (b, c)); 00084 } 00085 00095 template<typename T> 00096 inline T 00097 max3 (const T& a, const T& b, const T& c) 00098 { 00099 return (a > b ? std::max < T > (a, c) : std::max < T > (b, c)); 00100 } 00101 00105 class DominantColor 00106 { 00107 public: 00108 DominantColor () : 00109 sum_colors_ (0), sum_r_ (0), sum_g_ (0), sum_b_ (0), hue_histogram_ (HIST_SIZE, 0) 00110 { 00111 } 00112 00113 ~DominantColor () 00114 { 00115 } 00116 00125 void 00126 addColor (uint8_t r, uint8_t g, uint8_t b, int weight = 1); 00127 00135 void 00136 getColor (uint8_t& r, uint8_t& g, uint8_t& b) const; 00137 00145 int 00146 incrBin (int h); 00147 00153 int 00154 getMaxBin () const; 00155 00166 void 00167 rgb2hsv (uint8_t r, uint8_t g, uint8_t b, int& h, int& s, int& v) const; 00168 00179 void 00180 hsv2rgb (int h, int s, int v, uint8_t& r, uint8_t& g, uint8_t& b) const; 00181 00185 void 00186 reset (); 00187 00188 private: 00192 enum 00193 { 00194 HIST_SIZE = 180 00195 }; 00196 int sum_colors_; 00197 //int sum_sat_; 00198 //int sum_val_; 00199 int sum_r_, sum_g_, sum_b_; 00200 std::vector<int> hue_histogram_; 00201 //std::vector<int> sat_values_; 00202 00203 static const float inv_bin_size = 1.0f / 360.0f * HIST_SIZE; 00204 //static const float bin_size = 360.0f / HIST_SIZE; 00205 //static const float bin_center = ((360.0f / HIST_SIZE) - 1.0f) * 0.5f; 00206 }; 00207 } 00208 #endif /* DOMINANT_COLOR_H_ */ 00209 00210 /*template<typename T> 00211 inline T min3(const T& a, const T& b, const T& c) { return ( a < b ? std::min<T>(a,c) : std::min<T>(b,c) ); } 00212 template<typename T> 00213 inline T max3(const T& a, const T& b, const T& c) { return ( a > b ? std::max<T>(a,c) : std::max<T>(b,c) ); } 00214 00215 class DominantColor 00216 { 00217 private: 00218 enum { HIST_SIZE = 180 }; // uint8_t limits hue to 0..255 00219 00220 public: 00221 DominantColor() : sum_colors_(0), sum_sat_(0), sum_val_(0), hue_histogram_(HIST_SIZE,0), sat_values_(HIST_SIZE,0) 00222 { } 00223 00224 ~DominantColor() { } 00225 00226 void addColor(uint8_t r, uint8_t g, uint8_t b) 00227 { 00228 int h,s,v; 00229 rgb2hsv(r,g,b,h,s,v); 00230 int pos = incrBin(h); 00231 sat_values_[pos] += s; 00232 sum_sat_ += s; 00233 sum_val_ += v; 00234 ++sum_colors_; 00235 } 00236 00237 inline void getColor(uint8_t& r, uint8_t& g, uint8_t& b) const 00238 { 00239 if(!sum_colors_) { r=0; g=0; b=0; return; } 00240 int pos = getMaxBin(); 00241 hsv2rgb( round(pos*bin_size+bin_center), sat_values_[pos]/hue_histogram_[pos], sum_val_/sum_colors_, r,g,b ); 00242 } 00243 00244 inline int incrBin(int h) 00245 { int bin = h*inv_bin_size; hue_histogram_[bin] += 1; return bin; } 00246 00247 inline int getMaxBin() const 00248 { 00249 int max_bin=0, max_size=0; 00250 for(int i=0;i<HIST_SIZE;++i) 00251 { 00252 if (hue_histogram_[i] >= max_size) 00253 { 00254 max_size = hue_histogram_[i]; 00255 max_bin = i; 00256 } 00257 } 00258 //std::cout<<"max_(bin/size): "<<max_bin<<"/"<<max_size<<std::endl; 00259 return max_bin; 00260 } 00261 00262 inline void rgb2hsv(uint8_t r, uint8_t g, uint8_t b, int& h, int& s, int& v) const 00263 { 00264 int rgb_min = min3(r,g,b); 00265 int rgb_max = max3(r,g,b); 00266 int delta = rgb_max - rgb_min; 00267 v = rgb_max; 00268 if (v == 0) { s = h = 0; return; } 00269 s = round(float(delta) / float(v) * 100.0f); 00270 v /= 2.55f; 00271 float h_tmp; 00272 if (s == 0) { h = 0; return; } 00273 if ((int)r == rgb_max) h_tmp = (float(g - b)) / (float(delta)); 00274 else if ((int)g == rgb_max) h_tmp = 2.0f + (float(b - r)) / (float(delta)); 00275 else h_tmp = 4.0f + (float(r - g)) / (float(delta)); 00276 00277 h = h_tmp * 60.0f; 00278 if(h<0) h+=360; 00279 } 00280 00281 inline void hsv2rgb(int h, int s, int v, uint8_t& r, uint8_t& g, uint8_t& b) const 00282 { 00283 if (s == 0) { r = g = b = v*2.55f; return; } 00284 00285 float hh = h / 60.0f; // sector 0..5 00286 int i = floor(hh); 00287 float f = hh - i; 00288 v = round(v*2.55f); 00289 int p = v * (100 - s) * 0.01f; 00290 int q = v * (100 - s * f) * 0.01f; 00291 int t = v * (100 - s * (1.0f - f)) * 0.01f; 00292 00293 switch(i) 00294 { 00295 case 0: 00296 { r = v; g = t; b = p; break; } 00297 case 1: 00298 { r = q; g = v; b = p; break; } 00299 case 2: 00300 { r = p; g = v; b = t; break; } 00301 case 3: 00302 { r = p; g = q; b = v; break; } 00303 case 4: 00304 { r = t; g = p; b = v; break; } 00305 default:// case 5: 00306 { r = v; g = p; b = q; break; } 00307 } 00308 } 00309 00310 private: 00311 int sum_colors_; 00312 int sum_sat_; 00313 int sum_val_; 00314 std::vector<int> hue_histogram_; 00315 std::vector<int> sat_values_; 00316 00317 static const float inv_bin_size = 1.0f / 360.0f * HIST_SIZE; 00318 static const float bin_size = 360.0f / HIST_SIZE; 00319 static const float bin_center = ((360.0f / HIST_SIZE) - 1.0f) * 0.5f; 00320 };*/