KINECT STATS GENERATOR FOR SPORTS VISUALISATION  1.0
BallPointsProcessing Class Reference

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>

+ Collaboration diagram for BallPointsProcessing:

List of all members.

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.
PlayerDatam_playerA
 Player instances. This will be set in the constructor by the mainwindow.
PlayerDatam_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

Detailed Description

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.


Constructor & Destructor Documentation

parameterized constructor taking in playerA and playerB instances from mainwindow

Parameters:
[in]_playerAinstance
[in]_playerBinstance

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;

}

Member Function Documentation

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
    }
}

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

void BallPointsProcessing::setBallImpactDepthMaxThreshold ( double  _impactPtDepthMaxThresh) [slot]

called from UI to set max depth value

Parameters:
[in]_impactDepthMaxThreshvalue 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

Parameters:
[in]_impactDepthMinThreshvalue 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.

Parameters:
[in]_inputTrackedPointis the current tracked point in realtime

Definition at line 44 of file BallPointsProcessing.cpp.

References m_entireTrackedDataPts.

{
    m_entireTrackedDataPts.push_back(_inputTrackedPoint);
}

+ Here is the caller graph for this function:


Member Data Documentation

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.

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.

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.

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.


The documentation for this class was generated from the following files:
 All Classes Files Functions Variables Enumerations Enumerator