00001 #include "Image/Image.H" 00002 #include "Image/Pixels.H" 00003 #include "GenericUtils/ProcessFunctor.H" 00004 #include "GenericUtils/GenericItem.H" 00005 #include <vector> 00006 00007 //typdef our ProcessFunction and associated GenericItem definitions, the first 00008 // template type is the underlying container type, and the second is all the 00009 // types that could be processed. If a conversion is desired, we will attempt to 00010 // convert from the end to the front. 00011 // ###################################################################### 00012 typedef ProcessFunctor<Image, PixRGB<byte>, byte, double, float> ImageFunctor; 00013 typedef GenericItem<Image, PixRGB<byte>, byte, double, float> GenericImage; 00014 00015 // ###################################################################### 00016 //a simple class to sum images as an example 00017 // ###################################################################### 00018 class SumFunc : public ImageFunctor//implements virtual funcions for PixRGB<byte>, byte, double, float 00019 { 00020 public: 00021 float getSum() const { return itsSum; }; 00022 private : 00023 00024 //implement for float 00025 bool process(const Image<float>& feature) 00026 { 00027 //take the sum of the image 00028 itsSum = 0.0; 00029 Image<float>::const_iterator iter(feature.begin()); 00030 while (iter != feature.end()) 00031 itsSum += *iter++; 00032 return true; 00033 } 00034 00035 //for other types if desired....but if left empty then we will attempt to convert to float 00036 00037 float itsSum; 00038 }; 00039 // ###################################################################### 00040 // here is how you would make one generically... now, for all types in Types 00041 // functions will be defined. In the base implementaton, specialization for 00042 // other types not part of Types could be declared (for instance, if you want to 00043 // do something generically for all types but 1. 00044 // ###################################################################### 00045 //define a recursive template 00046 template<typename... Types> class GenSumFunc; 00047 //base case derives from ImageFunctor, accessor function and storage of data 00048 template<> struct GenSumFunc<> : public ImageFunctor 00049 { 00050 float getSum() const { return itsSum; }; 00051 float itsSum; 00052 00053 //specializations for process go here by just defining the function 00054 }; 00055 //recursive case creates our funcions 00056 template<typename T, typename... Tail> 00057 class GenSumFunc<T, Tail...> : public GenSumFunc<Tail...> 00058 { 00059 private: 00060 bool process(const Image<T>& feature) 00061 { 00062 //take the sum of the image 00063 T sum = T(); 00064 typename Image<T>::const_iterator iter(feature.begin()); 00065 while (iter != feature.end()) 00066 sum += *iter++; 00067 00068 GenSumFunc<>::itsSum = (float)sum; 00069 return true; 00070 } 00071 }; 00072 00073 // ###################################################################### 00074 int main(const int argc, const char **argv) 00075 { 00076 //Fill a vector of generic images 00077 Image<float> I1(10,10,ZEROS); 00078 I1.setVal(1,1,10.0F); 00079 Image<double> I2(10,10,ZEROS); 00080 I2.setVal(1,1,9.0); 00081 Image<int> I3(10,10,ZEROS); 00082 I3.setVal(1,8); 00083 00084 std::vector<GenericImage> fsv;//collectin of generic images 00085 fsv.push_back(GenericImage::make(I1)); 00086 fsv.push_back(GenericImage::make(I2)); 00087 fsv.push_back(GenericImage::make(I3)); 00088 00089 //iterate through and take the sum, allowing conversions to float and possibly 00090 //converting to others first depending on the order of the template 00091 //declaration: 00092 // element 1) direct call to the virtual function 00093 // 00094 // element 2) call the non-op double function (our SumFunc knows about 00095 // doubles, but didn't implement and function for them, which will dive 00096 // straight to the non-op base function, and then convert to float since float 00097 // is last in declaration (we try converting backwards) and it is implemented 00098 // 00099 // element 3) Dive straight to the non-op base function (GenericImage doesn't 00100 // know about ints), and then convert to float since float is last in 00101 // declaration (we try converting backwards) and it is implemented 00102 std::vector<GenericImage>::iterator i(fsv.begin()); 00103 while (i != fsv.end()) 00104 { 00105 SumFunc f; 00106 (i++)->runProcessFunctor(f, true);//if the last argument is true, force conversion to float, otherwise no-op 00107 if (f.hasData()) 00108 LINFO("%3.2f", f.getSum()); 00109 } 00110 00111 //No conversion for the first two elements se our template defines functions 00112 //for them automaticall, and then conversion if Image<int> to Image<float> as 00113 //in the above example; 00114 i = fsv.begin(); 00115 while (i != fsv.end()) 00116 { 00117 GenSumFunc<float, double> f; 00118 (i++)->runProcessFunctor(f, true);//if the last argument is true, force conversion to float if we 00119 if (f.hasData()) //are not a float or double, otherwise no-op 00120 LINFO("%3.2f", f.getSum()); 00121 } 00122 00123 return 0; 00124 00125 };