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.