KINECT STATS GENERATOR FOR SPORTS VISUALISATION  1.0
QuadCurveFitUtility.cpp
Go to the documentation of this file.
00001 /********
00002   This least squares fitting is partly sources from
00003   http://www.codeproject.com/Articles/63170/Least-Squares-Regression-for-Quadratic-Curve-Fitti
00004 ********/
00005 
00006 #include "QuadCurveFitUtility.h"
00007 #include "ngl/Vec3.h"
00008 
00009 
00010 const int MIN_VALUES = 3;
00011 
00012 
00013 QuadCurveFitUtility::QuadCurveFitUtility()
00014 {
00015     m_dataPoints.clear();
00016     m_dataPointsAfterInterpol.clear();
00017     m_a = m_b = m_c = 0;
00018 
00019 }
00020 
00021 QuadCurveFitUtility::~QuadCurveFitUtility()
00022 {
00023 
00024 }
00033 void QuadCurveFitUtility::addPoints( cv::Point2f _inputSet )
00034 {
00035     m_dataPoints.push_back(_inputSet);
00036 }
00037 
00038 
00039 
00040 /*
00041   y = ax^2 + bx + c
00042 
00043   notation Sjk to mean the sum of x_i^j*y_i^k.
00044   2a*S40 + 2c*S20 + 2b*S30 - 2*S21 = 0
00045   2b*S20 + 2a*S30 + 2c*S10 - 2*S11 = 0
00046   2a*S20 + 2c*S00 + 2b*S10 - 2*S01 = 0
00047 
00048   solve the system of simultaneous equations using Cramer's law
00049 
00050   [ S40  S30  S20 ] [ a ]   [ S21 ]
00051   [ S30  S20  S10 ] [ b ] = [ S11 ]
00052   [ S20  S10  S00 ] [ c ]   [ S01 ]
00053 
00054   D = [ S40  S30  S20 ]
00055       [ S30  S20  S10 ]
00056       [ S20  S10  S00 ]
00057 
00058       S40(S20*S00 - S10*S10) - S30(S30*S00 - S10*S20) + S20(S30*S10 - S20*S20)
00059 
00060  Da = [ S21  S30  S20 ]
00061       [ S11  S20  S10 ]
00062       [ S01  S10  S00 ]
00063 
00064       S21(S20*S00 - S10*S10) - S11(S30*S00 - S10*S20) + S01(S30*S10 - S20*S20)
00065 
00066  Db = [ S40  S21  S20 ]
00067       [ S30  S11  S10 ]
00068       [ S20  S01  S00 ]
00069 
00070       S40(S11*S00 - S01*S10) - S30(S21*S00 - S01*S20) + S20(S21*S10 - S11*S20)
00071 
00072  Dc = [ S40  S30  S21 ]
00073       [ S30  S20  S11 ]
00074       [ S20  S10  S01 ]
00075 
00076       S40(S20*S01 - S10*S11) - S30(S30*S01 - S10*S21) + S20(S30*S11 - S20*S21)
00077 
00078  */
00079 
00080 
00088 double QuadCurveFitUtility::getATerm()
00089 {
00090     if( m_dataPoints.size() < MIN_VALUES )
00091     {
00092         std::cout<<"Atleast 3 data sets required to interpolate" ;
00093         return 0;
00094     }
00095 
00096     // notation sjk to mean the sum of x_i^j_i^k.
00097     double s40 = getSxy( 4, 0 );
00098     double s30 = getSxy( 3, 0 );
00099     double s20 = getSxy( 2, 0 );
00100     double s10 = getSxy( 1, 0 );
00101     double s00 = (double)m_dataPoints.size();
00102 
00103     double s21 = getSxy( 2, 1 );
00104     double s11 = getSxy( 1, 1 );
00105     double s01 = getSxy( 0, 1 );
00106 
00107     // Da / D
00108     m_a = (s21 * (s20 * s00 - s10 * s10) - s11 * (s30 * s00 - s10 * s20) + s01 * (s30 * s10 - s20 * s20))
00109                 /
00110                 (s40 * (s20 * s00 - s10 * s10) - s30 * (s30 * s00 - s10 * s20) + s20 * (s30 * s10 - s20 * s20));
00111 
00112     return m_a;
00113 }
00114 
00122 double QuadCurveFitUtility::getBTerm()
00123 {
00124     if( m_dataPoints.size() < MIN_VALUES )
00125     {
00126         std::cout<<"Atleast 3 data sets required to interpolate" ;
00127         return 0;
00128     }
00129 
00130 
00131     // notation sjk to mean the sum of x_i^j_i^k.
00132     double s40 = getSxy( 4, 0 );
00133     double s30 = getSxy( 3, 0 );
00134     double s20 = getSxy( 2, 0 );
00135     double s10 = getSxy( 1, 0 );
00136     double s00 = (double)m_dataPoints.size();
00137 
00138     double s21 = getSxy( 2, 1 );
00139     double s11 = getSxy( 1, 1 );
00140     double s01 = getSxy( 0, 1 );
00141 
00142     //   Db / D
00143     m_b = (s40 * (s11 * s00 - s01 * s10) - s30 * (s21 * s00 - s01 * s20) + s20 * (s21 * s10 - s11 * s20))
00144         /
00145         (s40 * (s20 * s00 - s10 * s10) - s30 * (s30 * s00 - s10 * s20) + s20 * (s30 * s10 - s20 * s20));
00146 
00147     return m_b;
00148 }
00149 
00157 double QuadCurveFitUtility::getCTerm()
00158 {
00159     if( m_dataPoints.size() < MIN_VALUES )
00160     {
00161         std::cout<<"Atleast 3 data sets required to interpolate" ;
00162         return 0;
00163     }
00164 
00165 
00166     // notation sjk to mean the sum of x_i^j_i^k.
00167     double s40 = getSxy( 4, 0 );
00168     double s30 = getSxy( 3, 0 );
00169     double s20 = getSxy( 2, 0 );
00170     double s10 = getSxy( 1, 0 );
00171     double s00 = (double)m_dataPoints.size();
00172 
00173     double s21 = getSxy( 2, 1 );
00174     double s11 = getSxy( 1, 1 );
00175     double s01 = getSxy( 0, 1 );
00176 
00177     //   Dc / D
00178     m_c = (s40*(s20 * s01 - s10 * s11) - s30*(s30 * s01 - s10 * s21) + s20*(s30 * s11 - s20 * s21))
00179             /
00180             (s40 * (s20 * s00 - s10 * s10) - s30 * (s30 * s00 - s10 * s20) + s20 * (s30 * s10 - s20 * s20));
00181 
00182     return m_c;
00183 }
00184 
00192 double QuadCurveFitUtility::getRSquare()
00193 {
00194     if( m_dataPoints.size() < MIN_VALUES )
00195     {
00196         std::cout<<"Atleast 3 data sets required to interpolate" ;
00197         return 0;
00198     }
00199 
00200     return (1.0 - getSSerr() / getSStot());
00201 
00202 }
00203 
00204 // helper functions
00205 
00216 double QuadCurveFitUtility::getSxy( int _nX, int _nY )
00217 {
00218     double dSxy = 0.0;
00219 
00220     for(int i = 0;i<m_dataPoints.size();i++)
00221     {
00222         dSxy += pow(m_dataPoints[i].x,_nX) * pow(m_dataPoints[i].y,_nY);
00223     }
00224 
00225     return dSxy;
00226 }
00227 
00235 double QuadCurveFitUtility::getYMean()
00236 {
00237     double dTotal = 0.0;
00238     int nCount = 0;
00239     for(int i = 0;i<m_dataPoints.size();i++)
00240     {
00241         dTotal += m_dataPoints[i].y;
00242         nCount++;
00243     }
00244 
00245     return dTotal / nCount;
00246 }
00247 
00255 double QuadCurveFitUtility::getSStot()
00256 {
00257     double ssTot = 0.0;
00258     double dYMean = getYMean();
00259 
00260     for(int i = 0;i<m_dataPoints.size();i++)
00261     {
00262         ssTot += pow( (m_dataPoints[i].y * dYMean), 2 );
00263     }
00264 
00265     return ssTot;
00266 }
00267 
00275 double QuadCurveFitUtility::getSSerr()
00276 {
00277     double ssErr = 0.0;
00278 
00279     //auto pThis = this;
00280 
00281     for(int i = 0;i<m_dataPoints.size();i++)
00282     {
00283         ssErr += pow( (m_dataPoints[i].y - getPredictedY( m_dataPoints[i].x)), 2 );
00284     }
00285 
00286     return ssErr;
00287 }
00288 
00298 double QuadCurveFitUtility::getPredictedY( double _x )
00299 {
00300     return (getATerm() * pow( _x, 2 )) + (getBTerm() * _x) + getCTerm();
00301 }
00302 
00303 double QuadCurveFitUtility::getDifferential( double _x )
00304 {
00305     //2at + b is the differential
00306     return ((2 * getATerm() *  _x) + (getBTerm()));
00307 }
00308 
00309 
00310 void QuadCurveFitUtility::processParametricPoints3D(std::vector<float>& _inputBuffer,float& o_coeffX)
00311 {
00312     int i = m_dataPoints.size();
00313 
00314     //std::sort(m_dataPoints)
00315     std::cout<<"size is:"<<i<<"first:"<<m_dataPoints[0].x<<"::"<<m_dataPoints[0].y<<"last:"<<m_dataPoints[i - 1].x<<"::"<<m_dataPoints[i - 1].y<<"\n";
00316     double temp = 0;
00317     if(i != 0)
00318     {
00319         temp = m_dataPoints[0].x;
00320         while(temp <= 1.0)
00321         {
00322             std::cout<<" Interpol. X and Y are: "<<temp<<":"<<getPredictedY(temp);
00323             //m_dataPointsAfterInterpol.push_back(cv::Point2f(temp,getPredictedY(temp)));
00324 
00325             float tempValue = getPredictedY(temp);
00326             if(!(std::isnan(tempValue)))
00327             {
00328                 _inputBuffer.push_back(getPredictedY(temp));
00329             }
00330             temp = temp + 0.01;
00331         }
00332 
00333         // get the differential at t = 1.0 which will be our
00334         // tangent to the impact point
00335         o_coeffX = getDifferential(1.0);
00336 
00337     }
00338 }
00339 
 All Classes Files Functions Variables Enumerations Enumerator