ViSP  2.10.0
vpKinect.cpp
1 /****************************************************************************
2  *
3  * $Id: vpKinect.cpp 5126 2015-01-05 22:07:11Z fspindle $
4  *
5  *
6  * This file is part of the ViSP software.
7  * Copyright (C) 2005 - 2014 by INRIA. All rights reserved.
8  *
9  * This software is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU General Public License
11  * ("GPL") version 2 as published by the Free Software Foundation.
12  * See the file LICENSE.txt at the root directory of this source
13  * distribution for additional information about the GNU GPL.
14  *
15  * For using ViSP with software that can not be combined with the GNU
16  * GPL, please contact INRIA about acquiring a ViSP Professional
17  * Edition License.
18  *
19  * See http://www.irisa.fr/lagadic/visp/visp.html for more information.
20  *
21  * This software was developed at:
22  * INRIA Rennes - Bretagne Atlantique
23  * Campus Universitaire de Beaulieu
24  * 35042 Rennes Cedex
25  * France
26  * http://www.irisa.fr/lagadic
27  *
28  * If you have questions regarding the use of this file, please contact
29  * INRIA at visp@inria.fr
30  *
31  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
32  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
33  *
34  *
35  * Description:
36  * API for using a Microsoft Kinect device
37  * Requires libfreenect as a third party library
38  *
39  * Authors:
40  * Celine Teuliere
41  *
42  *****************************************************************************/
43 
44 #include <visp/vpConfig.h>
45 
46 // Note that libfreenect needs libusb-1.0 and libpthread
47 #if defined(VISP_HAVE_LIBFREENECT_AND_DEPENDENCIES)
48 
49 #include <limits> // numeric_limits
50 
51 #include <visp/vpKinect.h>
52 #include <visp/vpXmlParserCamera.h>
53 
57 vpKinect::vpKinect(freenect_context *ctx, int index)
58  : Freenect::FreenectDevice(ctx, index),
59  m_rgb_mutex(), m_depth_mutex(), RGBcam(), IRcam(),
60  rgbMir(), irMrgb(), DMres(DMAP_LOW_RES),
61  hd(240), wd(320),
62  dmap(), IRGB(),
63  m_new_rgb_frame(false),
64  m_new_depth_map(false),
65  m_new_depth_image(false),
66  height(480), width(640)
67 {
68  dmap.resize(height, width);
69  IRGB.resize(height, width);
70  vpPoseVector r(-0.0266,-0.0047,-0.0055,0.0320578,0.0169041,-0.0076519 );
71  rgbMir.buildFrom(r);
72  irMrgb = rgbMir.inverse();
73 }
74 
79 {
80 
81 }
82 
84 {
85  DMres = res;
86  height = 480;
87  width = 640;
89  if (DMres == DMAP_LOW_RES){
90  std::cout << "vpKinect::start LOW depth map resolution 240x320" << std::endl;
91  // IRcam.setparameters(IRcam.get_px()/2, IRcam.get_py()/2, IRcam.get_u0()/2, IRcam.get_v0()/2);
92  //IRcam.initPersProjWithoutDistortion(303.06,297.89,160.75,117.9);
93  IRcam.initPersProjWithDistortion(303.06, 297.89, 160.75, 117.9, -0.27, 0);
94  hd = 240;
95  wd = 320;
96  }
97  else
98  {
99  std::cout << "vpKinect::start MEDIUM depth map resolution 480x640" << std::endl;
100 
101  //IRcam.initPersProjWithoutDistortion(606.12,595.78,321.5,235.8);
102  IRcam.initPersProjWithDistortion(606.12, 595.78, 321.5, 235.8, -0.27, 0);
103  // Idmap.resize(height, width);
104  hd = 480;
105  wd = 640;
106  }
107 
108 #if defined(VISP_HAVE_ACCESS_TO_NAS) && defined(VISP_HAVE_XML2)
109  vpXmlParserCamera cameraParser;
110  char cameraXmlFile[FILENAME_MAX];
111  sprintf(cameraXmlFile, "/udd/fspindle/robot/Viper850/Viper850-code/include/const_camera_Viper850.xml");
112  cameraParser.parse(RGBcam, cameraXmlFile, "Generic-camera", vpCameraParameters::perspectiveProjWithDistortion, width, height);
113 #else
114 // RGBcam.initPersProjWithoutDistortion(525.53, 524.94, 309.9, 282.8);//old
115 // RGBcam.initPersProjWithDistortion(536.76, 537.25, 313.45, 273.27,0.04,-0.04);//old
116 // RGBcam.initPersProjWithoutDistortion(512.0559503505,511.9352058050,310.6693938678,267.0673901049);//new
117  RGBcam.initPersProjWithDistortion(522.5431816996,522.7191431808,311.4001982614,267.4283562142,0.0477365207,-0.0462326418);//new
118 #endif
119 
120  this->startVideo();
121  this->startDepth();
122 }
123 
125 {
126  this->stopVideo();
127  this->stopDepth();
128 }
129 
130 
134 void vpKinect::VideoCallback(void* rgb, uint32_t /* timestamp */)
135 {
136 // std::cout << "vpKinect Video callback" << std::endl;
137  vpMutex::vpScopedLock lock(m_rgb_mutex);
138  uint8_t* rgb_ = static_cast<uint8_t*>(rgb);
139  for (unsigned i = 0; i< height;i++){
140  for (unsigned j = 0 ; j < width ; j++)
141  {
142  IRGB[i][j].R = rgb_[3*(width*i +j)+0];
143  IRGB[i][j].G = rgb_[3*(width*i +j)+1];
144  IRGB[i][j].B = rgb_[3*(width*i +j)+2];
145  }
146  }
147 
148  m_new_rgb_frame = true;
149 }
150 
161 void vpKinect::DepthCallback(void* depth, uint32_t /* timestamp */)
162 {
163 // std::cout << "vpKinect Depth callback" << std::endl;
164  vpMutex::vpScopedLock lock(m_depth_mutex);
165  uint16_t* depth_ = static_cast<uint16_t*>(depth);
166  for (unsigned i = 0; i< height;i++){
167  for (unsigned j = 0 ; j < width ; j++)
168  {
169  dmap[i][j] = 0.1236f * tan(depth_[width*i +j] / 2842.5f + 1.1863f);//formula from http://openkinect.org/wiki/Imaging_Information
170  if(depth_[width*i +j]>1023){//Depth cannot be computed
171  dmap[i][j] = -1;
172  }
173  }
174  }
175  m_new_depth_map = true;
176  m_new_depth_image = true;
177 }
178 
179 
184 {
185  vpMutex::vpScopedLock lock(m_depth_mutex);
186  if (!m_new_depth_map)
187  return false;
188  map = this->dmap;
189  m_new_depth_map = false;
190  return true;
191 }
192 
193 
198 {
199  // vpMutex::vpScopedLock lock(m_depth_mutex);
200  vpImage<float> tempMap;
201  m_depth_mutex.lock();
202  if (!m_new_depth_map && !m_new_depth_image)
203  {
204  m_depth_mutex.unlock();
205  return false;
206  }
207  tempMap = dmap;
208 
209  m_new_depth_map = false;
210  m_new_depth_image = false;
211  m_depth_mutex.unlock();
212 
213  if ((Imap.getHeight()!=hd )||(map.getHeight()!=hd))
214  vpERROR_TRACE(1, "Image size does not match vpKinect DM resolution");
215  if (DMres == DMAP_LOW_RES){
216  for(unsigned int i = 0; i < hd; i++)
217  for(unsigned int j = 0; j < wd; j++){
218  map[i][j] = tempMap[i<<1][j<<1];
219  //if (map[i][j] != -1)
220  if (fabs(map[i][j] + 1.f) > std::numeric_limits<float>::epsilon())
221  Imap[i][j] = (unsigned char)(255*map[i][j]/5);
222  else
223  Imap[i][j] = 255;
224  }
225  }
226  else
227  {
228  for (unsigned i = 0; i< height;i++)
229  for (unsigned j = 0 ; j < width ; j++){
230  map[i][j] = tempMap[i][j];
231  //if (map[i][j] != -1)
232  if (fabs(map[i][j] + 1.f) > std::numeric_limits<float>::epsilon())
233  Imap[i][j] = (unsigned char)(255*map[i][j]/5);
234  else
235  Imap[i][j] = 255;
236  }
237  }
238 
239  return true;
240 }
241 
242 
247 {
248  vpMutex::vpScopedLock lock(m_rgb_mutex);
249  if (!m_new_rgb_frame)
250  return false;
251  I_RGB = this->IRGB;
252  m_new_rgb_frame = false;
253  return true;
254 }
255 
259 void vpKinect::warpRGBFrame(const vpImage<vpRGBa> & Irgb, const vpImage<float> & Idepth, vpImage<vpRGBa> & IrgbWarped)
260 {
261  if ((Idepth.getHeight()!=hd )||(Idepth.getWidth()!=wd)){
262  vpERROR_TRACE(1, "Idepth image size does not match vpKinect DM resolution");
263  }
264  else{
265  if((IrgbWarped.getHeight()!=hd )||(IrgbWarped.getWidth()!=wd))
266  IrgbWarped.resize(hd, wd);
267  IrgbWarped=0;
268  double x1=0., y1=0., x2=0., y2=0., Z1, Z2;
269  vpImagePoint imgPoint(0,0);
270  double u=0., v=0.;
271  vpColVector P1(4),P2(4);
272 
273 // std::cout <<"rgbMir : "<<rgbMir<<std::endl;
274 
275  for (unsigned int i = 0; i< hd;i++)
276  for (unsigned int j = 0 ; j < wd ; j++){
278  vpPixelMeterConversion::convertPoint(IRcam, j, i, x1, y1);
279  Z1 = Idepth[i][j];
280  //if (Z1!=-1){
281  if (std::fabs(Z1+1) <= std::numeric_limits<double>::epsilon()){
282  P1[0]=x1*Z1;
283  P1[1]=y1*Z1;
284  P1[2]=Z1;
285  P1[3]=1;
286 
288  P2 = rgbMir*P1;
289  Z2 = P2[2];
290  //if (Z2!= 0){
291  if (std::fabs(Z2) > std::numeric_limits<double>::epsilon()){
292  x2 = P2[0]/P2[2];
293  y2 = P2[1]/P2[2];
294  }
295  else
296  std::cout<<"Z2 = 0 !!"<<std::endl;
297 
299  vpMeterPixelConversion::convertPoint(RGBcam, x2, y2, u, v);
300 
301  unsigned int u_ = (unsigned int)u;
302  unsigned int v_ = (unsigned int)v;
304  if ((u_<width)&&(v_<height)){
305  IrgbWarped[i][j] = Irgb[v_][u_];
306  }
307  else
308  IrgbWarped[i][j] = 0;
309  }
310  }
311  }
312 }
313 
314 
315 
316 
317 #endif // VISP_HAVE_LIBFREENECT
318 
Class that allows protection by mutex.
Definition: vpMutex.h:85
void start(vpKinect::vpDMResolution res=DMAP_LOW_RES)
Definition: vpKinect.cpp:83
vpDMResolution
Definition: vpKinect.h:118
void lock()
Definition: vpMutex.h:68
unsigned int getWidth() const
Definition: vpImage.h:161
#define vpERROR_TRACE
Definition: vpDebug.h:395
static void convertPoint(const vpCameraParameters &cam, const double &x, const double &y, double &u, double &v)
Point coordinates conversion from normalized coordinates in meter to pixel coordinates ...
void unlock()
Definition: vpMutex.h:71
static void convertPoint(const vpCameraParameters &cam, const double &u, const double &v, double &x, double &y)
Point coordinates conversion from pixel coordinates to normalized coordinates in meter...
XML parser to load and save intrinsic camera parameters.
void resize(const unsigned int h, const unsigned int w)
set the size of the image without initializing it.
Definition: vpImage.h:536
bool getRGB(vpImage< vpRGBa > &IRGB)
Definition: vpKinect.cpp:246
void warpRGBFrame(const vpImage< vpRGBa > &Irgb, const vpImage< float > &Idepth, vpImage< vpRGBa > &IrgbWarped)
Definition: vpKinect.cpp:259
Perspective projection with distortion model.
void buildFrom(const vpTranslationVector &t, const vpRotationMatrix &R)
Construction from translation vector and rotation matrix.
Class that provides a data structure for the column vectors as well as a set of operations on these v...
Definition: vpColVector.h:72
The pose is a complete representation of every rigid motion in the euclidian space.
Definition: vpPoseVector.h:92
vpHomogeneousMatrix inverse() const
void stop()
Definition: vpKinect.cpp:124
unsigned int getHeight() const
Definition: vpImage.h:152
Class that defines a 2D point in an image. This class is useful for image processing and stores only ...
Definition: vpImagePoint.h:93
int parse(vpCameraParameters &cam, const std::string &filename, const std::string &camera_name, const vpCameraParameters::vpCameraParametersProjType &projModel, const unsigned int image_width=0, const unsigned int image_height=0)
bool getDepthMap(vpImage< float > &map)
Definition: vpKinect.cpp:183
void initPersProjWithDistortion(const double px, const double py, const double u0, const double v0, const double kud, const double kdu)
virtual ~vpKinect()
Definition: vpKinect.cpp:78
vpKinect(freenect_context *ctx, int index)
Definition: vpKinect.cpp:57