tpimageutil.h

Go to the documentation of this file.
00001 #ifndef TPIMAGEUTIL_H
00002 #define TPIMAGEUTIL_H
00003 
00004 #include <typeinfo>
00005 #include <cstring>
00006 #include <cmath>
00007 #include <cassert>
00008 #include "tpimage.h"
00009 
00010 /** @file tpimageutil.h
00011     Templated image utility functions */
00012 
00013 //=========================================================================
00014 
00015 /// Gaussian low-pass filtering, with computational cost proportional to \b dw
00016 /** @param dw filter width (an odd value, typ. \f$ 4 \sigma+1 \f$)
00017     @param limg source image
00018     @param variance filter variance \f$ \sigma^2 \f$
00019     @retval oimg filtered image */
00020 template<int dw> void GaussLowPass(SImage<float> &limg, SImage<float> &oimg,
00021                                    float variance);
00022 /// Low-pass filtering using Deriche's recursive method, with constant cost for all filter sizes. Suitable for \f$ \sigma \f$ up to about 5. For floating point images, an assembly implementation is used
00023 /** @param src source image
00024     @param sigma filter standard deviation \f$ \sigma \f$
00025     @param zeroboard whether to assume outer area is zero or mirrored
00026     @retval dst filtered image */
00027 template <class T> void DericheLowPass(SImage<T> &src, SImage<T> &dst,
00028                                        double sigma, bool zeroboard);
00029 
00030 /// Convert from RGB (three value per pixel) to grey-level image
00031 /** @param src RGB source image
00032     @retval dst grey-level image */
00033 template <class S, class T> void RGBToGrey(SImage<S> &src, SImage<T> &dst);
00034 /// Convert from UYVY (two value per pixel) to grey-level image
00035 /** @param src UYVY source image
00036     @retval dst grey-level image */
00037 template <class S, class T> void YUVToGrey(SImage<S> &src, SImage<T> &dst);
00038 /// Convert from RGB to YUV
00039 /** @param src RGB source image
00040     @retval yimg luminance component image
00041     @retval uimg u colour component image
00042     @retval vimg v colour component image */
00043 template <class S, class T> void RGBToYUV(SImage<S> &src, SImage<T> &yimg,
00044                                           SImage<T> &uimg, SImage<T> &vimg);
00045 /// Convert from YUV to RGB
00046 /** @param yimg luminance component image
00047     @param uimg u colour component image
00048     @param vimg v colour component image
00049     @retval dst RGB image*/
00050 template <class S, class T> void YUVToRGB(SImage<T> &yimg, SImage<T> &uimg,
00051                                           SImage<T> &vimg, SImage<S> &dst);
00052 
00053 /// Point-wise multiply two images
00054 /** @param src source image
00055     @retval dst product image */
00056 template <class T> void operator*=(SImage<T> &dst, SImage<T> &src);
00057 /// Point-wise divide two images
00058 /** @param src source image
00059     @retval dst fraction image */
00060 template <class T> void operator/=(SImage<T> &dst, SImage<T> &src);
00061 /// Point-wise add two images
00062 /** @param src source image
00063     @retval dst sum image */
00064 template <class T> void operator+=(SImage<T> &dst, SImage<T> &src);
00065 /// Point-wise subtract two images
00066 /** @param src source image
00067     @retval dst difference image */
00068 template <class T> void operator-=(SImage<T> &dst, SImage<T> &src);
00069 /// Compute Laplacian of image
00070 /** @param src source image
00071     @retval dst Laplacian image */
00072 template <class T> void Laplace(SImage<T> &src, SImage<T> &dst);
00073 /// Compute absolute difference between two images
00074 /** @param src source image
00075     @retval dst absolute difference image */
00076 template <class T> void AbsDiff(SImage<T> &src, SImage<T> &dst);
00077 /// Compute absolute value of image
00078 /** @param src source image
00079     @retval dst absolute value image */
00080 template <class T> void Abs(SImage<T> &src, SImage<T> &dst);
00081 /// Sum up values within rectangular regions (quick implementation)
00082 /** @param src source image
00083     @param dw region widths
00084     @param dh region heights
00085     @retval dst image of summed up values */
00086 template <class T> void RotatingSum(SImage<T> &src, SImage<T> &dst,
00087                                     int dw, int dh);
00088 
00089 /// Rescale image values
00090 /** @param scale rescaling factor
00091     @retval img image to be rescales */
00092 template <class T> void ReScale(SImage<T> &img, float scale);
00093 /// Copy an data array to image
00094 /** @param indat array of image data
00095     @retval img destination image */
00096 template <class T, class S> void Copy(T* indat, SImage<S> &img);
00097 /// Copy data from one image to another
00098 /** @param src source image
00099     @retval dst destination image */
00100 template <class T, class S> void Copy(SImage<T> &src, SImage<S> &dst);
00101 /// Copy a sub-window from an image
00102 /** @param src source image
00103     @param x center x-position of window in source image
00104     @param y center y-position of window in source image
00105     @param dst destination sub-window */
00106 template <class T> void SubCopy(SImage<T> &src, SImage<T> &dst, int x, int y);
00107 /// Clear image data
00108 /** @retval img image to be cleared */
00109 template <class T> void Clear(SImage<T> &img);
00110 /// Fill image data with a certain value
00111 /** @param value value to be used for filling
00112     @retval img image to be filled */
00113 template <class T> void Fill(SImage<T> &img, T value);
00114 
00115 /// Scale-up an image to twice the size
00116 /** @param src source image
00117     @retval dst destination image of twice the size */
00118 template <class T> void ScaleUp(SImage<T> &src, SImage<T> &dst);
00119 /// Low-pass and scale-down an image to half the size
00120 /** @param src source image
00121     @retval dst destination image of half the size */
00122 template <class T> void ScaleDown(SImage<T> &src, SImage<T> &dst);
00123 /// Scale-down an image to a smaller size
00124 /** @param src source image
00125     @param res scale-down factor
00126     @retval dst scale-downed destination image */
00127 template<int res, class T> void SubSample(SImage<T> &src, SImage<T> &dst);
00128 
00129 /// Low-pass an image with variance \f$\sigma^2\f$ = 1.0
00130 /** @param img source image (repeated boundary assumed)
00131     @retval out blurred destination image */
00132 template <class T> void LowPass(SImage<T> &img, SImage<T> &out);
00133 /// Low-pass an image with variance \f$\sigma^2\f$ = 1.0
00134 /** @param img source image (zero boundary assumed)
00135     @retval out blurred destination image */
00136 template <class T> void LowPassZero(SImage<T> &img, SImage<T> &out);
00137 /// Low-pass an image with variance \f$\sigma^2\f$ = 0.5
00138 /** @param img source image (repeated boundary assumed)
00139     @retval out blurred destination image */
00140 template <class T> void LowPass3(SImage<T> &img, SImage<T> &out);
00141 
00142 /// Low-pass an image x-wise with variance \f$\sigma^2\f$ = 1.0
00143 /** @param img source image
00144     @retval out blurred destination image */
00145 template <class T> void LowPassX(SImage<T> &img, SImage<T> &out);
00146 /// Low-pass an image y-wise with variance \f$\sigma^2\f$ = 1.0
00147 /** @param img source image
00148     @retval out blurred destination image */
00149 template <class T> void LowPassY(SImage<T> &img, SImage<T> &out);
00150 /// Low-pass an image x-wise with variance \f$\sigma^2\f$ = 0.5
00151 /** @param img source image
00152     @retval out blurred destination image */
00153 template <class T> void LowPassX3(SImage<T> &img, SImage<T> &out);
00154 /// Low-pass an image y-wise with variance \f$\sigma^2\f$ = 0.5
00155 /** @param img source image
00156     @retval out blurred destination image */
00157 template <class T> void LowPassY3(SImage<T> &img, SImage<T> &out);
00158 /// Compute x-wise derivative
00159 /** @param img source image
00160     @retval out x-wise derivative */
00161 template <class T> void HighPassX3(SImage<T> &img, SImage<T> &out);
00162 /// Compute y-wise derivative
00163 /** @param img source image
00164     @retval out y-wise derivative */
00165 template <class T> void HighPassY3(SImage<T> &img, SImage<T> &out);
00166 
00167 /// Recify (rotate around y-axis and translate) a sub-window
00168 /** @param img image to be rectified
00169     @param angle rotation angle around y-axis
00170     @param focal focal length (in pixels)
00171     @param xp x-position of sub-window
00172     @param yp y-position of sub-window
00173     @param sourcepos whether positions defined in source image
00174     @retval out rectifed sub-window */
00175 template <class T, class S> void SubRectify(SImage<T> &img, SImage<S> &out,
00176                                             float angle, float focal, float xp, float yp, bool sourcepos = true);
00177 /// Recify (rotate around y-axis and translate) an image
00178 /** @param img image to be rectified
00179     @param angle rotation angle around y-axis
00180     @param focal focal length (in pixels)
00181     @param xshift x-wise translation
00182     @param yshift y-wise translation
00183     @retval out rectifed image */
00184 template <class T, class S> void Rectify(SImage<T> &img, SImage<S> &out,
00185                                          float angle, float focal, float xshift = 0.0, float yshift = 0.0);
00186 /// Correct an image for radial distortion
00187 template <class T> void RadialCorrect(SImage<T> &img, SImage<T> &out,
00188                                       float factor);
00189 
00190 typedef double (*DoubleFunc1)(double);
00191 typedef double (*DoubleFunc2)(double, double);
00192 template <class T> void SImageFunc(DoubleFunc1, SImage<T> &img, SImage<T> &out);
00193 template <class T> void SImageFunc(DoubleFunc2, SImage<T> &img1, SImage<T> &img2,
00194                                   SImage<T> &out);
00195 
00196 //=========================================================================
00197 
00198 /// @cond
00199 typedef unsigned char UCHAR;
00200 void operator+=(SImage<UCHAR> &dst, SImage<UCHAR> &src);
00201 template<> void LowPassX<UCHAR>(SImage<UCHAR> &img, SImage<UCHAR> &out);
00202 template<> void LowPassY<UCHAR>(SImage<UCHAR> &img, SImage<UCHAR> &out);
00203 template<> void LowPass<float>(SImage<float> &img, SImage<float> &out);
00204 /// @endcond
00205 
00206 //=========================================================================
00207 
00208 /// @cond
00209 template<int dw>
00210 void GaussLowPass(SImage<float> &limg, SImage<float> &oimg, float variance)
00211 {
00212   float filter[dw];
00213   const int m = (dw-1) / 2;
00214   float sum = 0.0;
00215   for (int i=0;i<dw;i++) {
00216     filter[i] = exp(-(i-m)*(i-m)/(2.0*variance));
00217     sum += filter[i];
00218   }
00219   for (int i=0;i<dw;i++)
00220     filter[i] /= sum;
00221 
00222 #ifdef PYRAASM
00223   if (dw==5) {
00224     SymmFilter5(limg, oimg, filter[2], filter[1], filter[0]);
00225     return;
00226   }
00227 #endif
00228   int w = limg.GetWidth();
00229   int h = limg.GetHeight();
00230   SImage<float> temp(w, h);
00231   float *limd = limg.GetData();
00232   float *temd = temp.GetData();
00233   for (int y=0;y<h;y++) {
00234     for (int x=0;x<m;x++) {
00235       float sum = 0.0;
00236       for (int d=-m;d<-x;d++)
00237         sum += limd[y*w]*filter[m+d];
00238       for (int d=-x;d<=m;d++)
00239         sum += limd[y*w+x+d]*filter[m+d];
00240       temd[y*w+x] = sum;
00241     }
00242     for (int x=m;x<w-m;x++) {
00243       float sum = 0.0;
00244       for (int d=-m;d<=m;d++)
00245         sum += limd[y*w+x+d]*filter[m+d];
00246       temd[y*w+x] = sum;
00247     }
00248     for (int x=w-m;x<w;x++) {
00249       float sum = 0.0;
00250       for (int d=-m;d<w-x;d++)
00251         sum += limd[y*w+x+d]*filter[m+d];
00252       for (int d=w-x;d<=m;d++)
00253         sum += limd[y*w+w-1]*filter[m+d];
00254       temd[y*w+x] = sum;
00255     }
00256   }
00257   float *oimd = oimg.GetData();
00258   for (int x=0;x<w;x++) {
00259     for (int y=0;y<m;y++) {
00260       float sum = 0.0;
00261       for (int d=-m;d<-y;d++)
00262         sum += temd[x]*filter[m+d];
00263       for (int d=-y;d<=m;d++)
00264         sum += temd[(y+d)*w+x]*filter[m+d];
00265       oimd[y*w+x] = sum;
00266     }
00267     for (int y=m;y<h-m;y++) {
00268       float sum = 0.0;
00269       for (int d=-m;d<=m;d++)
00270         sum += temd[(y+d)*w+x]*filter[m+d];
00271       oimd[y*w+x] = sum;
00272     }
00273     for (int y=h-m;y<h;y++) {
00274       float sum = 0.0;
00275       for (int d=-m;d<h-y;d++)
00276         sum += temd[(y+d)*w+x]*filter[m+d];
00277       for (int d=h-y;d<m;d++)
00278         sum += temd[(h-1)*w+x]*filter[m+d];
00279       oimd[y*w+x] = sum;
00280     }
00281   }
00282 }
00283 
00284 template <class T>
00285 void DericheLowPassXRow(T *srcd, float *tmpd, float *facd, int w)
00286 {
00287   float t1 = facd[24] * srcd[0];
00288   float t2 = t1;
00289   float *td = &tmpd[1];
00290   T *sd = &srcd[1];
00291   td[-1] = t1;
00292   for (int x=1;x<w;x++,td++,sd++) {
00293     td[0] = facd[0]*(float)sd[0] + facd[4]*(float)sd[-1] -
00294       facd[16]*t1 - facd[20]*t2;
00295     t2 = t1;
00296     t1 = td[0];
00297   }
00298   t1 = t2 = facd[28]  * srcd[w-1];
00299   sd = &srcd[w-2];
00300   td = &tmpd[w-3];
00301   td[2] += t1;
00302   td[1] += t1;
00303   for (int x=w-3;x>=0;x--,td--,sd--) {
00304     float t3 = facd[8]*(float)sd[0] + facd[12]*(float)sd[1] -
00305       facd[16]*t1 - facd[20]*t2;
00306     td[0] += t3;
00307     t2 = t1;
00308     t1 = t3;
00309   }
00310 }
00311 
00312 template <class T>
00313 void DericheLowPassYRowD(float *td1, float *td2, float *tm1, float *tm2,
00314                          T *dd, float *fd, int w)
00315 {
00316   for (int x=0;x<w;x++) {
00317     float t3 = fd[0]*td1[x] + fd[4]*td2[x] - fd[16]*tm1[x] - fd[20]*tm2[x];
00318     dd[x] = (T)t3;
00319     tm2[x] = t3;
00320   }
00321 }
00322 
00323 template <class T>
00324 void DericheLowPassYRowU(float *td1, float *td2, float *tm1, float *tm2,
00325                          T *dd, float *fd, int w)
00326 {
00327   for (int x=0;x<w;x++) {
00328     float t3 = fd[8]*td1[x] + fd[12]*td2[x] - fd[16]*tm1[x] - fd[20]*tm2[x];
00329     dd[x] += (T)t3;
00330     tm2[x] = t3;
00331   }
00332 }
00333 
00334 template <class T>
00335 void DericheLowPass(SImage<T> &src, SImage<T> &dst, double sigma,
00336                     bool zeroboard = false)
00337 {
00338   // L(z) = (a0 + a1*z^-1) / (1.0 + b1*z^-1 + b2*z^-2) * X(z)
00339   // R(z) = (a2 + a3*z^+1) / (1.0 + b1*z^+1 + b2*z^+2) * X(z)
00340   // Y(z) = L(z) + R(z)
00341 
00342   //sigma /= sqrt(2.0); //%%%%  Uncertain
00343 #ifdef PYRAASM
00344   if (typeid(T)==typeid(float) && !(src.GetWidth()%4) &&
00345       !(src.GetHeight()%4)) {
00346     DericheLowPass(src.GetData(), dst.GetData(), src.GetWidth(),
00347                    src.GetHeight(),sigma, zeroboard);
00348     return;
00349   }
00350 #endif
00351   SImage<float> factors(4, 8);
00352   float *facd = factors.GetData();
00353 
00354   float alpha = 5.0 / (2.0*sqrt(3.1415)*sigma);
00355   float ea = exp(-alpha);
00356   float e2a = exp(-2.0*alpha);
00357   float c0 = (1.0-ea)*(1.0-ea);
00358   float k = c0 / (1.0+2.0*alpha*ea-e2a);
00359 
00360   for (int i=0;i<4;i++) {
00361     float a0 = facd[i] = k;                               // a0
00362     float a1 = facd[i+4] = k*ea*(alpha-1);                // a1
00363     float a2 = facd[i+8] = k*ea*(alpha+1);                // a2
00364     float a3 = facd[i+12] = -k*e2a;                       // a3
00365     facd[i+16] = -2.0*ea;                                 // b1
00366     facd[i+20] = e2a;                                     // b2
00367     facd[i+24] = (zeroboard ? 0.0 : 1.0) * (a0+a1) / c0;  // L(-1)
00368     facd[i+28] = (zeroboard ? 0.0 : 1.0) * (a2+a3) / c0;  // R(w)
00369   }
00370 
00371   int w = src.GetWidth();
00372   int h = src.GetHeight();
00373   SImage<float> tmp(w, 2);
00374   SImage<float> buf(w, 2);
00375   T *srcd = src.GetData();
00376   float *tmpd = tmp.GetData();
00377   float *bufd = buf.GetData();
00378   DericheLowPassXRow(src[0], tmp[-1], facd, w);
00379   DericheLowPassXRow(src[0], tmp[0], facd, w);
00380   for (int i=0;i<2*w;i++)
00381     bufd[i] = facd[24]*tmpd[i];
00382   for (int y=0;y<h;y++) {
00383     DericheLowPassXRow(src[y], tmp[y], facd, w);
00384     DericheLowPassYRowD(tmp[y], tmp[y-1], buf[y], buf[y-1], dst[y], facd, w);
00385   }
00386   DericheLowPassXRow(src[h-1], tmp[h], facd, w);
00387   DericheLowPassXRow(src[h-1], tmp[h-1], facd, w);
00388   for (int i=0;i<2*w;i++)
00389     bufd[i] = facd[28]*tmpd[i];
00390   DericheLowPassYRowU(tmp[h-1], tmp[h], buf[h-1], buf[h], dst[h-1], facd, w);
00391   for (int y=h-2;y>=0;y--) {
00392     DericheLowPassXRow(src[y+1], tmp[y], facd, w);
00393     DericheLowPassYRowU(tmp[y], tmp[y+1], buf[y], buf[y+1], dst[y], facd, w);
00394   }
00395 }
00396 
00397 template <class T>
00398 void DericheLowPassOld(SImage<T> &src, SImage<T> &dst, double sigma,
00399                        bool zeroboard = false)
00400 {
00401   T *srcd = src.GetData();
00402   T *dstd = dst.GetData();
00403   int w = src.GetWidth();
00404   int h = src.GetHeight();
00405   if (w!=dst.GetWidth() && h!=dst.GetHeight()) {
00406     std::cout << "ERROR: DericheLowPass requires images of the same sizes"
00407               << std::endl;
00408     return;
00409   }
00410 
00411   SImage<float> temp(w, h);
00412   float *temd = temp.GetData();
00413   float *tmpX = new float[w];
00414   float *tmpY = new float[h];
00415 
00416   float alpha = 5.0 / (2.0*sqrt(3.1415)*sigma);
00417   float ea = exp(-alpha);
00418   float e2a = exp(-2.0*alpha);
00419   float c0 = (1.0-ea)*(1.0-ea);
00420   float k = c0 / (1.0+2.0*alpha*ea-e2a);
00421 
00422   float b1 = -2.0*ea;
00423   float b2 = e2a;
00424   float a0 = k;
00425   float a1 = k*ea*(alpha-1);
00426   float a2 = k*ea*(alpha+1);
00427   float a3 = -k*e2a;
00428 
00429   float t1, t2;
00430   float boardfac = (zeroboard ? 0.0 : 1.0);
00431 
00432   for (int y=0;y<h;y++) {
00433     t1 = t2 = boardfac * srcd[y*w] * (a0+a1) / c0;
00434     tmpX[0] = t1;
00435     for (int x=1;x<w; x++) {
00436       tmpX[x] = a0*srcd[y*w+x] + a1*srcd[y*w+x-1] - b1*t1 - b2*t2;
00437       t2 = t1;
00438       t1 = tmpX[x];
00439     }
00440     t1 = t2 = boardfac * srcd[y*w+w-1] * (a2+a3) / c0;
00441     temd[y*w+w-2] = tmpX[w-2] + t1;
00442     temd[y*w+w-1] = tmpX[w-1] + t1;
00443     for (int x=w-3;x>=0;x--) {
00444       float t3 = a2*srcd[y*w+x+1] + a3*srcd[y*w+x+2] - b1*t1 - b2*t2;
00445       temd[y*w+x] = tmpX[x] + t3;
00446       t2 = t1;
00447       t1 = t3;
00448     }
00449   }
00450 
00451   for (int x=0;x<w;x++) {
00452     t1 = t2 = boardfac * temd[x] * (a0+a1) / c0;
00453     tmpY[0] = t1;
00454     for (int y=1;y<h;y++) {
00455       tmpY[y] = a0*temd[y*w+x] + a1*temd[(y-1)*w+x] - b1*t1 - b2*t2;
00456       t2 = t1;
00457       t1 = tmpY[y];
00458     }
00459     t1 = t2 = boardfac * temd[(h-1)*w+x] * (a2+a3) / c0;
00460     dstd[(h-2)*w+x] = tmpY[h-2] + t1;
00461     dstd[(h-1)*w+x] = tmpY[h-1] + t1;
00462     for (int y=h-3;y>=0;y--) {
00463       float t3  = a2*temd[(y+1)*w+x] + a3*temd[(y+2)*w+x] - b1*t1 - b2*t2;
00464       dstd[y*w+x] = tmpY[y] + t3;
00465       t2 = t1;
00466       t1 = t3;
00467     }
00468   }
00469 
00470   delete [] tmpY;
00471   delete [] tmpX;
00472 }
00473 
00474 template <class S, class T>
00475   void RGBToGrey(SImage<S> &src, SImage<T> &dst)
00476 {
00477   S *srcd = src.GetData();
00478   T *dstd = dst.GetData();
00479   int w = dst.GetWidth();
00480   int h = dst.GetHeight();
00481   assert((3*w)==src.GetWidth());
00482 #ifdef PYRAASM
00483   if (typeid(S)==typeid(unsigned char) && typeid(T)==typeid(unsigned char) &&
00484       !(src.GetWidth()%4)) {
00485     RGBToGreyCCASM((unsigned char*)srcd, (unsigned char*)dstd, w, h);
00486     return;
00487   }
00488 #endif
00489   for (int i=0;i<w*h;i++)
00490     dstd[i] = (T)(0.1159*srcd[3*i+2] + 0.5849*srcd[3*i+1] + 0.2991*srcd[3*i]);
00491 }
00492 
00493 template <class S, class T>
00494   void YUVToGrey(SImage<S> &src, SImage<T> &dst)
00495 {
00496   S *srcd = src.GetData();
00497   T *dstd = dst.GetData();
00498   int w = dst.GetWidth();
00499   int h = dst.GetHeight();
00500   assert((2*w)==src.GetWidth());
00501 #ifdef PYRAASM
00502   if (typeid(S)==typeid(unsigned char) && typeid(T)==typeid(unsigned char) &&
00503       !(src.GetWidth()%4)) {
00504     YUVToGreyASM((unsigned char*)srcd, (unsigned char*)dstd, w, h);
00505     return;
00506   }
00507 #endif
00508   for (int i=0;i<w*h;i++)
00509     dstd[i] = (T)(srcd[2*i+1]);
00510 }
00511 
00512 template <class S, class T>
00513   void RGBToYUV(SImage<S> &src, SImage<T> &yimg, SImage<T> &uimg, SImage<T> &vimg)
00514 {
00515   S *srcd = src.GetData();
00516   T *yimd = yimg.GetData();
00517   T *uimd = uimg.GetData();
00518   T *vimd = vimg.GetData();
00519   int w = yimg.GetWidth();
00520   int h = yimg.GetHeight();
00521   assert((3*w)==src.GetWidth());
00522   for (int i=0;i<w*h;i++) {
00523     float r = srcd[3*i+0];
00524     float g = srcd[3*i+1];
00525     float b = srcd[3*i+2];
00526     yimd[i] = (T)( 0.299*r + 0.587*g + 0.114*b);
00527     uimd[i] = (T)(-0.146*r - 0.288*g + 0.434*b);
00528     vimd[i] = (T)( 0.617*r - 0.517*g - 0.100*b);
00529   }
00530 }
00531 
00532 template <class S, class T>
00533   void YUVToRGB(SImage<T> &yimg, SImage<T> &uimg, SImage<T> &vimg, SImage<S> &dst)
00534 {
00535   T *yimd = yimg.GetData();
00536   T *uimd = uimg.GetData();
00537   T *vimd = vimg.GetData();
00538   S *dstd = dst.GetData();
00539   int w = yimg.GetWidth();
00540   int h = yimg.GetHeight();
00541   assert((3*w)==dst.GetWidth());
00542   for (int i=0;i<w*h;i++) {
00543     float y = yimd[i];
00544     float u = uimd[i];
00545     float v = vimd[i];
00546     dstd[3*i+0] = (T)(1.0000*y - 0.0009*u + 1.1359*v);
00547     dstd[3*i+1] = (T)(1.0000*y - 0.3959*u - 0.5783*v);
00548     dstd[3*i+2] = (T)(1.0000*y + 2.0411*u - 0.0016*v);
00549   }
00550 }
00551 
00552 template <class T>
00553 void ScaleUpRow(T *src, T *dst, int w1, int w2)
00554 {
00555   dst[0] = (7*src[0] + src[1]) / 8;
00556   dst[1] = (src[0] + src[1]) / 2;
00557   for (int x=1;x<(w2-1);x++) {
00558     dst[2*x] = (src[x-1] + 6*src[x] + src[x+1]) / 8;
00559     dst[2*x+1] = (src[x] + src[x+1]) / 2;
00560   }
00561   dst[2*w2-2] = (src[w2-2] + 7*src[w2-1]) / 8;
00562   dst[2*w2-1] = src[w2-1];
00563   if (w1>(2*w2)) dst[2*w2] = src[w2-1];
00564 }
00565 
00566 
00567 template <class T>
00568 void ScaleUp(SImage<T> &src, SImage<T> &dst)
00569 {
00570   int w1 = dst.GetWidth();
00571   int h1 = dst.GetHeight();
00572   int w2 = src.GetWidth();
00573   int h2 = src.GetHeight();
00574   SImage<T> buf(w1, 3);
00575   ScaleUpRow(src[0], buf[-1], w1, w2);
00576   ScaleUpRow(src[0], buf[0], w1, w2);
00577   for (int y=0;y<(h2-1);y++) {
00578     ScaleUpRow(src[y+1], buf[y+1], w1, w2);
00579     T *row1 = buf[y-1], *row2 = buf[y], *row3 = buf[y+1];
00580     T *des1 = dst[2*y], *des2 = dst[2*y+1];
00581     for (int x=0;x<w1;x++) {
00582       des1[x] = (row1[x] + 6*row2[x] + row3[x]) / 8;
00583       des2[x] = (row2[x] + row3[x]) / 2;
00584     }
00585   }
00586   T *row1 = buf[h2-2], *row2 = buf[h2-1];
00587   T *des1 = dst[2*h2-2], *des2 = dst[2*h2-1], *des3 = dst[2*h2];
00588   for (int x=0;x<w1;x++) {
00589     des1[x] = (row1[x] + 7*row2[x]) / 8;
00590     des2[x] = row2[x];
00591   }
00592   if (h1>(2*h2))
00593     for (int x=0;x<w1;x++) des3[x] = row2[x];
00594 }
00595 
00596 template <class T>
00597 void ScaleDownRow(T *src, T *dst, int w1, int w2)
00598 {
00599   dst[0] = (11*src[0] + 4*src[1] + src[2]) / 16;
00600   for (int x=1;x<(w2-1);x++)
00601     dst[x] = (src[2*x-2] + 4*src[2*x-1] + 6*src[2*x] + 4*src[2*x+1] + src[2*x+2]) / 16;
00602   dst[w2-1] = src[2*w2-4] + 4*src[2*w2-3] + 6*src[2*w2-2] + 4*src[2*w2-1];
00603   if (w1>(2*w2)) dst[w2-1] += src[2*w2];
00604   else dst[w2-1] += src[2*w2-1];
00605   dst[w2-1] /= 16;
00606 }
00607 
00608 template <class T>
00609 void ScaleDown(SImage<T> &src, SImage<T> &dst)
00610 {
00611   int w1 = src.GetWidth();
00612   int h1 = src.GetHeight();
00613   int w2 = dst.GetWidth();
00614   int h2 = dst.GetHeight();
00615   SImage<T> buf(w2, 5);
00616   ScaleDownRow(src[0], buf[-2], w1, w2);
00617   ScaleDownRow(src[0], buf[-1], w1, w2);
00618   ScaleDownRow(src[0], buf[0], w1, w2);
00619   for (int y=0;y<(h2-1);y++) {
00620     ScaleDownRow(src[2*y+1], buf[2*y+1], w1, w2);
00621     ScaleDownRow(src[2*y+2], buf[2*y+2], w1, w2);
00622     T *row1 = buf[2*y-2], *row2 = buf[2*y-1], *row3 = buf[2*y];
00623     T *row4 = buf[2*y+1], *row5 = buf[2*y+2], *dest = dst[y];
00624     for (int x=0;x<w2;x++)
00625       dest[x] = (row1[x] + 4*row2[x] + 6*row3[x] + 4*row4[x] + row5[x]) / 16;
00626   }
00627   ScaleDownRow(src[2*h2-1], buf[2*h2-1], w1, w2);
00628   T *row1 = buf[2*h2-4], *row2 = buf[2*h2-3], *row3 = buf[2*h2-2];
00629   T *row4 = buf[2*h2-1], *row5 = buf[2*h2], *dest = dst[h2-1];
00630   if (h1>(2*h2)) ScaleDownRow(src[2*h2], buf[2*h2], w1, w2);
00631   else ScaleDownRow(src[2*h2-1], buf[2*h2], w1, w2);
00632   for (int x=0;x<w2;x++)
00633     dest[x] = (row1[x] + 4*row2[x] + 6*row3[x] + 4*row4[x] + row5[x]) / 16;
00634 }
00635 
00636 template<int res, class T>
00637   void SubSample(SImage<T> &src, SImage<T> &dst)
00638 {
00639   T *srcd = src.GetData();
00640   T *dstd = dst.GetData();
00641   int sw = src.GetWidth();
00642   int sh = src.GetHeight();
00643   int dw = dst.GetWidth();
00644   int dh = dst.GetHeight();
00645   int w = (sw<dw*res ? sw / res : dw);
00646   int h = (sh<dh*res ? sh / res : dh);
00647   for (int y=0;y<h;y++) {
00648     int sx = 0;
00649     for (int dx=0;dx<w;dx++,sx+=res)
00650       dstd[dx] = srcd[sx];
00651     for (int dx=w;dx<dw;dx++)
00652       dstd[dx] = dstd[w-1];
00653     srcd += sw*res;
00654     dstd += dw;
00655   }
00656   for (int y=h;y<dh;y++) {
00657     for (int dx=0;dx<dw;dx++)
00658       dstd[dx] = dstd[dx-dw];
00659     dstd += dw;
00660   }
00661 }
00662 
00663 template <class T>
00664 void Laplace(SImage<T> &src, SImage<T> &dst)
00665 {
00666   T *srcd = src.GetData();
00667   T *dstd = dst.GetData();
00668   int w = src.GetWidth();
00669   int h = src.GetHeight();
00670   T *s = srcd;
00671   T *d = dstd;
00672   d[0] = d[w-1] = d[(h-1)*w] = d[h*w-1] = 0;
00673   for (int x=1;x<w-1;x++)
00674     d[x] = (- s[x-1] + 2*s[x] - s[x+1]) / 2;
00675   for (int y=1;y<h-1;y++) {
00676     s = &srcd[y*w];
00677     d = &dstd[y*w];
00678     d[0] = (- s[-w] + 2*s[0] - s[w]) / 2;
00679     for (int x=1;x<w-1;x++)
00680       d[x] = (- s[x-w] - s[x-1] + 4*s[x] - s[x+1] - s[x+w]) / 2;
00681     d[w-1] = (- s[w-1-w] + 2*s[w-1] - s[w-1+w]) / 2;
00682   }
00683   s = &srcd[(h-1)*w];
00684   d = &dstd[(h-1)*w];
00685   for (int x=1;x<w-1;x++)
00686     d[x] = (- s[x-1] + 2*s[x] - s[x+1]) / 2;
00687 }
00688 
00689 template <class T>
00690 void operator*=(SImage<T> &dst, SImage<T> &src)
00691 {
00692   T *srcd = src.GetData();
00693   T *dstd = dst.GetData();
00694   int w = src.GetWidth();
00695   int h = src.GetHeight();
00696   for (int i=0;i<w*h;i++) dstd[i] *= srcd[i];
00697 }
00698 
00699 template <class T>
00700 void operator/=(SImage<T> &dst, SImage<T> &src)
00701 {
00702   T *srcd = src.GetData();
00703   T *dstd = dst.GetData();
00704   int w = src.GetWidth();
00705   int h = src.GetHeight();
00706   for (int i=0;i<w*h;i++)
00707     if (srcd[i]!=(T)0)
00708       dstd[i] /= srcd[i];
00709     else
00710       dstd[i] = srcd[i];
00711 }
00712 
00713 template <class T>
00714 void operator+=(SImage<T> &dst, SImage<T> &src)
00715 {
00716   T *srcd = src.GetData();
00717   T *dstd = dst.GetData();
00718   int w = src.GetWidth();
00719   int h = src.GetHeight();
00720   for (int i=0;i<w*h;i++) dstd[i] += srcd[i];
00721 }
00722 
00723 template <class T>
00724 void operator-=(SImage<T> &dst, SImage<T> &src)
00725 {
00726   T *srcd = src.GetData();
00727   T *dstd = dst.GetData();
00728   int w = src.GetWidth();
00729   int h = src.GetHeight();
00730   for (int i=0;i<w*h;i++) dstd[i] -= srcd[i];
00731 }
00732 
00733 template <class T>
00734 void AbsDiff(SImage<T> &src, SImage<T> &dst)
00735 {
00736   int w = src.GetWidth();
00737   int h = src.GetHeight();
00738   T *srcd = src.GetData();
00739   T *dstd = dst.GetData();
00740 #ifdef PYRAASM
00741   if (typeid(T)==typeid(float)) {
00742     AbsDiffASM((float*)srcd, (float*)dstd, w*h);
00743     return;
00744   }
00745 #endif
00746   for (int i=0;i<w*h;i++) {
00747     T diff = dstd[i] - srcd[i];
00748     dstd[i] = (diff>0 ? diff : -diff);
00749   }
00750 }
00751 
00752 template <class T>
00753 void Abs(SImage<T> &src, SImage<T> &dst)
00754 {
00755   T *srcd = src.GetData();
00756   T *dstd = dst.GetData();
00757   int w = src.GetWidth();
00758   int h = src.GetHeight();
00759   for (int i=0;i<w*h;i++) {
00760     T diff = srcd[i];
00761     dstd[i] = (diff>0 ? diff : -diff);
00762   }
00763 }
00764 
00765 
00766 template <class T>
00767 void RotatingSum(SImage<T> &src, SImage<T> &dst, int dw, int dh)
00768 {
00769   T *srcd = src.GetData();
00770   T *dstd = dst.GetData();
00771   int w = src.GetWidth();
00772   int h = src.GetHeight();
00773   T *tmpd = new T[w];
00774   for (int i=0;i<w;i++)
00775     tmpd[i] = (T)0;
00776   int dw2 = dw/2;
00777   int dh2 = dh/2;
00778   for (int y=0;y<dh2;y++)
00779     for (int x=0;x<w;x++)
00780       tmpd[x] += srcd[y*w+x];
00781   for (int y=dh2;y<dh;y++) {
00782     for (int x=0;x<w;x++)
00783       tmpd[x] += srcd[y*w+x];
00784     int p = (y-dh2) * w;
00785     dstd[p] = tmpd[0];
00786     for (int x=-dw2+1;x<1;x++)
00787       dstd[p] += tmpd[x+dw2];
00788     for (int x=1;x<dw;x++)
00789       dstd[p+x] = dstd[p+x-1] + tmpd[x+dw2];
00790     for (int x=dw;x<w-dw2;x++)
00791       dstd[p+x] = dstd[p+x-1] + tmpd[x+dw2] - tmpd[x+dw2-dw];
00792     for (int x=w-dw2;x<w;x++)
00793       dstd[p+x] = dstd[p+x-1] - tmpd[x+dw2-dw];
00794   }
00795   for (int y=dh;y<h;y++) {
00796     for (int x=0;x<w;x++)
00797       tmpd[x] += (srcd[y*w+x] - srcd[(y-dh)*w+x]);
00798     int p = (y-dh2) * w;
00799     dstd[p] = tmpd[0];
00800     for (int x=-dw2+1;x<1;x++)
00801       dstd[p] += tmpd[x+dw2];
00802     for (int x=1;x<dw;x++)
00803       dstd[p+x] = dstd[p+x-1] + tmpd[x+dw2];
00804     for (int x=dw;x<w-dw2;x++)
00805       dstd[p+x] = dstd[p+x-1] + tmpd[x+dw2] - tmpd[x+dw2-dw];
00806     for (int x=w-dw2;x<w;x++)
00807       dstd[p+x] = dstd[p+x-1] - tmpd[x+dw2-dw];
00808   }
00809   for (int y=h;y<h+dh2;y++) {
00810     for (int x=0;x<w;x++)
00811       tmpd[x] -= srcd[(y-dh)*w+x];
00812     int p = (y-dh2) * w;
00813     dstd[p] = tmpd[0];
00814     for (int x=-dw2+1;x<1;x++)
00815       dstd[p] += tmpd[x+dw2];
00816     for (int x=1;x<dw;x++)
00817       dstd[p+x] = dstd[p+x-1] + tmpd[x+dw2];
00818     for (int x=dw;x<w-dw2;x++)
00819       dstd[p+x] = dstd[p+x-1] + tmpd[x+dw2] - tmpd[x+dw2-dw];
00820     for (int x=w-dw2;x<w;x++)
00821       dstd[p+x] = dstd[p+x-1] - tmpd[x+dw2-dw];
00822   }
00823   delete [] tmpd;
00824 }
00825 
00826 template <class T>
00827 void ReScale(SImage<T> &img, float scale)
00828 {
00829   T *image = img.GetData();
00830   int w = img.GetWidth();
00831   int h = img.GetHeight();
00832   for (int i=0;i<w*h;i++)
00833     image[i] = (T)(scale * image[i]);
00834 }
00835 
00836 template <class T, class S>
00837   void Copy(T* indat, SImage<S> &img)
00838 {
00839   if (typeid(T)==typeid(S))
00840     memcpy(img.GetData(), indat, sizeof(T) * img.GetWidth() * img.GetHeight());
00841   else {
00842     S *image = img.GetData();
00843     int w = img.GetWidth();
00844     int h = img.GetHeight();
00845     for (int i=0;i<w*h;i++)
00846       image[i] = (S)indat[i];
00847   }
00848 }
00849 
00850 template <class T, class S>
00851   void Copy(SImage<T> &src, SImage<S> &dst)
00852 {
00853   if (typeid(T)==typeid(S))
00854     memcpy(dst.GetData(), src.GetData(),
00855            sizeof(T) * src.GetWidth() * src.GetHeight());
00856   else {
00857     S *image = dst.GetData();
00858     T *indat = src.GetData();
00859     int w = dst.GetWidth();
00860     int h = dst.GetHeight();
00861     for (int i=0;i<w*h;i++)
00862       image[i] = (S)indat[i];
00863   }
00864 }
00865 
00866 template <class T>
00867 void SubCopy(SImage<T> &src, SImage<T> &dst, int xp, int yp)
00868 {
00869   int sw = src.GetWidth();
00870   int sh = src.GetHeight();
00871   int dw = dst.GetWidth();
00872   int dh = dst.GetHeight();
00873   int sx = xp - dw/2;
00874   int sy = yp - dh/2;
00875   int minx = (sx<0 ? -sx : 0);
00876   int maxx = (dw>(sw-sx) ? sw-sx  : dw);
00877   int miny = (sy<0 ? -sy : 0);
00878   int maxy = (dh>(sh-sy) ? sh-sy  : dh);
00879   T *srcd = src.GetData();
00880   T *dstd = dst.GetData();
00881   for (int y=0;y<miny;y++)
00882     for (int x=0;x<dw;x++)
00883       dstd[y*dw+x] = (T) 0;
00884   for (int y=miny;y<maxy;y++)
00885     for (int x=0;x<minx;x++)
00886       dstd[y*dw+x] = (T) 0;
00887   for (int y=miny;y<maxy;y++)
00888     for (int x=minx;x<maxx;x++)
00889       dstd[y*dw+x] = srcd[(y+sy)*sw+(x+sx)];
00890   for (int y=miny;y<maxy;y++)
00891     for (int x=maxx;x<dw;x++)
00892       dstd[y*dw+x] = (T) 0;
00893   for (int y=maxy;y<dh;y++)
00894     for (int x=0;x<dw;x++)
00895       dstd[y*dw+x] = (T) 0;
00896 }
00897 
00898 template <class T>
00899 void Clear(SImage<T> &img)
00900 {
00901   T *image = img.GetData();
00902   int w = img.GetWidth();
00903   int h = img.GetHeight();
00904   for (int i=0;i<(w*h);i++) image[i] = (T) 0;
00905 }
00906 
00907 template <class T>
00908 void Fill(SImage<T> &img, T value)
00909 {
00910   T *image = img.GetData();
00911   int w = img.GetWidth();
00912   int h = img.GetHeight();
00913   for (int i=0;i<(w*h);i++) image[i] = value;
00914 }
00915 
00916 template <class T>
00917 void LowPassRow(T *src, T *dst, int w)
00918 {
00919   dst[0] = (11*src[0] + 4*src[1] + src[2]) / 16;
00920   dst[1] = (5*src[0] + 6*src[1] + 4*src[2] + src[3]) / 16;
00921   for (int x=2;x<(w-2);x++)
00922     dst[x] = (src[x-2] + 4*src[x-1] + 6*src[x] + 4*src[x+1] + src[x+2]) / 16;
00923   dst[w-2] = (src[w-4] + 4*src[w-3] + 6*src[w-2] + 5*src[w-1]) / 16;
00924   dst[w-1] = (src[w-3] + 4*src[w-2] + 11*src[w-1]) / 16;
00925 }
00926 
00927 template <class T>
00928 void LowPass(SImage<T> &img, SImage<T> &out)
00929 {
00930   int w = img.GetWidth();
00931   int h = img.GetHeight();
00932   SImage<T> buf(w, 5);
00933   LowPassRow(img[0], buf[-2], w);
00934   LowPassRow(img[0], buf[-1], w);
00935   LowPassRow(img[0], buf[0], w);
00936   LowPassRow(img[1], buf[1], w);
00937   for (int y=0;y<(h-2);y++) {
00938     LowPassRow(img[y+2], buf[y+2], w);
00939     T *row1 = buf[y-2], *row2 = buf[y-1], *row3 = buf[y];
00940     T *row4 = buf[y+1], *row5 = buf[y+2], *dest = out[y];
00941     for (int x=0;x<w;x++)
00942       dest[x] = (row1[x] + 4*row2[x] + 6*row3[x] + 4*row4[x] + row5[x]) / 16;
00943   }
00944   for (int y=h-2;y<h;y++) {
00945     LowPassRow(img[h-1], buf[y+2], w);
00946     T *row1 = buf[y-2], *row2 = buf[y-1], *row3 = buf[y];
00947     T *row4 = buf[y+1], *row5 = buf[y+2], *dest = out[y];
00948     for (int x=0;x<w;x++)
00949       dest[x] = (row1[x] + 4*row2[x] + 6*row3[x] + 4*row4[x] + row5[x]) / 16;
00950   }
00951 }
00952 
00953 template <class T>
00954 void LowPassRowZero(T *src, T *dst, int w)
00955 {
00956   dst[0] = (6*src[0] + 4*src[1] + src[2]) / 16;
00957   dst[1] = (4*src[0] + 6*src[1] + 4*src[2] + src[3]) / 16;
00958   for (int x=2;x<(w-2);x++)
00959     dst[x] = (src[x-2] + 4*src[x-1] + 6*src[x] + 4*src[x+1] + src[x+2]) / 16;
00960   dst[w-2] = (src[w-4] + 4*src[w-3] + 6*src[w-2] + 4*src[w-1]) / 16;
00961   dst[w-1] = (src[w-3] + 4*src[w-2] + 6*src[w-1]) / 16;
00962 }
00963 
00964 template <class T>
00965 void LowPassZero(SImage<T> &img, SImage<T> &out)
00966 {
00967   int w = img.GetWidth();
00968   int h = img.GetHeight();
00969   SImage<T> buf(w, 5);
00970   buf.Clear();
00971   LowPassRowZero(img[0], buf[0], w);
00972   LowPassRowZero(img[1], buf[1], w);
00973   for (int y=0;y<(h-2);y++) {
00974     LowPassRowZero(img[y+2], buf[y+2], w);
00975     T *row1 = buf[y-2], *row2 = buf[y-1], *row3 = buf[y];
00976     T *row4 = buf[y+1], *row5 = buf[y+2], *dest = out[y];
00977     for (int x=0;x<w;x++)
00978       dest[x] = (row1[x] + 4*row2[x] + 6*row3[x] + 4*row4[x] + row5[x]) / 16;
00979   }
00980   for (int y=h-2;y<h;y++) {
00981     T *bptr = buf[y+2];
00982     for (int x=0;x<w;x++) bptr[x] = (T)0;
00983     T *row1 = buf[y-2], *row2 = buf[y-1], *row3 = buf[y];
00984     T *row4 = buf[y+1], *row5 = buf[y+2], *dest = out[y];
00985     for (int x=0;x<w;x++)
00986       dest[x] = (row1[x] + 4*row2[x] + 6*row3[x] + 4*row4[x] + row5[x]) / 16;
00987   }
00988 }
00989 
00990 template <class T>
00991 void LowPassRow3(T *src, T *dst, int w)
00992 {
00993   dst[0] = (3*src[0] + src[1]) / 4;
00994   for (int x=1;x<(w-1);x++)
00995     dst[x] = (src[x-1] + 2*src[x] + src[x+1]) / 4;
00996   dst[w-1] = (src[w-2] + 3*src[w-1]) / 4;
00997 }
00998 
00999 template <class T>
01000 void LowPass3(SImage<T> &img, SImage<T> &out)
01001 {
01002   int w = img.GetWidth();
01003   int h = img.GetHeight();
01004   SImage<T> buf(w, 3);
01005   LowPassRow(img[0], buf[-1], w);
01006   LowPassRow(img[0], buf[0], w);
01007   for (int y=0;y<(h-1);y++) {
01008     LowPassRow(img[y+1], buf[y+1], w);
01009     T *row1 = buf[y-1], *row2 = buf[y], *row3 = buf[y+1], *dest = out[y];
01010     for (int x=0;x<w;x++)
01011       dest[x] = (row1[x] + 2*row2[x] + row3[x]) / 4;
01012   }
01013   for (int y=h-1;y<h;y++) {
01014     LowPassRow(img[h-1], buf[y+1], w);
01015     T *row1 = buf[y-1], *row2 = buf[y], *row3 = buf[y+1], *dest = out[y];
01016     for (int x=0;x<w;x++)
01017       dest[x] = (row1[x] + 2*row2[x] + row3[x]) / 4;
01018   }
01019 }
01020 
01021 template <class T>
01022 void LowPassX(SImage<T> &img, SImage<T> &out)
01023 {
01024   T *image = img.GetData();
01025   T *outimg = out.GetData();
01026   int w = img.GetWidth();
01027   int h = img.GetHeight();
01028   for (int y=0;y<h;y++) {
01029     T *irow = &image[y*w];
01030     T *orow = &outimg[y*w];
01031     orow[0] = (irow[2] + 4*irow[1] + 6*irow[0]) / 11;
01032     orow[1] = (irow[3] + 4*(irow[0] + irow[2]) + 6*irow[1]) / 15;
01033     for (int x=2;x<(w-2);x++)
01034       orow[x] = (irow[x-2] + irow[x+2] + 4*(irow[x-1] +
01035                                             irow[x+1]) + 6*irow[x]) / 16;
01036     orow[w-2] = (irow[w-4] + 4*(irow[w-3] +
01037                                 irow[w-1]) + 6*irow[w-2]) / 15;
01038     orow[w-1] = (irow[w-3] + 4*irow[w-2] + 6*irow[w-1]) / 11;
01039   }
01040 }
01041 
01042 template <class T>
01043 void LowPassY(SImage<T> &img, SImage<T> &out)
01044 {
01045   T *image = img.GetData();
01046   T *outimg = out.GetData();
01047   int w = img.GetWidth();
01048   int h = img.GetHeight();
01049   for (int x=0;x<w;x++) {
01050     T *irow = &image[x];
01051     T *orow = &outimg[x];
01052     orow[0] = (irow[2*w] + 4*irow[w] + 6*irow[0]) / 11;
01053     orow[w] = (irow[3*w] + 4*(irow[0] + irow[2*w])+
01054                6*irow[w]) / 15;
01055     for (int y=2;y<(h-2);y++)
01056       orow[y*w] = (irow[(y-2)*w] + irow[(y+2)*w] +
01057                    4*(irow[(y-1)*w] + irow[(y+1)*w]) + 6*irow[y*w])/16;
01058     orow[(h-2)*w] = (irow[(h-4)*w] +
01059                      4*(irow[(h-3)*w] + irow[(h-1)*w]) +
01060                      6*irow[(h-2)*w]) / 15;
01061     orow[(h-1)*w] = (irow[(h-3)*w] +
01062                      4*irow[(h-2)*w] + 6*irow[(h-1)*w]) / 11;
01063   }
01064 }
01065 
01066 template <class T>
01067 void LowPassX3(SImage<T> &img, SImage<T> &out)
01068 {
01069   T *image = img.GetData();
01070   T *outimg = out.GetData();
01071   int w = img.GetWidth();
01072   int h = img.GetHeight();
01073   for (int y=0;y<h;y++) {
01074     T *irow = &image[y*w];
01075     T *orow = &outimg[y*w];
01076     orow[0] = (irow[1] + 2*irow[0]) / 3;
01077     for (int x=1;x<(w-1);x++)
01078       orow[x] = (irow[x-1] + irow[x+1] + 2*irow[x]) / 4;
01079     orow[w-1] = (irow[w-2] + 2*irow[w-1]) / 3;
01080   }
01081 }
01082 
01083 template <class T>
01084 void LowPassY3(SImage<T> &img, SImage<T> &out)
01085 {
01086   T *image = img.GetData();
01087   T *outimg = out.GetData();
01088   int w = img.GetWidth();
01089   int h = img.GetHeight();
01090   for (int x=0;x<w;x++) {
01091     T *irow = &image[x];
01092     T *orow = &outimg[x];
01093     orow[0] = (irow[w] + 2*irow[0]) / 3;
01094     for (int y=1;y<(h-1);y++)
01095       orow[y*w] = (irow[(y-1)*w] + irow[(y+1)*w] + 2*irow[y*w]) / 4;
01096     orow[(h-1)*w] = (irow[(h-2)*w] + 2*irow[(h-1)*w]) / 3;
01097   }
01098 }
01099 
01100 template <class T>
01101 void HighPassX3(SImage<T> &img, SImage<T> &out)
01102 {
01103   T *image = img.GetData();
01104   T *outimg = out.GetData();
01105   int w = img.GetWidth();
01106   int h = img.GetHeight();
01107   for (int y=0;y<h;y++) {
01108     T *irow = &image[y*w];
01109     T *orow = &outimg[y*w];
01110     orow[0] = irow[1] - irow[0];
01111     for (int x=1;x<(w-1);x++)
01112       orow[x] = (irow[x+1] - irow[x-1]) / 2;
01113     orow[w-1] = irow[w-1] - irow[w-2];
01114   }
01115 }
01116 
01117 template <class T>
01118 void HighPassY3(SImage<T> &img, SImage<T> &out)
01119 {
01120   T *image = img.GetData();
01121   T *outimg = out.GetData();
01122   int w = img.GetWidth();
01123   int h = img.GetHeight();
01124 #ifdef PYRAASM
01125   if (typeid(T)==typeid(float) && !(w%4)) {
01126     HighPassY3ASM(image, outimg, w, h);
01127     return;
01128   }
01129 #endif
01130   for (int x=0;x<w;x++) {
01131     T *irow = &image[x];
01132     T *orow = &outimg[x];
01133     orow[0] = irow[w] - irow[0];
01134     for (int y=1;y<(h-1);y++)
01135       orow[y*w] = (irow[(y+1)*w] - irow[(y-1)*w]) / 2;
01136     orow[(h-1)*w] = irow[(h-1)*w] - irow[(h-2)*w];
01137   }
01138 }
01139 
01140 template <class T, class S>
01141   void SubRectify(SImage<T> &img, SImage<S> &out, float angle, float focal,
01142                   float xp, float yp, bool sourcepos)
01143 {
01144   T *indat = img.GetData();
01145   S *outdat = out.GetData();
01146   int w = out.GetWidth();
01147   int h = out.GetHeight();
01148   int wi = img.GetWidth();                // x' =  cx / (sx + f)
01149   int hi = img.GetHeight();               // y' =   y / (sx + f)
01150   float cosa = cos(3.1415*angle/180.0);   // x =  fx' / (c - sx')
01151   float sina = sin(3.1415*angle/180.0);   // y = cfy' / (c - sx')
01152 
01153   float xval, fval, xflt;
01154   for (int x=0;x<w;x++) {
01155     if (sourcepos) {
01156       xval = (float)(x+xp - wi/2);
01157       fval = sina * xval + focal;
01158       xflt = (focal * cosa * xval/fval + 0.5) + wi/2;
01159     } else {
01160       xval = (float)(x - w/2);
01161       fval = cosa * focal - sina * xval;
01162       xflt = (focal * xval/fval + 0.5) + w/2 - xp;
01163     }
01164     if (xflt>=0.0 && xflt<(wi-1)) {
01165       int xint = (int)xflt;
01166       float xfra = xflt - xint;
01167       T *intmp = &indat[xint];
01168       S *outtmp = outdat;
01169 
01170       float ydel = (sourcepos ? focal / fval : cosa * focal / fval);
01171       float yflt = (sourcepos ? hi/2 : h/2) * (1.0 - ydel);
01172       if (sourcepos)
01173         yflt += yp*ydel;
01174       else
01175         yflt -= yp;
01176       int yfirst = 0;
01177       if (yflt<0.0) {
01178         int num = -(int)(yflt/ydel) + 1;
01179         yfirst += num;
01180         yflt += num*ydel;
01181       }
01182       int ylast = (int)(((hi-2)-yflt) / ydel) + yfirst;
01183       if (ylast>=(h-1))
01184         ylast = h-1;
01185 
01186       for (int y=0;y<yfirst;y++) {
01187         *outtmp = (S) 0;
01188         outtmp = &outtmp[w];
01189       }
01190       int ydeli = (int)(ydel * 0x0400);
01191       int yflti = (int)(yflt * 0x0400);
01192       int xfrai = (int)(xfra * 0x0400);
01193       int xfram = 0x0400 - xfrai;
01194       for (int y=yfirst;y<ylast;y++) {
01195         yflti += ydeli;
01196         int yfrai = yflti & 0x03ff;
01197         T *inp = &intmp[(yflti >> 10) * wi];
01198         int ix1 = (int)(xfram * inp[0] + xfrai * inp[1]);
01199         int ix2 = (int)(xfram * inp[wi] + xfrai * inp[wi+1]);
01200         int yfram = 0x0400 - yfrai;
01201         *outtmp = (S)((yfram * ix1 + yfrai * ix2) >> 20);
01202         outtmp += w;
01203       }
01204       for (int y=ylast;y<h;y++) {
01205         *outtmp = (S) 0;
01206         outtmp = &outtmp[w];
01207       }
01208     } else
01209       for (int y=0;y<h;y++)
01210         outdat[y*w] = (S) 0;
01211     outdat = &outdat[1];
01212   }
01213 }
01214 
01215 template <class T, class S>
01216   void Rectify(SImage<T> &img, SImage<S> &out, float angle, float focal,
01217                float xshift = 0.0, float yshift = 0.0)
01218 {
01219   T *indat = img.GetData();
01220   S *outdat = out.GetData();
01221   int w = out.GetWidth();
01222   int h = out.GetHeight();
01223   int wi = img.GetWidth();
01224   int hi = img.GetHeight();
01225   float scale = (float) wi / w;
01226   float cosa = cos(3.1415*angle/180.0);
01227   float sina = sin(3.1415*angle/180.0);
01228   int yshi = (int)(yshift / scale);
01229 
01230   for (int x=0;x<w;x++) {
01231     float xval = (float)(scale * x - wi/2);
01232     float fval = sina * xval + focal;
01233     float xflt = (focal * cosa * xval/fval + 0.5) + wi/2 + xshift;
01234     if (xflt>=0.0 && xflt<(wi-1)) {
01235       int xint = (int)xflt;
01236       float xfra = xflt - xint;
01237       T *intmp = &indat[xint];
01238       S *outtmp = outdat;
01239 
01240       float ydel = scale * focal / fval;
01241       float yflt = (scale - ydel) * h/2;
01242       int yfirst = (int)(- h/2 * fval / focal + h/2 + 1);
01243       if (yfirst<0) yfirst = 0;
01244       else yflt += (yfirst * ydel);
01245       yfirst += yshi;
01246       if (yfirst<0) {
01247         yflt -= (yfirst * ydel);
01248         yfirst = 0;
01249       }
01250       int ylast = (int)((h-1 - h/2) * fval / focal + h/2 - 1) + yshi;
01251       if (ylast>=h) ylast = h-1;
01252 
01253       for (int y=0;y<yfirst;y++) {
01254         *outtmp = (S) 0;
01255         outtmp = &outtmp[w];
01256       }
01257       int ydeli = (int)(ydel * 0x0400);
01258       int yflti = (int)(yflt * 0x0400);
01259       int xfrai = (int)(xfra * 0x0400);
01260       int xfram = 0x0400 - xfrai;
01261       for (int y=yfirst;y<ylast;y++) {
01262         yflti += ydeli;
01263         int yfrai = yflti & 0x03ff;
01264         T *inp = &intmp[(yflti >> 10) * wi];
01265         int ix1 = (int)(xfram * inp[0] + xfrai * inp[1]);
01266         int ix2 = (int)(xfram * inp[wi] + xfrai * inp[wi+1]);
01267         int yfram = 0x0400 - yfrai;
01268         *outtmp = (S)((yfram * ix1 + yfrai * ix2) >> 20);
01269         outtmp += w;
01270       }
01271       for (int y=ylast;y<h;y++) {
01272         *outtmp = (S) 0;
01273         outtmp = &outtmp[w];
01274       }
01275     } else for (int y=0;y<h;y++) outdat[y*w] = (S) 0;
01276     outdat = &outdat[1];
01277   }
01278 }
01279 
01280 
01281 // pos_new = pos_old * (1.0 + factor*radius^2)
01282 // radius = 1.0 for each image corner
01283 template <class T>
01284 void RadialCorrect(SImage<T> &img, SImage<T> &out, float factor)
01285 {
01286   T *imgd = img.GetData();
01287   T *outd = out.GetData();
01288   int w = img.GetWidth();
01289   int h = img.GetHeight();
01290   float xc =  w / 2;
01291   float yc = h / 2;
01292   float rscale = factor / (xc*xc + yc*yc);
01293   for (int y=-(int)yc;y<yc;y++) {
01294     for (int x=-(int)xc;x<xc;x++) {
01295       float scale = (1 - rscale * (x*x+y*y));
01296       float xf = x*scale + xc;
01297       int xn = (int)xf;
01298       float xd = xf - xn;
01299       float yf = y*scale + yc;
01300       int yn = (int)yf;
01301       float yd = yf - yn;
01302       *outd++ = (T)((1.0-yd)*((1.0-xd)*imgd[yn*w+xn] + xd*imgd[yn*w+xn+1]) +
01303                     yd*((1.0-xd)*imgd[yn*w+xn+w] + xd*imgd[yn*w+xn+w+1]));
01304     }
01305   }
01306 }
01307 
01308 template <class T>
01309 void SImageFunc(DoubleFunc1 func, SImage<T> &img, SImage<T> &out)
01310 {
01311   T *imgd = img.GetData();
01312   T *outd = out.GetData();
01313   int w = img.GetWidth();
01314   int h = img.GetHeight();
01315   for (int i=0;i<w*h;i++)
01316     outd[i] = (T)func((double)imgd[i]);
01317 }
01318 
01319 template <class T>
01320 void SImageFunc(DoubleFunc2 func, SImage<T> &img1, SImage<T> &img2, SImage<T> &out)
01321 {
01322   T *im1d = img1.GetData();
01323   T *im2d = img2.GetData();
01324   T *outd = out.GetData();
01325   int w = img1.GetWidth();
01326   int h = img1.GetHeight();
01327   for (int i=0;i<w*h;i++)
01328     outd[i] = (T)func((double)im1d[i], (double)im2d[i]);
01329 }
01330 
01331 /// @endcond
01332 
01333 #endif // TPIMAGEUTIL_H
Generated on Sun May 8 08:04:44 2011 for iLab Neuromorphic Vision Toolkit by  doxygen 1.6.3