00001
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;
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;
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
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
00054
00055 newFrontier = frontier[*space.idxN] + frontier[*space.idxS]
00056 + frontier[*space.idxW] + frontier[*space.idxE]
00057 - (obstInds + frontier + oldFrontier);
00058 newFrontier.trimBounds(space);
00059
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
00076
00077 Sketch<uint> dist("edist("+target->getName()+")", target);
00078 dist = maxdist;
00079 dist->setColorMap(jetMapScaled);
00080
00081
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
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
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
00141 CMVision::ConnectComponents(rle_buffer,numRuns);
00142 int const maxRegions = (sketch.width * sketch.height) / 16;
00143 CMVision::region *regions = new CMVision::region[maxRegions];
00144 unsigned int numRegions = CMVision::ExtractRegions(regions, maxRegions, rle_buffer, numRuns);
00145 int const numColors = 2;
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
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
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);
00166 }
00167 }
00168 }
00169
00170 delete[] ccs;
00171 delete[] regions;
00172 delete[] rle_buffer;
00173 return result;
00174 }
00175
00176
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
00187
00188
00189 std::vector<int> eq_classes(500);
00190 eq_classes.clear();
00191 eq_classes.push_back(0);
00192 int highest_label = 0;
00193 int up_label = 0;
00194 int left_label = 0;
00195 int ul_label = 0;
00196 int ur_label = 0;
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;
00207
00208 eq_classes.push_back(highest_label);
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
00225
00226
00227 int root = up_label;
00228 while (eq_classes[root] != root) {
00229 root = eq_classes[root];
00230 }
00231
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;
00236 tmp_root = next_root;
00237 }
00238
00239 eq_classes[left_label] = root;
00240 labels(i,j) = root;
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
00246 int root = ur_label;
00247 while (eq_classes[root] != root) {
00248 root = eq_classes[root];
00249 }
00250
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;
00255 tmp_root = next_root;
00256 }
00257
00258 eq_classes[left_label] = root;
00259 labels(i,j) = root;
00260 }
00261 }
00262 }
00263 }
00264
00265
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
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++;
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++;
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
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443
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
00455 NEW_SKETCH_N(regions, uint, oldlabelcc(! borders, visops::FourWayConnect));
00456 NEW_SKETCH_N(result, bool, regions == regions->at(index));
00457 return result;
00458 }
00459
00460
00461 void fillExteriorHelper(const Sketch<uint> ®ions, 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
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
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
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);
00602
00603 setup_brightness_lut(&bp,brightness,6);
00604
00605
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
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);
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 }