Homepage Demos Overview Downloads Tutorials Reference
Credits

Region.cc

Go to the documentation of this file.
00001 //-*-c++-*-
00002 #include <cmath>
00003 #include <vector>
00004 #include <list>
00005 
00006 #include "Measures.h"
00007 #include "SketchSpace.h"
00008 #include "SketchIndices.h"
00009 #include "Sketch.h"
00010 
00011 #include "Region.h"
00012 
00013 namespace DualCoding {
00014 
00015 // be careful about changing this value, b/c memset writes bytes
00016 #define NOTCOMPUTED 0
00017 
00018 Region::Region(const SketchSpace& _space) : 
00019   SketchIndices(), space(_space),
00020   topBound(NOTCOMPUTED), botBound(NOTCOMPUTED), 
00021   leftBound(NOTCOMPUTED), rightBound(NOTCOMPUTED),
00022   area(NOTCOMPUTED)
00023 { 
00024   memset(&moments, NOTCOMPUTED, sizeof(float)*(MAX_MOMENT+1)*(MAX_MOMENT+1));
00025   memset(&cmoments, NOTCOMPUTED, sizeof(float)*(MAX_MOMENT+1)*(MAX_MOMENT+1));
00026 }
00027 
00028 void Region::recomputeProperties() {
00029   topBound = NOTCOMPUTED;
00030   botBound = NOTCOMPUTED; 
00031   leftBound = NOTCOMPUTED;
00032   rightBound = NOTCOMPUTED;
00033   area = NOTCOMPUTED;
00034   memset(&moments, NOTCOMPUTED, sizeof(float)*(MAX_MOMENT+1)*(MAX_MOMENT+1));
00035   memset(&cmoments, NOTCOMPUTED, sizeof(float)*(MAX_MOMENT+1)*(MAX_MOMENT+1));
00036 }
00037 
00038 std::list<Region> Region::extractRegions(const Sketch<usint>& labels, int area_thresh)
00039 {
00040   size_t length = labels->getNumPixels();
00041   
00042   // tally up areas
00043   vector<int> areas(labels->max()+1, 0); // not having +1 may have caused malloc crash
00044   for (size_t i = 0; i < length; i++)
00045     if (labels[i] != 0)
00046       areas[labels[i]]++; 
00047   
00048   // add unsorted Regions to list
00049   std::list<Region> regionlist;
00050   for (int r = 0; r < (int)(areas.size()); r++) {
00051     if (areas[r] >= area_thresh) {
00052       // construct Region and add to list
00053       Region cur_reg(labels->getSpace());
00054       for (size_t i = 0; i < length; i++)
00055   if (labels[i] == r)
00056     cur_reg.table.insert(i);
00057       cur_reg.area = areas[r]; // go ahead and pre-set area
00058       regionlist.push_back(cur_reg); // actually calls copy constructor
00059     }
00060   }
00061   
00062   regionlist.sort();
00063   return regionlist;
00064 }
00065 
00066 
00067 Region Region::extractRegion(const Sketch<bool>& sketch)
00068 {
00069   size_t length = sketch->getNumPixels();
00070 
00071   Region cur_reg(sketch->getSpace());
00072 
00073   int area = 0;
00074 
00075   for (size_t i = 0; i< length; i++) {
00076     if (sketch[i]) {
00077       area++;
00078       cur_reg.table.insert(i);
00079     }
00080   }
00081 
00082   cur_reg.area = area;
00083 
00084   return cur_reg;
00085 }
00086 
00087 bool Region::operator< (const Region& other) const { return (area > other.area); }
00088 
00089 
00090 
00091 int Region::findTopBound() {
00092   if (topBound != NOTCOMPUTED)  // problem if NOTCOMPUTED == 0
00093     return topBound;
00094   else {
00095     SketchIndices::CI it;
00096     int top = 9999;
00097     int temp = 0;
00098     int width = space.getWidth();
00099     //int width = space.getWidth()+1;
00100     for (it = table.begin(); it != table.end(); it++)
00101       if ((*it)/width < top) {
00102   top = (*it)/width;
00103   temp = *it;
00104       }
00105     //    cout << "Top bound: " << temp << " / " << width << " = " << top << endl;
00106     topBound = top;
00107     return top;
00108   }
00109 }
00110 
00111 int Region::findBotBound() {
00112   if (botBound != NOTCOMPUTED)  // problem if NOTCOMPUTED == 0
00113     return botBound;  
00114   else {
00115     SketchIndices::CI it;
00116     int bot = -1;
00117     int width = space.getWidth();
00118     //int width = space.getWidth()+1;
00119     for (it = table.begin(); it != table.end(); it++)
00120       if ((*it+1)/width > bot)
00121   bot = (*it)/width;
00122     botBound = bot;
00123     return bot;
00124   }
00125 }
00126 
00127 int Region::findLeftBound() {
00128   if (leftBound != NOTCOMPUTED)  // problem if NOTCOMPUTED == 0
00129     return leftBound; 
00130   else {
00131     SketchIndices::CI it;
00132     int left = 9999;
00133     int width = space.getWidth();
00134     for (it = table.begin(); it != table.end(); it++)
00135       if ((*it)%width < left)
00136   left = (*it)%width;
00137     leftBound = left;
00138     return left;
00139   }
00140 }
00141 
00142 int Region::findRightBound() {
00143   if (rightBound != NOTCOMPUTED)  // problem if NOTCOMPUTED == 0
00144     return rightBound;  
00145   else {
00146     SketchIndices::CI it;
00147     int right = -1;
00148     int width = space.getWidth();
00149     for (it = table.begin(); it != table.end(); it++)
00150       if ((*it)%width > right)
00151   right = (*it)%width;
00152     rightBound = right;
00153     return right;
00154   }
00155 }
00156 
00157 // returns x coordinate of first match Point for given y_coord
00158 int Region::findXcoordFor(const coordinate_t y_coord) {
00159   const int width = space.getWidth();
00160   //  const int width = space.getWidth()+1;
00161   for (SketchIndices::CI it = table.begin(); 
00162        it != table.end(); it++) 
00163     if ((*it)/width == y_coord) 
00164       return (*it)%width;
00165   //return (*it)%(width-1);
00166   return -1;
00167 }
00168 
00169 // returns y coordinate of first match Point for given x_coord
00170 int Region::findYcoordFor(const coordinate_t x_coord) {
00171   const int width = space.getWidth();
00172   for (SketchIndices::CI it = table.begin(); 
00173        it != table.end(); it++)
00174     if ((*it)%width == x_coord)
00175       return (*it)/width;
00176   return -1;
00177 }
00178 
00179 Point Region::findTopBoundPoint() {
00180   const coordinate_t y_coord = findTopBound();
00181   return Point(findXcoordFor(y_coord),y_coord);
00182 }
00183 Point Region::findBotBoundPoint() {
00184   const coordinate_t y_coord = findBotBound();
00185   return Point(findXcoordFor(y_coord),y_coord);
00186 }
00187 Point Region::findLeftBoundPoint() {
00188   const coordinate_t x_coord = findLeftBound();
00189   return Point(x_coord, findYcoordFor(x_coord));
00190 }
00191 Point Region::findRightBoundPoint() {
00192   const coordinate_t x_coord = findRightBound();
00193   return Point(x_coord, findYcoordFor(x_coord));
00194 }
00195 
00196 bool Region::isContained(const Point& pt, const int max_dist) {
00197   const int x_coord = (int) pt.coordX();
00198   const int y_coord = (int) pt.coordY();
00199   const int width = space.getWidth();
00200   //  cout << pt << endl;
00201   for (SketchIndices::CI it = table.begin(); 
00202        it != table.end(); it++)
00203     if (((*it)%width <= x_coord+max_dist && (*it)%width >= x_coord-max_dist)
00204   && ((*it)/width <= y_coord+max_dist && (*it)/width >= y_coord-max_dist))
00205       return true;
00206   return false;
00207 }
00208 
00209 Point Region::mostDistantPtFrom(const LineData& ln) {
00210   float max_dist = 0;
00211   Point most_dist_pt;
00212   const int width = space.getWidth();
00213   //  cout << pt << endl;
00214   for (SketchIndices::CI it = table.begin(); 
00215        it != table.end(); it++) {
00216     if (ln.perpendicularDistanceFrom(Point((*it)%width, (*it)/width)) > max_dist) {
00217       max_dist = ln.perpendicularDistanceFrom(Point((*it)%width, (*it)/width));
00218       most_dist_pt.setCoords((*it)%width, (*it)/width);
00219     }
00220   }
00221   return most_dist_pt;
00222 }
00223 
00224 
00225 
00226 
00227 // All moment-based equations taken from Prokop & Reeves 1992, "A survey of moment-based techniques for unoccluded object representation and recognition"
00228 float Region::findMoment(size_t p, size_t q) 
00229 {
00230   // should add in more efficient routines for some low-moments like area
00231   
00232   if(moments[p][q] != NOTCOMPUTED) {
00233     return moments[p][q];
00234   } else {
00235     // should pre-calculate powers for rows and columns, as in Flusser (1998)
00236     int xmin = findLeftBound(), xmax = findRightBound();
00237     float powp[xmax-xmin+1];
00238     for (int x = xmin; x <= xmax; x++) {
00239       if (x == 0) // if don't check for this, risk floating-point exception
00240   powp[x-xmin] = 1;
00241       else powp[x-xmin] = pow((float)(x), (float)p); 
00242     }
00243     int ymin = findTopBound(), ymax = findBotBound();
00244     float powq[ymax-ymin+1];
00245     for (int y = ymin; y <= ymax; y++) {
00246       if (y == 0)
00247   powq[y-ymin] = 1;
00248       else powq[y-ymin] = pow((float)(y), (float)q); 
00249     }
00250     
00251     float m = 0;
00252     int xval, yval;
00253     for (SketchIndices::CI it = table.begin(); it != table.end(); ++it) {
00254       xval = (*it) % space.getWidth();
00255       yval = (*it) / space.getWidth();
00256       m += powp[xval-xmin] * powq[yval-ymin];
00257     }
00258     moments[p][q] = m;
00259     return m;
00260   }
00261 }
00262 
00263 float Region::findCentralMoment(size_t p, size_t q) {
00264   // should add in more efficient routines for some low-moments like area
00265   
00266   if(cmoments[p][q] != NOTCOMPUTED) {
00267     return cmoments[p][q];
00268   } else {
00269     Point centroid = findCentroid(); //cen.first;
00270     const float cx = centroid.coordX();
00271     const float cy = centroid.coordY();
00272     
00273     // should pre-calculate powers for rows and columns, as in Flusser (1998)
00274     int xmin = findLeftBound(), xmax = findRightBound();
00275     float powp[xmax-xmin+1];
00276     for (int x = xmin; x <= xmax; x++) {
00277       if ((x-cx)==0) // if don't check for this, risk floating-point exception
00278   powp[x-xmin] = 1;
00279       else powp[x-xmin] = pow((float)(x-cx), (float)p); 
00280     }
00281     int ymin = findTopBound(), ymax = findBotBound();
00282     float powq[ymax-ymin+1];
00283     for (int y = ymin; y <= ymax; y++) {
00284       if ((y-cy)==0)
00285   powq[y-ymin] = 1;
00286       else powq[y-ymin] = pow((float)(y-cy), (float)q); 
00287     }
00288     
00289     float m = 0;
00290     int xval, yval;
00291     for (SketchIndices::CI it = table.begin(); it != table.end(); ++it) {
00292       xval = (*it) % space.getWidth();
00293       yval = (*it) / space.getWidth();
00294       //m += pow(xval,(float)p) * pow(yval,(float)q);
00295       m += powp[xval-xmin] * powq[yval-ymin];
00296     }
00297     
00298     cmoments[p][q] = m;
00299     return m;
00300   }
00301 }
00302 
00303 float Region::findNormCentralMoment(size_t p, size_t q) {
00304   // normalize
00305   // from Gonzalez & Woods (1992)
00306   float gamma = (p+q)/2 + 1;
00307   return(findCentralMoment(p,q) / pow(findArea(), gamma));
00308 }
00309 
00310 int Region::findArea() {
00311   if (area != NOTCOMPUTED)
00312     return area;
00313   else {
00314     area = table.size();
00315     return area;
00316   }
00317 }
00318 
00319 Point Region::findCentroid() {
00320   findArea();
00321   return Point(findMoment(1,0)/area, findMoment(0,1)/area);
00322   //  centroid.first = findMoment(1,0)/findMoment(0,0);
00323   //  centroid.second = findMoment(0,1)/findMoment(0,0);
00324   //  return centroid;
00325   
00326   /*  if (centroid.first != NOTCOMPUTED) {
00327   return centroid;
00328   } else {
00329   int xsum = 0, ysum = 0;
00330   typedef SketchIndices::const_iterator CI;
00331   for (CI i = begin(); i != end(); ++i) {
00332   xsum += (*i) % space.getWidth();
00333   ysum += (*i) / space.getWidth();
00334   }
00335   centroid.first = xsum/findArea();
00336   centroid.second = ysum/findArea();
00337   return centroid;
00338   }*/
00339 }
00340 
00341 AngPi Region::findPrincipalAxisOrientation() {
00342   return AngPi((0.5)*atan2(2*findCentralMoment(1,1), 
00343          findCentralMoment(2,0)-findCentralMoment(0,2)));
00344 }
00345 
00346 float Region::findSemiMajorAxisLength() {
00347   float u20 = findCentralMoment(2,0);
00348   float u02 = findCentralMoment(0,2);
00349   float u11 = findCentralMoment(1,1);
00350   //  float u00 = findCentralMoment(0,0);
00351   float u00 = findArea();
00352   return sqrt((2.0*(u20+u02+sqrt((u20-u02)*(u20-u02)+4*u11*u11)))/u00);
00353 }
00354 
00355 float Region::findSemiMinorAxisLength() {
00356   float u20 = findCentralMoment(2,0);
00357   float u02 = findCentralMoment(0,2);
00358   float u11 = findCentralMoment(1,1);
00359   // float u00 = findCentralMoment(0,0);
00360   float u00 = findArea();
00361   return sqrt((2.0*(u20+u02-sqrt((u20-u02)*(u20-u02)+4*u11*u11)))/u00);
00362 }
00363 
00364 /* FIX THIS
00365 float Region::findRadius() {
00366   float u20 = findCentralMoment(2,0);
00367   float u02 = findCentralMoment(0,2);
00368   float u00 = findArea();
00369   return sqrt((2.0*(u20+u02))/u00);
00370 }
00371 */
00372 
00373 } // namespace

DualCoding 3.0beta
Generated Wed Oct 4 00:01:54 2006 by Doxygen 1.4.7