00001
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
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
00045 std::vector<uint> areas(labels->max()+1, 0);
00046 for (size_t i = 0; i < length; i++)
00047 if (labeldata[i] != 0)
00048 areas[labeldata[i]]++;
00049
00050
00051 std::list<Region> regionlist;
00052 for (uint r = 0; r < (uint)(areas.size()); r++) {
00053 if (areas[r] >= area_thresh) {
00054
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];
00060 regionlist.push_back(cur_reg);
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)
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)
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)
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)
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
00152 int Region::findXcoordFor(const coordinate_t y_coord) {
00153 const int width = space.getWidth();
00154
00155 for (SketchIndices::CI it = table.begin();
00156 it != table.end(); it++)
00157 if ((*it)/width == y_coord)
00158 return (*it)%width;
00159
00160 return -1;
00161 }
00162
00163
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
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
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
00222 float Region::findMoment(size_t p, size_t q)
00223 {
00224
00225
00226 if(moments[p][q] != NOTCOMPUTED) {
00227 return moments[p][q];
00228 } else {
00229
00230 int xmin = findLeftBound(), xmax = findRightBound();
00231 float powp[xmax-xmin+1];
00232 for (int x = xmin; x <= xmax; x++) {
00233 if (x == 0)
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
00259
00260 if(cmoments[p][q] != NOTCOMPUTED) {
00261 return cmoments[p][q];
00262 } else {
00263 Point centroid = findCentroid();
00264 const float cx = centroid.coordX();
00265 const float cy = centroid.coordY();
00266
00267
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)
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
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
00299
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
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
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();
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
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
00372
00373
00374
00375
00376
00377
00378
00379
00380 }