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 FEATURECLUSTERFILTERS_H_DEFINED
00039 #define FEATURECLUSTERFILTERS_H_DEFINED
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052 #include "Util/Assert.H"
00053 #include "Image/Image.H"
00054
00055 #include <vector>
00056
00057
00058
00059
00060
00061
00062 template <class T_or_RGB> inline
00063 T_or_RGB filterAtLocation(Image<T_or_RGB> *image,
00064 Image<float> *kernel, Point2D<int> *location);
00065
00066
00067
00068
00069
00070
00071
00072
00073 template <class T_or_RGB> inline
00074 void filterAtLocationBatch(const Image<T_or_RGB> *image,
00075 const Image<float> *kernel,
00076 const std::vector<Point2D<int>*> *location,
00077 std::vector<T_or_RGB> *results,
00078 const unsigned int size);
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098 template <class T_or_RGB> inline
00099 void multiScaleBatchFilter(const Image<T_or_RGB> *image,
00100 const std::vector<Point2D<int>*> *location,
00101 const unsigned int *locations,
00102 const std::vector<Image<float> > *filters,
00103 const unsigned int scales,
00104 const bool quarterSize,
00105 const bool normalize,
00106 std::vector<std::vector<T_or_RGB> > *results);
00107
00108
00109
00110
00111
00112
00113
00114 template <class T> inline
00115 void multiScaleJunctionFilter(const unsigned int size,
00116 const unsigned int scales,
00117 const std::vector<std::vector<PixH2SV2<T> > >
00118 *input,
00119 std::vector<std::vector<PixH2SV2<T> > > *results);
00120
00121
00122 template <class T> inline
00123 void multiScaleJunctionFilter(const unsigned int size,
00124 const unsigned int scales,
00125 const std::vector<std::vector<T> >
00126 *input,
00127 std::vector<std::vector<T> > *results);
00128
00129
00130
00131
00132
00133
00134
00135
00136 template <class T_or_RGB> inline
00137 T_or_RGB filterAtLocation(Image<T_or_RGB> *image,
00138 Image<float> *kernel, Point2D<int> *location)
00139 {
00140 ASSERT((kernel->getWidth() % 2 == 1) && (kernel->getHeight() % 2 == 1));
00141 int w = image->getWidth();
00142 int h = image->getHeight();
00143 int kw = kernel->getWidth();
00144 int kh = kernel->getHeight();
00145 int kx = (kw-1)/2;
00146 int ky = (kh-1)/2;
00147 int kstartx = 0;
00148 int kstarty = 0;
00149
00150
00151
00152
00153 int startx = location->i - kx;
00154 if(startx < 0){ kstartx = abs(startx); startx = 0;}
00155 int endx = location->i + kx;
00156 if(endx >= w) { endx = w - 1; }
00157
00158 int starty = location->j - ky;
00159 if(starty < 0){ kstarty = abs(starty); starty = 0;}
00160 int endy = location->j + ky;
00161 if(endy >= h) { endy = h - 1; }
00162
00163 T_or_RGB result = T_or_RGB(0);
00164 T_or_RGB zero = T_or_RGB(0);
00165 float sum = 0;
00166
00167
00168
00169 typename Image<float>::iterator ker;
00170 typename Image<T_or_RGB>::iterator img;
00171 for(int iy = starty; iy <= endy; iy++)
00172 {
00173
00174 ker = kernel->beginw() +
00175 (kw*(kstarty+iy-starty)) + kstartx;
00176
00177
00178
00179
00180 for(img = image->beginw() + w*iy + startx;
00181 img != image->beginw() + w*iy + endx; ++img, ++ker)
00182 {
00183 result += clamped_convert<T_or_RGB>((*img) * (*ker));
00184
00185 sum += *ker;
00186
00187 }
00188 }
00189
00190 if(sum != 0)
00191 {
00192 result = clamped_convert<T_or_RGB>(result/sum);
00193 }
00194 else
00195 {
00196 result = zero;
00197 }
00198 return result;
00199 }
00200
00201
00202 template <class T_or_RGB> inline
00203 void filterAtLocationBatch(const Image<T_or_RGB> *image,
00204 const Image<float> *kernel,
00205 const std::vector<Point2D<int>*> *location,
00206 std::vector<T_or_RGB> *results,
00207 const unsigned int size)
00208 {
00209 ASSERT((kernel->getWidth() % 2 == 1) && (kernel->getHeight() % 2 == 1));
00210 ASSERT(results->size() >= size);
00211 int w = image->getWidth();
00212 int h = image->getHeight();
00213 int kw = kernel->getWidth();
00214 int kh = kernel->getHeight();
00215 int kx = (kw-1)/2;
00216 int ky = (kh-1)/2;
00217 int kstartx = 0;
00218 int kstarty = 0;
00219
00220 typename std::vector<T_or_RGB>::iterator resultsItr = results->begin();
00221
00222 std::vector<Point2D<int>*>::const_iterator locationItr = location->begin();
00223
00224
00225
00226
00227 int startx,endx,starty,endy;
00228
00229 typename Image<float>::const_iterator ker;
00230 typename Image<T_or_RGB>::const_iterator img;
00231 bool useSlow;
00232 T_or_RGB zero = T_or_RGB(0);
00233
00234 for(unsigned int i = 0; i < size; i++, ++resultsItr, ++locationItr)
00235 {
00236 useSlow = false;
00237 startx = (*locationItr)->i - kx;
00238 if(startx < 0){ kstartx = abs(startx); startx = 0; useSlow = true; }
00239 endx = (*locationItr)->i + kx;
00240 if(endx >= w) { endx = w - 1; useSlow = true; }
00241
00242 starty = (*locationItr)->j - ky;
00243 if(starty < 0){ kstarty = abs(starty); starty = 0; useSlow = true; }
00244 endy = (*locationItr)->j + ky;
00245 if(endy >= h) { endy = h - 1; useSlow = true; }
00246
00247 float sum = 0;
00248
00249
00250 *resultsItr = zero;
00251
00252 if(useSlow == true)
00253 {
00254
00255 for(int iy = starty; iy <= endy; iy++)
00256 {
00257
00258 ker = kernel->begin() +
00259 (kw*(kstarty+iy-starty)) + kstartx;
00260
00261 for(img = image->begin() + w*iy + startx;
00262 img != image->begin() + w*iy + endx; ++img, ++ker)
00263 {
00264 *resultsItr += clamped_convert<T_or_RGB>((*img) * (*ker));
00265 sum += *ker;
00266 }
00267 }
00268
00269 if(sum != 0)
00270 {
00271 *resultsItr = clamped_convert<T_or_RGB>((*resultsItr)/sum);
00272 }
00273 else
00274 {
00275 *resultsItr = zero;
00276 }
00277 }
00278 else
00279 {
00280
00281 ker = kernel->begin();
00282 for(int iy = starty; iy <= endy; iy++)
00283 {
00284 for(img = image->begin() + w*iy + startx;
00285 img != image->begin() + w*iy + endx; ++img, ++ker)
00286 {
00287 *resultsItr += clamped_convert<T_or_RGB>((*img) * (*ker));
00288 sum += *ker;
00289 }
00290 }
00291 if(sum != 0)
00292 {
00293 *resultsItr = clamped_convert<T_or_RGB>((*resultsItr)/sum);
00294 }
00295 else
00296 {
00297 *resultsItr = zero;
00298 }
00299 }
00300 }
00301 }
00302
00303
00304 template <class T_or_RGB> inline
00305 void multiScaleBatchFilter(const Image<T_or_RGB> *image,
00306 const std::vector<Point2D<int>*> *location,
00307 const unsigned int *locations,
00308 const std::vector<Image<float> > *filters,
00309 const unsigned int scales,
00310 const bool quarterSize,
00311 const bool normalize,
00312 std::vector<std::vector<T_or_RGB> > *results)
00313 {
00314
00315
00316 T_or_RGB zero = T_or_RGB(0);
00317
00318
00319
00320 const double rooty = sqrt(.5);
00321
00322
00323 std::vector<Point2D<int> > currentLocation1;
00324 std::vector<Point2D<int> > currentLocation2;
00325 std::vector<Point2D<int> > *currentLocation;
00326
00327
00328 Image<T_or_RGB> currentImage1 = *image;
00329 Image<T_or_RGB> currentImage2;
00330 Image<T_or_RGB> *currentImage;
00331
00332
00333
00334
00335 std::vector<Point2D<int>*>::const_iterator ilocation = location->begin();
00336
00337 for(unsigned int i = 0; i < *locations; i++, ++ilocation)
00338 {
00339 currentLocation1.push_back(**ilocation);
00340 }
00341 if(quarterSize)
00342 {
00343 Point2D<int> pp;
00344 currentImage2 = rescaleBilinear(currentImage1,
00345 (int)floor(currentImage1.getWidth()*rooty),
00346 (int)floor(currentImage1.getHeight()*rooty));
00347 currentLocation2.resize(currentLocation1.size(),pp);
00348 std::vector<Point2D<int> >::iterator icur1 = currentLocation1.begin();
00349 std::vector<Point2D<int> >::iterator icur2 = currentLocation2.begin();
00350 while(icur1 != currentLocation1.end())
00351 {
00352 icur2->i = (int)floor(icur1->i * rooty);
00353 icur2->j = (int)floor(icur1->j * rooty);
00354 ++icur1; ++icur2;
00355 }
00356 }
00357
00358 int startx,starty;
00359 unsigned int endx,endy;
00360
00361 Image<float>::const_iterator ker;
00362 typename Image<T_or_RGB>::iterator img;
00363
00364 typename std::vector<std::vector<T_or_RGB> >::iterator iresults =
00365 results->begin();
00366
00367
00368
00369 for(unsigned int sc = 0; sc < scales; sc++)
00370 {
00371 if((!quarterSize) || (sc%2 == 0) || (sc == 0))
00372 {
00373 currentLocation = ¤tLocation1;
00374 currentImage = ¤tImage1;
00375 }
00376 else
00377 {
00378 currentLocation = ¤tLocation2;
00379 currentImage = ¤tImage2;
00380 }
00381
00382 const unsigned int w = currentImage->getWidth();
00383 const unsigned int h = currentImage->getHeight();
00384 unsigned int kstartx = 0;
00385 unsigned int kstarty = 0;
00386
00387 for(std::vector<Image<float> >::const_iterator
00388 ifilters = filters->begin();
00389 ifilters != filters->end(); ++ifilters, ++iresults)
00390 {
00391
00392
00393 const unsigned int kw = ifilters->getWidth();
00394 const unsigned int kh = ifilters->getHeight();
00395 const unsigned int kx = (kw-1)/2;
00396 const unsigned int ky = (kh-1)/2;
00397
00398 typename std::vector<T_or_RGB>::iterator iiresults =
00399 iresults->begin();
00400 std::vector<Point2D<int> >::iterator icurrentLocation
00401 = currentLocation->begin();
00402 for(unsigned int l = 0; l < *locations; l++,
00403 ++icurrentLocation, ++iiresults)
00404 {
00405 startx = icurrentLocation->i - kx;
00406 if(startx < 0)
00407 { kstartx = abs(startx); startx = 0; }
00408 endx = icurrentLocation->i + kx;
00409 if(endx >= w) { endx = w - 1; }
00410
00411 starty = icurrentLocation->j - ky;
00412 if(starty < 0)
00413 { kstarty = abs(starty); starty = 0; }
00414 endy = icurrentLocation->j + ky;
00415 if(endy >= h) { endy = h - 1; }
00416
00417 float sum = 0;
00418
00419
00420
00421 for(unsigned int iy = starty; iy <= endy; iy++)
00422 {
00423
00424 ker = ifilters->begin() +
00425 (kw*(kstarty+iy-starty)) + kstartx;
00426
00427 for(img = currentImage->beginw() + w*iy + startx;
00428 img != currentImage->beginw() + w*iy + endx; ++img, ++ker)
00429 {
00430 *iiresults += clamped_convert<T_or_RGB>((*img) * (*ker));
00431 sum += fabs(*ker);
00432 }
00433 }
00434
00435 if(normalize)
00436 {
00437 if(sum != 0)
00438 {
00439 *iiresults = clamped_convert<T_or_RGB>((*iiresults)/sum);
00440 }
00441 else
00442 {
00443 *iiresults = zero;
00444 }
00445 }
00446 kstarty = 0;
00447 kstartx = 0;
00448 }
00449 }
00450
00451
00452
00453 *currentImage = decXY(*currentImage);
00454
00455
00456 for(std::vector<Point2D<int> >::iterator icurrentLocation
00457 = currentLocation->begin();
00458 icurrentLocation != currentLocation->end();
00459 ++icurrentLocation)
00460 {
00461 *icurrentLocation = *icurrentLocation/2;
00462 }
00463 }
00464 }
00465
00466
00467 template <class T> inline
00468 void multiScaleJunctionFilter(const unsigned int size,
00469 const unsigned int scales,
00470 const std::vector<std::vector<PixH2SV2<T> > >
00471 *input,
00472 std::vector<std::vector<PixH2SV2<T> > > *results)
00473 {
00474 const PixH2SV2<T> zero(T(0));
00475
00476 typename std::vector<std::vector<PixH2SV2<T> > >::const_iterator
00477 iinput1a = input->begin();
00478 typename std::vector<std::vector<PixH2SV2<T> > >::const_iterator
00479 iinput2a = input->begin()+1;
00480 typename std::vector<std::vector<PixH2SV2<T> > >::const_iterator
00481 iinput1b = input->begin()+2;
00482 typename std::vector<std::vector<PixH2SV2<T> > >::const_iterator
00483 iinput2b = input->begin()+3;
00484 typename std::vector<std::vector<PixH2SV2<T> > >::iterator
00485 iresults = results->begin();
00486
00487 for(unsigned int s = 0; s < scales; s++)
00488 {
00489 typename std::vector<PixH2SV2<T> >::const_iterator
00490 iiinput1a = iinput1a->begin();
00491 typename std::vector<PixH2SV2<T> >::const_iterator
00492 iiinput2a = iinput2a->begin();
00493 typename std::vector<PixH2SV2<T> >::const_iterator
00494 iiinput1b = iinput1b->begin();
00495 typename std::vector<PixH2SV2<T> >::const_iterator
00496 iiinput2b = iinput2b->begin();
00497 typename std::vector<PixH2SV2<T> >::iterator iiresults = iresults->begin();
00498
00499 PixH2SV2<T> max1a = PixH2SV2<T>(0); PixH2SV2<T> max2a = PixH2SV2<T>(0);
00500 PixH2SV2<T> max1b = PixH2SV2<T>(0); PixH2SV2<T> max2b = PixH2SV2<T>(0);
00501
00502 for(unsigned int i = 0; i < size; i++,++iiinput1a)
00503 {
00504 max1a = maxmerge(*iiinput1a,max1a);
00505 }
00506 for(unsigned int i = 0; i < size; i++,++iiinput2a)
00507 {
00508 max2a = maxmerge(*iiinput2a,max2a);
00509 }
00510 for(unsigned int i = 0; i < size; i++,++iiinput1b)
00511 {
00512 max1b = maxmerge(*iiinput1b,max1b);
00513 }
00514 for(unsigned int i = 0; i < size; i++,++iiinput2b)
00515 {
00516 max2b = maxmerge(*iiinput2b,max2b);
00517 }
00518
00519 iiinput1a = iinput1a->begin();
00520 iiinput2a = iinput2a->begin();
00521 iiinput1b = iinput1b->begin();
00522 iiinput2b = iinput2b->begin();
00523
00524 const PixH2SV2<T> norm1( max1a + max1b );
00525 const PixH2SV2<T> norm2( max2a + max2b );
00526
00527
00528 if((norm1 != zero) && (norm2 != zero))
00529 {
00530 for(unsigned int i = 0; i < size; i++,
00531 ++iiinput1a,++iiinput2a,
00532 ++iiinput1b,++iiinput2b,
00533 ++iiresults)
00534 {
00535 const PixH2SV2<T> c1mix( abs((*iiinput1a)-(*iiinput1b))/(norm1) );
00536 const PixH2SV2<T> c2mix( abs((*iiinput2a)-(*iiinput2b))/(norm2) );
00537
00538 const PixH2SV2<T> c1Gmix( ((*iiinput1a)+(*iiinput1b))/(norm1) );
00539 const PixH2SV2<T> c2Gmix( ((*iiinput2a)+(*iiinput2b))/(norm2) );
00540
00541 const PixH2SV2<T> iOutA( (c1Gmix+c2Gmix)/2 );
00542
00543
00544 const PixH2SV2<T> iOutB( abs(c1mix-c2mix)/2 );
00545
00546 *iiresults = PixH2SV2<T>(iOutA - iOutB);
00547
00548 }
00549 }
00550 else
00551 {
00552 LINFO("WARNING - AT %d ALL VALUES ARE ZERO",s);
00553 for(unsigned int i = 0; i < size; i++,++iiresults)
00554 {
00555 *iiresults = zero;
00556 }
00557 }
00558 iinput1a = iinput1a + 4;
00559 iinput2a = iinput2a + 4;
00560 iinput1b = iinput1b + 4;
00561 iinput2b = iinput2b + 4;
00562 ++iresults;
00563 }
00564 }
00565
00566
00567 template <class T> inline
00568 void multiScaleJunctionFilter(const unsigned int size,
00569 const unsigned int scales,
00570 const std::vector<std::vector<T> >
00571 *input,
00572 std::vector<std::vector<T> > *results)
00573 {
00574 const T zero = T(0);
00575
00576 typename std::vector<std::vector<T> >::const_iterator
00577 iinput1a = input->begin();
00578 typename std::vector<std::vector<T> >::const_iterator
00579 iinput2a = input->begin()+1;
00580 typename std::vector<std::vector<T> >::const_iterator
00581 iinput1b = input->begin()+2;
00582 typename std::vector<std::vector<T> >::const_iterator
00583 iinput2b = input->begin()+3;
00584 typename std::vector<std::vector<T> >::iterator
00585 iresults = results->begin();
00586
00587 for(unsigned int s = 0; s < scales; s++)
00588 {
00589 typename std::vector<T>::const_iterator
00590 iiinput1a = iinput1a->begin();
00591 typename std::vector<T>::const_iterator
00592 iiinput2a = iinput2a->begin();
00593 typename std::vector<T>::const_iterator
00594 iiinput1b = iinput1b->begin();
00595 typename std::vector<T>::const_iterator
00596 iiinput2b = iinput2b->begin();
00597 typename std::vector<T>::iterator iiresults = iresults->begin();
00598
00599 T max1a = T(0); T max2a = T(0);
00600 T max1b = T(0); T max2b = T(0);
00601
00602 for(unsigned int i = 0; i < size; i++,++iiinput1a)
00603 {
00604 max1a = maxmerge(*iiinput1a,max1a);
00605 }
00606 for(unsigned int i = 0; i < size; i++,++iiinput2a)
00607 {
00608 max2a = maxmerge(*iiinput2a,max2a);
00609 }
00610 for(unsigned int i = 0; i < size; i++,++iiinput1b)
00611 {
00612 max1b = maxmerge(*iiinput1b,max1b);
00613 }
00614 for(unsigned int i = 0; i < size; i++,++iiinput2b)
00615 {
00616 max2b = maxmerge(*iiinput2b,max2b);
00617 }
00618
00619 iiinput1a = iinput1a->begin();
00620 iiinput2a = iinput2a->begin();
00621 iiinput1b = iinput1b->begin();
00622 iiinput2b = iinput2b->begin();
00623
00624 const T norm1 = max1a + max1b;
00625 const T norm2 = max2a + max2b;
00626
00627
00628 if((norm1 != 0) && (norm2 != 0))
00629 {
00630 for(unsigned int i = 0; i < size; i++,
00631 ++iiinput1a,++iiinput2a,
00632 ++iiinput1b,++iiinput2b,
00633 ++iiresults)
00634 {
00635 const T c1mix = T(fabs((*iiinput1a)-(*iiinput1b))/(norm1));
00636 const T c2mix = T(fabs((*iiinput2a)-(*iiinput2b))/(norm2));
00637
00638 const T c1Gmix = (((*iiinput1a)+(*iiinput1b))/(norm1));
00639 const T c2Gmix = (((*iiinput2a)+(*iiinput2b))/(norm2));
00640
00641 const T iOutA = (c1Gmix+c2Gmix)/2;
00642
00643
00644 const T iOutB = T(fabs(c1mix-c2mix)/2);
00645
00646 *iiresults = iOutA - iOutB;
00647
00648 }
00649 }
00650 else
00651 {
00652 LINFO("WARNING - AT %d ALL VALUES ARE ZERO",s);
00653 for(unsigned int i = 0; i < size; i++,++iiresults)
00654 {
00655 *iiresults = zero;
00656 }
00657 }
00658 iinput1a = iinput1a + 4;
00659 iinput2a = iinput2a + 4;
00660 iinput1b = iinput1b + 4;
00661 iinput2b = iinput2b + 4;
00662 ++iresults;
00663 }
00664 }
00665
00666 #endif // !FEATURECLUSTERFILTERS_H_DEFINED
00667
00668
00669
00670
00671
00672