Tekkotsu Homepage
Demos
Overview
Downloads
Dev. Resources
Reference
Credits

visops.cc

Go to the documentation of this file.
00001 //-*-c++-*-
00002 
00003 #include <math.h>
00004 #include "susan.h"
00005 
00006 #include "visops.h"
00007 
00008 using namespace DualCoding;
00009 
00010 namespace visops {
00011 
00012 Sketch<bool> zeros(SketchSpace& space) {
00013   Sketch<bool> result(space,"zeros()");
00014   *result.pixels = 0;  // valarray assignment
00015   return result;
00016 }
00017 
00018 Sketch<bool> zeros(const SketchRoot& other) {
00019   const Sketch<bool>& fake = reinterpret_cast<const Sketch<bool>&>(other);
00020   Sketch<bool> result("zeros("+fake->getName()+")", fake);
00021   *result.pixels = 0;  // valarray assignment
00022   return result;
00023 }
00024 
00025 Sketch<bool> colormask(const Sketch<uchar>& src, const std::string &colorname) {
00026   return colormask(src, ProjectInterface::getColorIndex(colorname));
00027 }
00028 
00029 Sketch<bool> colormask(const Sketch<uchar>& src, color_index cindex) {
00030   Sketch<bool> result(src == cindex);
00031   result->setColor(ProjectInterface::getColorRGB(cindex));
00032   return result;
00033 }
00034 
00035 Sketch<uint> bdist(const Sketch<bool>& dest, 
00036           const Sketch<bool>& obst, 
00037           const uint maxdist) {
00038   SketchSpace &space = dest->getSpace();
00039   space.requireIdx4way();
00040   Sketch<uint> result("bdist("+dest->getName()+","+obst->getName()+")", dest);
00041   result = maxdist;
00042   result->setColorMap(jetMapScaled);
00043   
00044   // Start at the target and iteratively expand out the frontier
00045   SketchIndices frontier;
00046   frontier.addIndices(dest);
00047   result.setIndices(frontier, 0);
00048   SketchIndices obstInds;
00049   obstInds.addIndices(obst);
00050   SketchIndices newFrontier, oldFrontier;
00051 
00052   for (uint dist = 1; dist < maxdist; dist++) {
00053     // newFrontier should become all values adjacent to frontier, not
00054     // actually in the frontier, not a boundary, or in oldFrontier
00055     newFrontier = frontier[*space.idxN] + frontier[*space.idxS] 
00056       + frontier[*space.idxW] + frontier[*space.idxE]
00057       - (obstInds + frontier + oldFrontier);
00058     newFrontier.trimBounds(space);
00059     // if no more frontier, done
00060     if (newFrontier.table.empty())
00061       break;
00062     result.setIndices(newFrontier, dist);
00063     oldFrontier = frontier;
00064     frontier = newFrontier;
00065   }
00066   
00067   return result;
00068 }
00069 
00070 Sketch<uint> edist(const Sketch<bool>& target) {
00071   SketchSpace &space = target->getSpace();
00072   const int width = space.getWidth();
00073   const int height = space.getHeight();
00074   const uint maxdist = width + height + 1;
00075   // at the moment doing 4-pass linear Manhattan distance, but should
00076   // probably use linear-time Euclidean algorithm described in 
00077   Sketch<uint> dist("edist("+target->getName()+")", target);
00078   dist = maxdist;
00079   dist->setColorMap(jetMapScaled);
00080   
00081   // find min distances within each row
00082   for (int j = 0; j < height; j++) {
00083     for (int i = 0, cur_dist = maxdist; i < width; i++) {
00084       if (target(i,j) == 1)
00085         dist(i,j) = cur_dist = 0;
00086       else if (dist(i,j) < (uint)cur_dist)
00087         cur_dist = dist(i,j);
00088       else dist(i,j) = cur_dist;
00089       cur_dist++;
00090     }
00091     for (int i = width-1, cur_dist = maxdist; i >= 0; i--) {
00092       if (target(i,j) == true)
00093   dist(i,j) = cur_dist = 0;
00094       else if (dist(i,j) < (uint)cur_dist)
00095   cur_dist = dist(i,j);
00096       else
00097   dist(i,j) = cur_dist;
00098       cur_dist++;
00099     }
00100   }
00101   // find min distances within each column
00102   for (int i = 0; i < width; i++) {
00103     for (int j = 0, cur_dist = maxdist; j < height; j++) {
00104       if (target(i,j) == 1)
00105         dist(i,j) = cur_dist = 0;
00106       else if (dist(i,j) < (uint)cur_dist)
00107         cur_dist = dist(i,j);
00108       else
00109         dist(i,j) = cur_dist;
00110       cur_dist++;
00111     }
00112     for (int j = height-1, cur_dist = maxdist; j  >= 0; j--) {
00113       if (target(i,j) == 1)
00114         dist(i,j) = cur_dist = 0;
00115       else if (dist(i,j) < (uint)cur_dist)
00116         cur_dist = dist(i,j);
00117       else
00118         dist(i,j) = cur_dist;
00119       cur_dist++;
00120     }
00121   }
00122   return dist;
00123 }
00124 
00125 Sketch<uint> labelcc(const Sketch<bool>& sketch, int minarea) {
00126   Sketch<uchar> temp;
00127   uchar *pixels;
00128   if ( sizeof(bool) == sizeof(uchar) )
00129     pixels = reinterpret_cast<uchar*>(&((*sketch.pixels)[0]));
00130   else {
00131     temp.bind((Sketch<uchar>)sketch);
00132     pixels = &((*temp.pixels)[0]);
00133   }
00134 
00135   // convert pixel array to RLE
00136   int const maxRuns = (sketch.width * sketch.height) / 8;
00137   CMVision::run<uchar> *rle_buffer = new CMVision::run<uchar>[maxRuns];
00138   unsigned int const numRuns = CMVision::EncodeRuns(rle_buffer, pixels, sketch.width, sketch.height, maxRuns);
00139 
00140   // convert RLE to region list
00141   CMVision::ConnectComponents(rle_buffer,numRuns);
00142   int const maxRegions = (sketch.width * sketch.height) / 16;   // formula from RegionGenerator.h
00143   CMVision::region *regions = new CMVision::region[maxRegions];
00144   unsigned int numRegions = CMVision::ExtractRegions(regions, maxRegions, rle_buffer, numRuns);
00145   int const numColors = 2;  // only two colors in a Sketch<bool>: 0 and 1
00146   CMVision::color_class_state *ccs = new CMVision::color_class_state[numColors];
00147   unsigned int const maxArea = CMVision::SeparateRegions(ccs, numColors, regions, numRegions);
00148   CMVision::SortRegions(ccs, numColors, maxArea);
00149   CMVision::MergeRegions(ccs, numColors, rle_buffer);
00150 
00151   // extract regions from region list
00152   NEW_SKETCH_N(result, uint, visops::zeros(sketch));
00153   result->setColorMap(jetMapScaled);
00154   const CMVision::region* list_head = ccs[1].list;
00155   if ( list_head != NULL ) {
00156     for (int label=1; list_head!=NULL && list_head->area >= minarea;
00157      list_head = list_head->next, label++) {
00158       // the first run might be array element 0, so use -1 as end of list test
00159       for (int runidx = list_head->run_start; runidx != -1;
00160      runidx = rle_buffer[runidx].next ? rle_buffer[runidx].next : -1) {
00161   const CMVision::run<uchar> &this_run = rle_buffer[runidx];
00162   const int xstop = this_run.x + this_run.width;
00163   const int yi = this_run.y;
00164   for ( int xi = this_run.x; xi < xstop; xi++ )
00165     result(xi,yi) = label * sketch(xi,yi); // the * undoes some of CMVision's noise removal
00166       }
00167     }
00168   }
00169 
00170   delete[] ccs;
00171   delete[] regions;
00172   delete[] rle_buffer;
00173   return result;
00174 }
00175 
00176 // written with guidance from this page: http://www.dai.ed.ac.uk/HIPR2/label.htm
00177 Sketch<uint> oldlabelcc(const Sketch<bool>& source, Connectivity_t connectivity)
00178 {
00179   bool conn8 = (connectivity == EightWayConnect);
00180   const int width = source.width;
00181   const int height = source.height;
00182   Sketch<uint> labels("oldlabelcc("+source->getName()+")",source);
00183   labels = 0;
00184   labels->setColorMap(jetMapScaled);
00185   
00186   // First scan: Give initial labels and sort connected label classes
00187   // into equivalence classes using UNION-FIND
00188   // Doing something similar to tree-based UNION-FIND, without the tree
00189   std::vector<int> eq_classes(500); // vector of equivalence classes for union-find
00190   eq_classes.clear();
00191   eq_classes.push_back(0); // added just so that indices match up with labels
00192   int highest_label = 0;
00193   int up_label = 0; // value above current pixel
00194   int left_label = 0; // value to left of current pixel
00195   int ul_label = 0; // value to upper-left of current pixel
00196   int ur_label = 0; // value to upper-right of current pixel
00197   for(int j = 0; j < height; j++) {
00198     for(int i = 0; i < width; i++) {
00199       if (source(i,j)) {
00200   up_label = (j == 0) ? 0 : labels(i,j-1);
00201   left_label = (i==0) ? 0 : labels(i-1,j); 
00202   ul_label = (i==0||j==0) ? 0 : labels(i-1,j-1);
00203   ur_label = (i==(width-1)||j==0) ? 0 : labels(i+1,j-1);
00204   if (up_label == 0 && left_label == 0
00205       && (!conn8 || (ul_label == 0 && ur_label == 0))) {
00206     labels(i,j) = ++highest_label;  // create new label
00207     // push back a new root label
00208     eq_classes.push_back(highest_label); // label value will be equal to index
00209   } else if (up_label && !left_label) {
00210     labels(i,j) = up_label;
00211   } else if (conn8 && !up_label && ur_label) {
00212     labels(i,j) = ur_label;
00213   } else if (left_label && !up_label) {
00214     labels(i,j) = left_label;
00215   } else if (conn8 && !left_label && !up_label 
00216        && ur_label && !ul_label) {
00217     labels(i,j) = ur_label; 
00218   } else if (conn8 && !left_label && !up_label
00219        && ul_label && !ur_label){
00220     labels(i,j) = ul_label; 
00221   }
00222   
00223   if (up_label && left_label && (up_label != left_label)) {
00224     // form union between two equivalence classes
00225     // if upper-left, assume equivalence class already made
00226     
00227     int root = up_label;
00228     while (eq_classes[root] != root) {
00229       root = eq_classes[root]; // "FIND" of UNION-FIND
00230     }
00231     // should do path compression to make more efficient
00232     int tmp_root = up_label, next_root;
00233     while(eq_classes[tmp_root] != root) {
00234       next_root = eq_classes[tmp_root];
00235       eq_classes[tmp_root] = root; // compress
00236       tmp_root = next_root;
00237     }
00238     
00239     eq_classes[left_label] = root; // "UNION" of UNION-FIND
00240     labels(i,j) = root; // not sure why putting this here works, but it does
00241   } else if (up_label && (up_label == left_label)) {
00242     labels(i,j) = up_label; 
00243   } else if (conn8 && ur_label && left_label 
00244        && (ur_label != left_label)) {
00245     // form union between two equivalence classes
00246     int root = ur_label;
00247     while (eq_classes[root] != root) {
00248       root = eq_classes[root]; // "FIND" of UNION-FIND
00249     }
00250     // should do path compression to make more efficient
00251     int tmp_root = ur_label, next_root;
00252     while(eq_classes[tmp_root] != root) {
00253       next_root = eq_classes[tmp_root];
00254       eq_classes[tmp_root] = root; // compress
00255       tmp_root = next_root;
00256     }
00257     
00258     eq_classes[left_label] = root; // "UNION" of UNION-FIND
00259     labels(i,j) = root; // not sure why putting this here works, but it does
00260   }
00261       }
00262     }
00263   }
00264   
00265   // Second scan: 
00266   int cur_label;
00267   for(int j = 0; j < height; j++) {
00268     for(int i = 0; i < width; i++) {
00269       cur_label = labels(i,j);
00270       if (cur_label != 0) {
00271   while(eq_classes[cur_label] != cur_label) {
00272     cur_label = eq_classes[cur_label];  
00273   }
00274   labels(i,j) = cur_label;
00275       }
00276       
00277     }
00278   }
00279   
00280   return labels;
00281 }
00282 
00283 Sketch<uint> areacc(const Sketch<bool>& source, Connectivity_t connectivity) {
00284   NEW_SKETCH_N(labels, uint, visops::oldlabelcc(source,connectivity));
00285   return visops::areacc(labels);
00286 }
00287 
00288 Sketch<uint> areacc(const Sketch<uint>& labels) {
00289   std::vector<int> areas(1+labels->max(), 0);
00290   for (uint i = 0; i<labels->getNumPixels(); i++)
00291     ++areas[labels[i]];
00292   areas[0] = 0;
00293   Sketch<uint> result("areacc("+labels->getName()+")",labels);
00294   for (uint i = 0; i<labels->getNumPixels(); i++)
00295     result[i] = areas[labels[i]];
00296   return result;
00297 }
00298 
00299 Sketch<bool> minArea(const Sketch<bool>& sketch, int minval) {
00300   NEW_SKETCH_N(labels, uint, visops::labelcc(sketch));
00301   NEW_SKETCH_N(areas, uint, visops::areacc(labels));
00302   NEW_SKETCH_N(result, bool, areas >= minval);
00303   return result;
00304 }
00305 
00306 Sketch<uchar> neighborSum(const Sketch<bool>& im, Connectivity_t connectivity) 
00307 {
00308   // using index redirection method
00309   SketchSpace &space = im->getSpace();
00310 
00311   space.requireIdx4way();
00312   if (connectivity == EightWayConnect)
00313     space.requireIdx8way();
00314 
00315   Sketch<uchar> result("neighborSum("+im->getName()+")", im);
00316   result->setColorMap(jetMapScaled);
00317   for ( unsigned int i = 0; i < im->getNumPixels(); i++ ) {
00318     uchar cnt = (uchar)im[(*space.idxN)[i]] +
00319       (uchar)im[(*space.idxS)[i]] +
00320       (uchar)im[(*space.idxE)[i]] +
00321       (uchar)im[(*space.idxW)[i]];
00322     if (connectivity == EightWayConnect)
00323       cnt += (uchar)im[(*space.idxNE)[i]] +
00324   (uchar)im[(*space.idxNW)[i]] +
00325   (uchar)im[(*space.idxSE)[i]] +
00326   (uchar)im[(*space.idxSW)[i]];
00327     result[i] = cnt;
00328   }
00329   return result;
00330 }
00331 
00332 Sketch<bool> fillin(const Sketch<bool>& im, int iter, 
00333           uchar min_thresh, uchar max_thresh, bool remove_only)
00334 {
00335   Sketch<bool> result(im);
00336   if ( remove_only )
00337     result.bind(visops::copy(im));
00338   Sketch<uchar> neighborCount(im);
00339   if (remove_only) {
00340     neighborCount.bind(neighborSum(result,EightWayConnect));
00341     result &= (neighborCount <= max_thresh);
00342     for (int i = 0; i < iter; i++)
00343       result &= (neighborCount >= min_thresh);
00344   }
00345   else {
00346     for (int i = 0; i < iter; i++) {
00347       neighborCount.bind(neighborSum(result,EightWayConnect));
00348       result.bind((neighborCount >= min_thresh) & (neighborCount <= max_thresh));
00349     }
00350   }
00351   result->setName("fillin("+im->getName()+")");
00352   result->setColor(im->getColor());
00353   return result;
00354 }
00355 
00356 Sketch<bool> edge(const Sketch<bool> &im) {
00357   im->getSpace().requireIdx4way();
00358   SketchSpace &space = im->getSpace();
00359   return (im != im[*space.idxS] | im != im[*space.idxE]);
00360 }
00361 
00362 
00363 Sketch<bool> horsym(const Sketch<bool> &im, int minskip, int maxskip)
00364 {
00365   NEW_SKETCH_N(result, bool, visops::zeros(im));
00366   result->setName("horsym("+im->getName()+")");
00367   const int width = im->getWidth();
00368   const int height = im->getHeight();
00369 
00370   for (int j = 0; j < height; j++) {
00371     for (int i = 0; i < width; i++) {
00372       while (i < width && !im(i,j)) i++; // skip over empty pixels
00373       for (int k = i+1; k <= width; k++) {
00374     if ( k==width || !im(k,j)) {
00375       if ( (k-i) >= minskip && (k-i) <= maxskip ) {
00376         const int u = (i+k)/2;
00377         result(u,j) = true;
00378       }
00379       i=k+1;
00380       break;
00381     }
00382       }
00383     }
00384   }
00385   return result;
00386 }
00387 
00388 Sketch<bool> versym(const Sketch<bool> &im, int minskip, int maxskip)
00389 {
00390   NEW_SKETCH_N(result, bool, visops::zeros(im));
00391   result->setName("horsym("+im->getName()+")");
00392   const int width = im->getWidth();
00393   const int height = im->getHeight();
00394 
00395   for (int i = 0; i < width; i++) {
00396     for (int j = 0; j < height; j++) {
00397       while (j < height && !im(i,j)) j++; // skip over empty pixels
00398       for (int k = j+1; k <= height; k++) {
00399     if ( k==height || !im(i,k)) {
00400       if ( (k-j) >= minskip && (k-j) <= maxskip ) {
00401         const int u = (j+k)/2;
00402         result(i,u) = true;
00403       }
00404       j=k+1;
00405       break;
00406     }
00407       }
00408     }
00409   }
00410   return result;
00411 }
00412 
00413 
00414 /*
00415 Sketch<bool> versym(const Sketch<bool>& im, int minskip, int maxskip)
00416 {
00417   NEW_SKETCH_N(result, bool, visops::zeros(im));
00418   result->setName("versym("+im->getName()+")");
00419   int height = im->getWidth();
00420   int width = im->getHeight();
00421   
00422   for (int j = 0; j < height; j++) {
00423     for (int i = 0; i < width; i++) {
00424       if (im(j,i)) {
00425   while (i < width-1 && im(j,i+1)) {
00426     i++; // skip over contiguous pixels
00427   }
00428   for (int k = i+1; k < width; k++) {
00429     if (k-i > maxskip)
00430       break;
00431     else if (im(j,k)) {
00432       if ((k-i) < minskip)
00433         break;
00434       int u = (i+k)/2;
00435       if (!im(j,u))
00436         result(j,u) = true; // was result(j,u) = k-i when this returned a Sketch<int>
00437       break; // only works well for non-'donut' ellipses
00438     }
00439   }
00440       }
00441     }
00442   }
00443   return result;
00444 }
00445 */
00446 
00447 Sketch<bool> skel(const Sketch<bool>& im) {
00448   NEW_SKETCH_N(result, bool, horsym(im) | versym(im));
00449   result->setName("skel("+im->getName()+")");
00450   return result;
00451 }
00452 
00453 Sketch<bool> seedfill(const Sketch<bool>& borders, size_t index) {
00454   // use four-way connect so thin diagonal line can function as a boundary
00455   NEW_SKETCH_N(regions, uint, oldlabelcc(! borders, visops::FourWayConnect));
00456   NEW_SKETCH_N(result, bool, regions == regions->at(index));  // use at() to do bounds checking
00457   return result;
00458 }
00459 
00460 // helper function called only inside visops::fillExterior
00461 void fillExteriorHelper(const Sketch<uint> &regions, Sketch<bool> &result, std::vector<bool> &processed, 
00462       const int x, const int y) {
00463   const uint c = regions(x,y);
00464   if ( c > 0 && !processed[c] ) {
00465     result |= (regions == c);
00466     processed[c] = true;
00467   }
00468 }
00469 
00470 Sketch<bool> fillExterior(const Sketch<bool>& borders) {
00471   // use four-way connect so thin diagonal line can function as a boundary
00472   NEW_SKETCH_N(regions, uint, oldlabelcc(! borders, visops::FourWayConnect));
00473   const uint numreg = regions->max();
00474   std::vector<bool> processed(numreg+1,false);
00475   NEW_SKETCH_N(result, bool, visops::zeros(borders));
00476   for ( int x = 0; x < result.width; x++ ) {
00477     fillExteriorHelper(regions,result,processed,x,0);
00478     fillExteriorHelper(regions,result,processed,x,result.height-1);
00479   }
00480   for ( int y = 0; y < result.height; y++ ) {
00481     fillExteriorHelper(regions,result,processed,0,y);
00482     fillExteriorHelper(regions,result,processed,result.width-1,y);
00483   }
00484   return result;
00485 }
00486 
00487 Sketch<bool> fillInterior(const Sketch<bool>& borders) {
00488   return ! (borders | fillExterior(borders));
00489 }
00490 
00491 Sketch<bool> leftHalfPlane(const Shape<LineData> &ln) {
00492   SketchSpace &SkS = ln->getSpace().getDualSpace();
00493   //! @todo **** THIS visops::leftHalfPlane CODE NEEDS TO CHECK THE SketchSpace ReferenceFrameType **** BECAUSE "left" MEANS DIFFERENT THINGS IN DIFFERENT FRAMES 
00494   int const x1 = (int)ln->end1Pt().coordX();
00495   int const y1 = (int)ln->end1Pt().coordY();
00496   int const x2 = (int)ln->end2Pt().coordX();
00497   int const y2 = (int)ln->end2Pt().coordY();
00498   float const m = (x1 == x2) ? BIG_SLOPE : (y2-y1) / (x2-x1);
00499   int const b = (int) (y1 - x1*m);
00500   int seed;
00501   if ( x1 == x2 )
00502     seed = ( x1 <= 0 ) ? -1 : 0;
00503   else if ( ln->getOrientation() > M_PI/2 )
00504     seed =  ( b <= 0) ? -1 : 0;
00505   else {
00506     int const lim = SkS.getHeight() - 1;
00507     seed =  ( b < lim ) ? (int)(*SkS.idx)(0,lim) : -1;
00508   }
00509   if ( seed == -1 ) {
00510     NEW_SKETCH_N(result, bool, visops::zeros(SkS));
00511     result->inheritFrom(ln);
00512     return result;
00513   } else {
00514     NEW_SHAPE_N(line_copy, LineData, ln->copy());
00515     line_copy->setInfinite();
00516     NEW_SKETCH_N(bounds, bool, line_copy->getRendering());
00517     bounds->inheritFrom(ln);
00518     return visops::seedfill(bounds,seed);
00519   }
00520 }
00521 
00522 Sketch<bool> rightHalfPlane(const Shape<LineData> &ln) {
00523     NEW_SHAPE_N(line_copy, LineData, ln->copy());
00524     line_copy->setInfinite();
00525     NEW_SKETCH_N(bounds, bool, line_copy->getRendering());
00526     bounds->inheritFrom(ln);
00527     return ! (visops::leftHalfPlane(ln) | bounds);
00528 }
00529 
00530 Sketch<bool> topHalfPlane(const Shape<LineData> &ln) {
00531   SketchSpace &SkS = ln->getSpace().getDualSpace();
00532   //! @todo **** visops::topHalfPlane needs to check the SketchSpace ReferenceFrameType because "left" means different things in different reference frames 
00533   int const x1 = (int)ln->end1Pt().coordX();
00534   int const y1 = (int)ln->end1Pt().coordY();
00535   int const x2 = (int)ln->end2Pt().coordX();
00536   int const y2 = (int)ln->end2Pt().coordY();
00537   float const m = (x1 == x2) ? BIG_SLOPE : (y2-y1) / (x2-x1);
00538   int const b = (int) (y1 - x1*m);
00539   int seed;
00540   if ( x1 == x2 )
00541     seed = ( y1 <= 0 ) ? -1 : 0;
00542   else if ( ln->getOrientation() > M_PI/2 )
00543     seed =  ( b <= 0) ? -1 : 0;
00544   else {
00545     int const lim = SkS.getWidth() - 1;
00546     seed =  ( int(m*lim+b) > 0 ) ? (int)(*SkS.idx)(lim,0) : -1;
00547   }
00548   if ( seed == -1 ) {
00549     NEW_SKETCH_N(result, bool, visops::zeros(SkS));
00550     result->inheritFrom(ln);
00551     return result;
00552   } else {
00553     NEW_SHAPE_N(line_copy, LineData, ln->copy());
00554     line_copy->setInfinite();
00555     NEW_SKETCH_N(bounds, bool, line_copy->getRendering());
00556     bounds->inheritFrom(ln);
00557     return visops::seedfill(bounds,seed);
00558   }
00559 }
00560 
00561 Sketch<bool> bottomHalfPlane(const Shape<LineData> &ln) {
00562     NEW_SHAPE_N(line_copy, LineData, ln->copy());
00563     line_copy->setInfinite();
00564     NEW_SKETCH_N(bounds, bool, line_copy->getRendering());
00565     bounds->inheritFrom(ln);
00566     return ! (visops::topHalfPlane(ln) | bounds);
00567 }
00568 
00569 Sketch<bool> non_bounds(const Sketch<bool>& im, int offset) {
00570   const int width = im->getWidth();
00571   const int height = im->getHeight();
00572   NEW_SKETCH_N(nbresult,bool,visops::copy(im));
00573   nbresult->setName("non_bounds("+im->getName()+")");
00574 
00575   for (int i = 0; i < width; i++) {
00576     for (int j = 0; j < offset; j++) {
00577       nbresult(i,j) = false;
00578       nbresult(i,height-j-1) = false;
00579     }
00580   }
00581   for (int i = 0; i < offset; i++) {
00582     for (int j = offset; j < height-offset; j++) {
00583       nbresult(i,j) = false;
00584       nbresult(width-i-1,j) = false;
00585     }
00586   }
00587   return nbresult;
00588 }
00589 
00590 
00591 Sketch<uchar> susan_edges(const Sketch<uchar>& im, int brightness)
00592 {
00593   const int width = im->getWidth();
00594   const int height = im->getHeight();
00595   unsigned char *bp;
00596   Sketch<uchar> edges(visops::copy(im));
00597 
00598   int *r = (int *)malloc(width*height*sizeof(int));
00599 
00600   unsigned char *mid = (unsigned char *)malloc(width*height);
00601   memset (mid,100,width * height); /* note not set to zero */
00602 
00603   setup_brightness_lut(&bp,brightness,6);
00604 
00605   // susan_principle(im->getRawPixels(),edges->getRawPixels(), &bp, 2650, width, height);
00606 
00607   susan_edges_internal(edges->getRawPixels(), r, mid, bp, 2650, width, height);
00608 
00609   susan_thin(r, mid, width, height);
00610 
00611   edge_draw(edges->getRawPixels(),mid,width,height,0);
00612 
00613    free(r);
00614    free(mid);
00615    free(bp-258);
00616 
00617   return edges;
00618 }
00619 
00620 
00621 // Default brightness was 20 for original algorithm
00622 Sketch<bool> susan_edge_points(const Sketch<uchar>& im, int brightness)
00623 {
00624   const int width = im->getWidth();
00625   const int height = im->getHeight();
00626   unsigned char *bp;
00627   Sketch<uchar> orig(im);
00628   Sketch<uchar> edges(visops::zeros(im));
00629   int *r = (int *)malloc(width*height*sizeof(int));
00630   unsigned char *mid = (unsigned char *)malloc(width*height);
00631   memset(mid,100,width * height); /* note not set to zero */
00632   setup_brightness_lut(&bp,brightness,6);
00633   susan_edges_internal(orig->getRawPixels(), r, mid, bp, 2650, width, height);
00634   susan_thin(r, mid, width, height);
00635   edge_draw(edges->getRawPixels(),mid,width,height,1);
00636   free(r);
00637   free(mid);
00638   Sketch<bool> result(edges);
00639   return result;
00640 }
00641 
00642 Sketch<uint> convolve(const Sketch<uchar> &sketch, Sketch<uchar> &kernel, 
00643            int istart, int jstart, int width, int height) {
00644   Sketch<uint> result("convolve("+sketch->getName()+")",sketch);
00645   result->setColorMap(jetMapScaled);
00646   int const di = - (int)(width/2);
00647   int const dj = - (int)(height/2);
00648   for (int si=0; si<sketch.width; si++)
00649     for (int sj=0; sj<sketch.height; sj++) {
00650       int sum = 0;
00651       for (int ki=0; ki<width; ki++)
00652   for (int kj=0; kj<height; kj++)
00653     if ( si+di+ki >= 0 && si+di+ki < sketch.width &&
00654          sj+dj+kj >= 0 && sj+dj+kj < sketch.height )
00655       sum += (uint)sketch(si+di+ki,sj+dj+kj) * (uint)kernel(istart+ki,jstart+kj);
00656       result(si,sj) = sum/(width*height);
00657     }
00658   return result;      
00659 }
00660 
00661 Sketch<uint> templateMatch(const Sketch<uchar> &sketch, Sketch<uchar> &kernel, 
00662            int istart, int jstart, int width, int height) {
00663   Sketch<uint> result("convolve0("+sketch->getName()+")",sketch);
00664   result->setColorMap(jetMapScaled);
00665   int const npix = width * height;
00666   int const di = - (int)(width/2);
00667   int const dj = - (int)(height/2);
00668   for (int si=0; si<sketch.width; si++)
00669     for (int sj=0; sj<sketch.height; sj++) {
00670       int sum = 0;
00671       for (int ki=0; ki<width; ki++)
00672   for (int kj=0; kj<height; kj++) {
00673     int k_pix = kernel(istart+ki,jstart+kj);
00674     if ( si+di+ki >= 0 && si+di+ki < sketch.width &&
00675          sj+dj+kj >= 0 && sj+dj+kj < sketch.height ) {
00676       int s_pix = sketch(si+di+ki,sj+dj+kj);
00677       sum +=  (s_pix - k_pix) * (s_pix - k_pix);
00678     }
00679     else
00680       sum += k_pix * k_pix;
00681   }
00682       result(si,sj) =  65535 - uint(sqrt(sum/float(npix)));
00683     }
00684   result = result - result->min();
00685   return result;
00686 }
00687 
00688 
00689 } // namespace

DualCoding 4.0
Generated Thu Nov 22 00:52:37 2007 by Doxygen 1.5.4