Isis 3 Programmer Reference
CentroidApolloPan.cpp
1 
20 //Isis.h and IsisDebug.h if needed
21 
22 
23 //C++ standard libraries if needed
24 #include <math.h>
25 #include <time.h>
26 
27 //QT libraries if needed if needed
28 
29 
30 //third party libraries if needed
31 #include <gsl/gsl_rng.h>
32 #include "GSLUtility.h"
33 
34 //Isis Headers if needed
35 #include "CentroidApolloPan.h"
36 
37 
38 using namespace std;
39 
40 namespace Isis {
41 
47  CentroidApolloPan::CentroidApolloPan(double pixelSizeMicrons)
48  {
49  if( pixelSizeMicrons > 0)
50  this->m_pixelSize = pixelSizeMicrons;
51  else
52  this->m_pixelSize = 5.0; //if a negative or zero value is passed set the default
53  }
54 
55 
59  CentroidApolloPan::~CentroidApolloPan(){};
60 
68  bool CentroidApolloPan::setPixelSize(double microns)
69  {
70  if( microns <= 0)return false;
71  this->m_pixelSize = microns;
72  return true;
73  }
74 
85  int CentroidApolloPan::selectAdaptive(Chip *inputChip,Chip *selectionChip) {
86  /*
87  Given a range of DN this function creates a biniary chip for all continuous pixels that have the
88  DN within the specified range using the center pixel of the chip as the seed value
89  input:
90  m_minDN,m_maxDN set using the this->SetDNRange(..)
91  inputChip chip centered around some centroidable feature (dark or light continous block of
92  pixels)
93 
94  output:
95  selectionChip binary chip of selected and unselected pixels
96 
97  */
98 
99  //check the sizes of the chips and make the selectionChip match the inputChip
100  int lines, samples;
101 
102  int i,j,k,l,step;
103 
104  double minDN,maxDN,temp;
105 
106  vector< double> dn;
107 
108  lines = inputChip->Lines();
109  samples = inputChip->Samples();
110  //printf("DEBUG: samples: %d lines: %d\n",samples,lines);
111 
112  if (lines <= 0 || samples <= 0)
113  return 0; //abort if the input chips isn't 2D
114 
115  //check DN's around the edge, we want this centroid to stop before the edge of the chip
116  minDN = this->getMinDN();
117  maxDN = this->getMaxDN();
118 
119  //build an array of all the DN around the border of the chip
120  for (i=1;i<=lines;i++) {
121  if (i == 1 || i == lines) {
122  step = 1;
123  }
124  else {
125  step = samples-1;
126  }
127  for(j=1;j<=samples;j+=step) {
128  dn.push_back(inputChip->GetValue(j,i));
129  }
130  }
131 
132  //find the 90 percentile of dn
133  j = dn.size();
134  for (i=0;;i++) {
135  //find the largest ellement of dn
136  l=0;
137  temp = dn[0];
138  for (k=1;k<int(dn.size());k++) {
139  if (dn[k] > temp) {
140  temp = dn[k];
141  l =k;
142  }
143  }
144  //erase the largest ellement of dn or quit
145  if (i < int(j/10)) dn.erase(dn.begin()+l);
146  else break;
147  }
148 
149  if( temp > minDN) this->setDNRange(temp,maxDN); //set updated DN range
150 
151  //printf("DEBUG: minDN: %lf\n",temp); getchar();
152 
153  this->select(inputChip,selectionChip);
154 
155  this->setDNRange(minDN,maxDN); //restore original DN range
156 
157  return 1;
158  }
159 
160 
203  int CentroidApolloPan::elipticalReduction(Chip *selectionChip, double percent_selected,
204  double play, int patience_limit)
205  {
206  int i,j,k,l,
207  emptySets, //number of consecutive failures to find a better ellipse
208  randPt, //random potential center point selection
209  samples, //samples in selectionChip
210  lines; //lines in selectionChip
211 
212  std::vector< std::vector<int> > pts; //vector of pixels on the border of the slection
213  std::vector< std::vector<double> > cen_pts; //vector of possible center pixels
214 
215  std::vector<double> pt(2); //individual pixel coordinate
216 
217  Ellipse ellNew,ellBest; //new and best ellipses
218 
219  double a = 60.0*5.0/m_pixelSize, //approximate semiMajor axis length
220  b = 60.0*5.0/m_pixelSize, //approximate semiMinor axis length
221  dpt[2]; //double 2D point
222 
223  //printf("DEBUG: a: %lf b: %lf pixel_size: %lf\n",a,b,m_pixelSize);
224  gsl_rng *randGen = gsl_rng_alloc(gsl_rng_taus);
225  gsl_rng_set(randGen, time(NULL)); //using the current time as a seed value
226 
227  samples = selectionChip->Samples();
228  lines = selectionChip->Lines();
229  //printf("DEBUG selectionchip samples: %d lines: %d\n",samples,lines);
230 
231  //populating a vector of all possible integral center points
232  k = int(ceil(double(samples) - a));
233  l = int(ceil(double(lines ) - b));
234  j=int(floor(b+1.0));
235  i=int(floor(a+1.0));
236 
237  cen_pts.clear();
238 
239  /*
240  * inorder to concentrate the search near the center of the chip we'll varry the step size for
241  * the center search nodes quadratically from 1*5.0/m_pixelSize at the center to
242  * 5.0*5.0/m_pixelSize at the edge
243  */
244  double searchStep = 5.0*5.0/m_pixelSize;
245  double aSearch,centerSample,centerLine,delta,cSearch;
246  cSearch = searchStep/5.0;
247  centerSample = double((k+i)/2.0);
248  centerLine = double((l+j)/2.0);
249  delta = (centerSample-double(i))*(centerSample-double(i)) + (centerLine -double(l))*(centerLine -double(l)); //square of the maximum distance from center of the search space
250 
251  aSearch = (searchStep-cSearch)/delta;
252 
253  for (pt[0]=floor(a+1.0); pt[0]<k; pt[0]+=searchStep) {
254  for (pt[1]=floor(b+1.0); pt[1]<l; pt[1]+=searchStep) {
255  cen_pts.push_back(pt);
256  delta = (centerSample-double(pt[0]))*(centerSample-double(pt[0])) + (centerLine-double(pt[1]))*(centerLine-double(pt[1])); //square of the distance from center of the search space
257  searchStep = aSearch*delta + cSearch;
258  if (searchStep > l - pt[1] && l - pt[1] > 1e-4) //don't jump outside the search area
259  searchStep = l - pt[1];
260  }
261  if (searchStep > k - pt[0] && k - pt[0] > 1e-4) //don't jump outside the search area
262  searchStep = k - pt[0];
263  }
264 
265  //STEP 1: finding points along the boundary of the selection
266  selectionEdge(selectionChip,&pts);
267  //printf("DEBUG: edgePoints: %d\n",pts.size());
268 
269  if (pts.size() ==0) return 0;
270 
271  emptySets = 0;
272  ellBest.area = 0.0; //initialize the current best ellipse to zero area
273 
274  while (emptySets < patience_limit && cen_pts.size()>0) {
275  //printf("DEBUGA\n");
276  //STEP 2: choosing a new random hypothesis point
277  randPt = gsl_rng_uniform_int( randGen ,cen_pts.size() );
278  dpt[0] = cen_pts[randPt][0];
279  dpt[1] = cen_pts[randPt][1];
280 
281  cen_pts.erase( cen_pts.begin() + randPt); //erasing this ellement ensures it will never be chosen again
282  //printf("DEBUGB\n");
283  //STEP 3: Now define the ellipse
284  ellipseFromCenterAxesAngle(&ellNew, dpt[0], dpt[1], a, b, 0.0);
285  //printf("Debug a: %lf b: %lf theta: %lf center: %lf %lf\n",ellNew.semiMajor,ellNew.semiMinor,ellNew.majorAxis[0],ellNew.cen[0],ellNew.cen[1]);getchar();
286  //printf("DEBUGC\n");
287  //STEP 4: Do a least squares generization. Any points within a distance of play pixels to the edge of the ellipse are included in the gernalization. The distance check is repeated for every iteration so the ellipse can effectively grow to include more points.
288  if (!bestFitEllipse(&ellNew, &pts, play, 50)) {
289  emptySets++;
290  continue; //if optimization fails go on to the next hypothesised ellipse
291  }
292  //printf("DEBUGD\n");
293  //STEP 5: If the generization is successfully check to see if the area is at least as great as the current best, and that the ellipse is contained in the chip
294  if (ellNew.area < ellBest.area) {
295  emptySets++;
296  continue;
297  }
298  //printf("DEBUGE\n");
299  if (!ellipseInChip(&ellNew,selectionChip)) { //if the ellipse is entirely contained in the chip
300  emptySets++;
301  continue;
302  }
303  //printf("DEBUGF\n");
304  //STEP 6: if the area is great enough check that the percent sellected is at least percent_selected.
305  if (elipsePercentSelected(selectionChip,&ellNew) < percent_selected) {
306  emptySets++;
307  continue;
308  }
309 
310  //STEP 7 saving the new Best ellipse so far
311  //printf("DEBUG: new best area: %lf\n",ellNew.area);
312  emptySets=0;
313  ellBest.area = ellNew.area;
314  ellBest.A[0] = ellNew.A[0];
315  ellBest.A[1] = ellNew.A[1];
316  ellBest.A[2] = ellNew.A[2];
317 
318  ellBest.cen[0] = ellNew.cen[0];
319  ellBest.cen[1] = ellNew.cen[1];
320 
321  ellBest.semiMajor = ellNew.semiMajor;
322  ellBest.semiMinor = ellNew.semiMinor;
323  ellBest.majorAxis[0] = ellNew.majorAxis[0];
324  ellBest.majorAxis[1] = ellNew.majorAxis[1];
325  ellBest.minorAxis[0] = ellNew.minorAxis[0];
326  ellBest.minorAxis[1] = ellNew.minorAxis[1];
327  }
328 
329  if( ellBest.area == 0)
330  return 0; //no ellipse meeting the selection criteria was found
331 
333 
334  //go through and unselect the points outside the trimming ellipse
335  for (i=1;i<=samples;i++) {
336  for (j=1;j<=lines;j++) {
337  dpt[0] = double(i) ;
338  dpt[1] = double(j) ;
339 
340  if (!pointInEllipse(&ellBest,dpt,play)) { //if the point isn't within play pixles of being within the elipse
341  if( selectionChip->GetValue(i,j) == 1)
342  selectionChip->SetValue(i,j,3.0);
343  }
344  }
345  }
346  return 1;
347 
348  }
349 
350 }
A small chip of data used for pattern matching.
Definition: Chip.h:102
Namespace for the standard library.
int Lines() const
Definition: Chip.h:122
void SetValue(int sample, int line, const double &value)
Sets a value in the chip.
Definition: Chip.h:142
int Samples() const
Definition: Chip.h:115
Namespace for ISIS/Bullet specific routines.
Definition: Apollo.h:31
double GetValue(int sample, int line)
Loads a Chip with a value.
Definition: Chip.h:161