Isis 3.0 Programmer Reference
Back | Home
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 namespace Isis {
40  CentroidApolloPan::CentroidApolloPan(double pixelSizeMicrons)
41  {
42  if( pixelSizeMicrons > 0)
43  this->m_pixelSize = pixelSizeMicrons;
44  else
45  this->m_pixelSize = 5.0; //if a negative or zero value is passed set the default
46  }
47 
48  CentroidApolloPan::~CentroidApolloPan(){};
49 
50  bool CentroidApolloPan::setPixelSize(double microns)
51  {
52  if( microns <= 0)return false;
53  this->m_pixelSize = microns;
54  return true;
55  }
56 
57  int CentroidApolloPan::selectAdaptive(Chip *inputChip,Chip *selectionChip) {
58  /*
59  Given a range of DN this function creates a biniary chip for all continuous pixels that have the DN within the specified range using the center pixel of the chip as the seed value
60  input:
61  m_minDN,m_maxDN set using the this->SetDNRange(..)
62  inputChip chip centered around some centroidable feature (dark or light continous block of pixels)
63 
64  output:
65  selectionChip binary chip of selected and unselected pixels
66 
67  */
68  //check the sizes of the chips and make the selectionChip match the inputChip
69  int lines, samples;
70 
71  int i,j,k,l,step;
72 
73  double minDN,maxDN,temp;
74 
75  vector< double> dn;
76 
77  lines = inputChip->Lines();
78  samples = inputChip->Samples();
79  //printf("DEBUG: samples: %d lines: %d\n",samples,lines);
80 
81  if (lines <= 0 || samples <= 0)
82  return 0; //abort if the input chips isn't 2D
83 
84  //check DN's around the edge, we want this centroid to stop before the edge of the chip
85  minDN = this->getMinDN();
86  maxDN = this->getMaxDN();
87 
88  //build an array of all the DN around the border of the chip
89  for (i=1;i<=lines;i++) {
90  if (i == 1 || i == lines) {
91  step = 1;
92  }
93  else {
94  step = samples-1;
95  }
96  for(j=1;j<=samples;j+=step) {
97  dn.push_back(inputChip->GetValue(j,i));
98  }
99  }
100 
101  //find the 90 percentile of dn
102  j = dn.size();
103  for (i=0;;i++) {
104  //find the largest ellement of dn
105  l=0;
106  temp = dn[0];
107  for (k=1;k<int(dn.size());k++) {
108  if (dn[k] > temp) {
109  temp = dn[k];
110  l =k;
111  }
112  }
113  //erase the largest ellement of dn or quit
114  if (i < int(j/10)) dn.erase(dn.begin()+l);
115  else break;
116  }
117 
118  if( temp > minDN) this->setDNRange(temp,maxDN); //set updated DN range
119 
120  //printf("DEBUG: minDN: %lf\n",temp); getchar();
121 
122  this->select(inputChip,selectionChip);
123 
124  this->setDNRange(minDN,maxDN); //restore original DN range
125 
126  return 1;
127  }
128 
129 
130  int CentroidApolloPan::elipticalReduction(Chip *selectionChip, double percent_selected, double play, int patience_limit)
131  {
132  /* The general elliptical reduction tool provided in the selection class is slow for the very large and potentially noisy ellipses of the apollo pan data
133  This method will take advantage of all the apriori knowlege we have of the size and orientation of the ellipse to speed up the process
134 
135  Specifically we know:
136  semiMajor Axis,a, is approximately parrallel to the sample chip axis and is approximately 60 5-micron pixels long
137  semiMinor Axis,b, is approximately parrallel to the line chip axis and is approximately 60 5-micron pixels long
138  Hence we know the center of the ellipse is on the range [a+1,Samples-a],[b+1,lines-b] (because the entire ellipse must be within the chip
139 
140  this->pixel_size will be used to do any scalling neccessary
141 
142  Algorithim:
143  Step 1: Compile an array of all points on the border of the selected area
144  Step 2: Choose a previously unused hypothesis center point from the range [a+1,samples-a],[b+1,lines-b]
145  Step 3: For a given hypothesized ellipse center in the search set, define the Ellipse.
146  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 effective grow to include more points.
147  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
148  Step 6: If the area is great enough check that the percent sellected is at least percent_selected.
149  Step 7: If all above tests are passed then we have a new Best ellipse and the number of consecutive emptySets is zeroed. Otherwise emptySets++
150  Step 8: repeat steps 2 through 7 until pacience_limit consecquitive failures to find a better (larger area) elipse have occured
151  */
152  int i,j,k,l,
153  emptySets, //number of consecutive failures to find a better ellipse
154  randPt, //random potential center point selection
155  samples, //samples in selectionChip
156  lines; //lines in selectionChip
157 
158  std::vector< std::vector<int> > pts; //vector of pixels on the border of the slection
159  std::vector< std::vector<double> > cen_pts; //vector of possible center pixels
160 
161  std::vector<double> pt(2); //individual pixel coordinate
162 
163  Ellipse ellNew,ellBest; //new and best ellipses
164 
165  double a = 60.0*5.0/m_pixelSize, //approximate semiMajor axis length
166  b = 60.0*5.0/m_pixelSize, //approximate semiMinor axis length
167  dpt[2]; //double 2D point
168 
169  //printf("DEBUG: a: %lf b: %lf pixel_size: %lf\n",a,b,m_pixelSize);
170  gsl_rng *randGen = gsl_rng_alloc(gsl_rng_taus);
171  gsl_rng_set(randGen, time(NULL)); //using the current time as a seed value
172 
173  samples = selectionChip->Samples();
174  lines = selectionChip->Lines();
175  //printf("DEBUG selectionchip samples: %d lines: %d\n",samples,lines);
176 
177  //populating a vector of all possible integral center points
178  k = int(ceil(double(samples) - a));
179  l = int(ceil(double(lines ) - b));
180  j=int(floor(b+1.0));
181  i=int(floor(a+1.0));
182 
183  cen_pts.clear();
184  //inorder to concentrate the search near the center of the chip we'll varry the step size for the center search nodes quadratically from 1*5.0/m_pixelSize at the center to 5.0*5.0/m_pixelSize at the edge
185  double searchStep = 5.0*5.0/m_pixelSize;
186  double aSearch,centerSample,centerLine,delta,cSearch;
187  cSearch = searchStep/5.0;
188  centerSample = double((k+i)/2.0);
189  centerLine = double((l+j)/2.0);
190  delta = (centerSample-double(i))*(centerSample-double(i)) + (centerLine -double(l))*(centerLine -double(l)); //square of the maximum distance from center of the search space
191 
192  aSearch = (searchStep-cSearch)/delta;
193 
194  for (pt[0]=floor(a+1.0); pt[0]<k; pt[0]+=searchStep) {
195  for (pt[1]=floor(b+1.0); pt[1]<l; pt[1]+=searchStep) {
196  cen_pts.push_back(pt);
197  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
198  searchStep = aSearch*delta + cSearch;
199  if (searchStep > l - pt[1] && l - pt[1] > 1e-4) //don't jump outside the search area
200  searchStep = l - pt[1];
201  }
202  if (searchStep > k - pt[0] && k - pt[0] > 1e-4) //don't jump outside the search area
203  searchStep = k - pt[0];
204  }
205 
206  //STEP 1: finding points along the boundary of the selection
207  selectionEdge(selectionChip,&pts);
208  //printf("DEBUG: edgePoints: %d\n",pts.size());
209 
210  if (pts.size() ==0) return 0;
211 
212  emptySets = 0;
213  ellBest.area = 0.0; //initialize the current best ellipse to zero area
214 
215  while (emptySets < patience_limit && cen_pts.size()>0) {
216  //printf("DEBUGA\n");
217  //STEP 2: choosing a new random hypothesis point
218  randPt = gsl_rng_uniform_int( randGen ,cen_pts.size() );
219  dpt[0] = cen_pts[randPt][0];
220  dpt[1] = cen_pts[randPt][1];
221 
222  cen_pts.erase( cen_pts.begin() + randPt); //erasing this ellement ensures it will never be chosen again
223  //printf("DEBUGB\n");
224  //STEP 3: Now define the ellipse
225  ellipseFromCenterAxesAngle(&ellNew, dpt[0], dpt[1], a, b, 0.0);
226  //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();
227  //printf("DEBUGC\n");
228  //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.
229  if (!bestFitEllipse(&ellNew, &pts, play, 50)) {
230  emptySets++;
231  continue; //if optimization fails go on to the next hypothesised ellipse
232  }
233  //printf("DEBUGD\n");
234  //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
235  if (ellNew.area < ellBest.area) {
236  emptySets++;
237  continue;
238  }
239  //printf("DEBUGE\n");
240  if (!ellipseInChip(&ellNew,selectionChip)) { //if the ellipse is entirely contained in the chip
241  emptySets++;
242  continue;
243  }
244  //printf("DEBUGF\n");
245  //STEP 6: if the area is great enough check that the percent sellected is at least percent_selected.
246  if (elipsePercentSelected(selectionChip,&ellNew) < percent_selected) {
247  emptySets++;
248  continue;
249  }
250 
251  //STEP 7 saving the new Best ellipse so far
252  //printf("DEBUG: new best area: %lf\n",ellNew.area);
253  emptySets=0;
254  ellBest.area = ellNew.area;
255  ellBest.A[0] = ellNew.A[0];
256  ellBest.A[1] = ellNew.A[1];
257  ellBest.A[2] = ellNew.A[2];
258 
259  ellBest.cen[0] = ellNew.cen[0];
260  ellBest.cen[1] = ellNew.cen[1];
261 
262  ellBest.semiMajor = ellNew.semiMajor;
263  ellBest.semiMinor = ellNew.semiMinor;
264  ellBest.majorAxis[0] = ellNew.majorAxis[0];
265  ellBest.majorAxis[1] = ellNew.majorAxis[1];
266  ellBest.minorAxis[0] = ellNew.minorAxis[0];
267  ellBest.minorAxis[1] = ellNew.minorAxis[1];
268  }
269 
270  if( ellBest.area == 0)
271  return 0; //no ellipse meeting the selection criteria was found
272 
274 
275  //go through and unselect the points outside the trimming ellipse
276  for (i=1;i<=samples;i++) {
277  for (j=1;j<=lines;j++) {
278  dpt[0] = double(i) ;
279  dpt[1] = double(j) ;
280 
281  if (!pointInEllipse(&ellBest,dpt,play)) { //if the point isn't within play pixles of being within the elipse
282  if( selectionChip->GetValue(i,j) == 1)
283  selectionChip->SetValue(i,j,3.0);
284  }
285  }
286  }
287  return 1;
288 
289  }
290 
291 }
A small chip of data used for pattern matching.
Definition: Chip.h:101
int Samples() const
Return the number of samples in the chip.
Definition: Chip.h:114
void SetValue(int sample, int line, const double &value)
Sets a value in the chip.
Definition: Chip.h:141
int Lines() const
Return the number of lines in the chip.
Definition: Chip.h:121
double GetValue(int sample, int line)
Loads a Chip with a value.
Definition: Chip.h:158

U.S. Department of the Interior | U.S. Geological Survey
ISIS | Privacy & Disclaimers | Astrogeology Research Program
To contact us, please post comments and questions on the ISIS Support Center
File Modified: 07/12/2023 23:15:44