Changeset 26533
- Timestamp:
- Jan 7, 2010, 12:06:22 PM (16 years ago)
- Location:
- branches/eam_branches/20091201/psModules/src
- Files:
-
- 3 edited
-
camera/pmFPA.c (modified) (1 diff)
-
objects/pmFootprintCullPeaks.c (modified) (7 diffs)
-
objects/pmFootprintFindAtPoint.c (modified) (13 diffs)
Legend:
- Unmodified
- Added
- Removed
-
branches/eam_branches/20091201/psModules/src/camera/pmFPA.c
r23740 r26533 105 105 psFree(fpa->concepts); 106 106 psFree(fpa->analysis); 107 psFree( (void *)fpa->camera);107 psFree(fpa->camera); 108 108 psFree(fpa->hdu); 109 109 -
branches/eam_branches/20091201/psModules/src/objects/pmFootprintCullPeaks.c
r24888 r26533 29 29 */ 30 30 31 # define IN_PEAK 1 31 # define IN_PEAK 1 32 32 psErrorCode pmFootprintCullPeaks(const psImage *img, // the image wherein lives the footprint 33 const psImage *weight,// corresponding variance image34 pmFootprint *fp, // Footprint containing mortal peaks35 const float nsigma_delta, // how many sigma above local background a peak needs to be to survive36 const float fPadding, // fractional padding added to stdev since bright peaks have unreasonably high significance37 const float min_threshold) { // minimum permitted coll height33 const psImage *weight, // corresponding variance image 34 pmFootprint *fp, // Footprint containing mortal peaks 35 const float nsigma_delta, // how many sigma above local background a peak needs to be to survive 36 const float fPadding, // fractional padding added to stdev since bright peaks have unreasonably high significance 37 const float min_threshold) { // minimum permitted coll height 38 38 assert (img != NULL); assert (img->type.type == PS_TYPE_F32); 39 39 assert (weight != NULL); assert (weight->type.type == PS_TYPE_F32); … … 42 42 43 43 if (fp->peaks == NULL || fp->peaks->n == 0) { // nothing to do 44 return PS_ERR_NONE;45 } 46 47 psRegion subRegion; // desired subregion; 1 larger than bounding box (grr)44 return PS_ERR_NONE; 45 } 46 47 psRegion subRegion; // desired subregion; 1 larger than bounding box (grr) 48 48 subRegion.x0 = fp->bbox.x0; subRegion.x1 = fp->bbox.x1 + 1; 49 49 subRegion.y0 = fp->bbox.y0; subRegion.y1 = fp->bbox.y1 + 1; … … 55 55 psImage *idImg = psImageAlloc(subImg->numCols, subImg->numRows, PS_TYPE_S32); 56 56 57 // We need a psArray of peaks brighter than the current peak. 57 // We need a psArray of peaks brighter than the current peak. 58 58 // We reject peaks which either: 59 59 // 1) are below the local threshold … … 67 67 // The brightest peak is always safe; go through other peaks trying to cull them 68 68 for (int i = 1; i < fp->peaks->n; i++) { // n.b. fp->peaks->n can change within the loop 69 const pmPeak *peak = fp->peaks->data[i];70 int x = peak->x - subImg->col0;71 int y = peak->y - subImg->row0;72 //73 // Find the level nsigma below the peak that must separate the peak74 // from any of its friends75 //76 assert (x >= 0 && x < subImg->numCols && y >= 0 && y < subImg->numRows);77 78 // const float stdev = sqrt(subWt->data.F32[y][x]);79 // float threshold = subImg->data.F32[y][x] - nsigma_delta*stdev;80 81 const float stdev = sqrt(subWt->data.F32[y][x]);82 const float flux = subImg->data.F32[y][x];83 const float fStdev = fabs(stdev/flux);84 const float stdev_pad = fabs(flux * hypot(fStdev, fPadding));85 // if flux is negative, careful with fStdev86 87 float threshold = flux - nsigma_delta*stdev_pad;88 89 if (isnan(threshold) || threshold < min_threshold) {90 // min_threshold is assumed to be below the detection threshold,91 // so all the peaks are pmFootprint, and this isn't the brightest92 continue;93 }94 95 // XXX EAM : if stdev >= 0, i'm not sure how this can ever be true?96 if (threshold > subImg->data.F32[y][x]) {97 threshold = subImg->data.F32[y][x] - 10*FLT_EPSILON;98 }99 100 // XXX this is a bit expensive: psImageAlloc for every peak contained in this footprint101 // perhaps this should alloc a single ID image above and pass it in to be set.102 103 // XXX optionally use the faster pmFootprintsFind if the subimage size is large (eg, M31)104 105 // XXX this is not quite there yet:106 // pmFootprint *peakFootprint = NULL;107 // int area = subImg->numCols * subImg->numRows;108 // if (area > 30000) {109 110 pmFootprint *peakFootprint = pmFootprintsFindAtPoint(subImg, threshold, brightPeaks, peak->y, peak->x);111 112 // at this point brightPeaks only has the peaks brighter than the current113 114 // XXX need to supply the image here115 // we set the IDs to either 1 (in peak) or 0 (not in peak)116 pmSetFootprintID (idImg, peakFootprint, IN_PEAK);117 psFree(peakFootprint);118 119 // Check if any of the previous (brighter) peaks are within the footprint of this peak120 // If so, the current peak is bogus; drop it.121 bool keep = true;122 for (int j = 0; keep && (j < brightPeaks->n); j++) {123 const pmPeak *peak2 = fp->peaks->data[j];124 int x2 = peak2->x - subImg->col0;125 int y2 = peak2->y - subImg->row0;126 if (idImg->data.S32[y2][x2] == IN_PEAK) 127 // There's a brighter peak within the footprint above threshold; so cull our initial peak128 keep = false;129 }130 if (!keep) continue;131 132 psArrayAdd (brightPeaks, 128, fp->peaks->data[i]);69 const pmPeak *peak = fp->peaks->data[i]; 70 int x = peak->x - subImg->col0; 71 int y = peak->y - subImg->row0; 72 // 73 // Find the level nsigma below the peak that must separate the peak 74 // from any of its friends 75 // 76 assert (x >= 0 && x < subImg->numCols && y >= 0 && y < subImg->numRows); 77 78 // const float stdev = sqrt(subWt->data.F32[y][x]); 79 // float threshold = subImg->data.F32[y][x] - nsigma_delta*stdev; 80 81 const float stdev = sqrt(subWt->data.F32[y][x]); 82 const float flux = subImg->data.F32[y][x]; 83 const float fStdev = fabs(stdev/flux); 84 const float stdev_pad = fabs(flux * hypot(fStdev, fPadding)); 85 // if flux is negative, careful with fStdev 86 87 float threshold = flux - nsigma_delta*stdev_pad; 88 89 if (isnan(threshold) || threshold < min_threshold) { 90 // min_threshold is assumed to be below the detection threshold, 91 // so all the peaks are pmFootprint, and this isn't the brightest 92 continue; 93 } 94 95 // XXX EAM : if stdev >= 0, i'm not sure how this can ever be true? 96 if (threshold > subImg->data.F32[y][x]) { 97 threshold = subImg->data.F32[y][x] - 10*FLT_EPSILON; 98 } 99 100 // XXX this is a bit expensive: psImageAlloc for every peak contained in this footprint 101 // perhaps this should alloc a single ID image above and pass it in to be set. 102 103 // XXX optionally use the faster pmFootprintsFind if the subimage size is large (eg, M31) 104 105 // XXX this is not quite there yet: 106 // pmFootprint *peakFootprint = NULL; 107 // int area = subImg->numCols * subImg->numRows; 108 // if (area > 30000) { 109 110 pmFootprint *peakFootprint = pmFootprintsFindAtPoint(subImg, threshold, brightPeaks, peak->y, peak->x); 111 112 // at this point brightPeaks only has the peaks brighter than the current 113 114 // XXX need to supply the image here 115 // we set the IDs to either 1 (in peak) or 0 (not in peak) 116 pmSetFootprintID (idImg, peakFootprint, IN_PEAK); 117 psFree(peakFootprint); 118 119 // Check if any of the previous (brighter) peaks are within the footprint of this peak 120 // If so, the current peak is bogus; drop it. 121 bool keep = true; 122 for (int j = 0; keep && (j < brightPeaks->n); j++) { 123 const pmPeak *peak2 = fp->peaks->data[j]; 124 int x2 = peak2->x - subImg->col0; 125 int y2 = peak2->y - subImg->row0; 126 if (idImg->data.S32[y2][x2] == IN_PEAK) 127 // There's a brighter peak within the footprint above threshold; so cull our initial peak 128 keep = false; 129 } 130 if (!keep) continue; 131 132 psArrayAdd (brightPeaks, 128, fp->peaks->data[i]); 133 133 } 134 134 … … 151 151 */ 152 152 psErrorCode pmFootprintCullPeaks_OLD(const psImage *img, // the image wherein lives the footprint 153 const psImage *weight,// corresponding variance image154 pmFootprint *fp, // Footprint containing mortal peaks155 const float nsigma_delta, // how many sigma above local background a peak needs to be to survive156 const float fPadding, // fractional padding added to stdev since bright peaks have unreasonably high significance157 const float min_threshold) { // minimum permitted coll height153 const psImage *weight, // corresponding variance image 154 pmFootprint *fp, // Footprint containing mortal peaks 155 const float nsigma_delta, // how many sigma above local background a peak needs to be to survive 156 const float fPadding, // fractional padding added to stdev since bright peaks have unreasonably high significance 157 const float min_threshold) { // minimum permitted coll height 158 158 assert (img != NULL); assert (img->type.type == PS_TYPE_F32); 159 159 assert (weight != NULL); assert (weight->type.type == PS_TYPE_F32); … … 162 162 163 163 if (fp->peaks == NULL || fp->peaks->n == 0) { // nothing to do 164 return PS_ERR_NONE;165 } 166 167 psRegion subRegion; // desired subregion; 1 larger than bounding box (grr)164 return PS_ERR_NONE; 165 } 166 167 psRegion subRegion; // desired subregion; 1 larger than bounding box (grr) 168 168 subRegion.x0 = fp->bbox.x0; subRegion.x1 = fp->bbox.x1 + 1; 169 169 subRegion.y0 = fp->bbox.y0; subRegion.y1 = fp->bbox.y1 + 1; … … 185 185 // 186 186 for (int i = 1; i < fp->peaks->n; i++) { // n.b. fp->peaks->n can change within the loop 187 const pmPeak *peak = fp->peaks->data[i];188 int x = peak->x - subImg->col0;189 int y = peak->y - subImg->row0;190 //191 // Find the level nsigma below the peak that must separate the peak192 // from any of its friends193 //194 assert (x >= 0 && x < subImg->numCols && y >= 0 && y < subImg->numRows);195 196 // stdev ~ sqrt(flux) : for bright regions (f ~ 1e6, sqrt(f) = 1e3 -- unrealistically small deviations)197 // add additional padding in quadrature:198 199 const float stdev = sqrt(subWt->data.F32[y][x]);200 const float flux = subImg->data.F32[y][x];201 const float fStdev = stdev/flux;202 const float stdev_pad = flux * hypot(fStdev, fPadding);203 float threshold = flux - nsigma_delta*stdev_pad;204 205 if (isnan(threshold) || threshold < min_threshold) {206 #if 1 // min_threshold is assumed to be below the detection threshold,207 // so all the peaks are pmFootprint, and this isn't the brightest208 // XXX mark peak to be dropped209 (void)psArrayRemoveIndex(fp->peaks, i);210 i--;// we moved everything down one211 continue;187 const pmPeak *peak = fp->peaks->data[i]; 188 int x = peak->x - subImg->col0; 189 int y = peak->y - subImg->row0; 190 // 191 // Find the level nsigma below the peak that must separate the peak 192 // from any of its friends 193 // 194 assert (x >= 0 && x < subImg->numCols && y >= 0 && y < subImg->numRows); 195 196 // stdev ~ sqrt(flux) : for bright regions (f ~ 1e6, sqrt(f) = 1e3 -- unrealistically small deviations) 197 // add additional padding in quadrature: 198 199 const float stdev = sqrt(subWt->data.F32[y][x]); 200 const float flux = subImg->data.F32[y][x]; 201 const float fStdev = stdev/flux; 202 const float stdev_pad = flux * hypot(fStdev, fPadding); 203 float threshold = flux - nsigma_delta*stdev_pad; 204 205 if (isnan(threshold) || threshold < min_threshold) { 206 #if 1 // min_threshold is assumed to be below the detection threshold, 207 // so all the peaks are pmFootprint, and this isn't the brightest 208 // XXX mark peak to be dropped 209 (void)psArrayRemoveIndex(fp->peaks, i); 210 i--; // we moved everything down one 211 continue; 212 212 #else 213 213 #error n.b. We will be running LOTS of checks at this threshold, so only find the footprint once 214 threshold = min_threshold;214 threshold = min_threshold; 215 215 #endif 216 }217 218 // XXX EAM : if stdev >= 0, i'm not sure how this can ever be true?219 if (threshold > subImg->data.F32[y][x]) {220 threshold = subImg->data.F32[y][x] - 10*FLT_EPSILON;221 }222 223 // XXX this is a bit expensive: psImageAlloc for every peak contained in this footprint224 // perhaps this should alloc a single ID image above and pass it in to be set.225 226 const int peak_id = 1;// the ID for the peak of interest227 brightPeaks->n = i;// only stop at a peak brighter than we are228 229 // XXX optionally use the faster pmFootprintsFind if the subimage size is large (eg, M31)230 231 pmFootprint *peakFootprint = pmFootprintsFindAtPoint(subImg, threshold, brightPeaks, peak->y, peak->x);232 brightPeaks->n = 0;// don't double free233 psImage *idImg = pmSetFootprintID(NULL, peakFootprint, peak_id);234 psFree(peakFootprint);235 236 // Check if any of the previous (brighter) peaks are within the footprint of this peak237 // If so, the current peak is bogus; drop it.238 int j;239 for (j = 0; j < i; j++) {240 const pmPeak *peak2 = fp->peaks->data[j];241 int x2 = peak2->x - subImg->col0;242 int y2 = peak2->y - subImg->row0;243 const int peak2_id = idImg->data.S32[y2][x2]; // the ID for some other peak244 245 if (peak2_id == peak_id) {// There's a brighter peak within the footprint above246 ;// threshold; so cull our initial peak247 (void)psArrayRemoveIndex(fp->peaks, i);248 i--;// we moved everything down one249 break;250 }251 }252 if (j == i) {253 j++;254 }255 256 psFree(idImg);216 } 217 218 // XXX EAM : if stdev >= 0, i'm not sure how this can ever be true? 219 if (threshold > subImg->data.F32[y][x]) { 220 threshold = subImg->data.F32[y][x] - 10*FLT_EPSILON; 221 } 222 223 // XXX this is a bit expensive: psImageAlloc for every peak contained in this footprint 224 // perhaps this should alloc a single ID image above and pass it in to be set. 225 226 const int peak_id = 1; // the ID for the peak of interest 227 brightPeaks->n = i; // only stop at a peak brighter than we are 228 229 // XXX optionally use the faster pmFootprintsFind if the subimage size is large (eg, M31) 230 231 pmFootprint *peakFootprint = pmFootprintsFindAtPoint(subImg, threshold, brightPeaks, peak->y, peak->x); 232 brightPeaks->n = 0; // don't double free 233 psImage *idImg = pmSetFootprintID(NULL, peakFootprint, peak_id); 234 psFree(peakFootprint); 235 236 // Check if any of the previous (brighter) peaks are within the footprint of this peak 237 // If so, the current peak is bogus; drop it. 238 int j; 239 for (j = 0; j < i; j++) { 240 const pmPeak *peak2 = fp->peaks->data[j]; 241 int x2 = peak2->x - subImg->col0; 242 int y2 = peak2->y - subImg->row0; 243 const int peak2_id = idImg->data.S32[y2][x2]; // the ID for some other peak 244 245 if (peak2_id == peak_id) { // There's a brighter peak within the footprint above 246 ; // threshold; so cull our initial peak 247 (void)psArrayRemoveIndex(fp->peaks, i); 248 i--; // we moved everything down one 249 break; 250 } 251 } 252 if (j == i) { 253 j++; 254 } 255 256 psFree(idImg); 257 257 } 258 258 259 259 brightPeaks->n = 0; psFree(brightPeaks); 260 psFree( (psImage *)subImg);261 psFree( (psImage *)subWt);260 psFree(subImg); 261 psFree(subWt); 262 262 263 263 return PS_ERR_NONE; -
branches/eam_branches/20091201/psModules/src/objects/pmFootprintFindAtPoint.c
r21183 r26533 29 29 * so we set appropriate mask bits 30 30 * 31 * EAM : these function were confusingly using "startspan" and "spartspan" 31 * EAM : these function were confusingly using "startspan" and "spartspan" 32 32 * I've rationalized them all to 'startspan' 33 33 */ … … 36 36 // An enum for what we should do with a Startspan 37 37 // 38 typedef enum {PM_SSPAN_DOWN = 0, // scan down from this span39 PM_SSPAN_UP,// scan up from this span40 PM_SSPAN_RESTART,// restart scanning from this span41 PM_SSPAN_DONE// this span is processed42 } PM_SSPAN_DIR; // How to continue searching38 typedef enum {PM_SSPAN_DOWN = 0, // scan down from this span 39 PM_SSPAN_UP, // scan up from this span 40 PM_SSPAN_RESTART, // restart scanning from this span 41 PM_SSPAN_DONE // this span is processed 42 } PM_SSPAN_DIR; // How to continue searching 43 43 // 44 44 // An enum for mask's pixel values. We're looking for pixels that are above threshold, and 45 45 // we keep extra book-keeping information in the PM_SSPAN_STOP plane. It's simpler to be 46 // able to check for 46 // able to check for 47 47 // 48 48 enum { 49 PM_SSPAN_INITIAL = 0x0, // initial state of pixels.50 PM_SSPAN_DETECTED = 0x1, // we've seen this pixel51 PM_SSPAN_STOP = 0x2 // you may stop searching when you see this pixel49 PM_SSPAN_INITIAL = 0x0, // initial state of pixels. 50 PM_SSPAN_DETECTED = 0x1, // we've seen this pixel 51 PM_SSPAN_STOP = 0x2 // you may stop searching when you see this pixel 52 52 }; 53 53 // … … 55 55 // 56 56 typedef struct { 57 const pmSpan *span; // save the pixel range58 PM_SSPAN_DIR direction; // How to continue searching59 bool stop; // should we stop searching?57 const pmSpan *span; // save the pixel range 58 PM_SSPAN_DIR direction; // How to continue searching 59 bool stop; // should we stop searching? 60 60 } Startspan; 61 61 62 62 static void startspanFree(Startspan *sspan) { 63 psFree( (void *)sspan->span);63 psFree(sspan->span); 64 64 } 65 65 66 66 static Startspan * 67 StartspanAlloc(const pmSpan *span, // The span in question68 psImage *mask,// Pixels that we've already detected69 const PM_SSPAN_DIR dir// Should we continue searching towards the top of the image?67 StartspanAlloc(const pmSpan *span, // The span in question 68 psImage *mask, // Pixels that we've already detected 69 const PM_SSPAN_DIR dir // Should we continue searching towards the top of the image? 70 70 ) { 71 71 Startspan *sspan = psAlloc(sizeof(Startspan)); … … 75 75 sspan->direction = dir; 76 76 sspan->stop = false; 77 78 if (mask != NULL) { // remember that we've detected these pixels79 psImageMaskType *mpix = &mask->data.PS_TYPE_IMAGE_MASK_DATA[span->y - mask->row0][span->x0 - mask->col0];80 81 for (int i = 0; i <= span->x1 - span->x0; i++) {82 mpix[i] |= PM_SSPAN_DETECTED;83 if (mpix[i] & PM_SSPAN_STOP) {84 sspan->stop = true;85 }86 }87 } 88 77 78 if (mask != NULL) { // remember that we've detected these pixels 79 psImageMaskType *mpix = &mask->data.PS_TYPE_IMAGE_MASK_DATA[span->y - mask->row0][span->x0 - mask->col0]; 80 81 for (int i = 0; i <= span->x1 - span->x0; i++) { 82 mpix[i] |= PM_SSPAN_DETECTED; 83 if (mpix[i] & PM_SSPAN_STOP) { 84 sspan->stop = true; 85 } 86 } 87 } 88 89 89 return sspan; 90 90 } … … 94 94 // 95 95 static bool add_startspan(psArray *startspans, // the saved Startspans 96 const pmSpan *sp, // the span in question97 psImage *mask, // mask of detected/stop pixels98 const PM_SSPAN_DIR dir) { // the desired direction to search96 const pmSpan *sp, // the span in question 97 psImage *mask, // mask of detected/stop pixels 98 const PM_SSPAN_DIR dir) { // the desired direction to search 99 99 if (dir == PM_SSPAN_RESTART) { 100 if (add_startspan(startspans, sp, mask, PM_SSPAN_UP) ||101 add_startspan(startspans, sp, NULL, PM_SSPAN_DOWN)) {102 return true;103 }100 if (add_startspan(startspans, sp, mask, PM_SSPAN_UP) || 101 add_startspan(startspans, sp, NULL, PM_SSPAN_DOWN)) { 102 return true; 103 } 104 104 } else { 105 Startspan *sspan = StartspanAlloc(sp, mask, dir);106 if (sspan->stop) {// we detected a stop bit107 psFree(sspan);// don't allocate new span108 109 return true;110 } else {111 psArrayAdd(startspans, 1, sspan);112 psFree(sspan);// as it's now owned by startspans113 }105 Startspan *sspan = StartspanAlloc(sp, mask, dir); 106 if (sspan->stop) { // we detected a stop bit 107 psFree(sspan); // don't allocate new span 108 109 return true; 110 } else { 111 psArrayAdd(startspans, 1, sspan); 112 psFree(sspan); // as it's now owned by startspans 113 } 114 114 } 115 115 … … 127 127 */ 128 128 static bool do_startspan(pmFootprint *fp, // the footprint that we're building 129 const psImage *img, // the psImage we're working on130 psImage *mask, // the associated masks131 const float threshold,// Threshold132 psArray *startspans) {// specify which span to process next133 bool F32 = false; // is this an F32 image?129 const psImage *img, // the psImage we're working on 130 psImage *mask, // the associated masks 131 const float threshold, // Threshold 132 psArray *startspans) { // specify which span to process next 133 bool F32 = false; // is this an F32 image? 134 134 if (img->type.type == PS_TYPE_F32) { 135 F32 = true;135 F32 = true; 136 136 } else if (img->type.type == PS_TYPE_S32) { 137 F32 = false;138 } else { // N.b. You can't trivially add more cases here; F32 is just a bool139 psError(PS_ERR_UNKNOWN, true, "Unsupported psImage type: %d", img->type.type);140 return NULL;141 } 142 143 psF32 *imgRowF32 = NULL; // row pointer if F32144 psS32 *imgRowS32 = NULL; // " " " " !F32145 psImageMaskType *maskRow = NULL; // masks's row pointer146 137 F32 = false; 138 } else { // N.b. You can't trivially add more cases here; F32 is just a bool 139 psError(PS_ERR_UNKNOWN, true, "Unsupported psImage type: %d", img->type.type); 140 return NULL; 141 } 142 143 psF32 *imgRowF32 = NULL; // row pointer if F32 144 psS32 *imgRowS32 = NULL; // " " " " !F32 145 psImageMaskType *maskRow = NULL; // masks's row pointer 146 147 147 const int row0 = img->row0; 148 148 const int col0 = img->col0; 149 149 const int numRows = img->numRows; 150 150 const int numCols = img->numCols; 151 151 152 152 /********************************************************************************************************/ 153 153 154 154 Startspan *sspan = NULL; 155 155 for (int i = 0; i < startspans->n; i++) { 156 sspan = startspans->data[i];157 if (sspan->direction != PM_SSPAN_DONE) {158 break;159 }160 if (sspan->stop) {161 break;162 }156 sspan = startspans->data[i]; 157 if (sspan->direction != PM_SSPAN_DONE) { 158 break; 159 } 160 if (sspan->stop) { 161 break; 162 } 163 163 } 164 164 if (sspan == NULL || sspan->direction == PM_SSPAN_DONE) { // no more Startspans to process 165 return false;166 } 167 if (sspan->stop) { // they don't want any more spans processed168 return false;165 return false; 166 } 167 if (sspan->stop) { // they don't want any more spans processed 168 return false; 169 169 } 170 170 /* … … 179 179 * Go through image identifying objects 180 180 */ 181 int nx0, nx1 = -1; // new values of x0, x1181 int nx0, nx1 = -1; // new values of x0, x1 182 182 const int di = (dir == PM_SSPAN_UP) ? 1 : -1; // how much i changes to get to the next row 183 bool stop = false; // should I stop searching for spans?183 bool stop = false; // should I stop searching for spans? 184 184 185 185 for (int i = sspan->span->y -row0 + di; i < numRows && i >= 0; i += di) { 186 imgRowF32 = img->data.F32[i];// only one of187 imgRowS32 = img->data.S32[i];// these is valid!188 maskRow = mask->data.PS_TYPE_IMAGE_MASK_DATA[i];189 //190 // Search left from the pixel diagonally to the left of (i - di, x0). If there's191 // a connected span there it may need to grow up and/or down, so push it onto192 // the stack for later consideration193 //194 nx0 = -1;195 for (int j = x0 - 1; j >= -1; j--) {196 double pixVal = (j < 0) ? threshold - 100 : (F32 ? imgRowF32[j] : imgRowS32[j]);197 if ((maskRow[j] & PM_SSPAN_DETECTED) || pixVal < threshold) {198 if (j < x0 - 1) {// we found some pixels above threshold199 nx0 = j + 1;200 }201 break;202 }203 }204 205 if (nx0 < 0) {// no span to the left206 nx1 = x0 - 1;// we're going to resume searching at nx1 + 1207 } else {208 //209 // Search right in leftmost span210 //211 //nx1 = 0;// make gcc happy212 for (int j = nx0 + 1; j <= numCols; j++) {213 double pixVal = (j >= numCols) ? threshold - 100 : (F32 ? imgRowF32[j] : imgRowS32[j]);214 if ((maskRow[j] & PM_SSPAN_DETECTED) || pixVal < threshold) {215 nx1 = j - 1;216 break;217 }218 }219 220 const pmSpan *sp = pmFootprintAddSpan(fp, i + row0, nx0 + col0, nx1 + col0);221 222 if (add_startspan(startspans, sp, mask, PM_SSPAN_RESTART)) {223 stop = true;224 break;225 }226 }227 //228 // Now look for spans connected to the old span. The first of these we'll229 // simply process, but others will have to be deferred for later consideration.230 //231 // In fact, if the span overhangs to the right we'll have to defer the overhang232 // until later too, as it too can grow in both directions233 //234 // Note that column numCols exists virtually, and always ends the last span; this235 // is why we claim below that sx1 is always set236 //237 bool first = false;// is this the first new span detected?238 for (int j = nx1 + 1; j <= x1 + 1; j++) {239 double pixVal = (j >= numCols) ? threshold - 100 : (F32 ? imgRowF32[j] : imgRowS32[j]);240 if (!(maskRow[j] & PM_SSPAN_DETECTED) && pixVal >= threshold) {241 int sx0 = j++;// span that we're working on is sx0:sx1242 int sx1 = -1;// We know that if we got here, we'll also set sx1243 for (; j <= numCols; j++) {244 double pixVal = (j >= numCols) ? threshold - 100 : (F32 ? imgRowF32[j] : imgRowS32[j]);245 if ((maskRow[j] & PM_SSPAN_DETECTED) || pixVal < threshold) { // end of span246 sx1 = j;247 break;248 }249 }250 assert (sx1 >= 0);251 252 const pmSpan *sp;253 if (first) {254 if (sx1 <= x1) {255 sp = pmFootprintAddSpan(fp, i + row0, sx0 + col0, sx1 + col0 - 1);256 if (add_startspan(startspans, sp, mask, PM_SSPAN_DONE)) {257 stop = true;258 break;259 }260 } else {// overhangs to right261 sp = pmFootprintAddSpan(fp, i + row0, sx0 + col0, x1 + col0);262 if (add_startspan(startspans, sp, mask, PM_SSPAN_DONE)) {263 stop = true;264 break;265 }266 sp = pmFootprintAddSpan(fp, i + row0, x1 + 1 + col0, sx1 + col0 - 1);267 if (add_startspan(startspans, sp, mask, PM_SSPAN_RESTART)) {268 stop = true;269 break;270 }271 }272 first = false;273 } else {274 sp = pmFootprintAddSpan(fp, i + row0, sx0 + col0, sx1 + col0 - 1);275 if (add_startspan(startspans, sp, mask, PM_SSPAN_RESTART)) {276 stop = true;277 break;278 }279 }280 }281 }282 283 if (stop || first == false) {// we're done284 break;285 }286 287 x0 = nx0; x1 = nx1;186 imgRowF32 = img->data.F32[i]; // only one of 187 imgRowS32 = img->data.S32[i]; // these is valid! 188 maskRow = mask->data.PS_TYPE_IMAGE_MASK_DATA[i]; 189 // 190 // Search left from the pixel diagonally to the left of (i - di, x0). If there's 191 // a connected span there it may need to grow up and/or down, so push it onto 192 // the stack for later consideration 193 // 194 nx0 = -1; 195 for (int j = x0 - 1; j >= -1; j--) { 196 double pixVal = (j < 0) ? threshold - 100 : (F32 ? imgRowF32[j] : imgRowS32[j]); 197 if ((maskRow[j] & PM_SSPAN_DETECTED) || pixVal < threshold) { 198 if (j < x0 - 1) { // we found some pixels above threshold 199 nx0 = j + 1; 200 } 201 break; 202 } 203 } 204 205 if (nx0 < 0) { // no span to the left 206 nx1 = x0 - 1; // we're going to resume searching at nx1 + 1 207 } else { 208 // 209 // Search right in leftmost span 210 // 211 //nx1 = 0; // make gcc happy 212 for (int j = nx0 + 1; j <= numCols; j++) { 213 double pixVal = (j >= numCols) ? threshold - 100 : (F32 ? imgRowF32[j] : imgRowS32[j]); 214 if ((maskRow[j] & PM_SSPAN_DETECTED) || pixVal < threshold) { 215 nx1 = j - 1; 216 break; 217 } 218 } 219 220 const pmSpan *sp = pmFootprintAddSpan(fp, i + row0, nx0 + col0, nx1 + col0); 221 222 if (add_startspan(startspans, sp, mask, PM_SSPAN_RESTART)) { 223 stop = true; 224 break; 225 } 226 } 227 // 228 // Now look for spans connected to the old span. The first of these we'll 229 // simply process, but others will have to be deferred for later consideration. 230 // 231 // In fact, if the span overhangs to the right we'll have to defer the overhang 232 // until later too, as it too can grow in both directions 233 // 234 // Note that column numCols exists virtually, and always ends the last span; this 235 // is why we claim below that sx1 is always set 236 // 237 bool first = false; // is this the first new span detected? 238 for (int j = nx1 + 1; j <= x1 + 1; j++) { 239 double pixVal = (j >= numCols) ? threshold - 100 : (F32 ? imgRowF32[j] : imgRowS32[j]); 240 if (!(maskRow[j] & PM_SSPAN_DETECTED) && pixVal >= threshold) { 241 int sx0 = j++; // span that we're working on is sx0:sx1 242 int sx1 = -1; // We know that if we got here, we'll also set sx1 243 for (; j <= numCols; j++) { 244 double pixVal = (j >= numCols) ? threshold - 100 : (F32 ? imgRowF32[j] : imgRowS32[j]); 245 if ((maskRow[j] & PM_SSPAN_DETECTED) || pixVal < threshold) { // end of span 246 sx1 = j; 247 break; 248 } 249 } 250 assert (sx1 >= 0); 251 252 const pmSpan *sp; 253 if (first) { 254 if (sx1 <= x1) { 255 sp = pmFootprintAddSpan(fp, i + row0, sx0 + col0, sx1 + col0 - 1); 256 if (add_startspan(startspans, sp, mask, PM_SSPAN_DONE)) { 257 stop = true; 258 break; 259 } 260 } else { // overhangs to right 261 sp = pmFootprintAddSpan(fp, i + row0, sx0 + col0, x1 + col0); 262 if (add_startspan(startspans, sp, mask, PM_SSPAN_DONE)) { 263 stop = true; 264 break; 265 } 266 sp = pmFootprintAddSpan(fp, i + row0, x1 + 1 + col0, sx1 + col0 - 1); 267 if (add_startspan(startspans, sp, mask, PM_SSPAN_RESTART)) { 268 stop = true; 269 break; 270 } 271 } 272 first = false; 273 } else { 274 sp = pmFootprintAddSpan(fp, i + row0, sx0 + col0, sx1 + col0 - 1); 275 if (add_startspan(startspans, sp, mask, PM_SSPAN_RESTART)) { 276 stop = true; 277 break; 278 } 279 } 280 } 281 } 282 283 if (stop || first == false) { // we're done 284 break; 285 } 286 287 x0 = nx0; x1 = nx1; 288 288 } 289 289 /* … … 309 309 */ 310 310 pmFootprint * 311 pmFootprintsFindAtPoint(const psImage *img, // image to search312 const float threshold,// Threshold313 const psArray *peaks, // array of peaks; finding one terminates search for footprint314 int row, int col) { // starting position (in img's parent's coordinate system)311 pmFootprintsFindAtPoint(const psImage *img, // image to search 312 const float threshold, // Threshold 313 const psArray *peaks, // array of peaks; finding one terminates search for footprint 314 int row, int col) { // starting position (in img's parent's coordinate system) 315 315 assert(img != NULL); 316 316 317 bool F32 = false; // is this an F32 image?317 bool F32 = false; // is this an F32 image? 318 318 if (img->type.type == PS_TYPE_F32) { 319 319 F32 = true; 320 320 } else if (img->type.type == PS_TYPE_S32) { 321 321 F32 = false; 322 } else { // N.b. You can't trivially add more cases here; F32 is just a bool322 } else { // N.b. You can't trivially add more cases here; F32 is just a bool 323 323 psError(PS_ERR_UNKNOWN, true, "Unsupported psImage type: %d", img->type.type); 324 324 return NULL; 325 325 } 326 psF32 *imgRowF32 = NULL; // row pointer if F32327 psS32 *imgRowS32 = NULL; // " " " " !F32328 326 psF32 *imgRowF32 = NULL; // row pointer if F32 327 psS32 *imgRowS32 = NULL; // " " " " !F32 328 329 329 const int row0 = img->row0; 330 330 const int col0 = img->col0; … … 339 339 psError(PS_ERR_BAD_PARAMETER_VALUE, true, 340 340 "row/col == (%d, %d) are out of bounds [%d--%d, %d--%d]", 341 row + row0, col + col0, row0, row0 + numRows - 1, col0, col0 + numCols - 1);341 row + row0, col + col0, row0, row0 + numRows - 1, col0, col0 + numCols - 1); 342 342 return NULL; 343 343 } … … 347 347 return pmFootprintAlloc(0, img); 348 348 } 349 349 350 350 pmFootprint *fp = pmFootprintAlloc(1 + img->numRows/10, img); 351 351 /* … … 364 364 if (peaks != NULL) { 365 365 for (int i = 0; i < peaks->n; i++) { 366 pmPeak *peak = peaks->data[i];367 mask->data.PS_TYPE_IMAGE_MASK_DATA[peak->y - mask->row0][peak->x - mask->col0] |= PM_SSPAN_STOP;366 pmPeak *peak = peaks->data[i]; 367 mask->data.PS_TYPE_IMAGE_MASK_DATA[peak->y - mask->row0][peak->x - mask->col0] |= PM_SSPAN_STOP; 368 368 } 369 369 } … … 372 372 */ 373 373 psArray *startspans = psArrayAllocEmpty(1); // spans where we have to restart the search 374 375 imgRowF32 = img->data.F32[row]; // only one of376 imgRowS32 = img->data.S32[row]; // these is valid!374 375 imgRowF32 = img->data.F32[row]; // only one of 376 imgRowS32 = img->data.S32[row]; // these is valid! 377 377 psImageMaskType *maskRow = mask->data.PS_TYPE_IMAGE_MASK_DATA[row]; 378 378 { 379 379 int i; 380 380 for (i = col; i >= 0; i--) { 381 pixVal = F32 ? imgRowF32[i] : imgRowS32[i];382 if ((maskRow[i] & PM_SSPAN_DETECTED) || pixVal < threshold) {383 break;384 }381 pixVal = F32 ? imgRowF32[i] : imgRowS32[i]; 382 if ((maskRow[i] & PM_SSPAN_DETECTED) || pixVal < threshold) { 383 break; 384 } 385 385 } 386 386 int i0 = i; 387 387 for (i = col; i < numCols; i++) { 388 pixVal = F32 ? imgRowF32[i] : imgRowS32[i];389 if ((maskRow[i] & PM_SSPAN_DETECTED) || pixVal < threshold) {390 break;391 }388 pixVal = F32 ? imgRowF32[i] : imgRowS32[i]; 389 if ((maskRow[i] & PM_SSPAN_DETECTED) || pixVal < threshold) { 390 break; 391 } 392 392 } 393 393 int i1 = i; … … 404 404 */ 405 405 psFree(mask); 406 psFree(startspans); // restores the image pixel407 408 return fp; // pmFootprint really406 psFree(startspans); // restores the image pixel 407 408 return fp; // pmFootprint really 409 409 }
Note:
See TracChangeset
for help on using the changeset viewer.
