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
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 template<int dw> void GaussLowPass(SImage<float> &limg, SImage<float> &oimg,
00021 float variance);
00022
00023
00024
00025
00026
00027 template <class T> void DericheLowPass(SImage<T> &src, SImage<T> &dst,
00028 double sigma, bool zeroboard);
00029
00030
00031
00032
00033 template <class S, class T> void RGBToGrey(SImage<S> &src, SImage<T> &dst);
00034
00035
00036
00037 template <class S, class T> void YUVToGrey(SImage<S> &src, SImage<T> &dst);
00038
00039
00040
00041
00042
00043 template <class S, class T> void RGBToYUV(SImage<S> &src, SImage<T> &yimg,
00044 SImage<T> &uimg, SImage<T> &vimg);
00045
00046
00047
00048
00049
00050 template <class S, class T> void YUVToRGB(SImage<T> &yimg, SImage<T> &uimg,
00051 SImage<T> &vimg, SImage<S> &dst);
00052
00053
00054
00055
00056 template <class T> void operator*=(SImage<T> &dst, SImage<T> &src);
00057
00058
00059
00060 template <class T> void operator/=(SImage<T> &dst, SImage<T> &src);
00061
00062
00063
00064 template <class T> void operator+=(SImage<T> &dst, SImage<T> &src);
00065
00066
00067
00068 template <class T> void operator-=(SImage<T> &dst, SImage<T> &src);
00069
00070
00071
00072 template <class T> void Laplace(SImage<T> &src, SImage<T> &dst);
00073
00074
00075
00076 template <class T> void AbsDiff(SImage<T> &src, SImage<T> &dst);
00077
00078
00079
00080 template <class T> void Abs(SImage<T> &src, SImage<T> &dst);
00081
00082
00083
00084
00085
00086 template <class T> void RotatingSum(SImage<T> &src, SImage<T> &dst,
00087 int dw, int dh);
00088
00089
00090
00091
00092 template <class T> void ReScale(SImage<T> &img, float scale);
00093
00094
00095
00096 template <class T, class S> void Copy(T* indat, SImage<S> &img);
00097
00098
00099
00100 template <class T, class S> void Copy(SImage<T> &src, SImage<S> &dst);
00101
00102
00103
00104
00105
00106 template <class T> void SubCopy(SImage<T> &src, SImage<T> &dst, int x, int y);
00107
00108
00109 template <class T> void Clear(SImage<T> &img);
00110
00111
00112
00113 template <class T> void Fill(SImage<T> &img, T value);
00114
00115
00116
00117
00118 template <class T> void ScaleUp(SImage<T> &src, SImage<T> &dst);
00119
00120
00121
00122 template <class T> void ScaleDown(SImage<T> &src, SImage<T> &dst);
00123
00124
00125
00126
00127 template<int res, class T> void SubSample(SImage<T> &src, SImage<T> &dst);
00128
00129
00130
00131
00132 template <class T> void LowPass(SImage<T> &img, SImage<T> &out);
00133
00134
00135
00136 template <class T> void LowPassZero(SImage<T> &img, SImage<T> &out);
00137
00138
00139
00140 template <class T> void LowPass3(SImage<T> &img, SImage<T> &out);
00141
00142
00143
00144
00145 template <class T> void LowPassX(SImage<T> &img, SImage<T> &out);
00146
00147
00148
00149 template <class T> void LowPassY(SImage<T> &img, SImage<T> &out);
00150
00151
00152
00153 template <class T> void LowPassX3(SImage<T> &img, SImage<T> &out);
00154
00155
00156
00157 template <class T> void LowPassY3(SImage<T> &img, SImage<T> &out);
00158
00159
00160
00161 template <class T> void HighPassX3(SImage<T> &img, SImage<T> &out);
00162
00163
00164
00165 template <class T> void HighPassY3(SImage<T> &img, SImage<T> &out);
00166
00167
00168
00169
00170
00171
00172
00173
00174
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
00178
00179
00180
00181
00182
00183
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
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
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
00205
00206
00207
00208
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
00339
00340
00341
00342
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;
00362 float a1 = facd[i+4] = k*ea*(alpha-1);
00363 float a2 = facd[i+8] = k*ea*(alpha+1);
00364 float a3 = facd[i+12] = -k*e2a;
00365 facd[i+16] = -2.0*ea;
00366 facd[i+20] = e2a;
00367 facd[i+24] = (zeroboard ? 0.0 : 1.0) * (a0+a1) / c0;
00368 facd[i+28] = (zeroboard ? 0.0 : 1.0) * (a2+a3) / c0;
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();
01149 int hi = img.GetHeight();
01150 float cosa = cos(3.1415*angle/180.0);
01151 float sina = sin(3.1415*angle/180.0);
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
01282
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
01332
01333 #endif // TPIMAGEUTIL_H