00001
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
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
00043 std::vector<uint> 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 (uint r = 0; r < (uint)(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 int Region::findTopBound() {
00090 if (topBound != NOTCOMPUTED)
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)
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)
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)
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
00150 int Region::findXcoordFor(const coordinate_t y_coord) {
00151 const int width = space.getWidth();
00152
00153 for (SketchIndices::CI it = table.begin();
00154 it != table.end(); it++)
00155 if ((*it)/width == y_coord)
00156 return (*it)%width;
00157
00158 return -1;
00159 }
00160
00161
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
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
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
00220 float Region::findMoment(size_t p, size_t q)
00221 {
00222
00223
00224 if(moments[p][q] != NOTCOMPUTED) {
00225 return moments[p][q];
00226 } else {
00227
00228 int xmin = findLeftBound(), xmax = findRightBound();
00229 float powp[xmax-xmin+1];
00230 for (int x = xmin; x <= xmax; x++) {
00231 if (x == 0)
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
00257
00258 if(cmoments[p][q] != NOTCOMPUTED) {
00259 return cmoments[p][q];
00260 } else {
00261 Point centroid = findCentroid();
00262 const float cx = centroid.coordX();
00263 const float cy = centroid.coordY();
00264
00265
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)
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
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
00297
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
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
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
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
00352 float u00 = findArea();
00353 return sqrt((2.0*(u20+u02-sqrt((u20-u02)*(u20-u02)+4*u11*u11)))/u00);
00354 }
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365 }