Changeset 13441
- Timestamp:
- May 21, 2007, 7:49:18 AM (19 years ago)
- Location:
- trunk/psphot/src
- Files:
-
- 2 edited
-
pmFootprint.c (modified) (13 diffs)
-
pmFootprint.h (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
trunk/psphot/src/pmFootprint.c
r13372 r13441 448 448 void *data; // saved data 449 449 void *data_home; // where the data was saved from 450 } Startspan;451 452 static void startspanFree(Startspan *sspan) {450 } Old_Spartspan; 451 452 static void Old_startspanFree(Old_Spartspan *sspan) { 453 453 if (sspan->nbyte > 0) { 454 454 memcpy(sspan->data_home, sspan->data, sspan->nbyte); // restore image's pixels to their pristine state … … 459 459 } 460 460 461 static Startspan *462 StartspanAlloc(const pmSpan *span, // The span in question461 static Old_Spartspan * 462 Old_SpartspanAlloc(const pmSpan *span, // The span in question 463 463 psImage *img,// the data wherein lives the span 464 464 const PM_SSPAN_DIR dir // Should we continue searching towards the top of the image? 465 465 ) { 466 Startspan *sspan = psAlloc(sizeof(Startspan));467 psMemSetDeallocator(sspan, (psFreeFunc) startspanFree);466 Old_Spartspan *sspan = psAlloc(sizeof(Old_Spartspan)); 467 psMemSetDeallocator(sspan, (psFreeFunc)Old_startspanFree); 468 468 469 469 sspan->span = psMemIncrRefCounter((void *)span); … … 507 507 508 508 // 509 // Add a new Startspan to an array of Startspans509 // Add a new Old_Spartspan to an array of Old_Spartspans 510 510 // 511 static void add_startspan(psArray *startspans, // the saved Startspans511 static void old_add_startspan(psArray *startspans, // the saved Old_Spartspans 512 512 const pmSpan *sp, // the span in question 513 513 const psImage *img, // image to save/restore (or NULL) 514 514 const PM_SSPAN_DIR dir) { // the desired direction to search 515 515 if (dir == PM_SSPAN_RESTART) { 516 add_startspan(startspans, sp, img, PM_SSPAN_UP);517 add_startspan(startspans, sp, NULL, PM_SSPAN_DOWN);516 old_add_startspan(startspans, sp, img, PM_SSPAN_UP); 517 old_add_startspan(startspans, sp, NULL, PM_SSPAN_DOWN); 518 518 } else { 519 Startspan *sspan = StartspanAlloc(sp, (psImage *)img, dir);519 Old_Spartspan *sspan = Old_SpartspanAlloc(sp, (psImage *)img, dir); 520 520 psArrayAdd(startspans, 1, sspan); 521 521 psFree(sspan); // as it's now owned by startspans … … 525 525 /************************************************************************************************************/ 526 526 /* 527 * Search the image for pixels above threshold, starting at a single Startspan.527 * Search the image for pixels above threshold, starting at a single Old_Spartspan. 528 528 * We search the array looking for one to process; it'd be better to move the 529 529 * ones that we're done with to the end, but it probably isn't worth it for 530 530 * the anticipated uses of this routine. 531 531 * 532 * This is the guts of pm FindFootprintAtPoint533 */ 534 static bool do_startspan(pmFootprint *fp, // the footprint that we're building532 * This is the guts of pmOldFindFootprintAtPoint 533 */ 534 static bool old_do_startspan(pmFootprint *fp, // the footprint that we're building 535 535 const psImage *img, // the psImage we're working on 536 536 const float threshold, // Threshold … … 556 556 /********************************************************************************************************/ 557 557 558 Startspan *sspan = NULL;558 Old_Spartspan *sspan = NULL; 559 559 for (int i = 0; i < startspans->n; i++) { 560 560 sspan = startspans->data[i]; … … 563 563 } 564 564 } 565 if (sspan == NULL || sspan->direction == PM_SSPAN_DONE) { // no more Startspans to process565 if (sspan == NULL || sspan->direction == PM_SSPAN_DONE) { // no more Old_Spartspans to process 566 566 return false; 567 567 } … … 615 615 const pmSpan *sp = pmFootprintAddSpan(fp, i + row0, nx0 + col0, nx1 + col0); 616 616 617 add_startspan(startspans, sp, (psImage *)img, PM_SSPAN_RESTART);617 old_add_startspan(startspans, sp, (psImage *)img, PM_SSPAN_RESTART); 618 618 } 619 619 // … … 646 646 if (sx1 <= x1) { 647 647 sp = pmFootprintAddSpan(fp, i + row0, sx0 + col0, sx1 + col0 - 1); 648 add_startspan(startspans, sp, (psImage *)img, PM_SSPAN_DONE);648 old_add_startspan(startspans, sp, (psImage *)img, PM_SSPAN_DONE); 649 649 } else { // overhangs to right 650 650 sp = pmFootprintAddSpan(fp, i + row0, sx0 + col0, x1 + col0); 651 add_startspan(startspans, sp, (psImage *)img, PM_SSPAN_DONE);651 old_add_startspan(startspans, sp, (psImage *)img, PM_SSPAN_DONE); 652 652 sp = pmFootprintAddSpan(fp, i + row0, x1 + 1 + col0, sx1 + col0 - 1); 653 add_startspan(startspans, sp, (psImage *)img, PM_SSPAN_RESTART);653 old_add_startspan(startspans, sp, (psImage *)img, PM_SSPAN_RESTART); 654 654 } 655 655 first = false; 656 656 } else { 657 657 sp = pmFootprintAddSpan(fp, i + row0, sx0 + col0, sx1 + col0 - 1); 658 add_startspan(startspans, sp, (psImage *)img, PM_SSPAN_RESTART);658 old_add_startspan(startspans, sp, (psImage *)img, PM_SSPAN_RESTART); 659 659 } 660 660 } … … 689 689 */ 690 690 pmFootprint * 691 pm FindFootprintAtPoint(const psImage *img, // image to search691 pmOldFindFootprintAtPoint(const psImage *img, // image to search 692 692 const float threshold, // Threshold 693 693 int row, int col) { // starting position (in img's parent's coordinate system) … … 753 753 const pmSpan *sp = pmFootprintAddSpan(fp, row + row0, i0 + col0 + 1, i1 + col0 - 1); 754 754 755 add_startspan(startspans, sp, (psImage *)img, PM_SSPAN_RESTART);755 old_add_startspan(startspans, sp, (psImage *)img, PM_SSPAN_RESTART); 756 756 } 757 757 /* 758 * Now workout from those Startspans, searching for pixels above threshold758 * Now workout from those Old_Spartspans, searching for pixels above threshold 759 759 */ 760 while ( do_startspan(fp, img, threshold, startspans)) continue;760 while (old_do_startspan(fp, img, threshold, startspans)) continue; 761 761 /* 762 762 * Cleanup 763 763 */ 764 psFree(startspans); // restores the image pixel 765 766 return fp; // pmFootprint really 767 } 768 769 /************************************************************************************************************/ 770 /* 771 * A data structure to hold the starting point for a search for pixels above threshold, 772 * used by pmFindFootprintAtPoint 773 * 774 * We don't want to find this span again --- it's already part of the footprint --- 775 * so we set the pixels in the image to as small a value as we can. N.b. We may want 776 * to reconsider this when dealing with difference images 777 */ 778 #if 0 779 typedef enum {PM_SSPAN_DOWN = 0, // scan down from this span 780 PM_SSPAN_UP, // scan up from this span 781 PM_SSPAN_RESTART, // restart scanning from this span 782 PM_SSPAN_DONE // this span is processed 783 } PM_SSPAN_DIR; // How to continue searching 784 #endif 785 786 // 787 // An enum for mask's pixel values. We're looking for pixels that are above threshold, and 788 // we keep extra book-keeping information in the PM_SSPAN_STOP plane. It's simpler to be 789 // able to check for 790 enum { 791 PM_SSPAN_INITIAL = 0x0, // initial state of pixels. 792 PM_SSPAN_DETECTED = 0x1, // we've seen this pixel 793 PM_SSPAN_STOP = 0x2 // you may stop searching when you see this pixel 794 }; 795 796 typedef struct { 797 const pmSpan *span; // save the pixel range 798 PM_SSPAN_DIR direction; // How to continue searching 799 bool stop; // should we stop searching? 800 } Spartspan; 801 802 static void startspanFree(Spartspan *sspan) { 803 psFree((void *)sspan->span); 804 } 805 806 static Spartspan * 807 SpartspanAlloc(const pmSpan *span, // The span in question 808 psImage *mask, // Pixels that we've already detected 809 const PM_SSPAN_DIR dir // Should we continue searching towards the top of the image? 810 ) { 811 Spartspan *sspan = psAlloc(sizeof(Spartspan)); 812 psMemSetDeallocator(sspan, (psFreeFunc)startspanFree); 813 814 sspan->span = psMemIncrRefCounter((void *)span); 815 sspan->direction = dir; 816 sspan->stop = false; 817 818 if (mask != NULL) { // remember that we've detected these pixels 819 psMaskType *mpix = &mask->data.PS_TYPE_MASK_DATA[span->y - mask->row0][span->x0 - mask->col0]; 820 821 for (int i = 0; i <= span->x1 - span->x0; i++) { 822 mpix[i] |= PM_SSPAN_DETECTED; 823 if (mpix[i] & PM_SSPAN_STOP) { 824 sspan->stop = true; 825 } 826 } 827 } 828 829 return sspan; 830 } 831 832 // 833 // Add a new Spartspan to an array of Spartspans. Iff we see a stop bit, return true 834 // 835 static bool add_startspan(psArray *startspans, // the saved Spartspans 836 const pmSpan *sp, // the span in question 837 psImage *mask, // mask of detected/stop pixels 838 const PM_SSPAN_DIR dir) { // the desired direction to search 839 if (dir == PM_SSPAN_RESTART) { 840 if (add_startspan(startspans, sp, mask, PM_SSPAN_UP) || 841 add_startspan(startspans, sp, NULL, PM_SSPAN_DOWN)) { 842 return true; 843 } 844 } else { 845 Spartspan *sspan = SpartspanAlloc(sp, mask, dir); 846 if (sspan->stop) { // we detected a stop bit 847 psFree(sspan); // don't allocate new span 848 849 return true; 850 } else { 851 psArrayAdd(startspans, 1, sspan); 852 psFree(sspan); // as it's now owned by startspans 853 } 854 } 855 856 return false; 857 } 858 859 /************************************************************************************************************/ 860 /* 861 * Search the image for pixels above threshold, starting at a single Spartspan. 862 * We search the array looking for one to process; it'd be better to move the 863 * ones that we're done with to the end, but it probably isn't worth it for 864 * the anticipated uses of this routine. 865 * 866 * This is the guts of pmFindFootprintAtPoint 867 */ 868 static bool do_startspan(pmFootprint *fp, // the footprint that we're building 869 const psImage *img, // the psImage we're working on 870 psImage *mask, // the associated masks 871 const float threshold, // Threshold 872 psArray *startspans) { // specify which span to process next 873 bool F32 = false; // is this an F32 image? 874 if (img->type.type == PS_TYPE_F32) { 875 F32 = true; 876 } else if (img->type.type == PS_TYPE_S32) { 877 F32 = false; 878 } else { // N.b. You can't trivially add more cases here; F32 is just a bool 879 psError(PS_ERR_UNKNOWN, true, "Unsupported psImage type: %d", img->type.type); 880 return NULL; 881 } 882 883 psF32 *imgRowF32 = NULL; // row pointer if F32 884 psS32 *imgRowS32 = NULL; // " " " " !F32 885 psMaskType *maskRow = NULL; // masks's row pointer 886 887 const int row0 = img->row0; 888 const int col0 = img->col0; 889 const int numRows = img->numRows; 890 const int numCols = img->numCols; 891 892 /********************************************************************************************************/ 893 894 Spartspan *sspan = NULL; 895 for (int i = 0; i < startspans->n; i++) { 896 sspan = startspans->data[i]; 897 if (sspan->direction != PM_SSPAN_DONE) { 898 break; 899 } 900 if (sspan->stop) { 901 break; 902 } 903 } 904 if (sspan == NULL || sspan->direction == PM_SSPAN_DONE) { // no more Spartspans to process 905 return false; 906 } 907 if (sspan->stop) { // they don't want any more spans processed 908 return false; 909 } 910 /* 911 * Work 912 */ 913 const PM_SSPAN_DIR dir = sspan->direction; 914 /* 915 * Set initial span to the startspan 916 */ 917 int x0 = sspan->span->x0 - col0, x1 = sspan->span->x1 - col0; 918 /* 919 * Go through image identifying objects 920 */ 921 int nx0, nx1 = -1; // new values of x0, x1 922 const int di = (dir == PM_SSPAN_UP) ? 1 : -1; // how much i changes to get to the next row 923 bool stop = false; // should I stop searching for spans? 924 925 for (int i = sspan->span->y -row0 + di; i < numRows && i >= 0; i += di) { 926 imgRowF32 = img->data.F32[i]; // only one of 927 imgRowS32 = img->data.S32[i]; // these is valid! 928 maskRow = mask->data.PS_TYPE_MASK_DATA[i]; 929 // 930 // Search left from the pixel diagonally to the left of (i - di, x0). If there's 931 // a connected span there it may need to grow up and/or down, so push it onto 932 // the stack for later consideration 933 // 934 nx0 = -1; 935 for (int j = x0 - 1; j >= -1; j--) { 936 double pixVal = (j < 0) ? threshold - 100 : (F32 ? imgRowF32[j] : imgRowS32[j]); 937 if ((maskRow[j] & PM_SSPAN_DETECTED) || pixVal < threshold) { 938 if (j < x0 - 1) { // we found some pixels above threshold 939 nx0 = j + 1; 940 } 941 break; 942 } 943 } 944 945 if (nx0 < 0) { // no span to the left 946 nx1 = x0 - 1; // we're going to resume searching at nx1 + 1 947 } else { 948 // 949 // Search right in leftmost span 950 // 951 //nx1 = 0; // make gcc happy 952 for (int j = nx0 + 1; j <= numCols; j++) { 953 double pixVal = (j >= numCols) ? threshold - 100 : (F32 ? imgRowF32[j] : imgRowS32[j]); 954 if ((maskRow[j] & PM_SSPAN_DETECTED) || pixVal < threshold) { 955 nx1 = j - 1; 956 break; 957 } 958 } 959 960 const pmSpan *sp = pmFootprintAddSpan(fp, i + row0, nx0 + col0, nx1 + col0); 961 962 if (add_startspan(startspans, sp, mask, PM_SSPAN_RESTART)) { 963 stop = true; 964 break; 965 } 966 } 967 // 968 // Now look for spans connected to the old span. The first of these we'll 969 // simply process, but others will have to be deferred for later consideration. 970 // 971 // In fact, if the span overhangs to the right we'll have to defer the overhang 972 // until later too, as it too can grow in both directions 973 // 974 // Note that column numCols exists virtually, and always ends the last span; this 975 // is why we claim below that sx1 is always set 976 // 977 bool first = false; // is this the first new span detected? 978 for (int j = nx1 + 1; j <= x1 + 1; j++) { 979 double pixVal = (j >= numCols) ? threshold - 100 : (F32 ? imgRowF32[j] : imgRowS32[j]); 980 if (!(maskRow[j] & PM_SSPAN_DETECTED) && pixVal >= threshold) { 981 int sx0 = j++; // span that we're working on is sx0:sx1 982 int sx1 = -1; // We know that if we got here, we'll also set sx1 983 for (; j <= numCols; j++) { 984 double pixVal = (j >= numCols) ? threshold - 100 : (F32 ? imgRowF32[j] : imgRowS32[j]); 985 if ((maskRow[j] & PM_SSPAN_DETECTED) || pixVal < threshold) { // end of span 986 sx1 = j; 987 break; 988 } 989 } 990 assert (sx1 >= 0); 991 992 const pmSpan *sp; 993 if (first) { 994 if (sx1 <= x1) { 995 sp = pmFootprintAddSpan(fp, i + row0, sx0 + col0, sx1 + col0 - 1); 996 if (add_startspan(startspans, sp, mask, PM_SSPAN_DONE)) { 997 stop = true; 998 break; 999 } 1000 } else { // overhangs to right 1001 sp = pmFootprintAddSpan(fp, i + row0, sx0 + col0, x1 + col0); 1002 if (add_startspan(startspans, sp, mask, PM_SSPAN_DONE)) { 1003 stop = true; 1004 break; 1005 } 1006 sp = pmFootprintAddSpan(fp, i + row0, x1 + 1 + col0, sx1 + col0 - 1); 1007 if (add_startspan(startspans, sp, mask, PM_SSPAN_RESTART)) { 1008 stop = true; 1009 break; 1010 } 1011 } 1012 first = false; 1013 } else { 1014 sp = pmFootprintAddSpan(fp, i + row0, sx0 + col0, sx1 + col0 - 1); 1015 if (add_startspan(startspans, sp, mask, PM_SSPAN_RESTART)) { 1016 stop = true; 1017 break; 1018 } 1019 } 1020 } 1021 } 1022 1023 if (stop || first == false) { // we're done 1024 break; 1025 } 1026 1027 x0 = nx0; x1 = nx1; 1028 } 1029 /* 1030 * Cleanup 1031 */ 1032 1033 sspan->direction = PM_SSPAN_DONE; 1034 return stop ? false : true; 1035 } 1036 1037 /* 1038 * Go through an image, starting at (row, col) and assembling all the pixels 1039 * that are connected to that point (in a chess kings-move sort of way) into 1040 * a pmFootprint. 1041 * 1042 * This is much slower than pmFindFootprints if you want to find lots of 1043 * footprints, but if you only want a small region about a given point it 1044 * can be much faster 1045 * 1046 * N.b. The returned pmFootprint is not in "normal form"; that is the pmSpans 1047 * are not sorted by increasing y, x0, x1. If this matters to you, call 1048 * pmFootprintNormalize() 1049 */ 1050 pmFootprint * 1051 pmFindFootprintAtPoint(const psImage *img, // image to search 1052 const float threshold, // Threshold 1053 const psArray *peaks, // array of peaks; finding one terminates search for footprint 1054 int row, int col) { // starting position (in img's parent's coordinate system) 1055 assert(img != NULL); 1056 1057 bool F32 = false; // is this an F32 image? 1058 if (img->type.type == PS_TYPE_F32) { 1059 F32 = true; 1060 } else if (img->type.type == PS_TYPE_S32) { 1061 F32 = false; 1062 } else { // N.b. You can't trivially add more cases here; F32 is just a bool 1063 psError(PS_ERR_UNKNOWN, true, "Unsupported psImage type: %d", img->type.type); 1064 return NULL; 1065 } 1066 psF32 *imgRowF32 = NULL; // row pointer if F32 1067 psS32 *imgRowS32 = NULL; // " " " " !F32 1068 1069 const int row0 = img->row0; 1070 const int col0 = img->col0; 1071 const int numRows = img->numRows; 1072 const int numCols = img->numCols; 1073 /* 1074 * Is point in image, and above threshold? 1075 */ 1076 row -= row0; col -= col0; 1077 if (row < 0 || row >= numRows || 1078 col < 0 || col >= numCols) { 1079 psError(PS_ERR_BAD_PARAMETER_VALUE, true, 1080 "row/col == (%d, %d) are out of bounds [%d--%d, %d--%d]", 1081 row + row0, col + col0, row0, row0 + numRows - 1, col0, col0 + numCols - 1); 1082 return NULL; 1083 } 1084 1085 double pixVal = F32 ? img->data.F32[row][col] : img->data.S32[row][col]; 1086 if (pixVal < threshold) { 1087 return pmFootprintAlloc(0, img); 1088 } 1089 1090 pmFootprint *fp = pmFootprintAlloc(1 + img->numRows/10, img); 1091 /* 1092 * We need a mask for two purposes; to indicate which pixels are already detected, 1093 * and to store the "stop" pixels --- those that, once reached, should stop us 1094 * looking for the rest of the pmFootprint. These are generally set from peaks. 1095 */ 1096 psImage *mask = psImageAlloc(numCols, numRows, PS_TYPE_MASK); 1097 P_PSIMAGE_SET_ROW0(mask, row0); 1098 P_PSIMAGE_SET_COL0(mask, col0); 1099 psImageInit(mask, PM_SSPAN_INITIAL); 1100 // 1101 // Set stop bits from peaks list 1102 // 1103 assert (peaks == NULL || peaks->n == 0 || pmIsPeak(peaks->data[0])); 1104 if (peaks != NULL) { 1105 for (int i = 0; i < peaks->n; i++) { 1106 pmPeak *peak = peaks->data[i]; 1107 mask->data.PS_TYPE_MASK_DATA[peak->y - mask->row0][peak->x - mask->col0] |= PM_SSPAN_STOP; 1108 } 1109 } 1110 /* 1111 * Find starting span passing through (row, col) 1112 */ 1113 psArray *startspans = psArrayAllocEmpty(1); // spans where we have to restart the search 1114 1115 imgRowF32 = img->data.F32[row]; // only one of 1116 imgRowS32 = img->data.S32[row]; // these is valid! 1117 psMaskType *maskRow = mask->data.PS_TYPE_MASK_DATA[row]; 1118 { 1119 int i; 1120 for (i = col; i >= 0; i--) { 1121 pixVal = F32 ? imgRowF32[i] : imgRowS32[i]; 1122 if ((maskRow[i] & PM_SSPAN_DETECTED) || pixVal < threshold) { 1123 break; 1124 } 1125 } 1126 int i0 = i; 1127 for (i = col; i < numCols; i++) { 1128 pixVal = F32 ? imgRowF32[i] : imgRowS32[i]; 1129 if ((maskRow[i] & PM_SSPAN_DETECTED) || pixVal < threshold) { 1130 break; 1131 } 1132 } 1133 int i1 = i; 1134 const pmSpan *sp = pmFootprintAddSpan(fp, row + row0, i0 + col0 + 1, i1 + col0 - 1); 1135 1136 (void)add_startspan(startspans, sp, mask, PM_SSPAN_RESTART); 1137 } 1138 /* 1139 * Now workout from those Spartspans, searching for pixels above threshold 1140 */ 1141 while (do_startspan(fp, img, mask, threshold, startspans)) continue; 1142 /* 1143 * Cleanup 1144 */ 1145 psFree(mask); 764 1146 psFree(startspans); // restores the image pixel 765 1147 … … 1058 1440 * starting point, discard the peak. 1059 1441 */ 1060 psErrorCode pm FootprintCullPeaks(const psImage *img, // the image wherein lives the footprint1442 psErrorCode pmOldFootprintCullPeaks(const psImage *img, // the image wherein lives the footprint 1061 1443 const psImage *weight, // corresponding variance image 1062 1444 pmFootprint *fp, // Footprint containing mortal peaks … … 1117 1499 #else 1118 1500 const int peak_id = 1; // the ID for the peak of interest 1119 pmFootprint *peakFootprint = pm FindFootprintAtPoint(subImg, threshold, peak->y, peak->x);1501 pmFootprint *peakFootprint = pmOldFindFootprintAtPoint(subImg, threshold, peak->y, peak->x); 1120 1502 psImage *idImg = pmSetFootprintID(peakFootprint, peak_id); 1121 1503 psFree(peakFootprint); … … 1143 1525 } 1144 1526 1527 psFree((psImage *)subImg); 1528 psFree((psImage *)subWt); 1529 1530 return PS_ERR_NONE; 1531 } 1532 1533 /************************************************************************************************************/ 1534 /* 1535 * Examine the peaks in a pmFootprint, and throw away the ones that are not sufficiently 1536 * isolated. More precisely, for each peak find the highest coll that you'd have to traverse 1537 * to reach a still higher peak --- and if that coll's more than nsigma DN below your 1538 * starting point, discard the peak. 1539 */ 1540 psErrorCode pmFootprintCullPeaks(const psImage *img, // the image wherein lives the footprint 1541 const psImage *weight, // corresponding variance image 1542 pmFootprint *fp, // Footprint containing mortal peaks 1543 const float nsigma_delta, // how many sigma above local background a peak 1544 // needs to be to survive 1545 const float min_threshold) { // minimum permitted coll height 1546 assert (img != NULL); assert (img->type.type == PS_TYPE_F32); 1547 assert (weight != NULL); assert (weight->type.type == PS_TYPE_F32); 1548 assert (img->row0 == weight->row0 && img->col0 == weight->col0); 1549 assert (fp != NULL); 1550 1551 if (fp->peaks == NULL || fp->peaks->n == 0) { // nothing to do 1552 return PS_ERR_NONE; 1553 } 1554 1555 psRegion subRegion; // desired subregion; 1 larger than bounding box (grr) 1556 subRegion.x0 = fp->bbox.x0; subRegion.x1 = fp->bbox.x1 + 1; 1557 subRegion.y0 = fp->bbox.y0; subRegion.y1 = fp->bbox.y1 + 1; 1558 const psImage *subImg = psImageSubset((psImage *)img, subRegion); 1559 const psImage *subWt = psImageSubset((psImage *)weight, subRegion); 1560 assert (subImg != NULL && subWt != NULL); 1561 // 1562 // We need a psArray of peaks brighter than the current peak. We'll fake this 1563 // for efficiency --- shhh 1564 // 1565 psArray *brightPeaks = psArrayAlloc(0); 1566 psFree(brightPeaks->data); 1567 brightPeaks->data = psMemIncrRefCounter(fp->peaks->data);// use the data from fp->peaks 1568 // 1569 // The brightest peak is always safe; go through other peaks trying to cull them 1570 // 1571 for (int i = 1; i < fp->peaks->n; i++) { // n.b. fp->peaks->n can change within the loop 1572 const pmPeak *peak = fp->peaks->data[i]; 1573 int x = peak->x - subImg->col0; 1574 int y = peak->y - subImg->row0; 1575 // 1576 // Find the level nsigma below the peak that must separate the peak 1577 // from any of its friends 1578 // 1579 assert (x >= 0 && x < subImg->numCols && y >= 0 && y < subImg->numRows); 1580 const float stdev = sqrt(subWt->data.F32[y][x]); 1581 float threshold = subImg->data.F32[y][x] - nsigma_delta*stdev; 1582 if (isnan(threshold) || threshold < min_threshold) { 1583 #if 1 // min_threshold is assumed to be below the detection threshold, 1584 // so all the peaks are pmFootprint, and this isn't the brightest 1585 (void)psArrayRemoveIndex(fp->peaks, i); 1586 i--; // we moved everything down one 1587 continue; 1588 #else 1589 #error n.b. We will be running LOTS of checks at this threshold, so only find the footprint once 1590 threshold = min_threshold; 1591 #endif 1592 } 1593 if (threshold > subImg->data.F32[y][x]) { 1594 threshold = subImg->data.F32[y][x] - 10*FLT_EPSILON; 1595 } 1596 1597 const int peak_id = 1; // the ID for the peak of interest 1598 brightPeaks->n = i; // only stop at a peak brighter than we are 1599 pmFootprint *peakFootprint = pmFindFootprintAtPoint(subImg, threshold, brightPeaks, peak->y, peak->x); 1600 brightPeaks->n = 0; // don't double free 1601 psImage *idImg = pmSetFootprintID(peakFootprint, peak_id); 1602 psFree(peakFootprint); 1603 1604 int j; 1605 for (j = 0; j < i; j++) { 1606 const pmPeak *peak2 = fp->peaks->data[j]; 1607 int x2 = peak2->x - subImg->col0; 1608 int y2 = peak2->y - subImg->row0; 1609 const int peak2_id = idImg->data.S32[y2][x2]; // the ID for some other peak 1610 1611 if (peak2_id == peak_id) { // There's a brighter peak within the footprint above 1612 ; // threshold; so cull our initial peak 1613 (void)psArrayRemoveIndex(fp->peaks, i); 1614 i--; // we moved everything down one 1615 break; 1616 } 1617 } 1618 if (j == i) { 1619 j++; 1620 } 1621 1622 psFree(idImg); 1623 } 1624 1625 brightPeaks->n = 0; psFree(brightPeaks); 1145 1626 psFree((psImage *)subImg); 1146 1627 psFree((psImage *)subWt); -
trunk/psphot/src/pmFootprint.h
r13372 r13441 31 31 void pmFootprintSetBBox(pmFootprint *fp); 32 32 psArray *pmFindFootprints(const psImage *img, const float threshold, const int npixMin); 33 pmFootprint *pmOldFindFootprintAtPoint(const psImage *img, 34 const float threshold, 35 int row, int col); 33 36 pmFootprint *pmFindFootprintAtPoint(const psImage *img, 34 37 const float threshold, 38 const psArray *peaks, 35 39 int row, int col); 36 40
Note:
See TracChangeset
for help on using the changeset viewer.
