29 #include <gsl/gsl_linalg.h>    30 #include <gsl/gsl_rng.h>    41   Selection::Selection() {};
    42   Selection::~Selection() {};
    46   int Selection::elipticalReduction(Chip *selectionChip, 
double percent_selected, 
double play, 
int patience_limit) {
    65     std::vector < std::vector<int> > pts;  
    67     double dpt[2], random5[5][2];
    69     unsigned long int randPt;
    73     gsl_rng *rand_gen = gsl_rng_alloc(gsl_rng_taus);
    74     gsl_rng_set( rand_gen, time(NULL) );  
    77     samples = selectionChip->Samples();
    78     lines  = selectionChip->Lines();
    81     selectionEdge(selectionChip,&pts);
    87     while (emptySets < patience_limit) {
    90         randPt = gsl_rng_uniform_int( rand_gen  ,pts.size());
    91         random5[i][0] = pts[randPt][0];
    92         random5[i][1] = pts[randPt][1];
    96       if (!ellipseFrom5Pts(&ellNew,random5)) { 
   102       if ( ellNew.cen[0] < 1 || ellNew.cen[0] > samples || ellNew.cen[1] < 1 || ellNew.cen[1] > lines ) {
   108       if (!bestFitEllipse(&ellNew, &pts, play, 50)) {
   114       if (ellNew.area < ellBest.area) {    
   120       if (!ellipseInChip(&ellNew,selectionChip)) {  
   127       if (elipsePercentSelected(selectionChip,&ellNew) < percent_selected) {
   136       ellBest.area = ellNew.area;
   137       ellBest.A[0] = ellNew.A[0];
   138       ellBest.A[1] = ellNew.A[1];
   139       ellBest.A[2] = ellNew.A[2];
   141       ellBest.cen[0] = ellNew.cen[0];
   142       ellBest.cen[1] = ellNew.cen[1];
   144       ellBest.semiMajor = ellNew.semiMajor;
   145       ellBest.semiMinor = ellNew.semiMinor;
   146       ellBest.majorAxis[0] = ellNew.majorAxis[0];
   147       ellBest.majorAxis[1] = ellNew.majorAxis[1];
   148       ellBest.minorAxis[0] = ellNew.minorAxis[0];
   149       ellBest.minorAxis[1] = ellNew.minorAxis[1];
   153     if (ellBest.area == 0)
   157     for (i=1;i<=samples;i++) {
   158       for (j=1;j<=lines;j++) {
   162         if (!pointInEllipse(&ellBest,dpt,play)) {  
   164           selectionChip->SetValue(i,j,0.0);
   178   int Selection::centerOfMass(Chip *selectionChip, 
double *sample, 
double *line) {
   180     unsigned int samples, lines, i, j, n=0;
   183     samples = selectionChip->Samples();
   184     lines =   selectionChip->Lines();
   186     for (i=1;i<=samples;i++) {
   187       for (j=1;j<=lines;j++) {
   188         if (selectionChip->GetValue(i,j) == 1) {
   196     *sample /= double(n);
   201   int Selection::centerOfMassWeighted(Chip *inputChip, Chip *selectionChip, 
double *sample, 
double *line) {
   204     int samples, lines,i, j;
   206     samples = selectionChip->Samples();
   207     if (inputChip->Samples() != samples) {
   212     lines =   selectionChip->Lines();
   213     if (inputChip->Lines() != lines) {
   223     for (i=1;i<=samples;i++) {
   224       for (j=1;j<=lines;j++) {
   225         if (selectionChip->GetValue(i,j) == 1) {
   226           temp = inputChip->GetValue(i,j);
   227           *sample += double(i)*temp;
   228           *line   += double(j)*temp;
   242   std::vector<double> Selection::minimumBoundingElipse(std::vector< std::vector<int> > pts,
Ellipse *ell) {
   249     std::vector<double> lamda(pts.size(),1.0/double(pts.size()));  
   252     double delta,temp,ptc[2];
   254     unsigned int niter=0;
   260       ell->cen[0] = ell->cen[1] = 0.0;
   261       for (i=0; i<pts.size(); i++) {
   262         ell->cen[0] += pts[i][0]*lamda[i];
   263         ell->cen[1] += pts[i][1]*lamda[i];
   267       ell->A[0]=ell->A[1]=ell->A[2]=0.0;
   268       for (i=0;i<pts.size();i++) {
   269         ell->A[0] += pts[i][0] * pts[i][0] * lamda[i];
   270         ell->A[1] += pts[i][0] * pts[i][1] * lamda[i];
   271         ell->A[2] += pts[i][1] * pts[i][1] * lamda[i];
   275       ell->A[0] = ell->A[2];
   277       temp = ell->A[0]*ell->A[2] - ell->A[1]*ell->A[1];
   285       for (i=0; i<pts.size(); i++) {
   287         ptc[0] = pts[i][0] - ell->cen[0];
   288         ptc[1] = pts[i][1] - ell->cen[1];
   289         lamda[i] = ( (ptc[0]*ell->A[0] + ptc[1]*ell->A[1] )*ptc[0] + ( ptc[0]*ell->A[1] + ptc[1]*ell->A[2] )*ptc[1]  )*lamda[i]/2.0;  
   290         delta += ( lamda[i] - temp )*( lamda[i] - temp );
   294     } 
while (delta > 1e-10 && niter < 500);
   301     ellipseAxesAreaFromMatrix(ell);
   306   double Selection::elipsePercentSelected(Chip *selectionChip,
Ellipse *ell) {
   308     unsigned int lines, samples, i,j, 
   310                  ellipsePixelsSelected=0,
   311                  outsideEllipsePixelsSelected=0;
   314     lines = selectionChip->Lines();
   315     samples = selectionChip->Samples();
   319     for (i=1; i<=samples; i++) {
   320       for (j=1; j<=lines; j++) {
   323         if (pointInEllipse(ell, ptc, 0.0)) {  
   325           if (selectionChip->GetValue(i,j) == 1) ellipsePixelsSelected++;  
   329           if (selectionChip->GetValue(i,j) == 1) outsideEllipsePixelsSelected++;  
   338     if (
double(outsideEllipsePixelsSelected)/double(outsideEllipsePixelsSelected+ellipsePixelsSelected) > 0.33) 
return 0;
   341     return double(ellipsePixelsSelected)/double(ellipsePixels)*100.0;  
   345   bool Selection::ellipseFrom5Pts(
Ellipse *ell,
double pts[5][2]) {
   348     svdu[5][0]=svdu[5][1]=svdu[5][2]=svdu[5][3]=svdu[5][4]=svdu[5][5]=0.0;  
   350     double svdv[6][6],cubic[6],discriminant,delta, svdd[6];
   354     gsl_matrix SVDVT,SVDU;
   359     SVDU.data = &svdu[0][0];
   365     SVDVT.data = &svdv[0][0];
   375       svdu[i][3] = pts[i][0];
   376       svdu[i][4] = pts[i][1];
   378       svdu[i][0] = svdu[i][3]*svdu[i][3];
   379       svdu[i][1] = svdu[i][3]*svdu[i][4];
   380       svdu[i][2] = svdu[i][4]*svdu[i][4];
   383     gsl_linalg_SV_decomp_jacobi(&SVDU,&SVDVT,&SVDD);
   386     for (i=0;i<6;i++) cubic[i] = svdv[i][5];
   389     discriminant = cubic[1]*cubic[1]-4*cubic[0]*cubic[2];
   390     delta = (cubic[0]*cubic[2]-cubic[1]*cubic[1]/4.0)*cubic[5] + cubic[1]*cubic[4]*cubic[3]/4.0 - cubic[2]*cubic[3]*cubic[3]/4.0 - cubic[0]*cubic[4]*cubic[4]/4.0;
   392     if( discriminant < 0 && delta < 0) 
   393       return this->ellipseFromCubic(ell,cubic);
   399   bool Selection::ellipseFromCubic(
Ellipse *ell, 
double cubic[6]) {
   402     double discriminant,delta;
   403     discriminant = cubic[1]*cubic[1]-4*cubic[0]*cubic[2];
   404     delta = (cubic[0]*cubic[2]-cubic[1]*cubic[1]/4.0)*cubic[5] + cubic[1]*cubic[4]*cubic[3]/4.0 - cubic[2]*cubic[3]*cubic[3]/4.0 - cubic[0]*cubic[4]*cubic[4]/4.0;
   406     if (discriminant > 0 || delta > 0) 
return false;  
   409     ell->cen[0] = (-cubic[4]*cubic[1]+2*cubic[2]*cubic[3])/(cubic[1]*cubic[1] - 4*cubic[0]*cubic[2]);
   410     ell->cen[1] = (cubic[4] + cubic[1]*ell->cen[0])/(-2*cubic[2]);
   413     ell->A[0] = cubic[0];
   414     ell->A[1] = cubic[1]/2.0;
   415     ell->A[2] = cubic[2];
   418     temp = (ell->A[0]*ell->cen[0]*ell->cen[0] + 2.0*ell->A[1]*ell->cen[0]*ell->cen[1] + ell->A[2]*ell->cen[1]*ell->cen[1] - cubic[5]);
   424     ellipseAxesAreaFromMatrix(ell);
   430   bool Selection::bestFitEllipse(
Ellipse *ell, std::vector < std::vector<int> > *pts,
double play,
unsigned int max_iter) {
   477     double adot[5],bdot[2],mdot,wdot,ata[15],atf[5],dpt[2];  
   479     int iterFlag,i,j,k,l;
   484     while (iterFlag && ni<max_iter) {
   491       for (i=0,l=0; i<int((*pts).size()); i++) {
   492         dpt[0] = (*pts)[i][0];  
   493         dpt[1] = (*pts)[i][1];
   494         if (dpt[0]>150) 
continue;  
   497         bdot[0] = 2*ell->A[0]*dpt[0] + 2*ell->A[1]*dpt[1] + -2.0*(ell->A[0]*ell->cen[0] + ell->A[1]*ell->cen[1]);  
   498         bdot[1] = 2*ell->A[2]*dpt[1] + 2*ell->A[1]*dpt[0] + -2.0*(ell->A[1]*ell->cen[0] + ell->A[2]*ell->cen[1]);  
   500         mdot = 1.0 / (bdot[0]*bdot[0] + bdot[1]*bdot[1]); 
   502         wdot = -(     ell->A[0]*dpt[0]*dpt[0] + 
   503                   2.0*ell->A[1]*dpt[0]*dpt[1] + 
   504                       ell->A[2]*dpt[1]*dpt[1] + 
   505                 -2.0*(ell->A[0]*ell->cen[0] + ell->A[1]*ell->cen[1])*dpt[0] + 
   506                 -2.0*(ell->A[1]*ell->cen[0] + ell->A[2]*ell->cen[1])*dpt[1] +
   507                      (ell->A[0]*ell->cen[0]*ell->cen[0] + 2.0*ell->A[1]*ell->cen[0]*ell->cen[1] + ell->A[2]*ell->cen[1]*ell->cen[1] -1.0) );  
   509         if (fabs(wdot*sqrt(mdot)) > play) 
continue; 
   513         adot[0] = dpt[0]*dpt[0] + -2.0*ell->cen[0]*dpt[0] + ell->cen[0]*ell->cen[0];          
   514         adot[1] = 2.0*dpt[0]*dpt[1] - 2.0*ell->cen[1]*dpt[0] -2.0*ell->cen[0]*dpt[1] + 2.0*ell->cen[0]*ell->cen[1];  
   515         adot[2] = dpt[1]*dpt[1] + -2.0*ell->cen[1]*dpt[1] + ell->cen[1]*ell->cen[1];          
   522             ata[isymp(j,k)] += adot[j]*mdot*adot[k];  
   526           atf[j] += mdot*adot[j]*wdot;                
   529       if (l<5)
return false;
   532       if (choleski_solve(ata,atf,5,2) != 1) 
return false;  
   539       ell->cen[0]  += atf[3];
   540       ell->cen[1]  += atf[4];
   544         if (fabs(atf[i]) > 0.001) {
   557       if (atf[i] != atf[i]) 
return false;  
   563     return ellipseAxesAreaFromMatrix(ell);  
   567   void Selection::selectionEdge(Chip *selectionChip, std::vector < std::vector <int> > *pts) {
   572     std::vector <int> pt(2);
   573     int i,j,k,l,nUS,lines,samples;
   575     samples = selectionChip->Samples();
   576     lines   = selectionChip->Lines();
   577     for (i=2;i<samples;i++) {
   578       for (j=2;j<lines;j++) {
   580         for (k=i-1,nUS=0;k<=i+1;k++)
   581           for (l=j-1;l<=j+1;l++)
   582             if (selectionChip->GetValue(k,l) == 0 && k != l) nUS++;
   584         if (nUS > 0 && selectionChip->GetValue(i,j) == 1) {   
   587           (*pts).push_back(pt);
   595   bool Selection::ellipseAxesAreaFromMatrix(
Ellipse *ell) {
   601     temp = ell->A[0]*ell->A[2] - ell->A[1]*ell->A[1];
   603     Ai[0] =  ell->A[2]/temp;
   604     Ai[1] = -ell->A[1]/temp;
   605     Ai[2] =  ell->A[0]/temp;
   609     temp = -(Ai[0] + Ai[2]);
   610     temp = -0.5*(temp + ((temp>=0) - (temp<0))*sqrt(temp*temp - 4.0*(Ai[0]*Ai[2]-Ai[1]*Ai[1])));
   612     ell->semiMajor = temp;  
   613     ell->semiMinor = (Ai[0]*Ai[2]-Ai[1]*Ai[1])/temp;
   615     if (ell->semiMajor < 0 || ell->semiMinor < 0) 
return false;  
   617     if (ell->semiMajor < ell->semiMinor) {  
   618       temp= ell->semiMajor;
   619       ell->semiMajor = ell->semiMinor;
   620       ell->semiMinor = temp;
   628     temp = atan2(Ai[0]-ell->semiMajor,-Ai[1]);
   629     ell->majorAxis[0] = cos(temp);
   630     ell->majorAxis[1] = sin(temp);
   632     temp = atan2(Ai[0]-ell->semiMinor, -Ai[1]);
   633     ell->minorAxis[0] = cos(temp);
   634     ell->minorAxis[1] = sin(temp);
   636     ell->semiMajor = sqrt(ell->semiMajor);  
   637     ell->semiMinor = sqrt(ell->semiMinor);
   640     ell->area = ell->semiMajor*ell->semiMinor*acos(-1.0);
   646   bool Selection::ellipseInChip(
Ellipse *ell, Chip *chip) {
   649     double pt[4][2],vec[2],temp;
   653     samples = chip->Samples();
   654     lines   = chip->Lines();
   656     if (ell->cen[0] < 1 || ell->cen[0] > samples || ell->cen[1] < 1 || ell->cen[1] > lines) 
return false;
   659     pt[0][0] = 1-ell->cen[0];
   660     pt[0][1] = 1-ell->cen[1];
   662     pt[1][0] = 1-ell->cen[0];
   663     pt[1][1] = double(lines)-ell->cen[1];
   665     pt[2][0] = double(samples)-ell->cen[0];
   666     pt[2][1] = double(lines)-ell->cen[1];
   668     pt[3][0] = double(samples)-ell->cen[0];
   669     pt[3][1] = 1-ell->cen[1];
   678     pt[0][0] =  ell->majorAxis[0] * temp + ell->majorAxis[1] * pt[0][1];
   679     pt[0][1] = -ell->majorAxis[1] * temp + ell->majorAxis[0] * pt[0][1];
   681     pt[1][0] =  ell->majorAxis[0] * temp + ell->majorAxis[1] * pt[1][1];
   682     pt[1][1] = -ell->majorAxis[1] * temp + ell->majorAxis[0] * pt[1][1];
   685     pt[2][0] =  ell->majorAxis[0] * temp + ell->majorAxis[1] * pt[2][1];
   686     pt[2][1] = -ell->majorAxis[1] * temp + ell->majorAxis[0] * pt[2][1];
   689     pt[3][0] =  ell->majorAxis[0] * temp + ell->majorAxis[1] * pt[3][1];
   690     pt[3][1] = -ell->majorAxis[1] * temp + ell->majorAxis[0] * pt[3][1];
   694       pt[i][0] /= ell->semiMajor;
   695       pt[i][1] /= ell->semiMinor;
   700     vec[0] = pt[1][0] - pt[0][0];
   701     vec[1] = pt[1][1] - pt[0][1];
   702     temp = sqrt(vec[0]*vec[0] + vec[1]*vec[1]);
   706     temp = fabs(vec[0]*pt[0][1] - vec[1]*pt[0][0]);  
   707     if (temp < 1.0) 
return false;
   710     vec[0] = pt[2][0] - pt[1][0];
   711     vec[1] = pt[2][1] - pt[1][1];
   712     temp = sqrt(vec[0]*vec[0] + vec[1]*vec[1]);
   716     temp = fabs(vec[0]*pt[1][1] - vec[1]*pt[1][0]);  
   718     if (temp < 1.0) 
return false;
   721     vec[0] = pt[3][0] - pt[2][0];  
   722     vec[1] = pt[3][1] - pt[2][1];
   723     temp = sqrt(vec[0]*vec[0] + vec[1]*vec[1]);
   727     temp = fabs(vec[0]*pt[2][1] - vec[1]*pt[2][0]);  
   729     if (temp < 1.0) 
return false;
   732     vec[0] = pt[0][0] - pt[3][0];
   733     vec[1] = pt[0][1] - pt[3][1];
   734     temp = sqrt(vec[0]*vec[0] + vec[1]*vec[1]);
   738     temp = fabs(vec[0]*pt[3][1] - vec[1]*pt[3][0]);  
   739     if (temp < 1.0) 
return false;
   744   bool Selection::pointInEllipse(
Ellipse *ell, 
double pt[2], 
double play) {
   748     double bdot[2],mdot,wdot;
   750     bdot[0] = 2*ell->A[0]*pt[0] + 2*ell->A[1]*pt[1] + -2.0*(ell->A[0]*ell->cen[0] + ell->A[1]*ell->cen[1]);
   751     bdot[1] = 2*ell->A[2]*pt[1] + 2*ell->A[1]*pt[0] + -2.0*(ell->A[1]*ell->cen[0] + ell->A[2]*ell->cen[1]);
   752     mdot = 1.0 / (bdot[0]*bdot[0] + bdot[1]*bdot[1]); 
   754     wdot = (       ell->A[0]*pt[0]*pt[0] + 
   755                2.0*ell->A[1]*pt[0]*pt[1] + 
   756                    ell->A[2]*pt[1]*pt[1] + 
   757              -2.0*(ell->A[0]*ell->cen[0] + ell->A[1]*ell->cen[1])*pt[0] + 
   758              -2.0*(ell->A[1]*ell->cen[0] + ell->A[2]*ell->cen[1])*pt[1] +
   759                   (ell->A[0]*ell->cen[0]*ell->cen[0] + 2.0*ell->A[1]*ell->cen[0]*ell->cen[1] + ell->A[2]*ell->cen[1]*ell->cen[1] -1.0) );
   761     if (wdot*sqrt(mdot) > play) 
return false;  
   767   bool Selection::ellipseFromCenterAxesAngle(
Ellipse *ell, 
double centerSample, 
double centerLine, 
double semiMajor, 
double semiMinor, 
double theta) {
   778     if (semiMajor < semiMinor) 
return false;
   782     ell->semiMajor = semiMajor;
   783     ell->semiMinor = semiMinor;
   784     ell->majorAxis[0] = cos(theta);
   785     ell->majorAxis[1] = sin(theta);
   786     ell->minorAxis[0] = -ell->majorAxis[1];
   787     ell->minorAxis[1] = -ell->majorAxis[0];
   788     ell->cen[0] = centerSample;
   789     ell->cen[1] = centerLine;
   791     Ai[0] = ell->majorAxis[0]*ell->majorAxis[0]*ell->semiMajor*ell->semiMajor + ell->majorAxis[1]*ell->majorAxis[1]*ell->semiMinor*ell->semiMinor;
   792     Ai[2] = ell->majorAxis[1]*ell->majorAxis[1]*ell->semiMajor*ell->semiMajor + ell->majorAxis[0]*ell->majorAxis[0]*ell->semiMinor*ell->semiMinor;
   794     Ai[1] = ell->majorAxis[0]*ell->majorAxis[1]*(ell->semiMajor*ell->semiMajor - ell->semiMinor*ell->semiMinor);
   796     temp = Ai[0]*Ai[2] + Ai[1]*Ai[1];
   798     ell->A[0] =  Ai[2]/temp;
   799     ell->A[1] = -Ai[1]/temp;
   800     ell->A[2] =  Ai[0]/temp;
   802     ell->area = semiMajor*semiMinor*acos(-1.0);
 
Namespace for the standard library. 
 
Namespace for ISIS/Bullet specific routines.