IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Changeset 13441


Ignore:
Timestamp:
May 21, 2007, 7:49:18 AM (19 years ago)
Author:
rhl
Message:

Rewrote pmFindFootprintAtPoint for speed using a mask and stop-pixels

Location:
trunk/psphot/src
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/psphot/src/pmFootprint.c

    r13372 r13441  
    448448    void *data;                         // saved data
    449449    void *data_home;                    // where the data was saved from
    450 } Startspan;
    451 
    452 static void startspanFree(Startspan *sspan) {
     450} Old_Spartspan;
     451
     452static void Old_startspanFree(Old_Spartspan *sspan) {
    453453    if (sspan->nbyte > 0) {
    454454        memcpy(sspan->data_home, sspan->data, sspan->nbyte); // restore image's pixels to their pristine state
     
    459459}
    460460
    461 static Startspan *
    462 StartspanAlloc(const pmSpan *span, // The span in question
     461static Old_Spartspan *
     462Old_SpartspanAlloc(const pmSpan *span, // The span in question
    463463               psImage *img,// the data wherein lives the span
    464464               const PM_SSPAN_DIR dir   // Should we continue searching towards the top of the image?
    465465    ) {
    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);
    468468
    469469    sspan->span = psMemIncrRefCounter((void *)span);
     
    507507
    508508//
    509 // Add a new Startspan to an array of Startspans
     509// Add a new Old_Spartspan to an array of Old_Spartspans
    510510//
    511 static void add_startspan(psArray *startspans, // the saved Startspans
     511static void old_add_startspan(psArray *startspans, // the saved Old_Spartspans
    512512                          const pmSpan *sp, // the span in question
    513513                          const psImage *img, // image to save/restore (or NULL)
    514514                          const PM_SSPAN_DIR dir) { // the desired direction to search
    515515    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);
    518518    } else {
    519         Startspan *sspan = StartspanAlloc(sp, (psImage *)img, dir);
     519        Old_Spartspan *sspan = Old_SpartspanAlloc(sp, (psImage *)img, dir);
    520520        psArrayAdd(startspans, 1, sspan);
    521521        psFree(sspan);                  // as it's now owned by startspans
     
    525525/************************************************************************************************************/
    526526/*
    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.
    528528 * We search the array looking for one to process; it'd be better to move the
    529529 * ones that we're done with to the end, but it probably isn't worth it for
    530530 * the anticipated uses of this routine.
    531531 *
    532  * This is the guts of pmFindFootprintAtPoint
    533  */
    534 static bool do_startspan(pmFootprint *fp, // the footprint that we're building
     532 * This is the guts of pmOldFindFootprintAtPoint
     533 */
     534static bool old_do_startspan(pmFootprint *fp, // the footprint that we're building
    535535                         const psImage *img, // the psImage we're working on
    536536                         const float threshold, // Threshold
     
    556556    /********************************************************************************************************/
    557557   
    558     Startspan *sspan = NULL;
     558    Old_Spartspan *sspan = NULL;
    559559    for (int i = 0; i < startspans->n; i++) {
    560560        sspan = startspans->data[i];
     
    563563        }
    564564    }
    565     if (sspan == NULL || sspan->direction == PM_SSPAN_DONE) { // no more Startspans to process
     565    if (sspan == NULL || sspan->direction == PM_SSPAN_DONE) { // no more Old_Spartspans to process
    566566        return false;
    567567    }
     
    615615            const pmSpan *sp = pmFootprintAddSpan(fp, i + row0, nx0 + col0, nx1 + col0);
    616616           
    617             add_startspan(startspans, sp, (psImage *)img, PM_SSPAN_RESTART);
     617            old_add_startspan(startspans, sp, (psImage *)img, PM_SSPAN_RESTART);
    618618        }
    619619        //
     
    646646                    if (sx1 <= x1) {
    647647                        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);
    649649                    } else {            // overhangs to right
    650650                        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);
    652652                        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);
    654654                    }
    655655                    first = false;
    656656                } else {
    657657                    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);
    659659                }
    660660            }
     
    689689 */
    690690pmFootprint *
    691 pmFindFootprintAtPoint(const psImage *img,      // image to search
     691pmOldFindFootprintAtPoint(const psImage *img,   // image to search
    692692                       const float threshold,   // Threshold
    693693                       int row, int col) { // starting position (in img's parent's coordinate system)
     
    753753       const pmSpan *sp = pmFootprintAddSpan(fp, row + row0, i0 + col0 + 1, i1 + col0 - 1);
    754754
    755        add_startspan(startspans, sp, (psImage *)img, PM_SSPAN_RESTART);
     755       old_add_startspan(startspans, sp, (psImage *)img, PM_SSPAN_RESTART);
    756756   }
    757757   /*
    758     * Now workout from those Startspans, searching for pixels above threshold
     758    * Now workout from those Old_Spartspans, searching for pixels above threshold
    759759    */
    760    while (do_startspan(fp, img, threshold, startspans)) continue;
     760   while (old_do_startspan(fp, img, threshold, startspans)) continue;
    761761   /*
    762762    * Cleanup
    763763    */
     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
     779typedef 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
     790enum {
     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
     796typedef 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
     802static void startspanFree(Spartspan *sspan) {
     803    psFree((void *)sspan->span);
     804}
     805
     806static Spartspan *
     807SpartspanAlloc(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//
     835static 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 */
     868static 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 */
     1050pmFootprint *
     1051pmFindFootprintAtPoint(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);
    7641146   psFree(startspans);                  // restores the image pixel
    7651147
     
    10581440  * starting point, discard the peak.
    10591441  */
    1060 psErrorCode pmFootprintCullPeaks(const psImage *img, // the image wherein lives the footprint
     1442psErrorCode pmOldFootprintCullPeaks(const psImage *img, // the image wherein lives the footprint
    10611443                                 const psImage *weight, // corresponding variance image
    10621444                                 pmFootprint *fp, // Footprint containing mortal peaks
     
    11171499#else
    11181500        const int peak_id = 1; // the ID for the peak of interest
    1119         pmFootprint *peakFootprint = pmFindFootprintAtPoint(subImg, threshold, peak->y, peak->x);
     1501        pmFootprint *peakFootprint = pmOldFindFootprintAtPoint(subImg, threshold, peak->y, peak->x);
    11201502        psImage *idImg = pmSetFootprintID(peakFootprint, peak_id);
    11211503        psFree(peakFootprint);
     
    11431525    }
    11441526
     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  */
     1540psErrorCode 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);
    11451626    psFree((psImage *)subImg);
    11461627    psFree((psImage *)subWt);
  • trunk/psphot/src/pmFootprint.h

    r13372 r13441  
    3131void pmFootprintSetBBox(pmFootprint *fp);
    3232psArray *pmFindFootprints(const psImage *img, const float threshold, const int npixMin);
     33pmFootprint *pmOldFindFootprintAtPoint(const psImage *img,
     34                                    const float threshold,
     35                                    int row, int col);
    3336pmFootprint *pmFindFootprintAtPoint(const psImage *img,
    3437                                    const float threshold,
     38                                    const psArray *peaks,
    3539                                    int row, int col);
    3640
Note: See TracChangeset for help on using the changeset viewer.