KINECT STATS GENERATOR FOR SPORTS VISUALISATION
1.0
|
This class processes the tracked points that is set into the vector members by the BallTrackingUtility class as and when the ball is tracked in real time. More...
#include <BallPointsProcessing.h>
Public Slots | |
void | processTrackingData () |
This module processes the tracked data once the stop tracking is pressedfrom UI. This is the main module which classifies player's points into specific rallies against specific player's and populates the multi-dimensional data structure of depth index. | |
void | setBallImpactDepthMaxThreshold (double _impactPtDepthMaxThresh) |
called from UI to set max depth value | |
void | setBallImpactDepthMinThreshold (double _impactPtDepthMinThresh) |
creates the specified model | |
Public Member Functions | |
BallPointsProcessing () | |
default constructor | |
BallPointsProcessing (PlayerData *_playerA, PlayerData *_playerB) | |
parameterized constructor taking in playerA and playerB instances from mainwindow | |
~BallPointsProcessing () | |
destructor | |
void | setTrackedPoints (cv::Point3f _inputTrackedPoint) |
This module is called by ballTrackingUtility to push tracked points into the tracking vector repository. | |
Private Attributes | |
std::vector< cv::Point3f > | m_entireTrackedDataPts |
Tracked points are set into this vector by balltrackingutility. | |
std::vector< std::vector < cv::Point3f > > | m_playerAPts |
Tracked points belonging to player A. | |
std::vector< std::vector < cv::Point3f > > | m_playerBPts |
Tracked points belonging to player B. | |
std::vector< std::vector< int > > | m_playerADeepestPtIndices |
Multi-dimnesional vector respository containing look up index into the m_playerAPts. | |
std::vector< std::vector< int > > | m_playerBDeepestPtIndices |
Multi-dimnesional vector respository containing look up index into the m_playerBPts. | |
PlayerData * | m_playerA |
Player instances. This will be set in the constructor by the mainwindow. | |
PlayerData * | m_playerB |
float | m_ballImpactDepthMaxThresh |
Pitch location min and max threshold set from UI to determine if the ball has crossed a minimum threshold to be considered for depth calculations and a max value to be compared against in direct comparison test. | |
float | m_ballImpactDepthMinThresh |
This class processes the tracked points that is set into the vector members by the BallTrackingUtility class as and when the ball is tracked in real time.
Definition at line 21 of file BallPointsProcessing.h.
default constructor
Definition at line 8 of file BallPointsProcessing.cpp.
References m_ballImpactDepthMaxThresh, m_ballImpactDepthMinThresh, m_entireTrackedDataPts, m_playerADeepestPtIndices, m_playerAPts, m_playerBDeepestPtIndices, and m_playerBPts.
{ m_entireTrackedDataPts.clear(); m_playerAPts.clear(); m_playerBPts.clear(); m_playerADeepestPtIndices.clear(); m_playerBDeepestPtIndices.clear(); m_ballImpactDepthMaxThresh = 0.70; // to be decided after measuring with tape m_ballImpactDepthMinThresh = 0.60; }
BallPointsProcessing::BallPointsProcessing | ( | PlayerData * | _playerA, |
PlayerData * | _playerB | ||
) |
parameterized constructor taking in playerA and playerB instances from mainwindow
[in] | _playerA | instance |
[in] | _playerB | instance |
Definition at line 21 of file BallPointsProcessing.cpp.
References m_ballImpactDepthMaxThresh, m_ballImpactDepthMinThresh, m_entireTrackedDataPts, m_playerADeepestPtIndices, m_playerAPts, m_playerBDeepestPtIndices, and m_playerBPts.
:m_playerA(_playerA),m_playerB(_playerB) { m_entireTrackedDataPts.clear(); m_playerAPts.clear(); m_playerBPts.clear(); m_playerADeepestPtIndices.clear(); m_playerBDeepestPtIndices.clear(); m_ballImpactDepthMaxThresh = 0.70; // to be decided after measuring with tape m_ballImpactDepthMinThresh = 0.60; }
destructor
Definition at line 34 of file BallPointsProcessing.cpp.
References m_entireTrackedDataPts, m_playerADeepestPtIndices, m_playerAPts, m_playerBDeepestPtIndices, and m_playerBPts.
{ m_entireTrackedDataPts.clear(); m_playerAPts.clear(); m_playerBPts.clear(); m_playerADeepestPtIndices.clear(); m_playerBDeepestPtIndices.clear(); }
void BallPointsProcessing::processTrackingData | ( | ) | [slot] |
This module processes the tracked data once the stop tracking is pressedfrom UI. This is the main module which classifies player's points into specific rallies against specific player's and populates the multi-dimensional data structure of depth index.
Definition at line 60 of file BallPointsProcessing.cpp.
References m_ballImpactDepthMaxThresh, m_ballImpactDepthMinThresh, m_entireTrackedDataPts, m_playerA, m_playerADeepestPtIndices, m_playerAPts, m_playerB, m_playerBDeepestPtIndices, m_playerBPts, PlayerData::setPlayerBallPts(), PlayerData::setPlayerDataProcessedFlag(), and PlayerData::setPlayerImpactPtIndices().
{ int _dataSetSize = m_entireTrackedDataPts.size(); std::cout<<"DataSize is:"<<_dataSetSize<<"\n"; int _rallyIncrementIndexLR = 0; int _rallyIncrementIndexRL = 0; bool _rightToLeft = false; bool _leftToRight = false; // initial initialization for the first sets of rally.... m_playerAPts.push_back(std::vector<cv::Point3f> ()); m_playerBPts.push_back(std::vector<cv::Point3f> ()); m_playerADeepestPtIndices.push_back(std::vector<int> ()); m_playerBDeepestPtIndices.push_back(std::vector<int> ()); if(_dataSetSize != 0) { for(int i=0;(i+1)<_dataSetSize;i++) // we shud stop one element before the last as there wud be no next elt to compare it with { // Rally direction classification // notes to self: // equality condition not needed as 2 pts equal and next to each other is most probably // a redundant data rather than actual data as the ball when travelling // with high speed is getting detected twice at almost the same locaions // so one of the values can be safely ignored // so if i == i+1,it would be classified into a single rally once if((int)(m_entireTrackedDataPts[i].x) < (int)(m_entireTrackedDataPts[i+1].x)) // changed to <= as we have pasted it inverted // but the data is from 0,0 at the top right { //player left to right ( when viwed in perspective of kinet's position) // lesser pixels to greater pixels assuming 0,0 at top right of table // if previously there was a rally from right to left, // then there is a direction change now, hence it has come into this if // hence we need to increment rally index and // set the current direction to true as long as it comes into this if if(_rightToLeft == true) { if(m_playerBDeepestPtIndices[_rallyIncrementIndexRL].size() == 0) { m_playerBDeepestPtIndices[_rallyIncrementIndexRL].push_back(-1); } // duplication of end points when direction changes m_playerBPts[_rallyIncrementIndexRL].push_back(m_entireTrackedDataPts[i]); _rallyIncrementIndexRL++; m_playerBPts.push_back(std::vector<cv::Point3f> ()); m_playerBDeepestPtIndices.push_back(std::vector<int> ()); _rightToLeft = false; } m_playerAPts[_rallyIncrementIndexLR].push_back(m_entireTrackedDataPts[i]); // Impact point classification // if fortunately we have actually got a point beyond our impact point thrsh // then this must be the impact point if(m_entireTrackedDataPts[i].z > m_ballImpactDepthMaxThresh) { m_playerADeepestPtIndices[_rallyIncrementIndexLR].push_back((m_playerAPts[_rallyIncrementIndexLR].size() - 1)); } // else we need to check for polarity change // if there is a positive polarity(sign) in the difference among the depth values // of 3 consecutively detected points then this is an impact point // i.e. if sign of the difference in depth values between 1 and 2 is positive and // sign of the difference in depth values between 2 and 3 is also positive // then the ball must have pitched on the ground else { // depth detected should atleast be > this min thresh // else some points which has a depth of say 0.5 which is supposed to // be not compared for polarity changes will be taken for comparison // this will be useful when data points are low in number, and // no data is actually valid for depth..this might not be useful // if detection is proper // first point wont fit into this condition as we need 3 points atleast if((i !=0) && (m_entireTrackedDataPts[i].z > m_ballImpactDepthMinThresh) ) { if(((m_entireTrackedDataPts[i].z - m_entireTrackedDataPts[i-1].z) > 0) && ((m_entireTrackedDataPts[i].z - m_entireTrackedDataPts[i+1].z) > 0)) { // we need to push the index of this point // so push the (current size - 1) of the ith rally which will refer to the current ball point // as vector starts from 0 m_playerADeepestPtIndices[_rallyIncrementIndexLR].push_back((m_playerAPts[_rallyIncrementIndexLR].size() - 1)); } } } // if next point is the last point // then push the last point as part of the current rally if((i+1) == (_dataSetSize -1)) { //- for Rally Classification //m_playerAPts.push_back(std::vector<cv::Point3f> ()); // next elt is the last elt..push it into the same player rally as the prev point m_playerAPts[_rallyIncrementIndexLR].push_back(m_entireTrackedDataPts[i+1]); //- for Impact Point Classification // as this last point may actually be an impact point // we cannot perform the other logic of polarity change, but // we can atleast perform the depth thresh check if(m_entireTrackedDataPts[i+1].z > m_ballImpactDepthMaxThresh) { m_playerADeepestPtIndices[_rallyIncrementIndexLR].push_back((m_playerAPts[_rallyIncrementIndexLR].size() - 1)); } } // if next point is the last point - for Depth classification // in case there was no depth change detected until the last point // then the last point will be automatically treated as an end point with regards to interpolation // and there will be no impact point _leftToRight = true; } else if ((int)(m_entireTrackedDataPts[i].x) > (int)(m_entireTrackedDataPts[i+1].x)) { // player right to left as seen from kinects top view // greater pixels to lesser pixels assuming 640,480 at left bottom of table // if previously there was a rally from left to right, // then there is a sirection change now, hence it has come into this else // hence we need to increment rally index and // set the current direction to true as long as it comes into this else if(_leftToRight == true) { if(m_playerADeepestPtIndices[_rallyIncrementIndexLR].size() == 0) { m_playerADeepestPtIndices[_rallyIncrementIndexLR].push_back(-1); } // duplication of end points when direction changes m_playerAPts[_rallyIncrementIndexLR].push_back(m_entireTrackedDataPts[i]); _rallyIncrementIndexLR++; m_playerAPts.push_back(std::vector<cv::Point3f> ()); m_playerADeepestPtIndices.push_back(std::vector<int> ()); _leftToRight = false; } m_playerBPts[_rallyIncrementIndexRL].push_back(m_entireTrackedDataPts[i]); // Impact point classification // same logic if(m_entireTrackedDataPts[i].z > m_ballImpactDepthMaxThresh) { m_playerBDeepestPtIndices[_rallyIncrementIndexRL].push_back((m_playerBPts[_rallyIncrementIndexRL].size() - 1)); } else { if((i !=0) && (m_entireTrackedDataPts[i].z > m_ballImpactDepthMinThresh) ) { if(((m_entireTrackedDataPts[i].z - m_entireTrackedDataPts[i-1].z) > 0) && ((m_entireTrackedDataPts[i].z - m_entireTrackedDataPts[i+1].z) > 0)) { m_playerBDeepestPtIndices[_rallyIncrementIndexRL].push_back((m_playerBPts[_rallyIncrementIndexRL].size() - 1)); } } } // if next point is the last point // same logic if((i+1) == (_dataSetSize -1)) { //- for Rally Classification //m_playerBPts.push_back(std::vector<cv::Point3f> ()); // next elt is the last elt..push it into the same player rally as the prev point m_playerBPts[_rallyIncrementIndexRL].push_back(m_entireTrackedDataPts[i+1]); //- for Impact Point Classification if(m_entireTrackedDataPts[i+1].z > m_ballImpactDepthMaxThresh) { m_playerBDeepestPtIndices[_rallyIncrementIndexRL].push_back((m_playerBPts[_rallyIncrementIndexRL].size() - 1)); } } // if next point is the last point for Depth classification // in case there was no depth change detected until the last point // then the last point will be automatically treated as an end point with regards to interpolation // and there will be no impact point _rightToLeft = true; } } // set the playerA vector and playerB vector into the respective instances // by calling their set() functions m_playerA->setPlayerBallPts(m_playerAPts); m_playerA->setPlayerImpactPtIndices(m_playerADeepestPtIndices); m_playerB->setPlayerBallPts(m_playerBPts); m_playerB->setPlayerImpactPtIndices(m_playerBDeepestPtIndices); int aRallies = 0; int bRallies = 0; for(int i = 0;i<m_playerAPts.size();i++) { for(int j=0;j<m_playerAPts[i].size();j++) { if(j==0) { aRallies++; std::cout<<"New rally starts....\n"; } std::cout<<"PlayerA points are:"<<m_playerAPts[i][j]<<"\n"; } } for(int i = 0;i<m_playerBPts.size();i++) { for(int j=0;j<m_playerBPts[i].size();j++) { if(j==0) { bRallies++; std::cout<<"New rally starts....\n"; } std::cout<<"PlayerB points are:"<<m_playerBPts[i][j]<<"\n"; } } // these are the proper rally counts // as we push an empty vector set each time there is a direction change into the // opposite direction's vectorofvector for the next anitcipated direction change // which may not get filled in as the anticipated next change of direction // might not have occured which leaves the last pushed vector set empty // hence the rally increment counter has to be incremented only when there is data in the // inner vector set..this increment is done in the above inner for loop std::cout<<"A rallies:\n"<<aRallies; std::cout<<"B rallies\n:"<<bRallies; for(int i = 0;i<m_playerADeepestPtIndices.size();i++) { for(int j=0;j<m_playerADeepestPtIndices[i].size();j++) { std::cout<<"PlayerA Impact index are:"<<m_playerADeepestPtIndices[i][j]<<"\n"; std::cout<<"which is"<<m_playerAPts[i][m_playerADeepestPtIndices[i][j]]<<"\n"; } } for(int i = 0;i<m_playerBDeepestPtIndices.size();i++) { for(int j=0;j<m_playerBDeepestPtIndices[i].size();j++) { std::cout<<"PlayerB Impact index are:"<<m_playerBDeepestPtIndices[i][j]<<"\n"; std::cout<<"which is"<<m_playerBPts[i][m_playerBDeepestPtIndices[i][j]]<<"\n"; } } // set the data processed flag for both the players as we have now filled all the points needed // for further stats calculation // this flag when set will be queried by the stats window to gather data from the player's // object m_playerA->setPlayerDataProcessedFlag(); m_playerB->setPlayerDataProcessedFlag(); } else { QString warningString("Oops.Enough data points not available. Relax!!! Start Tracking again and Play to generate new data!!!"); QMessageBox * warning = new QMessageBox(QMessageBox::Warning,QString("NO DATA WARNING"),warningString,QMessageBox::Ok); warning->setModal(true); warning->setText(warningString); warning->show(); // display this in message box } }
void BallPointsProcessing::setBallImpactDepthMaxThreshold | ( | double | _impactPtDepthMaxThresh | ) | [slot] |
called from UI to set max depth value
[in] | _impactDepthMaxThresh | value from UI |
Definition at line 386 of file BallPointsProcessing.cpp.
References m_ballImpactDepthMaxThresh.
{ m_ballImpactDepthMaxThresh = (float)_impactPtDepthMaxThresh; }
void BallPointsProcessing::setBallImpactDepthMinThreshold | ( | double | _impactPtDepthMinThresh | ) | [slot] |
creates the specified model
[in] | _impactDepthMinThresh | value from UI |
Definition at line 391 of file BallPointsProcessing.cpp.
References m_ballImpactDepthMinThresh.
{ m_ballImpactDepthMinThresh = (float)_impactPtDepthMinThresh; }
void BallPointsProcessing::setTrackedPoints | ( | cv::Point3f | _inputTrackedPoint | ) |
This module is called by ballTrackingUtility to push tracked points into the tracking vector repository.
[in] | _inputTrackedPoint | is the current tracked point in realtime |
Definition at line 44 of file BallPointsProcessing.cpp.
References m_entireTrackedDataPts.
{ m_entireTrackedDataPts.push_back(_inputTrackedPoint); }
float BallPointsProcessing::m_ballImpactDepthMaxThresh [private] |
Pitch location min and max threshold set from UI to determine if the ball has crossed a minimum threshold to be considered for depth calculations and a max value to be compared against in direct comparison test.
Definition at line 64 of file BallPointsProcessing.h.
float BallPointsProcessing::m_ballImpactDepthMinThresh [private] |
Definition at line 64 of file BallPointsProcessing.h.
std::vector<cv::Point3f> BallPointsProcessing::m_entireTrackedDataPts [private] |
Tracked points are set into this vector by balltrackingutility.
Definition at line 29 of file BallPointsProcessing.h.
PlayerData* BallPointsProcessing::m_playerA [private] |
Player instances. This will be set in the constructor by the mainwindow.
Definition at line 56 of file BallPointsProcessing.h.
std::vector<std::vector<int> > BallPointsProcessing::m_playerADeepestPtIndices [private] |
Multi-dimnesional vector respository containing look up index into the m_playerAPts.
Definition at line 45 of file BallPointsProcessing.h.
std::vector<std::vector<cv::Point3f> > BallPointsProcessing::m_playerAPts [private] |
Tracked points belonging to player A.
Definition at line 34 of file BallPointsProcessing.h.
PlayerData * BallPointsProcessing::m_playerB [private] |
Definition at line 56 of file BallPointsProcessing.h.
std::vector<std::vector<int> > BallPointsProcessing::m_playerBDeepestPtIndices [private] |
Multi-dimnesional vector respository containing look up index into the m_playerBPts.
Definition at line 51 of file BallPointsProcessing.h.
std::vector<std::vector<cv::Point3f> > BallPointsProcessing::m_playerBPts [private] |
Tracked points belonging to player B.
Definition at line 39 of file BallPointsProcessing.h.