00001
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
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
00043 vector<int> areas(labels->max()+1, 0);
00044 for (size_t i = 0; i < length; i++)
00045 if (labels[i] != 0)
00046 areas[labels[i]]++;
00047
00048
00049 std::list<Region> regionlist;
00050 for (int r = 0; r < (int)(areas.size()); r++) {
00051 if (areas[r] >= area_thresh) {
00052
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];
00058 regionlist.push_back(cur_reg);
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)
00093 return topBound;
00094 else {
00095 SketchIndices::CI it;
00096 int top = 9999;
00097 int temp = 0;
00098 int width = space.getWidth();
00099
00100 for (it = table.begin(); it != table.end(); it++)
00101 if ((*it)/width < top) {
00102 top = (*it)/width;
00103 temp = *it;
00104 }
00105
00106 topBound = top;
00107 return top;
00108 }
00109 }
00110
00111 int Region::findBotBound() {
00112 if (botBound != NOTCOMPUTED)
00113 return botBound;
00114 else {
00115 SketchIndices::CI it;
00116 int bot = -1;
00117 int width = space.getWidth();
00118
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)
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)
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
00158 int Region::findXcoordFor(const coordinate_t y_coord) {
00159 const int width = space.getWidth();
00160
00161 for (SketchIndices::CI it = table.begin();
00162 it != table.end(); it++)
00163 if ((*it)/width == y_coord)
00164 return (*it)%width;
00165
00166 return -1;
00167 }
00168
00169
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
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
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
00228 float Region::findMoment(size_t p, size_t q)
00229 {
00230
00231
00232 if(moments[p][q] != NOTCOMPUTED) {
00233 return moments[p][q];
00234 } else {
00235
00236 int xmin = findLeftBound(), xmax = findRightBound();
00237 float powp[xmax-xmin+1];
00238 for (int x = xmin; x <= xmax; x++) {
00239 if (x == 0)
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
00265
00266 if(cmoments[p][q] != NOTCOMPUTED) {
00267 return cmoments[p][q];
00268 } else {
00269 Point centroid = findCentroid();
00270 const float cx = centroid.coordX();
00271 const float cy = centroid.coordY();
00272
00273
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)
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
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
00305
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
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
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
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
00360 float u00 = findArea();
00361 return sqrt((2.0*(u20+u02-sqrt((u20-u02)*(u20-u02)+4*u11*u11)))/u00);
00362 }
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373 }