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

DualCoding 5.1CVS
Generated Mon May 9 04:56:27 2016 by Doxygen 1.6.3