stdalgorithm.cpp

Go to the documentation of this file.
00001 #include "stdalgorithm.hpp"
00002 #include "kube-gustavson-fft.hpp"
00003 #include <fstream>
00004 #include <iostream>
00005 #include <cmath>
00006 
00007 using namespace std;
00008 
00009 const int Parabelzentrum::order=5;
00010 // Anzahl Koeffizienten = 5
00011 
00012 Parabelzentrum::Parabelzentrum(const bildfloat& bild_, int pktmax_) : 
00013  bild(bild_), pktmax(pktmax_), xmax(1), ymax(1), xmin(1), ymin(1) {
00014   reserve_2D(R, order, pktmax);
00015   f=new double[pktmax];
00016   koeff=new double[order];
00017   errors=new double[order];
00018   rel_errors=new double[order];
00019   pktzahl=0;
00020   x_estimate=0.0;
00021   y_estimate=0.0;
00022 }  
00023 
00024 Parabelzentrum::~Parabelzentrum() {
00025   delete_2D(R);
00026   delete[] f;
00027   delete[] koeff;
00028   delete[] errors;
00029   delete[] rel_errors;
00030 }  
00031 
00032 void Parabelzentrum::estimate(double x, double y) {
00033   if (pktzahl>0) STHROW("Error: Can set estimate only if there are no points");
00034   x_estimate=x;
00035   y_estimate=y;
00036 }  
00037 
00038 void Parabelzentrum::operator () (int x, int y) {
00039   if (pktzahl==pktmax) STHROW("Mist -- zuwenig Platz für die Punkte");
00040   
00041   // rechte Seite
00042   f[pktzahl]=bild(y,x);
00043   
00044   
00045   // Schätzwerte für x und y abziehen
00046   // für alle weiteren Werte
00047   double xn=x-x_estimate;
00048   double yn=y-y_estimate;
00049   R[pktzahl][0]=1.0;
00050   R[pktzahl][1]=xn;
00051   R[pktzahl][2]=yn;
00052   R[pktzahl][3]=xn*xn;
00053   R[pktzahl][4]=yn*yn;
00054   pktzahl++;
00055   xmax.put(xn);
00056   xmin.put(xn);
00057   ymax.put(yn);
00058   ymin.put(yn);
00059 }
00060 
00061 void Parabelzentrum::clear() {
00062   pktzahl=0;
00063   xmax.clear();
00064   xmin.clear();
00065   ymax.clear();
00066   ymin.clear();
00067   x_cent=0.0;
00068   y_cent=0.0;
00069   x_estimate=0.0;
00070   y_estimate=0.0;
00071 
00072 }  
00073 
00074 bool  Parabelzentrum::fit() {
00075   x_cent=0; y_cent=0;
00076   for (int i=0; i<pktzahl; i++) {
00077     x_cent+=R[i][1];
00078     y_cent+=R[i][2];
00079   }
00080   x_cent/=pktzahl;
00081   y_cent/=pktzahl;
00082   /* Berechne den Schwerpunkt der Punkte als Notlösung,
00083      falls der Fit versagt */
00084   // Fehler dazu als Fehler des Mittelwerts
00085   s_xcent=0; s_ycent=0;
00086   for (int i=0; i<pktzahl; i++) {
00087     s_xcent+=SQR(R[i][1]-x_cent);
00088     s_ycent+=SQR(R[i][2]-y_cent);
00089   }
00090   s_xcent/=pktzahl;
00091   s_ycent/=pktzahl;
00092 
00093   if (pktzahl==0) {
00094     std::cerr<<"Fit ohne Punkte !"<<std::endl;
00095     return false; //nix machen
00096   }  
00097 
00098   if (pktzahl < 2*order) {
00099     std::cerr<<"Sehr wenig Punkte !"<<std::endl;
00100     return true; /* Schwerpunkt zählt */
00101   }  
00102   // Gleichungssystem unterbestimmt bzw. schwach definiert 
00103   
00104   double *d=new double[order];
00105   // Löse das Fitproblem mit QR
00106   // || R x - f || minimal für x
00107 
00108   if(QR(pktzahl, order, R, d, f, 1e-10))  {
00109       std::cerr<<"Matrix singulär ????"<<std::endl;
00110      // Fitmatrix war singulär -- darf eigentlich nicht sein
00111      // Nimm Schwerpunkt
00112      return false;
00113   }
00114   
00115   // Jetzt löse nach den Koeffizienten auf
00116   rdsolve(order, R, d, f, koeff);
00117   double x=-koeff[1]/(2*koeff[3]);
00118   double y=-koeff[2]/(2*koeff[4]);
00119 
00120   // Berechne die statistischen Fehler der Koeffizenten
00121   compute_errors(order, pktzahl, R, d, f, errors);
00122   for (int o=0; o<order; o++)
00123     rel_errors[o]=errors[o]/koeff[o];
00124     
00125   /* Parabel falschherum gekrümmt -- das ist kein Peak ! 
00126 
00127   if ((koeff[3]<=0) || (koeff[4]<=0)) {
00128     std::cerr<<"Parabel falschherum"<<std::endl;
00129     return false;
00130   }  */
00131   
00132   /* Wenn der Parabelmittelpunkt außerhalb der Punkte liegt, nimm Schwerpunkt */
00133   if ((x>xmax()) || (x<xmin()) || (y>ymax()) || (y<ymin()))  {
00134     std::cerr<<"Danebengeschossen !"<<std::endl;
00135     return true;
00136   }  
00137 
00138   /* Endgültig Fit-Werte akzeptieren */
00139   x_cent=x;
00140   y_cent=y;
00141 
00142   
00143   // Fehler berechnen
00144   s_xcent=x_cent*sqrt(SQR(rel_errors[1]) + SQR (rel_errors[3]));
00145   s_ycent=y_cent*sqrt(SQR(rel_errors[2]) + SQR (rel_errors[4]));
00146 
00147   return true;
00148   delete[] d;
00149 }  
00150 
00151 bildcomplex::bildcomplex(const bildfloat &realvalue) :
00152  bildcomplex_base() 
00153 { MAP(realvalue) {
00154     (*this)(y,x).re=realvalue(y,x);
00155     (*this)(y,x).im=0.0;
00156   }  
00157 }    
00158 
00159 bildcomplex::bildcomplex(const bildfloat& real, const bildfloat& imag) :
00160  bildcomplex_base() 
00161 { MAP(real) {
00162     (*this)(y,x).re=real(y,x);
00163     (*this)(y,x).im=imag(y,x);
00164   }  
00165 }    
00166 
00167 void bildcomplex::decompose(bildfloat&real, bildfloat& imag) 
00168 {
00169   MAP((*this)) {
00170     real(y,x)=(*this)(y,x).re;
00171     imag(y,x)=(*this)(y,x).im;
00172   }
00173 
00174 }
00175 
00176 
00177 bildcomplex& bildcomplex::FFT_forward() {
00178   forward_fft2f(bild[0], SIZEY, SIZEX);
00179   return *this;
00180 }
00181 
00182 
00183 bildcomplex& bildcomplex::FFT_backward() {
00184   inverse_fft2f(bild[0], SIZEY, SIZEX);
00185   return *this;
00186 }
00187 
00188 bildfloat& bildcomplex::norm(bildfloat &ret) {
00189   MAP (ret) {
00190     ret(y,x)=SQR((*this)(y,x).re)+SQR((*this)(y,x).im);
00191   }
00192   return ret;
00193 }
00194 
00195 bildcomplex& bildcomplex::Hamming_window(float width, float xm, float ym) {
00196   
00197   MAP((*this)) {        
00198    float xs=x-xm;
00199    float ys=y-ym;
00200    if (SQR(xs)+SQR(ys) < SQR(width))
00201      (*this)(y,x)*=SQR(0.54+0.46*cos(M_PI*sqrt(SQR(xs)+SQR(ys))/width))*2.36961606240022;
00202    else 
00203      (*this)(y,x)=0.0; 
00204   } 
00205   return *this;
00206 }
00207 
00208 bildcomplex& bildcomplex::Hamming_unwindow(float width, float xm, float ym) {
00209   
00210   MAP((*this)) {        
00211    float xs=x-xm;
00212    float ys=y-ym;
00213    if (SQR(xs)+SQR(ys) < SQR(width))
00214      (*this)(y,x)/=SQR(0.54+0.46*cos(M_PI*sqrt(SQR(xs)+SQR(ys))/width))*2.36961606240022;
00215    else 
00216      (*this)(y,x)=0.0; 
00217   } 
00218   return *this;
00219 }
00220 
00221 /*
00222  * Copyright notice to pnpoly, interior point testing of a polygon
00223  *
00224  *   Copyright (c) 1970-2003, Wm. Randolph Franklin
00225  * 
00226  * Permission is hereby granted, free of charge, to any person obtaining a copy of
00227  * this software and associated documentation files (the "Software"), to deal in
00228  * the Software without restriction, including without limitation the rights to
00229  * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
00230  * of the Software, and to permit persons to whom the Software is furnished to do
00231  * so, subject to the following conditions:
00232  * 
00233  *    1. Redistributions of source code must retain the above copyright notice,
00234  *    this list of conditions and the following disclaimers.  2. Redistributions
00235  *    in binary form must reproduce the above copyright notice in the
00236  *    documentation and/or other materials provided with the distribution.  3. The
00237  *    name of W. Randolph Franklin may not be used to endorse or promote products
00238  *    derived from this Software without specific prior written permission. 
00239  * 
00240  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00241  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00242  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
00243  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
00244  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
00245  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
00246  * SOFTWARE. 
00247  */
00248 
00249 bool pnpoly(int npol, float *xp, float *yp, float x, float y)
00250     {
00251       int i, j;
00252       bool c = false;
00253       for (i = 0, j = npol-1; i < npol; j = i++) {
00254         if ((((yp[i]<=y) && (y<yp[j])) ||
00255              ((yp[j]<=y) && (y<yp[i]))) &&
00256             (x < (xp[j] - xp[i]) * (y - yp[i]) / (yp[j] - yp[i]) + xp[i]))
00257 
00258           c = !c;
00259       }
00260       return c;
00261     }
00262 
00263 
00264 
00265 Voronoischnitt::Voronoischnitt(bildfloat &bfl, float xmitte_, float ymitte_, const char *vorofile) :
00266   rb(bfl), xmitte(xmitte_), ymitte(ymitte_), r(0,0) 
00267 {
00268   ifstream vf(vorofile);
00269   vector<Point> centerpoints;
00270   vector<cell> zellen;
00271   if (!vf) STHROW("Voronoidata "<<vorofile<<" not found"); 
00272           
00273   while (vf) {
00274     // lese Voronoi-Daten ein
00275     float x; float y; int anzahl;
00276     vf >>x; vf >>y; vf>>anzahl;
00277     
00278     int cellindex=centerpoints.size();
00279     centerpoints.push_back(make_pair(x,y));
00280     
00281     // Zentrum der Voronoi-Zelle
00282     zellen.resize(cellindex+1);
00283     for (int i=0; i<anzahl; i++) {
00284       vf >> x; vf >>y; 
00285       zellen[cellindex].push_back(make_pair(x,y));
00286     }
00287   }  
00288   vf.close();
00289   
00290   if (zellen.size()<2) STHROW("Could not read Voronoi data "<<vorofile);
00291   // suche die nächste Zelle
00292   int ind=0;
00293   float mindist=SQR(centerpoints[0].first-xmitte)+SQR(centerpoints[0].second-ymitte);
00294   for (size_t i=1; i<centerpoints.size(); i++) {
00295     float dist=SQR(centerpoints[i].first-xmitte)+SQR(centerpoints[i].second-ymitte);
00296     if (dist<mindist) {
00297       mindist=dist;
00298       ind=i;
00299     }
00300   }
00301   // Punkt nr. ind ist am nächsten
00302   cerr<<ind<<endl;
00303   zelle=zellen[ind];
00304   // cerr<<"Ende\n"<<flush;
00305   stddev=0;
00306   // Speichere Polygonecken in C-Array für pnpoly
00307   npol=zelle.size()+1;
00308   xp=new float[npol];
00309   yp=new float[npol];
00310   for (int i=0; i<npol-1; i++) {
00311     xp[i]=zelle[i].first;
00312     yp[i]=zelle[i].second;
00313   }
00314   xp[npol-1]=xp[0];
00315   yp[npol-1]=yp[0];
00316   // schließen
00317   
00318 }
00319 
00320 Voronoischnitt::~Voronoischnitt() {
00321   delete [] xp;
00322   delete [] yp;
00323 }
00324 
00325 void Voronoischnitt::compute_schnitt(int nr) {
00326   // Suche die längste Diagonale
00327   int anzahl=zelle.size();
00328   if (anzahl!=6) cerr<<"Warnung: Zelle hat nicht 6 Ecken, sondern "<<anzahl<<endl;
00329   int ind=0;
00330   maxdist=mindist=SQR(zelle[0].first-zelle[3].first)+SQR(zelle[0].second-zelle[3].second);
00331   for (int shift=1; shift < anzahl; shift++) {
00332     float aktdist=SQR(zelle[shift%anzahl].first-zelle[(shift+3)%anzahl].first)+
00333                   SQR(zelle[shift%anzahl].second-zelle[(shift+3)%anzahl].second);
00334     if (aktdist>maxdist) {
00335        maxdist=aktdist;
00336        ind=shift;
00337     }
00338     if (aktdist<mindist) mindist=aktdist;
00339   }
00340   
00341   mindist=sqrt(mindist);
00342   maxdist=sqrt(maxdist);
00343   
00344   cerr<<".c create line "<<zelle[ind%anzahl].first<<" "<<zelle[ind%anzahl].second<<" "<<
00345          zelle[(ind+3)%anzahl].first<<" "<<zelle[(ind+3)%anzahl].second<<endl;
00346 
00347   // Berechne "Ausgleichsgerade", die durch das Zentrum geht und den Winkel gleichmäßig verteilt
00348   vec2d M(xmitte, ymitte);
00349   vec2d P1(zelle[ind%anzahl].first, zelle[ind%anzahl].second);
00350   vec2d P2(zelle[(ind+3)%anzahl].first, zelle[(ind+3)%anzahl].second);
00351 
00352   vec2d v1=P1-M;
00353   vec2d v2=P2-M;
00354   
00355   r=v1/abs(v1)-v2/abs(v2);
00356   
00357   int stepstart, stepend;
00358   
00359   // r ist Richtungsvektor der gesuchten Geraden
00360   cerr<<"Richtungsvektor "<<r.x<<", "<<r.y<<endl;
00361   if (abs(r.x) >abs(r.y)) {
00362     r/=r.x;
00363     // stepstart=(r*1.0/abs(r))*((P1-M)*r).x;
00364     if (P1.x < P2.x) {
00365       stepstart=int(-abs(v1.x)); stepend=int(abs(v2.x));
00366     } else {
00367       stepstart=int(-abs(v2.x)); stepend=int(abs(v1.x));
00368     }  
00369   } else {
00370     r/=r.y;
00371     if (P1.y < P2.y) {
00372       stepstart=int(-abs(v1.y)); stepend=int(abs(v2.y));
00373     } else {
00374       stepstart=int(-abs(v2.y)); stepend=int(abs(v1.y));
00375     } 
00376   }
00377 
00378   // Normierung, so dass immer ein Schritt entlang x oder y gemacht wird 
00379 
00380   for (int step=stepstart; step<=stepend; step++) {
00381     int xpunkt= int(floor(r.x*step+M.x+0.5));
00382     int ypunkt= int(floor(r.y*step+M.y+0.5));
00383     // Genaue Stachelmitte ist mit Subpixelgenauigkeit in xmitte, ymitte
00384     // Berechne Punkte als Abstand dazu, Richtung aus Projektion auf r
00385     vec2d distvec(xpunkt-xmitte, ypunkt-ymitte);
00386     double dist=abs(distvec);
00387     if (r*distvec < 0) dist*=-1;
00388     
00389     cout<<nr<<"\t"<<dist<<"\t"<<rb(ypunkt, xpunkt)<<endl;
00390   } 
00391   cout<<endl;
00392          
00393 }  
00394 
00395 vec2d Voronoischnitt::direction() {
00396   return r;
00397 }  
00398 
00399 
00400 float Voronoischnitt::boundary_average() 
00401 {
00402   int anzahl=zelle.size();
00403   if (anzahl!=6) cerr<<"Warnung: Zelle hat nicht 6 Ecken, sondern "<<anzahl<<endl;
00404   
00405   mean_avg avg(rb);
00406   for (int i=0; i<anzahl; i++) {
00407     /*vec2d P1(zelle[i].first, zelle[i].second);
00408     vec2d P2(zelle[(i+1)%anzahl].first, zelle[(i+1)%anzahl].second);
00409     line_iterate(P1, P2, avg); */
00410     avg(int(floor(zelle[i].first+0.5)), int(floor(zelle[i].second+0.5)));
00411   }
00412 
00413   double height=avg.sum/avg.pktzahl;
00414   stddev=sqrt((avg.sqrsum/avg.pktzahl) - SQR(height));
00415   cerr<<"Mittlere Höhe am Rand: "<<height<<" +/- "<<stddev<<endl;
00416   return avg.sum/avg.pktzahl;
00417 }  
00418 
00419 
00420 bool Voronoischnitt::contains(float x, float y) {
00421   return pnpoly(npol, xp, yp, x, y);
00422 }  
00423 
00424 

Generated on Fri Jul 24 12:49:17 2009 for Xgrayimg Library by  doxygen 1.5.5