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