degate  0.1.2
ImageHistogram.h
Go to the documentation of this file.
00001 /* -*-c++-*-
00002 
00003  This file is part of the IC reverse engineering tool degate.
00004 
00005  Copyright 2008, 2009, 2010 by Martin Schobert
00006 
00007  Degate is free software: you can redistribute it and/or modify
00008  it under the terms of the GNU General Public License as published by
00009  the Free Software Foundation, either version 3 of the License, or
00010  any later version.
00011 
00012  Degate is distributed in the hope that it will be useful,
00013  but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  GNU General Public License for more details.
00016 
00017  You should have received a copy of the GNU General Public License
00018  along with degate. If not, see <http://www.gnu.org/licenses/>.
00019 
00020 */
00021 
00022 #ifndef __IMAGEHISTOGRAM_H__
00023 #define __IMAGEHISTOGRAM_H__
00024 
00025 #include <Image.h>
00026 #include <degate_exceptions.h>
00027 #include <TypeConstraints.h>
00028 #include <ImageManipulation.h>
00029 
00030 #include <fstream>
00031 #include <iostream>
00032 #include <boost/format.hpp>
00033 
00034 namespace degate {
00035 
00036   template<typename KeyType, typename ValueType>
00037   class ImageHistogram {
00038 
00039   private:
00040     typedef std::map<KeyType, ValueType> map_type;
00041     map_type histogram;
00042     unsigned int counts;
00043 
00044     double from, to, class_width;
00045 
00046   protected:
00047 
00048     void check_bounding_box(BoundingBox const& bb, ImageBase_shptr img) const {
00049 
00050       if(std::max(bb.get_min_x(), bb.get_max_x()) >= (int)img->get_width() ||
00051          std::max(bb.get_min_y(), bb.get_max_y()) >= (int)img->get_height() ||
00052          std::min(bb.get_min_x(), bb.get_max_x()) < 0 ||
00053          std::min(bb.get_min_y(), bb.get_max_y()) < 0) {
00054         boost::format f("Error in add_area(). Defined region %1% is beyond image boundary.");
00055         f % bb.to_string();
00056         throw DegateRuntimeException(f.str());
00057       }
00058 
00059       if(bb.get_height() == 0 && bb.get_width() == 0)
00060         throw DegateRuntimeException("Bounding box has zero size");
00061     }
00062 
00063     KeyType to_class(ValueType v, ValueType from, ValueType to, ValueType class_width) const {
00064       //unsigned int classes = (to - from) / class_width;
00065       //unsigned int class_num = v / class_width;
00066       //KeyType cl = v * class_width;
00067 
00068       unsigned int c = 0;
00069       for(ValueType i = from; i < to; i+= class_width, c++) {
00070         if(v >= (ValueType)c*class_width && v < (ValueType)(c+1)*class_width)
00071           return (ValueType)c*class_width;
00072       }
00073 
00074     }
00075 
00076   public:
00077 
00078     ImageHistogram(double _from, double _to, double _class_width) :
00079       counts(0),
00080       from(_from),
00081       to(_to),
00082       class_width(_class_width) {}
00083 
00084     virtual ~ImageHistogram() {}
00085 
00086     virtual void add(KeyType k) {
00087       histogram[to_class(k, from, to, class_width)] += 1;
00088       counts++;
00089     }
00090 
00091     virtual ValueType get(KeyType k) const {
00092       if(counts == 0) return 0;
00093 
00094       else {
00095         typename map_type::const_iterator found = histogram.find(to_class(k, from, to, class_width));
00096         if(found == histogram.end()) return 0;
00097         else return (*found).second / (double)counts;
00098       }
00099     }
00100 
00101     virtual ValueType get_for_rgb(rgba_pixel_t) const = 0;
00102 
00103     virtual void save_histogram(std::string const& path) const {
00104 
00105       std::ofstream histogram_file;
00106       histogram_file.open(path.c_str());
00107 
00108       if(counts > 0)
00109         for(typename map_type::const_iterator iter = histogram.begin(); iter != histogram.end(); ++iter) {
00110           double frequency = (*iter).second / (double)counts;
00111           histogram_file << (*iter).first << " " << frequency << std::endl;
00112         }
00113 
00114       histogram_file.close();
00115     }
00116 
00117 
00118   };
00119 
00120 
00121 
00122   class HueImageHistogram : public ImageHistogram<double, double> {
00123 
00124   public:
00125 
00126     HueImageHistogram() : ImageHistogram<double, double>(0, 360, 1) {}
00127 
00128     template<class ImageType>
00129     void add_area(std::shared_ptr<ImageType> img, BoundingBox const& bb) {
00130 
00131       assert_is_multi_channel_image<ImageType>();
00132       check_bounding_box(bb, img);
00133 
00134       for(unsigned int y = (unsigned int)bb.get_min_y(); y <= (unsigned int)bb.get_max_y(); y++)
00135         for(unsigned int x = (unsigned int)bb.get_min_x(); x <= (unsigned int)bb.get_max_x(); x++)
00136           add(rgba_to_hue(img->get_pixel(x, y)));
00137     }
00138 
00139 
00140     virtual double get_for_rgb(rgba_pixel_t pixel) const {
00141       return get(rgba_to_hue(pixel));
00142     }
00143 
00144   };
00145 
00146 
00147 
00148   class SaturationImageHistogram : public ImageHistogram<double, double> {
00149 
00150   public:
00151 
00152     SaturationImageHistogram() : ImageHistogram<double, double>(0, 1, 0.01) {}
00153 
00154     template<class ImageType>
00155     void add_area(std::shared_ptr<ImageType> img, BoundingBox const& bb) {
00156 
00157       assert_is_multi_channel_image<ImageType>();
00158       check_bounding_box(bb, img);
00159 
00160       for(unsigned int y = (unsigned int)bb.get_min_y(); y <= (unsigned int)bb.get_max_y(); y++)
00161         for(unsigned int x = (unsigned int)bb.get_min_x(); x <= (unsigned int)bb.get_max_x(); x++)
00162           add(rgba_to_saturation(img->get_pixel(x, y)));
00163     }
00164 
00165     virtual double get_for_rgb(rgba_pixel_t pixel) const {
00166       return get(rgba_to_saturation(pixel));
00167     }
00168 
00169   };
00170 
00171   class LightnessImageHistogram : public ImageHistogram<double, double> {
00172 
00173   public:
00174 
00175     LightnessImageHistogram() : ImageHistogram<double, double>(0, 255, 1) {}
00176 
00177     template<class ImageType>
00178     void add_area(std::shared_ptr<ImageType> img, BoundingBox const& bb) {
00179 
00180       assert_is_multi_channel_image<ImageType>();
00181       check_bounding_box(bb, img);
00182 
00183       for(unsigned int y = (unsigned int)bb.get_min_y(); y <= (unsigned int)bb.get_max_y(); y++)
00184         for(unsigned int x = (unsigned int)bb.get_min_x(); x <= (unsigned int)bb.get_max_x(); x++)
00185           add(rgba_to_lightness(img->get_pixel(x, y)));
00186     }
00187 
00188     virtual double get_for_rgb(rgba_pixel_t pixel) const {
00189       return get(rgba_to_lightness(pixel));
00190     }
00191 
00192   };
00193 
00194 
00195 
00196   class RedChannelImageHistogram : public ImageHistogram<double, double> {
00197 
00198   public:
00199 
00200     RedChannelImageHistogram() : ImageHistogram<double, double>(0, 255, 1) {}
00201 
00202     template<class ImageType>
00203     void add_area(std::shared_ptr<ImageType> img, BoundingBox const& bb) {
00204 
00205       assert_is_multi_channel_image<ImageType>();
00206       check_bounding_box(bb, img);
00207 
00208       for(unsigned int y = (unsigned int)bb.get_min_y(); y <= (unsigned int)bb.get_max_y(); y++)
00209         for(unsigned int x = (unsigned int)bb.get_min_x(); x <= (unsigned int)bb.get_max_x(); x++)
00210 
00211           add(MASK_R(img->get_pixel(x, y)));
00212     }
00213 
00214 
00215     virtual double get_for_rgb(rgba_pixel_t pixel) const {
00216       return get(MASK_R(pixel));
00217     }
00218 
00219   };
00220 
00221 
00222 
00223   class GreenChannelImageHistogram : public ImageHistogram<double, double> {
00224 
00225   public:
00226 
00227     GreenChannelImageHistogram() : ImageHistogram<double, double>(0, 255, 1) {}
00228 
00229     template<class ImageType>
00230     void add_area(std::shared_ptr<ImageType> img, BoundingBox const& bb) {
00231 
00232       assert_is_multi_channel_image<ImageType>();
00233       check_bounding_box(bb, img);
00234 
00235       for(unsigned int y = (unsigned int)bb.get_min_y(); y <= (unsigned int)bb.get_max_y(); y++)
00236         for(unsigned int x = (unsigned int)bb.get_min_x(); x <= (unsigned int)bb.get_max_x(); x++)
00237           add(MASK_G(img->get_pixel(x, y)));
00238     }
00239 
00240     virtual double get_for_rgb(rgba_pixel_t pixel) const {
00241       return get(MASK_G(pixel));
00242     }
00243 
00244   };
00245 
00246 
00247 
00248   class BlueChannelImageHistogram : public ImageHistogram<double, double> {
00249 
00250   public:
00251 
00252     BlueChannelImageHistogram() : ImageHistogram<double, double>(0, 255, 1) {}
00253 
00254     template<class ImageType>
00255     void add_area(std::shared_ptr<ImageType> img, BoundingBox const& bb) {
00256 
00257       assert_is_multi_channel_image<ImageType>();
00258       check_bounding_box(bb, img);
00259 
00260       for(unsigned int y = (unsigned int)bb.get_min_y(); y <= (unsigned int)bb.get_max_y(); y++)
00261         for(unsigned int x = (unsigned int)bb.get_min_x(); x <= (unsigned int)bb.get_max_x(); x++)
00262           add(MASK_B(img->get_pixel(x, y)));
00263 
00264     }
00265 
00266     virtual double get_for_rgb(rgba_pixel_t pixel) const {
00267       return get(MASK_B(pixel));
00268     }
00269 
00270 
00271   };
00272 
00273 
00274   /*
00275   class LocalStdDevImageHistogram : public ImageHistogram<double, double> {
00276 
00277   private:
00278     unsigned int radius;
00279 
00280   public:
00281 
00282     LocalStdDevImageHistogram(double from, double to, double class_width, unsigned int _radius = 2) :
00283       ImageHistogram<double, double>(from, to, class_width),
00284       radius(_radius) {}
00285 
00286     virtual ~LocalStdDevImageHistogram() {}
00287 
00288     template<class ImageType, class EvaluateFunc>
00289     void add_area(std::shared_ptr<ImageType> img, BoundingBox const& bb) {
00290 
00291       assert_is_multi_channel_image<ImageType>();
00292       check_bounding_box(bb, img);
00293 
00294       for(unsigned int y = (unsigned int)bb.get_min_y(); y <= (unsigned int)bb.get_max_y(); y++) {
00295         for(unsigned int x = (unsigned int)bb.get_min_x(); x <= (unsigned int)bb.get_max_x(); x++) {
00296 
00297           std::vector<double> v = fill_vector<ImageType, EvaluateFunc>(img, bb, x, y, radius);
00298           add(standard_deviation<double>(v));
00299         }
00300       }
00301     }
00302 
00303   protected:
00304 
00305     template<class ImageType, class EvaluateFunc>
00306     inline std::vector<double> fill_vector(std::shared_ptr<ImageType> img, BoundingBox const& bb,
00307                                     unsigned int x, unsigned int y, unsigned int radius) {
00308       std::vector<double> v;
00309       unsigned int min_x = bb.get_min_x() + radius < x ? x - radius : bb.get_min_x();
00310       unsigned int max_x = (x + radius < (unsigned int)bb.get_max_x()) ? x + radius : bb.get_max_x();
00311       unsigned int min_y = bb.get_min_y() + radius < y ? y - radius : bb.get_min_y();
00312       unsigned int max_y = (y + radius < (unsigned int)bb.get_max_y()) ? y + radius : bb.get_max_y();
00313 
00314       for(unsigned int _y = min_y; _y < max_y; _y++)
00315         for(unsigned int _x = min_x; _x < max_x; _x++)
00316           v.push_back(EvaluateFunc::func(img->get_pixel(_x, _y)));
00317       return v;
00318     }
00319 
00320 
00321   };
00322 
00323 
00324   class HueStdDevImageHistogram : public LocalStdDevImageHistogram {
00325   private:
00326     struct rgba_to_hue_calculation {
00327       static double func(rgba_pixel_t pix) { return rgba_to_hue(pix); }
00328     };
00329 
00330   public:
00331     HueStdDevImageHistogram(unsigned int radius = 2) : LocalStdDevImageHistogram(0, 255, 1, radius) {}
00332 
00333     template<class ImageType>
00334     void add_area(std::shared_ptr<ImageType> img, BoundingBox const& bb) {
00335       LocalStdDevImageHistogram::add_area<ImageType, rgba_to_hue_calculation>(img, bb);
00336     }
00337   };
00338 
00339 
00340   class SaturationStdDevImageHistogram : public LocalStdDevImageHistogram {
00341   private:
00342     struct rgba_to_sat_calculation {
00343       static double func(rgba_pixel_t pix) { return rgba_to_saturation(pix); }
00344     };
00345 
00346   public:
00347     SaturationStdDevImageHistogram(unsigned int radius = 2) : LocalStdDevImageHistogram(0, 1, 0.05, radius) {}
00348 
00349     template<class ImageType>
00350     void add_area(std::shared_ptr<ImageType> img, BoundingBox const& bb) {
00351       LocalStdDevImageHistogram::add_area<ImageType, rgba_to_sat_calculation>(img, bb);
00352     }
00353   };
00354 
00355 
00356 
00357   class LightnessStdDevImageHistogram : public LocalStdDevImageHistogram {
00358   private:
00359     struct rgba_to_lightness_calculation {
00360       static double func(rgba_pixel_t pix) { return rgba_to_lightness(pix); }
00361     };
00362 
00363   public:
00364     LightnessStdDevImageHistogram(unsigned int radius = 2) : LocalStdDevImageHistogram(0, 255, 1, radius) {}
00365 
00366     template<class ImageType>
00367     void add_area(std::shared_ptr<ImageType> img, BoundingBox const& bb) {
00368       LocalStdDevImageHistogram::add_area<ImageType, rgba_to_lightness_calculation>(img, bb);
00369     }
00370   };
00371 
00372   */
00373 
00374 }
00375 
00376 #endif