KINECT STATS GENERATOR FOR SPORTS VISUALISATION
1.0
|
00001 #include "BallTrackingVisualization.h" 00002 #include "StatsVisualization.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 00013 /* 00014 LICENSING: You are free to use any part of this project provided I am informed about it via email 00015 at santoshwins@hotmail.com and referenced appropriately in your works 00016 */ 00017 00018 //---------------------------------------------------------------------------------------------------------------------- 00019 BallTrackingVisualization::BallTrackingVisualization(QWidget *_parent) : QGLWidget( new CreateCoreGLContext(QGLFormat::defaultFormat()), _parent ) 00020 00021 { 00022 00023 // re-size the widget to that of the parent (in this case the GLFrame passed in on construction) 00024 this->resize(_parent->size()); 00025 startTimer(20); 00026 m_rgb = cvCreateMat(480,640,CV_8UC3); 00027 00028 m_gray = cvCreateMat(480,640,CV_8UC1); 00029 00030 m_nextBuffer = cvCreateMat(480,640,CV_8UC1); 00031 m_prevBuffer = cvCreateMat(480,640,CV_8UC1); 00032 m_diffBuffer = cvCreateMat(480,640,CV_8UC1); 00033 00034 m_bufferDepthRaw=cvCreateMat(480,640,CV_8UC1); 00035 m_bufferDepthRaw1=cvCreateMat(480,640,CV_8UC1); 00036 00037 m_binaryLowerThresh = 100.0; 00038 m_binaryMaxVal = 255.0; 00039 m_cannyLowerThresh = 100.0; 00040 m_cannyHigherThresh = 200.0; 00041 m_contourAreaThresh = 100.0; 00042 m_diffAreaThresh = 10.0; 00043 m_ellipsesize = 2; 00044 m_blurSize = 5; 00045 m_noOfTimesToDialate = 2; 00046 00047 m_masterRigCheck = 0; 00048 00049 for( unsigned int i = 0 ; i < 640*480 ; ++i) 00050 { 00051 m_depthinm[i] = 0; 00052 } 00053 00054 00055 m_momentList.clear(); 00056 00057 area = rectArea = 0.0; 00058 } 00059 00060 // This virtual function is called once before the first call to paintGL() or resizeGL(), 00061 //and then once whenever the widget has been assigned a new QGLContext. 00062 // This function should set up any required OpenGL context rendering flags, defining display lists, etc. 00063 00064 //---------------------------------------------------------------------------------------------------------------------- 00065 void BallTrackingVisualization::initializeGL() 00066 { 00067 00068 glEnable(GL_DEPTH_TEST); 00069 00070 00071 // 00072 ngl::NGLInit *Init = ngl::NGLInit::instance(); 00073 Init->initGlew(); 00074 00075 // now we have valid GL can create shaders etc 00076 ngl::ShaderLib *shader = ngl::ShaderLib::instance(); 00077 shader->createShaderProgram("TextureTrack"); 00078 00079 shader->attachShader("TextureVertex",ngl::VERTEX); 00080 shader->attachShader("TextureFragment",ngl::FRAGMENT); 00081 shader->loadShaderSource("TextureVertex","shaders/TextureVert.glsl"); 00082 shader->loadShaderSource("TextureFragment","shaders/TextureFrag.glsl"); 00083 00084 shader->compileShader("TextureVertex"); 00085 shader->compileShader("TextureFragment"); 00086 shader->attachShaderToProgram("TextureTrack","TextureVertex"); 00087 shader->attachShaderToProgram("TextureTrack","TextureFragment"); 00088 00089 shader->linkProgramObject("TextureTrack"); 00090 (*shader)["TextureTrack"]->use(); 00091 shader->setShaderParam1i("tex",0); 00092 00093 m_screen = new ScreenQuad(640,480,"TextureTrack"); 00094 00095 00096 } 00097 00098 //---------------------------------------------------------------------------------------------------------------------- 00099 //This virtual function is called whenever the widget has been resized. 00100 // The new size is passed in width and height. 00101 void BallTrackingVisualization::resizeGL( 00102 int _w, 00103 int _h 00104 ) 00105 { 00106 glViewport(0,0,_w,_h); 00107 00108 } 00109 00110 //---------------------------------------------------------------------------------------------------------------------- 00111 //This virtual function is called whenever the widget needs to be painted. 00112 // this is our main drawing routine 00113 void BallTrackingVisualization::paintGL() 00114 { 00115 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 00116 00117 00118 KinectInterface *kinect=KinectInterface::instance(); 00119 00120 cv::Rect _boundsCheck = kinect->getBoxObject(); 00121 00122 if(kinect->getTrackingFlag()) 00123 { 00124 00125 00126 static int _frameCount = 1; 00127 float depth = 0.0; 00128 00129 kinect->getDepthRaw(m_bufferDepthRaw,m_depthinm); 00130 00131 // commented for gpu trial 00132 00133 cv::blur(m_bufferDepthRaw,m_bufferDepthRaw1,cv::Size(m_blurSize,m_blurSize)); // to reduce noise, smotthing has been done 00134 /* cv::gpu::blur(m_bufferDepthRawGpu,m_bufferDepthRawGpu1,cv::Size(m_blurSize,m_blurSize));*/ 00135 00136 if(_frameCount == 1) 00137 { 00138 m_bufferDepthRaw1.copyTo(m_prevBuffer); 00139 } 00140 00141 m_bufferDepthRaw1.copyTo(m_nextBuffer); 00142 00143 // commented for gpu trial 00144 00145 cv::absdiff(m_nextBuffer,m_prevBuffer,m_diffBuffer); // has gpu variant // bg subtraction by frame differencing ...GMM method seems good through forums if at all we need 00146 /*cv::gpu::absdiff(m_nextBufferGpu,m_prevBufferGpu,m_diffBufferGpu);*/ 00147 00148 m_nextBuffer.copyTo(m_prevBuffer); 00149 00150 // commented for gpu trial 00151 00152 m_diffBuffer.copyTo(m_gray); 00153 /*m_diffBuffer.copyTo(m_grayGpu);*/ 00154 00155 // commented for gpu tiral 00156 cv::threshold(m_gray,m_gray,m_binaryLowerThresh,m_binaryMaxVal,CV_THRESH_BINARY_INV); // nned to decide the thresh factors and the thresh method 00157 cv::Mat element = cv::getStructuringElement(cv::MORPH_ELLIPSE,cv::Size(m_ellipsesize,m_ellipsesize)); // need to decide this size 00158 cv::dilate(m_gray,m_gray,element,cv::Point(-1,-1),m_noOfTimesToDialate); // try swapping this with below and try increasing iterations 00159 cv::erode(m_gray,m_gray,element,cv::Point(-1,-1),m_noOfTimesToDialate); 00160 00161 /*cv::gpu::threshold(m_grayGpu,m_grayGpu,m_binaryLowerThresh,m_binaryMaxVal,CV_THRESH_BINARY_INV); 00162 cv::Mat element = cv::getStructuringElement(cv::MORPH_ELLIPSE,cv::Size(m_ellipsesize,m_ellipsesize)); // need to decide this size 00163 cv::gpu::dilate(m_grayGpu,m_grayGpu,element,cv::Point(-1,-1),m_noOfTimesToDialate); // try swapping this with below and try increasing iterations 00164 cv::gpu::erode(m_grayGpu,m_grayGpu,element,cv::Point(-1,-1),m_noOfTimesToDialate);*/ 00165 00166 // commented for gpu trial 00167 00168 // Detect edges using canny 00169 cv::Canny( m_gray, canny_output, m_cannyLowerThresh, m_cannyHigherThresh, 3 ); // maintiain upper::lower ratio as 2:1 or 3:1 for better results 00170 // as suggested by CANNY 00171 /* cv::gpu::Canny(m_grayGpu, canny_outputGpu, m_cannyLowerThresh, m_cannyHigherThresh, 3);*/ 00172 // commented for gpu trial 00173 00174 // Find contours 00175 cv::findContours( canny_output, contours, hierarchy, CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE, cv::Point(0, 0) ); // methods to be decided 00176 /*cv::findContours( canny_outputGpu, contours, hierarchy, CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE, cv::Point(0, 0) ); // methods to be decided*/ 00177 00178 00179 cv::Mat drawing = cv::Mat::zeros( canny_output.size(), CV_8UC3 ); 00180 00181 00182 for( int i = 0; i < contours.size(); i++ ) 00183 { 00184 00185 /* cv::drawContours( drawing, contours, i, cv::Scalar(255,0,0),-1, 8, hierarchy, 0, cv::Point() );*/ // -- DEV PURPOSE 00186 00187 area = cv::contourArea(contours[i], false); 00188 00189 cv::RotatedRect r = cv::minAreaRect(contours[i]); 00190 00191 00192 00193 if (fabs(area) < m_contourAreaThresh) //my notes: this value is more important in reducing the false positives and filters out those false positives by preventing them 00194 // from getting processed further..provide in UI 00195 { 00196 continue; 00197 } 00198 else 00199 { 00200 // do nothing 00201 } 00202 00203 if (fabs(fabs(area) - (r.size.width * r.size.height * 3.14 / 4)) < m_diffAreaThresh) 00204 { 00205 00206 m_momentList.push_back(cv::moments( contours[i], false )); 00207 00208 float _xMomentsTemp = static_cast<float>(cv::moments( contours[i], false ).m10/cv::moments( contours[i], false ).m00); 00209 float _yMomentsTemp = static_cast<float>(cv::moments( contours[i], false ).m01/cv::moments( contours[i], false ).m00); 00210 00211 int depthIndex = (int)((640 - _xMomentsTemp) + (640 * _yMomentsTemp)); 00212 depth = m_depthinm[depthIndex] * 0.001; 00213 00214 if(depth != 0) 00215 { 00216 if((_xMomentsTemp >= _boundsCheck.x) && (_xMomentsTemp <= _boundsCheck.x + _boundsCheck.width) 00217 && (_yMomentsTemp >= _boundsCheck.y) && (_yMomentsTemp <= _boundsCheck.y + _boundsCheck.height)) 00218 { 00219 cv::ellipse(drawing,r,cv::Scalar(0,255,0),-1,8); 00220 std::cout<<"Rect center x:"<<r.center.x<<"\n"; 00221 } 00222 } 00223 00224 } 00225 00226 } 00227 00228 _frameCount++; 00229 00230 m_screen->draw(&drawing); 00231 00232 } 00233 else 00234 { 00235 // tracking not yet started...do nothing 00236 } 00237 00238 } 00239 00240 //---------------------------------------------------------------------------------------------------------------------- 00241 void BallTrackingVisualization::mouseMoveEvent ( QMouseEvent * _event) 00242 { 00243 Q_UNUSED(_event); 00244 } 00245 00246 00247 //---------------------------------------------------------------------------------------------------------------------- 00248 void BallTrackingVisualization::mousePressEvent (QMouseEvent * _event ) 00249 { 00250 Q_UNUSED(_event); 00251 00252 } 00253 00254 //---------------------------------------------------------------------------------------------------------------------- 00255 void BallTrackingVisualization::mouseReleaseEvent ( QMouseEvent * _event ) 00256 { 00257 // this event is called when the mouse button is released 00258 // we then set Rotate to false 00259 Q_UNUSED(_event); 00260 00261 } 00262 00263 void BallTrackingVisualization::timerEvent( QTimerEvent *_event ) 00264 { 00265 Q_UNUSED(_event); 00266 // re-draw GL 00267 updateGL(); 00268 00269 } 00270 00271 00272 BallTrackingVisualization::~BallTrackingVisualization() 00273 { 00274 if(m_screen) 00275 { 00276 delete m_screen; 00277 } 00278 } 00279 00280 00281 00282 void BallTrackingVisualization::setBinaryLowerThresh(double _lowerThresh) 00283 { 00284 m_binaryLowerThresh = _lowerThresh; 00285 updateGL(); 00286 } 00287 00288 void BallTrackingVisualization::setStructuringElementSize(int _size) 00289 { 00290 m_ellipsesize = _size; 00291 updateGL(); 00292 } 00293 00294 void BallTrackingVisualization::setBlurSize(int _size) 00295 { 00296 m_blurSize = _size; 00297 updateGL(); 00298 } 00299 00300 void BallTrackingVisualization::setCannyLowerThresh(double _lowerThresh) 00301 { 00302 m_cannyLowerThresh = _lowerThresh; 00303 updateGL(); 00304 } 00305 00306 00307 void BallTrackingVisualization::setCannyHigherThresh(double _higherThresh) 00308 { 00309 m_cannyHigherThresh = _higherThresh; 00310 updateGL(); 00311 } 00312 00313 00314 void BallTrackingVisualization::setNumerOfDialtions(int _numberOfDialtions) 00315 { 00316 m_noOfTimesToDialate = _numberOfDialtions; 00317 updateGL(); 00318 } 00319 00320 void BallTrackingVisualization::setContourAreaThresh(double _contourAreaThresh) 00321 { 00322 m_contourAreaThresh = _contourAreaThresh; 00323 updateGL(); 00324 } 00325 00326 void BallTrackingVisualization::setDifferenceInAreaThresh(double _diffAreaThresh) 00327 { 00328 m_diffAreaThresh = _diffAreaThresh; 00329 updateGL(); 00330 } 00331 00332 void BallTrackingVisualization::setMasterRigCheck(int _masterRigCheck) 00333 { 00334 m_masterRigCheck = _masterRigCheck; 00335 updateGL(); 00336 } 00337