|
degate 0.1.1
|
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::tr1::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::tr1::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::tr1::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::tr1::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::tr1::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::tr1::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::tr1::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::tr1::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::tr1::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::tr1::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::tr1::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
1.7.4