Changeset 27840 for branches/simtest_nebulous_branches/psModules/src/objects/pmFootprintFindAtPoint.c
- Timestamp:
- May 3, 2010, 8:50:52 AM (16 years ago)
- Location:
- branches/simtest_nebulous_branches
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/simtest_nebulous_branches
- Property svn:mergeinfo changed
-
branches/simtest_nebulous_branches/psModules
-
Property svn:mergeinfo
set to (toggle deleted branches)
/trunk/psModules merged eligible /branches/eam_branches/stackphot.20100406/psModules 27623-27653 /branches/pap_delete/psModules 27530-27595
-
Property svn:mergeinfo
set to (toggle deleted branches)
-
branches/simtest_nebulous_branches/psModules/src/objects/pmFootprintFindAtPoint.c
r21183 r27840 21 21 #include "pmFootprint.h" 22 22 #include "pmPeaks.h" 23 24 /* 25 * A data structure to hold the starting point for a search for pixels above threshold, 26 * used by pmFootprintsFindAtPoint 27 * 28 * We don't want to find this span again --- it's already part of the footprint --- 29 * so we set appropriate mask bits 30 * 31 * EAM : these function were confusingly using "startspan" and "spartspan" 32 * I've rationalized them all to 'startspan' 33 */ 34 35 // 36 // An enum for what we should do with a Startspan 37 // 38 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 // 44 // An enum for mask's pixel values. We're looking for pixels that are above threshold, and 45 // we keep extra book-keeping information in the PM_SSPAN_STOP plane. It's simpler to be 46 // able to check for 47 // 48 enum { 49 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 }; 53 // 54 // The struct that remembers how to [re-]start scanning the image for pixels 55 // 56 typedef struct { 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 } Startspan; 61 62 static void startspanFree(Startspan *sspan) { 63 psFree((void *)sspan->span); 64 } 65 66 static Startspan * 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 ) { 71 Startspan *sspan = psAlloc(sizeof(Startspan)); 72 psMemSetDeallocator(sspan, (psFreeFunc)startspanFree); 73 74 sspan->span = psMemIncrRefCounter((void *)span); 75 sspan->direction = dir; 76 sspan->stop = false; 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 return sspan; 90 } 91 92 // 93 // Add a new Startspan to an array of Startspans. Iff we see a stop bit, return true 94 // 95 static bool add_startspan(psArray *startspans, // the saved Startspans 96 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 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 } 104 } else { 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 } 115 116 return false; 117 } 23 #include "pmFootprintSpans.h" 118 24 119 25 /************************************************************************************************************/ 120 26 /* 121 * Search the image for pixels above threshold, starting at a single Startspan.27 * Search the image for pixels above threshold, starting at a single pmStartSpan. 122 28 * We search the array looking for one to process; it'd be better to move the 123 29 * ones that we're done with to the end, but it probably isn't worth it for … … 126 32 * This is the guts of pmFootprintsFindAtPoint 127 33 */ 128 static bool do_startspan(pmFootprint *fp, // the footprint that we're building 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? 34 bool pmFootprintSpansBuild(pmFootprint *fp, // the footprint that we're building 35 pmFootprintSpans *fpSpans, 36 const psImage *img, // the psImage we're working on 37 psImage *mask, // the associated masks 38 const float threshold // Threshold 39 ) { 40 bool F32 = false; // is this an F32 image? 41 if (img->type.type == PS_TYPE_F32) { 42 F32 = true; 43 } else if (img->type.type == PS_TYPE_S32) { 44 F32 = false; 45 } else { // N.b. You can't trivially add more cases here; F32 is just a bool 46 psError(PS_ERR_UNKNOWN, true, "Unsupported psImage type: %d", img->type.type); 47 return NULL; 48 } 49 50 psF32 *imgRowF32 = NULL; // row pointer if F32 51 psS32 *imgRowS32 = NULL; // " " " " !F32 52 psImageMaskType *maskRow = NULL; // masks's row pointer 53 54 const int row0 = img->row0; 55 const int col0 = img->col0; 56 const int numRows = img->numRows; 57 const int numCols = img->numCols; 58 59 /********************************************************************************************************/ 60 61 pmStartSpan *startspan = NULL; 62 for (int i = 0; i < fpSpans->nStartSpans; i++) { 63 startspan = fpSpans->startspans->data[i]; 64 if (startspan->direction != PM_STARTSPAN_DONE) { 65 break; 66 } 67 if (startspan->stop) { 68 break; 69 } 70 } 71 if (startspan == NULL || startspan->direction == PM_STARTSPAN_DONE) { // no more pmStartSpans to process 72 return false; 73 } 74 if (startspan->stop) { // they don't want any more spans processed 75 return false; 76 } 77 78 /* 79 * Work 80 */ 81 const PM_STARTSPAN_DIR dir = startspan->direction; 82 /* 83 * Set initial span to the startspan 84 */ 85 int x0 = startspan->span->x0 - col0, x1 = startspan->span->x1 - col0; 86 /* 87 * Go through image identifying objects 88 */ 89 int nx0, nx1 = -1; // new values of x0, x1 90 const int di = (dir == PM_STARTSPAN_UP) ? 1 : -1; // how much i changes to get to the next row 91 bool stop = false; // should I stop searching for spans? 92 93 for (int i = startspan->span->y - row0 + di; i < numRows && i >= 0; i += di) { 94 imgRowF32 = img->data.F32[i]; // only one of 95 imgRowS32 = img->data.S32[i]; // these is valid! 96 maskRow = mask->data.PS_TYPE_IMAGE_MASK_DATA[i]; 97 // 98 // Search left from the pixel diagonally to the left of (i - di, x0). If there's 99 // a connected span there it may need to grow up and/or down, so push it onto 100 // the stack for later consideration 101 // 102 nx0 = -1; 103 for (int j = x0 - 1; j >= -1; j--) { 104 double pixVal = (j < 0) ? threshold - 100 : (F32 ? imgRowF32[j] : imgRowS32[j]); 105 if ((maskRow[j] & PM_STARTSPAN_DETECTED) || pixVal < threshold) { 106 if (j < x0 - 1) { // we found some pixels above threshold 107 nx0 = j + 1; 108 } 109 break; 110 } 111 } 112 113 if (nx0 < 0) { // no span to the left 114 nx1 = x0 - 1; // we're going to resume searching at nx1 + 1 115 } else { 116 // 117 // Search right in leftmost span 118 // 119 for (int j = nx0 + 1; j <= numCols; j++) { 120 double pixVal = (j >= numCols) ? threshold - 100 : (F32 ? imgRowF32[j] : imgRowS32[j]); 121 if ((maskRow[j] & PM_STARTSPAN_DETECTED) || pixVal < threshold) { 122 nx1 = j - 1; 123 break; 124 } 125 } 126 127 pmSpan *sp = pmFootprintSetSpan(fp, i + row0, nx0 + col0, nx1 + col0); 128 bool status = pmFootprintSpansSet(fpSpans, sp, mask, PM_STARTSPAN_RESTART); 129 // fprintf (stderr, "set 1: %d vs %d\n", fp->nspans, fpSpans->nStartSpans); 130 if (status) { 131 stop = true; 132 break; 133 } 134 } 135 // 136 // Now look for spans connected to the old span. The first of these we'll 137 // simply process, but others will have to be deferred for later consideration. 138 // 139 // In fact, if the span overhangs to the right we'll have to defer the overhang 140 // until later too, as it too can grow in both directions 141 // 142 // Note that column numCols exists virtually, and always ends the last span; this 143 // is why we claim below that sx1 is always set 144 // 145 bool first = false; // is this the first new span detected? 146 for (int j = nx1 + 1; j <= x1 + 1; j++) { 147 double pixVal = (j >= numCols) ? threshold - 100 : (F32 ? imgRowF32[j] : imgRowS32[j]); 148 if (!(maskRow[j] & PM_STARTSPAN_DETECTED) && pixVal >= threshold) { 149 int sx0 = j++; // span that we're working on is sx0:sx1 150 int sx1 = -1; // We know that if we got here, we'll also set sx1 151 for (; j <= numCols; j++) { 152 double pixVal = (j >= numCols) ? threshold - 100 : (F32 ? imgRowF32[j] : imgRowS32[j]); 153 if ((maskRow[j] & PM_STARTSPAN_DETECTED) || pixVal < threshold) { // end of span 154 sx1 = j; 155 break; 156 } 157 } 158 assert (sx1 >= 0); 159 160 pmSpan *sp; 161 if (first) { 162 if (sx1 <= x1) { 163 sp = pmFootprintSetSpan(fp, i + row0, sx0 + col0, sx1 + col0 - 1); 164 bool status = pmFootprintSpansSet(fpSpans, sp, mask, PM_STARTSPAN_DONE); 165 // fprintf (stderr, "set 2: %d vs %d\n", fp->nspans, fpSpans->nStartSpans); 166 if (status) { 167 stop = true; 168 break; 169 } 170 } else { // overhangs to right 171 sp = pmFootprintSetSpan(fp, i + row0, sx0 + col0, x1 + col0); 172 bool status = pmFootprintSpansSet(fpSpans, sp, mask, PM_STARTSPAN_DONE); 173 // fprintf (stderr, "set 3: %d vs %d\n", fp->nspans, fpSpans->nStartSpans); 174 if (status) { 175 stop = true; 176 break; 177 } 178 sp = pmFootprintSetSpan(fp, i + row0, x1 + 1 + col0, sx1 + col0 - 1); 179 status = pmFootprintSpansSet(fpSpans, sp, mask, PM_STARTSPAN_RESTART); 180 // fprintf (stderr, "set 4: %d vs %d\n", fp->nspans, fpSpans->nStartSpans); 181 if (status) { 182 stop = true; 183 break; 184 } 185 } 186 first = false; 187 } else { 188 sp = pmFootprintSetSpan(fp, i + row0, sx0 + col0, sx1 + col0 - 1); 189 bool status = pmFootprintSpansSet(fpSpans, sp, mask, PM_STARTSPAN_RESTART); 190 // fprintf (stderr, "set 5: %d vs %d\n", fp->nspans, fpSpans->nStartSpans); 191 if (status) { 192 stop = true; 193 break; 194 } 195 } 196 } 197 } 198 199 if (stop || first == false) { // we're done 200 break; 201 } 202 203 x0 = nx0; x1 = nx1; 204 } 205 /* 206 * Cleanup 207 */ 208 209 startspan->direction = PM_STARTSPAN_DONE; 210 return stop ? false : true; 211 } 212 213 /* 214 * Go through an image, starting at (row, col) and assembling all the pixels 215 * that are connected to that point (in a chess kings-move sort of way) into 216 * a pmFootprint. 217 * 218 * This is much slower than pmFootprintsFind if you want to find lots of 219 * footprints, but if you only want a small region about a given point it 220 * can be much faster 221 * 222 * N.b. The returned pmFootprint is not in "normal form"; that is the pmSpans 223 * are not sorted by increasing y, x0, x1. If this matters to you, call 224 * pmFootprintNormalize() 225 * 226 * The calling function must supply a footprint allocated with a reasonable amount of space 227 * 228 */ 229 230 bool pmFootprintsFindAtPoint(pmFootprint *fp, 231 pmFootprintSpans *fpSpans, 232 const psImage *img, // image to search 233 psImage *mask, 234 const float threshold, // Threshold 235 const psArray *peaks, // array of peaks; finding one terminates search for footprint 236 int row, int col) { // starting position (in img's parent's coordinate system) 237 psAssert(img, "image must be supplied"); 238 psAssert(fp, "footprint must be supplied"); 239 psAssert(fpSpans, "footprint spans must be supplied"); 240 241 bool F32 = false; // is this an F32 image? 134 242 if (img->type.type == PS_TYPE_F32) { 135 243 F32 = true; 136 244 } else if (img->type.type == PS_TYPE_S32) { 137 245 F32 = false; 138 } else { // N.b. You can't trivially add more cases here; F32 is just a bool246 } else { // N.b. You can't trivially add more cases here; F32 is just a bool 139 247 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 248 return false; 249 } 250 psF32 *imgRowF32 = NULL; // row pointer if F32 251 psS32 *imgRowS32 = NULL; // " " " " !F32 252 147 253 const int row0 = img->row0; 148 254 const int col0 = img->col0; 149 255 const int numRows = img->numRows; 150 256 const int numCols = img->numCols; 151 152 /********************************************************************************************************/ 153 154 Startspan *sspan = NULL; 155 for (int i = 0; i < startspans->n; i++) { 156 sspan = startspans->data[i]; 157 if (sspan->direction != PM_SSPAN_DONE) { 158 break; 257 258 /* 259 * Is point in image, and above threshold? 260 */ 261 row -= row0; col -= col0; 262 if (row < 0 || row >= numRows || 263 col < 0 || col >= numCols) { 264 psError(PS_ERR_BAD_PARAMETER_VALUE, true, 265 "row/col == (%d, %d) are out of bounds [%d--%d, %d--%d]", 266 row + row0, col + col0, row0, row0 + numRows - 1, col0, col0 + numCols - 1); 267 return false; 268 } 269 270 double pixVal = F32 ? img->data.F32[row][col] : img->data.S32[row][col]; 271 if (pixVal < threshold) { 272 return true; 273 } 274 275 /* 276 * We need a mask for two purposes; to indicate which pixels are already detected, 277 * and to store the "stop" pixels --- those that, once reached, should stop us 278 * looking for the rest of the pmFootprint. These are generally set from peaks. 279 */ 280 281 pmFootprintInit(fp); 282 pmFootprintSpansInit(fpSpans); 283 psImageInit(mask, PM_STARTSPAN_INITIAL); 284 285 // fprintf (stderr, "init: %d vs %d\n", fp->nspans, fpSpans->nStartSpans); 286 287 // 288 // Set stop bits from peaks list 289 // 290 assert (peaks == NULL || peaks->n == 0 || psMemCheckPeak(peaks->data[0])); 291 if (peaks != NULL) { 292 for (int i = 0; i < peaks->n; i++) { 293 pmPeak *peak = peaks->data[i]; 294 mask->data.PS_TYPE_IMAGE_MASK_DATA[peak->y - mask->row0][peak->x - mask->col0] |= PM_STARTSPAN_STOP; 159 295 } 160 if (sspan->stop) { 161 break; 162 } 163 } 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 processed 168 return false; 169 } 170 /* 171 * Work 172 */ 173 const PM_SSPAN_DIR dir = sspan->direction; 174 /* 175 * Set initial span to the startspan 176 */ 177 int x0 = sspan->span->x0 - col0, x1 = sspan->span->x1 - col0; 178 /* 179 * Go through image identifying objects 180 */ 181 int nx0, nx1 = -1; // new values of x0, x1 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? 184 185 for (int i = sspan->span->y -row0 + di; i < numRows && i >= 0; i += di) { 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 } 296 } 297 298 /* 299 * Find starting span passing through (row, col) 300 */ 301 imgRowF32 = img->data.F32[row]; // only one of 302 imgRowS32 = img->data.S32[row]; // these is valid! 303 psImageMaskType *maskRow = mask->data.PS_TYPE_IMAGE_MASK_DATA[row]; 304 { 305 int i; 306 for (i = col; i >= 0; i--) { 307 pixVal = F32 ? imgRowF32[i] : imgRowS32[i]; 308 if ((maskRow[i] & PM_STARTSPAN_DETECTED) || pixVal < threshold) { 201 309 break; 202 310 } 203 311 } 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; 312 int i0 = i; 313 for (i = col; i < numCols; i++) { 314 pixVal = F32 ? imgRowF32[i] : imgRowS32[i]; 315 if ((maskRow[i] & PM_STARTSPAN_DETECTED) || pixVal < threshold) { 224 316 break; 225 317 } 226 318 } 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 } 319 int i1 = i; 320 pmSpan *sp = pmFootprintSetSpan(fp, row + row0, i0 + col0 + 1, i1 + col0 - 1); 321 pmFootprintSpansSet(fpSpans, sp, mask, PM_STARTSPAN_RESTART); 322 // fprintf (stderr, "first: %d vs %d\n", fp->nspans, fpSpans->nStartSpans); 323 } 324 /* 325 * Now workout from those pmStartSpans, searching for pixels above threshold 326 */ 327 while (pmFootprintSpansBuild(fp, fpSpans, img, mask, threshold)) continue; 289 328 /* 290 329 * Cleanup 291 330 */ 292 293 sspan->direction = PM_SSPAN_DONE; 294 return stop ? false : true; 331 // psFree(mask); 332 // psFree(startspans); // restores the image pixel 333 334 return fp; // pmFootprint really 295 335 } 296 297 /*298 * Go through an image, starting at (row, col) and assembling all the pixels299 * that are connected to that point (in a chess kings-move sort of way) into300 * a pmFootprint.301 *302 * This is much slower than pmFootprintsFind if you want to find lots of303 * footprints, but if you only want a small region about a given point it304 * can be much faster305 *306 * N.b. The returned pmFootprint is not in "normal form"; that is the pmSpans307 * are not sorted by increasing y, x0, x1. If this matters to you, call308 * pmFootprintNormalize()309 */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)315 assert(img != NULL);316 317 bool F32 = false; // is this an F32 image?318 if (img->type.type == PS_TYPE_F32) {319 F32 = true;320 } else if (img->type.type == PS_TYPE_S32) {321 F32 = false;322 } else { // N.b. You can't trivially add more cases here; F32 is just a bool323 psError(PS_ERR_UNKNOWN, true, "Unsupported psImage type: %d", img->type.type);324 return NULL;325 }326 psF32 *imgRowF32 = NULL; // row pointer if F32327 psS32 *imgRowS32 = NULL; // " " " " !F32328 329 const int row0 = img->row0;330 const int col0 = img->col0;331 const int numRows = img->numRows;332 const int numCols = img->numCols;333 /*334 * Is point in image, and above threshold?335 */336 row -= row0; col -= col0;337 if (row < 0 || row >= numRows ||338 col < 0 || col >= numCols) {339 psError(PS_ERR_BAD_PARAMETER_VALUE, true,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);342 return NULL;343 }344 345 double pixVal = F32 ? img->data.F32[row][col] : img->data.S32[row][col];346 if (pixVal < threshold) {347 return pmFootprintAlloc(0, img);348 }349 350 pmFootprint *fp = pmFootprintAlloc(1 + img->numRows/10, img);351 /*352 * We need a mask for two purposes; to indicate which pixels are already detected,353 * and to store the "stop" pixels --- those that, once reached, should stop us354 * looking for the rest of the pmFootprint. These are generally set from peaks.355 */356 psImage *mask = psImageAlloc(numCols, numRows, PS_TYPE_IMAGE_MASK);357 P_PSIMAGE_SET_ROW0(mask, row0);358 P_PSIMAGE_SET_COL0(mask, col0);359 psImageInit(mask, PM_SSPAN_INITIAL);360 //361 // Set stop bits from peaks list362 //363 assert (peaks == NULL || peaks->n == 0 || psMemCheckPeak(peaks->data[0]));364 if (peaks != NULL) {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;368 }369 }370 /*371 * Find starting span passing through (row, col)372 */373 psArray *startspans = psArrayAllocEmpty(1); // spans where we have to restart the search374 375 imgRowF32 = img->data.F32[row]; // only one of376 imgRowS32 = img->data.S32[row]; // these is valid!377 psImageMaskType *maskRow = mask->data.PS_TYPE_IMAGE_MASK_DATA[row];378 {379 int i;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 }385 }386 int i0 = i;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 }392 }393 int i1 = i;394 const pmSpan *sp = pmFootprintAddSpan(fp, row + row0, i0 + col0 + 1, i1 + col0 - 1);395 396 (void)add_startspan(startspans, sp, mask, PM_SSPAN_RESTART);397 }398 /*399 * Now workout from those Startspans, searching for pixels above threshold400 */401 while (do_startspan(fp, img, mask, threshold, startspans)) continue;402 /*403 * Cleanup404 */405 psFree(mask);406 psFree(startspans); // restores the image pixel407 408 return fp; // pmFootprint really409 }
Note:
See TracChangeset
for help on using the changeset viewer.
