00001
00002
00003 #include <math.h>
00004 #include "susan.h"
00005
00006 #include "visops.h"
00007 #include "Vision/cmvision.h"
00008
00009 using namespace DualCoding;
00010
00011 namespace visops {
00012
00013 Sketch<bool> zeros(SketchSpace& space) {
00014 Sketch<bool> result(space,"zeros()");
00015 *result.pixels = 0;
00016 return result;
00017 }
00018
00019 Sketch<bool> zeros(const SketchRoot& other) {
00020 const Sketch<bool>& fake = reinterpret_cast<const Sketch<bool>&>(other);
00021 Sketch<bool> result("zeros("+fake->getName()+")", fake);
00022 *result.pixels = 0;
00023 return result;
00024 }
00025
00026 Sketch<bool> colormask(const Sketch<uchar>& src, const std::string &colorname) {
00027 return colormask(src, ProjectInterface::getColorIndex(colorname));
00028 }
00029
00030 Sketch<bool> colormask(const Sketch<uchar>& src, color_index cindex) {
00031 Sketch<bool> result(src == cindex);
00032 result->setColor(ProjectInterface::getColorRGB(cindex));
00033 return result;
00034 }
00035
00036 std::vector<xyPair> boundaryPoints(const Sketch<uint>& dest, uint& mindist, const uint maxval) {
00037 SketchSpace &space = dest->getSpace();
00038 const int width = space.getWidth();
00039 const int height = space.getHeight();
00040 std::vector<xyPair> boundaryPt;
00041 boundaryPt.clear();
00042 mindist = maxval;
00043
00044 for (int i=1; i<width-1; i++)
00045 for (int j=1; j<height-1; j++)
00046 if (dest(i,j)<maxval)
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064 if ( dest(i,j-1)==maxval ||
00065 dest(i-1,j)==maxval ||
00066 dest(i+1,j)==maxval ||
00067 dest(i,j+1)==maxval )
00068 {
00069 boundaryPt.push_back(xyPair(i,j));
00070 if (dest(i,j)<mindist) mindist = dest(i,j);
00071 }
00072
00073 return boundaryPt;
00074 }
00075
00076 bool radiate(const xyPair center, Sketch<uint>& dist, const Sketch<bool>& dest, const Sketch<bool>& obst, const uint maxval) {
00077 SketchSpace &space = dist->getSpace();
00078 const int width = space.getWidth();
00079 const int height = space.getHeight();
00080 const int ctxiw = center.first;
00081 const int ctyjh = center.second;
00082 const uint centerdis = dist(ctxiw,ctyjh);
00083
00084 float r[360];
00085 int theta[5];
00086 for (int i=0; i<360; i++) r[i]=maxval;
00087 for (int i=1; i<width-1; i++)
00088 for (int j=1; j<height-1; j++) {
00089 if (i==ctxiw && j== ctyjh) continue;
00090
00091 else if (obst(i,j)) {
00092 if ((i-1==ctxiw && j== ctyjh)) {r[0]=1;continue;}
00093 if ((i+1==ctxiw && j==ctyjh)) {r[180]=1;continue;}
00094 if ((i==ctxiw && j-1==ctyjh)) {r[270]=1;continue;}
00095 if ((i==ctxiw && j+1==ctyjh)) {r[90]=1;continue;}
00096 float temp = std::sqrt( (j-ctyjh)*(j-ctyjh) + (i-ctxiw)*(i-ctxiw) );
00097 theta[0] = int(std::atan2(j-ctyjh, i-ctxiw)*180/M_PI+360)%360;
00098 theta[1] = int(std::atan2(j-ctyjh, i+1-ctxiw)*180/M_PI+360)%360;
00099 theta[2] = int(std::atan2(j-1-ctyjh, i-ctxiw)*180/M_PI+360)%360;
00100 theta[3] = int(std::atan2(j-ctyjh, i-1-ctxiw)*180/M_PI+360)%360;
00101 theta[4] = int(std::atan2(j+1-ctyjh, i-ctxiw)*180/M_PI+360)%360;
00102 bool area1 = false;
00103 bool area4 = false;
00104 for (int k=0; k<5; k++) {
00105 if (theta[k] >=0 && theta[k] < 90) area1 = true;
00106 else if (theta[k] >=270 && theta[k] < 360) area4 = true;
00107 }
00108 if (area1 && area4) {
00109 for (int k=0; k<5; k++)
00110 if (theta[k]<=90) theta[k]+=360;
00111 }
00112 int start = 1000;
00113 int end = -1;
00114 for (int k=0; k<5; k++) {
00115 if (start>theta[k]) start = theta[k];
00116 if (end<theta[k]) end = theta[k];
00117 }
00118 for (int k=start; k<=end+1; k++)
00119 if (r[k%360] > temp) r[k%360] = temp;
00120 }
00121 }
00122
00123 bool changed = false;
00124 for (int i=0; i<width; i++)
00125 for (int j=0; j<height; j++) {
00126 if (obst(i,j) || dest(i,j)) continue;
00127 int thet = int(std::atan2(j-ctyjh, i-ctxiw)*180/M_PI+360)%360;
00128 float temp = std::sqrt( (j-ctyjh)*(j-ctyjh) + (i-ctxiw)*(i-ctxiw) );
00129
00130 if ( temp<r[thet] && dist(i,j)>centerdis+temp) {
00131 dist(i,j) = centerdis+temp;
00132 changed = true;
00133 }
00134 }
00135
00136 return changed;
00137 }
00138
00139 Sketch<uint> ebdist(const Sketch<bool>& dest, const Sketch<bool>& obst, const uint maxdist, const uint time) {
00140 SketchSpace &space = dest->getSpace();
00141 const int width = space.getWidth();
00142 const int height = space.getHeight();
00143 const uint maxval = (uint)-2;
00144
00145 Sketch<uint> distSk("ebdist("+dest->getName()+","+obst->getName()+")", dest);
00146 distSk = maxval;
00147 distSk->setColorMap(jetMapScaled);
00148
00149 for (int i=0; i<width; i++)
00150 for (int j=0; j<height; j++)
00151 if (dest(i,j)) distSk(i,j)=0;
00152
00153 for (int i=0; i<width; i++)
00154 for (int j=0; j<height; j++)
00155 if (obst(i,j)) distSk(i,j)=maxval+1;
00156
00157 bool finish = false;
00158 uint t = 0;
00159 uint mindist;
00160 std::vector<xyPair> boundary = boundaryPoints(distSk, mindist, maxval);
00161 if (boundary.size() == 0) finish = true;
00162 else if (mindist >= maxval) finish = true;
00163 while (!finish) {
00164 bool changed = false;
00165 for(std::vector<xyPair>::iterator it=boundary.begin(); it!=boundary.end(); it++) {
00166 if (radiate(*it, distSk, dest, obst, maxval)) changed = true;
00167 }
00168
00169
00170
00171
00172
00173 t++;
00174 if (!changed) break;
00175 if (t >= time && time!=0) break;
00176 boundary = boundaryPoints(distSk, mindist, maxval);
00177 if (boundary.size() == 0) break;
00178 else if (mindist >= maxval) break;
00179 }
00180
00181 std::cout << "Run radiate for " << t << " times." << std::endl;
00182 for (int i=0; i<width; i++)
00183 for (int j=0; j<height; j++)
00184 if ( distSk(i,j) > maxdist ) distSk(i,j)=maxdist;
00185
00186 return distSk;
00187 }
00188
00189 Sketch<uint> bdist(const Sketch<bool>& dest,
00190 const Sketch<bool>& obst,
00191 const uint maxdist) {
00192 SketchSpace &space = dest->getSpace();
00193 space.requireIdx4way();
00194 Sketch<uint> result("bdist("+dest->getName()+","+obst->getName()+")", dest);
00195 result = maxdist;
00196 result->setColorMap(jetMapScaled);
00197
00198
00199 SketchIndices frontier;
00200 frontier.addIndices(dest);
00201 result.setIndices(frontier, 0);
00202 SketchIndices obstInds;
00203 obstInds.addIndices(obst);
00204 SketchIndices newFrontier, oldFrontier;
00205
00206 for (uint dist = 1; dist < maxdist; dist++) {
00207
00208
00209 newFrontier = frontier[*space.idxN] + frontier[*space.idxS]
00210 + frontier[*space.idxW] + frontier[*space.idxE]
00211 - (obstInds + frontier + oldFrontier);
00212 newFrontier.trimBounds(space);
00213
00214 if (newFrontier.table.empty())
00215 break;
00216 result.setIndices(newFrontier, dist);
00217 oldFrontier = frontier;
00218 frontier = newFrontier;
00219 }
00220
00221 return result;
00222 }
00223
00224 Sketch<uint> mdist(const Sketch<bool>& targetSk) {
00225 SketchSpace &space = targetSk->getSpace();
00226 const size_t width = space.getWidth();
00227 const size_t height = space.getHeight();
00228 const uint maxdist = width + height + 1;
00229
00230
00231 Sketch<uint> distSk("mdist("+targetSk->getName()+")", targetSk);
00232 distSk = maxdist;
00233 distSk->setColorMap(jetMapScaled);
00234
00235 SketchData<bool>& target = *targetSk.data;
00236 SketchData<uint>& dist = *distSk.data;
00237 uint cur_dist;
00238
00239
00240 for (size_t j = 0; j < height; j++) {
00241 cur_dist = maxdist;
00242 const bool* targetrow = &target(0,j);
00243 uint* distrow = &dist(0,j);
00244 for (size_t i = 0; i < width; i++) {
00245 if (targetrow[i] == 1)
00246 distrow[i] = cur_dist = 0;
00247 else if (distrow[i] < (uint)cur_dist)
00248 cur_dist = distrow[i];
00249 else distrow[i] = cur_dist;
00250 cur_dist++;
00251 }
00252 cur_dist = maxdist;
00253 for (size_t i = width; i > 0; ) {
00254 --i;
00255 if (targetrow[i] == true)
00256 distrow[i] = cur_dist = 0;
00257 else if (distrow[i] < (uint)cur_dist)
00258 cur_dist = distrow[i];
00259 else
00260 distrow[i] = cur_dist;
00261 cur_dist++;
00262 }
00263 }
00264
00265 for (size_t i = 0; i < width; i++) {
00266 cur_dist = maxdist;
00267 const bool* targetcol = &target(i,0);
00268 uint* distcol = &dist(i,0);
00269 for (size_t j = 0; j < height*width; j+=width) {
00270 if (targetcol[j] == 1)
00271 distcol[j] = cur_dist = 0;
00272 else if (distcol[j] < (uint)cur_dist)
00273 cur_dist = distcol[j];
00274 else
00275 distcol[j] = cur_dist;
00276 cur_dist++;
00277 }
00278 cur_dist = maxdist;
00279 for (size_t j = height*width; j > 0; ) {
00280 j-=width;
00281 if (targetcol[j] == 1)
00282 distcol[j] = cur_dist = 0;
00283 else if (distcol[j] < (uint)cur_dist)
00284 cur_dist = distcol[j];
00285 else
00286 distcol[j] = cur_dist;
00287 cur_dist++;
00288 }
00289 }
00290 return distSk;
00291 }
00292
00293 Sketch<float> edist(const Sketch<bool>& targetSk) {
00294 SketchSpace &space = targetSk->getSpace();
00295 const size_t width = space.getWidth();
00296 const size_t height = space.getHeight();
00297 const uint maxdist = width + height + 1;
00298
00299 Sketch<uint> xVals("xVals(" + targetSk->getName() + ")", targetSk);
00300 Sketch<uint> yVals("yVals(" + targetSk->getName() + ")", targetSk);
00301 xVals = maxdist;
00302 yVals = maxdist;
00303 xVals->setColorMap(jetMapScaled);
00304 yVals->setColorMap(jetMapScaled);
00305 Sketch<float> distSk("edist("+targetSk->getName()+")", targetSk);
00306 distSk = maxdist;
00307 distSk->setColorMap(jetMapScaled);
00308
00309 uint cur_xdist, cur_ydist;
00310 float cur_dist, this_dist;
00311
00312
00313
00314
00315
00316
00317 for (int pass=0; pass<2; pass++) {
00318
00319 for (size_t j = 0; j < height; j++) {
00320 cur_xdist = maxdist;
00321 cur_ydist = maxdist;
00322 for (size_t i = 0; i < width; i++) {
00323 if (targetSk(i,j) == true) {
00324 xVals(i,j) = cur_xdist = 0;
00325 yVals(i,j) = cur_ydist = 0;
00326 } else {
00327 cur_dist = cur_xdist*cur_xdist + cur_ydist*cur_ydist;
00328 this_dist = xVals(i,j)*xVals(i,j) + yVals(i,j)*yVals(i,j);
00329 if (this_dist < cur_dist) {
00330 cur_xdist = xVals(i,j);
00331 cur_ydist = yVals(i,j);
00332 } else {
00333 xVals(i,j) = cur_xdist;
00334 yVals(i,j) = cur_ydist;
00335 }
00336 }
00337 cur_xdist++;
00338 }
00339 cur_xdist = maxdist;
00340 cur_ydist = maxdist;
00341 for (size_t i = width; i > 0; ) {
00342 i--;
00343 if (targetSk(i,j) == true) {
00344 xVals(i,j) = cur_xdist = 0;
00345 yVals(i,j) = cur_ydist = 0;
00346 } else {
00347 cur_dist = cur_xdist*cur_xdist + cur_ydist*cur_ydist;
00348 this_dist = xVals(i,j)*xVals(i,j) + yVals(i,j)*yVals(i,j);
00349 if (this_dist < cur_dist) {
00350 cur_xdist = xVals(i,j);
00351 cur_ydist = yVals(i,j);
00352 } else {
00353 xVals(i,j) = cur_xdist;
00354 yVals(i,j) = cur_ydist;
00355 }
00356 }
00357 cur_xdist++;
00358 }
00359 }
00360
00361
00362 for (size_t i = 0; i < width; i++) {
00363 cur_xdist = maxdist;
00364 cur_ydist = maxdist;
00365
00366 for (size_t j = 0; j < height; j++) {
00367 if (targetSk(i,j) == true) {
00368 xVals(i,j) = cur_xdist = 0;
00369 yVals(i,j) = cur_ydist = 0;
00370 } else {
00371 cur_dist = cur_xdist*cur_xdist + cur_ydist*cur_ydist;
00372 this_dist = xVals(i,j)*xVals(i,j) + yVals(i,j)*yVals(i,j);
00373 if (this_dist < cur_dist) {
00374 cur_xdist = xVals(i,j);
00375 cur_ydist = yVals(i,j);
00376 } else {
00377 xVals(i,j) = cur_xdist;
00378 yVals(i,j) = cur_ydist;
00379 }
00380 }
00381 cur_ydist++;
00382 }
00383 cur_xdist = maxdist;
00384 cur_ydist = maxdist;
00385 for (size_t j = height; j > 0; ) {
00386 j--;
00387 if (targetSk(i,j) == true) {
00388 xVals(i,j) = cur_xdist = 0;
00389 yVals(i,j) = cur_ydist = 0;
00390 } else {
00391 cur_dist = cur_xdist*cur_xdist + cur_ydist*cur_ydist;
00392 this_dist = xVals(i,j)*xVals(i,j) + yVals(i,j)*yVals(i,j);
00393 if (this_dist < cur_dist) {
00394 cur_xdist = xVals(i,j);
00395 cur_ydist = yVals(i,j);
00396 } else {
00397 xVals(i,j) = cur_xdist;
00398 yVals(i,j) = cur_ydist;
00399 }
00400 }
00401 cur_ydist++;
00402 }
00403 }
00404 }
00405
00406 for(unsigned i = 0; i < width; i++)
00407 for(unsigned j = 0; j < height; j++) {
00408 float x = (float)xVals(i,j), y = (float)yVals(i,j);
00409 distSk(i,j) = std::sqrt(x*x + y*y);
00410 }
00411
00412 return distSk;
00413 }
00414
00415 Sketch<uint> labelcc(const Sketch<bool>& sketch, int minarea) {
00416 Sketch<uchar> temp;
00417 uchar *pixels;
00418 if ( sizeof(bool) == sizeof(uchar) )
00419 pixels = reinterpret_cast<uchar*>(&((*sketch.pixels)[0]));
00420 else {
00421 temp.bind((Sketch<uchar>)sketch);
00422 pixels = &((*temp.pixels)[0]);
00423 }
00424
00425
00426 int const maxRuns = (sketch.width * sketch.height) / 8;
00427 CMVision::run<uchar> *rle_buffer = new CMVision::run<uchar>[maxRuns];
00428 unsigned int const numRuns = CMVision::EncodeRuns(rle_buffer, pixels, sketch.width, sketch.height, maxRuns);
00429
00430
00431 CMVision::ConnectComponents(rle_buffer,numRuns);
00432 int const maxRegions = (sketch.width * sketch.height) / 16;
00433 CMVision::region *regions = new CMVision::region[maxRegions];
00434 unsigned int numRegions = CMVision::ExtractRegions(regions, maxRegions, rle_buffer, numRuns);
00435 int const numColors = 2;
00436 CMVision::color_class_state *ccs = new CMVision::color_class_state[numColors];
00437 unsigned int const maxArea = CMVision::SeparateRegions(ccs, numColors, regions, numRegions);
00438 CMVision::SortRegions(ccs, numColors, maxArea);
00439 CMVision::MergeRegions(ccs, numColors, rle_buffer);
00440
00441
00442 NEW_SKETCH_N(result, uint, visops::zeros(sketch));
00443 result->setColorMap(jetMapScaled);
00444 const CMVision::region* list_head = ccs[1].list;
00445 if ( list_head != NULL ) {
00446 for (int label=1; list_head!=NULL && list_head->area >= minarea;
00447 list_head = list_head->next, label++) {
00448
00449 for (int runidx = list_head->run_start; runidx != -1;
00450 runidx = rle_buffer[runidx].next ? rle_buffer[runidx].next : -1) {
00451 const CMVision::run<uchar> &this_run = rle_buffer[runidx];
00452 const int xstop = this_run.x + this_run.width;
00453 const int yi = this_run.y;
00454 for ( int xi = this_run.x; xi < xstop; xi++ )
00455 result(xi,yi) = label * sketch(xi,yi);
00456 }
00457 }
00458 }
00459
00460 delete[] ccs;
00461 delete[] regions;
00462 delete[] rle_buffer;
00463 return result;
00464 }
00465
00466
00467 Sketch<uint> oldlabelcc(const Sketch<bool>& source, Connectivity_t connectivity)
00468 {
00469 bool conn8 = (connectivity == EightWayConnect);
00470 const int width = source.width;
00471 const int height = source.height;
00472 Sketch<uint> labels("oldlabelcc("+source->getName()+")",source);
00473 labels = 0;
00474 labels->setColorMap(jetMapScaled);
00475 uint* data = labels->getRawPixels();
00476 const bool* srcdata = source->getRawPixels();
00477
00478
00479
00480
00481 std::vector<int> eq_classes(500);
00482 eq_classes.clear();
00483 eq_classes.push_back(0);
00484 int highest_label = 0;
00485 int up_label = 0;
00486 int left_label = 0;
00487 int ul_label = 0;
00488 int ur_label = 0;
00489 for(int j = 0; j < height; j++) {
00490 uint* row = &data[j*width];
00491 const bool* srcrow = &srcdata[j*width];
00492 for(int i = 0; i < width; i++) {
00493 uint* p = &row[i];
00494 if (srcrow[i]) {
00495 up_label = (j == 0) ? 0 : *(p-width);
00496 left_label = (i==0) ? 0 : *(p-1);
00497 ul_label = (i==0||j==0) ? 0 : *(p-1-width);
00498 ur_label = (i==(width-1)||j==0) ? 0 : *(p+1-width);
00499 if (up_label == 0 && left_label == 0 && (!conn8 || (ul_label == 0 && ur_label == 0))) {
00500 *p = ++highest_label;
00501
00502 eq_classes.push_back(highest_label);
00503 } else if (up_label && !left_label) {
00504 *p = up_label;
00505 } else if (conn8 && !up_label && ur_label) {
00506 *p = ur_label;
00507 } else if (left_label && !up_label) {
00508 *p = left_label;
00509 } else if (conn8 && !left_label && !up_label && ur_label && !ul_label) {
00510 *p = ur_label;
00511 } else if (conn8 && !left_label && !up_label && ul_label && !ur_label){
00512 *p = ul_label;
00513 }
00514
00515 if (up_label && left_label && (up_label != left_label)) {
00516
00517
00518
00519 int root = up_label;
00520 while (eq_classes[root] != root) {
00521 root = eq_classes[root];
00522 }
00523
00524 int tmp_root = up_label, next_root;
00525 while(eq_classes[tmp_root] != root) {
00526 next_root = eq_classes[tmp_root];
00527 eq_classes[tmp_root] = root;
00528 tmp_root = next_root;
00529 }
00530
00531 eq_classes[left_label] = root;
00532 *p = root;
00533 } else if (up_label && (up_label == left_label)) {
00534 *p = up_label;
00535 } else if (conn8 && ur_label && left_label && (ur_label != left_label)) {
00536
00537 int root = ur_label;
00538 while (eq_classes[root] != root) {
00539 root = eq_classes[root];
00540 }
00541
00542 int tmp_root = ur_label, next_root;
00543 while(eq_classes[tmp_root] != root) {
00544 next_root = eq_classes[tmp_root];
00545 eq_classes[tmp_root] = root;
00546 tmp_root = next_root;
00547 }
00548
00549 eq_classes[left_label] = root;
00550 *p = root;
00551 }
00552 }
00553 }
00554 }
00555
00556
00557 uint *p = data, *end = &data[width*height];
00558 for(; p!=end; ++p) {
00559 int cur_label=*p;
00560 if (cur_label != 0) {
00561 while(eq_classes[cur_label] != cur_label) {
00562 cur_label = eq_classes[cur_label];
00563 }
00564 *p = cur_label;
00565 }
00566 }
00567
00568 return labels;
00569 }
00570
00571 Sketch<uint> areacc(const Sketch<bool>& source, Connectivity_t connectivity) {
00572 NEW_SKETCH_N(labels, uint, visops::oldlabelcc(source,connectivity));
00573 return visops::areacc(labels);
00574 }
00575
00576 Sketch<uint> areacc(const Sketch<uint>& labels) {
00577 int const numlabels = 1 + labels->max();
00578 std::vector<int> areas(numlabels, 0);
00579 for (uint i = 0; i<labels->getNumPixels(); i++)
00580 ++areas[labels[i]];
00581 areas[0] = 0;
00582 Sketch<uint> result("areacc("+labels->getName()+")",labels);
00583 for (uint i = 0; i<labels->getNumPixels(); i++)
00584 result[i] = areas[labels[i]];
00585 return result;
00586 }
00587
00588 Sketch<bool> minArea(const Sketch<bool>& sketch, int minval) {
00589 NEW_SKETCH_N(labels, uint, visops::labelcc(sketch));
00590 NEW_SKETCH_N(areas, uint, visops::areacc(labels));
00591 NEW_SKETCH_N(result, bool, areas >= minval);
00592 return result;
00593 }
00594
00595 Sketch<uchar> neighborSum(const Sketch<bool>& im, Connectivity_t connectivity)
00596 {
00597 im.checkValid();
00598 const bool* imdata = im->getRawPixels();
00599
00600 SketchSpace &space = im->getSpace();
00601
00602 space.requireIdx4way();
00603
00604 skindex* idxN = (*space.idxN)->getRawPixels();
00605 skindex* idxS = (*space.idxS)->getRawPixels();
00606 skindex* idxE = (*space.idxE)->getRawPixels();
00607 skindex* idxW = (*space.idxW)->getRawPixels();
00608 skindex *idxNE=NULL, *idxNW=NULL, *idxSE=NULL, *idxSW=NULL;
00609
00610 if (connectivity == EightWayConnect) {
00611 space.requireIdx8way();
00612 idxNE = (*space.idxNE)->getRawPixels();
00613 idxNW = (*space.idxNW)->getRawPixels();
00614 idxSE = (*space.idxSE)->getRawPixels();
00615 idxSW = (*space.idxSW)->getRawPixels();
00616 }
00617
00618 Sketch<uchar> result("neighborSum("+im->getName()+")", im);
00619 uchar* rdata = result->getRawPixels();
00620 result->setColorMap(jetMapScaled);
00621 const unsigned int length = im->getNumPixels();
00622 for ( unsigned int i = 0; i < length; i++ ) {
00623 uchar cnt = imdata[idxN[i]] + imdata[idxS[i]] + imdata[idxE[i]] + imdata[idxW[i]];
00624 if (connectivity == EightWayConnect)
00625 cnt += imdata[idxNE[i]] + imdata[idxNW[i]] + imdata[idxSE[i]] + imdata[idxSW[i]];
00626 rdata[i] = cnt;
00627 }
00628 return result;
00629 }
00630
00631 Sketch<bool> fillin(const Sketch<bool>& im, int iter,
00632 uchar min_thresh, uchar max_thresh, bool remove_only)
00633 {
00634 Sketch<bool> result(im);
00635 if ( remove_only )
00636 result.bind(visops::copy(im));
00637 Sketch<uchar> neighborCount(im);
00638 if (remove_only) {
00639 neighborCount.bind(neighborSum(result,EightWayConnect));
00640 result &= (neighborCount <= max_thresh);
00641 for (int i = 0; i < iter; i++)
00642 result &= (neighborCount >= min_thresh);
00643 }
00644 else {
00645 for (int i = 0; i < iter; i++) {
00646 neighborCount.bind(neighborSum(result,EightWayConnect));
00647 result.bind((neighborCount >= min_thresh) & (neighborCount <= max_thresh));
00648 }
00649 }
00650 result->setName("fillin("+im->getName()+")");
00651 result->setColor(im->getColor());
00652 return result;
00653 }
00654
00655 Sketch<bool> edge(const Sketch<bool> &im) {
00656 im->getSpace().requireIdx4way();
00657 SketchSpace &space = im->getSpace();
00658 return ((im != im[*space.idxS]) | (im != im[*space.idxE]));
00659 }
00660
00661
00662 Sketch<bool> horsym(const Sketch<bool> &im, size_t minskip, size_t maxskip)
00663 {
00664 NEW_SKETCH_N(result, bool, visops::zeros(im));
00665 result->setName("horsym("+im->getName()+")");
00666 bool * rdata = result->getRawPixels();
00667 const bool * imdata = im->getRawPixels();
00668 const size_t width = im->getWidth();
00669 const size_t height = im->getHeight();
00670
00671 for (size_t j = 0; j < height; j++) {
00672 const bool * imrow = &imdata[j*width];
00673 for (size_t i = 0; i < width; i++) {
00674 while (i < width && !imrow[i]) i++;
00675 for (size_t k = i+1; k <= width; k++) {
00676 if ( k==width || !imrow[k]) {
00677 if ( (k-i) >= minskip && (k-i) <= maxskip ) {
00678 const size_t u = (i+k)/2;
00679 rdata[j*width+u] = true;
00680 }
00681 i=k+1;
00682 break;
00683 }
00684 }
00685 }
00686 }
00687 return result;
00688 }
00689
00690 Sketch<bool> versym(const Sketch<bool> &im, size_t minskip, size_t maxskip)
00691 {
00692 NEW_SKETCH_N(result, bool, visops::zeros(im));
00693 result->setName("horsym("+im->getName()+")");
00694 bool * rdata = result->getRawPixels();
00695 const bool * imdata = im->getRawPixels();
00696 const size_t width = im->getWidth();
00697 const size_t height = im->getHeight();
00698
00699 for (size_t i = 0; i < width; i++) {
00700 const bool * imcol = &imdata[i];
00701 for (size_t j = 0; j < height; j++) {
00702 while (j < height && !imcol[j*width]) j++;
00703 for (size_t k = j+1; k <= height; k++) {
00704 if ( k==height || !imcol[k*width]) {
00705 if ( (k-j) >= minskip && (k-j) <= maxskip ) {
00706 const size_t u = (j+k)/2;
00707 rdata[u*width+i] = true;
00708 }
00709 j=k+1;
00710 break;
00711 }
00712 }
00713 }
00714 }
00715 return result;
00716 }
00717
00718
00719
00720
00721
00722
00723
00724
00725
00726
00727
00728
00729
00730
00731
00732
00733
00734
00735
00736
00737
00738
00739
00740
00741
00742
00743
00744
00745
00746
00747
00748
00749
00750
00751
00752 Sketch<bool> skel(const Sketch<bool>& im) {
00753 NEW_SKETCH_N(result, bool, horsym(im) | versym(im));
00754 result->setName("skel("+im->getName()+")");
00755 return result;
00756 }
00757
00758 Sketch<bool> seedfill(const Sketch<bool>& borders, size_t index) {
00759
00760 NEW_SKETCH_N(regions, uint, oldlabelcc(! borders, visops::FourWayConnect));
00761 NEW_SKETCH_N(result, bool, regions == regions->at(index));
00762 return result;
00763 }
00764
00765
00766 void fillExteriorHelper(const Sketch<uint> ®ions, Sketch<bool> &result, std::vector<bool> &processed,
00767 const int x, const int y) {
00768 const uint c = regions(x,y);
00769 if ( c > 0 && !processed[c] ) {
00770 result |= (regions == c);
00771 processed[c] = true;
00772 }
00773 }
00774
00775 Sketch<bool> fillExterior(const Sketch<bool>& borders) {
00776
00777 NEW_SKETCH_N(regions, uint, oldlabelcc(! borders, visops::FourWayConnect));
00778 const uint numreg = regions->max();
00779 std::vector<bool> processed(numreg+1,false);
00780 NEW_SKETCH_N(result, bool, visops::zeros(borders));
00781 for ( int x = 0; x < result.width; x++ ) {
00782 fillExteriorHelper(regions,result,processed,x,0);
00783 fillExteriorHelper(regions,result,processed,x,result.height-1);
00784 }
00785 for ( int y = 0; y < result.height; y++ ) {
00786 fillExteriorHelper(regions,result,processed,0,y);
00787 fillExteriorHelper(regions,result,processed,result.width-1,y);
00788 }
00789 return result;
00790 }
00791
00792 Sketch<bool> fillInterior(const Sketch<bool>& borders) {
00793 return ! (borders | fillExterior(borders));
00794 }
00795
00796 Sketch<bool> leftHalfPlane(const Shape<LineData> &ln) {
00797 SketchSpace &SkS = ln->getSpace().getDualSpace();
00798
00799 float const x1 = ln->end1Pt().coordX();
00800 float const y1 = ln->end1Pt().coordY();
00801 float const x2 = ln->end2Pt().coordX();
00802 float const y2 = ln->end2Pt().coordY();
00803 bool const roughlyVertical = fabs(x1-x2) < 0.001;
00804 float const m = roughlyVertical ? BIG_SLOPE : (y2-y1) / (x2-x1);
00805 float const b = y1 - x1*m;
00806 int seed;
00807 if ( roughlyVertical )
00808 seed = ( x1 <= 0 ) ? -1 : 0;
00809 else if ( ln->getOrientation() > M_PI/2 )
00810 seed = ( b <= 0) ? -1 : 0;
00811 else {
00812 int const lim = SkS.getHeight() - 1;
00813 seed = ( b < lim ) ? (int)(*SkS.idx)(0,lim) : -1;
00814 }
00815 if ( seed == -1 ) {
00816 NEW_SKETCH_N(result, bool, visops::zeros(SkS));
00817 result->inheritFrom(ln);
00818 return result;
00819 } else {
00820 NEW_SHAPE_N(line_copy, LineData, ln->copy());
00821 line_copy->setInfinite();
00822 NEW_SKETCH_N(bounds, bool, line_copy->getRendering());
00823 bounds->inheritFrom(ln);
00824 return visops::seedfill(bounds,seed);
00825 }
00826 }
00827
00828 Sketch<bool> rightHalfPlane(const Shape<LineData> &ln) {
00829 NEW_SHAPE_N(line_copy, LineData, ln->copy());
00830 line_copy->setInfinite();
00831 NEW_SKETCH_N(bounds, bool, line_copy->getRendering());
00832 bounds->inheritFrom(ln);
00833 return ! (visops::leftHalfPlane(ln) | bounds);
00834 }
00835
00836 Sketch<bool> topHalfPlane(const Shape<LineData> &ln) {
00837 SketchSpace &SkS = ln->getSpace().getDualSpace();
00838
00839 float const x1 = ln->end1Pt().coordX();
00840 float const y1 = ln->end1Pt().coordY();
00841 float const x2 = ln->end2Pt().coordX();
00842 float const y2 = ln->end2Pt().coordY();
00843 bool const roughlyVertical = fabs(x1-x2) < 0.001;
00844 float const m = roughlyVertical ? BIG_SLOPE : (y2-y1) / (x2-x1);
00845 float const b = y1 - x1*m;
00846 int seed;
00847 if ( roughlyVertical )
00848 seed = ( y1 <= 0 ) ? -1 : 0;
00849 else if ( ln->getOrientation() > M_PI/2 )
00850 seed = ( b <= 0) ? -1 : 0;
00851 else {
00852 int const lim = SkS.getWidth() - 1;
00853 seed = ( int(m*lim+b) > 0 ) ? (int)(*SkS.idx)(lim,0) : -1;
00854 }
00855 if ( seed == -1 ) {
00856 NEW_SKETCH_N(result, bool, visops::zeros(SkS));
00857 result->inheritFrom(ln);
00858 return result;
00859 } else {
00860 NEW_SHAPE_N(line_copy, LineData, ln->copy());
00861 line_copy->setInfinite();
00862 NEW_SKETCH_N(bounds, bool, line_copy->getRendering());
00863 bounds->inheritFrom(ln);
00864 return visops::seedfill(bounds,seed);
00865 }
00866 }
00867
00868 Sketch<bool> bottomHalfPlane(const Shape<LineData> &ln) {
00869 NEW_SHAPE_N(line_copy, LineData, ln->copy());
00870 line_copy->setInfinite();
00871 NEW_SKETCH_N(bounds, bool, line_copy->getRendering());
00872 bounds->inheritFrom(ln);
00873 return ! (visops::topHalfPlane(ln) | bounds);
00874 }
00875
00876 Sketch<bool> non_bounds(const Sketch<bool>& im, int offset) {
00877 const int width = im->getWidth();
00878 const int height = im->getHeight();
00879 NEW_SKETCH_N(nbresult,bool,visops::copy(im));
00880 nbresult->setName("non_bounds("+im->getName()+")");
00881
00882 for (int i = 0; i < width; i++) {
00883 for (int j = 0; j < offset; j++) {
00884 nbresult(i,j) = false;
00885 nbresult(i,height-j-1) = false;
00886 }
00887 }
00888 for (int i = 0; i < offset; i++) {
00889 for (int j = offset; j < height-offset; j++) {
00890 nbresult(i,j) = false;
00891 nbresult(width-i-1,j) = false;
00892 }
00893 }
00894 return nbresult;
00895 }
00896
00897
00898 Sketch<uchar> susan_edges(const Sketch<uchar>& im, int brightness)
00899 {
00900 const int width = im->getWidth();
00901 const int height = im->getHeight();
00902 unsigned char *bp;
00903 Sketch<uchar> edges(visops::copy(im));
00904
00905 int *r = (int *)malloc(width*height*sizeof(int));
00906
00907 unsigned char *mid = (unsigned char *)malloc(width*height);
00908 memset (mid,100,width * height);
00909
00910 setup_brightness_lut(&bp,brightness,6);
00911
00912
00913
00914 susan_edges_internal(edges->getRawPixels(), r, mid, bp, 2650, width, height);
00915
00916 susan_thin(r, mid, width, height);
00917
00918 edge_draw(edges->getRawPixels(),mid,width,height,0);
00919
00920 free(r);
00921 free(mid);
00922 free(bp-258);
00923
00924 return edges;
00925 }
00926
00927
00928
00929 Sketch<bool> susan_edge_points(const Sketch<uchar>& im, int brightness)
00930 {
00931 const int width = im->getWidth();
00932 const int height = im->getHeight();
00933 unsigned char *bp;
00934 Sketch<uchar> orig(im);
00935 Sketch<uchar> edges(visops::zeros(im));
00936 int *r = (int *)malloc(width*height*sizeof(int));
00937 unsigned char *mid = (unsigned char *)malloc(width*height);
00938 memset(mid,100,width * height);
00939 setup_brightness_lut(&bp,brightness,6);
00940 susan_edges_internal(orig->getRawPixels(), r, mid, bp, 2650, width, height);
00941 susan_thin(r, mid, width, height);
00942 edge_draw(edges->getRawPixels(),mid,width,height,1);
00943 free(r);
00944 free(mid);
00945 Sketch<bool> result(edges);
00946 return result;
00947 }
00948
00949 Sketch<uint> convolve(const Sketch<uchar> &sketch, Sketch<uchar> &kernel,
00950 int istart, int jstart, int width, int height) {
00951 Sketch<uint> result("convolve("+sketch->getName()+")",sketch);
00952 result->setColorMap(jetMapScaled);
00953 int const di = - (int)(width/2);
00954 int const dj = - (int)(height/2);
00955 for (int si=0; si<sketch.width; si++)
00956 for (int sj=0; sj<sketch.height; sj++) {
00957 int sum = 0;
00958 for (int ki=0; ki<width; ki++)
00959 for (int kj=0; kj<height; kj++)
00960 if ( si+di+ki >= 0 && si+di+ki < sketch.width &&
00961 sj+dj+kj >= 0 && sj+dj+kj < sketch.height )
00962 sum += (uint)sketch(si+di+ki,sj+dj+kj) * (uint)kernel(istart+ki,jstart+kj);
00963 result(si,sj) = sum/(width*height);
00964 }
00965 return result;
00966 }
00967
00968 Sketch<uint> templateMatch(const Sketch<uchar> &sketch, Sketch<uchar> &kernel,
00969 int istart, int jstart, int width, int height) {
00970 Sketch<uint> result("convolve0("+sketch->getName()+")",sketch);
00971 result->setColorMap(jetMapScaled);
00972 int const npix = width * height;
00973 int const di = - (int)(width/2);
00974 int const dj = - (int)(height/2);
00975 for (int si=0; si<sketch.width; si++)
00976 for (int sj=0; sj<sketch.height; sj++) {
00977 int sum = 0;
00978 for (int ki=0; ki<width; ki++)
00979 for (int kj=0; kj<height; kj++) {
00980 int k_pix = kernel(istart+ki,jstart+kj);
00981 if ( si+di+ki >= 0 && si+di+ki < sketch.width &&
00982 sj+dj+kj >= 0 && sj+dj+kj < sketch.height ) {
00983 int s_pix = sketch(si+di+ki,sj+dj+kj);
00984 sum += (s_pix - k_pix) * (s_pix - k_pix);
00985 }
00986 else
00987 sum += k_pix * k_pix;
00988 }
00989 result(si,sj) = 65535 - uint(sqrt(sum/float(npix)));
00990 }
00991 result = result - result->min();
00992 return result;
00993 }
00994
00995
00996 }