CVD 0.8
|
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) const; 00075 00079 float_type operator[](const TooN::Vector<2>& pos) const; 00080 00082 TooN::Vector<2> min() const; 00084 TooN::Vector<2> max() const; 00085 }; 00086 #endif 00087 00088 00089 00090 #ifndef DOXYGEN_IGNORE_INTERNAL 00091 00092 template<class I, class C> class image_interpolate; 00093 00094 //Zero order (nearest neighbour) 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) const 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) const 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) const 00122 { 00123 return im->in_image(to_ir(pos)); 00124 } 00125 00126 FT operator[](const TooN::Vector<2>& pos) const 00127 { 00128 return (*im)[to_ir(pos)]; 00129 } 00130 00131 TooN::Vector<2> min() const 00132 { 00133 return TooN::makeVector( 0, 0); 00134 } 00135 00136 TooN::Vector<2> max() const 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) const 00150 { 00151 return TooN::makeVector( ::floor(v[0]), ::floor(v[1])); 00152 } 00153 00154 TooN::Vector<2> ceil(const TooN::Vector<2>& v) const 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) const 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) const 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() const 00204 { 00205 return TooN::makeVector( 0, 0); 00206 } 00207 00208 TooN::Vector<2> max() const 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) const 00222 { 00223 return f <0 ? 0 : f; 00224 } 00225 00226 float r(float x) const 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) const 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) const 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 //Algorithm as described in http://astronomy.swin.edu.au/~pbourke/colour/bicubic/ 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() const 00267 { 00268 return TooN::makeVector( 1, 1); 00269 } 00270 00271 TooN::Vector<2> max() const 00272 { 00273 return TooN::makeVector( im->size().x - 2, im->size().y - 2); 00274 } 00275 00276 }; 00277 #endif 00278 00279 } 00280 00281 #endif