00001 #ifndef Impala_Core_Array_AniGauss_h
00002 #define Impala_Core_Array_AniGauss_h
00003
00004 #include "Util/Math.h"
00005 #include "Core/Array/Arrays.h"
00006 #include "Core/Array/Set.h"
00007
00008 namespace Impala
00009 {
00010 namespace Core
00011 {
00012 namespace Array
00013 {
00014
00015
00016 #ifndef M_PI
00017 #define M_PI 3.14159265358979323846
00018 #endif
00019
00020
00021
00022 #define SRCTYPE Real64
00023
00024
00025 #define DSTTYPE Real64
00026
00027
00028
00029 static inline void
00030 TriggsM(double *filter, double *M)
00031 {
00032 double scale;
00033 double a1, a2, a3;
00034
00035 a3 = filter[0];
00036 a2 = filter[1];
00037 a1 = filter[2];
00038
00039 scale = 1.0/((1.0+a1-a2+a3)*(1.0-a1-a2-a3)*(1.0+a2+(a1-a3)*a3));
00040 M[0] = scale*(-a3*a1+1.0-a3*a3-a2);
00041 M[1] = scale*(a3+a1)*(a2+a3*a1);
00042 M[2] = scale*a3*(a1+a3*a2);
00043 M[3] = scale*(a1+a3*a2);
00044 M[4] = -scale*(a2-1.0)*(a2+a3*a1);
00045 M[5] = -scale*a3*(a3*a1+a3*a3+a2-1.0);
00046 M[6] = scale*(a3*a1+a2+a1*a1-a2*a2);
00047 M[7] = scale*(a1*a2+a3*a2*a2-a1*a3*a3-a3*a3*a3-a3*a2+a3);
00048 M[8] = scale*a3*(a1+a3*a2);
00049 }
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063 static inline void
00064 f_iir_xline_filter(SRCTYPE *src, DSTTYPE *dest, int sx, int sy, double *filter)
00065 {
00066 int i, j;
00067 double b1, b2, b3;
00068 double pix, p1, p2, p3;
00069 double sum, sumsq;
00070 double iplus, uplus, vplus;
00071 double unp, unp1, unp2;
00072 double M[9];
00073
00074 sumsq = filter[3];
00075 sum = sumsq*sumsq;
00076
00077 for (i = 0; i < sy; i++) {
00078
00079 b1 = filter[2]; b2 = filter[1]; b3 = filter[0];
00080 p1 = *src/sumsq; p2 = p1; p3 = p1;
00081
00082 iplus = src[sx-1];
00083 for (j = 0; j < sx; j++) {
00084 pix = *src++ + b1*p1 + b2*p2 + b3*p3;
00085 *dest++ = pix;
00086 p3 = p2; p2 = p1; p1 = pix;
00087 }
00088
00089
00090
00091
00092 uplus = iplus/(1.0-b1-b2-b3);
00093 b1 = filter[4]; b2 = filter[5]; b3 = filter[6];
00094 vplus = uplus/(1.0-b1-b2-b3);
00095
00096 unp = p1-uplus;
00097 unp1 = p2-uplus;
00098 unp2 = p3-uplus;
00099
00100 TriggsM(filter, M);
00101
00102 pix = M[0]*unp+M[1]*unp1+M[2]*unp2 + vplus;
00103 p1 = M[3]*unp+M[4]*unp1+M[5]*unp2 + vplus;
00104 p2 = M[6]*unp+M[7]*unp1+M[8]*unp2 + vplus;
00105 pix *= sum; p1 *= sum; p2 *= sum;
00106
00107 *(--dest) = pix;
00108 p3 = p2; p2 = p1; p1 = pix;
00109
00110 for (j = sx-2; j >= 0; j--) {
00111 pix = sum * *(--dest) + b1*p1 + b2*p2 + b3*p3;
00112 *dest = pix;
00113 p3 = p2; p2 = p1; p1 = pix;
00114 }
00115 dest += sx;
00116 }
00117 }
00118
00119 static inline void
00120 f_iir_yline_filter(DSTTYPE *src, DSTTYPE *dest, int sx, int sy, double *filter)
00121 {
00122 double *p0, *p1, *p2, *p3, *pswap;
00123 double *buf0, *buf1, *buf2, *buf3;
00124 double *uplusbuf;
00125 int i, j;
00126 double b1, b2, b3;
00127 double pix;
00128 double sum, sumsq;
00129 double uplus, vplus;
00130 double unp, unp1, unp2;
00131 double M[9];
00132
00133 sumsq = filter[3];
00134 sum = sumsq*sumsq;
00135
00136 uplusbuf = (double*) malloc(sx*sizeof(*uplusbuf));
00137
00138 buf0 = (double*) malloc(sx*sizeof(*buf0));
00139 buf1 = (double*) malloc(sx*sizeof(*buf1));
00140 buf2 = (double*) malloc(sx*sizeof(*buf2));
00141 buf3 = (double*) malloc(sx*sizeof(*buf3));
00142
00143 p0 = buf0; p1 = buf1; p2 = buf2; p3 = buf3;
00144
00145
00146 b1 = filter[2]; b2 = filter[1]; b3 = filter[0];
00147
00148
00149 for (j = 0; j < sx; j++) {
00150 pix = *src++/sumsq;
00151 p1[j] = pix; p2[j] = pix; p3[j] = pix;
00152 }
00153
00154 src += (sy-2)*sx;
00155 for (j = 0; j < sx; j++)
00156 uplusbuf[j] = *src++/(1.0-b1-b2-b3);
00157 src -= sy*sx;
00158
00159 for (i = 0; i < sy; i++) {
00160 for (j = 0; j < sx; j++) {
00161 pix = *src++ + b1*p1[j] + b2*p2[j] + b3*p3[j];
00162 *dest++ = pix;
00163 p0[j] = pix;
00164 }
00165
00166
00167 pswap = p3; p3 = p2; p2 = p1; p1 = p0; p0 = pswap;
00168 }
00169
00170
00171
00172
00173
00174 b1 = filter[4]; b2 = filter[5]; b3 = filter[6];
00175 TriggsM(filter, M);
00176
00177
00178 p0 = uplusbuf;
00179 for (j = sx-1; j >= 0; j--) {
00180 uplus = p0[j];
00181 vplus = uplus/(1.0-b1-b2-b3);
00182
00183 unp = p1[j]-uplus;
00184 unp1 = p2[j]-uplus;
00185 unp2 = p3[j]-uplus;
00186 pix = M[0]*unp+M[1]*unp1+M[2]*unp2 + vplus;
00187 pix *= sum;
00188 *(--dest) = pix;
00189 p1[j] = pix;
00190 pix = M[3]*unp+M[4]*unp1+M[5]*unp2 + vplus;
00191 p2[j] = pix*sum;
00192 pix = M[6]*unp+M[7]*unp1+M[8]*unp2 + vplus;
00193 p3[j] = pix*sum;
00194 }
00195
00196 for (i = sy-2; i >= 0; i--) {
00197 for (j = sx-1; j >= 0; j--) {
00198 pix = sum * *(--dest) + b1*p1[j] + b2*p2[j] + b3*p3[j];
00199 *dest = pix;
00200 p0[j] = pix;
00201 }
00202
00203
00204 pswap = p3; p3 = p2; p2 = p1; p1 = p0; p0 = pswap;
00205 }
00206
00207 free(buf0);
00208 free(buf1);
00209 free(buf2);
00210 free(buf3);
00211 free(uplusbuf);
00212 }
00213
00214
00215 static inline void
00216 f_iir_tline_filter(DSTTYPE *src, DSTTYPE *dest, int sx, int sy,
00217 double *filter, double tanp)
00218 {
00219 double *p0, *p1, *p2, *p3;
00220 double *buf0, *buf1, *buf2, *buf3;
00221 double *uplusbuf;
00222 int i, j;
00223 double b1, b2, b3;
00224 double sum, sumsq;
00225 double uplus, vplus;
00226 double unp, unp1, unp2;
00227 double M[9];
00228 double pix, prev, val;
00229 double res, prevres;
00230 double xf;
00231 int x;
00232 double c, d;
00233 double e, f;
00234 int q4 = 0;
00235
00236
00237 if (tanp <= 0.0) {
00238 q4 = 1;
00239 tanp = -tanp;
00240 }
00241
00242
00243 uplusbuf = (double*) malloc(sx*sizeof(*uplusbuf));
00244
00245
00246 buf0 = (double*) malloc((sx+sy*tanp+2)*sizeof(*buf0));
00247 buf1 = (double*) malloc((sx+sy*tanp+2)*sizeof(*buf1));
00248 buf2 = (double*) malloc((sx+sy*tanp+2)*sizeof(*buf2));
00249 buf3 = (double*) malloc((sx+sy*tanp+2)*sizeof(*buf3));
00250
00251 if (q4) {
00252 buf0 += (int)(sy*tanp+1);
00253 buf1 += (int)(sy*tanp+1);
00254 buf2 += (int)(sy*tanp+1);
00255 buf3 += (int)(sy*tanp+1);
00256 }
00257
00258 sumsq = filter[3];
00259 sum = sumsq*sumsq;
00260
00261
00262 b1 = filter[2]; b2 = filter[1]; b3 = filter[0];
00263
00264
00265 p1 = buf1; p2 = buf2; p3 = buf3;
00266 for (j = 0; j < sx; j++) {
00267 pix = *src++;
00268 *dest++ = pix; *p1++ = pix; *p2++ = pix; *p3++ = pix;
00269 }
00270
00271
00272 src += (sy-2)*sx;
00273 for (j = 0; j < sx; j++)
00274 uplusbuf[j] = *src++ * sumsq/(1.0-b1-b2-b3);
00275 src -= (sy-1)*sx;
00276
00277 x = 0;
00278 for (i = 1; i < sy; i++) {
00279 xf = i*tanp;
00280
00281
00282 if (q4) {
00283 p1 = buf1-x; p2 = buf2-x; p3 = buf3-x;
00284 for (j=1; j <= (int)(xf)-x; j++) {
00285 p1[-j] = p1[0];
00286 p2[-j] = p2[0];
00287 p3[-j] = p3[0];
00288 }
00289 }
00290 else {
00291 p1 = buf1+x; p2 = buf2+x; p3 = buf3+x;
00292 for (j=1; j <= (int)(xf)-x; j++) {
00293 p1[sx+j-1] = p1[sx-1];
00294 p2[sx+j-1] = p2[sx-1];
00295 p3[sx+j-1] = p3[sx-1];
00296 }
00297 }
00298
00299
00300 x = (int)xf;
00301 c = xf-(double)x;
00302 d = 1.0-c;
00303
00304 e = c; f = d;
00305 if (!q4) {
00306 res = d; d = c; c = res;
00307 res = f; f = e; e = res;
00308 }
00309
00310 c *= sumsq; d *= sumsq;
00311
00312
00313 if (q4) {
00314 p0 = buf0-x; p1 = buf1-x; p2 = buf2-x; p3 = buf3-x;
00315 }
00316 else {
00317 p0 = buf0+x; p1 = buf1+x; p2 = buf2+x; p3 = buf3+x;
00318 }
00319 prev = *src;
00320 prevres = sumsq*prev + b1 * *p1 + b2 * *p2 + b3 * *p3;
00321
00322
00323 for (j = 0; j < sx; j++) {
00324 pix = *src++;
00325 val = c*pix+d*prev;
00326 prev = pix;
00327
00328 res = val + b1 * *p1++ + b2 * *p2++ + b3 * *p3++;
00329 *p0++ = res;
00330 *dest++ = f*res+e*prevres;
00331 prevres = res;
00332 }
00333
00334
00335 p0 = buf3; buf3 = buf2; buf2 = buf1; buf1 = buf0; buf0 = p0;
00336 }
00337
00338
00339
00340
00341 b1 = filter[4]; b2 = filter[5]; b3 = filter[6];
00342 TriggsM(filter, M);
00343
00344
00345 x = (int)((sy-1)*tanp);
00346 if (q4) {
00347 p1 = buf1+sx-x; p2 = buf2+sx-x; p3 = buf3+sx-x;
00348 }
00349 else {
00350 p1 = buf1+sx+x; p2 = buf2+sx+x; p3 = buf3+sx+x;
00351 }
00352 p0 = uplusbuf+sx;
00353 for (j = 0; j < sx; j++) {
00354 uplus = *(--p0);
00355 vplus = uplus/(1.0-b1-b2-b3);
00356
00357 unp = *(--p1)-uplus;
00358 unp1 = *(--p2)-uplus;
00359 unp2 = *(--p3)-uplus;
00360 pix = M[0]*unp+M[1]*unp1+M[2]*unp2 + vplus;
00361 pix *= sumsq;
00362 *(--dest) = pix; *p1 = pix;
00363 pix = M[3]*unp+M[4]*unp1+M[5]*unp2 + vplus;
00364 *p2 = pix*sumsq;
00365 pix = M[6]*unp+M[7]*unp1+M[8]*unp2 + vplus;
00366 *p3 = pix*sumsq;
00367 }
00368
00369 for (i = sy-2; i >= 0; i--) {
00370 xf = i*tanp;
00371
00372
00373 if (q4) {
00374 p1 = buf1-x; p2 = buf2-x; p3 = buf3-x;
00375 for (j=1; j <= x-(int)(xf); j++) {
00376 p1[sx+j-1] = p1[sx-1];
00377 p2[sx+j-1] = p2[sx-1];
00378 p3[sx+j-1] = p3[sx-1];
00379 }
00380 }
00381 else {
00382 p1 = buf1+x; p2 = buf2+x; p3 = buf3+x;
00383 for (j=1; j <= x-(int)(xf); j++) {
00384 p1[-j] = p1[0];
00385 p2[-j] = p2[0];
00386 p3[-j] = p3[0];
00387 }
00388 }
00389
00390
00391 x = (int)xf;
00392 c = xf-(double)x;
00393 d = 1.0-c;
00394
00395 e = c; f = d;
00396 c *= sumsq; d *= sumsq;
00397
00398 if (!q4) {
00399 res = d; d = c; c = res;
00400 res = f; f = e; e = res;
00401 }
00402
00403
00404 if (q4) {
00405 p0 = buf0+sx-x; p1 = buf1+sx-x; p2 = buf2+sx-x; p3 = buf3+sx-x;
00406 }
00407 else {
00408 p0 = buf0+sx+x; p1 = buf1+sx+x; p2 = buf2+sx+x; p3 = buf3+sx+x;
00409 }
00410 prev = *(dest-1);
00411 prevres = sumsq*prev + b1 * *(p1-1) + b2 * *(p2-1) + b3 * *(p3-1);
00412
00413
00414 for (j = 0; j < sx; j++) {
00415 pix = *(--dest);
00416 val = d*pix+c*prev;
00417 prev = pix;
00418
00419 res = val + b1 * *(--p1) + b2 * *(--p2) + b3 * *(--p3);
00420 *(--p0) = res;
00421 *dest = e*res+f*prevres;
00422 prevres = res;
00423 }
00424
00425
00426 p0 = buf3; buf3 = buf2; buf2 = buf1; buf1 = buf0; buf0 = p0;
00427 }
00428
00429 if (q4) {
00430 buf0 -= (int)(sy*tanp+1);
00431 buf1 -= (int)(sy*tanp+1);
00432 buf2 -= (int)(sy*tanp+1);
00433 buf3 -= (int)(sy*tanp+1);
00434 }
00435 free(buf0);
00436 free(buf1);
00437 free(buf2);
00438 free(buf3);
00439 free(uplusbuf);
00440 }
00441
00442
00443 static void
00444 f_iir_derivative_filter(DSTTYPE *src, DSTTYPE *dest, int sx, int sy,
00445 double phi, int order)
00446 {
00447 int i, j;
00448 DSTTYPE *prev, *center, *next;
00449 DSTTYPE *buf, *pstore;
00450 double pn, pc, pp;
00451 double cn, cc, cp;
00452 double nn, nc, np;
00453 double cosp, sinp;
00454
00455 buf = (DSTTYPE*) malloc(sx*sizeof(*buf));
00456
00457 sinp = 0.5*sin(phi); cosp = 0.5*cos(phi);
00458
00459 center = src; prev = src; next = src+sx;
00460 for (i = 0; i < sy; i++) {
00461 pstore = buf;
00462 pn = *prev++; cn = *center++; nn = *next++;
00463 pp = pn; pc = pn;
00464 cp = cn; cc = cn;
00465 np = pn; nc = nn;
00466 *pstore++ = cc;
00467 for (j = 1; j < sx; j++) {
00468 pn = *prev++;
00469 cn = *center++;
00470 nn = *next++;
00471 *dest++ = sinp*(pc-nc)+cosp*(cn-cp);
00472 pp = pc; pc = pn;
00473 cp = cc; cc = cn;
00474 np = pc; nc = nn;
00475 *pstore++ = cc;
00476 }
00477 *dest++ = sinp*(pc-nc)+cosp*(cn-cp);
00478 prev = buf;
00479 if (i==sy-2)
00480 next -= sx;
00481 }
00482
00483 free(buf);
00484 }
00485
00486 void YvVfilterCoef(double sigma, double *filter)
00487 {
00488
00489
00490
00491
00492
00493
00494
00495 double q, qsq;
00496 double scale;
00497 double B, b1, b2, b3;
00498
00499
00500 double m0 = 1.16680, m1 = 1.10783, m2 = 1.40586;
00501 double m1sq = m1*m1, m2sq = m2*m2;
00502
00503
00504 if(sigma < 3.556)
00505 q = -0.2568 + 0.5784 * sigma + 0.0561 * sigma * sigma;
00506 else
00507 q = 2.5091 + 0.9804 * (sigma - 3.556);
00508
00509 qsq = q*q;
00510
00511
00512 scale = (m0 + q) * (m1sq + m2sq + 2*m1*q + qsq);
00513 b1 = -q * (2*m0*m1 + m1sq + m2sq + (2*m0 + 4*m1) * q + 3*qsq) / scale;
00514 b2 = qsq * (m0 + 2*m1 + 3*q) / scale;
00515 b3 = - qsq * q / scale;
00516
00517
00518 B = (m0 * (m1sq + m2sq))/scale;
00519
00520
00521 filter[0] = -b3;
00522 filter[1] = -b2;
00523 filter[2] = -b1;
00524 filter[3] = B;
00525 filter[4] = -b1;
00526 filter[5] = -b2;
00527 filter[6] = -b3;
00528 }
00529
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552 static inline void
00553 anigauss(SRCTYPE *input, DSTTYPE *output, int sizex, int sizey,
00554 double sigmav, double sigmau, double phi, int orderv, int orderu)
00555 {
00556 double filter[7];
00557 double sigmax, sigmay, tanp;
00558 double su2, sv2;
00559 double phirad;
00560 double a11, a21, a22;
00561 int i;
00562
00563 su2 = sigmau*sigmau;
00564 sv2 = sigmav*sigmav;
00565 phirad = phi*M_PI/180.;
00566
00567 a11 = cos(phirad)*cos(phirad)*su2 + sin(phirad)*sin(phirad)*sv2;
00568 a21 = cos(phirad)*sin(phirad)*(su2-sv2);
00569 a22 = cos(phirad)*cos(phirad)*sv2 + sin(phirad)*sin(phirad)*su2;
00570
00571 sigmax = sqrt(a11-a21*a21/a22);
00572 tanp = a21/a22;
00573 sigmay = sqrt(a22);
00574
00575
00576 YvVfilterCoef(sigmax, filter);
00577
00578
00579 f_iir_xline_filter(input,output,sizex,sizey,filter);
00580
00581
00582 YvVfilterCoef(sigmay, filter);
00583
00584 if (tanp != 0.0) {
00585
00586 f_iir_tline_filter(output,output,sizex,sizey,filter, tanp);
00587 }
00588 else {
00589
00590 f_iir_yline_filter(output,output,sizex,sizey,filter);
00591 }
00592
00593
00594 for(i=0; i<orderv; i++)
00595 f_iir_derivative_filter(output, output, sizex, sizey, phirad-M_PI/2., 1);
00596 for(i=0; i<orderu; i++)
00597 f_iir_derivative_filter(output, output, sizex, sizey, phirad, 1);
00598 }
00599
00610 inline void
00611 AniGauss(Array2dScalarReal64*& dst, Array2dScalarReal64* src, Real64 sigmaV,
00612 Real64 sigmaU, Real64 phi, int orderV, int orderU)
00613 {
00614
00615 if ((dst == 0) || (dst->BW() != 0) || (dst->BH() != 0))
00616 {
00617 if (dst)
00618 delete dst;
00619 dst = new Array2dScalarReal64(src->CW(), src->CH(), 0, 0);
00620 }
00621 if ((src->BW() == 0) && (src->BH() == 0))
00622 {
00623 anigauss(src->PB(), dst->PB(), src->W(), src->H(), sigmaV, sigmaU, phi,
00624 orderV, orderU);
00625 }
00626 else
00627 {
00628 Set(dst, src);
00629 anigauss(dst->PB(), dst->PB(), dst->W(), dst->H(), sigmaV, sigmaU, phi,
00630 orderV, orderU);
00631 }
00632 }
00633
00634 #undef SRCTYPE
00635 #undef DSTTYPE
00636
00637 }
00638 }
00639 }
00640
00641 #endif