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