KINECT STATS GENERATOR FOR SPORTS VISUALISATION  1.0
BallTrackingUtility.cpp
Go to the documentation of this file.
00001 #include "BallTrackingUtility.h"
00002 #include "BallPointsProcessing.h"
00003 
00004 #include <iostream>
00005 #include <libfreenect.hpp>
00006 #include <libfreenect_sync.h>
00007 #include <Mutex.h>
00008 #include <QDebug>
00009 #include <KinectInterface.h>
00010 #include <ngl/NGLInit.h>
00011 #include <ngl/ShaderLib.h>
00012 #include <QTimer>
00013 #include <QObject>
00014 
00015 /*
00016   LICENSING: You are free to use any part of this project provided I am informed about it via email
00017   at santoshwins@hotmail.com and referenced appropriately in your works
00018   */
00019 
00020 void thresh_callback(int, void* );
00021 
00022 bool compareXX(cv::Point2f i, cv::Point2f j){ return (i.x < j.x);}
00023 
00024 bool compareXXHermite(cv::Point3f i, cv::Point3f j){ return (i.x < j.x);}
00025 
00026 bool compareXX3D(cv::Point3f i, cv::Point3f j){ return (i.x < j.x);}
00027 
00028 
00029 BallTrackingUtility::BallTrackingUtility()
00030 {
00031 
00032 }
00033 
00034 //----------------------------------------------------------------------------------------------------------------------
00035 BallTrackingUtility::BallTrackingUtility(BallPointsProcessing *_inputBallProcessingUtility):m_ballPointProcessing(_inputBallProcessingUtility)
00036 
00037 {
00038 
00039   m_rgb = cvCreateMat(480,640,CV_8UC3);
00040 
00041   m_gray = cvCreateMat(480,640,CV_8UC1);
00042 
00043   m_nextBuffer = cvCreateMat(480,640,CV_8UC1);
00044   m_prevBuffer = cvCreateMat(480,640,CV_8UC1);
00045   m_diffBuffer = cvCreateMat(480,640,CV_8UC1);
00046 
00047   m_bufferDepthRaw=cvCreateMat(480,640,CV_8UC1);
00048   m_bufferDepthRaw1=cvCreateMat(480,640,CV_8UC1);
00049 
00050   m_binaryLowerThresh = 100.0;
00051   m_binaryMaxVal = 255.0;
00052   m_cannyLowerThresh = 100.0;
00053   m_cannyHigherThresh = 300.0;
00054   m_contourAreaThresh = 120.0;
00055   m_diffAreaThresh = 30.0;
00056   m_ellipsesize = 2;
00057   m_blurSize = 5;
00058   m_noOfTimesToDialate = 2;
00059 
00060   m_masterRigCheck = 0;
00061 
00062   for( unsigned int i = 0 ; i < 640*480 ; ++i)
00063   {
00064       m_depthinm[i] = 0;
00065   }
00066 
00067   // all these are separate lists filled by separate calls to interpolate functions
00068   m_momentList.clear();
00069 
00070   area = rectArea = 0.0;
00071   m_updateTimer = new QTimer(this);
00072 
00073   connect(m_updateTimer, SIGNAL(timeout()), this, SLOT(trackBall()));
00074   m_updateTimer->start(1);
00075 
00076 }
00077 
00078 
00079 //----------------------------------------------------------------------------------------------------------------------
00080 //This virtual function is called whenever the widget needs to be painted.
00081 // this is our main drawing routine
00082 void BallTrackingUtility::trackBall()
00083 {
00084 
00085 
00086     KinectInterface *kinect=KinectInterface::instance();
00087 
00088     cv::Rect _boundsCheck = kinect->getBoxObject();
00089 
00090  if(kinect->getTrackingFlag())
00091  {
00092     static int _frameCount = 1;
00093 
00094     float depth = 0.0;
00095 
00096     kinect->getDepthRaw(m_bufferDepthRaw,m_depthinm);
00097 
00098     cv::blur(m_bufferDepthRaw,m_bufferDepthRaw1,cv::Size(m_blurSize,m_blurSize));
00099     // to reduce noise, smotthing has been done
00100 
00101     if(_frameCount == 1)
00102     {
00103         m_bufferDepthRaw1.copyTo(m_prevBuffer);
00104     }
00105 
00106     m_bufferDepthRaw1.copyTo(m_nextBuffer);
00107     cv::absdiff(m_nextBuffer,m_prevBuffer,m_diffBuffer);
00108     // has gpu variant // bg subtraction by frame differencing ...GMM method seems good through forums if at all we need
00109     m_nextBuffer.copyTo(m_prevBuffer);
00110     m_diffBuffer.copyTo(m_gray);
00111 
00112     cv::threshold(m_gray,m_gray,m_binaryLowerThresh,m_binaryMaxVal,CV_THRESH_BINARY_INV);
00113     cv::Mat element = cv::getStructuringElement(cv::MORPH_ELLIPSE,cv::Size(m_ellipsesize,m_ellipsesize));
00114     cv::dilate(m_gray,m_gray,element,cv::Point(-1,-1),m_noOfTimesToDialate);
00115     cv::erode(m_gray,m_gray,element,cv::Point(-1,-1),m_noOfTimesToDialate);
00116 
00118     cv::Canny( m_gray, canny_output, m_cannyLowerThresh, m_cannyHigherThresh, 3 ); // maintiain upper::lower ratio as 2:1 or 3:1 for better results
00119                                                                                    // as suggested by CANNY
00121     cv::findContours( canny_output, contours, hierarchy, CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE, cv::Point(0, 0) ); // methods to be decided
00122 
00123 
00124     for( int i = 0; i < contours.size(); i++ )
00125     {
00126         /* cv::drawContours( drawing, contours, i, cv::Scalar(255,0,0),-1, 8, hierarchy, 0, cv::Point() );*/ // -- DEV PURPOSE
00127         area = cv::contourArea(contours[i], false);
00128         cv::RotatedRect r = cv::minAreaRect(contours[i]);
00129 
00130         if (fabs(area) < m_contourAreaThresh) //my notes: this value is more important in reducing the
00131             //false positives and filters out those false positives by preventing them
00132             // from getting processed further..provide in UI
00133         {
00134             continue;
00135         }
00136         else
00137         {
00138             // do nothing
00139         }
00140 
00141        if (fabs(fabs(area) - (r.size.width * r.size.height * 3.14 / 4)) < m_diffAreaThresh)
00142        {
00143            m_momentList.push_back(cv::moments( contours[i], false ));
00144            float _xMomentsTemp = static_cast<float>(cv::moments( contours[i], false ).m10/cv::moments( contours[i], false ).m00);
00145            float _yMomentsTemp = static_cast<float>(cv::moments( contours[i], false ).m01/cv::moments( contours[i], false ).m00);
00146            int depthIndex = (int)((640 - _xMomentsTemp) + (640 * _yMomentsTemp));
00147            depth = m_depthinm[depthIndex] * 0.001;
00148 
00149            if(depth != 0)
00150            {
00151             if((_xMomentsTemp >= _boundsCheck.x) && (_xMomentsTemp <= _boundsCheck.x + _boundsCheck.width) &&
00152                     (_yMomentsTemp >= _boundsCheck.y) && (_yMomentsTemp <= _boundsCheck.y + _boundsCheck.height))
00153             {
00154 
00155 
00156                 std::cout<<"XMoments:"<<_xMomentsTemp<<"\n";
00157                 m_ballPointProcessing->setTrackedPoints(cv::Point3f(_xMomentsTemp,_yMomentsTemp,depth));
00158 
00159              }
00160             }
00161 
00162           }
00163         }
00164 
00165 
00166         _frameCount++;
00167   }
00168  else
00169  {
00170      // tracking not yet started...do nothing
00171 
00172 
00173  }
00174 
00175 
00176 }
00177 
00178 //----------------------------------------------------------------------------------------------------------------------
00179 void BallTrackingUtility::mouseMoveEvent ( QMouseEvent * _event)
00180 {
00181     Q_UNUSED(_event);
00182 }
00183 
00184 
00185 //----------------------------------------------------------------------------------------------------------------------
00186 void BallTrackingUtility::mousePressEvent (QMouseEvent * _event )
00187 {
00188     Q_UNUSED(_event);
00189 
00190 }
00191 
00192 //----------------------------------------------------------------------------------------------------------------------
00193 void BallTrackingUtility::mouseReleaseEvent ( QMouseEvent * _event )
00194 {
00195   // this event is called when the mouse button is released
00196   // we then set Rotate to false
00197   Q_UNUSED(_event);
00198 
00199 }
00200 
00201 void BallTrackingUtility::timerEvent( QTimerEvent *_event )
00202 {
00203     Q_UNUSED(_event);
00204     // re-draw GL
00205     //updateGL();
00206 
00207     trackBall();
00208 
00209 }
00210 
00211 
00212 BallTrackingUtility::~BallTrackingUtility()
00213 {
00214 
00215 }
00216 
00217 
00218 
00219 
00220 void BallTrackingUtility::setBinaryLowerThresh(double _lowerThresh)
00221 {
00222     m_binaryLowerThresh = _lowerThresh;
00223     //updateGL();
00224 }
00225 
00226 void BallTrackingUtility::setStructuringElementSize(int _size)
00227 {
00228     m_ellipsesize = _size;
00229     //updateGL();
00230 }
00231 
00232 void BallTrackingUtility::setBlurSize(int _size)
00233 {
00234     m_blurSize = _size;
00235     //updateGL();
00236 }
00237 
00238 void BallTrackingUtility::setCannyLowerThresh(double _lowerThresh)
00239 {
00240     m_cannyLowerThresh = _lowerThresh;
00241     //updateGL();
00242 }
00243 
00244 
00245 void BallTrackingUtility::setCannyHigherThresh(double _higherThresh)
00246 {
00247     m_cannyHigherThresh = _higherThresh;
00248     //updateGL();
00249 }
00250 
00251 
00252 void BallTrackingUtility::setNumerOfDialtions(int _numberOfDialtions)
00253 {
00254     m_noOfTimesToDialate = _numberOfDialtions;
00255     //updateGL();
00256 }
00257 
00258 void BallTrackingUtility::setContourAreaThresh(double _contourAreaThresh)
00259 {
00260     m_contourAreaThresh = _contourAreaThresh;
00261     //updateGL();
00262 }
00263 
00264 void BallTrackingUtility::setDifferenceInAreaThresh(double _diffAreaThresh)
00265 {
00266     m_diffAreaThresh = _diffAreaThresh;
00267     //updateGL();
00268 }
00269 
00270 void BallTrackingUtility::setMasterRigCheck(int _masterRigCheck)
00271 {
00272     m_masterRigCheck = _masterRigCheck;
00273     //updateGL();
00274 }
00275 
00276 
 All Classes Files Functions Variables Enumerations Enumerator