00001
00063 #ifndef COB_3D_MAPPING_TOOLS_GUI_TOOLS_H_
00064 #define COB_3D_MAPPING_TOOLS_GUI_TOOLS_H_
00065
00066 #include <highgui.h>
00067
00068 #include <pcl/point_types.h>
00069 #include <pcl/point_cloud.h>
00070 #include <boost/function.hpp>
00071
00072 #include "cob_3d_mapping_tools/gui/types.h"
00073
00074 namespace Gui
00075 {
00076 namespace Tools
00077 {
00078 template<typename T>
00079 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) ); }
00080 template<typename T>
00081 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) ); }
00082
00083 class DominantColor
00084 {
00085 private:
00086 enum { HIST_SIZE = 180 };
00087
00088 public:
00089 DominantColor() : sum_colors_(0), sum_sat_(0), sum_val_(0), hue_histogram_(HIST_SIZE,0), sat_values_(HIST_SIZE,0)
00090 { }
00091
00092 ~DominantColor() { }
00093
00094 void addColor(uint8_t r, uint8_t g, uint8_t b)
00095 {
00096 int h,s,v;
00097 rgb2hsv(r,g,b,h,s,v);
00098 int pos = incrBin(h);
00099 sat_values_[pos] += s;
00100 sum_sat_ += s;
00101 sum_val_ += v;
00102 ++sum_colors_;
00103 }
00104
00105 inline void getColor(uint8_t& r, uint8_t& g, uint8_t& b) const
00106 {
00107 if(!sum_colors_) { r=0; g=0; b=0; return; }
00108 int pos = getMaxBin();
00109 hsv2rgb( round(pos*bin_size+bin_center), sat_values_[pos]/hue_histogram_[pos], sum_val_/sum_colors_, r,g,b );
00110 }
00111
00112 inline int incrBin(int h)
00113 {
00114 int bin = h*inv_bin_size;
00115 std::cout << "incBin:"<<bin<<" H:"<<(int)h<<"inv_bin"<<inv_bin_size<<std::endl;
00116 hue_histogram_[(size_t)bin] += 1;
00117 return bin;
00118 }
00119
00120 inline int getMaxBin() const
00121 {
00122 int max_bin=0, max_size=0;
00123 for(int i=0;i<HIST_SIZE;++i)
00124 {
00125 if (hue_histogram_[i] >= max_size)
00126 {
00127 max_size = hue_histogram_[i];
00128 max_bin = i;
00129 }
00130 }
00131 std::cout<<"max_(bin/size): "<<max_bin<<"/"<<max_size<<std::endl;
00132 return max_bin;
00133 }
00134
00135 inline void rgb2hsv(uint8_t r, uint8_t g, uint8_t b, int& h, int& s, int& v) const
00136 {
00137 int rgb_min = min3(r,g,b);
00138 int rgb_max = max3(r,g,b);
00139 int delta = rgb_max - rgb_min;
00140 v = rgb_max;
00141 if (v == 0) { s = h = 0; return; }
00142 s = round(float(delta) / float(v) * 100.0f);
00143 v /= 2.55f;
00144 float h_tmp;
00145 if (s == 0) { h = 0; return; }
00146 if ((int)r == rgb_max) h_tmp = (float(g - b)) / (float(delta));
00147 else if ((int)g == rgb_max) h_tmp = 2.0f + (float(b - r)) / (float(delta));
00148 else h_tmp = 4.0f + (float(r - g)) / (float(delta));
00149
00150 h = h_tmp * 60.0f;
00151 if(h<0) h+=360;
00152 }
00153
00154 inline void hsv2rgb(int h, int s, int v, uint8_t& r, uint8_t& g, uint8_t& b) const
00155 {
00156 if (s == 0) { r = g = b = v; return; }
00157
00158 float hh = h / 60.0f;
00159 int i = floor(hh);
00160 float f = hh - i;
00161 v = round(v*2.55f);
00162 int p = v * (100 - s) * 0.01f;
00163 int q = v * (100 - s * f) * 0.01f;
00164 int t = v * (100 - s * (1.0f - f)) * 0.01f;
00165
00166 switch(i)
00167 {
00168 case 0:
00169 { r = v; g = t; b = p; break; }
00170 case 1:
00171 { r = q; g = v; b = p; break; }
00172 case 2:
00173 { r = p; g = v; b = t; break; }
00174 case 3:
00175 { r = p; g = q; b = v; break; }
00176 case 4:
00177 { r = t; g = p; b = v; break; }
00178 default:
00179 { r = v; g = p; b = q; break; }
00180 }
00181 }
00182
00183 private:
00184 int sum_colors_;
00185 int sum_sat_;
00186 int sum_val_;
00187 std::vector<int> hue_histogram_;
00188 std::vector<int> sat_values_;
00189
00190 static const float inv_bin_size = 1.0f / 360.0f * HIST_SIZE;
00191 static const float bin_size = 360.0f / HIST_SIZE;
00192 static const float bin_center = ((360.0f / HIST_SIZE) - 1.0f) * 0.5f;
00193 };
00194
00195
00196 uint32_t getGradientColor(float, float, float, cv::Vec3b&);
00197 uint32_t getGradientColor(double, cv::Vec3b&);
00198
00199
00200 template<typename PointT>
00201 class PointConverterBase
00202 {
00203 public:
00204 PointConverterBase(const typename pcl::PointCloud<PointT>::ConstPtr& cloud)
00205 : cloud_(cloud) { }
00206 virtual ~PointConverterBase() { }
00207
00208 virtual cv::Vec3b operator() (int)=0;
00209
00210 protected:
00211 typename pcl::PointCloud<PointT>::ConstPtr cloud_;
00212 };
00213
00214
00215 template<typename PointT>
00216 class PointConverterRGB : public PointConverterBase<PointT>
00217 {
00218 public:
00219 PointConverterRGB(const typename pcl::PointCloud<PointT>::ConstPtr& cloud) : PointConverterBase<PointT>(cloud) { }
00220
00221 cv::Vec3b operator() (int idx)
00222 {
00223 cv::Vec3b rgb;
00224 rgb[0] = (*this->cloud_)[idx].b;
00225 rgb[1] = (*this->cloud_)[idx].g;
00226 rgb[2] = (*this->cloud_)[idx].r;
00227 return rgb;
00228 }
00229 };
00230
00231
00232 template<typename PointT>
00233 class PointConverterDepth : public PointConverterBase<PointT>
00234 {
00235 public:
00236 PointConverterDepth(const typename pcl::PointCloud<PointT>::ConstPtr& cloud, float z_min, float z_max)
00237 : PointConverterBase<PointT>(cloud), z_min_(z_min), z_max_(z_max)
00238 { }
00239
00240 cv::Vec3b operator() (int idx)
00241 {
00242 cv::Vec3b bgr;
00243 getGradientColor((*this->cloud_)[idx].z, z_min_, z_max_, bgr);
00244 return bgr;
00245 }
00246
00247 private:
00248 float z_min_;
00249 float z_max_;
00250 };
00251
00252 template<typename PointT>
00253 void convertPointCloud2Cv(const typename pcl::PointCloud<PointT>::ConstPtr& cloud, cvImagePtr& image,
00254 boost::function<cv::Vec3b (int)>& converter);
00255
00256 template<typename PointT>
00257 void getMinMaxZ(const typename pcl::PointCloud<PointT>::ConstPtr& cloud, float& z_min, float& z_max);
00258 }
00259 }
00260
00261 #endif