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/fancynorm.H"
00039
00040 #include "Util/Assert.H"
00041 #include "Image/Image.H"
00042 #include "Image/ImageSet.H"
00043 #include "Image/FilterOps.H"
00044 #include "Image/Kernels.H"
00045 #include "Image/MathOps.H"
00046 #include "Image/ShapeOps.H"
00047 #include "Image/Transforms.H"
00048 #include "Image/PyramidOps.H"
00049 #include "Util/StringConversions.H"
00050 #include "Util/log.H"
00051 #include "rutz/compat_cmath.h"
00052 #include "rutz/trace.h"
00053
00054 #include <algorithm>
00055 #include <cmath>
00056
00057
00058
00059
00060
00061
00062 template <class T>
00063 Image<T> maxNormalize(const Image<T>& src,
00064 const T mi, const T ma, const MaxNormType normtyp,
00065 int nbiter, const Image<float> *lrexcit)
00066 {
00067 GVX_TRACE(__PRETTY_FUNCTION__);
00068 #ifdef SHOW_MAXNORM_INFO
00069 T mm, mmm; getMinMax(src, mm, mmm);
00070 LDEBUG("mini = %f, maxi= %f", float(mm), float(mmm));
00071 #endif
00072
00073 Image<T> result;
00074
00075
00076 switch(normtyp)
00077 {
00078 case VCXNORM_NONE:
00079 result = maxNormalizeNone(src, mi, ma);
00080 break;
00081 case VCXNORM_MAXNORM:
00082 result = maxNormalizeStd(src, mi, ma);
00083 break;
00084 case VCXNORM_FANCYFAST:
00085 result = maxNormalizeFancyFast(src, mi, ma, nbiter);
00086 break;
00087 case VCXNORM_FANCYONE:
00088 nbiter = 1;
00089 case VCXNORM_FANCY:
00090 result = maxNormalizeFancy(src, mi, ma, nbiter, 1.0, lrexcit);
00091 break;
00092 case VCXNORM_FANCYLANDMARK:
00093 result = maxNormalizeFancyLandmark(src, mi, ma, nbiter);
00094 break;
00095 case VCXNORM_LANDMARK:
00096 result = maxNormalizeLandmark(src, mi, ma);
00097 break;
00098 case VCXNORM_FANCYWEAK:
00099 result = maxNormalizeFancy(src, mi, ma, nbiter, 0.5);
00100 break;
00101 case VCXNORM_FANCYVWEAK:
00102 result = maxNormalizeFancy(src, mi, ma, nbiter, 0.1);
00103 break;
00104 case VCXNORM_IGNORE:
00105 result = src;
00106 break;
00107 case VCXNORM_SURPRISE:
00108 result = src;
00109 break;
00110 case VCXNORM_STDEV:
00111 result = maxNormalizeStdev(src);
00112 break;
00113 case VCXNORM_STDEV0:
00114 result = maxNormalizeStdev0(src);
00115 break;
00116 default:
00117 LFATAL("Unknown normalization type: %d", int(normtyp));
00118 }
00119
00120 #ifdef SHOW_MAXNORM_INFO
00121 getMinMax(result, mm, mmm);
00122 LDEBUG("newmin = %f, newmax = %f", float(mm), float(mmm));
00123 #endif
00124
00125 return result;
00126 }
00127
00128
00129 template <class T>
00130 Image<T> maxNormalizeNone(const Image<T>& src, const T mi, const T ma)
00131 {
00132 GVX_TRACE(__PRETTY_FUNCTION__);
00133 Image<T> result = src;
00134
00135
00136 inplaceRectify(result);
00137
00138
00139 if (mi != T() || ma != T()) inplaceNormalize(result, mi, ma);
00140
00141 return result;
00142 }
00143
00144
00145
00146 template <class T>
00147 Image<T> maxNormalizeStd(const Image<T>& src, const T mi, const T ma)
00148 {
00149 GVX_TRACE(__PRETTY_FUNCTION__);
00150 ASSERT(src.initialized());
00151 T zero = T();
00152
00153 Image<T> result = src;
00154
00155
00156 inplaceRectify(result);
00157
00158
00159 if (mi != zero || ma != zero) inplaceNormalize(result, mi, ma);
00160
00161 const int w = result.getWidth();
00162 const int h = result.getHeight();
00163
00164
00165
00166
00167 T thresh = T(mi + (ma - mi) / 10.0);
00168
00169
00170 double lm_sum = 0.0;
00171 int lm_nb = 0;
00172 for (int j = 1; j < h - 1; j ++)
00173 for (int i = 1; i < w - 1; i ++)
00174 {
00175 int index = i + w * j;
00176 T val = result.getVal(index);
00177 if (val >= thresh &&
00178 val >= result.getVal(index - w) &&
00179 val >= result.getVal(index + w) &&
00180 val >= result.getVal(index - 1) &&
00181 val >= result.getVal(index + 1))
00182 {
00183 lm_sum += double(val);
00184 lm_nb ++;
00185 }
00186 }
00187
00188 if (lm_nb > 1)
00189 {
00190 double factor = ma - (T)(lm_sum / double(lm_nb));
00191 result *= T(factor * factor);
00192 }
00193 else if (lm_nb == 1)
00194 result *= (ma * ma);
00195 else
00196 {
00197
00198 }
00199
00200 return result;
00201 }
00202
00203
00204
00205 template <class T>
00206 Image<T> maxNormalizeFancyFast(const Image<T>& src, const T mi, const T ma,
00207 const int nbiter)
00208 {
00209 GVX_TRACE(__PRETTY_FUNCTION__);
00210 ASSERT(src.initialized());
00211 T zero = T();
00212
00213 Image<T> result = src;
00214
00215
00216 inplaceRectify(result);
00217
00218
00219 if (mi != zero || ma != zero) inplaceNormalize(result, mi, ma);
00220
00221 const int w = result.getWidth();
00222 const int h = result.getHeight();
00223
00224 int wh = std::max(w, h);
00225
00226
00227
00228 int ilev = 1+(int)(log(float(wh) / 1.5 * FANCYISIG / 100.0) /
00229 log(sqrt(5)));
00230
00231
00232 if (ilev < 0) ilev = 0;
00233
00234 int elev = (int)(log(float(wh) / 1.5 * FANCYESIG / 100.0) /
00235 log(sqrt(5)));
00236
00237
00238 if (elev < 0) elev = 0;
00239
00240 for (int i = 0; i < nbiter; ++i)
00241 {
00242 ImageSet<T> inhibPyr = buildPyrGaussian(result, 0, ilev+1, 9);
00243 Image<T> excit = inhibPyr[elev];
00244 Image<T> inhib = inhibPyr[ilev];
00245 excit *= T(FANCYCOEX); inhib *= T(FANCYCOIN);
00246 excit = rescale(excit, w, h);
00247 inplaceAttenuateBorders(excit, wh/16);
00248 inhib = rescale(inhib, w, h);
00249 excit -= inhib;
00250
00251 T globinhi, minim, maxim; getMinMax(result, minim, maxim);
00252 globinhi = (T)(0.01 * FANCYINHI * maxim);
00253
00254 result += excit;
00255 result += -globinhi;
00256 inplaceRectify(result);
00257 }
00258
00259 return result;
00260 }
00261
00262
00263
00264 template <class T>
00265 Image<T> maxNormalizeFancy(const Image<T>& src, const T mi, const T ma,
00266 const int nbiter, const double weakness,
00267 const Image<float>* lrexcit)
00268 {
00269 GVX_TRACE(__PRETTY_FUNCTION__);
00270
00271
00272
00273 ASSERT(src.initialized());
00274 T zero = T();
00275
00276 Image<T> result = src;
00277
00278
00279 inplaceRectify(result);
00280
00281
00282 if (mi != zero || ma != zero) inplaceNormalize(result, mi, ma);
00283
00284 const int w = result.getWidth();
00285 const int h = result.getHeight();
00286
00287 int siz = std::max(w, h);
00288 int maxhw = std::max(0, std::min(w, h) / 2 - 1);
00289
00290 float esig = (float(siz) * FANCYESIG) * 0.01F;
00291 float isig = (float(siz) * FANCYISIG) * 0.01F;
00292 Image<float> gExc =
00293 gaussian<float>(FANCYCOEX/(esig*sqrt(2.0*M_PI)) * weakness, esig, maxhw);
00294 Image<float> gInh =
00295 gaussian<float>(FANCYCOIN/(isig*sqrt(2.0*M_PI)) * weakness, isig, maxhw);
00296
00297 for (int i = 0; i < nbiter; ++i)
00298 {
00299 if (lrexcit)
00300 {
00301 Image<T> tmp(result);
00302 tmp = downSize(tmp, w / (1<<LRLEVEL), h / (1<<LRLEVEL));
00303 tmp = convolve(tmp, *lrexcit, CONV_BOUNDARY_ZERO);
00304 tmp += T(1.0);
00305 inplaceClamp(tmp, T(1.0), T(1.25));
00306 tmp = rescale(tmp, w, h);
00307 T tmi, tma; getMinMax(tmp, tmi,tma);
00308 LDEBUG("lrexcit(%d): [%f..%f]", i, double(tmi), double(tma));
00309 result *= tmp;
00310 }
00311
00312 Image<T> excit = sepFilter(result, gExc, gExc, CONV_BOUNDARY_CLEAN);
00313 Image<T> inhib = sepFilter(result, gInh, gInh, CONV_BOUNDARY_CLEAN);
00314 excit -= inhib;
00315 T minim, maxim; getMinMax(result, minim, maxim);
00316 T globinhi = (T)(0.01 * FANCYINHI * maxim);
00317
00318 result += excit;
00319 result += -globinhi;
00320 inplaceRectify(result);
00321
00322 }
00323
00324 return result;
00325 }
00326
00327
00328
00329
00330 template <class T>
00331 Image<T> maxNormalizeFancyLandmark(const Image<T>& src, const T mi, const T ma,
00332 const int nbiter)
00333 {
00334 GVX_TRACE(__PRETTY_FUNCTION__);
00335
00336
00337
00338 ASSERT(src.initialized());
00339 T zero = T();
00340
00341 Image<T> result = src;
00342
00343
00344 inplaceRectify(result);
00345
00346
00347 if (mi != zero || ma != zero) inplaceNormalize(result, mi, ma);
00348
00349 const int w = result.getWidth();
00350 const int h = result.getHeight();
00351
00352 int siz = std::max(w, h);
00353 int maxhw = std::max(0, std::min(w, h) / 2 - 1);
00354
00355 float esig = (float(siz)*2)*0.01;
00356 float isig = (float(siz)*3)*0.01;
00357 Image<float> gExc = gaussian<float>(FANCYCOEX/(esig*sqrt(2.0*M_PI)),
00358 esig, maxhw);
00359 Image<float> gInh = gaussian<float>(FANCYCOIN/(isig*sqrt(2.0*M_PI)),
00360 isig, maxhw);
00361
00362 for (int i = 0; i < nbiter; ++i)
00363 {
00364 Image<T> excit = sepFilter(result, gExc, gExc, CONV_BOUNDARY_CLEAN);
00365 Image<T> inhib = sepFilter(result, gInh, gInh, CONV_BOUNDARY_CLEAN);
00366 excit -= inhib;
00367 T minim, maxim; getMinMax(result, minim, maxim);
00368 T globinhi = (T)(0.01 * FANCYINHI * maxim);
00369
00370 result += excit;
00371 result += -globinhi;
00372 inplaceRectify(result);
00373
00374 }
00375
00376 return result;
00377 }
00378
00379
00380
00381 template <class T>
00382 Image<T> maxNormalizeLandmark(const Image<T>& src, const T mi, const T ma)
00383 {
00384 GVX_TRACE(__PRETTY_FUNCTION__);
00385 ASSERT(src.initialized());
00386 Image<T> result = src;
00387 inplaceNormalize(result, (T)MAXNORMMIN, (T)MAXNORMLANDMARK);
00388
00389
00390
00391
00392
00393
00394
00395
00396 Image<byte> target;
00397 Image<T> comp_map;
00398 T max, thresh;
00399 float area_prev = 0.0f;
00400 int comp_next = 0;
00401 double activity_prev = 0.0, real_activity = 0.0, standout = 0.0;
00402 double sum_prev = 0.0, sum_next = 0.0;
00403 float goodness_map = 0.0f;
00404 float landmarkness = 0.0f;
00405
00406 thresh = (T) MAXNORMMIN;
00407 Point2D<int> max_locn;
00408 findMax(result, max_locn, max);
00409
00410
00411 while(max > thresh)
00412 {
00413 area_prev = 0.0f;
00414 activity_prev = 0.0;
00415 int val = segmentLandmark(result, max_locn, target, activity_prev,
00416 standout, area_prev);
00417
00418 if (val != -1)
00419 {
00420 result = result - result * (Image<T>)target;
00421 real_activity = (double)src.getVal(max_locn);
00422 findMax(result, max_locn, max);
00423
00424 if(area_prev > 0.125)
00425 {
00426 sum_prev += (double)area_prev * activity_prev;
00427
00428
00429 int peaks = findPeaks((Image<T>)target,(T) MAXNORMMIN,
00430 (T) MAXNORMLANDMARK,
00431 sum_next);
00432 if(peaks == 0)
00433 {
00434 peaks = 10;
00435 }
00436
00437
00438 LINFO("area_prev = %f, peaks = %d",
00439 area_prev, peaks);
00440 LINFO("real_activity = %f, activity_prev = %f, standout = %f",
00441 real_activity, activity_prev, standout);
00442 landmarkness = (float) (real_activity * standout);
00443
00444
00445
00446 LINFO("-----landmarkness = %f", landmarkness);
00447
00448 if (!comp_map.initialized())
00449 comp_map = (Image<T>)target / 255.0f * (T)landmarkness ;
00450 else comp_map += (Image<T>)target / 255.0f * (T)landmarkness;
00451 }
00452 }
00453 else break;
00454 }
00455
00456
00457 result = src;
00458 comp_next = findPeaks(result,(T) MAXNORMMIN, (T) MAXNORMLANDMARK,
00459 sum_next);
00460
00461
00462 if(comp_next == 0)
00463 {
00464 comp_next = 10;
00465 }
00466 if (sum_prev != 0.0)
00467 goodness_map = (float)(sum_next / (sum_prev * comp_next * comp_next)) ;
00468
00469 goodness_map = pow(goodness_map, 0.5);
00470 LINFO("# of comps = %d", comp_next);
00471
00472 LINFO("goodness_map = %f", goodness_map);
00473
00474
00475 if (comp_map.initialized())
00476 comp_map *= (T)(goodness_map);
00477
00478 else comp_map.resize(src.getDims(), true);
00479 return comp_map;
00480 }
00481
00482
00483 template <class T>
00484 int findPeaks(const Image<T>& src, const T mi, const T ma,
00485 double& sum_activity)
00486 {
00487 GVX_TRACE(__PRETTY_FUNCTION__);
00488 Image<T> result = src;
00489 result = maxNormalize(result, mi, ma, VCXNORM_FANCY);
00490 T max, thresh; Point2D<int> max_locn; double standout = 0.0;
00491 int peaks = 0;
00492 thresh = (T)((ma - mi)/10 + mi);
00493 sum_activity = 0.0;
00494
00495 findMax(result, max_locn, max);
00496 while(max > thresh)
00497 {
00498 float area = 0.0f; double activity = 0.0; Image<byte> target;
00499 int val = segmentLandmark(result, max_locn, target,
00500 activity, standout, area);
00501 if(val != -1)
00502 {
00503 if(area > 0.0675)
00504 {
00505 peaks++;
00506 sum_activity += (double)area * activity;
00507 }
00508 result = result - result * (Image<T>)target;
00509 findMax(result, max_locn, max);
00510 }
00511 else break;
00512 }
00513 return peaks;
00514 }
00515
00516
00517 template <class T>
00518 float goodness_map(const Image<T>& src)
00519 {
00520 GVX_TRACE(__PRETTY_FUNCTION__);
00521 ASSERT(src.initialized());
00522
00523 Image<T> result = src;
00524 inplaceNormalize(result, (T)MAXNORMMIN, (T)MAXNORMLANDMARK);
00525
00526
00527
00528
00529
00530
00531
00532
00533 Image<byte> target;
00534 Image<T> comp_map;
00535 T max, thresh;
00536 float area_prev = 0.0f;
00537 int comp_next = 0;
00538 double standout = 0.0, activity_prev = 0.0;
00539 double sum_prev = 0.0, sum_next = 0.0;
00540 float goodness_map = 0.0f;
00541
00542
00543 thresh = (T) MAXNORMMIN;
00544 Point2D<int> max_locn;
00545 findMax(result, max_locn, max);
00546
00547
00548 while(max > thresh)
00549 {
00550 area_prev = 0.0f;
00551 activity_prev = 0.0, standout = 0.0 ;
00552 int val = segmentLandmark(result, max_locn, target, activity_prev,
00553 standout, area_prev);
00554
00555 if (val != -1)
00556 {
00557 result = result - result * (Image<T>)target;
00558 findMax(result, max_locn, max);
00559
00560 if(area_prev > 0.125)
00561 {
00562 sum_prev += (double)area_prev * activity_prev;
00563 }
00564 }
00565 else break;
00566 }
00567 result = src;
00568 comp_next = findPeaks(result,(T) MAXNORMMIN, (T) MAXNORMLANDMARK,
00569 sum_next);
00570
00571
00572 if(comp_next == 0)
00573 {
00574 comp_next = 10;
00575 }
00576 if (sum_prev != 0.0)
00577 goodness_map = (float)(sum_next / (sum_prev * comp_next * comp_next)) ;
00578 LINFO("# of comps = %d", comp_next);
00579 LINFO("goodness_map = %f", goodness_map);
00580
00581 return goodness_map;
00582 }
00583
00584
00585 template <class T>
00586 Image<T> maxNormalizeStdev(const Image<T>& src)
00587 {
00588
00589
00590 const float s = float(stdev(src));
00591
00592 if (s == 0.0f)
00593 return Image<T>(src.getDims(), ZEROS);
00594
00595 typedef typename promote_trait<T, float>::TP TF;
00596
00597 Image<TF> result(src);
00598 result /= s;
00599
00600 TF mini, maxi; getMinMax(result, mini, maxi);
00601 result -= mini;
00602
00603 return Image<T>(result);
00604 }
00605
00606
00607 template <class T>
00608 Image<T> maxNormalizeStdev0(const Image<T>& src)
00609 {
00610
00611
00612 const float s = float(stdev(src));
00613 const float u = float(mean(src));
00614
00615 if (s == 0.0f)
00616 return Image<T>(src.getDims(), ZEROS);
00617
00618 typedef typename promote_trait<T, float>::TP TF;
00619
00620 Image<TF> result(src);
00621 result -= u;
00622 result /= s;
00623
00624 return Image<T>(result);
00625 }
00626
00627
00628
00629
00630
00631
00632 std::string convertToString(const MaxNormType val)
00633 {
00634 GVX_TRACE(__PRETTY_FUNCTION__);
00635 return maxNormTypeName(val);
00636 }
00637
00638 void convertFromString(const std::string& str, MaxNormType& val)
00639 {
00640 GVX_TRACE(__PRETTY_FUNCTION__);
00641
00642 for (int i = 0; i < NBMAXNORMTYPES; i ++)
00643 if (str.compare(maxNormTypeName(MaxNormType(i))) == 0)
00644 { val = MaxNormType(i); return; }
00645
00646 conversion_error::raise<MaxNormType>(str);
00647 }
00648
00649
00650
00651
00652 #include "inst/Image/fancynorm.I"
00653
00654
00655
00656
00657
00658