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 #ifndef IMAGE_LOWPASS_C_DEFINED
00039 #define IMAGE_LOWPASS_C_DEFINED
00040
00041 #include "Image/LowPass.H"
00042
00043 #include "Image/Convolutions.H"
00044 #include "Image/Image.H"
00045 #include "Image/Kernels.H"
00046 #include "Image/Pixels.H"
00047 #include "rutz/trace.h"
00048
00049 namespace
00050 {
00051
00052 template <class T>
00053 T median3scalar(T a, T b, T c)
00054 {
00055 if (b < a) { T t = b; b = a; a = t; }
00056 if (c < b) { T t = c; c = b; b = t; }
00057 if (b < a) { T t = b; b = a; a = t; }
00058
00059 return b;
00060 }
00061
00062
00063 template <class T>
00064 PixRGB<T> median3scalar(PixRGB<T> a, PixRGB<T> b, PixRGB<T> c)
00065 {
00066 return PixRGB<T>(median3scalar(a.p[0], b.p[0], c.p[0]),
00067 median3scalar(a.p[1], b.p[1], c.p[1]),
00068 median3scalar(a.p[2], b.p[2], c.p[2]));
00069 }
00070
00071 Image<PixRGB<float> > lowPass3x_rgb(const Image<PixRGB<float> >& src)
00072 {
00073 const int w = src.getWidth(), h = src.getHeight();
00074 if (w < 2) return src;
00075 Image<PixRGB<float> > result(w, h, NO_INIT);
00076 Image<PixRGB<float> >::const_iterator sptr = src.begin();
00077 Image<PixRGB<float> >::iterator dptr = result.beginw();
00078
00079
00080
00081
00082
00083
00084
00085
00086 for (int j = 0; j < h; j ++)
00087 {
00088
00089 dptr->setRed(sptr[0].red() * (2.0F / 3.0F)
00090 + sptr[1].red() * (1.0F / 3.0F));
00091 dptr->setGreen(sptr[0].green() * (2.0F / 3.0F)
00092 + sptr[1].green() * (1.0F / 3.0F));
00093 dptr->setBlue(sptr[0].blue() * (2.0F / 3.0F)
00094 + sptr[1].blue() * (1.0F / 3.0F));
00095 ++dptr;
00096
00097
00098 for (int i = 0; i < w - 2; i ++)
00099 {
00100 dptr->setRed((sptr[0].red() + sptr[2].red())
00101 * 0.25F + sptr[1].red() * 0.5F);
00102 dptr->setGreen((sptr[0].green() + sptr[2].green())
00103 * 0.25F + sptr[1].green() * 0.5F);
00104 dptr->setBlue((sptr[0].blue() + sptr[2].blue())
00105 * 0.25F + sptr[1].blue() * 0.5F);
00106 ++dptr;
00107 ++sptr;
00108 }
00109
00110
00111 dptr->setRed(sptr[0].red() * (1.0F / 3.0f)
00112 + sptr[1].red() * (2.0F / 3.0F));
00113 dptr->setGreen(sptr[0].green() * (1.0F / 3.0f)
00114 + sptr[1].green() * (2.0F / 3.0F));
00115 dptr->setBlue(sptr[0].blue() * (1.0F / 3.0f)
00116 + sptr[1].blue() * (2.0F / 3.0F));
00117 ++dptr;
00118 sptr += 2;
00119 }
00120 return result;
00121 }
00122
00123 Image<PixRGB<float> > lowPass3y_rgb(const Image<PixRGB<float> >& src)
00124 {
00125 const int w = src.getWidth(), h = src.getHeight();
00126 if (h < 2) return src;
00127 Image<PixRGB<float> > result(w, h, NO_INIT);
00128 Image<PixRGB<float> >::const_iterator sptr = src.begin();
00129 Image<PixRGB<float> >::iterator dptr = result.beginw();
00130 const int w2 = w * 2;
00131
00132
00133
00134 for (int i = 0; i < w; i ++)
00135 {
00136
00137 dptr->setRed(sptr[0].red() * (2.0F / 3.0F)
00138 + sptr[w].red() * (1.0F / 3.0F));
00139 dptr->setGreen(sptr[0].green() * (2.0F / 3.0F)
00140 + sptr[w].green() * (1.0F / 3.0F));
00141 dptr->setBlue(sptr[0].blue() * (2.0F / 3.0F)
00142 + sptr[w].blue() * (1.0F / 3.0F));
00143 ++dptr;
00144 ++sptr;
00145 }
00146 sptr -= w;
00147
00148
00149 for (int j = 0; j < h - 2; j ++)
00150 for (int i = 0; i < w; i ++)
00151 {
00152
00153 dptr->setRed((sptr[0].red() + sptr[w2].red())
00154 * 0.25F + sptr[w].red() * 0.5F);
00155 dptr->setGreen((sptr[0].green() + sptr[w2].green())
00156 * 0.25F + sptr[w].green() * 0.5F);
00157 dptr->setBlue((sptr[0].blue() + sptr[w2].blue())
00158 * 0.25F + sptr[w].blue() * 0.5F);
00159 ++dptr;
00160 ++sptr;
00161 }
00162
00163
00164 for (int i = 0; i < w; i ++)
00165 {
00166
00167 dptr->setRed(sptr[0].red() * (1.0F / 3.0F) + sptr[w].red()
00168 * (2.0F / 3.0F));
00169 dptr->setGreen(sptr[0].green() * (1.0F / 3.0F) + sptr[w].green()
00170 * (2.0F / 3.0F));
00171 dptr->setBlue(sptr[0].blue() * (1.0F / 3.0F) + sptr[w].blue()
00172 * (2.0F / 3.0F));
00173 ++dptr;
00174 ++sptr;
00175 }
00176
00177
00178 return result;
00179 }
00180 }
00181
00182
00183 template <>
00184 Image<promote_trait<PixRGB<float>, float>::TP>
00185 lowPass3x(const Image<PixRGB<float> >& src)
00186 {
00187 GVX_TRACE(__PRETTY_FUNCTION__);
00188 return lowPass3x_rgb(src);
00189 }
00190
00191
00192 template <class T>
00193 Image<typename promote_trait<T, float>::TP>
00194 lowPass3x(const Image<T>& src)
00195 {
00196 GVX_TRACE(__PRETTY_FUNCTION__);
00197 const int w = src.getWidth(), h = src.getHeight();
00198
00199
00200
00201
00202
00203 typedef typename promote_trait<T, float>::TP TF;
00204 const Image<TF> source = src;
00205 if (w < 2) return source;
00206 Image<TF> result(w, h, NO_INIT);
00207 typename Image<TF>::const_iterator sptr = source.begin();
00208 typename Image<TF>::iterator dptr = result.beginw();
00209
00210
00211
00212
00213
00214
00215
00216
00217 for (int j = 0; j < h; j ++)
00218 {
00219
00220 *dptr++ = sptr[0] * (2.0F / 3.0F) + sptr[1] * (1.0F / 3.0F);
00221
00222
00223 for (int i = 0; i < w - 2; i ++)
00224 {
00225 *dptr++ = (sptr[0] + sptr[2]) * 0.25F + sptr[1] * 0.5F;
00226 sptr++;
00227 }
00228
00229
00230 *dptr++ = sptr[0] * (1.0F / 3.0F) + sptr[1] * (2.0F / 3.0F);
00231 sptr += 2;
00232 }
00233 return result;
00234 }
00235
00236
00237 template <>
00238 Image<promote_trait<PixRGB<float>, float>::TP>
00239 lowPass3y(const Image<PixRGB<float> >& src)
00240 {
00241 GVX_TRACE(__PRETTY_FUNCTION__);
00242 return lowPass3y_rgb(src);
00243 }
00244
00245
00246 template <class T>
00247 Image<typename promote_trait<T, float>::TP>
00248 lowPass3y(const Image<T>& src)
00249 {
00250 GVX_TRACE(__PRETTY_FUNCTION__);
00251 const int w = src.getWidth(), h = src.getHeight();
00252
00253
00254
00255
00256
00257 typedef typename promote_trait<T, float>::TP TF;
00258 const Image<TF> source = src;
00259 if (h < 2) return source;
00260 Image<TF> result(w, h, NO_INIT);
00261 typename Image<TF>::const_iterator sptr = source.begin();
00262 typename Image<TF>::iterator dptr = result.beginw();
00263 const int w2 = w * 2;
00264
00265
00266
00267 for (int i = 0; i < w; i ++)
00268 {
00269 *dptr++ = sptr[0] * (2.0F / 3.0F) + sptr[w] * (1.0F / 3.0F);
00270 sptr++;
00271 }
00272 sptr -= w;
00273
00274
00275 for (int j = 0; j < h - 2; j ++)
00276 for (int i = 0; i < w; i ++)
00277 {
00278 *dptr++ = (sptr[0] + sptr[w2]) * 0.25F + sptr[w] * 0.5F;
00279 sptr++;
00280 }
00281
00282
00283 for (int i = 0; i < w; i ++)
00284 {
00285 *dptr++ = sptr[0] * (1.0F / 3.0F) + sptr[w] * (2.0F / 3.0F);
00286 sptr++;
00287 }
00288
00289
00290 return result;
00291 }
00292
00293
00294 template <class T>
00295 Image<typename promote_trait<T, float>::TP>
00296 lowPass5x(const Image<T>& src)
00297 {
00298 GVX_TRACE(__PRETTY_FUNCTION__);
00299 const int w = src.getWidth(), h = src.getHeight();
00300
00301
00302
00303
00304
00305 typedef typename promote_trait<T, float>::TP TF;
00306 const Image<TF> source = src;
00307 if (w < 2) return source;
00308 Image<TF> result(w, h, NO_INIT);
00309 typename Image<TF>::const_iterator sptr = source.begin();
00310 typename Image<TF>::iterator dptr = result.beginw();
00311
00312 if (w == 2)
00313 for (int j = 0; j < h; j ++)
00314 {
00315
00316 *dptr++ = sptr[0] * (6.0F / 10.0F) + sptr[1] * (4.0F / 10.0F);
00317
00318
00319 *dptr++ = sptr[0] * (4.0F / 10.0F) + sptr[1] * (6.0F / 10.0F);
00320
00321 sptr += 2;
00322 }
00323 else if (w == 3)
00324 for (int j = 0; j < h; j ++)
00325 {
00326
00327 *dptr++ = sptr[0] * (6.0F / 11.0F) +
00328 sptr[1] * (4.0F / 11.0F) +
00329 sptr[2] * (1.0F / 11.0F);
00330
00331
00332 *dptr++ = (sptr[0] + sptr[2]) * (4.0F / 14.0F) +
00333 sptr[1] * (6.0F / 14.0F);
00334
00335
00336 *dptr++ = sptr[0] * (1.0F / 11.0F) +
00337 sptr[1] * (4.0F / 11.0F) +
00338 sptr[2] * (6.0F / 11.0F);
00339
00340 sptr += 3;
00341 }
00342 else
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352 for (int j = 0; j < h; j ++)
00353 {
00354
00355 *dptr++ = sptr[0] * (6.0F / 11.0F) +
00356 sptr[1] * (4.0F / 11.0F) +
00357 sptr[2] * (1.0F / 11.0F);
00358
00359
00360 *dptr++ = (sptr[0] + sptr[2]) * (4.0F / 15.0F) +
00361 sptr[1] * (6.0F / 15.0F) +
00362 sptr[3] * (1.0F / 15.0F);
00363
00364
00365 for (int i = 0; i < w - 4; i ++)
00366 {
00367 *dptr++ = (sptr[0] + sptr[4]) * (1.0F / 16.0F) +
00368 (sptr[1] + sptr[3]) * (4.0F / 16.0F) +
00369 sptr[2] * (6.0F / 16.0F);
00370 sptr++;
00371 }
00372
00373
00374 *dptr++ = sptr[0] * (1.0F / 15.0F) +
00375 (sptr[1] + sptr[3]) * (4.0F / 15.0F) +
00376 sptr[2] * (6.0F / 15.0F);
00377 sptr++;
00378
00379
00380 *dptr++ = sptr[0] * (1.0F / 11.0F) +
00381 sptr[1] * (4.0F / 11.0F) +
00382 sptr[2] * (6.0F / 11.0F);
00383 sptr += 3;
00384 }
00385 return result;
00386 }
00387
00388
00389 template <class T>
00390 Image<typename promote_trait<T, float>::TP>
00391 lowPass5y(const Image<T>& src)
00392 {
00393 GVX_TRACE(__PRETTY_FUNCTION__);
00394 const int w = src.getWidth(), h = src.getHeight();
00395
00396
00397
00398
00399
00400 typedef typename promote_trait<T, float>::TP TF;
00401 const Image<TF> source = src;
00402 if (h < 2) return source;
00403 Image<TF> result(w, h, NO_INIT);
00404 typename Image<TF>::const_iterator sptr = source.begin();
00405 typename Image<TF>::iterator dptr = result.beginw();
00406
00407
00408 const int w2 = w * 2, w3 = w * 3, w4 = w * 4;
00409
00410 if (h == 2)
00411 {
00412
00413 for (int i = 0; i < w; i ++)
00414 {
00415 *dptr++ = sptr[0] * (6.0F / 10.0F) +
00416 sptr[w] * (4.0F / 10.0F);
00417 sptr++;
00418 }
00419 sptr -= w;
00420
00421
00422 for (int i = 0; i < w; i ++)
00423 {
00424 *dptr++ = sptr[0] * (4.0F / 10.0F) +
00425 sptr[w] * (6.0F / 10.0F);
00426 sptr++;
00427 }
00428 }
00429 else if (h == 3)
00430 {
00431
00432 for (int i = 0; i < w; i ++)
00433 {
00434 *dptr++ = sptr[ 0] * (6.0F / 11.0F) +
00435 sptr[ w] * (4.0F / 11.0F) +
00436 sptr[w2] * (1.0F / 11.0F);
00437 sptr++;
00438 }
00439 sptr -= w;
00440
00441
00442 for (int i = 0; i < w; i ++)
00443 {
00444 *dptr++ = (sptr[ 0] + sptr[w2]) * (4.0F / 14.0F) +
00445 sptr[ w] * (6.0F / 14.0F);
00446 sptr++;
00447 }
00448 sptr -= w;
00449
00450
00451 for (int i = 0; i < w; i ++)
00452 {
00453 *dptr++ = sptr[ 0] * (1.0F / 11.0F) +
00454 sptr[ w] * (4.0F / 11.0F) +
00455 sptr[w2] * (6.0F / 11.0F);
00456 sptr++;
00457 }
00458 }
00459 else
00460 {
00461
00462 for (int i = 0; i < w; i ++)
00463 {
00464 *dptr++ = sptr[ 0] * (6.0F / 11.0F) +
00465 sptr[ w] * (4.0F / 11.0F) +
00466 sptr[w2] * (1.0F / 11.0F);
00467 sptr++;
00468 }
00469 sptr -= w;
00470
00471
00472 for (int i = 0; i < w; i ++)
00473 {
00474 *dptr++ = (sptr[ 0] + sptr[w2]) * (4.0F / 15.0F) +
00475 sptr[ w] * (6.0F / 15.0F) +
00476 sptr[w3] * (1.0F / 15.0F);
00477 sptr++;
00478 }
00479 sptr -= w;
00480
00481
00482 for (int j = 0; j < h - 4; j ++)
00483 for (int i = 0; i < w; i ++)
00484 {
00485 *dptr++ = (sptr[ 0] + sptr[w4]) * (1.0F / 16.0F) +
00486 (sptr[ w] + sptr[w3]) * (4.0F / 16.0F) +
00487 sptr[w2] * (6.0F / 16.0F);
00488 sptr++;
00489 }
00490
00491
00492 for (int i = 0; i < w; i ++)
00493 {
00494 *dptr++ = sptr[ 0] * (1.0F / 15.0F) +
00495 (sptr[ w] + sptr[w3]) * (4.0F / 15.0F) +
00496 sptr[w2] * (6.0F / 15.0F);
00497 sptr++;
00498 }
00499
00500
00501 for (int i = 0; i < w; i ++)
00502 {
00503 *dptr++ = sptr[ 0] * (1.0F / 11.0F) +
00504 sptr[ w] * (4.0F / 11.0F) +
00505 sptr[w2] * (6.0F / 11.0F);
00506 sptr++;
00507 }
00508
00509 }
00510 return result;
00511 }
00512
00513
00514 template <class T>
00515 Image<typename promote_trait<T, float>::TP>
00516 lowPass5xDecX(const Image<T>& src, const int factor)
00517 {
00518 GVX_TRACE(__PRETTY_FUNCTION__);
00519 ASSERT(factor > 0);
00520
00521
00522 if (factor == 1) return lowPass5x(src);
00523
00524
00525 const int w = src.getWidth(), h = src.getHeight();
00526 int w2 = w / factor;
00527 if (w2 == 0) w2 = 1;
00528
00529
00530
00531
00532
00533
00534 typedef typename promote_trait<T, float>::TP TF;
00535 const Image<TF> source = src;
00536 if (w < 2) return source;
00537
00538 Image<TF> result(w2, h, NO_INIT);
00539 typename Image<TF>::const_iterator sptr = source.begin();
00540 typename Image<TF>::iterator dptr = result.beginw();
00541
00542 if (w == 2)
00543 for (int j = 0; j < h; j ++)
00544 {
00545
00546 *dptr++ = sptr[0] * (6.0F / 10.0F) + sptr[1] * (4.0F / 10.0F);
00547
00548 sptr += 2;
00549 }
00550 else if (w == 3)
00551 for (int j = 0; j < h; j ++)
00552 {
00553
00554
00555 *dptr++ = sptr[0] * (6.0F / 11.0F) +
00556 sptr[1] * (4.0F / 11.0F) +
00557 sptr[2] * (1.0F / 11.0F);
00558
00559
00560
00561 sptr += 3;
00562 }
00563 else
00564
00565
00566
00567
00568
00569
00570
00571
00572
00573 for (int j = 0; j < h; j ++)
00574 {
00575 int i1 = 0, i2 = 0;
00576 typename Image<TF>::const_iterator sptr2 = sptr;
00577
00578
00579
00580 *dptr++ = sptr2[0] * (6.0F / 11.0F) +
00581 sptr2[1] * (4.0F / 11.0F) +
00582 sptr2[2] * (1.0F / 11.0F);
00583 ++i2;
00584 i1 += factor;
00585
00586
00587 sptr2 += (factor-2);
00588
00589
00590 while ((i1 < (w-2)) && (i2 < w2))
00591 {
00592 *dptr++ = (sptr2[0] + sptr2[4]) * (1.0F / 16.0F) +
00593 (sptr2[1] + sptr2[3]) * (4.0F / 16.0F) +
00594 sptr2[2] * (6.0F / 16.0F);
00595 i1 += factor; sptr2 += factor;
00596 ++i2;
00597 }
00598
00599
00600 if ((i2 < w2) && (i1 == (w-2)))
00601 {
00602 sptr2 = sptr + w - 4;
00603
00604 *dptr++ = sptr2[0] * (1.0F / 15.0F) +
00605 (sptr2[1] + sptr2[3]) * (4.0F / 15.0F) +
00606 sptr2[2] * (6.0F / 15.0F);
00607 i1 += factor;
00608 ++i2;
00609 }
00610
00611
00612 if ((i2 < w2) && (i1 == (w-1)))
00613 {
00614 sptr2 = sptr + w - 3;
00615
00616 *dptr++ = sptr2[0] * (1.0F / 11.0F) +
00617 sptr2[1] * (4.0F / 11.0F) +
00618 sptr2[2] * (6.0F / 11.0F);
00619 ++i2;
00620 }
00621 sptr += w;
00622 }
00623 return result;
00624 }
00625
00626
00627 template <class T>
00628 Image<typename promote_trait<T, float>::TP>
00629 lowPass5yDecY(const Image<T>& src, const int factor)
00630 {
00631 GVX_TRACE(__PRETTY_FUNCTION__);
00632 ASSERT(factor > 0);
00633
00634
00635 if (factor == 1) return lowPass5y(src);
00636
00637
00638 const int w = src.getWidth(), h = src.getHeight();
00639 int h2 = h / factor;
00640 if (h2 == 0) h2 = 1;
00641
00642
00643
00644
00645
00646
00647 typedef typename promote_trait<T, float>::TP TF;
00648 const Image<TF> source = src;
00649 if (h < 2) return source;
00650
00651 Image<TF> result(w, h2, NO_INIT);
00652 typename Image<TF>::const_iterator sptr = source.begin();
00653 typename Image<TF>::iterator dptr = result.beginw();
00654
00655
00656 const int w2 = w * 2, w3 = w * 3, w4 = w * 4;
00657
00658 if (h == 2)
00659 {
00660
00661 for (int i = 0; i < w; i ++)
00662 {
00663 *dptr++ = sptr[0] * (6.0F / 10.0F) + sptr[w] * (4.0F / 10.0F);
00664 sptr++;
00665 }
00666 sptr -= w;
00667 }
00668 else if (h == 3)
00669 {
00670
00671 for (int i = 0; i < w; i ++)
00672 {
00673 *dptr++ = sptr[ 0] * (6.0F / 11.0F) +
00674 sptr[ w] * (4.0F / 11.0F) +
00675 sptr[w2] * (1.0F / 11.0F);
00676 sptr++;
00677 }
00678 sptr -= w;
00679
00680
00681 }
00682 else
00683 {
00684 int i1 = 0, i2 = 0;
00685 const int skip = (factor - 1) * w;
00686
00687
00688 for (int i = 0; i < w; i ++)
00689 {
00690 *dptr++ = sptr[ 0] * (6.0F / 11.0F) +
00691 sptr[ w] * (4.0F / 11.0F) +
00692 sptr[w2] * (1.0F / 11.0F);
00693 sptr++;
00694 }
00695 sptr -= w;
00696 ++i2;
00697 i1 += factor;
00698
00699
00700 sptr += (skip - w);
00701
00702
00703 while((i1 < (h-2)) && (i2 < h2))
00704 {
00705 for (int i = 0; i < w; i ++)
00706 {
00707 *dptr++ = (sptr[ 0] + sptr[w4]) * (1.0F / 16.0F) +
00708 (sptr[ w] + sptr[w3]) * (4.0F / 16.0F) +
00709 sptr[w2] * (6.0F / 16.0F);
00710 sptr++;
00711 }
00712 sptr += skip;
00713 i1 += factor;
00714 ++ i2;
00715 }
00716
00717
00718 if ((i2 < h2) && (i1 == (h-2)))
00719 {
00720 sptr = source.end() - w4;
00721
00722 for (int i = 0; i < w; i ++)
00723 {
00724 *dptr++ = sptr[ 0] * (1.0F / 15.0F) +
00725 (sptr[ w] + sptr[w3]) * (4.0F / 15.0F) +
00726 sptr[w2] * (6.0F / 15.0F);
00727 sptr++;
00728 }
00729 i1 += factor;
00730 ++i2;
00731 }
00732
00733
00734 if ((i2 < h2) && (i1 == (h-1)))
00735 {
00736 sptr = source.end() - w3;
00737
00738 for (int i = 0; i < w; i ++)
00739 {
00740 *dptr++ = sptr[ 0] * (1.0F / 11.0F) +
00741 sptr[ w] * (4.0F / 11.0F) +
00742 sptr[w2] * (6.0F / 11.0F);
00743 sptr++;
00744 }
00745 }
00746 }
00747 return result;
00748 }
00749
00750
00751 template <class T>
00752 Image<typename promote_trait<T, float>::TP>
00753 lowPass9x(const Image<T>& src)
00754 {
00755 GVX_TRACE(__PRETTY_FUNCTION__);
00756 const int w = src.getWidth(), h = src.getHeight();
00757
00758
00759
00760
00761
00762 typedef typename promote_trait<T, float>::TP TF;
00763 const Image<TF> source = src;
00764 if (w < 2) return source;
00765 Image<TF> result(w, h, NO_INIT);
00766 typename Image<TF>::const_iterator sptr = source.begin();
00767 typename Image<TF>::iterator dptr = result.beginw();
00768
00769 if (w < 9)
00770 {
00771 float kernel[9] = { 1.0F / 256.0F, 8.0F / 256.0F, 28.0F / 256.0F,
00772 56.0F / 256.0F, 70.0F / 256.0F, 56.0F / 256.0F,
00773 28.0F / 256.0F, 8.0F / 256.0F, 1.0F / 256.0F };
00774 return sepFilter(src, kernel, NULL, 9, 0,
00775 CONV_BOUNDARY_CLEAN);
00776 }
00777
00778
00779 for (int j = 0; j < h; j ++)
00780 {
00781
00782 *dptr++ = sptr[0] * (70.0F / 163.0F) +
00783 sptr[1] * (56.0F / 163.0F) +
00784 sptr[2] * (28.0F / 163.0F) +
00785 sptr[3] * ( 8.0F / 163.0F) +
00786 sptr[4] * ( 1.0F / 163.0F);
00787 *dptr++ = (sptr[0] + sptr[2]) * (56.0F / 219.0F) +
00788 sptr[1] * (70.0F / 219.0F) +
00789 sptr[3] * (28.0F / 219.0F) +
00790 sptr[4] * ( 8.0F / 219.0F) +
00791 sptr[5] * ( 1.0F / 219.0F);
00792 *dptr++ = (sptr[0] + sptr[4]) * (28.0F / 247.0F) +
00793 (sptr[1] + sptr[3]) * (56.0F / 247.0F) +
00794 sptr[2] * (70.0F / 247.0F) +
00795 sptr[5] * ( 8.0F / 247.0F) +
00796 sptr[6] * ( 1.0F / 247.0F);
00797 *dptr++ = (sptr[0] + sptr[6]) * ( 8.0F / 255.0F) +
00798 (sptr[1] + sptr[5]) * (28.0F / 255.0F) +
00799 (sptr[2] + sptr[4]) * (56.0F / 255.0F) +
00800 sptr[3] * (70.0F / 255.0F) +
00801 sptr[7] * ( 1.0F / 255.0F);
00802
00803
00804 for (int i = 0; i < w - 8; i ++)
00805 {
00806 *dptr++ = (sptr[0] + sptr[8]) * ( 1.0F / 256.0F) +
00807 (sptr[1] + sptr[7]) * ( 8.0F / 256.0F) +
00808 (sptr[2] + sptr[6]) * (28.0F / 256.0F) +
00809 (sptr[3] + sptr[5]) * (56.0F / 256.0F) +
00810 sptr[4] * (70.0F / 256.0F);
00811 sptr ++;
00812 }
00813
00814
00815 *dptr++ = sptr[0] * ( 1.0F / 255.0F) +
00816 (sptr[1] + sptr[7]) * ( 8.0F / 255.0F) +
00817 (sptr[2] + sptr[6]) * (28.0F / 255.0F) +
00818 (sptr[3] + sptr[5]) * (56.0F / 255.0F) +
00819 sptr[4] * (70.0F / 255.0F);
00820 sptr ++;
00821 *dptr++ = sptr[0] * ( 1.0F / 247.0F) +
00822 sptr[1] * ( 8.0F / 247.0F) +
00823 (sptr[2] + sptr[6]) * (28.0F / 247.0F) +
00824 (sptr[3] + sptr[5]) * (56.0F / 247.0F) +
00825 sptr[4] * (70.0F / 247.0F);
00826 sptr ++;
00827 *dptr++ = sptr[0] * ( 1.0F / 219.0F) +
00828 sptr[1] * ( 8.0F / 219.0F) +
00829 sptr[2] * (28.0F / 219.0F) +
00830 (sptr[3] + sptr[5]) * (56.0F / 219.0F) +
00831 sptr[4] * (70.0F / 219.0F);
00832 sptr ++;
00833 *dptr++ = sptr[0] * ( 1.0F / 163.0F) +
00834 sptr[1] * ( 8.0F / 163.0F) +
00835 sptr[2] * (28.0F / 163.0F) +
00836 sptr[3] * (56.0F / 163.0F) +
00837 sptr[4] * (70.0F / 163.0F);
00838 sptr += 5;
00839 }
00840 return result;
00841 }
00842
00843
00844 template <class T>
00845 Image<typename promote_trait<T, float>::TP>
00846 lowPass9y(const Image<T>& src)
00847 {
00848 GVX_TRACE(__PRETTY_FUNCTION__);
00849 const int w = src.getWidth(), h = src.getHeight();
00850
00851
00852
00853
00854
00855 typedef typename promote_trait<T, float>::TP TF;
00856 const Image<TF> source = src;
00857 if (h < 2) return source;
00858 Image<TF> result(w, h, NO_INIT);
00859 typename Image<TF>::const_iterator sptr = source.begin();
00860 typename Image<TF>::iterator dptr = result.beginw();
00861
00862 if (h < 9)
00863 {
00864 float kernel[9] = { 1.0F / 256.0F, 8.0F / 256.0F, 28.0F / 256.0F,
00865 56.0F / 256.0F, 70.0F / 256.0F, 56.0F / 256.0F,
00866 28.0F / 256.0F, 8.0F / 256.0F, 1.0F / 256.0F };
00867 return sepFilter(src, NULL, kernel, 0, 9,
00868 CONV_BOUNDARY_CLEAN);
00869 }
00870
00871
00872 const int w2 = w + w, w3 = w2 + w, w4 = w3 + w, w5 = w4 + w, w6 = w5 + w,
00873 w7 = w6 + w, w8 = w7 + w;
00874 for (int i = 0; i < w; i ++)
00875 {
00876 *dptr++ = sptr[ 0] * (70.0F / 163.0F) +
00877 sptr[ w] * (56.0F / 163.0F) +
00878 sptr[w2] * (28.0F / 163.0F) +
00879 sptr[w3] * ( 8.0F / 163.0F) +
00880 sptr[w4] * ( 1.0F / 163.0F);
00881 sptr ++;
00882 }
00883 sptr -= w;
00884 for (int i = 0; i < w; i ++)
00885 {
00886 *dptr++ = (sptr[ 0] + sptr[w2]) * (56.0F / 219.0F) +
00887 sptr[ w] * (70.0F / 219.0F) +
00888 sptr[w3] * (28.0F / 219.0F) +
00889 sptr[w4] * ( 8.0F / 219.0F) +
00890 sptr[w5] * ( 1.0F / 219.0F);
00891 sptr ++;
00892 }
00893 sptr -= w;
00894 for (int i = 0; i < w; i ++)
00895 {
00896 *dptr++ = (sptr[ 0] + sptr[w4]) * (28.0F / 247.0F) +
00897 (sptr[ w] + sptr[w3]) * (56.0F / 247.0F) +
00898 sptr[w2] * (70.0F / 247.0F) +
00899 sptr[w5] * ( 8.0F / 247.0F) +
00900 sptr[w6] * ( 1.0F / 247.0F);
00901 sptr ++;
00902 }
00903 sptr -= w;
00904 for (int i = 0; i < w; i ++)
00905 {
00906 *dptr++ = (sptr[ 0] + sptr[w6]) * ( 8.0F / 255.0F) +
00907 (sptr[ w] + sptr[w5]) * (28.0F / 255.0F) +
00908 (sptr[w2] + sptr[w4]) * (56.0F / 255.0F) +
00909 sptr[w3] * (70.0F / 255.0F) +
00910 sptr[w7] * ( 1.0F / 255.0F);
00911 sptr ++;
00912 }
00913 sptr -= w;
00914 for (int j = 0; j < h - 8; j ++)
00915 for (int i = 0; i < w; i ++)
00916 {
00917 *dptr++ = (sptr[ 0] + sptr[w8]) * ( 1.0F / 256.0F) +
00918 (sptr[ w] + sptr[w7]) * ( 8.0F / 256.0F) +
00919 (sptr[w2] + sptr[w6]) * (28.0F / 256.0F) +
00920 (sptr[w3] + sptr[w5]) * (56.0F / 256.0F) +
00921 sptr[w4] * (70.0F / 256.0F);
00922 sptr ++;
00923 }
00924 for (int i = 0; i < w; i ++)
00925 {
00926 *dptr++ = sptr[ 0] * ( 1.0F / 255.0F) +
00927 (sptr[ w] + sptr[w7]) * ( 8.0F / 255.0F) +
00928 (sptr[w2] + sptr[w6]) * (28.0F / 255.0F) +
00929 (sptr[w3] + sptr[w5]) * (56.0F / 255.0F) +
00930 sptr[w4] * (70.0F / 255.0F);
00931 sptr ++;
00932 }
00933 for (int i = 0; i < w; i ++)
00934 {
00935 *dptr++ = sptr[ 0] * ( 1.0F / 247.0F) +
00936 sptr[ w] * ( 8.0F / 247.0F) +
00937 (sptr[w2] + sptr[w6]) * (28.0F / 247.0F) +
00938 (sptr[w3] + sptr[w5]) * (56.0F / 247.0F) +
00939 sptr[w4] * (70.0F / 247.0F);
00940 sptr ++;
00941 }
00942 for (int i = 0; i < w; i ++)
00943 {
00944 *dptr++ = sptr[ 0] * ( 1.0F / 219.0F) +
00945 sptr[ w] * ( 8.0F / 219.0F) +
00946 sptr[w2] * (28.0F / 219.0F) +
00947 (sptr[w3] + sptr[w5]) * (56.0F / 219.0F) +
00948 sptr[w4] * (70.0F / 219.0F);
00949 sptr ++;
00950 }
00951 for (int i = 0; i < w; i ++)
00952 {
00953 *dptr++ = sptr[ 0] * ( 1.0F / 163.0F) +
00954 sptr[ w] * ( 8.0F / 163.0F) +
00955 sptr[w2] * (28.0F / 163.0F) +
00956 sptr[w3] * (56.0F / 163.0F) +
00957 sptr[w4] * (70.0F / 163.0F);
00958 sptr ++;
00959 }
00960 return result;
00961 }
00962
00963
00964 template <class T>
00965 Image<typename promote_trait<T, float>::TP>
00966 lowPass3(const Image<T>& src, const bool go_x, const bool go_y)
00967 {
00968 Image<typename promote_trait<T, float>::TP> result = src;
00969 if (go_x) result = lowPass3x(result);
00970 if (go_y) result = lowPass3y(result);
00971 return result;
00972 }
00973
00974
00975 template <class T>
00976 Image<typename promote_trait<T, float>::TP>
00977 lowPass5(const Image<T>& src, const bool go_x, const bool go_y)
00978 {
00979 Image<typename promote_trait<T, float>::TP> result = src;
00980 if (go_x) result = lowPass5x(result);
00981 if (go_y) result = lowPass5y(result);
00982 return result;
00983 }
00984
00985
00986 template <class T>
00987 Image<typename promote_trait<T, float>::TP>
00988 lowPass9(const Image<T>& src, const bool go_x, const bool go_y)
00989 {
00990 Image<typename promote_trait<T, float>::TP> result = src;
00991 if (go_x) result = lowPass9x(result);
00992 if (go_y) result = lowPass9y(result);
00993 return result;
00994 }
00995
00996
00997 template <class T>
00998 Image<typename promote_trait<T, float>::TP>
00999 lowPass(const int N, const Image<T>& src,
01000 const bool go_x = true, const bool go_y = true)
01001 {
01002 Image<typename promote_trait<T, float>::TP> result = src;
01003 if (go_x) result = lowPassX(N, result);
01004 if (go_y) result = lowPassY(N, result);
01005 return result;
01006 }
01007
01008
01009 template <class T>
01010 Image<typename promote_trait<T, float>::TP>
01011 lowPassX(const int N, const Image<T>& src)
01012 {
01013 GVX_TRACE(__PRETTY_FUNCTION__);
01014 switch (N)
01015 {
01016 case 3: return lowPass3x(src);
01017 case 5: return lowPass5x(src);
01018 case 9: return lowPass9x(src);
01019 default: break;
01020 }
01021
01022 const Image<float> kern = binomialKernel(N);
01023 ASSERT(kern.getWidth() == N);
01024 ASSERT(kern.getHeight() == 1);
01025 return sepFilter(src, kern.getArrayPtr(), NULL, N, 0,
01026 CONV_BOUNDARY_CLEAN);
01027 }
01028
01029
01030 template <class T>
01031 Image<typename promote_trait<T, float>::TP>
01032 lowPassY(const int N, const Image<T>& src)
01033 {
01034 GVX_TRACE(__PRETTY_FUNCTION__);
01035 switch (N)
01036 {
01037 case 3: return lowPass3y(src);
01038 case 5: return lowPass5y(src);
01039 case 9: return lowPass9y(src);
01040 default: break;
01041 }
01042
01043 const Image<float> kern = binomialKernel(N);
01044 ASSERT(kern.getWidth() == N);
01045 ASSERT(kern.getHeight() == 1);
01046 return sepFilter(src, NULL, kern.getArrayPtr(), 0, N,
01047 CONV_BOUNDARY_CLEAN);
01048 }
01049
01050
01051 template <class T>
01052 Image<T> median3x(const Image<T>& in)
01053 {
01054 if (in.getWidth() < 3) return in;
01055
01056 const int w = in.getWidth();
01057 const int h = in.getHeight();
01058
01059 Image<T> result(in.getDims(), NO_INIT);
01060
01061 typename Image<T>::const_iterator sptr = in.begin();
01062 typename Image<T>::iterator dptr = result.beginw();
01063
01064 for (int y = 0; y < h; ++y)
01065 for (int x = 0; x < w; ++x)
01066 {
01067 if (x == 0 || x == w-1)
01068 *dptr = *sptr;
01069 else
01070 *dptr = median3scalar(sptr[-1], sptr[0], sptr[1]);
01071
01072 ++dptr;
01073 ++sptr;
01074 }
01075
01076 return result;
01077 }
01078
01079
01080 template <class T>
01081 Image<T> median3y(const Image<T>& in)
01082 {
01083 if (in.getHeight() < 3) return in;
01084
01085 const int w = in.getWidth();
01086 const int h = in.getHeight();
01087
01088 Image<T> result(in.getDims(), NO_INIT);
01089
01090 typename Image<T>::const_iterator sptr = in.begin();
01091 typename Image<T>::iterator dptr = result.beginw();
01092
01093 for (int y = 0; y < h; ++y)
01094 {
01095 if (y == 0 || y == h-1)
01096 for (int x = 0; x < w; ++x)
01097 *dptr++ = *sptr++;
01098 else
01099 for (int x = 0; x < w; ++x)
01100 {
01101 *dptr = median3scalar(sptr[-w], sptr[0], sptr[w]);
01102
01103 ++dptr;
01104 ++sptr;
01105 }
01106 }
01107
01108 return result;
01109 }
01110
01111
01112 template <class T>
01113 Image<T> median3(const Image<T>& in, bool go_x, bool go_y)
01114 {
01115 Image<T> result = in;
01116 if (go_x) result = median3x(result);
01117 if (go_y) result = median3y(result);
01118 return result;
01119 }
01120
01121
01122 template <class T>
01123 Image<typename promote_trait<T, float>::TP>
01124 convGauss(const Image<T>& src, const float sigmaX, const float sigmaY,
01125 const float threshperc)
01126 {
01127 GVX_TRACE(__PRETTY_FUNCTION__);
01128 Image<typename promote_trait<T, float>::TP> result = src;
01129 Image <float> kernel;
01130 if (sigmaX > 0.0)
01131 {
01132 kernel = gaussian<float>(0.0F, sigmaX, result.getWidth(),threshperc);
01133 result = sepFilter(result, kernel, Image<float>(),
01134 CONV_BOUNDARY_CLEAN);
01135 }
01136 if (sigmaY > 0.0)
01137 {
01138 kernel = gaussian<float>(0.0F, sigmaY, src.getHeight(), threshperc);
01139 result = sepFilter(result, Image<float>(), kernel,
01140 CONV_BOUNDARY_CLEAN);
01141 }
01142 return result;
01143 }
01144
01145
01146 #include "inst/Image/LowPass.I"
01147
01148 template
01149 Image<promote_trait<double, float>::TP>
01150 lowPass3(const Image<double>& src, const bool, const bool);
01151
01152 template
01153 Image<promote_trait<double, float>::TP>
01154 lowPass5(const Image<double>& src, const bool, const bool);
01155
01156 template
01157 Image<promote_trait<double, float>::TP>
01158 lowPass3x(const Image<double>& src);
01159
01160 template
01161 Image<promote_trait<double, float>::TP>
01162 lowPass3y(const Image<double>& src);
01163
01164 template
01165 Image<promote_trait<double, float>::TP>
01166 lowPass5x(const Image<double>& src);
01167
01168 template
01169 Image<promote_trait<double, float>::TP>
01170 lowPass5y(const Image<double>& src);
01171
01172
01173
01174
01175
01176
01177
01178
01179 #endif // IMAGE_LOWPASS_C_DEFINED