KINECT STATS GENERATOR FOR SPORTS VISUALISATION
1.0
|
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