KINECT STATS GENERATOR FOR SPORTS VISUALISATION
1.0
|
00001 /* 00002 * This file is part of the OpenKinect Project. http://www.openkinect.org 00003 * 00004 * Copyright (c) 2010 individual OpenKinect contributors. See the CONTRIB file 00005 * for details. 00006 * 00007 * This code is licensed to you under the terms of the Apache License, version 00008 * 2.0, or, at your option, the terms of the GNU General Public License, 00009 * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, 00010 * or the following URLs: 00011 * http://www.apache.org/licenses/LICENSE-2.0 00012 * http://www.gnu.org/licenses/gpl-2.0.txt 00013 * 00014 * If you redistribute this file in source form, modified or unmodified, you 00015 * may: 00016 * 1) Leave this header intact and distribute it under the same terms, 00017 * accompanying it with the APACHE20 and GPL20 files, or 00018 * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or 00019 * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file 00020 * In all cases you must keep the copyright notice intact and include a copy 00021 * of the CONTRIB file. 00022 * 00023 * Binary distributions must follow the binary distribution requirements of 00024 * either License. 00025 */ 00026 00027 //---------------------------------------------------------------------------------------------------------------------- 00031 //---------------------------------------------------------------------------------------------------------------------- 00032 00033 #include <KinectInterface.h> 00034 #include <QDebug> 00035 #include <cstdlib> 00036 #include <cmath> 00037 #include <cassert> 00038 //#include <boost/lexical_cast.hpp> 00039 00040 00041 00042 //---------------------------------------------------------------------------------------------------------------------- 00043 KinectInterface *KinectInterface::s_instance = 0;// initialize pointer 00044 //---------------------------------------------------------------------------------------------------------------------- 00045 00046 00047 //---------------------------------------------------------------------------------------------------------------------- 00048 void QKinectProcessEvents::run() 00049 { 00050 // loop while we are active and process the kinect event queue 00051 while(m_active) 00052 { 00053 //qDebug()<<"process thread\n"; 00054 if(freenect_process_events(m_ctx) < 0) 00055 { 00056 throw std::runtime_error("Cannot process freenect events"); 00057 } 00058 } 00059 } 00060 00061 //---------------------------------------------------------------------------------------------------------------------- 00063 //---------------------------------------------------------------------------------------------------------------------- 00064 KinectInterface::~KinectInterface() 00065 { 00066 // dtor is not called directly 00067 if (s_instance) 00068 { 00069 delete s_instance; 00070 } 00071 } 00072 //---------------------------------------------------------------------------------------------------------------------- 00074 //---------------------------------------------------------------------------------------------------------------------- 00075 KinectInterface* KinectInterface::instance() 00076 { 00077 // this is the main singleton code first check to see if we exist 00078 if (s_instance==0 ) 00079 { 00080 // we do so create an instance (this will validate the pointer so other 00081 // methods called in the init function will have a valid pointer to use) 00082 s_instance = new KinectInterface; 00083 // now setup the actual class (with a valid pointer) 00085 if(s_instance->init() == false) 00086 { 00087 s_instance = 0; 00088 } 00089 } 00090 // otherwise return the existing pointer 00091 return s_instance; 00092 } 00093 00094 00095 //---------------------------------------------------------------------------------------------------------------------- 00096 KinectInterface::KinectInterface() : QObject(0) 00097 { 00098 // nothing to see here we just need a valid object pointer the init 00099 // method does all the hard work 00100 qDebug()<<"ctor called \n"; 00101 00102 for( unsigned int i = 0 ; i < 640*480 ; ++i) 00103 { 00104 m_bufferDepthinM[i] = 0; 00105 } 00106 00107 00108 00109 00110 } 00111 //---------------------------------------------------------------------------------------------------------------------- 00112 bool KinectInterface::init() 00113 { 00114 // first see if we can init the kinect 00115 if (freenect_init(&m_ctx, NULL) < 0) 00116 { 00117 qDebug()<<"freenect_init() failed\n"; 00118 exit(EXIT_FAILURE); 00119 } 00121 freenect_set_log_level(m_ctx, FREENECT_LOG_DEBUG); 00123 int nr_devices = freenect_num_devices (m_ctx); 00124 qDebug()<<"Number of devices found: "<<nr_devices<<"\n"; 00125 00126 if(nr_devices < 1) 00127 { 00128 //delete s_instance; 00129 //s_instance = 0; 00130 return false; 00131 } 00133 m_userDeviceNumber = 0; 00134 // grab the buffer size and store for later use 00135 m_resolutionRGBBytes=freenect_find_video_mode(FREENECT_RESOLUTION_MEDIUM,FREENECT_VIDEO_RGB).bytes; 00136 m_bufferDepth=cvCreateMat(480,640,CV_8UC3); 00137 00138 //m_bufferVideo.resize(m_resolutionRGBBytes); 00139 00140 m_bufferVideo = cvCreateMat(480,640,CV_8UC3); 00141 00142 // m_nextBuffer = cvCreateMat(480,640,CV_8UC1); 00143 // m_prevBuffer = cvCreateMat(480,640,CV_8UC1); 00144 // m_diffBuffer = cvCreateMat(480,640,CV_8UC1); 00145 00146 m_resolutionDepthBytes=freenect_find_depth_mode(FREENECT_RESOLUTION_MEDIUM,FREENECT_DEPTH_11BIT).bytes; 00147 //m_bufferDepthRaw.resize(m_resolutionDepthBytes); 00148 m_bufferDepthRaw16=cvCreateMat(480,640,CV_8UC1); 00149 00150 m_bufferDepthRaw=cvCreateMat(480,640,CV_8UC1); 00151 00152 00153 00154 // m_originalFrameDepth=NULL; 00155 00156 00157 00158 m_gamma.resize(2048); 00162 if (freenect_open_device(m_ctx, &m_dev, m_userDeviceNumber) < 0) 00163 { 00164 qDebug()<<"Could not open device\n"; 00165 exit(EXIT_FAILURE); 00166 } 00167 00168 00171 // for (int i=0; i<2048; ++i) 00172 // { 00173 // float v = i/2048.0; 00174 // v = std::pow(v, 3)* 6; 00175 // m_gamma[i] = v*6*256; 00176 // } 00177 00178 00179 // from opencv imaging imformation wiki page http://openkinect.org/wiki/Imaging_Information 00180 const float k1 = 1.1863; 00181 const float k2 = 2842.5; 00182 const float k3 = 0.1236; 00183 const float offset = 0.037; 00184 float depth = 0; 00185 for (size_t i=0; i<2048; i++) 00186 { 00187 depth = k3 * tanf(i/k2 + k1) - offset; 00188 m_gamma[i] = depth; 00189 } 00190 00191 00193 m_newRgbFrame=false; 00194 m_newDepthFrame=false; 00195 m_deviceActive=true; 00196 00197 m_threshValue = 100; 00198 00199 00200 // set our video formats to RGB by default 00202 freenect_set_video_mode(m_dev, freenect_find_video_mode(FREENECT_RESOLUTION_MEDIUM, FREENECT_VIDEO_RGB)); 00203 freenect_set_depth_mode(m_dev, freenect_find_depth_mode(FREENECT_RESOLUTION_MEDIUM, FREENECT_DEPTH_11BIT)); 00204 // deprecated 00205 //freenect_set_video_format(m_dev, FREENECT_VIDEO_RGB); 00206 //freenect_set_depth_format(m_dev, FREENECT_DEPTH_11BIT); 00208 freenect_set_depth_callback(m_dev, depthCallback); 00209 freenect_set_video_callback(m_dev, videoCallback); 00210 // start the video and depth sub systems 00211 startVideo(); 00212 startDepth(); 00213 // set the thread to be active and start 00214 m_process = new QKinectProcessEvents(m_ctx); 00215 m_process->setActive(); 00216 m_process->start(); 00217 00218 m_depthLower = 0.02; 00219 m_depthHigher = 1.02; // has to be just above the table (in meteres) 00220 00221 //m_selectedBoxCoords = NULL; 00222 00223 m_selectedBoxCoords = cv::Rect(0,0,0,0); 00224 00225 m_toggleTracking = false; 00226 m_setBounds = false; 00227 00228 return true; 00229 } 00230 00231 //---------------------------------------------------------------------------------------------------------------------- 00232 void KinectInterface::shutDownKinect() 00233 { 00235 m_process->setInActive(); 00237 freenect_stop_depth(m_dev); 00238 freenect_stop_video(m_dev); 00239 // close down our devices 00240 freenect_close_device(m_dev); 00241 freenect_shutdown(m_ctx); 00242 00243 } 00244 00245 //---------------------------------------------------------------------------------------------------------------------- 00246 void KinectInterface::setVideoMode( 00247 int _mode 00248 ) 00249 { 00250 freenect_video_format vm=FREENECT_VIDEO_RGB; 00251 switch(_mode) 00252 { 00253 case 0 : { vm=FREENECT_VIDEO_RGB; break;} 00254 case 1 : { vm=FREENECT_VIDEO_YUV_RGB; break;} 00255 case 2 : { vm=FREENECT_VIDEO_IR_8BIT; break;} 00256 /* 00258 case 1 : { vm=FREENECT_VIDEO_BAYER; break;} 00259 case 2 : { vm=FREENECT_VIDEO_IR_8BIT; break;} 00260 case 3 : { vm=FREENECT_VIDEO_IR_10BIT; break;} 00261 case 4 : { vm=FREENECT_VIDEO_IR_10BIT_PACKED; break;} 00262 case 5 : { vm=FREENECT_VIDEO_YUV_RGB; break;} 00263 case 6 : { vm=FREENECT_VIDEO_YUV_RAW; break;} 00264 */ 00265 default : qDebug()<<"index out of bounds for video mode\n"; 00266 vm=FREENECT_VIDEO_RGB; 00267 break; 00268 } 00270 freenect_stop_video(m_dev); 00271 freenect_set_video_mode(m_dev, freenect_find_video_mode(FREENECT_RESOLUTION_MEDIUM, FREENECT_VIDEO_RGB)); 00272 //deprecated 00273 // freenect_set_video_format(m_dev, vm); 00274 freenect_start_video(m_dev); 00275 } 00276 00277 //---------------------------------------------------------------------------------------------------------------------- 00278 bool KinectInterface::getRGB(cv::Mat &o_buffer) 00279 { 00280 00281 //static int _frameCount = 1; 00284 QMutexLocker locker( &m_mutex ); 00285 // do we have a new frame? 00286 if(m_newRgbFrame) 00287 { 00288 00289 m_bufferVideo.copyTo(o_buffer); 00290 m_newRgbFrame = false; 00291 return true; 00292 } 00293 else 00294 { 00295 return false; 00296 } 00297 } 00298 00299 00300 //---------------------------------------------------------------------------------------------------------------------- 00301 bool KinectInterface::getDepth( 00302 cv::Mat &o_buffer 00303 ) 00304 { 00305 // this fills the depth buffer, first lock our mutex 00306 QMutexLocker locker( &m_mutex ); 00307 if(m_newDepthFrame) 00308 { 00309 // swap data 00310 m_bufferDepth.copyTo(o_buffer); 00311 00312 m_newDepthFrame = false; 00313 return true; 00314 } 00315 else 00316 { 00317 return false; 00318 } 00319 } 00320 //---------------------------------------------------------------------------------------------------------------------- 00321 bool KinectInterface::getDepth16Bit( 00322 cv::Mat &o_buffer 00323 ) 00324 { 00326 QMutexLocker locker( &m_mutex ); 00327 if(m_newDepthFrame) 00328 { 00329 // fill our buffer if avaliable 00330 m_bufferDepthRaw16.copyTo(o_buffer); 00331 m_newDepthFrame = false; 00332 return true; 00333 } 00334 else 00335 { 00336 return false; 00337 } 00338 } 00339 00340 00341 //---------------------------------------------------------------------------------------------------------------------- 00342 bool KinectInterface::getDepthSliced( 00343 cv::Mat &o_buffer 00344 ) 00345 { 00347 QMutexLocker locker( &m_mutex ); 00348 if(m_newDepthFrame) 00349 { 00350 // fill our buffer if avaliable 00351 m_bufferDepthRaw.copyTo(o_buffer); 00352 m_newDepthFrame = false; 00353 return true; 00354 } 00355 else 00356 { 00357 return false; 00358 } 00359 } 00360 00361 //---------------------------------------------------------------------------------------------------------------------- 00362 bool KinectInterface::getDepthRaw(cv::Mat &o_buffer, float *o_depthinmBuffer) 00363 { 00364 00365 00366 QMutexLocker locker( &m_mutex ); 00367 if(m_newDepthFrame) 00368 { 00369 00370 m_bufferDepthRaw.copyTo(o_buffer); 00371 for( unsigned int i = 0 ; i < 640*480 ; ++i) 00372 { 00373 o_depthinmBuffer[i] = m_bufferDepthinM[i]; 00374 } 00375 m_newDepthFrame = false; 00376 return true; 00377 } 00378 else 00379 { 00380 return false; 00381 } 00382 } 00383 //---------------------------------------------------------------------------------------------------------------------- 00384 void KinectInterface::grabDepth( 00385 void *_depth, 00386 uint32_t _timestamp 00387 ) 00388 { 00389 // this method fills all the different depth buffers at once 00390 // modifed from the sample code glview and cppview.cpp 00392 QMutexLocker locker( &m_mutex ); 00393 // cast the void pointer to the unint16_t the data is actually in 00394 uint16_t* depth = static_cast<uint16_t*>(_depth); 00395 00396 00397 00398 // now loop and fill data buffers 00399 for( unsigned int i = 0 ; i < 640*480 ; ++i) 00400 { 00401 // first our two raw buffers the first will lose precision and may well 00402 // be removed in the next iterations 00403 00404 // now get the index into the gamma table 00405 float pval = m_gamma[depth[i]]; // my notes: so pval is in metres now..using cam caliberation values, we have converted depth values to metres 00406 // using open kinect forum formulae this (i,j,z) value can be transformed to (x,y,z) 00407 00408 00409 00410 00411 00412 //m_bufferDepthinM.data[i] = m_gamma[depth[i]]; 00413 00414 //m_originalFrameDepth1[_frameCountGrab] = m_gamma[depth[i]]; 00415 00416 00417 //std::cout<<"pval is"<<pval<<"\n"; 00418 00419 // a bounded volume as explained in rally keeper project to detect contours 00420 if (pval >= m_depthLower && pval <= m_depthHigher) 00421 { 00422 m_bufferDepthRaw.data[i]=255; 00423 m_bufferDepthRaw16.data[i]=255; 00424 m_bufferDepthinM[i] = depth[i]; 00425 } 00426 else 00427 { 00428 m_bufferDepthRaw.data[i]=0; 00429 m_bufferDepthRaw16.data[i]=0; 00430 } 00431 if (pval <= 0.9) 00432 { 00433 m_bufferDepth.data[3*i+0] = 255; 00434 m_bufferDepth.data[3*i+1] = 0; 00435 m_bufferDepth.data[3*i+2] = 0; 00436 00437 } 00438 else if (pval > 0.9 && pval <= 2) 00439 { 00440 m_bufferDepth.data[3*i+0] = 0; 00441 m_bufferDepth.data[3*i+1] = 255; 00442 m_bufferDepth.data[3*i+2] = 0; 00443 00444 } 00445 else if (pval > 2) 00446 { 00447 m_bufferDepth.data[3*i+0] = 0; 00448 m_bufferDepth.data[3*i+1] = 0; 00449 m_bufferDepth.data[3*i+2] = 255; 00450 00451 } 00452 } 00453 // flag we have a new frame 00454 m_newDepthFrame = true; 00455 } 00456 //---------------------------------------------------------------------------------------------------------------------- 00457 void KinectInterface::grabVideo( 00458 void *_video, 00459 uint32_t _timestamp 00460 ) 00461 { 00462 // lock our mutex and copy the data from the video buffer 00463 QMutexLocker locker( &m_mutex ); 00464 uint8_t* rgb = static_cast<uint8_t*>(_video); 00465 //std::copy(rgb, rgb+m_resolutionRGBBytes, m_bufferVideo.begin()); 00466 memcpy( m_bufferVideo.data , rgb, m_resolutionRGBBytes); 00467 00468 m_newRgbFrame = true; 00469 } 00470 00471 //---------------------------------------------------------------------------------------------------------------------- 00472 void KinectInterface::startVideo() 00473 { 00474 if(freenect_start_video(m_dev) < 0) 00475 { 00476 throw std::runtime_error("Cannot start RGB callback"); 00477 } 00478 } 00479 //---------------------------------------------------------------------------------------------------------------------- 00480 void KinectInterface::stopVideo() 00481 { 00482 if(freenect_stop_video(m_dev) < 0) 00483 { 00484 throw std::runtime_error("Cannot stop RGB callback"); 00485 } 00486 } 00487 //---------------------------------------------------------------------------------------------------------------------- 00488 void KinectInterface::startDepth() 00489 { 00490 if(freenect_start_depth(m_dev) < 0) 00491 { 00492 throw std::runtime_error("Cannot start depth callback"); 00493 } 00494 } 00495 00496 //---------------------------------------------------------------------------------------------------------------------- 00497 void KinectInterface::stopDepth() 00498 { 00499 if(freenect_stop_depth(m_dev) < 0) 00500 { 00501 throw std::runtime_error("Cannot stop depth callback"); 00502 } 00503 } 00504 00505 //---------------------------------------------------------------------------------------------------------------------- 00506 void KinectInterface::toggleVideoState(bool _mode) 00507 { 00508 if(_mode ==true) 00509 { 00510 startVideo(); 00511 } 00512 else 00513 { 00514 stopVideo(); 00515 } 00516 } 00517 //---------------------------------------------------------------------------------------------------------------------- 00518 void KinectInterface::toggleDepthState(bool _mode) 00519 { 00520 if(_mode == true) 00521 { 00522 startDepth(); 00523 } 00524 else 00525 { 00526 stopDepth(); 00527 } 00528 } 00529 00530 00531 void KinectInterface::setDepthVolumeLower(double _inputLowerDepth) 00532 { 00533 m_depthLower = _inputLowerDepth; 00534 } 00535 00536 void KinectInterface::setDepthVolumeHigher(double _inputHigherDepth) 00537 { 00538 m_depthHigher = _inputHigherDepth; 00539 } 00540 00541 void KinectInterface::setBoxObject(int _topX, int _topY, int _width, int _height) 00542 { 00543 m_setBounds = true; 00544 m_selectedBoxCoords.x = _topX; 00545 m_selectedBoxCoords.y = _topY; 00546 m_selectedBoxCoords.width = _width; 00547 m_selectedBoxCoords.height = _height; 00548 00549 } 00550 00551 cv::Rect& KinectInterface::getBoxObject() 00552 { 00553 return m_selectedBoxCoords; 00554 } 00555 00556 void KinectInterface::toggleTracking() 00557 { 00558 m_toggleTracking = !(m_toggleTracking); 00559 } 00560 00561 bool KinectInterface::getTrackingFlag() 00562 { 00563 return m_toggleTracking; 00564 } 00565 00566 bool KinectInterface::getBounds() 00567 { 00568 return m_setBounds; 00569 } 00570 00571 void KinectInterface::setBoundsDefined(bool _isBoundsDefined) 00572 { 00573 m_setBounds = _isBoundsDefined; 00574 } 00575 00576 00577 //----------------------------------------------------------------------------------------------------------------------