zsig 1.0.0

include/zpolbasist.hh

Go to the documentation of this file.
00001 
00008 #ifndef ZSIG_ZPOLBASIST_HH
00009 #define ZSIG_ZPOLBASIST_HH
00010 
00011 //== INCLUDES =================================================================
00012 
00013 #include <cmath>
00014 #include <vector>
00015 #include <complex>
00016 #include <iostream>
00017 
00018 //== NAMESPACES ===============================================================
00019 
00020 namespace zsig {
00021 
00022 //=== IMPLEMENTATION ==========================================================
00023 
00032 template< class T >
00033 T fac( const int& _n ) {
00034         T f = (T)1;
00035         for (int i = 2; i <= _n; ++i) f *= i;
00036         return f;
00037 }
00038 
00060 template< class T >
00061 T compute_R( const unsigned& _p,
00062              const int& _q,
00063              const T& _r ) {
00064 
00065         int a, b, c, d;
00066         T sum = (T)0;
00067 
00068         for (int k = (_q<0?-_q:_q); k <= _p; k += 2) {
00069 
00070                 a = (_p - k) / 2; b = (_p + k) / 2;
00071                 c = (k - _q) / 2; d = (k + _q) / 2;
00072 
00073                 sum += ( ( pow( (T)-1.0, (T)a ) * fac<T>(b) ) /
00074                          ( fac<T>(a) * fac<T>(c) * fac<T>(d) ) ) * pow( _r, (T)k );
00075 
00076         }
00077 
00078         return sum;
00079 
00080 }
00081 
00101 template< class T >
00102 std::complex< T > compute_V( const unsigned& _p,
00103                              const int& _q,
00104                              const T& _r,
00105                              const T& _t ) {
00106 
00107         return std::polar( compute_R<T>( _p, _q, _r), _q * _t );
00108 
00109 }
00110 
00111 //== CLASS DEFINITION =========================================================
00112 
00162 template< unsigned Order = 8, class T = long double >
00163 class ZernikePolynomialsBasisT {
00164 
00165 public:
00166 
00167         typedef ZernikePolynomialsBasisT< Order, T > zpolbasis_type; 
00168         typedef std::complex< T > value_type; 
00169         typedef std::vector< value_type > radial_polynomial; 
00170 
00177         ZernikePolynomialsBasisT() : pol(Order+1) {
00178                 for (unsigned p = 0; p <= Order; ++p) pol[p].resize( 1+p/2 );
00179         }
00180 
00211         void project( const T **_fxy,
00212                       const zpolbasis_type **_zpb,
00213                       const unsigned int& _szx,
00214                       const unsigned int& _szy ) {
00215                 T x, y, r; // (x, y) cartesian coordinates and radius r
00216                 for (unsigned p = 0; p <= Order; ++p) {
00217                         T p1pi = (p + 1) / M_PI; // frac outside summation
00218                         for (int qi = 0; qi <= p/2; ++qi) {
00219                                 pol[p][qi] = value_type();
00220                                 for (int gx = 0; gx < _szx; ++gx) {
00221                                         x = ( (T)2 * gx + (T)1 ) / (T)_szx - (T)1;
00222                                         for (int gy = 0; gy < _szy; ++gy) {
00223                                                 y = ( (T)2 * gy + (T)1 ) / (T)_szy - (T)1;
00224                                                 r = (T)sqrt( x*x + y*y );
00225                                                 if( r > (T)1 ) continue; // outside unit circle is zero
00226                                                 pol[p][qi] += std::conj( _zpb[gx][gy][p][qi] ) * _fxy[gx][gy];
00227                                         } // gy
00228                                 } // gx
00229                                 pol[p][qi] *= p1pi;
00230                         } // qi
00231                 } // p
00232         }
00233 
00241         void project( const T **_fxy,
00242                       zpolbasis_type **_zpb,
00243                       const unsigned int& _szx,
00244                       const unsigned int& _szy ) {
00245                 project( _fxy, (const zpolbasis_type **)_zpb, _szx, _szy );
00246         }
00247 
00255         void project( T **_fxy,
00256                       const zpolbasis_type **_zpb,
00257                       const unsigned int& _szx,
00258                       const unsigned int& _szy ) {
00259                 project( (const T **)_fxy, (const zpolbasis_type **)_zpb, _szx, _szy );
00260         }
00261 
00269         void project( T **_fxy,
00270                       zpolbasis_type **_zpb,
00271                       const unsigned int& _szx,
00272                       const unsigned int& _szy ) {
00273                 project( (const T **)_fxy, (const zpolbasis_type **)_zpb, _szx, _szy );
00274         }
00275 
00287         void project( const T **_fxy,
00288                       const unsigned int& _szx,
00289                       const unsigned int& _szy ) {
00290                 T x, y, r, t; // (x, y) cartesian and (r, t) polar coordinates
00291                 for (unsigned p = 0; p <= Order; ++p) {
00292                         T p1pi = (p + 1) / M_PI; // frac outside summation
00293                         int qi = 0; // q index: q[0, 2, 4] -> qi[0, 1, 2]
00294                         for (int q = p % 2; q <= p; q += 2, qi++) {
00295                                 pol[p][qi] = value_type();
00296                                 for (int gx = 0; gx < _szx; ++gx) {
00297                                         x = ( (T)2 * gx + (T)1 ) / (T)_szx - (T)1;
00298                                         for (int gy = 0; gy < _szy; ++gy) {
00299                                                 y = ( (T)2 * gy + (T)1 ) / (T)_szy - (T)1;
00300                                                 r = (T)sqrt( x*x + y*y );
00301                                                 if( r > (T)1 ) continue; // outside unit circle is zero
00302                                                 t = (T)atan2( y, x );
00303                                                 pol[p][qi] += std::conj( compute_V(p, q, r, t) ) * _fxy[gx][gy];
00304                                         } // gy
00305                                 } // gx
00306                                 pol[p][qi] *= p1pi;
00307                         } // q
00308                 } // p
00309         }
00310 
00317         void project( T **_fxy,
00318                       const unsigned int& _szx,
00319                       const unsigned int& _szy ) {
00320                 project( (const T **)_fxy, _szx, _szy );
00321         }
00322 
00336         void reconstruct( T **_fxy,
00337                           const zpolbasis_type **_zpb,
00338                           const unsigned int& _szx,
00339                           const unsigned int& _szy ) const {
00340                 value_type rv; // reconstructed value
00341                 for (int gx = 0; gx < _szx; ++gx) {
00342                         for (int gy = 0; gy < _szy; ++gy) {
00343                                 rv = value_type();
00344                                 for (unsigned p = 0; p <= Order; ++p) {
00345                                         for (int qi = 0; qi <= p/2; ++qi) {
00346                                                 rv += pol[p][qi] * _zpb[gx][gy][p][qi]; // using +q
00347                                                 if( p % 2 != 0 or qi != 0 ) // for p even and q zero z does not repeat itself
00348                                                         rv += std::conj( pol[p][qi] ) * std::conj( _zpb[gx][gy][p][qi] ); // using -q
00349                                         } // qi
00350                                 } // p
00351                                 _fxy[gx][gy] = rv.real();
00352                         } // gy
00353                 } // gx
00354         }
00355 
00363         void reconstruct( T **_fxy,
00364                           zpolbasis_type **_zpb,
00365                           const unsigned int& _szx,
00366                           const unsigned int& _szy ) const {
00367                 reconstruct( _fxy, (const zpolbasis_type **)_zpb, _szx, _szy );
00368         }
00369 
00380         void reconstruct( T **_fxy,
00381                           const unsigned int& _szx,
00382                           const unsigned int& _szy ) const {
00383                 T x, y, r, t; // (x, y) cartesian and (r, t) polar coordinates
00384                 value_type rv, zpV; // reconstructed value and Zernike Polynomial V
00385                 for (int gx = 0; gx < _szx; ++gx) {
00386                         x = ( (T)2 * gx + (T)1 ) / (T)_szx - (T)1;
00387                         for (int gy = 0; gy < _szy; ++gy) {
00388                                 y = ( (T)2 * gy + (T)1 ) / (T)_szy - (T)1;
00389                                 r = (T)sqrt( x*x + y*y );
00390                                 rv = value_type();
00391                                 if( r <= (T)1 ) { // reconstruct inside unit circle only
00392                                         for (unsigned p = 0; p <= Order; ++p) {
00393                                                 int qi = 0; // q index: q[0, 2, 4] -> qi[0, 1, 2]
00394                                                 for (int q = p % 2; q <= p; q += 2, qi++) {
00395                                                         t = (T)atan2( y, x );
00396                                                         zpV = compute_V(p, q, r, t);
00397                                                         rv += pol[p][qi] * zpV; // using +q
00398                                                         if( p % 2 != 0 or qi != 0 ) // for p even and q zero z does not repeat itself
00399                                                                 rv += std::conj( pol[p][qi] ) * std::conj( zpV ); // using -q
00400                                                 } // q
00401                                         } // p
00402                                 } // if
00403                                 _fxy[gx][gy] = rv.real();
00404                         } // gy
00405                 } // gx
00406         }
00407 
00419         T compare( const zpolbasis_type& _zp ) const {
00420                 T dist = (T)0; // distance
00421                 T modz[2]; // modulus of z
00422                 for (unsigned p = 0; p <= Order; ++p) {
00423                         for (unsigned qi = 0; qi <= p/2; ++qi) {
00424                                 modz[0] = std::abs( pol[p][qi] );
00425                                 modz[1] = std::abs( _zp[p][qi] );
00426                                 dist += (modz[0] - modz[1] ) * (modz[0] - modz[1] );
00427                         } // qi
00428                 } // p
00429                 return sqrt( dist );
00430         }
00431 
00437         radial_polynomial& operator[] ( const unsigned& _p ) { return this->pol[_p]; }
00438 
00444         const radial_polynomial& operator[] ( const unsigned& _p ) const { return this->pol[_p]; }
00445 
00452         friend std::ostream& operator << ( std::ostream& _out,
00453                                            const zpolbasis_type& _z ) {
00454                 for (unsigned p = 0; p <= Order; ++p) {
00455                         _out << _z[p][0];
00456                         for (unsigned qi = 1; qi <= p/2; ++qi)
00457                                 _out << " " << _z[p][qi];
00458                         if( p < Order ) _out << "\n";
00459                 }
00460                 return _out;
00461         }
00462 
00469         friend std::istream& operator >> ( std::istream& _in,
00470                                            zpolbasis_type& _z ) {
00471                 for (unsigned p = 0; p <= Order; ++p)
00472                         for (unsigned qi = 0; qi <= p/2; ++qi)
00473                                 _in >> _z[p][qi];
00474                 return _in;
00475         }
00476 
00477 private:
00478 
00479         std::vector< radial_polynomial > pol; 
00480 
00481 };
00490 //=== IMPLEMENTATION ==========================================================
00491 
00523 template< unsigned Order, class T >
00524 void compute_basis( ZernikePolynomialsBasisT< Order, T > **_zpb,
00525                     const unsigned int& _szx,
00526                     const unsigned int& _szy ) {
00527 
00528         T x, y, r, t; // (x, y) cartesian and (r, t) polar coordinates
00529 
00530         for (unsigned gx = 0; gx < _szx; ++gx) {
00531 
00532                 x = ( (T)2 * gx + (T)1 ) / (T)_szx - (T)1;
00533 
00534                 for (unsigned gy = 0; gy < _szy; ++gy) {
00535 
00536                         y = ( (T)2 * gy + (T)1 ) / (T)_szy - (T)1;
00537 
00538                         r = (T)sqrt( x*x + y*y );
00539                         if( r > (T)1 ) continue; // outside unit circle is zero
00540 
00541                         t = (T)atan2( y, x );
00542 
00543                         for (int p = 0; p <= Order; ++p) {
00544 
00545                                 int qi = 0; // q index: q[0, 2, 4] -> qi[0, 1, 2]
00546 
00547                                 for (int q = p % 2; q <= p; q += 2, qi++) {
00548 
00549                                         _zpb[gx][gy][p][qi] = compute_V(p, q, r, t);
00550 
00551                                 } // q
00552 
00553                         } // p
00554 
00555                 } // gy
00556 
00557         } // gx
00558 
00559 }
00568 //=============================================================================
00569 } // namespace zsig
00570 //=============================================================================
00571 #endif // ZSIG_ZPOLBASIST_HH
00572 //=============================================================================
 All Classes Files Functions Variables Typedefs Friends