source: tags/release-0.9/Detection/lutz_detect.cc @ 813

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

Introduced a new parameter to the Image class : minSize, the minimum size
of a detection for it to be accepted.
Added code in the searching algorithms to distinguish between minPix and
minChannels for the 2D and 1D searches.
Set default value of minPix to 2.

File size: 6.4 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 Stack{
22public:
23  Stack(){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 <Stack>  *oS     = new vector <Stack>;
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 = new char;
54      *currentMarker = marker[posX];
55      marker[posX] = NULLMARKER;
56      pix->setX(posX);
57
58      bool *isObject = new bool;
59      *isObject = false;
60      if((posX<this->axisDim[0])&&(posY<this->axisDim[1])){ // if we are in the original image
61        *isObject = this->isDetection(posX,posY);
62        pix->setF( this->array[posY*this->axisDim[0] + posX] );
63      }
64      // else we're in the padding row/col and isObject=FALSE;
65
66      /**
67       * ------------------------------ START SEGMENT ------------------------
68       * If the current pixel is object and the previous pixel is not, then
69       * start a new segment.
70       * If the pixel touches an object on the prior row, the marker is either 
71       * an S or an s, depending on whether the object has started yet.
72       * If it doesn't touch a prior object, this is the start of a completly
73       * new object on this row.
74       */
75      if ( (*isObject) && (status[CURRENT] != OBJECT) ){
76
77        status[CURRENT] = OBJECT;
78        if(status[PRIOR] == OBJECT){
79         
80          if(oS->back().start==NULLSTART){
81            marker[posX] = 'S';
82            oS->back().start = posX;
83          }
84          else  marker[posX] = 's';
85        }
86        else{
87          psS->push_back(status[PRIOR]);  //PUSH PS onto PSSTACK;
88          marker[posX] = 'S';
89          oS->resize(oS->size()+1);        //PUSH OBSTACK;
90          oS->back().start = posX;
91
92          status[PRIOR] = COMPLETE;
93        }
94      }
95
96      /**
97       * ------------------------------ PROCESS MARKER --------------------------
98       * If the current marker is not blank, then we need to deal with it.
99       * Four cases:
100       *   S --> start of object on prior row. Push priorStatus onto PSSTACK
101       *         and set priorStatus to OBJECT
102       *   s --> start of a secondary segment of object on prior row.
103       *         If current object joined, pop PSSTACK and join the objects.
104       *         Set priorStatus to OBJECT.
105       *   f --> end of a secondary segment of object on prior row.
106       *         Set priorStatus to INCOMPLETE.
107       *   F --> end of object on prior row. If no more of the object is to come
108       *         (priorStatus=COMPLETE), then finish it and output data.
109       *         Addition -- only if it has more than the minimum no. of pixels.
110       */
111      if(*currentMarker != NULLMARKER){
112
113        if(*currentMarker == 'S'){
114          psS->push_back(status[PRIOR]);      // PUSH PS onto PSSTACK
115          if(status[CURRENT] == NONOBJECT){
116            psS->push_back(COMPLETE);         // PUSH COMPLETE ONTO PSSTACK;
117            oS->resize(oS->size()+1);          // PUSH OBSTACK;
118            oS->back().info = store[posX];
119          }
120          else oS->back().info.addAnObject( store[posX] );
121         
122          status[PRIOR] = OBJECT;
123        }
124
125        /*---------*/
126        if(*currentMarker == 's'){
127
128          if( (status[CURRENT] == OBJECT) && (status[PRIOR] == COMPLETE) ){
129            status[PRIOR] = psS->back();
130            psS->pop_back();                   //POP PSSTACK ONTO PS
131
132            oS->at(oS->size()-2).info.addAnObject( oS->back().info );
133            if(oS->at(oS->size()-2).start == NULLSTART) oS->at(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      delete currentMarker;
206      delete isObject;
207
208    }//-> end of loop over posX
209
210  }//-> end of loop over posY
211
212  // clean up and remove declared arrays
213  delete [] marker;
214  delete oS;
215  delete psS;
216  delete [] store;
217  delete [] status;
218  delete pix;
219
220}
Note: See TracBrowser for help on using the repository browser.