source: branches/fitshead-branch/Detection/lutz_detect.cc @ 1441

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

Coding fixes, improving the readability of the code, particularly regarding
the declaration of temporary variables. Files affected:
Detection/areClose.cc
Detection/detection.cc
Detection/thresholding_functions.cc
Detection/growObject.cc
Detection/mergeIntoList.cc
Detection/lutz_detect.cc

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