source: trunk/src/Detection/lutz_detect.cc @ 222

Last change on this file since 222 was 222, checked in by Matthew Whiting, 17 years ago

Large commit, but mostly documentation-oriented.

Only non-doc-related changes are:

  • To remove two deprecated files and any declarations of the functions in them
  • To move drawBlankEdges to the Cubes/ directory
  • Some small changes to the implementation of the StatsContainer? functions.
  • Creation of Utils/devel.hh to hide functions not used in Duchamp
  • To move the trimmedHist stats functions to their own file, again to hide them.
File size: 6.9 KB
Line 
1#include <Cubes/cubes.hh>
2#include <Detection/detection.hh>
3#include <vector>
4
5enum STATUS { NONOBJECT, OBJECT, COMPLETE, INCOMPLETE };
6enum ROW { PRIOR=0, CURRENT};
7enum NULLS { NULLSTART=-1, NULLMARKER=45}; //ASCII 45 = '-' --> eases printing in case of debugging
8
9/**
10 * Local class to manage locating detections.
11 * Keeps a track of a detection, as well as the start and finish
12 * locations of the detection on the current row.
13 */
14class Object{
15public:
16  Object(){start=NULLSTART; end=NULLSTART;};
17  int start; ///< Pixel on the current row where the detection starts.
18  int end;   ///< Pixel on the current row where the detection finishes.
19  Detection info; ///< Collection of detected pixels.
20};
21
22void Image::lutz_detect()
23{
24/**
25 *  A detection algorithm for 2-dimensional images based on that of
26 *  Lutz (1980).
27 * 
28 *  The image is raster-scanned, and searched row-by-row. Objects
29 *  detected in each row are compared to objects in subsequent rows,
30 *  and combined if they are connected (in an 8-fold sense).
31 *
32 *  Note that "detected" here means according to the
33 *  Image::isDetection(long,long) function.
34 *
35 *  Upon return, the detected objects are stored in the
36 *  Image::objectList vector.
37 *
38 */
39
40  // Allocate necessary arrays.
41  STATUS *status   = new STATUS[2];
42  Detection *store = new Detection[this->axisDim[0]+1];
43  char *marker     = new char[this->axisDim[0]+1];
44  for(int i=0; i<(this->axisDim[0]+1); i++) marker[i] = NULLMARKER;
45  vector <Object>  *oS    = new vector <Object>;
46  vector <STATUS> *psS    = new vector <STATUS>;
47
48  Pixel *pix = new Pixel;
49
50  for(int posY=0;posY<(this->axisDim[1]+1);posY++){
51    // Loop over each row -- consider rows one at a time
52   
53    status[PRIOR] = COMPLETE;
54    status[CURRENT] = NONOBJECT;
55
56    pix->setY(posY);
57
58    for(int posX=0;posX<(this->axisDim[0]+1);posX++){
59      // Now the loop for a given row, looking at each column individually.
60
61      char currentMarker = marker[posX];
62      marker[posX] = NULLMARKER;
63      pix->setX(posX);
64
65      bool isObject = false;
66      if((posX<this->axisDim[0])&&(posY<this->axisDim[1])){
67        // if we are in the original image
68        isObject = this->isDetection(posX,posY);
69        pix->setF( this->array[posY*this->axisDim[0] + posX] );
70      }
71      // else we're in the padding row/col and isObject=FALSE;
72
73      //
74      // ------------------------------ START SEGMENT ------------------------
75      // If the current pixel is object and the previous pixel is not, then
76      // start a new segment.
77      // If the pixel touches an object on the prior row, the marker is either
78      // an S or an s, depending on whether the object has started yet.
79      // If it doesn't touch a prior object, this is the start of a completly
80      // new object on this row.
81      //
82      if ( (isObject) && (status[CURRENT] != OBJECT) ){
83
84        status[CURRENT] = OBJECT;
85        if(status[PRIOR] == OBJECT){
86         
87          if(oS->back().start==NULLSTART){
88            marker[posX] = 'S';
89            oS->back().start = posX;
90          }
91          else  marker[posX] = 's';
92        }
93        else{
94          psS->push_back(status[PRIOR]);  //PUSH PS onto PSSTACK;
95          marker[posX] = 'S';
96          oS->resize(oS->size()+1);        //PUSH OBSTACK;
97          oS->back().start = posX;
98
99          status[PRIOR] = COMPLETE;
100        }
101      }
102
103      //
104      // ------------------------------ PROCESS MARKER -----------------------
105      // If the current marker is not blank, then we need to deal with it.
106      // Four cases:
107      //   S --> start of object on prior row. Push priorStatus onto PSSTACK
108      //         and set priorStatus to OBJECT
109      //   s --> start of a secondary segment of object on prior row.
110      //         If current object joined, pop PSSTACK and join the objects.
111      //         Set priorStatus to OBJECT.
112      //   f --> end of a secondary segment of object on prior row.
113      //         Set priorStatus to INCOMPLETE.
114      //   F --> end of object on prior row. If no more of the object is to
115      //          come (priorStatus=COMPLETE), then finish it and output data.
116      //         Add to list, but only if it has more than the minimum number
117      //           of pixels.
118      //
119      if(currentMarker != NULLMARKER){
120
121        if(currentMarker == 'S'){
122          psS->push_back(status[PRIOR]);      // PUSH PS onto PSSTACK
123          if(status[CURRENT] == NONOBJECT){
124            psS->push_back(COMPLETE);         // PUSH COMPLETE ONTO PSSTACK;
125            oS->resize(oS->size()+1);          // PUSH OBSTACK;
126            oS->back().info = store[posX];
127          }
128          else oS->back().info.addAnObject( store[posX] );
129         
130          status[PRIOR] = OBJECT;
131        }
132
133        /*---------*/
134        if(currentMarker == 's'){
135
136          if( (status[CURRENT] == OBJECT) && (status[PRIOR] == COMPLETE) ){
137            status[PRIOR] = psS->back();
138            psS->pop_back();                   //POP PSSTACK ONTO PS
139
140//          oS->at(oS->size()-2).info.addAnObject( oS->back().info );
141//          if(oS->at(oS->size()-2).start == NULLSTART) oS->at(oS->size()-2).start = oS->back().start;
142//          else marker[oS->back().start] = 's';
143            (*oS)[oS->size()-2].info.addAnObject( oS->back().info );
144            if((*oS)[oS->size()-2].start == NULLSTART)
145              (*oS)[oS->size()-2].start = oS->back().start;
146            else marker[oS->back().start] = 's';
147
148            oS->pop_back();
149          }
150
151          status[PRIOR] = OBJECT;
152        }
153
154        /*---------*/
155        if(currentMarker == 'f') status[PRIOR] = INCOMPLETE;
156
157        /*---------*/
158        if(currentMarker == 'F') {
159
160          status[PRIOR] = psS->back();
161          psS->pop_back();                    //POP PSSTACK ONTO PS
162
163          if( (status[CURRENT] == NONOBJECT) && (status[PRIOR] == COMPLETE) ){
164
165            if(oS->back().start == NULLSTART){ // object completed
166              if(oS->back().info.getSize() >= this->minSize){
167                // is it big enough?
168                oS->back().info.calcParams(); // work out midpoints, fluxes etc
169                this->addObject(oS->back().info);
170              }
171            }
172            else{
173              marker[ oS->back().end ] = 'F';
174              store[ oS->back().start ] = oS->back().info;
175            }
176
177            oS->pop_back();
178
179            status[PRIOR] = psS->back();
180            psS->pop_back();
181          }
182        }
183
184      } // end of PROCESSMARKER section ( if(currentMarker!=NULLMARKER) )
185
186      if (isObject){
187        oS->back().info.addPixel(*pix);
188      }
189      else{
190        //
191        // ----------------------------- END SEGMENT -------------------------
192        // If the current pixel is background and the previous pixel was an
193        // object, then finish the segment.
194        // If the prior status is COMPLETE, it's the end of the final segment
195        // of the object section.
196        // If not, it's end of the segment, but not necessarily the section.
197        //
198        if ( status[CURRENT] == OBJECT) {
199
200          status[CURRENT] = NONOBJECT;
201
202          if(status[PRIOR] != COMPLETE){
203            marker[posX] = 'f';
204            oS->back().end = posX;
205          }
206          else{
207            status[PRIOR] = psS->back();
208            psS->pop_back();                   //POP PSSTACK onto PS;
209            marker[posX] = 'F';
210            store[ oS->back().start ] = oS->back().info;
211            oS->pop_back();
212          }
213        }
214       
215      } //-> end of END SEGMENT else{ clause
216
217    }//-> end of loop over posX
218
219  }//-> end of loop over posY
220
221  // clean up and remove declared arrays
222  delete [] marker;
223  delete oS;
224  delete psS;
225  delete [] store;
226  delete [] status;
227  delete pix;
228
229}
Note: See TracBrowser for help on using the repository browser.