00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038 #include "Image/FilterOps.H"
00039
00040 #include "Image/Image.H"
00041 #include "Image/Kernels.H"
00042 #include "Image/MathOps.H"
00043 #include "Image/Pixels.H"
00044 #include "Util/Assert.H"
00045 #include "Util/MathFunctions.H"
00046 #include "Util/Promotions.H"
00047 #include "Util/log.H"
00048 #include "rutz/trace.h"
00049
00050 #include <algorithm>
00051 #include <cmath>
00052 #include <limits>
00053
00054
00055 template <class T>
00056 Image<typename promote_trait<T, float>::TP>
00057 correlation(const Image<T>& src, const Image<float>& filter)
00058 {
00059 ASSERT(src.initialized());
00060 ASSERT(filter.initialized());
00061 const int src_w = src.getWidth();
00062 const int src_h = src.getHeight();
00063
00064 Image<float>::const_iterator fptrBegin = filter.begin();
00065 const int fil_w = filter.getWidth();
00066 const int fil_h = filter.getHeight();
00067 ASSERT((fil_w & 1) && (fil_h & 1));
00068
00069
00070
00071
00072
00073
00074
00075 typedef typename promote_trait<T, float>::TP TF;
00076 const Image<TF> source = src;
00077 Image<TF> result(src_w, src_h, NO_INIT);
00078 typename Image<TF>::const_iterator sptr = source.begin();
00079 typename Image<TF>::iterator dptr = result.beginw();
00080
00081
00082
00083
00084
00085 const int srow_skip = src_w-fil_w;
00086
00087
00088 for (int dst_y = 0; dst_y < src_h-fil_h; dst_y++) {
00089
00090 for (int dst_x = 0; dst_x < src_w-fil_w; dst_x++, dptr++) {
00091
00092 float dst_val = 0.0f;
00093
00094 Image<float>::const_iterator fptr = fptrBegin;
00095
00096
00097
00098
00099 Image<float>::const_iterator srow_ptr =
00100 sptr + (src_w*dst_y) + dst_x;
00101
00102
00103
00104
00105 for (int f_y = 0; f_y < fil_h; ++f_y)
00106 {
00107 for (int f_x = 0; f_x < fil_w; ++f_x){
00108 dst_val += fabs((*srow_ptr++) - (*fptr++));
00109 }
00110
00111 srow_ptr += srow_skip;
00112
00113 }
00114 *dptr = dst_val;
00115 continue;
00116 }
00117 }
00118
00119 return result;
00120
00121 }
00122
00123
00124 template <class T>
00125 Image<typename promote_trait<T, float>::TP>
00126 templMatch(const Image<T>& src, const Image<float>& filter, int method)
00127 {
00128 ASSERT(src.initialized());
00129 ASSERT(filter.initialized());
00130 const int src_w = src.getWidth();
00131 const int src_h = src.getHeight();
00132
00133
00134
00135
00136
00137
00138
00139
00140 const int fil_w = filter.getWidth();
00141 const int fil_h = filter.getHeight();
00142
00143 typedef typename promote_trait<T, float>::TP TF;
00144 const Image<TF> source = src;
00145 Image<TF> result(src_w-fil_w+1, src_h-fil_h+1, NO_INIT);
00146
00147 result = correlation(source, filter);
00148
00149 return result;
00150 }
00151
00152
00153
00154
00155 template <class T>
00156 Image<typename promote_trait<T, float>::TP>
00157 spatialPoolMax(const Image<T>& src, const int si, const int sj,
00158 const int sti, const int stj)
00159 {
00160 GVX_TRACE(__PRETTY_FUNCTION__);
00161 const int w = src.getWidth(), h = src.getHeight();
00162
00163
00164
00165
00166
00167 typedef typename promote_trait<T, float>::TP TF;
00168 const Image<TF> source = src;
00169 Image<TF> result((int)ceil((float)w / (float)si),
00170 (int)ceil((float)h / (float)sj),
00171 NO_INIT);
00172 typename Image<TF>::const_iterator sptr = source.begin();
00173 typename Image<TF>::iterator dptr = result.beginw();
00174
00175
00176 for (int j = 0; j < h; j += sj)
00177 {
00178 int jmax = std::min(j + stj, h);
00179 for (int i = 0; i < w; i += si)
00180 {
00181 TF val = std::numeric_limits<TF>::min();
00182 int imax = std::min(i + sti, w);
00183
00184 for (int jj = j; jj < jmax; jj ++)
00185 for (int ii = i; ii < imax; ii ++)
00186 if (sptr[jj * w + ii] > val) val = sptr[jj * w + ii];
00187 *dptr++ = val;
00188 }
00189 }
00190 return result;
00191 }
00192
00193
00194 template<class T>
00195 float featurePoolHmax(const Image<T>& img1, const Image<T>& img2,
00196 const Image<T>& img3, const Image<T>& img4,
00197 const int si, const int sj, const float s2t)
00198 {
00199 GVX_TRACE(__PRETTY_FUNCTION__);
00200 ASSERT(img1.isSameSize(img2)&&img1.isSameSize(img3)&&img1.isSameSize(img4));
00201
00202 float res = std::numeric_limits<float>::min();
00203 int w = img1.getWidth(), h = img1.getHeight();
00204 typename Image<T>::const_iterator i1 = img1.begin() + si + w * sj;
00205 typename Image<T>::const_iterator i2 = img2.begin() + si;
00206 typename Image<T>::const_iterator i3 = img3.begin() + w * sj;
00207 typename Image<T>::const_iterator i4 = img4.begin();
00208
00209 for (int y = sj; y < h; y++)
00210 {
00211 for (int x = si; x < w; x++)
00212 {
00213 float s2r = (*i1 - s2t) * (*i1 - s2t) + (*i2 - s2t) * (*i2 - s2t) +
00214 (*i3 - s2t) * (*i3 - s2t) + (*i4 - s2t) * (*i4 - s2t);
00215 if (s2r > res) res = s2r;
00216 i1++; i2++; i3++; i4++;
00217 }
00218 i1 += si; i2 += si; i3 += si; i4 += si;
00219 }
00220 return res;
00221 }
00222
00223 namespace
00224 {
00225 pthread_once_t trigtab_init_once = PTHREAD_ONCE_INIT;
00226
00227 const int TRIGTAB_SIZE = 256;
00228
00229 double sintab[TRIGTAB_SIZE];
00230 double costab[TRIGTAB_SIZE];
00231
00232 void trigtab_init()
00233 {
00234 for (int i = 0; i < 256; ++i)
00235 {
00236 const double arg = (2.0*M_PI*i) / 256.0;
00237
00238 #if defined(HAVE_ASM_FSINCOS)
00239 asm("fsincos"
00240 :"=t"(costab[i]), "=u"(sintab[i])
00241 :"0"(arg));
00242 #elif defined(HAVE_SINCOS)
00243 sincos(arg, &sintab[i], &costab[i]);
00244 #else
00245 sintab[i] = sin(arg);
00246 costab[i] = cos(arg);
00247 #endif
00248 }
00249 }
00250 }
00251
00252
00253 template <class T>
00254 Image<typename promote_trait<T, float>::TP>
00255 orientedFilter(const Image<T>& src, const float k,
00256 const float theta, const float intensity,
00257 const bool usetab)
00258 {
00259 GVX_TRACE(__PRETTY_FUNCTION__);
00260 double kx = double(k) * cos((theta + 90.0) * M_PI / 180.0);
00261 double ky = double(k) * sin((theta + 90.0) * M_PI / 180.0);
00262
00263 typedef typename promote_trait<T, float>::TP TF;
00264 Image<TF> re(src.getDims(), NO_INIT), im(src.getDims(), NO_INIT);
00265 typename Image<T>::const_iterator sptr = src.begin();
00266 typename Image<TF>::iterator reptr = re.beginw(), imptr = im.beginw();
00267
00268
00269 int w2l = src.getWidth() / 2, w2r = src.getWidth() - w2l;
00270 int h2l = src.getHeight() / 2, h2r = src.getHeight() - h2l;
00271
00272 if (usetab)
00273 {
00274 pthread_once(&trigtab_init_once, &trigtab_init);
00275
00276 const double kx2 = (256.0 * kx) / (2.0*M_PI);
00277 const double ky2 = (256.0 * ky) / (2.0*M_PI);
00278
00279 for (int j = -h2l; j < h2r; ++j)
00280 for (int i = -w2l; i < w2r; ++i)
00281 {
00282 const double arg2 = kx2 * i + ky2 * j;
00283 int idx = int(arg2) % 256;
00284 if (idx < 0) idx += 256;
00285 const TF val = (*sptr++) * intensity;
00286
00287 const double sinarg = sintab[idx];
00288 const double cosarg = costab[idx];
00289
00290 *reptr++ = TF(val * cosarg);
00291 *imptr++ = TF(val * sinarg);
00292 }
00293 }
00294 else
00295 {
00296 for (int j = -h2l; j < h2r; ++j)
00297 for (int i = -w2l; i < w2r; ++i)
00298 {
00299 const double arg = kx * i + ky * j;
00300 const TF val = (*sptr++) * intensity;
00301
00302 #if defined(HAVE_ASM_FSINCOS)
00303
00304
00305
00306 double sinarg, cosarg;
00307 asm("fsincos"
00308 :"=t"(cosarg), "=u"(sinarg)
00309 :"0"(arg));
00310
00311 #elif defined(HAVE_SINCOS)
00312
00313
00314
00315
00316
00317
00318
00319
00320 double sinarg, cosarg;
00321 sincos(arg, &sinarg, &cosarg);
00322
00323 #else
00324
00325
00326 double sinarg = sin(arg);
00327 double cosarg = cos(arg);
00328 #endif
00329
00330 *reptr++ = TF(val * cosarg);
00331 *imptr++ = TF(val * sinarg);
00332 }
00333 }
00334
00335 re = ::lowPass9(re);
00336 im = ::lowPass9(im);
00337
00338 return quadEnergy(re, im);
00339 }
00340
00341
00342 template <class T>
00343 Image<T> centerSurround(const Image<T>& center,
00344 const Image<T>& surround,
00345 const bool absol)
00346 {
00347 GVX_TRACE(__PRETTY_FUNCTION__);
00348 const int lw = center.getWidth(), lh = center.getHeight();
00349 const int sw = surround.getWidth(), sh = surround.getHeight();
00350
00351 if (sw > lw || sh > lh) LFATAL("center must be larger than surround");
00352
00353 int scalex = lw / sw, remx = lw - 1 - (lw % sw);
00354 int scaley = lh / sh, remy = lh - 1 - (lh % sh);
00355
00356
00357 Image<T> result(center.getDims(), NO_INIT);
00358
00359
00360 int ci = 0, cj = 0;
00361 typename Image<T>::const_iterator lptr = center.begin();
00362 typename Image<T>::const_iterator sptr = surround.begin();
00363 typename Image<T>::iterator dptr = result.beginw();
00364 T zero = T();
00365
00366 if (absol == true)
00367 {
00368 for (int j = 0; j < lh; ++j)
00369 {
00370 for (int i = 0; i < lw; ++i)
00371 {
00372 if (*lptr > *sptr)
00373 *dptr++ = T(*lptr++ - *sptr);
00374 else
00375 *dptr++ = T(*sptr - *lptr++);
00376
00377 if ((++ci) == scalex && i != remx) { ci = 0; ++sptr; }
00378 }
00379 if (ci) { ci = 0; ++sptr; }
00380 if ((++cj) == scaley && j != remy) cj = 0; else sptr -= sw;
00381 }
00382 }
00383 else
00384 {
00385 for (int j = 0; j < lh; ++j)
00386 {
00387 for (int i = 0; i < lw; ++i)
00388 {
00389 if (*lptr > *sptr)
00390 *dptr++ = T(*lptr++ - *sptr);
00391 else
00392 { *dptr++ = zero; lptr++; }
00393
00394 if ((++ci) == scalex && i != remx) { ci = 0; ++sptr; }
00395 }
00396 if (ci) { ci = 0; ++sptr; }
00397 if ((++cj) == scaley && j != remy) cj = 0; else sptr -= sw;
00398 }
00399 }
00400
00401
00402 inplaceAttenuateBorders(result, result.getDims().max() / 20);
00403
00404 return result;
00405 }
00406
00407
00408 template <class T>
00409 void centerSurround(const Image<T>& center, const Image<T>& surround,
00410 Image<T>& pos, Image<T>& neg)
00411 {
00412 GVX_TRACE(__PRETTY_FUNCTION__);
00413 const int lw = center.getWidth(), lh = center.getHeight();
00414 const int sw = surround.getWidth(), sh = surround.getHeight();
00415
00416 if (sw > lw || sh > lh) LFATAL("center must be larger than surround");
00417
00418 int scalex = lw / sw, remx = lw - 1 - (lw % sw);
00419 int scaley = lh / sh, remy = lh - 1 - (lh % sh);
00420
00421
00422 pos.resize(center.getDims(), NO_INIT);
00423 neg.resize(center.getDims(), NO_INIT);
00424
00425
00426 int ci = 0, cj = 0;
00427 typename Image<T>::const_iterator lptr = center.begin();
00428 typename Image<T>::const_iterator sptr = surround.begin();
00429 typename Image<T>::iterator pptr = pos.beginw(), nptr = neg.beginw();
00430 T zero = T();
00431
00432 for (int j = 0; j < lh; ++j)
00433 {
00434 for (int i = 0; i < lw; ++i)
00435 {
00436 if (*lptr > *sptr) { *pptr++ = T(*lptr++ - *sptr); *nptr++ = zero; }
00437 else { *pptr++ = zero; *nptr++ = T(*sptr - *lptr++); }
00438
00439 if ((++ci) == scalex && i != remx) { ci = 0; ++sptr; }
00440 }
00441 if (ci) { ci = 0; ++sptr; }
00442 if ((++cj) == scaley && j != remy) cj = 0; else sptr -= sw;
00443 }
00444
00445
00446 inplaceAttenuateBorders(pos, pos.getDims().max() / 20);
00447 inplaceAttenuateBorders(neg, neg.getDims().max() / 20);
00448 }
00449
00450
00451 template <class T>
00452 Image<typename promote_trait<T, float>::TP>
00453 doubleOpp(const Image<T>& cplus, const Image<T>& cminus,
00454 const Image<T>& splus, const Image<T>& sminus)
00455 {
00456 GVX_TRACE(__PRETTY_FUNCTION__);
00457 ASSERT(cplus.isSameSize(cminus)); ASSERT(splus.isSameSize(sminus));
00458
00459 typedef typename promote_trait<T, float>::TP TF;
00460
00461
00462 Image<TF> cdiff = cplus; cdiff -= cminus;
00463
00464
00465 Image<TF> sdiff = splus; sdiff -= sminus;
00466
00467
00468 return centerSurround(cdiff, sdiff, true);
00469 }
00470
00471
00472 template <class T>
00473 void avgOrient(const Image<T>& src,
00474 Image<float>& orient, Image<float>& strength)
00475 {
00476 GVX_TRACE(__PRETTY_FUNCTION__);
00477 float Gf1[9] = { 0.0094, 0.1148, 0.3964, -0.0601, -0.9213, -0.0601,
00478 0.3964, 0.1148, 0.0094 };
00479 float Gf2[9] = { 0.0008, 0.0176, 0.1660, 0.6383, 1.0, 0.6383, 0.1660,
00480 0.0176, 0.0008 };
00481 float Gf3[9] = { -0.0028, -0.0480, -0.3020, -0.5806, 0.0, 0.5806, 0.3020,
00482 0.0480, 0.0028 };
00483 float Hf1[9] = { -0.0098, -0.0618, 0.0998, 0.7551, 0.0, -0.7551, -0.0998,
00484 0.0618, 0.0098 };
00485 float Hf2[9] = { 0.0008, 0.0176, 0.1660, 0.6383, 1.0, 0.6383, 0.1660,
00486 0.0176, 0.0008 };
00487 float Hf3[9] = { -0.0020, -0.0354, -0.2225, -0.4277, 0.0, 0.4277, 0.2225,
00488 0.0354, 0.0020 };
00489 float Hf4[9] = { 0.0048, 0.0566, 0.1695, -0.1889, -0.7349, -0.1889, 0.1695,
00490 0.0566, 0.0048 };
00491
00492 Image<float> fima = src;
00493
00494
00495 Image<float> G2a = sepFilter(fima, Gf1, Gf2, 9, 9, CONV_BOUNDARY_ZERO);
00496 Image<float> G2b = sepFilter(fima, Gf3, Gf3, 9, 9, CONV_BOUNDARY_ZERO);
00497 Image<float> G2c = sepFilter(fima, Gf2, Gf1, 9, 9, CONV_BOUNDARY_ZERO);
00498 Image<float> H2a = sepFilter(fima, Hf1, Hf2, 9, 9, CONV_BOUNDARY_ZERO);
00499 Image<float> H2b = sepFilter(fima, Hf4, Hf3, 9, 9, CONV_BOUNDARY_ZERO);
00500 Image<float> H2c = sepFilter(fima, Hf3, Hf4, 9, 9, CONV_BOUNDARY_ZERO);
00501 Image<float> H2d = sepFilter(fima, Hf2, Hf1, 9, 9, CONV_BOUNDARY_ZERO);
00502
00503
00504 orient = Image<float>(src.getDims(), NO_INIT);
00505 strength = Image<float>(src.getDims(), NO_INIT);
00506
00507 const int siz = src.getSize();
00508
00509 typename Image<float>::const_iterator
00510 pG2a = G2a.begin(),
00511 pG2b = G2b.begin(),
00512 pG2c = G2c.begin(),
00513 pH2a = H2a.begin(),
00514 pH2b = H2b.begin(),
00515 pH2c = H2c.begin(),
00516 pH2d = H2d.begin();
00517
00518 Image<float>::iterator porient = orient.beginw();
00519 Image<float>::iterator pstrength = strength.beginw();
00520
00521 for (int k = 0; k < siz; ++k)
00522 {
00523 const float c2 = 0.5 * (squareOf(pG2a[k]) - squareOf(pG2c[k]))
00524 + 0.46875 * (squareOf(pH2a[k]) - squareOf(pH2d[k]))
00525 + 0.28125 * (squareOf(pH2b[k]) - squareOf(pH2c[k]))
00526 + 0.1875 * (pH2a[k] * pH2c[k] - pH2b[k] * pH2d[k]);
00527 const float c3 =
00528 - pG2a[k] * pG2b[k]
00529 - pG2b[k] * pG2c[k]
00530 - 0.9375 * (pH2c[k] * pH2d[k] + pH2a[k] * pH2b[k])
00531 - 1.6875 * pH2b[k] * pH2c[k]
00532 - 0.1875 * pH2a[k] * pH2d[k];
00533 porient[k] = (atan2(c3, c2) + M_PI)/ 2.0;
00534 pstrength[k] = sqrt(squareOf(c2) + squareOf(c3));
00535 }
00536 }
00537
00538
00539 template <class T>
00540 Image<T> energyNorm(const Image<T>& img)
00541 {
00542 GVX_TRACE(__PRETTY_FUNCTION__);
00543
00544
00545
00546 Image<float> result = img + 1.0f;
00547
00548
00549 const Image<float> energy = sqrt(lowPass9(result * result));
00550
00551
00552 result = result / energy;
00553
00554
00555 result -= mean(result);
00556
00557 return result;
00558 }
00559
00560
00561 template <class T>
00562 Image<T> junctionFilterFull(const Image<T>& i0, const Image<T>& i45,
00563 const Image<T>& i90, const Image<T>& i135,
00564 const bool r[8], const int dx = 6,
00565 const int dy = 6,
00566 const bool useEuclidDiag = true)
00567 {
00568 GVX_TRACE(__PRETTY_FUNCTION__);
00569
00570 ASSERT(i0.isSameSize(i45));
00571 ASSERT(i0.isSameSize(i90));
00572 ASSERT(i0.isSameSize(i135));
00573
00574 Image<T> result(i0.getDims(), ZEROS);
00575
00576 const int w = i0.getWidth(), h = i0.getHeight();
00577
00578
00579
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589
00590
00591
00592
00593
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607 int dx_diag, dy_diag;
00608
00609
00610
00611 if(useEuclidDiag)
00612 {
00613 dx_diag = (int)round(sqrt(pow(dx,2)/2.0f));
00614 dy_diag = (int)round(sqrt(pow(dy,2)/2.0f));
00615 }
00616 else
00617 {
00618 dx_diag = dx;
00619 dy_diag = dy;
00620 }
00621
00622
00623 const int o0 = dx;
00624 const int o2 = -dy*w;
00625 const int o4 = -dx;
00626 const int o6 = dy*w;
00627
00628
00629 const int o1 = dx_diag - dy_diag*w;
00630 const int o3 = -dx_diag - dy_diag*w;
00631 const int o5 = -dx_diag + dy_diag*w;
00632 const int o7 = dx_diag + dy_diag*w;
00633
00634
00635 typename Image<T>::const_iterator
00636 ip0 = i0.begin() + dx + dy*w, ip45 = i45.begin() + dx + dy*w,
00637 ip90 = i90.begin() + dx + dy*w, ip135 = i135.begin() + dx + dy*w;
00638 typename Image<T>::iterator rp = result.beginw() + dx + dy*w;
00639
00640
00641
00642
00643 const T max = std::numeric_limits<T>::max();
00644
00645 for (int j = (dy*2); j < h; j ++)
00646 {
00647 for (int i = (dx*2); i < w; i ++)
00648 {
00649
00650
00651 const T r0 = ip0[o0], r4 = ip0[o4]; ++ip0;
00652 const T r1 = ip45[o1], r5 = ip45[o5]; ++ip45;
00653 const T r2 = ip90[o2], r6 = ip90[o6]; ++ip90;
00654 const T r3 = ip135[o3], r7 = ip135[o7]; ++ip135;
00655
00656
00657
00658
00659 T minRel = max;
00660 if (r[0] && r0 < minRel) minRel = r0;
00661 if (r[1] && r1 < minRel) minRel = r1;
00662 if (r[2] && r2 < minRel) minRel = r2;
00663 if (r[3] && r3 < minRel) minRel = r3;
00664 if (r[4] && r4 < minRel) minRel = r4;
00665 if (r[5] && r5 < minRel) minRel = r5;
00666 if (r[6] && r6 < minRel) minRel = r6;
00667 if (r[7] && r7 < minRel) minRel = r7;
00668 minRel /= 2;
00669
00670
00671 float resp = 1.0f;
00672
00673
00674
00675
00676
00677
00678
00679 if (r[0]) resp *= r0; else resp *= (minRel - r0);
00680 if (resp <= 0.0f) resp = 0.0f;
00681 else
00682 {
00683 if (r[1]) resp *= r1; else resp *= (minRel - r1);
00684 if (resp <= 0.0f) resp = 0.0f;
00685 else
00686 {
00687 if (r[2]) resp *= r2; else resp *= (minRel - r2);
00688 if (resp <= 0.0f) resp = 0.0f;
00689 else
00690 {
00691 if (r[3]) resp *= r3; else resp *= (minRel - r3);
00692 if (resp <= 0.0f) resp = 0.0f;
00693 else
00694 {
00695 if (r[4]) resp *= r4; else resp *= (minRel - r4);
00696 if (resp <= 0.0f) resp = 0.0f;
00697 else
00698 {
00699 if (r[5]) resp *= r5; else resp *= (minRel - r5);
00700 if (resp <= 0.0f) resp = 0.0f;
00701 else
00702 {
00703 if (r[6]) resp *= r6; else resp *= (minRel - r6);
00704 if (resp <= 0.0f) resp = 0.0f;
00705 else
00706 {
00707 if (r[7]) resp *= r7; else resp *= (minRel - r7);
00708 if (resp <= 0.0f) resp = 0.0f;
00709 else
00710 {
00711
00712 resp = pow(resp, 1.0/8.0);
00713 }
00714 }
00715 }
00716 }
00717 }
00718 }
00719 }
00720 }
00721
00722
00723 *rp++ = T(resp);
00724 }
00725
00726 ip0 += dx*2; ip45 += dx*2; ip90 += dx*2; ip135 += dx*2; rp += dx*2;
00727 }
00728
00729 return result;
00730 }
00731
00732
00733 namespace
00734 {
00735
00736 template <class DstItr, class SrcItr>
00737 inline void JFILT(DstItr dptr, SrcItr sptr,
00738 const int w, const int jmax, const int imax)
00739 {
00740 for(int j = 0; j < jmax; ++j)
00741 {
00742 for (int i = 0; i < imax; ++i)
00743 dptr[i] *= sptr[i];
00744
00745 sptr += w; dptr += w;
00746 }
00747 }
00748 }
00749
00750 template <class T>
00751 Image<T> junctionFilterPartial(const Image<T>& i0, const Image<T>& i45,
00752 const Image<T>& i90, const Image<T>& i135,
00753 const bool r[8], const int dx = 6,
00754 const int dy = 6,
00755 const bool useEuclidDiag = false)
00756 {
00757 GVX_TRACE(__PRETTY_FUNCTION__);
00758
00759
00760 ASSERT(i0.isSameSize(i45) && i0.isSameSize(i90) && i0.isSameSize(i135));
00761 Image<T> result(i0.getDims(), ZEROS);
00762
00763 const int w = i0.getWidth(), h = i0.getHeight();
00764
00765 int dx_diag, dy_diag;
00766
00767
00768
00769 if(useEuclidDiag)
00770 {
00771 dx_diag = (int)round(fastSqrt((dx*dx)/2.0f));
00772 dy_diag = (int)round(fastSqrt((dy*dy)/2.0f));
00773 }
00774 else
00775 {
00776 dx_diag = dx;
00777 dy_diag = dy;
00778 }
00779
00780
00781 const int o0 = dx;
00782 const int o2 = -dy*w;
00783 const int o4 = -dx;
00784 const int o6 = dy*w;
00785
00786
00787 const int o1 = dx_diag - dy_diag*w;
00788 const int o3 = -dx_diag - dy_diag*w;
00789 const int o5 = -dx_diag + dy_diag*w;
00790 const int o7 = dx_diag + dy_diag*w;
00791
00792 const int offset = dx + dy*w;
00793
00794 typename Image<T>::iterator const rpp = result.beginw() + offset;
00795
00796
00797 int nr = 0; for (int i = 0; i < 8; i++) if (r[i]) nr++;
00798
00799 const int imax = w - dx*2;
00800 const int jmax = h - dy*2;
00801
00802
00803 {
00804 typename Image<T>::iterator rp = rpp;
00805 for (int j = 0; j < jmax; ++j)
00806 {
00807 for (int i = 0; i < imax; ++i)
00808 rp[i] = T(1.0);
00809 rp += w;
00810 }
00811 }
00812
00813
00814
00815 {
00816 if (r[0]) JFILT(rpp, i0.begin() + o0 + offset, w, jmax, imax);
00817 if (r[1]) JFILT(rpp, i45.begin() + o1 + offset, w, jmax, imax);
00818 if (r[2]) JFILT(rpp, i90.begin() + o2 + offset, w, jmax, imax);
00819 if (r[3]) JFILT(rpp, i135.begin() + o3 + offset, w, jmax, imax);
00820 if (r[4]) JFILT(rpp, i0.begin() + o4 + offset, w, jmax, imax);
00821 if (r[5]) JFILT(rpp, i45.begin() + o5 + offset, w, jmax, imax);
00822 if (r[6]) JFILT(rpp, i90.begin() + o6 + offset, w, jmax, imax);
00823 if (r[7]) JFILT(rpp, i135.begin() + o7 + offset, w, jmax, imax);
00824 }
00825
00826
00827
00828
00829 {
00830 typename Image<T>::iterator rp = rpp;
00831 if (nr == 1)
00832 {
00833
00834 }
00835 else if (nr == 2)
00836 {
00837 for (int j = 0; j < jmax; ++j)
00838 {
00839 for (int i = 0; i < imax; ++i)
00840 rp[i] = T(fastSqrt(rp[i]));
00841 rp += w;
00842 }
00843 }
00844 else if (nr == 3)
00845 {
00846 for (int j = 0; j < jmax; ++j)
00847 {
00848 for (int i = 0; i < imax; ++i)
00849 rp[i] = T(cbrt(rp[i]));
00850 rp += w;
00851 }
00852 }
00853 else if (nr == 4)
00854 {
00855 for (int j = 0; j < jmax; ++j)
00856 {
00857 for (int i = 0; i < imax; ++i)
00858 rp[i] = T(fastSqrt(fastSqrt(rp[i])));
00859 rp += w;
00860 }
00861 }
00862 else
00863 {
00864 const double power = 1.0 / nr;
00865 for (int j = 0; j < jmax; ++j)
00866 {
00867 for (int i = 0; i < imax; ++i)
00868 rp[i] = T(pow(rp[i], power));
00869 rp += w;
00870 }
00871 }
00872 }
00873 return result;
00874 }
00875
00876
00877
00878
00879 template <class T>
00880 Image<T> MSTFilterFull(const Image<T>& i0, const Image<T>& i45,
00881 const Image<T>& i90, const Image<T>& i135,
00882 const bool r[8], const int dx = 6,
00883 const int dy = 6,
00884 const bool useEuclidDiag = true)
00885 {
00886 GVX_TRACE(__PRETTY_FUNCTION__);
00887
00888 ASSERT(i0.isSameSize(i45));
00889 ASSERT(i0.isSameSize(i90));
00890 ASSERT(i0.isSameSize(i135));
00891
00892 Image<T> result(i0.getDims(), ZEROS);
00893
00894 const int w = i0.getWidth(), h = i0.getHeight();
00895
00896
00897
00898
00899
00900
00901
00902
00903
00904
00905
00906
00907
00908
00909
00910
00911
00912
00913
00914
00915 int dx_diag, dy_diag;
00916
00917
00918
00919 if(useEuclidDiag)
00920 {
00921 dx_diag = (int)round(sqrt(pow(dx,2)/2.0f));
00922 dy_diag = (int)round(sqrt(pow(dy,2)/2.0f));
00923 }
00924 else
00925 {
00926 dx_diag = dx;
00927 dy_diag = dy;
00928 }
00929
00930
00931 const int o0 = dx;
00932 const int o2 = -dy*w;
00933 const int o4 = -dx;
00934 const int o6 = dy*w;
00935
00936 const int o8 = dx*2;
00937 const int o10 = -dy*w*2;
00938 const int o12 = -dx*2;
00939 const int o14 = dy*w*2;
00940
00941
00942 const int o1 = dx_diag - dy_diag*w;
00943 const int o3 = -dx_diag - dy_diag*w;
00944 const int o5 = -dx_diag + dy_diag*w;
00945 const int o7 = dx_diag + dy_diag*w;
00946
00947 const int o9 = (dx_diag - dy_diag*w)*2;
00948 const int o11 = (-dx_diag - dy_diag*w)*2;
00949 const int o13 = (-dx_diag + dy_diag*w)*2;
00950 const int o15 = (dx_diag + dy_diag*w)*2;
00951
00952
00953 typename Image<T>::const_iterator
00954 ip0 = i0.begin() + dx + dy*w, ip45 = i45.begin() + dx + dy*w,
00955 ip90 = i90.begin() + dx + dy*w, ip135 = i135.begin() + dx + dy*w;
00956 typename Image<T>::iterator rp = result.beginw() + dx + dy*w;
00957
00958
00959
00960
00961 const T max = std::numeric_limits<T>::max();
00962
00963 for (int j = (dy*2); j < h; j ++)
00964 {
00965 for (int i = (dx*2); i < w; i ++)
00966 {
00967
00968
00969 const T r0 = ip0[o0], r4 = ip0[o4], r8 = ip0[o8], r12 = ip0[o12]; ++ip0;
00970 const T r1 = ip45[o1], r5 = ip45[o5], r9 = ip45[o9], r13 = ip45[o13]; ++ip45;
00971 const T r2 = ip90[o2], r6 = ip90[o6], r10 = ip90[o10], r14 = ip90[o14]; ++ip90;
00972 const T r3 = ip135[o3], r7 = ip135[o7], r11 = ip135[o11], r15 = ip135[o15]; ++ip135;
00973
00974
00975
00976
00977 T minRel = max;
00978 if (r[0] && r0 < minRel) minRel = r0;
00979 if (r[1] && r1 < minRel) minRel = r1;
00980 if (r[2] && r2 < minRel) minRel = r2;
00981 if (r[3] && r3 < minRel) minRel = r3;
00982 if (r[4] && r4 < minRel) minRel = r4;
00983 if (r[5] && r5 < minRel) minRel = r5;
00984 if (r[6] && r6 < minRel) minRel = r6;
00985 if (r[7] && r7 < minRel) minRel = r7;
00986
00987 if (r[0] && r8 < minRel) minRel = r8;
00988 if (r[1] && r9 < minRel) minRel = r9;
00989 if (r[2] && r10 < minRel) minRel = r10;
00990 if (r[3] && r11 < minRel) minRel = r11;
00991 if (r[4] && r12 < minRel) minRel = r12;
00992 if (r[5] && r13 < minRel) minRel = r13;
00993 if (r[6] && r14 < minRel) minRel = r14;
00994 if (r[7] && r15 < minRel) minRel = r15;
00995 minRel /= 2;
00996
00997
00998 float resp = 1.0f;
00999
01000
01001
01002
01003
01004
01005
01006 if (r[0]) resp *= r0; else resp *= (minRel - r0);
01007 if (resp <= 0.0f)
01008 resp = 0.0f;
01009 else
01010 {
01011 if (r[1]) resp *= r1; else resp *= (minRel - r1);
01012 if (resp <= 0.0f)
01013 resp = 0.0f;
01014 else
01015 {
01016 if (r[2]) resp *= r2; else resp *= (minRel - r2);
01017 if (resp <= 0.0f)
01018 resp = 0.0f;
01019 else
01020 {
01021 if (r[3]) resp *= r3; else resp *= (minRel - r3);
01022 if (resp <= 0.0f)
01023 resp = 0.0f;
01024 else
01025 {
01026 if (r[4]) resp *= r4; else resp *= (minRel - r4);
01027 if (resp <= 0.0f) resp = 0.0f;
01028 else
01029 {
01030 if (r[5]) resp *= r5; else resp *= (minRel - r5);
01031 if (resp <= 0.0f) resp = 0.0f;
01032 else
01033 {
01034 if (r[6]) resp *= r6; else resp *= (minRel - r6);
01035 if (resp <= 0.0f) resp = 0.0f;
01036 else
01037 {
01038 if (r[7]) resp *= r7; else resp *= (minRel - r7);
01039 if (resp <= 0.0f) resp = 0.0f;
01040 else
01041 {
01042 if (r[0]) resp *= r8; else resp *= (minRel - r8);
01043 if (resp <= 0.0f && r8<r0)
01044 resp = 0.0f;
01045 else
01046 {
01047 if (r[1]) resp *= r9; else resp *= (minRel - r9);
01048 if (resp <= 0.0f && r9<r1)
01049 resp = 0.0f;
01050 else
01051 {
01052 if (r[2]) resp *= r10; else resp *= (minRel - r10);
01053 if (resp <= 0.0f && r10<r2)
01054 resp = 0.0f;
01055 else
01056 {
01057 if (r[3]) resp *= r11; else resp *= (minRel - r11);
01058 if (resp <= 0.0f && r11<r3)
01059 resp = 0.0f;
01060 else
01061 {
01062 if (r[4]) resp *= r12; else resp *= (minRel - r12);
01063 if (resp <= 0.0f && r12<r4) resp = 0.0f;
01064 else
01065 {
01066 if (r[5]) resp *= r13; else resp *= (minRel - r13);
01067 if (resp <= 0.0f && r13<r5) resp = 0.0f;
01068 else
01069 {
01070 if (r[6]) resp *= r14; else resp *= (minRel - r14);
01071 if (resp <= 0.0f && r14<r6) resp = 0.0f;
01072 else
01073 {
01074 if (r[7]) resp *= r15; else resp *= (minRel - r15);
01075 if (resp <= 0.0f && r15<r7) resp = 0.0f;
01076 else
01077 {
01078
01079 resp = pow(resp, 1.0/8.0);
01080 }
01081 }
01082 }
01083 }
01084 }
01085 }
01086 }
01087 }
01088
01089
01090 }
01091 }
01092 }
01093 }
01094 }
01095 }
01096 }
01097 }
01098
01099
01100 *rp++ = T(resp);
01101 }
01102
01103 ip0 += dx*2; ip45 += dx*2; ip90 += dx*2; ip135 += dx*2; rp += dx*2;
01104 }
01105
01106 return result;
01107 }
01108
01109
01110 namespace
01111 {
01112
01113 template <class DstItr, class SrcItr>
01114 inline void MSTFILT(DstItr dptr, SrcItr sptr,
01115 const int w, const int jmax, const int imax)
01116 {
01117 for(int j = 0; j < jmax; ++j)
01118 {
01119 for (int i = 0; i < imax; ++i)
01120 dptr[i] *= sptr[i];
01121
01122 sptr += w; dptr += w;
01123 }
01124 }
01125 }
01126
01127 template <class T>
01128 Image<T> MSTFilterPartial(const Image<T>& i0, const Image<T>& i45,
01129 const Image<T>& i90, const Image<T>& i135,
01130 const bool r[8], const int dx = 6,
01131 const int dy = 6,
01132 const bool useEuclidDiag = false)
01133 {
01134 GVX_TRACE(__PRETTY_FUNCTION__);
01135
01136
01137 ASSERT(i0.isSameSize(i45) && i0.isSameSize(i90) && i0.isSameSize(i135));
01138 Image<T> result(i0.getDims(), ZEROS);
01139
01140 const int w = i0.getWidth(), h = i0.getHeight();
01141
01142 int dx_diag, dy_diag;
01143
01144
01145
01146 if(useEuclidDiag)
01147 {
01148 dx_diag = (int)round(fastSqrt((dx*dx)/2.0f));
01149 dy_diag = (int)round(fastSqrt((dy*dy)/2.0f));
01150 }
01151 else
01152 {
01153 dx_diag = dx;
01154 dy_diag = dy;
01155 }
01156
01157
01158 const int o0 = dx;
01159 const int o2 = -dy*w;
01160 const int o4 = -dx;
01161 const int o6 = dy*w;
01162
01163 const int o8 = dx*2;
01164 const int o10 = -dy*w*2;
01165 const int o12 = -dx*2;
01166 const int o14 = dy*w*2;
01167
01168
01169 const int o1 = dx_diag - dy_diag*w;
01170 const int o3 = -dx_diag - dy_diag*w;
01171 const int o5 = -dx_diag + dy_diag*w;
01172 const int o7 = dx_diag + dy_diag*w;
01173
01174 const int o9 = (dx_diag - dy_diag*w)*2;
01175 const int o11 = (-dx_diag - dy_diag*w)*2;
01176 const int o13 = (-dx_diag + dy_diag*w)*2;
01177 const int o15 = (dx_diag + dy_diag*w)*2;
01178
01179 const int offset = dx + dy*w;
01180
01181 typename Image<T>::iterator const rpp = result.beginw() + offset;
01182
01183
01184 int nr = 0; for (int i = 0; i < 8; i++) if (r[i]) nr++;
01185
01186 const int imax = w - dx*2;
01187 const int jmax = h - dy*2;
01188
01189
01190 {
01191 typename Image<T>::iterator rp = rpp;
01192 for (int j = 0; j < jmax; ++j)
01193 {
01194 for (int i = 0; i < imax; ++i)
01195 rp[i] = T(1.0);
01196 rp += w;
01197 }
01198 }
01199
01200
01201
01202 {
01203 if (r[0]) MSTFILT(rpp, i0.begin() + o0 + offset, w, jmax, imax);
01204 if (r[1]) MSTFILT(rpp, i45.begin() + o1 + offset, w, jmax, imax);
01205 if (r[2]) MSTFILT(rpp, i90.begin() + o2 + offset, w, jmax, imax);
01206 if (r[3]) MSTFILT(rpp, i135.begin() + o3 + offset, w, jmax, imax);
01207 if (r[4]) MSTFILT(rpp, i0.begin() + o4 + offset, w, jmax, imax);
01208 if (r[5]) MSTFILT(rpp, i45.begin() + o5 + offset, w, jmax, imax);
01209 if (r[6]) MSTFILT(rpp, i90.begin() + o6 + offset, w, jmax, imax);
01210 if (r[7]) MSTFILT(rpp, i135.begin() + o7 + offset, w, jmax, imax);
01211
01212 if (r[0]) MSTFILT(rpp, i0.begin() + o8 + offset, w, jmax, imax);
01213 if (r[1]) MSTFILT(rpp, i45.begin() + o9 + offset, w, jmax, imax);
01214 if (r[2]) MSTFILT(rpp, i90.begin() + o10 + offset, w, jmax, imax);
01215 if (r[3]) MSTFILT(rpp, i135.begin() + o11 + offset, w, jmax, imax);
01216 if (r[4]) MSTFILT(rpp, i0.begin() + o12 + offset, w, jmax, imax);
01217 if (r[5]) MSTFILT(rpp, i45.begin() + o13 + offset, w, jmax, imax);
01218 if (r[6]) MSTFILT(rpp, i90.begin() + o14 + offset, w, jmax, imax);
01219 if (r[7]) MSTFILT(rpp, i135.begin() + o15 + offset, w, jmax, imax);
01220
01221 }
01222
01223
01224
01225
01226 {
01227 typename Image<T>::iterator rp = rpp;
01228 if (nr == 1)
01229 {
01230
01231 }
01232 else if (nr == 2)
01233 {
01234 for (int j = 0; j < jmax; ++j)
01235 {
01236 for (int i = 0; i < imax; ++i)
01237 rp[i] = T(fastSqrt(rp[i]));
01238 rp += w;
01239 }
01240 }
01241 else if (nr == 3)
01242 {
01243 for (int j = 0; j < jmax; ++j)
01244 {
01245 for (int i = 0; i < imax; ++i)
01246 rp[i] = T(cbrt(rp[i]));
01247 rp += w;
01248 }
01249 }
01250 else if (nr == 4)
01251 {
01252 for (int j = 0; j < jmax; ++j)
01253 {
01254 for (int i = 0; i < imax; ++i)
01255 rp[i] = T(fastSqrt(fastSqrt(rp[i])));
01256 rp += w;
01257 }
01258 }
01259 else
01260 {
01261 const double power = 1.0 / nr;
01262 for (int j = 0; j < jmax; ++j)
01263 {
01264 for (int i = 0; i < imax; ++i)
01265 rp[i] = T(pow(rp[i], power));
01266 rp += w;
01267 }
01268 }
01269 }
01270 return result;
01271 }
01272
01273
01274
01275
01276 template <class T>
01277 Image<typename promote_trait<T, float>::TP> gradientmag(const Image<T>& input)
01278 {
01279 GVX_TRACE(__PRETTY_FUNCTION__);
01280 typedef typename promote_trait<T, float>::TP TF;
01281
01282 Image<TF> result(input.getDims(), NO_INIT);
01283 typename Image<T>::const_iterator src = input.begin();
01284 typename Image<TF>::iterator dst = result.beginw();
01285 const int w = input.getWidth(), h = input.getHeight();
01286 TF zero = TF();
01287
01288
01289 for (int i = 0; i < w; i ++) *dst ++ = zero;
01290 src += w;
01291
01292
01293 for (int j = 1; j < h-1; j ++)
01294 {
01295
01296 *dst ++ = zero; ++ src;
01297
01298
01299 for (int i = 1; i < w-1; i ++)
01300 {
01301 TF valx = src[1] - src[-1];
01302 TF valy = src[w] - src[-w];
01303
01304 *dst++ = sqrt(valx * valx + valy * valy);
01305 ++ src;
01306 }
01307
01308
01309 *dst ++ = zero; ++ src;
01310 }
01311
01312
01313 for (int i = 0; i < w; i ++) *dst ++ = zero;
01314
01315 return result;
01316 }
01317
01318
01319 template <class T>
01320 Image<typename promote_trait<T, float>::TP> gradientori(const Image<T>& input)
01321 {
01322 GVX_TRACE(__PRETTY_FUNCTION__);
01323 typedef typename promote_trait<T, float>::TP TF;
01324
01325 Image<TF> result(input.getDims(), NO_INIT);
01326 typename Image<T>::const_iterator src = input.begin();
01327 typename Image<TF>::iterator dst = result.beginw();
01328 const int w = input.getWidth(), h = input.getHeight();
01329 TF zero = TF();
01330
01331
01332 for (int i = 0; i < w; i ++) *dst ++ = zero;
01333 src += w;
01334
01335
01336 for (int j = 1; j < h-1; j ++)
01337 {
01338
01339 *dst ++ = zero; ++ src;
01340
01341
01342 for (int i = 1; i < w-1; i ++)
01343 {
01344 TF valx = src[1] - src[-1];
01345 TF valy = src[w] - src[-w];
01346
01347 *dst++ = atan2(valy, valx);
01348 ++ src;
01349 }
01350
01351
01352 *dst ++ = zero; ++ src;
01353 }
01354
01355
01356 for (int i = 0; i < w; i ++) *dst ++ = zero;
01357
01358 return result;
01359 }
01360
01361
01362 template <class T>
01363 void gradient(const Image<T>& input,
01364 Image<typename promote_trait<T, float>::TP>& mag,
01365 Image<typename promote_trait<T, float>::TP>& ori)
01366 {
01367 GVX_TRACE(__PRETTY_FUNCTION__);
01368 typedef typename promote_trait<T, float>::TP TF;
01369
01370 mag.resize(input.getDims()); ori.resize(input.getDims());
01371 typename Image<T>::const_iterator src = input.begin();
01372 typename Image<TF>::iterator m = mag.beginw(), o = ori.beginw();
01373 const int w = input.getWidth(), h = input.getHeight();
01374 TF zero = TF();
01375
01376
01377 for (int i = 0; i < w; i ++) { *m ++ = zero; *o ++ = zero; }
01378 src += w;
01379
01380
01381 for (int j = 1; j < h-1; j ++)
01382 {
01383
01384 *m ++ = zero; *o ++ = zero; ++ src;
01385
01386
01387 for (int i = 1; i < w-1; i ++)
01388 {
01389 TF valx = src[1] - src[-1];
01390 TF valy = src[w] - src[-w];
01391
01392 *m++ = sqrt(valx * valx + valy * valy);
01393 *o++ = atan2(valy, valx);
01394 ++ src;
01395 }
01396
01397
01398 *m ++ = zero; *o ++ = zero; ++ src;
01399 }
01400
01401
01402 for (int i = 0; i < w; i ++) { *m ++ = zero; *o ++ = zero; }
01403 }
01404
01405
01406 template <class T>
01407 void gradientSobel(const Image<T>& input,
01408 Image<typename promote_trait<T, float>::TP>& mag,
01409 Image<typename promote_trait<T, float>::TP>& ori,
01410 int kernelSize)
01411 {
01412 GVX_TRACE(__PRETTY_FUNCTION__);
01413 typedef typename promote_trait<T, float>::TP TF;
01414
01415 ASSERT( (kernelSize == 3 ) | (kernelSize == 5));
01416 mag.resize(input.getDims(), true); ori.resize(input.getDims(), true);
01417 typename Image<T>::const_iterator src = input.begin();
01418 typename Image<TF>::iterator m = mag.beginw(), o = ori.beginw();
01419 const int w = input.getWidth(), h = input.getHeight();
01420 TF zero = TF();
01421
01422
01423 switch (kernelSize) {
01424 case 3:
01425 for (int i = 0; i < w; i ++) { *m ++ = zero; *o ++ = zero; }
01426 src += w;
01427 break;
01428 case 5:
01429 for (int i = 0; i < w*2; i ++) { *m ++ = zero; *o ++ = zero; }
01430 src += w*2;
01431 break;
01432 }
01433
01434 switch (kernelSize){
01435 case 3:
01436
01437 for (int j = 1; j < h-1; j ++)
01438 {
01439
01440 *m ++ = zero; *o ++ = zero; ++ src;
01441
01442 for (int i = 1; i < w-1; i ++)
01443 {
01444 TF valx = -1*src[-1*w + -1] + 0*src[-1*w + 0] + 1*src[-1*w + 1]
01445 + -2*src[ 0*w + -1] + 0*src[ 0*w + 0] + 2*src[ 0*w + 1]
01446 + -1*src[ 1*w + -1] + 0*src[ 1*w + 0] + 1*src[ 1*w + 1];
01447
01448 TF valy = 1*src[-1*w + -1] + 2*src[-1*w + 0] + 1*src[-1*w + 1]
01449 + 0*src[ 0*w + -1] + 0*src[ 0*w + 0] + 0*src[ 0*w + 1]
01450 + -1*src[ 1*w + -1] + -2*src[ 1*w + 0] + -1*src[ 1*w + 1];
01451
01452 *m++ = sqrt(valx * valx + valy * valy);
01453 *o++ = atan2(valy, valx);
01454 ++ src;
01455 }
01456
01457 *m ++ = zero; *o ++ = zero; ++ src;
01458 }
01459 break;
01460
01461 case 5:
01462
01463 for (int j = 2; j < h-2; j ++)
01464 {
01465
01466 *m ++ = zero; *o ++ = zero; ++ src;
01467 *m ++ = zero; *o ++ = zero; ++ src;
01468
01469 for (int i = 2; i < w-2; i ++)
01470 {
01471 TF valx = -1*src[-2*w + -2] + -2*src[-2*w + -1] + 0*src[-2*w + 0] + 2*src[-2*w + 1] + 1*src[-2*w + 2]
01472 + -4*src[-1*w + -2] + -8*src[-1*w + -1] + 0*src[-1*w + 0] + 8*src[-1*w + 1] + 4*src[-1*w + 2]
01473 + -6*src[ 0*w + -2] + -12*src[ 0*w + -1] + 0*src[ 0*w + 0] + 12*src[ 0*w + 1] + 6*src[ 0*w + 2]
01474 + -4*src[ 1*w + -2] + -8*src[ 1*w + -1] + 0*src[ 1*w + 0] + 8*src[ 1*w + 1] + 4*src[ 1*w + 2]
01475 + -1*src[ 2*w + -2] + -2*src[ 2*w + -1] + 0*src[ 2*w + 0] + 2*src[ 2*w + 1] + 1*src[ 2*w + 2];
01476
01477 TF valy = 1*src[-2*w + -2] + 4*src[-2*w + -1] + 6*src[-2*w + 0] + 4*src[-2*w + 1] + 1*src[-2*w + 2]
01478 + 2*src[-1*w + -2] + 8*src[-1*w + -1] + 12*src[-1*w + 0] + 8*src[-1*w + 1] + 2*src[-1*w + 2]
01479 + 0*src[ 0*w + -2] + 0*src[ 0*w + -1] + 0*src[ 0*w + 0] + 0*src[ 0*w + 1] + 0*src[ 0*w + 2]
01480 + -2*src[ 1*w + -2] + -8*src[ 1*w + -1] + -12*src[ 1*w + 0] + -8*src[ 1*w + 1] + -2*src[ 1*w + 2]
01481 + -1*src[ 2*w + -2] + -4*src[ 2*w + -1] + -6*src[ 2*w + 0] + -4*src[ 2*w + 1] + -1*src[ 2*w + 2];
01482
01483 *m++ = sqrt(valx * valx + valy * valy);
01484 *o++ = atan2(valy, valx);
01485 ++ src;
01486 }
01487
01488 *m ++ = zero; *o ++ = zero; ++ src;
01489 }
01490 break;
01491 }
01492
01493
01494
01495 switch (kernelSize){
01496 case 3:
01497 for (int i = 0; i < w; i ++) { *m ++ = zero; *o ++ = zero; }
01498 break;
01499 case 5:
01500 for (int i = 0; i < w*2; i ++) { *m ++ = zero; *o ++ = zero; }
01501 break;
01502 }
01503 }
01504
01505
01506 Image<float> nonMaxSuppr(const Image<float>& mag, const Image<float>& ori)
01507 {
01508
01509 Image<float> outImg = mag;
01510 for(int y=0; y<mag.getHeight(); y++)
01511 for(int x=0; x<mag.getWidth(); x++)
01512 {
01513 if (mag.getVal(x,y) > 0)
01514 {
01515 float t = ori.getVal(x,y);
01516
01517
01518
01519
01520
01521
01522
01523
01524
01525
01526
01527
01528
01529
01530
01531
01532
01533
01534
01535
01536
01537
01538 int dx = int(1.5*cos(t));
01539 int dy = int(1.5*sin(t));
01540
01541 if (mag.coordsOk(x+dx, y-dy) &&
01542 mag.coordsOk(x-dx, y+dy) )
01543 {
01544
01545 if (mag.getVal(x,y) < mag.getVal(x+dx, y-dy) ||
01546 mag.getVal(x,y) <= mag.getVal(x-dx, y+dy) )
01547 outImg.setVal(x,y,0);
01548
01549 }
01550
01551 }
01552 }
01553
01554 return outImg;
01555 }
01556
01557
01558 template <class T>
01559 Image<T> shuffleImage(const Image<T> &img)
01560 {
01561
01562 Image<T> result(img.getDims(), NO_INIT);
01563
01564 uint imgSize = img.getSize();
01565 for(uint i=0; i < imgSize; i++)
01566 {
01567 uint j = i + rand() / (RAND_MAX / (imgSize-i) + 1);
01568 result[j] = img[i];
01569 result[i] = img[j];
01570 }
01571
01572 return result;
01573 }
01574
01575
01576
01577 #include "inst/Image/FilterOps.I"
01578
01579
01580
01581
01582
01583