Changeset 13236
- Timestamp:
- May 4, 2007, 6:40:14 AM (19 years ago)
- Location:
- trunk/psphot/src
- Files:
-
- 2 edited
-
pmFootprint.c (modified) (17 diffs)
-
pmFootprint.h (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/psphot/src/pmFootprint.c
r13007 r13236 34 34 } 35 35 36 // 37 // Sort pmSpans by y, then x0, then x1 38 // 39 int pmSpanSortByYX(const void **a, const void **b) { 40 const pmSpan *sa = *(const pmSpan **)a; 41 const pmSpan *sb = *(const pmSpan **)b; 42 43 if (sa->y < sb->y) { 44 return -1; 45 } else if (sa->y == sb->y) { 46 if (sa->x0 < sb->x0) { 47 return -1; 48 } else if (sa->x0 == sb->x0) { 49 if (sa->x1 < sb->x1) { 50 return -1; 51 } else if (sa->x1 == sb->x1) { 52 return 0; 53 } else { 54 return 1; 55 } 56 } else { 57 return 1; 58 } 59 } else { 60 return 1; 61 } 62 } 63 36 64 /************************************************************************************************************/ 37 65 … … 63 91 psMemSetDeallocator(footprint, (psFreeFunc) footprintFree); 64 92 93 footprint->normalized = false; 94 65 95 assert(nspan >= 0); 66 96 footprint->npix = 0; 67 footprint->nspan = nspan;68 97 footprint->spans = psArrayAllocEmpty(nspan); 69 98 footprint->peaks = psArrayAlloc(0); … … 90 119 } 91 120 121 pmFootprint *pmFootprintNormalize(pmFootprint *fp) { 122 if (fp != NULL && !fp->normalized) { 123 fp->peaks = psArraySort(fp->peaks, pmPeakSortBySN); 124 fp->normalized = true; 125 } 126 127 return fp; 128 } 129 92 130 // 93 // Add a span to a footprint, returning the n umber of pixels in the footprint131 // Add a span to a footprint, returning the new span 94 132 // 95 static intpmFootprintAddSpan(pmFootprint *fp, // the footprint to add to96 const int y,// row to add97 int x0,// range of98 int x1) {// columns133 static pmSpan *pmFootprintAddSpan(pmFootprint *fp, // the footprint to add to 134 const int y, // row to add 135 int x0, // range of 136 int x1) { // columns 99 137 100 138 if (x1 < x0) { … … 110 148 fp->npix += x1 - x0 + 1; 111 149 112 if (fp-> nspan == 1) {150 if (fp->spans->n == 1) { 113 151 fp->bbox.x0 = x0; 114 152 fp->bbox.x1 = x1; … … 122 160 } 123 161 124 return fp->npix;162 return sp; 125 163 } 126 164 127 165 void pmFootprintSetBBox(pmFootprint *fp) { 128 166 assert (fp != NULL); 129 if (fp-> nspan == 0) {167 if (fp->spans->n == 0) { 130 168 return; 131 169 } … … 154 192 assert (fp != NULL); 155 193 int npix = 0; 156 for (int i = 0; i < fp-> nspan; i++) {194 for (int i = 0; i < fp->spans->n; i++) { 157 195 pmSpan *span = fp->spans->data[i]; 158 196 npix += span->x1 - span->x0 + 1; … … 215 253 const int npixMin) // minimum number of pixels in an acceptable pmFootprint 216 254 { 217 int *aliases; /* aliases for object IDs */218 int *id_s; /* storage for id[cp] */219 int *idc, *idp; /* object IDs in current/previous row*/220 255 int i0; /* initial value of i */ 221 256 int id; /* object ID */ … … 224 259 int nobj = 0; /* number of objects found */ 225 260 int x0 = 0; /* unpacked from a WSPAN */ 226 int size_aliases = 0; /* size of aliases[] array */227 int size_spans = 0; /* size of spans[] array */228 WSPAN *spans; /* row:x0,x1 for objects */229 261 int *tmp; /* used in swapping idc/idp */ 230 262 … … 251 283 * refer to idp[-1] and idp[numCols], hence the (numCols + 2) 252 284 */ 253 i d_s = psAlloc(2*(numCols + 2)*sizeof(int));285 int *id_s = psAlloc(2*(numCols + 2)*sizeof(int)); 254 286 memset(id_s, '\0', 2*(numCols + 2)*sizeof(int)); assert(id_s[0] == 0); 255 idc = id_s + 1; idp = idc + (numCols + 2); 256 257 size_aliases = 1 + numRows/20; 258 aliases = psAlloc(size_aliases*sizeof(int)); 259 260 size_spans = 1 + numRows/20; 261 spans = psAlloc(size_spans*sizeof(WSPAN)); 287 int *idc = id_s + 1; // object IDs in current/ 288 int *idp = idc + (numCols + 2); // previous row 289 290 int size_aliases = 1 + numRows/20; // size of aliases[] array 291 int *aliases = psAlloc(size_aliases*sizeof(int)); // aliases for object IDs 292 293 int size_spans = 1 + numRows/20; // size of spans[] array 294 WSPAN *spans = psAlloc(size_spans*sizeof(WSPAN)); // row:x0,x1 for objects 262 295 /* 263 296 * Go through image identifying objects … … 273 306 in_span = 0; /* not in a span */ 274 307 for (j = 0; j < numCols; j++) { 275 double pixVal = F32 ? imgRowF32[j] : imgRowS32[j];308 double pixVal = F32 ? imgRowF32[j] : imgRowS32[j]; 276 309 if (pixVal < threshold) { 277 310 if (in_span) { … … 395 428 /************************************************************************************************************/ 396 429 /* 397 * Worker routine for the pmSetFootprintArrayIds (and pmMergeFootprintArrays) 398 */ 430 * A data structure to hold the starting point for a search for pixels above threshold, 431 * used by pmFindFootprintAtPoint 432 * 433 * We don't want to find this span again --- it's already part of the footprint --- 434 * so we set the pixels in the image to as small a value as we can. N.b. We may want 435 * to reconsider this when dealing with difference images 436 */ 437 typedef enum {PM_SSPAN_DOWN = 0, // scan down from this span 438 PM_SSPAN_UP, // scan up from this span 439 PM_SSPAN_RESTART, // restart scanning from this span 440 PM_SSPAN_DONE // this span is processed 441 } PM_SSPAN_DIR; // How to continue searching 442 443 typedef struct { 444 const pmSpan *span; // save the pixel range 445 PM_SSPAN_DIR direction; // How to continue searching 446 // private 447 int nbyte; // number of bytes saved 448 void *data; // saved data 449 void *data_home; // where the data was saved from 450 } Startspan; 451 452 static void startspanFree(Startspan *sspan) { 453 if (sspan->nbyte > 0) { 454 memcpy(sspan->data_home, sspan->data, sspan->nbyte); // restore image's pixels to their pristine state 455 } 456 457 psFree(sspan->data); 458 psFree((void *)sspan->span); 459 } 460 461 static Startspan * 462 StartspanAlloc(const pmSpan *span, // The span in question 463 psImage *img,// the data wherein lives the span 464 const PM_SSPAN_DIR dir // Should we continue searching towards the top of the image? 465 ) { 466 Startspan *sspan = psAlloc(sizeof(Startspan)); 467 psMemSetDeallocator(sspan, (psFreeFunc)startspanFree); 468 469 sspan->span = psMemIncrRefCounter((void *)span); 470 sspan->direction = dir; 471 472 if (img == NULL) { // nothing to save 473 sspan->nbyte = 0; 474 sspan->data_home = sspan->data = NULL; 475 476 return sspan; 477 } 478 // 479 // Save the pixels, and set the image to a -ve large value 480 // 481 sspan->nbyte = (span->x1 - span->x0 + 1)*PSELEMTYPE_SIZEOF(img->type.type); 482 sspan->data = psAlloc(sspan->nbyte); 483 484 switch (img->type.type) { 485 case PS_TYPE_F32: 486 sspan->data_home = &img->data.F32[span->y - img->row0][span->x0 - img->col0]; 487 memcpy(sspan->data, sspan->data_home, sspan->nbyte); 488 489 for (int i = 0; i <= span->x1 - span->x0; i++) { 490 ((psF32 *)sspan->data_home)[i] = PS_MIN_F32; 491 } 492 break; 493 case PS_TYPE_S32: 494 sspan->data_home = &img->data.S32[span->y - img->row0][span->x0 - img->col0]; 495 memcpy(sspan->data, sspan->data_home, sspan->nbyte); 496 497 for (int i = 0; i <= span->x1 - span->x0; i++) { 498 ((psS32 *)sspan->data_home)[i] = PS_MIN_S32; 499 } 500 break; 501 default: 502 psAbort("Unsupported image type %d\n", img->type.type); 503 } 504 505 return sspan; 506 } 507 508 // 509 // Add a new Startspan to an array of Startspans 510 // 511 static void add_startspan(psArray *startspans, // the saved Startspans 512 const pmSpan *sp, // the span in question 513 const psImage *img, // image to save/restore (or NULL) 514 const PM_SSPAN_DIR dir) { // the desired direction to search 515 if (dir == PM_SSPAN_RESTART) { 516 add_startspan(startspans, sp, img, PM_SSPAN_UP); 517 add_startspan(startspans, sp, NULL, PM_SSPAN_DOWN); 518 } else { 519 Startspan *sspan = StartspanAlloc(sp, (psImage *)img, dir); 520 psArrayAdd(startspans, 1, sspan); 521 psFree(sspan); // as it's now owned by startspans 522 } 523 } 524 525 /************************************************************************************************************/ 526 /* 527 * Search the image for pixels above threshold, starting at a single Startspan. 528 * We search the array looking for one to process; it'd be better to move the 529 * ones that we're done with to the end, but it probably isn't worth it for 530 * the anticipated uses of this routine. 531 * 532 * This is the guts of pmFindFootprintAtPoint 533 */ 534 static bool do_startspan(pmFootprint *fp, // the footprint that we're building 535 const psImage *img, // the psImage we're working on 536 const float threshold, // Threshold 537 psArray *startspans) { // specify which span to process next 538 bool F32 = false; // is this an F32 image? 539 if (img->type.type == PS_TYPE_F32) { 540 F32 = true; 541 } else if (img->type.type == PS_TYPE_S32) { 542 F32 = false; 543 } else { // N.b. You can't trivially add more cases here; F32 is just a bool 544 psError(PS_ERR_UNKNOWN, true, "Unsupported psImage type: %d", img->type.type); 545 return NULL; 546 } 547 548 psF32 *imgRowF32 = NULL; // row pointer if F32 549 psS32 *imgRowS32 = NULL; // " " " " !F32 550 551 const int row0 = img->row0; 552 const int col0 = img->col0; 553 const int numRows = img->numRows; 554 const int numCols = img->numCols; 555 556 /********************************************************************************************************/ 557 558 Startspan *sspan = NULL; 559 for (int i = 0; i < startspans->n; i++) { 560 sspan = startspans->data[i]; 561 if (sspan->direction != PM_SSPAN_DONE) { 562 break; 563 } 564 } 565 if (sspan == NULL || sspan->direction == PM_SSPAN_DONE) { // no more Startspans to process 566 return false; 567 } 568 /* 569 * Work 570 */ 571 const PM_SSPAN_DIR dir = sspan->direction; 572 /* 573 * Set initial span to the startspan 574 */ 575 int x0 = sspan->span->x0 - col0, x1 = sspan->span->x1 - col0; 576 /* 577 * Go through image identifying objects 578 */ 579 int nx0, nx1 = -1; // new values of x0, x1 580 const int di = (dir == PM_SSPAN_UP) ? 1 : -1; // how much i changes to get to the next row 581 for (int i = sspan->span->y -row0 + di; i < numRows && i >= 0; i += di) { 582 imgRowF32 = img->data.F32[i]; // only one of 583 imgRowS32 = img->data.S32[i]; // these is valid! 584 // 585 // Search left from the pixel diagonally to the left of (i - di, x0). If there's 586 // a connected span there it may need to grow up and/or down, so push it onto 587 // the stack for later consideration 588 // 589 nx0 = -1; 590 for (int j = x0 - 1; j >= -1; j--) { 591 double pixVal = (j < 0) ? threshold - 100 : (F32 ? imgRowF32[j] : imgRowS32[j]); 592 if (pixVal < threshold) { 593 if (j < x0 - 1) { // we found some pixels above threshold 594 nx0 = j + 1; 595 } 596 break; 597 } 598 } 599 600 if (nx0 < 0) { // no span to the left 601 nx1 = x0 - 1; // we're going to resume searching at nx1 + 1 602 } else { 603 // 604 // Search right in leftmost span 605 // 606 //nx1 = 0; // make gcc happy 607 for (int j = nx0 + 1; j <= numCols; j++) { 608 double pixVal = (j >= numCols) ? threshold - 100 : (F32 ? imgRowF32[j] : imgRowS32[j]); 609 if (pixVal < threshold) { 610 nx1 = j - 1; 611 break; 612 } 613 } 614 615 const pmSpan *sp = pmFootprintAddSpan(fp, i + row0, nx0 + col0, nx1 + col0); 616 617 add_startspan(startspans, sp, (psImage *)img, PM_SSPAN_RESTART); 618 } 619 // 620 // Now look for spans connected to the old span. The first of these we'll 621 // simply process, but others will have to be deferred for later consideration. 622 // 623 // In fact, if the span overhangs to the right we'll have to defer the overhang 624 // until later too, as it too can grow in both directions 625 // 626 // Note that column numCols exists virtually, and always ends the last span; this 627 // is why we claim below that sx1 is always set 628 // 629 bool first = false; // is this the first new span detected? 630 for (int j = nx1 + 1; j <= x1 + 1; j++) { 631 double pixVal = (j >= numCols) ? threshold - 100 : (F32 ? imgRowF32[j] : imgRowS32[j]); 632 if (pixVal >= threshold) { 633 int sx0 = j++; // span that we're working on is sx0:sx1 634 int sx1 = -1; // We know that if we got here, we'll also set sx1 635 for (; j <= numCols; j++) { 636 double pixVal = (j >= numCols) ? threshold - 100 : (F32 ? imgRowF32[j] : imgRowS32[j]); 637 if (pixVal < threshold) { // end of span 638 sx1 = j; 639 break; 640 } 641 } 642 assert (sx1 >= 0); 643 644 const pmSpan *sp; 645 if (first) { 646 if (sx1 <= x1) { 647 sp = pmFootprintAddSpan(fp, i + row0, sx0 + col0, sx1 + col0 - 1); 648 add_startspan(startspans, sp, (psImage *)img, PM_SSPAN_DONE); 649 } else { // overhangs to right 650 sp = pmFootprintAddSpan(fp, i + row0, sx0 + col0, x1 + col0); 651 add_startspan(startspans, sp, (psImage *)img, PM_SSPAN_DONE); 652 sp = pmFootprintAddSpan(fp, i + row0, x1 + 1 + col0, sx1 + col0 - 1); 653 add_startspan(startspans, sp, (psImage *)img, PM_SSPAN_RESTART); 654 } 655 first = false; 656 } else { 657 sp = pmFootprintAddSpan(fp, i + row0, sx0 + col0, sx1 + col0 - 1); 658 add_startspan(startspans, sp, (psImage *)img, PM_SSPAN_RESTART); 659 } 660 } 661 } 662 663 if (first == false) { // we're done 664 break; 665 } 666 667 x0 = nx0; x1 = nx1; 668 } 669 /* 670 * Cleanup 671 */ 672 673 sspan->direction = PM_SSPAN_DONE; 674 return true; 675 } 676 677 /* 678 * Go through an image, starting at (row, col) and assembling all the pixels 679 * that are connected to that point (in a chess kings-move sort of way) into 680 * a pmFootprint. 681 * 682 * This is much slower than pmFindFootprints if you want to find lots of 683 * footprints, but if you only want a small region about a given point it 684 * can be much faster 685 * 686 * N.b. The returned pmFootprint is not in "normal form"; that is the pmSpans 687 * are not sorted by increasing y, x0, x1. If this matters to you, call 688 * pmFootprintNormalize() 689 */ 690 pmFootprint * 691 pmFindFootprintAtPoint(const psImage *img, // image to search 692 const float threshold, // Threshold 693 int row, int col) { // starting position (in img's parent's coordinate system) 694 assert(img != NULL); 695 696 bool F32 = false; // is this an F32 image? 697 if (img->type.type == PS_TYPE_F32) { 698 F32 = true; 699 } else if (img->type.type == PS_TYPE_S32) { 700 F32 = false; 701 } else { // N.b. You can't trivially add more cases here; F32 is just a bool 702 psError(PS_ERR_UNKNOWN, true, "Unsupported psImage type: %d", img->type.type); 703 return NULL; 704 } 705 psF32 *imgRowF32 = NULL; // row pointer if F32 706 psS32 *imgRowS32 = NULL; // " " " " !F32 707 708 const int row0 = img->row0; 709 const int col0 = img->col0; 710 const int numRows = img->numRows; 711 const int numCols = img->numCols; 712 /* 713 * Is point in image, and above threshold? 714 */ 715 row -= row0; col -= col0; 716 if (row < 0 || row >= numRows || 717 col < 0 || col >= numCols) { 718 psError(PS_ERR_BAD_PARAMETER_VALUE, true, 719 "row/col == (%d, %d) are out of bounds [%d--%d, %d--%d]", 720 row + row0, col + col0, row0, row0 + numRows - 1, col0, col0 + numCols - 1); 721 return NULL; 722 } 723 724 double pixVal = F32 ? img->data.F32[row][col] : img->data.S32[row][col]; 725 if (pixVal < threshold) { 726 return pmFootprintAlloc(0, img); 727 } 728 729 pmFootprint *fp = pmFootprintAlloc(1 + img->numRows/10, img); 730 /* 731 * Find starting span passing through (row, col) 732 */ 733 psArray *startspans = psArrayAllocEmpty(1); // spans where we have to restart the search 734 735 imgRowF32 = img->data.F32[row]; // only one of 736 imgRowS32 = img->data.S32[row]; // these is valid! 737 { 738 int i; 739 for (i = col; i >= 0; i--) { 740 pixVal = F32 ? imgRowF32[i] : imgRowS32[i]; 741 if (pixVal < threshold) { 742 break; 743 } 744 } 745 int i0 = i; 746 for (i = col; i < numCols; i++) { 747 pixVal = F32 ? imgRowF32[i] : imgRowS32[i]; 748 if (pixVal < threshold) { 749 break; 750 } 751 } 752 int i1 = i; 753 const pmSpan *sp = pmFootprintAddSpan(fp, row + row0, i0 + col0 + 1, i1 + col0 - 1); 754 755 add_startspan(startspans, sp, (psImage *)img, PM_SSPAN_RESTART); 756 } 757 /* 758 * Now workout from those Startspans, searching for pixels above threshold 759 */ 760 while (do_startspan(fp, img, threshold, startspans)) continue; 761 /* 762 * Cleanup 763 */ 764 psFree(startspans); // restores the image pixel 765 766 return fp; // pmFootprint really 767 } 768 769 /************************************************************************************************************/ 770 /* 771 * Worker routine for the pmSetFootprintArrayIDs/pmSetFootprintID (and pmMergeFootprintArrays) 772 */ 773 static void 774 set_footprint_id(psImage *idImage, // the image to set 775 const pmFootprint *fp, // the footprint to insert 776 const int id) { // the desired ID 777 const int col0 = fp->region.x0; 778 const int row0 = fp->region.y0; 779 780 for (int j = 0; j < fp->spans->n; j++) { 781 const pmSpan *span = fp->spans->data[j]; 782 psS32 *imgRow = idImage->data.S32[span->y - row0]; 783 for(int k = span->x0 - col0; k <= span->x1 - col0; k++) { 784 imgRow[k] += id; 785 } 786 } 787 } 788 399 789 static void 400 790 set_footprint_array_ids(psImage *idImage, 401 791 const psArray *footprints, // the footprints to insert 402 792 const bool relativeIDs) { // show IDs starting at 0, not pmFootprint->id 403 const pmFootprint *fp = footprints->data[0];404 const int col0 = fp->region.x0;405 const int row0 = fp->region.y0;406 407 793 int id = 0; // first index will be 1 408 794 for (int i = 0; i < footprints->n; i++) { 409 fp = footprints->data[i]; 410 if (relativeIDs) { 411 id++; 412 } else { 413 id = fp->id; 414 } 415 416 for (int j = 0; j < fp->nspan; j++) { 417 const pmSpan *span = fp->spans->data[j]; 418 psS32 *imgRow = idImage->data.S32[span->y - row0]; 419 for(int k = span->x0 - col0; k <= span->x1 - col0; k++) { 420 imgRow[k] += id; 421 } 422 } 795 const pmFootprint *fp = footprints->data[i]; 796 if (relativeIDs) { 797 id++; 798 } else { 799 id = fp->id; 800 } 801 802 set_footprint_id(idImage, fp, id); 423 803 } 424 804 } … … 428 808 */ 429 809 psImage *pmSetFootprintArrayIDs(const psArray *footprints, // the footprints to insert 430 const bool relativeIDs) { // show IDs starting at 0, not pmFootprint->id810 const bool relativeIDs) { // show IDs starting at 1, not pmFootprint->id 431 811 assert (footprints != NULL); 432 812 … … 456 836 } 457 837 838 /* 839 * Set an image to the value of footprint's ID whever they may fall 840 */ 841 psImage *pmSetFootprintID(const pmFootprint *fp, // the footprint to insert 842 const int id) { // the desired ID 843 assert(fp != NULL && pmIsFootprint((const psPtr)fp)); 844 const int numCols = fp->region.x1 - fp->region.x0 + 1; 845 const int numRows = fp->region.y1 - fp->region.y0 + 1; 846 const int col0 = fp->region.x0; 847 const int row0 = fp->region.y0; 848 assert (numCols >= 0 && numRows >= 0); 849 850 psImage *idImage = psImageAlloc(numCols, numRows, PS_TYPE_S32); 851 P_PSIMAGE_SET_ROW0(idImage, row0); 852 P_PSIMAGE_SET_COL0(idImage, col0); 853 psImageInit(idImage, 0); 854 /* 855 * do the work 856 */ 857 set_footprint_id(idImage, fp, id); 858 859 return idImage; 860 861 } 862 458 863 /************************************************************************************************************/ 459 864 /* … … 575 980 for (int i = 0; i < footprints->n; i++) { 576 981 pmFootprint *fp = footprints->data[i]; 577 fp->peaks = psArraySort (fp->peaks, pmPeakSortBySN);982 fp->peaks = psArraySort(fp->peaks, pmPeakSortBySN); 578 983 } 579 984 … … 624 1029 float threshold = subImg->data.F32[y][x] - nsigma_delta*stdev; 625 1030 if (threshold < min_threshold) { 1031 #if 1 // min_threshold is assumed to be below the detection threshold, 1032 // so all the peaks are pmFootprint, and this isn't the brightest 1033 (void)psArrayRemoveIndex(fp->peaks, i); 1034 i--; // we moved everything down one 1035 continue; 1036 #else 1037 #error n.b. We will be running LOTS of checks at this threshold, so only find the footprint once 626 1038 threshold = min_threshold; 1039 #endif 627 1040 } 628 1041 if (threshold > subImg->data.F32[y][x]) { … … 630 1043 } 631 1044 632 psArray *peakFootprints = pmFindFootprints(subImg, threshold, 1); 1045 #if 0 1046 const in npixMin = 1; 1047 psArray *peakFootprints = pmFindFootprints(subImg, threshold, npixMin); 633 1048 psImage *idImg = pmSetFootprintArrayIDs(peakFootprints, true); 634 1049 psFree(peakFootprints); 635 1050 const int peak_id = idImg->data.S32[y][x]; // the ID for the peak of interest 636 1051 assert (peak_id != 0); 1052 #else 1053 const int peak_id = 1; // the ID for the peak of interest 1054 pmFootprint *peakFootprint = pmFindFootprintAtPoint(subImg, threshold, peak->y, peak->x); 1055 psImage *idImg = pmSetFootprintID(peakFootprint, peak_id); 1056 psFree(peakFootprint); 1057 #endif 637 1058 638 1059 int j; … … 654 1075 } 655 1076 656 psFree(peakFootprints);657 1077 psFree(idImg); 658 1078 } -
trunk/psphot/src/pmFootprint.h
r13007 r13236 1 1 #if !defined(PM_FOOTPRINT_H) 2 2 #define PM_FOOTPRINT_H 3 3 // 4 // Describe a segment of an image 5 // 4 6 typedef struct { 5 int y; 6 int x0, x1; 7 int y; //!< Row that span's in 8 int x0; //!< Starting column (inclusive) 9 int x1; //!< Ending column (inclusive) 7 10 } pmSpan; 8 11 9 12 pmSpan *pmSpanAlloc(int y, int x1, int x2); 10 13 bool pmIsSpan(const psPtr ptr); 14 int pmSpanSortByYX (const void **a, const void **b); 11 15 12 16 typedef struct { 13 const int id; // unique ID14 int npix; // number of pixels in this pmFootprint15 int nspan; // number of pmSpans in this pmFootprint16 ps Array *spans; // the pmSpans17 ps Region bbox; // the pmFootprint's bounding box18 ps Array *peaks; // the peaks lying in this footprint19 psRegion region; // A region describing the psImage the footprints live in17 const int id; //!< unique ID 18 int npix; //!< number of pixels in this pmFootprint 19 psArray *spans; //!< the pmSpans 20 psRegion bbox; //!< the pmFootprint's bounding box 21 psArray *peaks; //!< the peaks lying in this footprint 22 psRegion region; //!< A region describing the psImage the footprints live in 23 bool normalized; //!< Are the spans sorted? 20 24 } pmFootprint; 21 25 … … 23 27 bool pmIsFootprint(const psPtr ptr); 24 28 29 pmFootprint *pmFootprintNormalize(pmFootprint *fp); 25 30 int pmFootprintSetNpix(pmFootprint *fp); 26 31 void pmFootprintSetBBox(pmFootprint *fp); 27 32 psArray *pmFindFootprints(const psImage *img, const float threshold, const int npixMin); 33 pmFootprint *pmFindFootprintAtPoint(const psImage *img, 34 const float threshold, 35 int row, int col); 28 36 29 37 psArray *pmMergeFootprintArrays(const psArray *footprints1, const psArray *footprints2); 30 38 31 psImage *pmSetFootprintArrayIDs(const psArray *footprints, 32 const bool relativeIDs);39 psImage *pmSetFootprintArrayIDs(const psArray *footprints, const bool relativeIDs); 40 psImage *pmSetFootprintID(const pmFootprint *fp, const int id); 33 41 34 42 psErrorCode pmPeaksAssignToFootprints(psArray *footprints, const psArray *peaks);
Note:
See TracChangeset
for help on using the changeset viewer.
