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/PyrBuilder.H"
00039
00040 #include "Image/Image.H"
00041 #include "Image/ImageSet.H"
00042 #include "Image/ColorOps.H"
00043 #include "Image/CutPaste.H"
00044 #include "Image/FilterOps.H"
00045 #include "Image/MathOps.H"
00046 #include "Image/ShapeOps.H"
00047 #include "Image/Pixels.H"
00048 #include "Image/PyramidCache.H"
00049 #include "Image/PyramidOps.H"
00050 #include "rutz/trace.h"
00051
00052
00053
00054
00055
00056
00057 template <class T>
00058 PyrBuilder<T>::PyrBuilder()
00059 {
00060 GVX_TRACE(__PRETTY_FUNCTION__);
00061 }
00062
00063
00064 template <class T>
00065 PyrBuilder<T>::~PyrBuilder()
00066 {
00067 GVX_TRACE(__PRETTY_FUNCTION__);
00068 }
00069
00070
00071 template <class T>
00072 void PyrBuilder<T>::reset()
00073 {
00074 GVX_TRACE(__PRETTY_FUNCTION__);
00075 }
00076
00077
00078
00079
00080
00081 template <class T>
00082 GaussianPyrBuilder<T>::GaussianPyrBuilder(int filter_size) :
00083 PyrBuilder<T>(), itsFiltSize(filter_size)
00084 {
00085 GVX_TRACE(__PRETTY_FUNCTION__);
00086 }
00087
00088 template <class T>
00089 ImageSet<T> GaussianPyrBuilder<T>::build(const Image<T>& img,
00090 const int firstlevel,
00091 const int depth,
00092 PyramidCache<T>* cache)
00093 {
00094 GVX_TRACE(__PRETTY_FUNCTION__);
00095
00096 const ImageSet<T>* const cached =
00097 (cache != 0 && itsFiltSize == 5)
00098 ? cache->gaussian5.get(img)
00099 : 0;
00100
00101 return (cached != 0)
00102 ? *cached
00103 : buildPyrGaussian(img, firstlevel, depth, itsFiltSize);
00104 }
00105
00106 template <class T> inline
00107 GaussianPyrBuilder<T>* GaussianPyrBuilder<T>::clone() const
00108 {
00109 GVX_TRACE(__PRETTY_FUNCTION__);
00110 return new GaussianPyrBuilder<T>(*this);
00111 }
00112
00113
00114
00115
00116
00117 template <class T>
00118 GaussianRadialPyrBuilder<T>::GaussianRadialPyrBuilder() :
00119 PyrBuilder<T>()
00120 {
00121 GVX_TRACE(__PRETTY_FUNCTION__);
00122 }
00123
00124 template <class T>
00125 ImageSet<T> GaussianRadialPyrBuilder<T>::build(const Image<T>& img,
00126 const int firstlevel,
00127 const int depth,
00128 PyramidCache<T>* cache)
00129 {
00130 GVX_TRACE(__PRETTY_FUNCTION__);
00131
00132 const ImageSet<T>* const cached = (cache != 0)
00133 ? cache->gaussian5.get(img)
00134 : 0;
00135
00136 return (cached != 0)
00137 ? *cached
00138 : buildRadialPyrGaussian(img, firstlevel, depth);
00139 }
00140
00141 template <class T> inline
00142 GaussianRadialPyrBuilder<T>* GaussianRadialPyrBuilder<T>::clone() const
00143 {
00144 GVX_TRACE(__PRETTY_FUNCTION__);
00145 return new GaussianRadialPyrBuilder<T>(*this);
00146 }
00147
00148
00149
00150
00151
00152 template <class T>
00153 ConvolvePyrBuilder<T>::
00154 ConvolvePyrBuilder(const Image<float>& filt,
00155 ConvolutionBoundaryStrategy boundary) :
00156 PyrBuilder<T>(), itsFilt(filt), itsBoundary(boundary)
00157 {
00158 GVX_TRACE(__PRETTY_FUNCTION__);
00159 }
00160
00161 template <class T>
00162 ImageSet<T> ConvolvePyrBuilder<T>::build(const Image<T>& img,
00163 const int firstlevel,
00164 const int depth,
00165 PyramidCache<T>* cache)
00166 {
00167 GVX_TRACE(__PRETTY_FUNCTION__);
00168 return buildPyrConvolve(img, firstlevel, depth, itsFilt, itsBoundary);
00169 }
00170
00171 template <class T>
00172 ConvolvePyrBuilder<T>* ConvolvePyrBuilder<T>::clone() const
00173 {
00174 GVX_TRACE(__PRETTY_FUNCTION__);
00175 return new ConvolvePyrBuilder<T>(*this);
00176 }
00177
00178
00179
00180
00181
00182 template <class T>
00183 RGBConvolvePyrBuilder<T>::
00184 RGBConvolvePyrBuilder(const Image<float>& rfilt,
00185 const Image<float>& gfilt,
00186 const Image<float>& bfilt,
00187 ConvolutionBoundaryStrategy boundary) :
00188 PyrBuilder<T>(), itsRFilt(rfilt), itsGFilt(rfilt), itsBFilt(rfilt),
00189 itsBoundary(boundary)
00190 {
00191 GVX_TRACE(__PRETTY_FUNCTION__);
00192 }
00193
00194 template <class T>
00195 ImageSet<T> RGBConvolvePyrBuilder<T>::
00196 build(const Image< PixRGB<T> >& img,
00197 const int firstlevel,
00198 const int depth,
00199 PyramidCache<T>* cache)
00200 {
00201 GVX_TRACE(__PRETTY_FUNCTION__);
00202 Image<T> r, g, b; getComponents(img, r, g, b);
00203 ImageSet<T> rset = buildPyrConvolve(r, firstlevel, depth, itsRFilt, itsBoundary);
00204 ImageSet<T> gset = buildPyrConvolve(g, firstlevel, depth, itsGFilt, itsBoundary);
00205 ImageSet<T> bset = buildPyrConvolve(b, firstlevel, depth, itsBFilt, itsBoundary);
00206 ImageSet<T> result(depth);
00207
00208 for (int lev = firstlevel; lev < depth; ++lev)
00209 result[lev] = (rset[lev] + gset[lev] + bset[lev]) / 3;
00210
00211 return result;
00212 }
00213
00214 template <class T>
00215 ImageSet<T> RGBConvolvePyrBuilder<T>::
00216 build(const Image<T>& img,
00217 const int firstlevel,
00218 const int depth,
00219 PyramidCache<T>* cache)
00220 {
00221 GVX_TRACE(__PRETTY_FUNCTION__);
00222 LFATAL("Cannot process greyscale images");
00223 return ImageSet<T>();
00224 }
00225
00226 template <class T>
00227 ImageSet< PixRGB<T> > RGBConvolvePyrBuilder<T>::
00228 build2(const Image< PixRGB<T> >& img,
00229 const int firstlevel,
00230 const int depth,
00231 PyramidCache<T>* cache)
00232 {
00233 GVX_TRACE(__PRETTY_FUNCTION__);
00234 Image<T> r, g, b; getComponents(img, r, g, b);
00235 ImageSet<T> rset = buildPyrConvolve(r, firstlevel, depth, itsRFilt, itsBoundary);
00236 ImageSet<T> gset = buildPyrConvolve(g, firstlevel, depth, itsGFilt, itsBoundary);
00237 ImageSet<T> bset = buildPyrConvolve(b, firstlevel, depth, itsBFilt, itsBoundary);
00238 ImageSet< PixRGB<T> > result(depth);
00239
00240 for (int lev = firstlevel; lev < depth; ++lev)
00241 result[lev] = makeRGB (rset[lev], gset[lev], bset[lev]);
00242
00243 return result;
00244 }
00245
00246 template <class T>
00247 RGBConvolvePyrBuilder<T>* RGBConvolvePyrBuilder<T>::clone() const
00248 {
00249 GVX_TRACE(__PRETTY_FUNCTION__);
00250 return new RGBConvolvePyrBuilder<T>(*this);
00251 }
00252
00253
00254
00255
00256
00257 template <class T>
00258 LaplacianPyrBuilder<T>::LaplacianPyrBuilder(const int filter_size) :
00259 PyrBuilder<T>(), itsFiltSize(filter_size)
00260 {
00261 GVX_TRACE(__PRETTY_FUNCTION__);
00262 }
00263
00264 template <class T>
00265 ImageSet<T> LaplacianPyrBuilder<T>::build(const Image<T>& img,
00266 const int firstlevel,
00267 const int depth,
00268 PyramidCache<T>* cache)
00269 {
00270 GVX_TRACE(__PRETTY_FUNCTION__);
00271 return buildPyrLaplacian(img, firstlevel, depth, itsFiltSize);
00272 }
00273
00274 template <class T> inline
00275 LaplacianPyrBuilder<T>* LaplacianPyrBuilder<T>::clone() const
00276 {
00277 GVX_TRACE(__PRETTY_FUNCTION__);
00278 return new LaplacianPyrBuilder<T>(*this);
00279 }
00280
00281
00282
00283
00284
00285 template <class T>
00286 OrientedPyrBuilder<T>::OrientedPyrBuilder(const int filter_size,
00287 const float theta,
00288 const float intens,
00289 const bool usetab) :
00290 PyrBuilder<T>(), itsFiltSize(filter_size), itsAngle(theta),
00291 itsGaborIntens(intens), itsUseTab(usetab)
00292 {
00293 GVX_TRACE(__PRETTY_FUNCTION__);
00294 }
00295
00296 template <class T>
00297 ImageSet<T> OrientedPyrBuilder<T>::build(const Image<T>& img,
00298 const int firstlevel,
00299 const int depth,
00300 PyramidCache<T>* cache)
00301 {
00302 GVX_TRACE(__PRETTY_FUNCTION__);
00303
00304 const ImageSet<T>* const lplc =
00305 (cache != 0 && itsFiltSize == 9)
00306 ? cache->laplacian9.get(img)
00307 : 0;
00308
00309 return lplc != 0
00310 ? buildPyrOrientedFromLaplacian<T>(*lplc,
00311 itsFiltSize, itsAngle, itsGaborIntens,
00312 itsUseTab)
00313 : buildPyrOriented(img, firstlevel, depth,
00314 itsFiltSize, itsAngle, itsGaborIntens, itsUseTab);
00315 }
00316
00317 template <class T>
00318 OrientedPyrBuilder<T>* OrientedPyrBuilder<T>::clone() const
00319 {
00320 GVX_TRACE(__PRETTY_FUNCTION__);
00321 return new OrientedPyrBuilder<T>(*this);
00322 }
00323
00324
00325
00326
00327
00328
00329 template <class T>
00330 GenericPyrBuilder<T>::GenericPyrBuilder(const PyramidType typ,
00331 const float gabor_theta,
00332 const float intens) :
00333 PyrBuilder<T>(), itsPtype(typ), itsGaborAngle(gabor_theta),
00334 itsGaborIntens(intens)
00335 {
00336 GVX_TRACE(__PRETTY_FUNCTION__);
00337 }
00338
00339 template <class T>
00340 ImageSet<T> GenericPyrBuilder<T>::build(const Image<T>& image,
00341 const int firstlevel,
00342 const int depth,
00343 PyramidCache<T>* cache)
00344 {
00345 GVX_TRACE(__PRETTY_FUNCTION__);
00346 return buildPyrGeneric(image, firstlevel, depth, itsPtype,
00347 itsGaborAngle, itsGaborIntens);
00348 }
00349
00350 template <class T>
00351 GenericPyrBuilder<T>* GenericPyrBuilder<T>::clone() const
00352 {
00353 GVX_TRACE(__PRETTY_FUNCTION__);
00354 return new GenericPyrBuilder<T>(*this);
00355 }
00356
00357
00358
00359
00360 template <class T>
00361 ReichardtPyrBuilder<T>::ReichardtPyrBuilder(const float dx,
00362 const float dy,
00363 const PyramidType typ,
00364 const float gabor_theta,
00365 const float intens) :
00366 PyrBuilder<T>(), itsDX(dx), itsDY(dy), itsPtype(typ),
00367 itsGaborAngle(gabor_theta), itsGaborIntens(intens)
00368 {
00369 GVX_TRACE(__PRETTY_FUNCTION__);
00370 }
00371
00372 template <class T>
00373 ImageSet<T> ReichardtPyrBuilder<T>::build(const Image<T>& image,
00374 const int firstlevel,
00375 const int depth,
00376 PyramidCache<T>* cache)
00377 {
00378 GVX_TRACE(__PRETTY_FUNCTION__);
00379 const ImageSet<T>* const cached =
00380 (cache != 0 && itsPtype == Gaussian5)
00381 ? cache->gaussian5.get(image)
00382 : 0;
00383
00384
00385 ImageSet<T> upyr =
00386 cached != 0
00387 ? *cached
00388 : buildPyrGeneric(image, firstlevel, depth, itsPtype,
00389 itsGaborAngle, itsGaborIntens);
00390
00391 ImageSet<T> spyr(depth);
00392
00393
00394 for (int i = firstlevel; i < depth; ++i)
00395 spyr[i] = shiftImage(upyr[i], itsDX, itsDY);
00396
00397
00398 unshifted.push_back(upyr);
00399 shifted.push_back(spyr);
00400
00401 ImageSet<T> result(depth);
00402
00403
00404
00405 if (unshifted.size() == 1)
00406 {
00407 unshifted.push_back(upyr);
00408 shifted.push_back(spyr);
00409 }
00410
00411
00412 if (unshifted.size() == 3)
00413 {
00414 unshifted.pop_front();
00415 shifted.pop_front();
00416 }
00417
00418
00419 for (int i = firstlevel; i < depth; ++i)
00420 {
00421 result[i] =
00422 (unshifted.back()[i] * shifted.front()[i]) -
00423 (unshifted.front()[i] * shifted.back()[i]);
00424 }
00425
00426 return result;
00427 }
00428
00429
00430 template <class T>
00431 ReichardtPyrBuilder<T>* ReichardtPyrBuilder<T>::clone() const
00432 {
00433 GVX_TRACE(__PRETTY_FUNCTION__);
00434 return new ReichardtPyrBuilder<T>(*this);
00435 }
00436
00437
00438 template <class T>
00439 void ReichardtPyrBuilder<T>::reset()
00440 {
00441 GVX_TRACE(__PRETTY_FUNCTION__);
00442 shifted.clear();
00443 unshifted.clear();
00444 }
00445
00446
00447
00448
00449 TemplateMatchPyrBuilder::TemplateMatchPyrBuilder(const Image<float>& templ) :
00450 PyrBuilder<float>(), itsFilt(templ)
00451 {
00452 GVX_TRACE(__PRETTY_FUNCTION__);
00453 }
00454
00455
00456 TemplateMatchPyrBuilder* TemplateMatchPyrBuilder::clone() const
00457 {
00458 GVX_TRACE(__PRETTY_FUNCTION__);
00459 return new TemplateMatchPyrBuilder(*this);
00460 }
00461
00462
00463 ImageSet<float> TemplateMatchPyrBuilder::build(const Image<float>& image,
00464 const int firstlevel,
00465 const int depth,
00466 PyramidCache<float>* cache)
00467 {
00468 GVX_TRACE(__PRETTY_FUNCTION__);
00469 ImageSet<float> result(depth);
00470 if (0 >= firstlevel)
00471 result[0] = templateMatch(image);
00472 Image<float> prev_scale = image;
00473
00474 for (int lev = 1; lev < depth; ++lev)
00475 {
00476 Image<float> cur_scale = prev_scale;
00477
00478 cur_scale = decX(lowPass5x(cur_scale));
00479 cur_scale = decY(lowPass5y(cur_scale));
00480
00481
00482
00483 prev_scale = cur_scale;
00484
00485 if (lev >= firstlevel)
00486 result[lev] = templateMatch(cur_scale);
00487 }
00488
00489 return result;
00490 }
00491
00492
00493 Image<float> TemplateMatchPyrBuilder::templateMatch(const Image<float>& img)
00494 {
00495 GVX_TRACE(__PRETTY_FUNCTION__);
00496 Image<float> conv = convolve(img, itsFilt,
00497 CONV_BOUNDARY_ZERO);
00498 Image<float> conv2 = convolve(binaryReverse(img, 255.0f), itsFilt,
00499 CONV_BOUNDARY_ZERO);
00500 return takeMax(conv, conv2);
00501 }
00502
00503
00504
00505
00506 template <class T>
00507 GaborPyrBuilder<T>::GaborPyrBuilder(double angle,
00508 double filter_period,
00509 double elongation,
00510 int size,
00511 int buildFlags) :
00512 PyrBuilder<T>(),
00513 itsAngle(angle),
00514 itsPeriod(filter_period),
00515 itsElongation(elongation),
00516 itsSize(size),
00517 itsBuildFlags(buildFlags)
00518 {
00519 GVX_TRACE(__PRETTY_FUNCTION__);
00520 }
00521
00522
00523 template <class T>
00524 GaborPyrBuilder<T>* GaborPyrBuilder<T>::clone() const
00525 {
00526 GVX_TRACE(__PRETTY_FUNCTION__);
00527 return new GaborPyrBuilder<T>(*this);
00528 }
00529
00530
00531 template <class T>
00532 ImageSet<T> GaborPyrBuilder<T>::build(const Image<T>& img,
00533 const int firstlevel,
00534 const int depth,
00535 PyramidCache<T>* cache)
00536 {
00537 GVX_TRACE(__PRETTY_FUNCTION__);
00538 return buildPyrGabor(img, firstlevel, depth,
00539 itsAngle, itsPeriod, itsElongation,
00540 itsSize, itsBuildFlags);
00541 }
00542
00543
00544 template <class T>
00545 ImageSet<T> GaborPyrBuilder<T>::input(const ImageSet<T>& pyr)
00546 {
00547 GVX_TRACE(__PRETTY_FUNCTION__);
00548 return buildPyrGabor(pyr, itsAngle, itsPeriod, itsElongation,
00549 itsSize, itsBuildFlags);
00550 }
00551
00552
00553
00554
00555 template class GaborPyrBuilder<float>;
00556 template class RGBConvolvePyrBuilder<float>;
00557
00558 #define INSTANTIATE(T) \
00559 template class PyrBuilder< T >; \
00560 template class GenericPyrBuilder< T >; \
00561 template class GaussianPyrBuilder< T >; \
00562 template class GaussianRadialPyrBuilder< T >; \
00563 template class ConvolvePyrBuilder< T >; \
00564 template class LaplacianPyrBuilder< T >; \
00565 template class OrientedPyrBuilder< T >; \
00566 template class ReichardtPyrBuilder< T >; \
00567
00568 template class PyrBuilder<int>;
00569
00570 #ifdef INVT_INST_BYTE
00571 INSTANTIATE(byte);
00572 INSTANTIATE(PixRGB<byte>);
00573 #endif
00574 #ifdef INVT_INST_INT16
00575 INSTANTIATE(int16);
00576 INSTANTIATE(PixRGB<int16>);
00577 #endif
00578 #ifdef INVT_INST_INT32
00579 INSTANTIATE(int32);
00580 INSTANTIATE(PixRGB<int32>);
00581 #endif
00582 #ifdef INVT_INST_FLOAT
00583 INSTANTIATE(float);
00584 INSTANTIATE(PixRGB<float>);
00585 #endif
00586
00587
00588
00589
00590