Tekkotsu Homepage
Demos
Overview
Downloads
Dev. Resources
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 "Shared/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<uint>& labels, uint area_thresh)
00039 {
00040   size_t length = labels->getNumPixels();
00041   
00042   // tally up areas
00043   std::vector<uint> 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 (uint r = 0; r < (uint)(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 int Region::findTopBound() {
00090   if (topBound != NOTCOMPUTED)  // problem if NOTCOMPUTED == 0
00091     return topBound;
00092   else {
00093     SketchIndices::CI it;
00094     int top = space.getHeight();
00095     int width = space.getWidth();
00096     for (it = table.begin(); it != table.end(); it++)
00097       if (int((*it)/width) < top)
00098         top = (*it)/width;
00099     topBound = top;
00100     return top;
00101   }
00102 }
00103 
00104 int Region::findBotBound() {
00105   if (botBound != NOTCOMPUTED)  // problem if NOTCOMPUTED == 0
00106     return botBound;  
00107   else {
00108     SketchIndices::CI it;
00109     int bot = -1;
00110     int width = space.getWidth();
00111     for (it = table.begin(); it != table.end(); it++)
00112       if (int((*it+1)/width) > bot)
00113         bot = (*it)/width;
00114     botBound = bot;
00115     return bot;
00116   }
00117 }
00118 
00119 int Region::findLeftBound() {
00120   if (leftBound != NOTCOMPUTED)  // problem if NOTCOMPUTED == 0
00121     return leftBound; 
00122   else {
00123     SketchIndices::CI it;
00124     int left = 9999;
00125     int width = space.getWidth();
00126     for (it = table.begin(); it != table.end(); it++)
00127       if (int((*it)%width) < left)
00128         left = (*it)%width;
00129     leftBound = left;
00130     return left;
00131   }
00132 }
00133 
00134 int Region::findRightBound() {
00135   if (rightBound != NOTCOMPUTED)  // problem if NOTCOMPUTED == 0
00136     return rightBound;  
00137   else {
00138     SketchIndices::CI it;
00139     int right = -1;
00140     int width = space.getWidth();
00141     for (it = table.begin(); it != table.end(); it++)
00142       if (int((*it)%width) > right)
00143         right = (*it)%width;
00144     rightBound = right;
00145     return right;
00146   }
00147 }
00148 
00149 // returns x coordinate of first match Point for given y_coord
00150 int Region::findXcoordFor(const coordinate_t y_coord) {
00151   const int width = space.getWidth();
00152   //  const int width = space.getWidth()+1;
00153   for (SketchIndices::CI it = table.begin(); 
00154        it != table.end(); it++) 
00155     if ((*it)/width == y_coord) 
00156       return (*it)%width;
00157   //return (*it)%(width-1);
00158   return -1;
00159 }
00160 
00161 // returns y coordinate of first match Point for given x_coord
00162 int Region::findYcoordFor(const coordinate_t x_coord) {
00163   const int width = space.getWidth();
00164   for (SketchIndices::CI it = table.begin(); 
00165        it != table.end(); it++)
00166     if ((*it)%width == x_coord)
00167       return (*it)/width;
00168   return -1;
00169 }
00170 
00171 Point Region::findTopBoundPoint() {
00172   const coordinate_t y_coord = findTopBound();
00173   return Point(findXcoordFor(y_coord),y_coord);
00174 }
00175 Point Region::findBotBoundPoint() {
00176   const coordinate_t y_coord = findBotBound();
00177   return Point(findXcoordFor(y_coord),y_coord);
00178 }
00179 Point Region::findLeftBoundPoint() {
00180   const coordinate_t x_coord = findLeftBound();
00181   return Point(x_coord, findYcoordFor(x_coord));
00182 }
00183 Point Region::findRightBoundPoint() {
00184   const coordinate_t x_coord = findRightBound();
00185   return Point(x_coord, findYcoordFor(x_coord));
00186 }
00187 
00188 bool Region::isContained(const Point& pt, const uint max_dist) {
00189   const uint x_coord = (uint) pt.coordX();
00190   const uint y_coord = (uint) pt.coordY();
00191   const uint width = space.getWidth();
00192   //  cout << pt << endl;
00193   for (SketchIndices::CI it = table.begin(); 
00194        it != table.end(); it++)
00195     if (((*it)%width <= x_coord+max_dist && (*it)%width >= x_coord-max_dist)
00196         && ((*it)/width <= y_coord+max_dist && (*it)/width >= y_coord-max_dist))
00197       return true;
00198   return false;
00199 }
00200 
00201 Point Region::mostDistantPtFrom(const LineData& ln) {
00202   float max_dist = 0;
00203   Point most_dist_pt;
00204   const int width = space.getWidth();
00205   //  cout << pt << endl;
00206   for (SketchIndices::CI it = table.begin(); 
00207        it != table.end(); it++) {
00208     if (ln.perpendicularDistanceFrom(Point((*it)%width, (*it)/width)) > max_dist) {
00209       max_dist = ln.perpendicularDistanceFrom(Point((*it)%width, (*it)/width));
00210       most_dist_pt.setCoords((*it)%width, (*it)/width);
00211     }
00212   }
00213   return most_dist_pt;
00214 }
00215 
00216 
00217 
00218 
00219 // All moment-based equations taken from Prokop & Reeves 1992, "A survey of moment-based techniques for unoccluded object representation and recognition"
00220 float Region::findMoment(size_t p, size_t q) 
00221 {
00222   // should add in more efficient routines for some low-moments like area
00223   
00224   if(moments[p][q] != NOTCOMPUTED) {
00225     return moments[p][q];
00226   } else {
00227     // should pre-calculate powers for rows and columns, as in Flusser (1998)
00228     int xmin = findLeftBound(), xmax = findRightBound();
00229     float powp[xmax-xmin+1];
00230     for (int x = xmin; x <= xmax; x++) {
00231       if (x == 0) // if don't check for this, risk floating-point exception
00232   powp[x-xmin] = 1;
00233       else powp[x-xmin] = pow((float)(x), (float)p); 
00234     }
00235     int ymin = findTopBound(), ymax = findBotBound();
00236     float powq[ymax-ymin+1];
00237     for (int y = ymin; y <= ymax; y++) {
00238       if (y == 0)
00239   powq[y-ymin] = 1;
00240       else powq[y-ymin] = pow((float)(y), (float)q); 
00241     }
00242     
00243     float m = 0;
00244     int xval, yval;
00245     for (SketchIndices::CI it = table.begin(); it != table.end(); ++it) {
00246       xval = (*it) % space.getWidth();
00247       yval = (*it) / space.getWidth();
00248       m += powp[xval-xmin] * powq[yval-ymin];
00249     }
00250     moments[p][q] = m;
00251     return m;
00252   }
00253 }
00254 
00255 float Region::findCentralMoment(size_t p, size_t q) {
00256   // should add in more efficient routines for some low-moments like area
00257   
00258   if(cmoments[p][q] != NOTCOMPUTED) {
00259     return cmoments[p][q];
00260   } else {
00261     Point centroid = findCentroid(); //cen.first;
00262     const float cx = centroid.coordX();
00263     const float cy = centroid.coordY();
00264     
00265     // should pre-calculate powers for rows and columns, as in Flusser (1998)
00266     int xmin = findLeftBound(), xmax = findRightBound();
00267     float powp[xmax-xmin+1];
00268     for (int x = xmin; x <= xmax; x++) {
00269       if ((x-cx)==0) // if don't check for this, risk floating-point exception
00270   powp[x-xmin] = 1;
00271       else powp[x-xmin] = pow((float)(x-cx), (float)p); 
00272     }
00273     int ymin = findTopBound(), ymax = findBotBound();
00274     float powq[ymax-ymin+1];
00275     for (int y = ymin; y <= ymax; y++) {
00276       if ((y-cy)==0)
00277   powq[y-ymin] = 1;
00278       else powq[y-ymin] = pow((float)(y-cy), (float)q); 
00279     }
00280     
00281     float m = 0;
00282     int xval, yval;
00283     for (SketchIndices::CI it = table.begin(); it != table.end(); ++it) {
00284       xval = (*it) % space.getWidth();
00285       yval = (*it) / space.getWidth();
00286       //m += pow(xval,(float)p) * pow(yval,(float)q);
00287       m += powp[xval-xmin] * powq[yval-ymin];
00288     }
00289     
00290     cmoments[p][q] = m;
00291     return m;
00292   }
00293 }
00294 
00295 float Region::findNormCentralMoment(size_t p, size_t q) {
00296   // normalize
00297   // from Gonzalez & Woods (1992)
00298   float gamma = (p+q)/2 + 1;
00299   return(findCentralMoment(p,q) / pow(findArea(), gamma));
00300 }
00301 
00302 int Region::findArea() {
00303   if (area != NOTCOMPUTED)
00304     return area;
00305   else {
00306     area = table.size();
00307     return area;
00308   }
00309 }
00310 
00311 Point Region::findCentroid() {
00312   findArea();
00313   return Point(findMoment(1,0)/area, findMoment(0,1)/area);
00314   //  centroid.first = findMoment(1,0)/findMoment(0,0);
00315   //  centroid.second = findMoment(0,1)/findMoment(0,0);
00316   //  return centroid;
00317   
00318   /*  if (centroid.first != NOTCOMPUTED) {
00319   return centroid;
00320   } else {
00321   int xsum = 0, ysum = 0;
00322   typedef SketchIndices::const_iterator CI;
00323   for (CI i = begin(); i != end(); ++i) {
00324   xsum += (*i) % space.getWidth();
00325   ysum += (*i) / space.getWidth();
00326   }
00327   centroid.first = xsum/findArea();
00328   centroid.second = ysum/findArea();
00329   return centroid;
00330   }*/
00331 }
00332 
00333 AngPi Region::findPrincipalAxisOrientation() {
00334   return AngPi((0.5)*atan2(2*findCentralMoment(1,1), 
00335          findCentralMoment(2,0)-findCentralMoment(0,2)));
00336 }
00337 
00338 float Region::findSemiMajorAxisLength() {
00339   float u20 = findCentralMoment(2,0);
00340   float u02 = findCentralMoment(0,2);
00341   float u11 = findCentralMoment(1,1);
00342   //  float u00 = findCentralMoment(0,0);
00343   float u00 = findArea();
00344   return sqrt((2.0*(u20+u02+sqrt((u20-u02)*(u20-u02)+4*u11*u11)))/u00);
00345 }
00346 
00347 float Region::findSemiMinorAxisLength() {
00348   float u20 = findCentralMoment(2,0);
00349   float u02 = findCentralMoment(0,2);
00350   float u11 = findCentralMoment(1,1);
00351   // float u00 = findCentralMoment(0,0);
00352   float u00 = findArea();
00353   return sqrt((2.0*(u20+u02-sqrt((u20-u02)*(u20-u02)+4*u11*u11)))/u00);
00354 }
00355 
00356 /* FIX THIS
00357 float Region::findRadius() {
00358   float u20 = findCentralMoment(2,0);
00359   float u02 = findCentralMoment(0,2);
00360   float u00 = findArea();
00361   return sqrt((2.0*(u20+u02))/u00);
00362 }
00363 */
00364 
00365 } // namespace

DualCoding 4.0
Generated Thu Nov 22 00:52:36 2007 by Doxygen 1.5.4