00001 #ifndef CVD_IMAGE_INTERPOLATE_H
00002 #define CVD_IMAGE_INTERPOLATE_H
00003
00004 #include <TooN/TooN.h>
00005 #include <cvd/internal/pixel_operations.h>
00006 #include <cvd/internal/rgb_components.h>
00007 #include <cvd/vector_image_ref.h>
00008 #include <math.h>
00009
00010 namespace CVD
00011 {
00015 namespace Interpolate
00016 {
00023 class NearestNeighbour{};
00024
00042 class Bilinear{};
00043
00056 class Bicubic{};
00057 };
00058
00059 #ifdef DOXYGEN_INCLUDE_ONLY_FOR_DOCS
00060
00061
00062
00063
00064
00065 template<class I, class P> class image_interpolate
00066 {
00067 public:
00070 image_interpolate(const BasicImage<P>& i);
00071
00074 bool in_image(const TooN::Vector<2>& pos);
00075
00079 float_type operator[](const TooN::Vector<2>& pos);
00080
00082 TooN::Vector<2> min();
00084 TooN::Vector<2> max();
00085 };
00086 #endif
00087
00088
00089
00090 #ifndef DOXYGEN_IGNORE_INTERNAL
00091
00092 template<class I, class C> class image_interpolate;
00093
00094
00095
00096 template<class C> class image_interpolate<Interpolate::NearestNeighbour, C>
00097 {
00098 private:
00099 const BasicImage<C>* im;
00100
00101 int round(double d)
00102 {
00103 if(d < 0)
00104 return (int)ceil(d - .5);
00105 else
00106 return (int)floor(d + .5);
00107 }
00108
00109 ImageRef to_ir(const TooN::Vector<2>& v)
00110 {
00111 return ImageRef(round(v[0]), round(v[1]));
00112 }
00113
00114 typedef typename Pixel::traits<C>::float_type FT;
00115
00116 public:
00117 image_interpolate(const BasicImage<C>& i)
00118 :im(&i)
00119 {}
00120
00121 bool in_image(const TooN::Vector<2>& pos)
00122 {
00123 return im->in_image(to_ir(pos));
00124 }
00125
00126 FT operator[](const TooN::Vector<2>& pos)
00127 {
00128 return (*im)[to_ir(pos)];
00129 }
00130
00131 TooN::Vector<2> min()
00132 {
00133 return TooN::makeVector( 0, 0);
00134 }
00135
00136 TooN::Vector<2> max()
00137 {
00138 return vec(im->size());
00139 }
00140
00141
00142 };
00143
00144 template<class T> class image_interpolate<Interpolate::Bilinear, T>
00145 {
00146 private:
00147 const BasicImage<T>* im;
00148
00149 TooN::Vector<2> floor(const TooN::Vector<2>& v)
00150 {
00151 return TooN::makeVector( ::floor(v[0]), ::floor(v[1]));
00152 }
00153
00154 TooN::Vector<2> ceil(const TooN::Vector<2>& v)
00155 {
00156 return TooN::makeVector( ::ceil(v[0]), ::ceil(v[1]));
00157 }
00158
00159 typedef typename Pixel::traits<T>::float_type FT;
00160
00161 public:
00162 image_interpolate(const BasicImage<T>& i)
00163 :im(&i)
00164 {}
00165
00166 bool in_image(const TooN::Vector<2>& pos)
00167 {
00168 return im->in_image(ir(floor(pos))) && im->in_image(ir(ceil(pos)));
00169 }
00170
00171 FT operator[](const TooN::Vector<2>& pos)
00172 {
00173 TooN::Vector<2> delta = pos - floor(pos);
00174
00175 ImageRef p = ir(floor(pos));
00176
00177 double x = delta[0];
00178 double y = delta[1];
00179
00180 FT ret;
00181
00182 for(unsigned int i=0; i < Pixel::Component<T>::count; i++)
00183 {
00184 float a, b=0, c=0, d=0;
00185
00186 a = Pixel::Component<T>::get((*im)[p + ImageRef(0,0)], i) * (1-x) * (1-y);
00187
00188 if(x != 0)
00189 b = Pixel::Component<T>::get((*im)[p + ImageRef(1,0)], i) * x * (1-y);
00190
00191 if(y != 0)
00192 c = Pixel::Component<T>::get((*im)[p + ImageRef(0,1)], i) * (1-x) * y;
00193
00194 if(x !=0 && y != 0)
00195 d = Pixel::Component<T>::get((*im)[p + ImageRef(1,1)], i) * x * y;
00196
00197 Pixel::Component<FT>::get(ret, i) = a + b + c + d;
00198 }
00199
00200 return ret;
00201 }
00202
00203 TooN::Vector<2> min()
00204 {
00205 return TooN::makeVector( 0, 0);
00206 }
00207
00208 TooN::Vector<2> max()
00209 {
00210 return vec(im->size());
00211 }
00212
00213 };
00214
00215
00216 template<class T> class image_interpolate<Interpolate::Bicubic, T>
00217 {
00218 private:
00219 const BasicImage<T>* im;
00220
00221 float p(float f)
00222 {
00223 return f <0 ? 0 : f;
00224 }
00225
00226 float r(float x)
00227 {
00228 return ( pow(p(x+2), 3) - 4 * pow(p(x+1),3) + 6 * pow(p(x), 3) - 4* pow(p(x-1),3))/6;
00229 }
00230
00231 typedef typename Pixel::traits<T>::float_type FT;
00232
00233 public:
00234 image_interpolate(const BasicImage<T>& i)
00235 :im(&i)
00236 {}
00237
00238 bool in_image(const TooN::Vector<2>& pos)
00239 {
00240 return pos[0] >= 1 && pos[1] >=1 && pos[0] < im->size().x-2 && pos[1] < im->size().y - 2;
00241 }
00242
00243 FT operator[](const TooN::Vector<2>& pos)
00244 {
00245 int x = (int)floor(pos[0]);
00246 int y = (int)floor(pos[1]);
00247 float dx = pos[0] - x;
00248 float dy = pos[1] - y;
00249
00250
00251 FT ret;
00252 for(unsigned int i=0; i < Pixel::Component<T>::count; i++)
00253 {
00254 float s=0;
00255
00256 for(int m = -1; m < 3; m++)
00257 for(int n = -1; n < 3; n++)
00258 s += Pixel::Component<T>::get((*im)[y+n][x+m], i) * r(m - dx) * r(dy-n);
00259
00260 Pixel::Component<FT>::get(ret, i)= s;
00261 }
00262
00263 return ret;
00264 }
00265
00266 TooN::Vector<2> min()
00267 {
00268 return TooN::makeVector( 1, 1);
00269 }
00270
00271 TooN::Vector<2> max()
00272 {
00273 return TooN::makeVector( im->size().x - 2, im->size().y - 2);
00274 }
00275
00276 };
00277 #endif
00278
00279 }
00280
00281 #endif