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

Last change on this file since 108 was 108, checked in by Matthew Whiting, 18 years ago

Changed source tree structure: added a src/ directory that contains all the
code. Makefile.in and configure.ac changed to match.

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